Created
February 18, 2026 08:57
-
-
Save EncodeTheCode/6c80cd0d06971c5c470ead2366c5aad3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // =============================== | |
| // RAW XBOX CONTROLLER (Hardware) | |
| // =============================== | |
| class XboxController { | |
| constructor(index = 0, deadzone = 0.15) { | |
| this.index = index; | |
| this.deadzone = deadzone; | |
| // ---- RAW BUTTON STATES ---- | |
| this.A = this.A_Pressed = this.A_Released = 0; | |
| this.B = this.B_Pressed = this.B_Released = 0; | |
| this.X = this.X_Pressed = this.X_Released = 0; | |
| this.Y = this.Y_Pressed = this.Y_Released = 0; | |
| this.LB = this.LB_Pressed = this.LB_Released = 0; | |
| this.RB = this.RB_Pressed = this.RB_Released = 0; | |
| this.View = this.View_Pressed = this.View_Released = 0; | |
| this.Menu = this.Menu_Pressed = this.Menu_Released = 0; | |
| this.LS = this.LS_Pressed = this.LS_Released = 0; | |
| this.RS = this.RS_Pressed = this.RS_Released = 0; | |
| this.DPadUp = this.DPadUp_Pressed = this.DPadUp_Released = 0; | |
| this.DPadDown = this.DPadDown_Pressed = this.DPadDown_Released = 0; | |
| this.DPadLeft = this.DPadLeft_Pressed = this.DPadLeft_Released = 0; | |
| this.DPadRight = this.DPadRight_Pressed = this.DPadRight_Released = 0; | |
| // Analog triggers | |
| this.LT = 0; | |
| this.RT = 0; | |
| // Sticks | |
| this.leftX = 0; | |
| this.leftY = 0; | |
| this.rightX = 0; | |
| this.rightY = 0; | |
| // Previous states | |
| this._prev = new Uint8Array(16); | |
| } | |
| update() { | |
| const gp = navigator.getGamepads()[this.index]; | |
| if (!gp) return; | |
| const b = gp.buttons; | |
| const a = gp.axes; | |
| const p = this._prev; | |
| // Digital buttons | |
| this._btn(0, b[0].pressed, "A"); | |
| this._btn(1, b[1].pressed, "B"); | |
| this._btn(2, b[2].pressed, "X"); | |
| this._btn(3, b[3].pressed, "Y"); | |
| this._btn(4, b[4].pressed, "LB"); | |
| this._btn(5, b[5].pressed, "RB"); | |
| this._btn(8, b[8].pressed, "View"); | |
| this._btn(9, b[9].pressed, "Menu"); | |
| this._btn(10, b[10].pressed, "LS"); | |
| this._btn(11, b[11].pressed, "RS"); | |
| this._btn(12, b[12].pressed, "DPadUp"); | |
| this._btn(13, b[13].pressed, "DPadDown"); | |
| this._btn(14, b[14].pressed, "DPadLeft"); | |
| this._btn(15, b[15].pressed, "DPadRight"); | |
| // Analog triggers | |
| this.LT = b[6].value; | |
| this.RT = b[7].value; | |
| // Sticks with deadzone | |
| const dz = this.deadzone; | |
| let lx = a[0], ly = a[1], rx = a[2], ry = a[3]; | |
| this.leftX = (lx > dz || lx < -dz) ? lx : 0; | |
| this.leftY = (ly > dz || ly < -dz) ? ly : 0; | |
| this.rightX = (rx > dz || rx < -dz) ? rx : 0; | |
| this.rightY = (ry > dz || ry < -dz) ? ry : 0; | |
| } | |
| _btn(i, pressed, name) { | |
| const curr = pressed ? 1 : 0; | |
| const prev = this._prev[i]; | |
| this[name] = curr; | |
| this[name + "_Pressed"] = curr & (prev ^ 1); | |
| this[name + "_Released"] = (curr ^ 1) & prev; | |
| this._prev[i] = curr; | |
| } | |
| } | |
| // =============================== | |
| // PLAYER ACTION MAPPING LAYER | |
| // =============================== | |
| class PlayerInput { | |
| constructor(controller) { | |
| this.controller = controller; | |
| // ---- GAME ACTIONS ---- | |
| this.jump = 0; | |
| this.jump_Pressed = 0; | |
| this.jump_Released = 0; | |
| this.shoot = 0; | |
| this.reload = 0; | |
| this.pause = 0; | |
| this.moveX = 0; | |
| this.moveY = 0; | |
| this.lookX = 0; | |
| this.lookY = 0; | |
| } | |
| update() { | |
| const c = this.controller; | |
| // Map hardware → gameplay | |
| this.jump = c.A; | |
| this.jump_Pressed = c.A_Pressed; | |
| this.jump_Released = c.A_Released; | |
| this.shoot = c.RT > 0.5; | |
| this.reload = c.X; | |
| this.pause = c.Menu_Pressed; | |
| this.moveX = c.leftX; | |
| this.moveY = c.leftY; | |
| this.lookX = c.rightX; | |
| this.lookY = c.rightY; | |
| } | |
| } | |
| // =============================== | |
| // EXAMPLE GAME LOOP | |
| // =============================== | |
| const controller = new XboxController(0); | |
| const input = new PlayerInput(controller); | |
| // Example mock objects | |
| const player = { | |
| x: 0, | |
| y: 0, | |
| speed: 5, | |
| jump() { console.log("Jump"); }, | |
| fire() { console.log("Shoot"); } | |
| }; | |
| const camera = { | |
| look(x, y) { | |
| console.log("Look:", x.toFixed(2), y.toFixed(2)); | |
| } | |
| }; | |
| const game = { | |
| togglePause() { | |
| console.log("Paused"); | |
| } | |
| }; | |
| function gameLoop() { | |
| controller.update(); | |
| input.update(); | |
| if (input.jump_Pressed) player.jump(); | |
| if (input.shoot) player.fire(); | |
| if (input.pause) game.togglePause(); | |
| player.x += input.moveX * player.speed; | |
| player.y += input.moveY * player.speed; | |
| camera.look(input.lookX, input.lookY); | |
| requestAnimationFrame(gameLoop); | |
| } | |
| gameLoop(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment