forked from parente/spaceship
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.js
394 lines (366 loc) · 13.6 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
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
/**
* Startup code for the Spaceship! game.
*
* Copyright (c) 2008, 2009 Peter Parente under the terms of the BSD license.
* http://creativecommons.org/licenses/BSD/
*/
dojo.provide('spaceship.Main');
// sent by the main loop after the main menu shows
spaceship.START_MAIN_MENU_TOPIC = 'ss-startMainMenu';
dojo.declare('spaceship.Main', null, {
/**
* Shows a loading overlay. Imports all required modules.
*/
constructor: function() {
// require modules now
dojo.require('dojo.i18n');
dojo.require('dojo.hash');
dojo.require("dijit.layout.StackContainer");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout.BorderContainer");
dojo.require('spaceship.sounds.AudioManager');
dojo.require('spaceship.sounds.Jukebox');
dojo.require('spaceship.images.GraphicsManager');
dojo.require('spaceship.game.GameLevel');
dojo.require('spaceship.game.GameModel');
dojo.require('spaceship.game.GridView');
dojo.require('spaceship.game.GridAudio');
dojo.require('spaceship.menu.MenuModel');
dojo.require('spaceship.menu.MenuView');
dojo.require('spaceship.menu.MenuAudio');
dojo.require('spaceship.menu.MenuTopics');
// dojo.require('spaceship.menu.options.OptionsMenuModel');
// dojo.require('spaceship.menu.options.OptionsMenuView');
// dojo.require('spaceship.menu.options.OptionsMenuAudio');
dojo.require('spaceship.game.StatusModel')
dojo.require('spaceship.game.StatusView')
dojo.require('spaceship.game.StatusAudio');
// dojo.require('spaceship.html.HtmlModel')
// dojo.require('spaceship.html.HtmlView')
// dojo.require('spaceship.html.HtmlAudio');
dojo.require('spaceship.game.HUDView');
dojo.require('spaceship.game.HUDAudio');
dojo.require('spaceship.minigame.MiniGameManager');
dojo.require("dojo.parser");
dojo.requireLocalization('spaceship', 'labels');
// bundle of locale strings
this._labels = dojo.i18n.getLocalization('spaceship', 'labels');
// bundle of game config
this._config = null;
// bag of dojo.subscribe handles
this._subs = {};
// center stack container widget
this._stackWidget = null;
// footer content pane
this._footerWidget = null;
// border layout
this._layoutWidget = null;
// menu model
this._menuModel = null;
// game model
this._gameModel = null;
// music jukebox
this._jukebox = null;
// last active panel before a menu shows
this._lastPanel = null;
// number of ready reports
this._readyCount = 0;
// error dialog reference
this._errorDialog = null;
// register for when the page unloads
dojo.addOnUnload(dojo.hitch(this, this.uninitialize));
// register for when all modules load
var readyFunc = dojo.hitch(this, 'onLibReady');
// register for when audio is ready
var def = spaceship.sounds.AudioManager.startup();
def.addCallback(readyFunc);
// when all resources finish loading
dojo.addOnLoad(readyFunc);
// enable preferences
spaceship.preferences.PreferencesModel.startup();
// register for when images are ready
def = spaceship.images.GraphicsManager.startup();
def.addCallback(readyFunc);
},
/**
* Called when all resources are loaded. Initializes the game.
*/
onLibReady: function() {
++this._readyCount;
if(this._readyCount == 3) {
this.initialize();
}
},
/**
* Unsubscribe from all dojo.publish topics.
*/
uninitialize: function() {
for(var key in this._subs) {
dojo.unsubscribe(this._subs[key]);
}
},
/**
* Creates all of the necessary game framework objects.
* Hides the loading overlay.
*/
initialize: function() {
// parse the inline page widgets
dojo.parser.parse();
// read config name from hash value
var h = dojo.hash();
var segs = h.split('-');
this._config = spaceship.game.GameLevel[segs[0]];
if(!this._config) {
// default to easy
this._config = spaceship.game.GameLevel['easy']
}
// store the name of the minigame to use, or null/undefined/blank
// if the minigame manager should pick a random minigame
this._config.minigame = segs[1];
// get references to parsed widgets
this._stackWidget = dijit.byId('stack');
this._footerWidget = dijit.byId('footer');
this._layoutWidget = dijit.byId('layout');
// show the watermark
var wm = dojo.byId('watermark');
wm.style.display = '';
// track stack size to fit watermark graphic in region
dojo.connect(this._stackWidget, 'resize', this, 'onResizeStack');
// reflow the border layout widget and watermark
//this.onResizeStack();
this._stackWidget.resize();
// store menu args
this._mainArgs = {
itemLabels: [this._labels.NEW_GAME_ITEM]
};
this._returnArgs = {
itemLabels: [this._labels.RESUME_GAME_ITEM,
this._labels.QUIT_GAME_ITEM],
cancelable: true
};
this._quitArgs = {
itemLabels: [this._labels.NO_QUIT_ITEM,
this._labels.YES_QUIT_ITEM],
title: this._labels.QUIT_TITLE,
cancelable: true
};
// build a jukebox for music
this._jukebox = new spaceship.sounds.Jukebox();
// start listening for menu related events
this._subs['pause-game'] = dojo.subscribe(
spaceship.game.PAUSE_GAME_TOPIC, dojo.hitch(this, 'pauseGame'));
this._subs['pause-minigame'] = dojo.subscribe(
spaceship.game.PAUSE_MINIGAME_TOPIC, dojo.hitch(this, 'pauseGame'));
this._subs['end-game'] = dojo.subscribe(
spaceship.game.END_GAME_TOPIC, dojo.hitch(this, 'quitGame'));
// connect for global keys
uow.ui.connectKeys();
// show the main menu immediately
this.startMain();
},
/**
* Called when the browser resizes. Adjusts the watermark background size.
*/
onResizeStack: function() {
var size = dojo.contentBox(this._stackWidget.domNode);
// center the background graphic
var img = dojo.byId('watermark');
var is = dojo.marginBox(img);
box = {
top: (size.h - is.h) / 2 + 'px',
left: (size.w - is.w) / 2 + 'px'
};
dojo.style(img, box);
},
/**
* Called in response to CHOOSE_ITEM_TOPIC from the main menu.
*/
onChooseMain: function(index, label) {
// destroy the menu immediately
this._endMenu(false);
// pick a difficulty
this.startGame();
},
/**
* Called in response to CHOOSE_ITEM_TOPIC from the return menu.
*/
onChooseReturn: function(index, label) {
switch(label) {
case this._labels.RESUME_GAME_ITEM:
this.resumeGame();
break;
case this._labels.QUIT_GAME_ITEM:
// destroy the menu immediately
this._endMenu(false);
// make sure we want to quit the current game
this._startMenu(this._quitArgs, 'onChooseQuit', 'pauseGame');
break;
}
},
/**
* Called in response to CHOOSE_ITEM_TOPIC from the difficulty menu.
*/
onChooseDifficulty: function(index, label) {
// destroy the menu immediately
this._endMenu(false);
for(var i=0; i < spaceship.game.GameConfig.length; i++) {
var config = spaceship.game.GameConfig[i];
if(config.label == label) {
this._config = config;
break;
}
}
this.startGame();
},
/**
* Called in response to CHOOSE_ITEM_TOPIC from the confirm quit menu.
*/
onChooseQuit: function(index, label) {
// destroy the menu immediately
this._endMenu(false);
if(label == this._labels.YES_QUIT_ITEM) {
// throw away the last panel to prevent errors reactivating
this._lastPanel = null;
// destroy the game model which should notify all the views
this._gameModel.destroyRecursive();
} else {
// restart the resume menu
this._startMenu(this._returnArgs, 'onChooseReturn', 'resumeGame');
}
},
/**
* Starts a new menu.
*
* @param args Arguments to pass to the menu MVC components
* @param choose String name of method to handle item choice
* @param cancel String name of method to handle menu cancel
*/
_startMenu: function(args, choose, cancel) {
// store the last active panel
if(!this._lastPanel) {
this._lastPanel = this._stackWidget.selectedChildWidget;
}
// let the menu options drive this controller
this._subs['menu-choose'] = dojo.subscribe(spaceship.menu.CHOOSE_ITEM_TOPIC,
this, choose);
if(cancel) {
this._subs['menu-cancel'] = dojo.subscribe(
spaceship.menu.CANCEL_MENU_TOPIC, this, cancel);
}
// create the menu model and add it to the bag
this._menuModel = new spaceship.menu.MenuModel(args);
var vargs = {model: this._menuModel, interrupt: cancel == 'resumeGame'};
var mv = new spaceship.menu.MenuView(vargs);
var ma = new spaceship.menu.MenuAudio(vargs);
this._stackWidget.addChild(mv);
this._stackWidget.selectChild(mv);
},
/**
* Ends a menu by destroying the menu model.
*
* @param restore True to show previous active panel
*/
_endMenu: function(restore) {
// show the last active panel
if(restore && this._lastPanel) {
this._stackWidget.selectChild(this._lastPanel);
this._lastPanel = null;
}
if(this._menuModel) {
// destroy the menu
this._menuModel.destroyRecursive();
this._menuModel = null;
dojo.unsubscribe(this._subs['menu-choose']);
dojo.unsubscribe(this._subs['menu-cancel']);
delete this._subs['menu-choose'];
delete this._subs['menu-cancel'];
}
},
/**
* Starts the main menu.
*/
startMain: function() {
// destroy any existing menu
this._endMenu(false);
// indicate title screen started
dojo.publish(spaceship.START_MAIN_MENU_TOPIC);
this._startMenu(this._mainArgs, 'onChooseMain');
// ignore any possible last panel when starting the main menu;
// it could be leftover from an old game
this._lastPanel = null;
},
/**
* Starts a new game.
*/
startGame: function() {
// create a bag of common arguments
var args = {
labels: this._labels,
config: this._config
};
// create the game model and add it to the bag
this._gameModel = new spaceship.game.GameModel(args);
args.model = this._gameModel;
// create the HUD view and insert it into the footer
var hv = new spaceship.game.HUDView(args);
this._footerWidget.attr('content', hv);
var ha = new spaceship.game.HUDAudio(args);
// hide the logo
dojo.byId('logo').style.display = 'none';
// reflow the border layout widget
this._layoutWidget.resize();
// create the minigame manager and insert it into the stack
var mgm = new spaceship.minigame.MiniGameManager(args);
this._stackWidget.addChild(mgm);
// build the grid view-controller and insert it into the stack
var gv = new spaceship.game.GridView(args);
this._stackWidget.addChild(gv);
// create the grid audio display
var ga = new spaceship.game.GridAudio(args);
// create a status model and replace the game model in the bag
args.model = new spaceship.game.StatusModel(args);
// create the status view pane and insert it into the stack
var sv = new spaceship.game.StatusView(args);
this._stackWidget.addChild(sv);
// create the status audio display
var sa = new spaceship.game.StatusAudio(args);
// start the game loop
this._gameModel.run();
},
/**
* Pauses a game. Shows the pause menu.
*
* @param resumeTopic Topic to publish when resuming game
*/
pauseGame: function(resumeTopic) {
// destroy any existing menu
this._endMenu(false);
// store resume topic
if(resumeTopic) {
this._resumeTopic = resumeTopic;
}
this._startMenu(this._returnArgs, 'onChooseReturn', 'resumeGame');
},
/**
* Resumes a game
*/
resumeGame: function() {
// destroy any existing menu
this._endMenu(true);
dojo.publish(this._resumeTopic);
this._resumeTopic = null;
},
/**
* Ends a game by destroying the game model and returning to the main menu.
*/
quitGame: function() {
// clean up references
this._gameModel = null;
// show the logo again
dojo.byId('logo').style.display = '';
// reflow the border layout
this._layoutWidget.resize();
// show the main menu immediately
this.startMain();
}
});