whole lot of refactoring of main.js into more coherent pieces

This commit is contained in:
Richard Harrington 2013-08-19 20:05:39 -04:00
parent 42a4d40105
commit 284e2b55a9

View File

@ -1,10 +1,9 @@
;(function() {
var debugAnimationCounter = 0;
var debugSimulationCounter = 0;
var BUFFER_LENGTH = 500;
var FPS = 60;
var ROBOT_COLORS = ["#6aea2a", "#380bfa", "#fa2d0b", "#0bfaf7", "#faf20b"];
// TODO: This game info should probably come from the server
// in a preliminary ajax call.
var GAME_INFO = {
@ -14,7 +13,44 @@
gameSecondsPerTick: 0.03
}
var canvas = (function(el) {
function Worlds(bufferLength, constructorCallback) {
// This constructor function mostly mixes in the behavior
// of Queue, but it adds functionality to Queue's
// dequeue method, to fetch new items from the server
// when the queue is running low.
var queue = new Queue();
var isFetching = false;
function fetch(callback) {
$.getJSON('worlds/' + bufferLength, function(data) {
queue.enqueueArray(data);
if (callback) callback();
});
}
function dequeue() {
var result = queue.dequeue();
if (!isFetching && queue.getLength() < bufferLength) {
isFetching = true;
fetch(function() {
isFetching = false;
});
}
return result;
}
fetch(constructorCallback);
return {
dequeue: dequeue,
enqueueArray: queue.enqueueArray.bind(queue),
isEmpty: queue.isEmpty.bind(queue),
getLength: queue.getLength.bind(queue),
peek: queue.peek.bind(queue)
}
}
var Canvas = function(el) {
var width = parseInt(el.width);
var height = parseInt(el.height);
var roomForRobots = GAME_INFO.robotRadius * 2;
@ -37,7 +73,6 @@
var ctx = el.getContext('2d');
var drawRobot = function(robot, idx) {
console.log("ji");
ctx.fillStyle = ROBOT_COLORS[idx];
ctx.beginPath();
ctx.arc(
@ -55,13 +90,25 @@
world.robots.forEach(drawRobot);
}
return {draw: draw};
})($('#canvas')[0]);
return {
draw: draw
};
}
var tickQueue = new Queue();
var fastForward = 5;
function loop(worlds, interval, callback) {
(function continueLoop(tick) {
if (worlds.isEmpty()) {
return;
}
callback();
var nextTick = tick + interval;
setTimeout(function() {
continueLoop(nextTick);
}, nextTick - Date.now());
})(Date.now());
}
// fastForward can't be more than 5 if we want tickDuration to be greater
// NOTE: fastForward can't be greater than 5 if we want tickDuration to be greater
// than 6 milliseconds, which is close to the official 4-millisecond limit
// for setTimeout. TODO: set this as a limit in the user interface,
// and also look into how we can speed up by dropping ticks, while
@ -69,78 +116,29 @@
// to happen. Perhaps if we make sure to animate collisions over
// several ticks, it will work.
var fastForward = 5;
var tickDuration = parseInt (GAME_INFO.gameSecondsPerTick / fastForward * 1000);
var frameDuration = parseInt (1000 / FPS);
var fps = 60;
var frameDuration = parseInt (1000 / fps);
var debugAnimationCounter = 0;
var debugSimulationCounter = 0;
var debugSecondsCounter = 0;
var animationLoopId;
var debugTimeLoopInterval;
var worlds = (function() {
var isFetching = false;
return {
fetch: function() {
if (isFetching) {
return;
}
isFetching = true;
fetchWorlds(function() {
isFetching = false;
});
}
};
})();
function simulationLoop(tick) {
debugSimulationCounter++;
if (tickQueue.isEmpty()) {
clearTimeout(animationLoopId);
clearInterval(debugTimeLoopInterval);
}
if (tickQueue.isEmpty()) {
return;
}
if (tickQueue.getLength() < 500) {
worlds.fetch();
}
tickQueue.dequeue();
var nextTick = tick + tickDuration;
setTimeout(function() {
simulationLoop(nextTick);
}, nextTick - Date.now());
}
function animationLoop(frame) {
debugAnimationCounter++;
if (tickQueue.isEmpty()) {
return;
}
canvas.draw(tickQueue.peek());
var nextFrame = frame + frameDuration;
animationLoopId = setTimeout(function() {
animationLoop(nextFrame);
}, nextFrame - Date.now());
}
function debugTimeLoop() {
var start = Date.now();
debugTimeLoopInterval = setInterval(function() {
console.log(Math.floor((Date.now() - start) / 1000) + " " + debugAnimationCounter + " " + debugSimulationCounter);
}, 1000);
}
function fetchWorlds(callback) {
$.getJSON('worlds/500', function(worlds) {
tickQueue.enqueueArray(worlds);
if (callback) callback();
var canvas = new Canvas($('#canvas')[0]);
var worlds = new Worlds(BUFFER_LENGTH, function() {
loop(worlds, tickDuration, function() {
debugSimulationCounter++;
worlds.dequeue();
});
loop(worlds, frameDuration, function() {
debugAnimationCounter++;
canvas.draw(worlds.peek());
});
loop(worlds, 1000, function() {
debugSecondsCounter++;
console.log(Math.floor((Date.now() - start) / 1000) +
" " + debugAnimationCounter +
" " + debugSimulationCounter);
});
}
fetchWorlds(function() {
var now = Date.now();
simulationLoop(now);
animationLoop(now);
debugTimeLoop();
});
})();