0

単純なゲームループを作成し、JSでOOPパラダイムを使用しようとしています。これが私のコードです:

HTML

<body onload="Game.OnLoad('gameField')" onkeydown="Game.KeyDown(event)">
    <p id="info">1</p>
    <p id="info2">2</p>
    <canvas id="gameField" 
            width="896px" 
            height="717px" 
            class="game-field" 
            style="border: 4px solid aqua"
            onclick="Game.MouseClick(event)"></canvas>
</body>

JavaScript

// class Timer
// version: 1
// only tick() functionality available
// right now
function Timer() {
    var date = new Date();

    var prevTick = 0;
    var currTick = 0;
    // update timer with tick
    this.tick = function() {
        prevTick = currTick;
        currTick = date.getTime();
    }
    // get time between two ticks
    this.getLastTickInterval = function() {
        return currTick - prevTick;
    }
}

// global object Game
// which handles game loop
// and provide interfaces for     
var Game = new function() {
    // variables:
    this.canvas = 0;
    var gameLoopId = 0;
    this.timer = new Timer();
    // events:
    this.KeyDown = function(e) {}

    // game loop:    
    this.Run = function() {
        this.timer.tick();
        this.Update(this.timer.getLastTickInterval());
        this.Draw();
    }
    this.Update = function(dt) {
        document.getElementById("info").innerHTML = dt;
    }
    this.Draw = function() {}
    this.StopGameLoop = function() {
        clearInterval(gameLoopId);
    }
    this.OnLoad = function(canvasName) {
        this.canvas = document.getElementById(canvasName);
        this.timer.tick();

        // start game loop
        setInterval(this.Run, 1000);
    }
}​

フィドル

ゲームクラスをグローバルにしようとしています。他のクラスは、を使用してインスタンス化する必要がありますnew

クラスGameとTimerは、Game.jsとTimer.jsと呼ばれる異なるファイルに配置されます。このコードをChromeで実行すると、DevToolsでエラーが発生しまし"Uncaught TypeError: Cannot call method 'tick' of undefined"Game.Runthis.timer.tick();

だから、私のコードの問題は何ですか?返信ありがとうございます。

4

2 に答える 2

1

あなたの問題は文脈にあります。ティックを呼び出すときthisは、ゲームではなくウィンドウです。これは、たとえば、次のように設定することで処理できます。

var self = this;        
this.Run = function() {
    self.timer.tick();
    self.Update(self.timer.getLastTickInterval());
    self.Draw();
}
于 2012-10-23T13:18:19.403 に答える
0

コードで考慮すべき点はほとんどありません。

問題に関しては、setIntervalやsetTimeoutなどのメソッドがコンテキストを失います。最も簡単な解決策は、コンテキストをコールバックにバインドすることです。

setInterval(this.Run.bind(this), 1000);

次に、オブジェクト関数内にプライベートメソッドを追加しないでください。その場合、Gameのすべてのインスタンスに独自の関数セットがあります(メモリリーク)。プロトタイプの使用をお勧めします:

function Game () {
    this.canvas = null;
}
Game.prototype = {
    init: function() {}
    render: function () {}
};

最後に、毎秒再描画しますが、問題ありません。ただし、60 fpsが必要な場合は、requestAnimationFrameを使用して指向ループを描画できます。

ps:非常にわかりやすいように、関数の名前はキャメルケースにする必要があるため、小文字から始めます。

于 2016-11-15T09:13:05.633 に答える