画布游戏错误

时间:2012-10-23 13:12:06

标签: javascript html5-canvas

我正在尝试创建一个简单的游戏循环并尝试在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);
    }
}​

Fiddle

我正在努力使Game类全球化。其他类必须使用new进行即时处理。

类游戏和计时器放在名为Game.js和Timer.js的不同文件中。当我在Chrome中运行此代码时,我在DevTools中遇到错误:"Uncaught TypeError: Cannot call method 'tick' of undefined"函数Game.Runthis.timer.tick();

所以我想知道,我的代码有什么问题?谢谢你的回复。

2 个答案:

答案 0 :(得分:1)

您的问题与上下文有关。当你打电话时,this是窗口,而不是游戏。 例如,您可以通过设置:

来处理此问题
var self = this;        
this.Run = function() {
    self.timer.tick();
    self.Update(self.timer.getLastTickInterval());
    self.Draw();
}

答案 1 :(得分:0)

您的代码中需要考虑的事项很少:

关于你的问题,像setInterval或setTimeout这样的方法会松散上下文。最简单的解决方案是将上下文绑定到回调:

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

其次,避免在对象函数中添加私有方法。在这种情况下,Game的每个实例都有自己的一组函数(内存泄漏)。 更喜欢使用原型:

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

最后,我看到你每隔一秒重绘一次,这没关系。但是如果你想要60fps,你可以使用requestAnimationFrame来绘制导向循环。

ps:只是非常挑剔,函数的名称应该是camelCase,所以从小写开始。