我正在尝试使用Typescript和RaphaelJs进行一场小游戏。到目前为止,代码很短:
/// <reference path="raphael-2.1.d.ts"/>
window.onload = () => {
var paper: RaphaelPaper = Raphael(10, 50, 500, 500);
var time: Date =new Date();
var now = time.getTime();
var elapsedTime = time.getTime() - now;
var gameObjects = new GameObject[];
var robot =new Robot( paper.rect(10, 10, 100, 100));
robot.elem.attr("fill", "green");
gameObjects.push(robot);
while (true) {
elapsedTime = time.getTime() - now;
gameObjects.forEach((object) => object.update(elapsedTime));
//gameObjects.forEach((object) => object.draw(paper));
}
}
interface GameObject{
update(time:number);
}
class Robot implements GameObject{
public x: number;
public y: number;
public elem: RaphaelElement;
constructor(element: RaphaelElement) {
this.elem = element;
this.x = this.elem.attr("x");
this.y = this.elem.attr("y");
}
public update(time: number) {
this.x += 1;
this.y += 1;
this.elem.attr("x", this.x);
this.elem.attr("x", this.y);
}
}
当页面加载完新的RaphaelPaper后,会创建一个GameObjects列表。每个GameObject都需要实现一个方法:update。这个想法是在游戏过程中创建的每个RaphaelElement都存储在GameObject的具体实现中,并根据其规格进行更新。
让我们假设敌人是小蓝色矩形。为了将这些敌人添加到我的游戏中,我会添加一个实现GameObject的类Enemy,并且有一个特殊的更新方法,可以将敌人移向玩家并检查交叉点。机器人对象只是一个非常简单的例子。
代码对我来说似乎很好,VisualStudio标记没有错,但当我尝试运行游戏时,会弹出一条错误消息并通知我:
错误1命令“tsc --sourcemap”... strategy go \ game.ts“ “...策略go \ raphael-2.1.d.ts”“...策略go \ app.ts”“退出代码 1. ...策略go \ strategy go.csproj 85 5策略go
我确信这与我的IDE设置无关,因为另一个打字稿/ raphaelJs项目效果很好。不幸的是,我无法从错误消息中获取任何有用的信息。
更新:
注释掉gameObjects.forEach((object) => object.update(elapsedTime));
之后,项目编译没有错误。 VisualStudio说“构建成功”并且Chrome打开了。但页面从未完成加载。即使我输入此内容,我甚至都没有看到html文件中的文字。
更新2: 我用window.setInterval交换了while循环,现在错误消失了,页面加载了。但这不是经典的游戏循环。我想知道为什么一个简单的while循环阻止我的页面加载。这似乎是矛盾的,因为while循环是在window.onload中执行的。
答案 0 :(得分:3)
我不确定您的原始TypeScript错误(您通常可以通过在Visual Studio中构建项目时查看“输出”窗口来查看错误本身),但是为什么您的页面会在一段时间内冻结(true) {}循环是因为你创建了一个无限的阻塞循环。 JavaScript在单线程进程中运行,因此原始循环所做的是阻止窗口中发生的任何其他事情。
JavaScript还在基于队列的系统上执行代码,setInterval(fn,delay)所做的实际上是将函数添加到队列中,以便在命中延迟时执行(这也是我们实现异步编程的方式) JavaScript的)。因此,setInterval(fn,0)实际上不会立即执行代码(虽然它似乎可以这样做),但会将函数添加到队列的顶部,执行队列中的其他代码,然后执行您的函数当它到达它时(所以如果你正在评估执行时间,取决于你的代码中发生的一切,你的代码可能不会像你指定的那样在0ms执行)。
同样正因为如此,如果你想要实现具有一致帧速率的游戏循环,你不应该依赖setInterval函数的'delay'参数,因为这甚至可能因浏览器而异。如果帧率一致性在游戏中很重要,您应该跟踪自己的时间间隔和缩短时间。