0

我正在尝试用 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 的具体实现中,并根据其规范进行更新。

假设敌人是蓝色的小矩形。为了将这些敌人添加到我的游戏中,我将添加一个类 Enemy,它实现了 GameObject 并具有一个特殊的更新方法,可以将敌人移向玩家并检查交叉点。机器人对象只是一个非常简单的例子。

代码对我来说似乎很好,VisualStudio 没有标记任何错误,但是当我尝试运行游戏时,会弹出一条错误消息并通知我:

错误 1 ​​命令“tsc --sourcemap "...strategy go\game.ts" "...strategy go\raphael-2.1.d.ts" "...strategy go\app.ts"" 退出代码1. ...strategy go\strategy go.csproj 85 5 strategy go

我确信这与我的 IDE 设置无关,因为另一个 typescript/raphaelJs 项目效果很好。不幸的是,我无法从错误消息中获得任何有用的信息。

更新:注释掉gameObjects.forEach((object) => object.update(elapsedTime));项目后编译没有错误。VisualStudio 说“构建成功”并打开 Chrome。但页面从未完成加载。即使我输入这个,我什至没有看到 html 文件中的文本。

更新2: 我用window.setInterval交换了while循环,现在错误消失了,页面加载了。但这不是经典的游戏循环。我想知道为什么一个简单的 while 循环会阻止我的页面加载。这似乎是自相矛盾的,因为 while 循环是在 window.onload 中执行的。

4

1 回答 1

3

我不确定您最初的 TypeScript 错误(在 Visual Studio 中构建项目时,您通常可以通过查看输出窗口来查看错误本身),但至于为什么您的页面会在 while (true) { } 循环期间冻结是因为您创建了一个无限阻塞循环。JavaScript 在单线程进程中运行,因此您的原始循环所做的是阻止窗口中发生其他任何事情。

JavaScript 也在基于队列的系统上执行代码,setInterval(fn, delay) 所做的实际上是将函数添加到队列中,以便在遇到延迟时执行(这也是我们在 JavaScript 中实现异步编程的方式)。因此, setInterval(fn, 0) 实际上并没有立即执行代码(尽管它可能看起来这样做),而是将函数添加到队列的顶部,执行队列中的其他代码,然后执行您的函数当它到达时(因此,如果您正在评估执行时间,取决于代码中发生的一切,您的代码可能不会像您指定的那样在 0ms 执行)。

也正因为如此,如果您试图以一致的帧速率实现游戏循环,则不应依赖 setInterval 函数的“延迟”参数,因为这甚至可能因浏览器而异。如果帧速率一致性在您的游戏中很重要,您应该跟踪自己的时间间隔和已用时间。

于 2012-12-28T17:37:49.397 回答