Diffstat (limited to 'noncore/games/sfcave-sdl/sfcave.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/games/sfcave-sdl/sfcave.cpp | 546 |
1 files changed, 546 insertions, 0 deletions
diff --git a/noncore/games/sfcave-sdl/sfcave.cpp b/noncore/games/sfcave-sdl/sfcave.cpp new file mode 100644 index 0000000..8d376a1 --- a/dev/null +++ b/noncore/games/sfcave-sdl/sfcave.cpp | |||
@@ -0,0 +1,546 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | |||
4 | #include <time.h> | ||
5 | #include <sys/timeb.h> | ||
6 | |||
7 | #include "SDL.h" | ||
8 | #include "SDL_gfxPrimitives.h" | ||
9 | |||
10 | #include "constants.h" | ||
11 | |||
12 | #include "sound.h" | ||
13 | #include "menu.h" | ||
14 | #include "help.h" | ||
15 | #include "game.h" | ||
16 | #include "terrain.h" | ||
17 | #include "random.h" | ||
18 | #include "sfcave.h" | ||
19 | #include "font.h" | ||
20 | #include "settings.h" | ||
21 | #include "util.h" | ||
22 | |||
23 | #include "sfcave_game.h" | ||
24 | #include "gates_game.h" | ||
25 | #include "fly_game.h" | ||
26 | |||
27 | void start( int argc, char *argv[] ) | ||
28 | { | ||
29 | FontHandler::init(); | ||
30 | SFCave app( argc, argv ); | ||
31 | FontHandler::cleanUp(); | ||
32 | } | ||
33 | |||
34 | #ifdef __cplusplus | ||
35 | extern "C" | ||
36 | #endif | ||
37 | int main(int argc, char *argv[]) | ||
38 | { | ||
39 | start( argc, argv ); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | |||
44 | SFCave :: SFCave( int argc, char *argv[] ) | ||
45 | { | ||
46 | string diff = loadSetting( "GameDifficulty", "Easy" ); | ||
47 | string game = loadSetting( "GameType", "SFCave" ); | ||
48 | musicPath = loadSetting( "MusicPath", SOUND_PATH ); | ||
49 | printf( "musicPath %s\n", musicPath.c_str() ); | ||
50 | musicType = loadSetting( "MusicType", "mod,ogg" ); | ||
51 | if ( musicPath[musicPath.size()-1] != '/' ) | ||
52 | musicPath += "/"; | ||
53 | |||
54 | // Init main SDL Library | ||
55 | initSDL( argc, argv ); | ||
56 | |||
57 | // Init SoundHandler | ||
58 | if ( !SoundHandler :: init() ) | ||
59 | printf("Unable to open audio!\n"); | ||
60 | |||
61 | currentGame = Game::createGame( this, WIDTH, HEIGHT, game, diff ); | ||
62 | if ( !currentGame ) | ||
63 | currentGame = new SFCaveGame( this, WIDTH, HEIGHT, 0 ); | ||
64 | currentGame->setSeed(-1); | ||
65 | menu = new Menu( this ); | ||
66 | |||
67 | help = new Help( this ); | ||
68 | |||
69 | maxFPS = 50; | ||
70 | showFps = false; | ||
71 | mainEventLoop(); | ||
72 | |||
73 | SoundHandler :: cleanUp(); | ||
74 | SDL_Quit(); | ||
75 | } | ||
76 | |||
77 | SFCave :: ~SFCave() | ||
78 | { | ||
79 | if ( currentGame ) | ||
80 | delete currentGame; | ||
81 | |||
82 | if ( menu ) | ||
83 | delete menu; | ||
84 | |||
85 | SDL_FreeSurface( screen ); | ||
86 | } | ||
87 | |||
88 | |||
89 | void SFCave :: drawGameScreen( ) | ||
90 | { | ||
91 | //ClearScreen(screen, "Titletext"); | ||
92 | |||
93 | } | ||
94 | |||
95 | void SFCave :: initSDL( int argc, char *argv[] ) | ||
96 | { | ||
97 | const SDL_VideoInfo *info; | ||
98 | Uint8 video_bpp; | ||
99 | Uint32 videoflags; | ||
100 | |||
101 | |||
102 | |||
103 | /* Initialize SDL */ | ||
104 | if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0 ) { | ||
105 | fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); | ||
106 | exit(1); | ||
107 | } | ||
108 | atexit(SDL_Quit); | ||
109 | |||
110 | /* Alpha blending doesn't work well at 8-bit color */ | ||
111 | video_bpp = 16; | ||
112 | |||
113 | if ( !SDL_VideoModeOK(WIDTH, HEIGHT, 16, SDL_DOUBLEBUF) ) | ||
114 | printf( "No double buffering\n" ); | ||
115 | |||
116 | videoflags = SDL_HWSURFACE | SDL_SRCALPHA;//|| SDL_DOUBLEBUF;// | SDL_SRCALPHA | SDL_RESIZABLE; | ||
117 | while ( argc > 1 ) { | ||
118 | --argc; | ||
119 | if ( strcmp(argv[argc-1], "-bpp") == 0 ) { | ||
120 | video_bpp = atoi(argv[argc]); | ||
121 | --argc; | ||
122 | } else | ||
123 | if ( strcmp(argv[argc], "-hw") == 0 ) { | ||
124 | videoflags |= SDL_HWSURFACE; | ||
125 | } else | ||
126 | if ( strcmp(argv[argc], "-warp") == 0 ) { | ||
127 | videoflags |= SDL_HWPALETTE; | ||
128 | } else | ||
129 | if ( strcmp(argv[argc], "-fullscreen") == 0 ) { | ||
130 | videoflags |= SDL_FULLSCREEN; | ||
131 | } else { | ||
132 | fprintf(stderr, | ||
133 | "Usage: %s [-bpp N] [-warp] [-hw] [-fullscreen]\n", | ||
134 | argv[0]); | ||
135 | exit(1); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | /* Set 240x320 video mode */ | ||
140 | if ( (screen=SDL_SetVideoMode(WIDTH,HEIGHT,video_bpp,videoflags)) == NULL ) { | ||
141 | fprintf(stderr, "Couldn't set %ix%i video mode: %s\n",WIDTH,HEIGHT,SDL_GetError()); | ||
142 | exit(2); | ||
143 | } | ||
144 | |||
145 | /* Use alpha blending */ | ||
146 | SDL_SetAlpha(screen, SDL_RLEACCEL, 0); | ||
147 | |||
148 | /* Set title for window */ | ||
149 | SDL_WM_SetCaption("SFCave","SFCave"); | ||
150 | } | ||
151 | |||
152 | void SFCave :: mainEventLoop() | ||
153 | { | ||
154 | SDL_Event event; | ||
155 | int done; | ||
156 | |||
157 | /* Wait for a keystroke */ | ||
158 | done = 0; | ||
159 | state = 0; | ||
160 | state = STATE_CRASHED; | ||
161 | changeState( STATE_MENU ); | ||
162 | |||
163 | int FPS = 0; | ||
164 | bool limitFPS = true; | ||
165 | actualFPS = 0; | ||
166 | long time1 = 0; | ||
167 | long start; | ||
168 | long end; | ||
169 | //long nrTimes = 0; | ||
170 | struct timeb tp; | ||
171 | while ( !done ) | ||
172 | { | ||
173 | // calc FPS | ||
174 | ftime( &tp ); | ||
175 | start =(tp.time%10000)*10000 + tp.millitm; | ||
176 | // printf( "start = %ld, time1 - %d, st-tm - %d, tp.time - %ld\n", start, time1, start-time1, (tp.time%1000)*1000 ); | ||
177 | if ( start - time1 >= 1000 ) | ||
178 | { | ||
179 | actualFPS = FPS; | ||
180 | // printf( "%d FPS = %d\n", nrTimes++, actualFPS ); | ||
181 | FPS = 0; | ||
182 | time1 = start; | ||
183 | } | ||
184 | else | ||
185 | FPS ++; | ||
186 | |||
187 | SDL_FillRect( screen, 0, 0 ); | ||
188 | switch( state ) | ||
189 | { | ||
190 | case STATE_MENU: | ||
191 | SDL_FillRect( screen, 0, 0 ); | ||
192 | menu->draw( screen ); | ||
193 | break; | ||
194 | case STATE_HELP: | ||
195 | SDL_FillRect( screen, 0, 0 ); | ||
196 | help->update(); | ||
197 | help->draw( screen ); | ||
198 | break; | ||
199 | case STATE_NEWGAME: | ||
200 | printf( "STATE_NEWGAME\n" ); | ||
201 | currentGame->setReplay( false ); | ||
202 | currentGame->init(); | ||
203 | changeState( STATE_PLAYING ); | ||
204 | break; | ||
205 | |||
206 | case STATE_REPLAY: | ||
207 | printf( "STATE_NEWGAME\n" ); | ||
208 | currentGame->setReplay( true ); | ||
209 | currentGame->init(); | ||
210 | changeState( STATE_PLAYING ); | ||
211 | break; | ||
212 | |||
213 | case STATE_PLAYING: | ||
214 | case STATE_CRASHING: | ||
215 | currentGame->update( state ); | ||
216 | currentGame->draw( screen ); | ||
217 | break; | ||
218 | |||
219 | case STATE_CRASHED: | ||
220 | currentGame->update( state ); | ||
221 | currentGame->draw( screen ); | ||
222 | |||
223 | // Display Game Over message | ||
224 | break; | ||
225 | |||
226 | case STATE_QUIT: | ||
227 | done = 1; | ||
228 | break; | ||
229 | } | ||
230 | |||
231 | /* Show */ | ||
232 | // if ( state != STATE_CRASHED ) | ||
233 | SDL_Flip( screen ); | ||
234 | // SDL_UpdateRect(screen, 0, 0, 0, 0); | ||
235 | |||
236 | if ( limitFPS ) | ||
237 | { | ||
238 | /* Slow down polling - limit to x FPS*/ | ||
239 | ftime( &tp ); | ||
240 | end = abs((tp.time%10000)*10000 + tp.millitm); | ||
241 | if ( end-start < (1000/maxFPS) ) | ||
242 | { | ||
243 | // printf( "end - %ld, timetaken for frame = %ld, sleeping for %ld %d\n", end, end-start, (1000/maxFPS)-(end-start), actualFPS ); | ||
244 | if ( (1000/maxFPS)-(end-start) > 500 ) | ||
245 | { | ||
246 | // Should never happen but in case it does sleep for 5 seconds | ||
247 | printf( "WARNING WILL ROBINSON! delay = %ld - start %ld, end %ld\n", (1000/maxFPS)-(end-start), start, end ); | ||
248 | SDL_Delay( 5 ); | ||
249 | } | ||
250 | else | ||
251 | SDL_Delay((1000/maxFPS)-(end-start) ); | ||
252 | } | ||
253 | } | ||
254 | else | ||
255 | SDL_Delay( 5 ); | ||
256 | |||
257 | /* Check for events */ | ||
258 | while ( SDL_PollEvent(&event) ) | ||
259 | { | ||
260 | switch (event.type) | ||
261 | { | ||
262 | case SDL_KEYDOWN: | ||
263 | case SDL_KEYUP: | ||
264 | // Escape keypress quits the app | ||
265 | if ( event.key.keysym.sym != SDLK_ESCAPE ) | ||
266 | { | ||
267 | // printf( "Key Pressed was %d %s\n", event.key.keysym.sym, SDL_GetKeyName( event.key.keysym.sym ) ); | ||
268 | |||
269 | if ( state == STATE_MENU ) | ||
270 | { | ||
271 | int rc = menu->handleKeys( event.key ); | ||
272 | if ( rc != -1 ) | ||
273 | handleMenuSelect( rc ); | ||
274 | } | ||
275 | else if ( state == STATE_HELP ) | ||
276 | { | ||
277 | help->handleKeys( event.key ); | ||
278 | } | ||
279 | else if ( state == STATE_CRASHED ) | ||
280 | { | ||
281 | if ( event.type == SDL_KEYDOWN ) | ||
282 | { | ||
283 | if ( event.key.keysym.sym == SDLK_UP || | ||
284 | event.key.keysym.sym == SDLK_DOWN || | ||
285 | event.key.keysym.sym == SDLK_SPACE ) | ||
286 | changeState( STATE_NEWGAME ); | ||
287 | else if ( event.key.keysym.sym == SDLK_RETURN || event.key.keysym.sym == 0 ) | ||
288 | { | ||
289 | changeState( STATE_MENU ); | ||
290 | menu->resetToTopMenu(); | ||
291 | } | ||
292 | else if ( event.key.keysym.sym == SDLK_r ) | ||
293 | { | ||
294 | changeState( STATE_REPLAY ); | ||
295 | } | ||
296 | else if ( event.key.keysym.sym == SDLK_s ) | ||
297 | { | ||
298 | SoundHandler :: playSound( SND_EXPLOSION ); | ||
299 | } | ||
300 | } | ||
301 | } | ||
302 | else | ||
303 | { | ||
304 | switch ( event.key.keysym.sym ) | ||
305 | { | ||
306 | case SDLK_f: | ||
307 | printf( "showFPS - %d\n", showFps ); | ||
308 | if ( event.type == SDL_KEYDOWN ) | ||
309 | showFps = !showFps; | ||
310 | break; | ||
311 | case SDLK_l: | ||
312 | if ( event.type == SDL_KEYDOWN ) | ||
313 | limitFPS = !limitFPS; | ||
314 | break; | ||
315 | |||
316 | case SDLK_p: | ||
317 | if ( event.type == SDL_KEYDOWN ) | ||
318 | { | ||
319 | maxFPS ++; | ||
320 | printf( "maxFPS - %d\n", maxFPS ); | ||
321 | } | ||
322 | break; | ||
323 | |||
324 | case SDLK_o: | ||
325 | if ( event.type == SDL_KEYDOWN ) | ||
326 | { | ||
327 | maxFPS --; | ||
328 | printf( "maxFPS - %d\n", maxFPS ); | ||
329 | } | ||
330 | break; | ||
331 | |||
332 | case SDLK_n: | ||
333 | currentGame->getTerrain()->offset++; | ||
334 | break; | ||
335 | |||
336 | default: | ||
337 | currentGame->handleKeys( event.key ); | ||
338 | break; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | break; | ||
343 | } | ||
344 | |||
345 | |||
346 | case SDL_QUIT: | ||
347 | done = 1; | ||
348 | break; | ||
349 | default: | ||
350 | break; | ||
351 | } | ||
352 | } | ||
353 | } | ||
354 | } | ||
355 | |||
356 | void SFCave :: changeState( int s ) | ||
357 | { | ||
358 | if ( state != s ) | ||
359 | currentGame->stateChanged( state, s ); | ||
360 | |||
361 | if ( state == STATE_MENU && s == STATE_HELP ) | ||
362 | help->init(); | ||
363 | if ( state == STATE_CRASHED && s == STATE_MENU ) | ||
364 | { | ||
365 | SoundHandler :: stopMusic( true ); | ||
366 | |||
367 | string musicFile = chooseRandomFile( musicPath, musicType ); | ||
368 | printf("playing music %s\n", musicFile.c_str() ); | ||
369 | SoundHandler :: setMusicVolume( 128 ); | ||
370 | SoundHandler :: playMusic( musicFile ); | ||
371 | } | ||
372 | else if ( state == STATE_MENU && (s == STATE_NEWGAME || s == STATE_REPLAY) ) | ||
373 | { | ||
374 | SoundHandler :: stopMusic( ); | ||
375 | |||
376 | // Start the in game music | ||
377 | string musicFile = SOUND_PATH "ingame.mod"; | ||
378 | SoundHandler :: playMusic( musicFile ); | ||
379 | SoundHandler :: setMusicVolume( 25 ); | ||
380 | } | ||
381 | |||
382 | state = s; | ||
383 | } | ||
384 | |||
385 | |||
386 | void SFCave :: handleMenuSelect( int menuId ) | ||
387 | { | ||
388 | switch( menuId ) | ||
389 | { | ||
390 | case MENU_STARTGAME: | ||
391 | changeState( STATE_NEWGAME ); | ||
392 | break; | ||
393 | |||
394 | case MENU_HELP: | ||
395 | changeState( STATE_HELP ); | ||
396 | break; | ||
397 | |||
398 | case MENU_QUIT: | ||
399 | changeState( STATE_QUIT ); | ||
400 | break; | ||
401 | |||
402 | case MENU_PLAY_REPLAY: | ||
403 | if ( currentGame->isReplayAvailable() ) | ||
404 | changeState( STATE_REPLAY ); | ||
405 | else | ||
406 | setMenuStatusText( "No replay available yet" ); | ||
407 | break; | ||
408 | |||
409 | case MENU_LOAD_REPLAY: | ||
410 | { | ||
411 | #ifdef QWS | ||
412 | QString replayFile = getenv( "HOME" ); | ||
413 | #else | ||
414 | QString replayFile = "."; | ||
415 | #endif | ||
416 | replayFile += string( "/" ) + currentGame->getGameName() + ".replay"; | ||
417 | |||
418 | currentGame->loadReplay( replayFile ); | ||
419 | |||
420 | break; | ||
421 | } | ||
422 | |||
423 | case MENU_SAVE_REPLAY: | ||
424 | { | ||
425 | |||
426 | if ( currentGame->isReplayAvailable() ) | ||
427 | { | ||
428 | #ifdef QWS | ||
429 | QString replayFile = getenv( "HOME" ); | ||
430 | #else | ||
431 | QString replayFile = "."; | ||
432 | #endif | ||
433 | replayFile += string( "/" ) + currentGame->getGameName() + ".replay"; | ||
434 | |||
435 | currentGame->saveReplay( replayFile ); | ||
436 | } | ||
437 | else | ||
438 | setMenuStatusText( "No replay available yet" ); | ||
439 | |||
440 | break; | ||
441 | } | ||
442 | case MENU_CLEAR_SCORES: | ||
443 | break; | ||
444 | |||
445 | case MENU_GAME_SFCAVE: | ||
446 | if ( currentGame->getGameName() != "SFCave" ) | ||
447 | { | ||
448 | int diff = currentGame->getDifficulty(); | ||
449 | delete currentGame; | ||
450 | currentGame = new SFCaveGame( this, WIDTH, HEIGHT, 0 ); | ||
451 | currentGame->setDifficulty( diff ); | ||
452 | |||
453 | saveSetting( "GameType", "SFCave" ); | ||
454 | } | ||
455 | break; | ||
456 | |||
457 | case MENU_GAME_GATES: | ||
458 | if ( currentGame->getGameName() != "Gates" ) | ||
459 | { | ||
460 | int diff = currentGame->getDifficulty(); | ||
461 | delete currentGame; | ||
462 | currentGame = new GatesGame( this, WIDTH, HEIGHT, 0 ); | ||
463 | currentGame->setDifficulty( diff ); | ||
464 | |||
465 | saveSetting( "GameType", "Gates" ); | ||
466 | } | ||
467 | break; | ||
468 | break; | ||
469 | |||
470 | case MENU_GAME_FLY: | ||
471 | if ( currentGame->getGameName() != "Fly" ) | ||
472 | { | ||
473 | int diff = currentGame->getDifficulty(); | ||
474 | delete currentGame; | ||
475 | currentGame = new FlyGame( this, WIDTH, HEIGHT, 0 ); | ||
476 | currentGame->setDifficulty( diff ); | ||
477 | |||
478 | saveSetting( "GameType", "Fly" ); | ||
479 | } | ||
480 | break; | ||
481 | |||
482 | case MENU_DIFFICULTY_EASY: | ||
483 | currentGame->setDifficulty( MENU_DIFFICULTY_EASY ); | ||
484 | saveSetting( "GameDifficulty", "Easy" ); | ||
485 | break; | ||
486 | |||
487 | case MENU_DIFFICULTY_NORMAL: | ||
488 | currentGame->setDifficulty( MENU_DIFFICULTY_NORMAL ); | ||
489 | saveSetting( "GameDifficulty", "Medium" ); | ||
490 | break; | ||
491 | |||
492 | case MENU_DIFFICULTY_HARD: | ||
493 | currentGame->setDifficulty( MENU_DIFFICULTY_HARD ); | ||
494 | saveSetting( "GameDifficulty", "Hard" ); | ||
495 | break; | ||
496 | |||
497 | case MENU_SOUND_ON: | ||
498 | SoundHandler :: setSoundsOn( true ); | ||
499 | break; | ||
500 | |||
501 | case MENU_SOUND_OFF: | ||
502 | SoundHandler :: setSoundsOn( false ); | ||
503 | break; | ||
504 | |||
505 | case MENU_MUSIC_ON: | ||
506 | SoundHandler :: setMusicOn( true ); | ||
507 | break; | ||
508 | |||
509 | case MENU_MUSIC_OFF: | ||
510 | SoundHandler :: setMusicOn( false ); | ||
511 | break; | ||
512 | |||
513 | default: | ||
514 | break; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | void SFCave :: setMenuStatusText( string statusText ) | ||
519 | { | ||
520 | menu->setStatusText( statusText ); | ||
521 | } | ||
522 | |||
523 | |||
524 | void SFCave :: saveSetting( string key, string val ) | ||
525 | { | ||
526 | Settings cfg( "sfcave-sdl" ); | ||
527 | cfg.writeSetting( key, val ); | ||
528 | } | ||
529 | |||
530 | void SFCave :: saveSetting( string key, int val ) | ||
531 | { | ||
532 | Settings cfg( "sfcave-sdl" ); | ||
533 | cfg.writeSetting( key, val ); | ||
534 | } | ||
535 | |||
536 | string SFCave :: loadSetting( string key, string defaultVal ) | ||
537 | { | ||
538 | string val; | ||
539 | Settings cfg( "sfcave-sdl" ); | ||
540 | cfg.readSetting( key, val ); | ||
541 | |||
542 | if ( val == "" ) | ||
543 | val = defaultVal; | ||
544 | |||
545 | return val; | ||
546 | } | ||