--
--

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
21
2018

GamepadAPIを使ってゲームを市販のコントローラーで操作できるようにしてみる:応用編

Category技術
こんにちは。なるとりっくのシステム担当です。

今回は応用編ということで、画面遷移を考慮したGamepadAPIの使い方を書いていきます。


ゲームを作るとなるとトップ画面やコンフィグ画面やセーブ画面などいろんな画面が必要になってきます。そしてそれら全てにそれぞれの画面に応じたボタン押下時のイベントをGamepadAPIで付与しなければなりません。それとイベントを付与するだけでなく、削除の事も考える必要があります。


例えば画面Aから画面Bに遷移するときのイベントのライフサイクルは以下のようになります。

1. 画面Aを表示する
  →この時に画面AのGamepadイベント付与
2. 画面Bに遷移する
  →この時に画面AのGamepadイベント削除、画面BのGamepadイベント付与

画面Bに遷移するときは、不要になった画面AのGamepadイベントをちゃんと削除しておかなければいけません。
余計なイベントが残っていると不具合の原因になります。


次にこんな画面遷移の場合はどうなるでしょうか?

1.画面Aを表示する
2.画面Bに遷移する
3.前の画面(この場合は画面A)に戻る

例えば画面Bがコンフィグのような画面の場合、コンフィグをいじり終わった後に前の画面に戻らないといけません。
単純に考えると、
1で画面Aのイベント付与
2で画面Aのイベント削除と画面Bのイベント付与
3で画面Bのイベント削除と画面Aのイベント付与
となります。
これをコードで書くと以下のような感じになります。
Gamepadイベント付与は前回の基礎編でやった通りカスタムイベントを使います。

// 画面Aを表示する
show_a_view();

// 画面Aのイベント付与
var press_a1 = function() {
    console.log("画面AでAボタンを押しました!")
}
addEventListener("gamepad_a_press", press_a1);


// ---画面Aでいろいろやる---


// 画面Bに遷移
show_b_view();

// 画面Aのイベント削除
removeEventListener("gamepad_a_press", press_a1);

// 画面Bのイベント付与
var press_a2 = function() {
    console.log("画面BでAボタンを押しました!")
}
addEventListener("gamepad_a_press", press_a2);


// ---画面Bでいろいろやる---


// 前の画面に戻る
return_previous_view();

// 画面Bのイベント削除
removeEventListener("gamepad_a_press", press_a2);

// 前の画面のイベント付与
var press_a3 = function() {
    console.log("画面Aボタンを押しました!")
}
addEventListener("gamepad_a_press", press_a3);

こんな感じで前の画面に戻る時に、一旦削除したイベントを再度付け直さないといけません。
画面Bには画面Aからしか遷移しない場合は、このように画面Aのイベントを付け直すと決めてしまえばいいのですが、画面Cからも画面Bに遷移する可能性が出てきた場合に対応できなくなります。

なので元の画面に戻ってくることが前提の画面遷移をするときは一旦イベントをどこか別の場所に退避させておいて、元の画面に戻ったときに復活させるようにします。

そのために以下のような関数を用意しました。

var gamepad_events = {};
var stash_gamepad_events = {};

// Gamepadのイベントを付与する処理
var add_gamepad_event_listener = function (event, listener) {
    if (gamepad_events[event] == undefined) {
        gamepad_events[event] = [];
    }
    gamepad_events[event].push(listener);
    addEventListener(event, listener)
}

// Gamepadのイベントを退避しておく処理
var stash_gamepad_event_listener = function (key) {
    stash_gamepad_events[key] = gamepad_events;
    Object.keys(gamepad_events).forEach(function (key_) {
        for (var i = 0; i < gamepad_events[key_].length; i++) {
            var listener = gamepad_events[key_][i];
            removeEventListener(key_, listener);
        }
    });
    gamepad_events = {};
}

// 退避していたGamepadのイベントを復活させる処理
var restore_gamepad_event_listener = function (key) {
    Object.keys(gamepad_events).forEach(function (key_) {
        for (var i = 0; i < gamepad_events[key_].length; i++) {
            var listener = gamepad_events[key_][i];
            removeEventListener(key_, listener);
        }
    });
    gamepad_events = stash_gamepad_events[key];
    delete stash_gamepad_events[key];
    if(gamepad_events) {
        Object.keys(gamepad_events).forEach(function (key_) {
            for (var i = 0; i < gamepad_events[key_].length; i++) {
                var listener = gamepad_events[key_][i];
                addEventListener(key_, listener);
            }
        });
    }
}

// Gamepadのイベントをクリアする処理
var clear_gamepad_event_listener = function () {
    Object.keys(gamepad_events).forEach(function (key) {
        for (var i = 0; i < gamepad_events[key].length; i++) {
            var listener = gamepad_events[key][i];
            removeEventListener(key, listener);
        }
    });
    gamepad_events = {};
}

add_gamepad_event_listener(event, listener)はGamepadのイベントを付与すると同時に、付与したイベントを保持しておいてくれます。引数はaddEventListenerと同じなのでそのまま置き換えることができます。 
stash_gamepad_event_listener(key)は、add_gamepad_event_listener(event, listener)を使って付与したイベントを退避させてくれます。その際、現在付与されているイベントが一旦外れます。引数のkeyは必須です。
restore_gamepad_event_listener(key)は、stash_gamepad_event_listener(key)で退避したイベントを復活させてくれます。stashの際に指定したkeyと対応したイベントを復活させるので、引数のkeyは必須です。

clear_gamepad_event_listener()は、add_gamepad_event_listener(event, listener)を使って付与したイベントを退避無しで削除してくれます。


これらの関数を使って画面遷移の際のGamepadイベントを制御します。

すると以下のような感じになります。
 
// 画面Aを表示する
show_a_view();

// 画面Aのイベント付与
var press_a1 = function() {
    console.log("画面AでAボタンを押しました!")
}
add_gamepad_event_listener("gamepad_a_press", press_a1);


// ---画面Aでいろいろやる---


// 画面Bに遷移
show_b_view();

// 前の画面のイベントを退避
stash_gamepad_event_listener("b_view");

// 画面Bのイベント付与
var press_a2 = function() {
    console.log("画面BでAボタンを押しました!")
}
add_gamepad_event_listener("gamepad_a_press", press_a2);


// ---画面Bでいろいろやる---


// 前の画面に戻る
return_previous_view();

// 退避していた前の画面のイベントを復活
restore_gamepad_event_listener("b_view");

どこの画面から遷移してきたかというのは意識せずにとにかく今付与されているイベントを退避し、また必要になったら復活させるというやり方です。
これでどこから画面Bに遷移したとしても、前の画面に戻ったときにイベントを復活させることができるようになりました。
keyを指定して複数退避させることができるようにしているので、画面遷移がA→B→C→B→Aの様に深くなっても対応できます。

今回はここまでで、次回は具体例を交えた実践編をやりたいと思います。
スポンサーサイト

0 Comments

Leave a comment

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。