HTML5和Canvas滚动:欺骗有趣还是无用?

时间:2013-08-19 12:36:18

标签: html5 canvas scroll game-engine

我已经阅读了所有关于滚动的内容:

Structuring an HTML5 Canvas/JS Game

等等:

(最新的一个令人印象深刻,但即使几乎所有事情都已完成,滚动也没有。)

这就是我正在考虑的问题,而且我没有找到有价值的东西。我想到了一个想法,我想知道我是否应该花很多时间思考这个问题并尝试与否(这就是我实际上在这里问的原因)。

我打算用滚动的“àla”Mario进行游戏。

滚动的一大缺点是你必须重绘整个背景。 我已经避免了精灵/滚动的两个性能问题:创建两个画布彼此顶部:

  • 背景
  • 精灵

然后擦掉精灵。

问题在于背景:我正在为“可见”画布制作背景的完整副本。 (注意:闪烁没有问题,因为在JavaScript中编写是一个阻塞操作,所有现代浏览器都处理垂直同步,所以不需要双缓冲。)

这是我正在撰写的旧版本,但你会了解全局:

Test HTML5

现在我想知道滚动:如果我使用适当的CSS(背景的背景图像)执行“背景div”而不是画布,然后直接在图像上写入图块,然后更改CSS模拟滚动?应该更快吗?如果是这样,为什么?那有什么好主意吗?

4 个答案:

答案 0 :(得分:1)

在具有半近期+浏览器的半现代+计算机上,最快的事情可能是采用背景图像的超长div,将溢出设置为隐藏并通过调整scrollLeft或scrollTop属性进行滚动。这比调整CSS属性要快得多,因为它不应该触发CSS引擎中的任何回流计算。基本上,每当您触摸可能具有CSS影响的DOM属性时,都需要重新检查并重新呈现文档结构的整个(或至少很多)。

你可以加载背景的大块,因为它们接近以避免一个巨大的巨大图像负载。我不相信有任何100%的万无一失的方法可以在浏览器中删除内存中的图像,但是当你滚动远远时,在DOM或CSS中删除对它的引用可能并不会受到影响足够超过你的背景。这样浏览器的垃圾收集器至少可以选择清除内存。

依赖于网页浏览的泛移动解决方案(如Cordova / Phonegap),,以及为什么我会遇到这个问题。

我不知道,但我非常确定混合HTML和画布对于性能来说是一个糟糕的想法。现在我有一个非超级复杂的安卓游戏在一个安卓网页视图中的画布元素中窒息50x50 100px瓷砖,它还有一些基本的HTML混合用于控制和分离其他几个画布元素之类的东西从其他人。我基本上有一只观鸟船在周围巡航,并用一个俗气的辐射圆圈扫描,在地图上出现战争风格的元素。在浏览器中运行良好。在cordova应用程序版本中完成灾难。

我怀疑我实现泛手机游戏开发梦想的唯一方法是使用众多openGL-in-a-canvas-API解决方案中的一个,完全抛弃HTML鉴于我的大部分经验都在Web UI中,我觉得该UI实现很方便。 Web视图HTML的另一个一般提示是尽可能避免在内部元素内滚动(所以只需让主体处理溢出)。滚动溢出除了身体甚至不能在Android 2的网页浏览中工作,它似乎仍然导致4.1的观点扼杀了早期/更简单的应用程序版本我'正在努力。

答案 1 :(得分:0)

最快的滚动是使用CSS滚动。因此,您绘制所有背景一次,不仅是可见部分,而是全部,并隐藏不可见,并使用css滚动它(边距或位置)。没有重绘,只有CSS更改。这项工作真的很快。但如果所有地图都非常庞大,其他自定义方式可能会更好。

答案 2 :(得分:0)

我的最终结论:经过多次尝试,包括Eirk Reppen建议,我直接将“raw”写入画布的隐藏部分并使用CSS:所有webbrowsers处理已经出现的图像闪烁和所有这些东西,并且他们已经优化了所有内容

所以每次我尝试“优化”时,结果都更糟

似乎网页浏览器可以处理由初学者制作的正确基本内容...可能因为99%的HTML内容是由初学者制作的。

答案 3 :(得分:0)

这是一个通过更改CSS边距滚动超大画布的演示,这个基于滚动时间:https://jsfiddle.net/6othtm0c/

这个版本的鼠标拖动:https://jsfiddle.net/ax7n8944/

HTML:

<div id="canvasdiv" style="width: 500px; height: 250px; overflow: hidden">
    <canvas id="canvas" width="10000px" height="250px"></canvas>
</div>

JS for the scroll-with-time version:

canvas = document.getElementById("canvas");
context = canvas.getContext('2d');

for (var i = 0; i < 1000; i++) {
    context.beginPath();
    context.arc(Math.random() * 10000, Math.random() * 250, 20.0, 0, 2 * Math.PI, false);
    context.stroke();
} 

var t0 = window.performance.now();
setInterval(function(){
    canvas.style.marginLeft = -(window.performance.now() - t0)/5 + "px";
}, 5);