有一种简单的方法可以在JavaScript中制作游戏循环吗?就像是...
onTimerTick() { // update game state }
1-14x0r.. 32
根据您的应用程序,使用JavaScript实现此目的的方法有很多种.setInterval()或甚至是while()语句都可以解决这个问题.这不适用于游戏循环.JavaScript由浏览器解释,因此容易中断.中断将使你的游戏回放感到紧张.
CSS3的webkitRequestAnimationFrame属性旨在通过管理渲染循环本身来纠正这个问题.然而,这仍然不是最有效的方法,如果你有很多对象被更新,它将容易出现抖动.
这是一个很好的入门网站:
http://nokarma.org/2011/02/02/javascript-game-development-the-game-loop/index.html
这个网站有一些关于制作游戏循环的基础知识的很好的信息.它无论如何都不会触及任何类型的面向对象设计.实现精确计时的最准确方法是使用日期函数.
while ((new Date).getTime() > nextGameTick && loops < maxFrameSkip) { Game.update(); nextGameTick += skipTicks; loops++; }
这没有考虑setTimeout在高频下如何漂移.这也会导致事情变得不同步并变得紧张.JavaScript每秒会漂移+/- 18ms.
var start, tick = 0; var f = function() { if (!start) start = new Date().getTime(); var now = new Date().getTime(); if (now < start + tick*1000) { setTimeout(f, 0); } else { tick++; var diff = now - start; var drift = diff % 1000; $('
现在让我们把所有这些都放到一个有效的例子中.我们想将我们的游戏循环注入到WebKit的托管渲染循环中.这将有助于平滑渲染的图形.我们还想分割绘制和更新功能.这将在计算何时应绘制下一帧之前更新渲染场景中的对象.如果更新需要很长时间,游戏循环也应该跳过绘制框架.
的index.html
Game.js
var Game = {}; Game.fps = 60; Game.maxFrameSkip = 10; Game.skipTicks = 1000 / Game.fps; Game.initialize = function() { this.entities = []; this.viewport = document.body; this.input = new Input(); this.debug = new Debug(); this.debug.initialize(this.viewport); this.screen = new Screen(); this.screen.initialize(this.viewport); this.screen.setWorld(new World()); }; Game.update = function(tick) { Game.tick = tick; this.input.update(); this.debug.update(); this.screen.update(); }; Game.draw = function() { this.debug.draw(); this.screen.clear(); this.screen.draw(); }; Game.pause = function() { this.paused = (this.paused) ? false : true; }; /* * Runs the actual loop inside browser */ Game.run = (function() { var loops = 0; var nextGameTick = (new Date).getTime(); var startTime = (new Date).getTime(); return function() { loops = 0; while (!Game.paused && (new Date).getTime() > nextGameTick && loops < Game.maxFrameSkip) { Game.update(nextGameTick - startTime); nextGameTick += Game.skipTicks; loops++; } Game.draw(); }; })(); (function() { var onEachFrame; if (window.requestAnimationFrame) { onEachFrame = function(cb) { var _cb = function() { cb(); requestAnimationFrame(_cb); }; _cb(); }; } else if (window.webkitRequestAnimationFrame) { onEachFrame = function(cb) { var _cb = function() { cb(); webkitRequestAnimationFrame(_cb); }; _cb(); }; } else if (window.mozRequestAnimationFrame) { onEachFrame = function(cb) { var _cb = function() { cb(); mozRequestAnimationFrame(_cb); }; _cb(); }; } else { onEachFrame = function(cb) { setInterval(cb, Game.skipTicks); }; } window.onEachFrame = onEachFrame; })();
更多信息
您可以在此处找到完整的工作示例和所有代码.我已将此答案转换为可下载的javascript框架,您可以从中构建游戏.
https://code.google.com/p/twod-js/
根据您的应用程序,使用JavaScript实现此目的的方法有很多种.setInterval()或甚至是while()语句都可以解决这个问题.这不适用于游戏循环.JavaScript由浏览器解释,因此容易中断.中断将使你的游戏回放感到紧张.
CSS3的webkitRequestAnimationFrame属性旨在通过管理渲染循环本身来纠正这个问题.然而,这仍然不是最有效的方法,如果你有很多对象被更新,它将容易出现抖动.
这是一个很好的入门网站:
http://nokarma.org/2011/02/02/javascript-game-development-the-game-loop/index.html
这个网站有一些关于制作游戏循环的基础知识的很好的信息.它无论如何都不会触及任何类型的面向对象设计.实现精确计时的最准确方法是使用日期函数.
while ((new Date).getTime() > nextGameTick && loops < maxFrameSkip) { Game.update(); nextGameTick += skipTicks; loops++; }
这没有考虑setTimeout在高频下如何漂移.这也会导致事情变得不同步并变得紧张.JavaScript每秒会漂移+/- 18ms.
var start, tick = 0; var f = function() { if (!start) start = new Date().getTime(); var now = new Date().getTime(); if (now < start + tick*1000) { setTimeout(f, 0); } else { tick++; var diff = now - start; var drift = diff % 1000; $('
现在让我们把所有这些都放到一个有效的例子中.我们想将我们的游戏循环注入到WebKit的托管渲染循环中.这将有助于平滑渲染的图形.我们还想分割绘制和更新功能.这将在计算何时应绘制下一帧之前更新渲染场景中的对象.如果更新需要很长时间,游戏循环也应该跳过绘制框架.
的index.html
Game.js
var Game = {}; Game.fps = 60; Game.maxFrameSkip = 10; Game.skipTicks = 1000 / Game.fps; Game.initialize = function() { this.entities = []; this.viewport = document.body; this.input = new Input(); this.debug = new Debug(); this.debug.initialize(this.viewport); this.screen = new Screen(); this.screen.initialize(this.viewport); this.screen.setWorld(new World()); }; Game.update = function(tick) { Game.tick = tick; this.input.update(); this.debug.update(); this.screen.update(); }; Game.draw = function() { this.debug.draw(); this.screen.clear(); this.screen.draw(); }; Game.pause = function() { this.paused = (this.paused) ? false : true; }; /* * Runs the actual loop inside browser */ Game.run = (function() { var loops = 0; var nextGameTick = (new Date).getTime(); var startTime = (new Date).getTime(); return function() { loops = 0; while (!Game.paused && (new Date).getTime() > nextGameTick && loops < Game.maxFrameSkip) { Game.update(nextGameTick - startTime); nextGameTick += Game.skipTicks; loops++; } Game.draw(); }; })(); (function() { var onEachFrame; if (window.requestAnimationFrame) { onEachFrame = function(cb) { var _cb = function() { cb(); requestAnimationFrame(_cb); }; _cb(); }; } else if (window.webkitRequestAnimationFrame) { onEachFrame = function(cb) { var _cb = function() { cb(); webkitRequestAnimationFrame(_cb); }; _cb(); }; } else if (window.mozRequestAnimationFrame) { onEachFrame = function(cb) { var _cb = function() { cb(); mozRequestAnimationFrame(_cb); }; _cb(); }; } else { onEachFrame = function(cb) { setInterval(cb, Game.skipTicks); }; } window.onEachFrame = onEachFrame; })();
更多信息
您可以在此处找到完整的工作示例和所有代码.我已将此答案转换为可下载的javascript框架,您可以从中构建游戏.
https://code.google.com/p/twod-js/
setInterval(onTimerTick, 33); // 33 milliseconds = ~ 30 frames per sec function onTimerTick() { // Do stuff. }
requestAnimationFrame现在是大多数浏览器的绝佳选择.它使用setInterval执行您正在执行的操作,但是以烘焙方式执行.可能最好的事情是它只在你的标签聚焦时运行.如果你想让事情在后台运行,那么这可能是不使用它的一个原因,但是经常(特别是对于渲染循环,只在看到时很重要),当标签不活动时,不使用资源是很好的.
用法非常简单:
function gameLoop(){ window.requestAnimationFrame(gameLoop); Game.update(); }
我讨厌在旧线程上发帖,但这是"javascript游戏循环"的顶级谷歌结果,所以它确实需要包含requestAnimationFrame.
从paulirish复制的旧浏览器的Pollyfill:
(function() { var lastTime = 0; var vendors = ['ms', 'moz', 'webkit', 'o']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) { clearTimeout(id); }; }());
有关creativeJS的更深入的解释和使用提示