-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.js
executable file
·138 lines (100 loc) · 3.5 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// ========
// MAINLOOP
// ========
/*
The mainloop is one big object with a fairly small public interface
(e.g. init, iter, gameOver), and a bunch of private internal helper methods.
The "private" members are identified as such purely by the naming convention
of having them begin with a leading underscore. A more robust form of privacy,
with genuine name-hiding *is* possible in JavaScript (via closures), but I
haven't adopted it here.
*/
"use strict";
/* jshint browser: true, devel: true, globalstrict: true */
/*
0 1 2 3 4 5 6 7 8
12345678901234567890123456789012345678901234567890123456789012345678901234567890
*/
var main = {
// "Frame Time" is a (potentially high-precision) frame-clock for animations
_frameTime_ms : null,
_frameTimeDelta_ms : null,
};
// Perform one iteration of the mainloop
main.iter = function (frameTime) {
// Use the given frameTime to update all of our game-clocks
this._updateClocks(frameTime);
// Perform the iteration core to do all the "real" work
this._iterCore(this._frameTimeDelta_ms);
// Diagnostics, such as showing current timer values etc.
this._debugRender(g_ctx);
// Request the next iteration if needed
if (!this._isGameOver) this._requestNextIteration();
};
main._updateClocks = function (frameTime) {
// First-time initialisation
if (this._frameTime_ms === null) this._frameTime_ms = frameTime;
// Track frameTime and its delta
this._frameTimeDelta_ms = frameTime - this._frameTime_ms;
this._frameTime_ms = frameTime;
};
main._iterCore = function (dt) {
// Handle QUIT
//
// Actually, it's too easy to "quit" accidentally,
// so I'm gonna comment this out by default now.
//
//if (requestedQuit()) {
// this.gameOver();
// return;
//}
gatherInputs();
update(dt);
render(g_ctx);
};
main._isGameOver = false;
main.gameOver = function () {
this._isGameOver = true;
console.log("gameOver: quitting...");
};
// Simple voluntary quit mechanism
//
var KEY_QUIT = 'Q'.charCodeAt(0);
function requestedQuit() {
return keys[KEY_QUIT];
}
// Annoying shim for Firefox and Safari
window.requestAnimationFrame =
window.requestAnimationFrame || // Chrome
window.mozRequestAnimationFrame || // Firefox
window.webkitRequestAnimationFrame; // Safari
// This needs to be a "global" function, for the "window" APIs to callback to
function mainIterFrame(frameTime) {
main.iter(frameTime);
}
main._requestNextIteration = function () {
window.requestAnimationFrame(mainIterFrame);
};
// Mainloop-level debug-rendering
var TOGGLE_TIMER_SHOW = 'T'.charCodeAt(0);
main._doTimerShow = false;
main._debugRender = function (ctx) {
if (eatKey(TOGGLE_TIMER_SHOW)) this._doTimerShow = !this._doTimerShow;
if (!this._doTimerShow) return;
var y = 350;
ctx.fillText('FT ' + this._frameTime_ms, 50, y+10);
ctx.fillText('FD ' + this._frameTimeDelta_ms, 50, y+20);
ctx.fillText('UU ' + g_prevUpdateDu, 50, y+30);
ctx.fillText('FrameSync ON', 50, y+40);
};
main.init = function () {
// Grabbing focus is good, but it sometimes screws up jsfiddle,
// so it's a risky option during "development"
//
//window.focus(true);
// We'll be working on a black background here,
// so let's use a fillStyle which works against that...
//
g_ctx.fillStyle = "white";
this._requestNextIteration();
};