1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Slither.io(スリザリオ)をゲームコントローラーで遊びたい

1
Posted at

年に1回くらい、ふと遊びたくなるゲーム「Slither.io(スリザリオ)
PCブラウザでやるとマウスやトラックパッドでのカーソル操作なのですが、とても操作しにくいのでゲーム用のコントローラーで動かせるようにします。

Gamepad APIでコントローラーの情報を取得

ブラウザに用意されているGamepad APIを使用すると結構簡単にコントローラーの入力が取得できます。

コントローラーを接続するとイベントが発火して、コントローラーを認識する

window.addEventListener("gamepadconnected", (e) => {
  console.log("Gamepad connected!", e.gamepad);
});

各ボタンはこんな感じで取得可能です。

navigator.getGamepads().forEach((gp, index) => {
  let xAxis = gp.axes[0];
  let yAxis = gp.axes[1];
  let aButton = gp.buttons[0].pressed;
}

今回はPCへの接続が簡単な、XBOXコントローラーを使用しましたが

コントローラーの入力をマウスイベントに変換

MouseEventをつくり発火させることで、マウス操作を再現可能です。

const target = document.elementFromPoint(center.x, center.y);
const event = new MouseEvent("mousemove", {
  bubbles: true,
  clientX: x,
  clientY: y,
});
target.dispatchEvent(event);

Slither.ioの操作では画面の中央からどの向きにカーソルがあるかで、移動先を判断しているようなので
スティックの入力向きを変換しています。

完成形

Aボタンの押下中でブーストを使用されるようにしました。
ゲームオーバーになっても、Aボタンですぐに再開できます。

const SPEED = 20;

let x = window.innerWidth / 2;
let y = window.innerHeight / 2;

let wasPressed = false;

function fireMouseEvent(type, x, y, target) {
  console.log(`Firing ${type} at (${x}, ${y})`);
  const event = new MouseEvent(type, {
    bubbles: true,
    clientX: x,
    clientY: y,
  });
  target.dispatchEvent(event);
}

function update() {
  let center = {
    x: window.innerWidth / 2,
    y: window.innerHeight / 2,
  };

  const gamepads = navigator.getGamepads();
  gamepads.forEach((gp, index) => {
    if (!gp) {
      return;
    }

    let xAxis = gp.axes[0];
    let yAxis = gp.axes[1];

    if (xAxis < 0.1 && xAxis > -0.1) xAxis = 0;
    if (yAxis < 0.1 && yAxis > -0.1) yAxis = 0;

    console.log(`Gamepad ${index}:`, xAxis, yAxis);

    x = center.x + xAxis * SPEED;
    y = center.y + yAxis * SPEED;

    const target = document.elementFromPoint(center.x, center.y);
    fireMouseEvent("mousemove", x, y, target || document.body);

    const isPressed = gp.buttons[0].pressed; // Aボタン
    if (isPressed && !wasPressed) {
      if (document.querySelector("#login")?.style.display !== "none") {
        document.querySelector("#playh .btnt")?.click();
        return;
      }
      fireMouseEvent("mousedown", x, y, document.body);
    } else if (!isPressed && wasPressed) {
      fireMouseEvent("mouseup", x, y, document.body);
    }
    wasPressed = isPressed;
  });

  requestAnimationFrame(update);
}

window.addEventListener("gamepadconnected", () => {
  console.log("Gamepad connected!", navigator.getGamepads());
  alert("Gamepad connected!");
  update();
});
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?