2 Copyright (C) 2003 Parallel Realities
3 Copyright (C) 2011, 2012, 2013 Guus Sliepen
4 Copyright (C) 2012, 2015, 2016 onpon4 <onpon4@riseup.net>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 3
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "Starfighter.h"
22 static int showGameMenu(int continueSaveSlot)
24 screen_blitText(TS_START_NEW_GAME);
25 screen_blitText(TS_LOAD_GAME);
26 if (continueSaveSlot != -1)
28 screen_blitText(TS_CONTINUE_CURRENT_GAME);
30 screen_blitText(TS_OPTIONS);
33 gfx_textSprites[TS_QUIT].y = screen->h / 3 + 150;
34 screen_blitText(TS_CHEAT_OPTIONS);
38 gfx_textSprites[TS_QUIT].y = screen->h / 3 + 130;
40 screen_blitText(TS_QUIT);
48 static int showLoadMenu()
52 for (int i = TS_SAVESLOT_0 ; i <= TS_SAVESLOT_5 ; i++)
55 if (gfx_textSprites[i].image != NULL)
58 gfx_textSprites[TS_BACK_TO_MAIN_MENU].y = gfx_textSprites[i].y + 40;
61 screen_blitText(TS_BACK_TO_MAIN_MENU);
66 static void createDifficultyMenu()
68 gfx_createTextObject(TS_START_GAME, "»Ï¤á¤ë",
69 -1, screen->h / 3 + 50, FONT_WHITE);
71 if (game.difficulty == DIFFICULTY_EASY)
72 gfx_createTextObject(TS_DIFFICULTY, "Æñ°×ÅÙ - ´Êñ",
73 -1, screen->h / 3 + 70, FONT_WHITE);
74 else if (game.difficulty == DIFFICULTY_HARD)
75 gfx_createTextObject(TS_DIFFICULTY, "Æñ°×ÅÙ - Æñ¤·¤¤",
76 -1, screen->h / 3 + 70, FONT_WHITE);
77 else if (game.difficulty == DIFFICULTY_NIGHTMARE)
78 gfx_createTextObject(TS_DIFFICULTY, "Æñ°×ÅÙ - °Ì´!",
79 -1, screen->h / 3 + 70, FONT_WHITE);
80 else if (game.difficulty == DIFFICULTY_ORIGINAL)
81 gfx_createTextObject(TS_DIFFICULTY, "Æñ°×ÅÙ - µìÈÇ",
82 -1, screen->h / 3 + 70, FONT_WHITE);
84 gfx_createTextObject(TS_DIFFICULTY, "Æñ°×ÅÙ - ÉáÄÌ",
85 -1, screen->h / 3 + 70, FONT_WHITE);
88 static int showDifficultyMenu()
90 gfx_textSprites[TS_BACK_TO_MAIN_MENU].y = screen->h / 3 + 110;
92 screen_blitText(TS_START_GAME);
93 screen_blitText(TS_DIFFICULTY);
94 screen_blitText(TS_BACK_TO_MAIN_MENU);
99 static void createOptionsMenu()
102 gfx_createTextObject(TS_SOUND, "¸ú²Ì²» - ON",
103 -1, screen->h / 3 + 50, FONT_WHITE);
105 gfx_createTextObject(TS_SOUND, "¸ú²Ì²» - OFF",
106 -1, screen->h / 3 + 50, FONT_WHITE);
109 gfx_createTextObject(TS_MUSIC, "²»³Ú - ON",
110 -1, screen->h / 3 + 70, FONT_WHITE);
112 gfx_createTextObject(TS_MUSIC, "²»³Ú - OFF",
113 -1, screen->h / 3 + 70, FONT_WHITE);
115 if (engine.fullScreen)
116 gfx_createTextObject(TS_FULLSCREEN, "¥Õ¥ë¥¹¥¯¥ê¡¼¥ó - ON",
117 -1, screen->h / 3 + 90, FONT_WHITE);
119 gfx_createTextObject(TS_FULLSCREEN, "¥Õ¥ë¥¹¥¯¥ê¡¼¥ó - OFF",
120 -1, screen->h / 3 + 90, FONT_WHITE);
122 if (engine.autoPause)
123 gfx_createTextObject(TS_AUTOPAUSE, "¥ª¡¼¥È¥Ý¡¼¥º - ON",
124 -1, screen->h / 3 + 110, FONT_WHITE);
126 gfx_createTextObject(TS_AUTOPAUSE, "¥ª¡¼¥È¥Ý¡¼¥º - OFF",
127 -1, screen->h / 3 + 110, FONT_WHITE);
130 static int showOptionsMenu()
132 gfx_textSprites[TS_BACK_TO_MAIN_MENU].y = screen->h / 3 + 150;
134 screen_blitText(TS_SOUND);
135 screen_blitText(TS_MUSIC);
136 screen_blitText(TS_FULLSCREEN);
137 screen_blitText(TS_AUTOPAUSE);
138 screen_blitText(TS_BACK_TO_MAIN_MENU);
143 static void createCheatMenu()
145 if (engine.cheatShield)
146 gfx_createTextObject(TS_UNLIMITED_SHIELD, "̵À©¸Â¤Î¥·¡¼¥ë¥É - ON",
147 -1, screen->h / 3 + 50, FONT_WHITE);
149 gfx_createTextObject(TS_UNLIMITED_SHIELD, "̵À©¸Â¤Î¥·¡¼¥ë¥É - OFF",
150 -1, screen->h / 3 + 50, FONT_WHITE);
152 if (engine.cheatAmmo)
153 gfx_createTextObject(TS_UNLIMITED_AMMO, "̵À©¸Â¤Î¥×¥é¥º¥Þ - ON",
154 -1, screen->h / 3 + 70, FONT_WHITE);
156 gfx_createTextObject(TS_UNLIMITED_AMMO, "̵À©¸Â¤Î¥×¥é¥º¥Þ - OFF",
157 -1, screen->h / 3 + 70, FONT_WHITE);
159 if (engine.cheatCash)
160 gfx_createTextObject(TS_UNLIMITED_CASH, "̵À©¸Â¤Î¥¥ã¥Ã¥·¥å - ON",
161 -1, screen->h / 3 + 90, FONT_WHITE);
163 gfx_createTextObject(TS_UNLIMITED_CASH, "̵À©¸Â¤Î¥¥ã¥Ã¥·¥å - OFF",
164 -1, screen->h / 3 + 90, FONT_WHITE);
166 if (engine.cheatTime)
167 gfx_createTextObject(TS_UNLIMITED_TIME, "̵À©¸Â¤Î»þ´Ö - ON",
168 -1, screen->h / 3 + 110, FONT_WHITE);
170 gfx_createTextObject(TS_UNLIMITED_TIME, "̵À©¸Â¤Î»þ´Ö - OFF",
171 -1, screen->h / 3 + 110, FONT_WHITE);
174 static int showCheatMenu()
176 gfx_textSprites[TS_BACK_TO_MAIN_MENU].y = screen->h / 3 + 150;
178 screen_blitText(TS_UNLIMITED_SHIELD);
179 screen_blitText(TS_UNLIMITED_AMMO);
180 screen_blitText(TS_UNLIMITED_CASH);
181 screen_blitText(TS_UNLIMITED_TIME);
182 screen_blitText(TS_BACK_TO_MAIN_MENU);
188 This is the main title screen, with the stars whirling past and the
189 "Parallel Realities, Present..." text. Nothing too special.
193 int continueSaveSlot;
205 char buildVersion[25];
207 int selectedOption = 1;
209 int listLength = 5; // menu list length
210 int menuType = MENU_MAIN;
214 engine.gameSection = SECTION_TITLE;
216 screen_flushBuffer();
220 // required to stop the title screen crashing
222 game.area = MISN_START;
230 continueSaveSlot = initSaveSlots();
232 loadBackground("gfx/spirit.jpg");
234 SDL_Surface *prlogo, *sflogo;
235 prlogo = gfx_loadImage("gfx/prlogo.png");
236 sflogo = gfx_loadImage("gfx/sflogo.png");
238 prx = ((screen->w - prlogo->w) / 2);
239 pry = ((screen->h - prlogo->h) / 2);
241 sfx = ((screen->w - sflogo->w) / 2);
242 sfy = ((screen->h - sflogo->h) / 3);
244 gfx_createTextObject(TS_PRESENTS, "PRESENTS",
245 -1, screen->h / 2, FONT_WHITE);
246 gfx_createTextObject(TS_AN_SDL_GAME, "AN SDL GAME",
247 -1, screen->h / 2, FONT_WHITE);
248 gfx_createTextObject(TS_START_NEW_GAME, "ºÇ½é¤«¤é",
249 -1, screen->h / 3 + 50, FONT_WHITE);
250 gfx_createTextObject(TS_LOAD_GAME, "¥í¡¼¥É",
251 -1, screen->h / 3 + 70, FONT_WHITE);
252 gfx_createTextObject(TS_CONTINUE_CURRENT_GAME, "³¤",
253 -1, screen->h / 3 + 90, FONT_WHITE);
254 gfx_createTextObject(TS_OPTIONS, "¥ª¥×¥·¥ç¥ó",
255 -1, screen->h / 3 + 110, FONT_WHITE);
256 gfx_createTextObject(TS_CHEAT_OPTIONS, "¥Á¡¼¥È¥ª¥×¥·¥ç¥ó",
257 -1, screen->h / 3 + 130, FONT_WHITE);
258 gfx_createTextObject(TS_QUIT, "½ªÎ»",
259 -1, screen->h / 3 + 130, FONT_WHITE);
262 createDifficultyMenu();
263 gfx_createTextObject(TS_BACK_TO_MAIN_MENU, "¥á¥¤¥ó¥á¥Ë¥å¡¼¤ËÌá¤ë", -1, 0, FONT_WHITE);
267 // Set the star motion
273 then = SDL_GetTicks();
275 for (int i = 0 ; i < 15 ; i++)
277 aliens[i] = alien_defs[rand() % 3];
278 if ((rand() % 5) == 0)
279 aliens[i] = alien_defs[CD_TRANSPORTSHIP];
280 if ((rand() % 5) == 0)
281 aliens[i] = alien_defs[CD_MINER];
282 aliens[i].x = rand() % screen->w;
283 aliens[i].y = rand() % (screen->h - 40);
284 aliens[i].dx = 1 + rand() % 3;
288 sprintf(buildVersion, "Version %s", VERSION );
292 optionRec.x = screen->w / 2 - 110;
293 optionRec.y = screen->h / 3 + 45;
297 if (continueSaveSlot != -1)
303 screen_drawBackground();
307 engine.keyState[KEY_FIRE] = engine.keyState[KEY_ALTFIRE] = 0;
309 audio_playMusic("music/walking_among_androids.ogg", 1);
316 now = SDL_GetTicks();
321 for (int i = 0 ; i < 15 ; i++)
323 explosion_addEngine(&aliens[i]);
324 aliens[i].x += aliens[i].dx;
325 screen_blit(aliens[i].image[0], (int)aliens[i].x, (int)aliens[i].y);
326 if (aliens[i].x > screen->w + 30)
329 aliens[i].y = rand() % (screen->h - 20);
330 aliens[i].dx = 1 + rand() % 3;
334 if ((now - then > 2000) && (now - then < 8000) && (!skip))
336 screen_blit(prlogo, prx, pry);
338 else if ((now - then > 9000) && (now - then < 15000) && (!skip))
340 screen_blitText(TS_PRESENTS);
342 else if ((now - then > 16000) && (now - then < 21000) && (!skip))
344 screen_blitText(TS_AN_SDL_GAME);
346 else if ((now - then > 25500) || (skip))
348 screen_blit(sflogo, sfx, sfy);
350 if ((now - then >= 27500) || (skip))
352 screen_addBuffer(0, 0, screen->w, screen->h);
354 screen_drawRect(optionRec.x, optionRec.y, optionRec.w, optionRec.h, redGlow, 0x00, 0x00);
359 listLength = showGameMenu(continueSaveSlot);
361 case MENU_DIFFICULTY:
362 listLength = showDifficultyMenu();
365 listLength = showLoadMenu();
368 listLength = showOptionsMenu();
371 listLength = showCheatMenu();
376 if (redGlow <= 0) {redDir = 2; redGlow = 0;}
377 if (redGlow >= 255) {redDir = -2; redGlow = 255;}
379 if (engine.keyState[KEY_UP])
381 engine.keyState[KEY_UP] = 0;
382 WRAP_ADD(selectedOption, -1, 1, listLength + 1);
383 if (menuType == MENU_MAIN)
384 if (selectedOption == 3)
385 if (continueSaveSlot == -1)
388 if (engine.keyState[KEY_DOWN])
390 engine.keyState[KEY_DOWN] = 0;
391 WRAP_ADD(selectedOption, 1, 0, listLength);
392 if (menuType == MENU_MAIN)
393 if (selectedOption == 3)
394 if (continueSaveSlot == -1)
398 optionRec.y = screen->h / 3 + 26 + (20 * selectedOption);
399 if (menuType > MENU_MAIN)
400 if (selectedOption == listLength)
405 gfx_renderString("Copyright Parallel Realities 2003",
406 5, screen->h - 60, FONT_WHITE, 0, gfx_background);
407 gfx_renderString("Copyright Guus Sliepen, Astrid S. de Wijn and others 2012",
408 5, screen->h - 40, FONT_WHITE, 0, gfx_background);
409 gfx_renderString("Copyright 2015, 2016 onpon4",
410 5, screen->h - 20, FONT_WHITE, 0, gfx_background);
411 gfx_renderString(buildVersion, screen->w - 6 - strlen(buildVersion) * 9,
412 screen->h - 20, FONT_WHITE, 0, gfx_background);
413 screen_addBuffer(0, 0, screen->w, screen->h);
421 // if someone has invoked the credits cheat
422 if (engine.cheatCredits)
425 engine.cheatCredits = false;
428 if ((engine.keyState[KEY_FIRE] || engine.keyState[KEY_ALTFIRE]))
430 if ((now - then <= 27500) && (!skip))
432 gfx_renderString("Copyright Parallel Realities 2003",
433 5, screen->h - 60, FONT_WHITE, 0, gfx_background);
434 gfx_renderString("Copyright Guus Sliepen, Astrid S. de Wijn and others 2012",
435 5, screen->h - 40, FONT_WHITE, 0, gfx_background);
436 gfx_renderString("Copyright 2015, 2016 onpon4",
437 5, screen->h - 20, FONT_WHITE, 0, gfx_background);
438 gfx_renderString(buildVersion, screen->w - 6 - strlen(buildVersion) * 9,
439 screen->h - 20, FONT_WHITE, 0, gfx_background);
440 screen_addBuffer(0, 560, 800, 40);
448 if (selectedOption == 1)
450 menuType = MENU_DIFFICULTY;
453 else if (selectedOption == 2)
455 menuType = MENU_LOAD;
458 else if (selectedOption == 3)
460 else if (selectedOption == 4)
462 menuType = MENU_OPTIONS;
465 else if (selectedOption == 5)
469 menuType = MENU_CHEAT;
475 else if (selectedOption == 6)
479 case MENU_DIFFICULTY:
480 if (selectedOption == 1)
482 else if (selectedOption == 2)
485 game.difficulty %= DIFFICULTY_MAX;
487 else if (selectedOption == listLength)
489 menuType = MENU_MAIN;
492 createDifficultyMenu();
496 if (selectedOption != listLength)
499 continueSaveSlot = selectedOption - 1;
504 menuType = MENU_MAIN;
510 if ((selectedOption == 1) && (engine.useAudio))
511 engine.useSound = !engine.useSound;
512 else if ((selectedOption == 2) && (engine.useAudio))
514 engine.useMusic = !engine.useMusic;
519 "music/walking_among_androids.ogg", 1);
526 else if (selectedOption == 3)
528 engine.fullScreen = !engine.fullScreen;
529 SDL_SetWindowFullscreen(window,
531 SDL_WINDOW_FULLSCREEN_DESKTOP : 0));
533 else if (selectedOption == 4)
535 engine.autoPause = !engine.autoPause;
537 else if (selectedOption == listLength)
539 menuType = MENU_MAIN;
546 if (selectedOption == 1)
547 engine.cheatShield = !engine.cheatShield;
548 else if (selectedOption == 2)
549 engine.cheatAmmo = !engine.cheatAmmo;
550 else if (selectedOption == 3)
551 engine.cheatCash = !engine.cheatCash;
552 else if (selectedOption == 4)
553 engine.cheatTime = !engine.cheatTime;
554 else if (selectedOption == listLength)
556 menuType = MENU_MAIN;
563 menuType = MENU_MAIN;
568 engine.keyState[KEY_FIRE] = engine.keyState[KEY_ALTFIRE] = 0;
576 SDL_FreeSurface(prlogo);
577 SDL_FreeSurface(sflogo);
579 engine.keyState[KEY_FIRE] = engine.keyState[KEY_ALTFIRE] = 0;
583 if (selectedOption == 1)
586 selectedOption = 2; // go straight to mission 0
589 if (selectedOption == 3)
592 selectedOption = loadGame(continueSaveSlot);
595 // Send back a negative number...
596 if (selectedOption > 4)
602 return selectedOption;
606 Scrolls the intro text up the screen and nothing else.
612 int y = screen->h + 20;
616 fp = fopen("data/intro.txt", "rb");
622 while (fscanf(fp, "%d %[^\n]%*c", &nextPos, string) == 2)
625 gfx_createTextObject(index, string, -1, y, FONT_WHITE);
632 loadBackground("gfx/startUp.jpg");
633 screen_drawBackground();
634 screen_flushBuffer();
637 engine.keyState[KEY_FIRE] = engine.keyState[KEY_ALTFIRE] = 0;
646 if ((engine.keyState[KEY_FIRE] || engine.keyState[KEY_ALTFIRE]))
649 // XXX: The fact that it's line 8 that's watched is completely
650 // arbitrary. It might be prudent to replace this with something else.
651 if (gfx_textSprites[8].y > (screen->h / 2) + 150)
653 for (int i = 0 ; i < 9 ; i++)
655 gfx_textSprites[i].y -= 0.33333;
670 The game over screen :(
674 screen_flushBuffer();
676 SDL_FillRect(gfx_background, NULL, black);
678 engine.keyState[KEY_FIRE] = engine.keyState[KEY_ALTFIRE] = 0;
679 engine.gameSection = SECTION_INTERMISSION;
681 SDL_Surface *gameover = gfx_loadImage("gfx/gameover.png");
688 audio_playMusic("music/death.ogg", -1);
690 int x = (screen->w - gameover->w) / 2;
691 int y = (screen->h - gameover->h) / 2;
696 engine.keyState[KEY_FIRE] = engine.keyState[KEY_ALTFIRE] = 0;
702 if (engine.keyState[KEY_FIRE] || engine.keyState[KEY_ALTFIRE])
708 x = ((screen->w - gameover->w) / 2) - RANDRANGE(-2, 2);
709 y = ((screen->h - gameover->h) / 2) - RANDRANGE(-2, 2);
710 screen_blit(gameover, x, y);
715 SDL_FreeSurface(gameover);
717 screen_flushBuffer();
722 loadBackground("gfx/credits.jpg");
723 screen_flushBuffer();
730 int yPos2 = screen->h;
740 screen_drawBackground();
742 audio_playMusic("music/rise_of_spirit.ogg", 1);
744 fp = fopen("data/credits.txt", "rb");
745 // FIXME: It would be nice for the size of this array to be determined
746 // by the number of lines in the text file. I'm not sure how to do
747 // that at the moment, so just giving it a very large number for now.
748 credit = (textObject*) malloc(sizeof(textObject) * 300);
750 while (fscanf(fp, "%d %[^\n]%*c", &yPos, text) == 2)
753 credit[lastCredit].image = gfx_createTextSurface(text, FONT_WHITE);
754 credit[lastCredit].x = (screen->w - credit[lastCredit].image->w) / 2;
756 credit[lastCredit].y = yPos2;
763 engine.keyState[KEY_ESCAPE] = 0;
764 engine.keyState[KEY_FIRE] = 0;
765 engine.keyState[KEY_ALTFIRE] = 0;
774 if (engine.keyState[KEY_ESCAPE] || engine.keyState[KEY_FIRE] ||
775 engine.keyState[KEY_ALTFIRE])
779 if(engine.keyState[KEY_DOWN])
781 else if(engine.keyState[KEY_UP])
784 for (i = 0 ; i <= lastCredit ; i++)
786 if ((credit[i].y > -10) && (credit[i].y < (screen->h + 10)))
787 screen_blit(credit[i].image, (int)credit[i].x, (int)credit[i].y);
788 if (speed > 0 && credit[lastCredit].y > ((screen->h / 2) + 100))
789 credit[i].y -= speed;
790 else if(speed < 0 && credit[0].y < screen->h)
791 credit[i].y -= speed;
797 for (i = 0 ; i <= lastCredit ; i++)
799 SDL_FreeSurface(credit[i].image);