A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://developer.mozilla.org/ja/docs/Web/API/Gamepad_API/Using_the_Gamepad_API below:

ゲームパッド API の使用 - Web API

ゲームパッド API の使用

Baseline Widely available *

HTML はリッチでインタラクティブなゲームを開発するために必要なコンポーネントを多く搭載しています。 <canvas> や WebGL、 <audio> に <video> などの技術は、今までネイティブコードを書く必要のあった機能に対応できるほどに成長しました。ゲームパッド API は開発者とデザイナーにゲームパッドやコントローラーへのアクセスを提供するものです。

ゲームパッド API は Window オブジェクトにゲームパッドとコントローラー(以下、ゲームパッド)の状態を読み取る新しいイベントをいくつか追加します。さらに、 Gamepad というゲームパッドの接続状態が得られるオブジェクトと navigator.getGamepads() というゲームパッドの一覧を取得できるメソッドが追加されます。

ゲームパッドの接続

新しいゲームパッドが接続された時、アクティブなページは gamepadconnected イベントを受け取ります。ページ読み込み時にゲームパッドがすでに接続されている場合、ゲームパッドのボタンを押すなどの操作をした時に gamepadconnected イベントがアクティブなページに対して発生します。

メモ: Firefox では、ページが見える状態でかつユーザーによるゲームパッドの操作を受け付けたときにのみ、ゲームパッドが利用可能になります。これによって、ユーザーを特定するフィンガープリンティングに利用されることを防止しています。いったん一つのコントローラーが操作されれば、他のコントローラーも自動で接続され利用可能になります。

以下のようにして gamepadconnected を使用します。

window.addEventListener("gamepadconnected", (e) => {
  console.log(
    "Gamepad connected at index %d: %s. %d buttons, %d axes.",
    e.gamepad.index,
    e.gamepad.id,
    e.gamepad.buttons.length,
    e.gamepad.axes.length,
  );
});

ゲームパッドはそれぞれ固有の ID をイベントの gamepad プロパティの中に持っています。

ゲームパッドの切断

ゲームパッドが切断されたとき、ページに以前そのゲームパッドのために受信したデータ(例: gamepadconnected)があると、 2 番目のイベント、 gamepaddisconnected がフォーカスのあるウィンドウに配信されます。

window.addEventListener("gamepaddisconnected", (e) => {
  console.log(
    "Gamepad disconnected from index %d: %s",
    e.gamepad.index,
    e.gamepad.id,
  );
});

ゲームパッドの index プロパティは、同じ種類の複数のコントローラーが使用されている場合であっても、システムに接続された機器ごとに固有になります。 index プロパティもまた Navigator.getGamepads() から返される Array のイデックスとして機能します。

const gamepads = {};

function gamepadHandler(event, connected) {
  const gamepad = event.gamepad;
  // Note:
  // gamepad === navigator.getGamepads()[gamepad.index]

  if (connected) {
    gamepads[gamepad.index] = gamepad;
  } else {
    delete gamepads[gamepad.index];
  }
}

window.addEventListener(
  "gamepadconnected",
  (e) => {
    gamepadHandler(e, true);
  },
  false,
);
window.addEventListener(
  "gamepaddisconnected",
  (e) => {
    gamepadHandler(e, false);
  },
  false,
);

この前の例ではイベントが完了した後に gamepad プロパティがどのように保持できるかを示しています - 後でデバイスの状態照会のために使用する技術となります。

Gamepad オブジェクトの問い合わせ

ご覧のように、上述の gamepad イベントは Gamepad オブジェクトを返すイベントオブジェクト、上の gamepad のプロパティが含まれています。複数のゲームパッド(すなわち、その ID)を一度に接続される可能性があるため、イベントを発生させたのはどのゲームパッドを決定するためにこれらを使用することができます。それへの参照を保持し、それがボタンや軸のいずれかの時点で押されているかを知るために照会するなど、Gamepad オブジェクトから様々なことを行うことができます。そうすることで、多くの場合、今回と次回のイベント発生とゲームパッドの状態を知っておく必要があり、ゲームやその他のインタラクティブなウェブページであることが望ましいです。

このようなチェックを実行すると、開発者はゲームパッドやゲームパッドの状態に基づいて、現在のフレームのための意思決定を行うために必要なアニメーションループ (例 : requestAnimationFrame) と一緒に Gamepad オブジェクトを使用して関与する傾向があります。

Navigator.getGamepads() メソッドは現在ウェブページから見える Gamepad オブジェクト (ゲームパッドが繋がっていない時は毎回 null が返される ) のような、すべてのデバイスを配列として戻します。これは、同じ情報を得るために使用することができます。例えば、上記の最初のコード例は下記に示すように書き換えることができます。

window.addEventListener("gamepadconnected", (e) => {
  const gp = navigator.getGamepads()[e.gamepad.index];
  console.log(
    "Gamepad connected at index %d: %s. %d buttons, %d axes.",
    gp.index,
    gp.id,
    gp.buttons.length,
    gp.axes.length,
  );
});

Gamepad オブジェクトの機能は以下の通りです。

メモ: Gamepad オブジェクトは、セキュリティ上の理由から Window オブジェクトではなく gamepadconnected イベントで使用できます。一度参照を取得すると、そのプロパティでゲームパッドの現在の状態に関する情報を照会できます。 このオブジェクトは、ゲームパッドの状態が変わるたびに更新されます。

ボタン情報の使用

1 つのゲームパッドの接続情報を表示する簡単な例を見てみましょう (後続のゲームパッド接続を無視します)。ゲームパッドの右側にある 4 つのゲームパッドボタンを使用してボールを画面の周りに移動できます。デモをライブで見ることができことができ、Github でソースコードを見つけることができます。

まず、いくつかの変数を宣言します。接続情報が書き込まれる gamepadInfo のパラグラフ、移動する ball、requestAnimation Frame の ID として機能する start 変数、ボールを移動するための位置変更子として機能する a および b 変数、および短縮形変数 これは、 requestAnimationFrame() および cancelAnimationFrame() クロスブラウザーフォークで使用されます。

const gamepadInfo = document.getElementById("gamepad-info");
const ball = document.getElementById("ball");
let start;
let a = 0;
let b = 0;

次に gamepadconnected イベントを使用して、接続されているゲームパッドを確認します。接続されると Navigator.getGamepads()[0] を使用してゲームパッドを取得し、ゲームパッドに関する情報をゲームパッドの情報 div に出力し、全体のボールの動きが始まる gameLoop() 関数が呼び出されます。

window.addEventListener("gamepadconnected", (e) => {
  const gp = navigator.getGamepads()[e.gamepad.index];
  gamepadInfo.textContent = `Gamepad connected at index ${gp.index}: ${gp.id}. It has ${gp.buttons.length} buttons and ${gp.axes.length} axes.`;

  gameLoop();
});

これで gamepaddisconnected イベントを使用して、ゲームパッドが再び切断されたかどうかを確認します。 もしそうならば、 requestAnimationFrame() ループ (下記参照) を停止し、ゲームパッドの情報を元の状態に戻します。

window.addEventListener("gamepaddisconnected", (e) => {
  gamepadInfo.textContent = "Waiting for gamepad.";

  cancelAnimationFrame(start);
});

今度はメインのゲームループです。ループが実行されるたびに、4 つのボタンの 1 つが押されているかどうかがチェックされます。そうすると、a と b の移動変数の値を適切に更新し、 left と top のプロパティを更新し、その値を a および b とする。これはボールを画面の周りに動かす効果があります。

この作業がすべて完了したら、 requestAnimationFrame() を使用して gameLoop() を再び実行して次のアニメーションフレームを要求します。

function gameLoop() {
  const gamepads = navigator.getGamepads();
  if (!gamepads) {
    return;
  }

  const gp = gamepads[0];
  if (gp.buttons[0].pressed) {
    b--;
  }
  if (gp.buttons[2].pressed) {
    b++;
  }
  if (gp.buttons[1].pressed) {
    a++;
  }
  if (gp.buttons[3].pressed) {
    a--;
  }

  ball.style.left = `${a * 2}px`;
  ball.style.top = `${b * 2}px`;

  start = requestAnimationFrame(gameLoop);
}
完全な例: ゲームパッドの状態の表示

この例では、 Gamepad オブジェクト、gamepadconnected イベント、 gamepaddisconnected イベントを使用してシステムに接続されているすべてのゲームパッドの状態を表示します。この例は Gamepad demo に基づいており、GitHub で利用できるソースコード があります。

let loopstarted = false;

window.addEventListener("gamepadconnected", (evt) => {
  addgamepad(evt.gamepad);
});
window.addEventListener("gamepaddisconnected", (evt) => {
  removegamepad(evt.gamepad);
});

function addgamepad(gamepad) {
  const d = document.createElement("div");
  d.setAttribute("id", `controller${gamepad.index}`);

  const t = document.createElement("h1");
  t.textContent = `gamepad: ${gamepad.id}`;
  d.append(t);

  const b = document.createElement("ul");
  b.className = "buttons";
  gamepad.buttons.forEach((button, i) => {
    const e = document.createElement("li");
    e.className = "button";
    e.textContent = `Button ${i}`;
    b.append(e);
  });

  d.append(b);

  const a = document.createElement("div");
  a.className = "axes";

  gamepad.axes.forEach((axis, i) => {
    const p = document.createElement("progress");
    p.className = "axis";
    p.setAttribute("max", "2");
    p.setAttribute("value", "1");
    p.textContent = i;
    a.append(p);
  });

  d.appendChild(a);

  // See https://github.com/luser/gamepadtest/blob/master/index.html
  const start = document.querySelector("#start");
  if (start) {
    start.style.display = "none";
  }

  document.body.append(d);
  if (!loopstarted) {
    requestAnimationFrame(updateStatus);
    loopstarted = true;
  }
}

function removegamepad(gamepad) {
  document.querySelector(`#controller${gamepad.index}`).remove();
}

function updateStatus() {
  for (const gamepad of navigator.getGamepads()) {
    if (!gamepad) continue;

    const d = document.getElementById(`controller${gamepad.index}`);
    const buttonElements = d.getElementsByClassName("button");

    for (const [i, button] of gamepad.buttons.entries()) {
      const el = buttonElements[i];

      const pct = `${Math.round(button.value * 100)}%`;
      el.style.backgroundSize = `${pct} ${pct}`;
      if (button.pressed) {
        el.textContent = `Button ${i} [PRESSED]`;
        el.style.color = "#42f593";
        el.className = "button pressed";
      } else {
        el.textContent = `Button ${i}`;
        el.style.color = "#2e2d33";
        el.className = "button";
      }
    }

    const axisElements = d.getElementsByClassName("axis");
    for (const [i, axis] of gamepad.axes.entries()) {
      const el = axisElements[i];
      el.textContent = `${i}: ${axis.toFixed(4)}`;
      el.setAttribute("value", axis + 1);
    }
  }

  requestAnimationFrame(updateStatus);
}
仕様書 ブラウザーの互換性

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4