0

JavaScript ゲームに少しのイベント処理を実装しようとしているときに、奇妙な動作が発生します。私は JavaScript の専門家ではなく、何か重要なことを見逃しているように感じますが、何が問題なのかわかりません。

このEventManagerを「クラス」にしました。

function EventManager(events) {

    var _events;

    this.addEventCallback = function(eventName, callback) {
        _events[eventName].push(callback);
    }

    this.fireEvent = function(eventName) {
        for (var i = 0; i < _events[eventName].length; i++) {
            _events[eventName][i]();
        }
    }

    // constructor

    __construct = function(that) {
        _events = [];
        for (key in events) {
            _events[events[key]] = new Array();
        }
    }(this)

}

私のGameObjectクラスでは、次のように EventManager を使用します。

function GameObject() {

    // define event ids
    var _events = {
        MOVE_START: 0,
        MOVE_STOP: 1
    }

    var _eventManager;

    // how i fire the event:

    this.moveLeft = function() {
        if (!_isMoving()) {
                _eventManager.fireEvent(_events.MOVE_START);
                _velocity = new Vector(-1, 0);
        }
    }

    // event registration "interface"

    this.onMoveStart = function(fn) {
        _eventManager.addEventCallback(_events.MOVE_START, fn);
    }

    this.onMoveStop = function(fn) {
        _eventManager.addEventCallback(_events.MOVE_STOP, fn);
    }

    // constructor

    __construct = function(that) {
        _eventManager = new EventManager(_events);
    }(this);

}

それで、私は物事をテストします:

    for (var i = 0; i < _gameObjects.length; i++) {
        console.log("event handler to object number " + i);
        _gameObjects[i].onMoveStart(function() {
            console.log("object number " + i + " started moving");
        });
    }

最初のオブジェクトを移動すると「オブジェクト番号 0 が移動を開始」、2 番目のオブジェクトを移動すると「オブジェクト番号 1 が移動を開始」などの出力が期待されます。

出力は常に「オブジェクト番号 3 が移動を開始しました」です。どのオブジェクトを移動しても、常にオブジェクト番号 3 と表示されます。私にとって最も奇妙な部分は、_gameObjects-Array に 3 つのオブジェクトしかないため、少なくとも「オブジェクト番号 2 が動き始めた」と言うと予想されることです。

私はこれをやってみました:

    for (var i = 0; i < _gameObjects.length; i++) {
        var num = i;
        console.log("event handler to object number " + num);
        _gameObjects[i].onMoveStart(function() {
            console.log("object number " + num + " started moving");
        });
    }

すると、常に「オブジェクト番号 2 が動き始めました」と出力されます。

移動したいオブジェクトを移動できるため、オブジェクトがすべて同じであるとは限りません。

手伝ってくれてどうもありがとう!

4

1 に答える 1

1

あなたの質問に対する答えは「はい」です。つまり、JS 匿名関数の変数スコープについて何か見逃していました。ここで完全に引用されている記事である「Javascript Closures for Dummies」を読むことをお勧めします: JavaScript クロージャはどのように機能しますか? .

テスト コードを機能させるには、次のようにします。

function notifyStart(i) {
    return function() {
        console.log("object number " + i + " started moving");
    }
}

for (var i = 0; i < _gameObjects.length; i++) {
    _gameObjects[i].onMoveStart( notifyStart(i) );
}
于 2013-04-19T12:44:14.300 に答える