diff options
Diffstat (limited to 'jaws/src/game_loop.js')
| -rwxr-xr-x | jaws/src/game_loop.js | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/jaws/src/game_loop.js b/jaws/src/game_loop.js new file mode 100755 index 0000000..aa773e5 --- /dev/null +++ b/jaws/src/game_loop.js @@ -0,0 +1,135 @@ +if(typeof require !== "undefined") { var jaws = require("./core.js"); } + +var jaws = (function(jaws) { + +// requestAnim shim layer by Paul Irish +window.requestAnimFrame = (function(){ + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function(/* function */ callback, /* DOMElement */ element){ + window.setTimeout(callback, 16.666); + }; +})(); + +/** + * @class A classic game loop forever looping calls to update() / draw() with given framerate. "Field Summary" contains options for the GameLoop()-constructor. + * + * @property {int} tick_duration duration in ms between the last 2 ticks (often called dt) + * @property {int} fps the real fps (as opposed to the target fps), smoothed out with a moving average + * @property {int} ticks total amount of ticks since game loops start + * + * @example + * + * game = {} + * draw: function() { ... your stuff executed every 30 FPS ... } + * } + * + * game_loop = new jaws.GameLoop(game, {fps: 30}) + * game_loop.start() + * + * // You can also use the shortcut jaws.start(), it will: + * // 1) Load all assets with jaws.assets.loadAll() + * // 2) Create a GameLoop() and start it + * jaws.start(MyGameState, {fps: 30}) + * + */ +jaws.GameLoop = function GameLoop(game_object, options, game_state_setup_options) { + if( !(this instanceof arguments.callee) ) return new arguments.callee( game_object, options ); + + this.tick_duration = 0 + this.fps = 0 + this.ticks = 0 + + var update_id + var paused = false + var stopped = false + var that = this + var mean_value = new MeanValue(20) // let's have a smooth, non-jittery FPS-value + + /** + * returns how game_loop has been active in milliseconds + * does currently not factor in pause-time + */ + this.runtime = function() { + return (this.last_tick - this.first_tick) + } + + /** Start the game loop by calling setup() once and then loop update()/draw() forever with given FPS */ + this.start = function() { + jaws.log.info("Game loop start", true) + + this.first_tick = (new Date()).getTime(); + this.current_tick = (new Date()).getTime(); + this.last_tick = (new Date()).getTime(); + + if(options.setup !== false && game_object.setup) { game_object.setup(game_state_setup_options) } + step_delay = 1000 / options.fps; + + if(options.fps == 60) { + requestAnimFrame(this.loop) + } + else { + update_id = setInterval(this.loop, step_delay); + } + } + + /** The core of the game loop. Calculate a mean FPS and call update()/draw() if game loop is not paused */ + this.loop = function() { + that.current_tick = (new Date()).getTime(); + that.tick_duration = that.current_tick - that.last_tick + that.fps = mean_value.add(1000/that.tick_duration).get() + + if(!stopped && !paused) { + if(game_object.update) { game_object.update() } + if(game_object.draw) { game_object.draw() } + that.ticks++ + } + if(options.fps == 60 && !stopped) requestAnimFrame(that.loop); + that.last_tick = that.current_tick; + } + + /** Pause the game loop. loop() will still get called but not update() / draw() */ + this.pause = function() { paused = true } + + /** unpause the game loop */ + this.unpause = function() { paused = false } + + /** Stop the game loop */ + this.stop = function() { + if(update_id) clearInterval(update_id); + stopped = true; + } +} + +/** @ignore */ +function MeanValue(size) { + this.size = size + this.values = new Array(this.size) + this.value + + this.add = function(value) { + if(this.values.length > this.size) { // is values filled? + this.values.splice(0,1) + this.value = 0 + for(var i=0; this.values[i]; i++) { + this.value += this.values[i] + } + this.value = this.value / this.size + } + this.values.push(value) + + return this + } + + this.get = function() { + return parseInt(this.value) + } + +} + +return jaws; +})(jaws || {}); + |
