我正在用 TypeScript 编写贪吃蛇游戏,但在定义 KeyListener(用于改变贪吃蛇方向的箭头键)时遇到了问题。
我有一个 4 层架构,关键事件在 Gui 类中处理。这包含 Snake 对象、绘制蛇并处理关键事件。
我尝试了正常的方式,但是在 handleEvt 内部,snake 对象是未定义的。
document.addEventListener("keydown", handleEvt)
所以我尝试了粗箭头方法,但现在函数根本没有被调用。我怀疑关键监听器更改了上下文并且不再在窗口上工作
document.addEventListener("keydown", () => handleEvt)
谁能解释一下这里的问题是什么?将不胜感激!
下面是我的 Gui 类:
/// <reference path="../model/Snake.ts" />
/// <reference path="../model/Direction.ts" />
/// <reference path="../model/Part.ts" />
/// <reference path="../dao/Dao.ts" />
/// <reference path="../service/Service.ts" />
/// <reference path="../model/IPosObject.ts" />
module gui {
export class Gui {
snake:model.Snake;
canvas:HTMLCanvasElement;
ctx:CanvasRenderingContext2D;
loop:any;
lineWidth:number;
canvasSize:number;
loopSpeed:number;
unitLength:number;
constructor(snake:model.Snake) {
// init constants
this.snake = snake;
this.lineWidth = 3;
this.canvasSize = 200;
this.loopSpeed = 1000/60;
this.unitLength = 5;
// init canvas
this.canvas = document.getElementsByTagName("canvas")[0];
this.canvas.width = this.canvasSize;
this.canvas.height = this.canvasSize;
this.ctx = this.canvas.getContext("2d");
// Attach key event
// document.addEventListener("keydown", this.handleEvt);
document.addEventListener("keydown", () => this.handleEvt);
// activate game loop
this.loop = setInterval( () => this.gameLoop(), this.loopSpeed );
}
handleEvt(e):void {
var direction:model.Direction;
if (e) {
switch (e.which) {
case 37:
console.log("left");
direction = model.Direction.Left;
break;
case 38:
console.log("up");
direction = model.Direction.Up;
break;
case 39:
console.log("right");
direction = model.Direction.Right;
break;
case 40:
console.log("down");
direction = model.Direction.Down;
break;
}
this.snake.changeDirection(direction);
}
}
gameLoop():void {
if (this.snake) {
this.drawSnake();
}
}
drawSnake() {
// draw parts
}
}
}
最佳答案
这个问题有多种解决方案,您可以在 addEventListener 端修复它,方法与您对 setInterval 所做的相同。在 keyDown 监听器中,您没有调用 handleEvt,因此将其更改为
() => this.handleEvt()
.
另一个可以像上面那样使用它的解决方案是:
document.addEventListener("keydown", this.handleEvt);
然后像这样声明 handleEvt:
handleEvt = (e) => {
var direction:model.Direction;
...<snip>
}
或者另一种解决方案:
document.addEventListener("keydown", this.handleEvt.bind(this));
如您所见,有不同的解决方案,您可以选择自己喜欢的一种。 this
丢失是因为该函数不是在实例上调用的,这是正常的(但有时会造成混淆)JavaScript 行为。
关于javascript - TypeScript 中的 KeyListener 和 "this"上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29575916/