我正在尝试创建一个简单的游戏循环并尝试在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.Run
处this.timer.tick();
所以我想知道,我的代码有什么问题?谢谢你的回复。
答案 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,所以从小写开始。