-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathstate_manager.js
More file actions
187 lines (167 loc) · 5.24 KB
/
state_manager.js
File metadata and controls
187 lines (167 loc) · 5.24 KB
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// *** state_manager ***
// The game engine; manages all of the games states
// Provides update(), mouse_click(x, y), and key_pressed(k)
// The next state to go to, if applicable, is returned by state.update()
var state_manager = function (p) {
// object to return
var obj = {};
// --- private variables ---
var curr_state = loading_state(p); //The currently active state
//p.noLoop();
var displayed_states = [curr_state]; //THIS MUST ALWAYS BE SORTED BY RENDERING LEVEL
//A mapping from game states to their rendering levels
var type_to_level = {
"splash": 0,
"loading" : 0,
"game": 1,
"game_over": 2,
"pause": 2,
"credits": 2,
"help": 2,
"options" : 2
};
// --- private methods ---
//Removes a state from the displayed_states
//The state must be in displayed_states, or will throw an error
function remove_from_displayed(s) {
var index = displayed_states.indexOf(s);
if (index === -1) {
throw "error in remove_from_displayed in state_manager";
}
displayed_states.splice(index, 1); //remove the element
}
//Adds a state to displayed_states
//Ensures that displayed_states is sorted by ascending rendering level
var add_to_displayed_states = function(s) {
var render_level = type_to_level[s.get_type()];
//Insert in the array right before a render level that is higher than it, or
//at the end if none
var inserted = false;
for (var i = 0; i < displayed_states.length; i++) {
var old_render_level = type_to_level[displayed_states[i].get_type()];
if (old_render_level > render_level) {
displayed_states.splice(i, 0, s);
inserted = true;
}
}
if (inserted === false) { //add to end
displayed_states.push(s);
}
}
// --- public methods ---
//Updates the current state and renders all appropriate states
obj.update = function() {
// Update all the states, and get next_state from curr_state.update_wrapper();
var next_state = null;
var update_function = function(s) {
if (s === curr_state) {
next_state = s.update_wrapper();
}
else {
// i see no reason to update not current states
//s.update_wrapper();
}
};
for_each(displayed_states, update_function);
//If we have a new state to go to
if (next_state && next_state !== curr_state) {
//console.log("next is "+next_state.get_type());
//Figure out if next state is an overlay
var state_type = next_state.get_type();
var is_overlay = -1;
switch (state_type) {
case "splash":
is_overlay = false;
p.noLoop();
break;
case "game":
is_overlay = false;
p.loop();
break;
case "pause":
is_overlay = true;
p.noLoop();
break;
case "help":
is_overlay = true;
p.noLoop();
break;
case "game_over":
is_overlay = true;
p.noLoop();
break;
case "options":
is_overlay = true;
p.noLoop();
break;
case "loading":
is_overlay = false;
p.loop();
break;
case "high_scores":
is_overlay = true;
p.noLoop();
break;
case "credits":
is_overlay = true;
p.noLoop();
break;
}
//Error checking
if (is_overlay === -1) {
throw "error in update in state_manager";
}
//If overlay, add to displayed, otherwise reset displayed
if (is_overlay) {
// account for multiple overlays
// so we can go back to an overlay
if (member(displayed_states, next_state)) {
remove_from_displayed(curr_state);
}
else {
add_to_displayed_states(next_state);
}
}
else {
displayed_states = [next_state];
}
curr_state = next_state;
//Potentially a problem, we do this even if not returning to a state
curr_state.resume();
// updating its buttons
curr_state.update_wrapper();
}
for (var i = 0; i < displayed_states.length; i++) {
displayed_states[i].render_wrapper();
}
/*
if (curr_state.get_type() !== "game") {
p.noLoop();
}
else {
p.loop();
}
*/
};
//Passes clicks on to curr_state
obj.mouse_click = function (x, y) {
curr_state.mouse_click_wrapper(x, y);
if (curr_state.get_type() !== "game") {
obj.update();
}
};
obj.key_pressed = function(k) {
curr_state.key_pressed(k);
if (curr_state.get_type() !== "game") {
obj.update();
}
};
obj.mouse_moved = function(x,y) {
curr_state.mouse_moved_wrapper(x, y);
if (curr_state.get_type() !== "game") {
obj.update();
}
//obj.update();
}
return obj;
};