HTML5 Canvas渲染很奇怪



我正在学习HTML5(和OO Javascript),并试图制作一个简单的游戏引擎,但渲染到画布在非常奇怪的条件下工作。这是该页面的链接,这是我的索引.html:

<html>
<head>
    <script type="text/javascript">
        function load()
        {
            var game = new Game();
            game.start();   
        }
    </script>
    <title>Game</title>
    <style>
        canvas
        {
            outline:0;
            border:1px solid #000;
            margin-left: auto;
            margin-right: auto;
        }
    </style>
</head>
<body onload="load()">
    <canvas id='c'></canvas>
    <script src="classes/Tuple.js"></script>
    <script src="classes/Rect.js"></script>
    <script src="classes/Sprite.js"></script>
    <script src="classes/Game.js"></script>
</body>
</html>



首次加载时,它将在Firefox 11.0中给出NS_ERROR_DOM_TYPE_MISMATCH_ERR异常,在Chrome 18.0中给出TypeError异常。要使其正常工作:

火狐 11.0

  • 在地址栏中选择 URL,然后手动按回车键或
  • 单击刷新按钮或
  • 按 F5。

铬 18.0

  • 在地址栏中选择 URL,然后手动按回车键或
  • 单击刷新按钮或
  • 按 F5 或
  • 按 Shift/Ctrl + F5。

我怀疑 - 只是一个猜测,但似乎一个或多个.js文件在第一次页面加载期间调用时不可用/准备就绪。在Firebug中经历了几次之后,似乎精灵图像永远不会在第一页请求中加载。

也许一些.js文件仍在下载,因为正在对 Game() 进行实例化,然后缓存,并且只有在第二个页面加载时才能使用?

有什么想法吗?我很感激你的看法,谢谢!

我在本地复制了您的文件并进行了一些测试。在我看来,不可用的不是你的JavaScript文件,而是你的精灵。

在调用 Game.start 之前,您不会加载 PNG。 当您执行以下操作时:

roadSpritesheetImage.src = "assets/sprites/player/playerSpriteSheet.png";

这将开始映像的异步下载。其余代码在图像完全加载之前执行,因此当您对图像进行切片时,您将对其进行切片,就好像 src 属性为 null 一样。

这就是为什么您可以点击刷新并且一切都按预期工作的原因......图像被缓存。

您可以通过在画布之前添加图像标签来抢占精灵的加载:

<img src="assets/sprites/player/playerSpriteSheet.png" style="display:none;" />

这将起作用,因为在内容(包括图像)完全加载之前不会触发 body load 事件(我相信,我必须查找这个)。 然后,如果将此图像分配给img.src,则将引用缓存的图像。

或者,您可以将游戏功能的其余部分绑定到 img.onload .例如:

self.loadSprites = function()
{
    var roadSpritesheetImage = new Image();     
    roadSpritesheetImage.onload = function() { 
        self.entities.push(new Sprite("testTile", 
            roadSpritesheetImage, 
            new Tuple(16, 16), 
            new Rect(0, 0, 32, 16)));
        self.run();
    };
    roadSpritesheetImage.src = "assets/sprites/player/playerSpriteSheet.png";
};
self.run = function() {
    var drawSuccessful = false;
    drawSuccessful = self.entities[0].draw(self.context);
    self.entities[0].nextFrame();
    //if we managed to draw the Sprite successfully without any raised exceptions
    if(drawSuccessful) {
        setTimeout(self.run, 300);
    } else { alert("stopping execution of the game."); }
};
self.start = function()
{
    self.loadSprites();
};

这样做会更干净一些,它可以保证你的资源没有任何竞争条件。

我创建的jQuery插件也遇到了类似的问题,该插件用于从源图像绘制N拼图。 我发现这个 MDN 文档当时非常有用,尽管我最终使用了切片div 而不是画布。

最新更新