Существует множество способов достичь этого с помощью 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 будет дрейфовать +/- 18 мс в секунду.
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;
$('<li>').text(drift + "ms").appendTo('#results');
setTimeout(f, 990);
}
};
setTimeout(f, 990);
Теперь давайте все это приведем в рабочий пример. Мы хотим внедрить наш игровой цикл в цикл управляемого рендеринга WebKit. Это поможет сгладить визуализированную графику. Мы также хотим разделить функции рисования и обновления. Это обновит объекты в нашей сцене рендеринга перед вычислением, когда должен быть нарисован следующий кадр. Игровой цикл также должен пропускать рисованные кадры, если обновление занимает много времени.
Index.html
<html>
<head>
<!--load scripts-->
</head>
<!--
render canvas into body, alternative you can use div, but disable
right click and hide cursor on parent div
-->
<body oncontextmenu="return false" style="overflow:hidden;cursor:none;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;">
<script type="text/javascript" charset="utf-8">
Game.initialize();
window.onEachFrame(Game.run);
</script>
</body>
</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/