1 /* moon_lander.c
2 *
3 * copyright 06/26/2001
4 * magigames and dave blood - geekd@yahoo.com
5 *
6 * 07/03/2001 - Mike Heckman
7 * Added pause capability and compiler options to turn off sound
8 *
9 * 08/14/2001 - Mike Heckman added AI to play demo game, geekd added options
10 * and save/load user options, random backgrounds, and merged MH's AI in
11 *
12 * 08/16/2001 - found most memory leaks and patched them (geekd)
13 *
14 * 08/17/2001 - cleaned up some of the messy code, fixed last of the memory leaks,
15 * added ryan daniels' ship and thrusters
16 *
17 */
18
19
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <math.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <dirent.h>
28
29 #ifndef WIN32_BUILD
30 #include <pwd.h>
31 #endif
32
33 #include "gamelib.h"
34 #include "DT_drawtext.h"
35 #include "SDL_image.h"
36
37 #define XSIZE 640
38 #define YSIZE 480
39 #define TERRAIN_YSIZE (YSIZE / 2)
40 #define FPS (1000 / 35)
41 #define DATAPATH "%%PREFIX%%/share/moonlander/"
42
43 #define FRESHRUN 0
44 #define GAMEOVER 1
45 #define LOST 2
46 #define WON 3
47 #define NEWGAME 4
48 #define AIGAME 5
49 #define BONUS_SHIP 6
50
51 /************************************************/
52
53 typedef struct {
54 int r;
55 int g;
56 int b;
57 } RGBcolor;
58
59 /************************************************/
60
61 typedef struct {
62 float difference;
63 float vdiff;
64 float max_y;
65 float target;
66 int pad;
67 int distance;
68 int direction;
69 int state;
70 } AI;
71
72 /************************************************/
73
74 typedef struct {
75 Sprite sprite;
76 int landing_x[5];
77 int landing_y[5];
78 int landing_w[5];
79 float landing_speed[5];
80 int landing_score[5];
81 RGBcolor landing_color[5];
82 int difficulty;
83 int fuel;
84 int num_landings;
85 } Level;
86
87 /************************************************/
88
89 typedef struct {
90 int ships_remaining;
91 unsigned int fuel;
92 int score;
93 int difficulty;
94 float gravity;
95 int big_font;
96 int small_font;
97 int demo_mode;
98 int autopilot;
99 int state;
100 int ActualTime, LastTime;
101 int landing_pad;
102 int back_no;
103 SDL_Surface *screen;
104 Sprite explosion[25];
105 Sprite ship;
106 Sprite background;
107 Sprite thrust;
108 Sprite thrustb;
109 Sprite thrust_left;
110 Sprite thrust_right;
111 Sprite miniship;
112 Sprite logo;
113 Sprite gameover_screen;
114 Sprite magigames;
115 Level current_level;
116 int opt_prog_grav;
117 int opt_lp_bonus;
118 int opt_lp_warn;
119 int opt_num_lives;
120 int opt_fancy_terrain;
121 AI ai;
122 #ifndef NOSOUND
123 Mix_Chunk *engine;
124 Mix_Chunk *new_life;
125 Mix_Chunk *explosion_a;
126 Mix_Chunk *on;
127 Mix_Chunk *off;
128 Mix_Chunk *ready;
129 Mix_Chunk *go;
130 Mix_Chunk *eagle_landed;
131 #endif
132 } Game;
133
134
135 /************************************************/
136
delay(int t)137 void delay(int t){
138 SDL_Event event;
139 Uint8 *key_table;
140 int i;
141
142 for (i = 0;i < t; i++){
143
144 SDL_PollEvent(&event);
145
146 if (event.type == SDL_QUIT){
147 exit(0);
148 }
149
150 key_table = SDL_GetKeyState(NULL);
151
152 if (key_table[SDLK_q]){
153 exit(0);
154 }
155
156 SDL_Delay(20);
157 }
158 }
159
160 /************************************************/
161
frame_rate_limiter(Game * game)162 void frame_rate_limiter(Game *game){
163
164 /* timer - so that things run at an even speed regardless of cpu speed */
165
166 game->ActualTime = SDL_GetTicks();
167 if (game->ActualTime < game->LastTime + FPS){
168 SDL_Delay(game->LastTime + FPS - game->ActualTime);
169 }
170 game->LastTime = game->ActualTime;
171 }
172
173 /************************************************/
174
get_new_background(Game * game)175 void get_new_background(Game *game) {
176
177 char filename[1024];
178 DIR *dir;
179 char *bg[100];
180 struct dirent *d;
181 int count = 0;
182 int i;
183
184 /* read images/backgrounds dir and choose a random image from there.
185 * put it's filename in image_file
186 */
187
188
189
190 snprintf(filename, sizeof filename, "%simages/backgrounds", DATAPATH);
191
192 if ( !(dir = opendir(filename)) ){
193 /* error */
194 printf("cannot open dir %s\n", filename);
195 exit(0);
196 }
197
198 while ( (d = readdir(dir)) != NULL){
199 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
200 continue;
201 bg[count++] = strdup(d->d_name);
202 if (count >= 100)
203 break;
204 }
205
206 closedir(dir);
207
208
209 if (!count){
210 printf("I got no images for backgrounds - ERROR\n");
211 exit(0);
212 }
213
214
215
216
217 game->back_no++;
218
219 if (game->back_no < 0){
220 game->back_no = 0;
221 }
222
223 if (game->back_no >= count){
224 game->back_no = 0;
225 }
226
227
228 if (game->background.image != NULL){
229 //printf("about to free background\n");
230 SDL_FreeSurface(game->background.image);
231 }
232 else{
233 //printf("background was NULL\n");
234 }
235
236 //printf("about to get new background: %d\n", game->back_no );
237
238 snprintf(filename, sizeof(filename), "%simages/backgrounds/%s", DATAPATH, bg[game->back_no]);
239 for (i = 0; i < count; i++)
240 free(bg[i]);
241
242 // printf("got %s\n", filename);
243
244 new_sprite(&(game->background), filename, 0, 0, 0, 0);
245 // printf("got new background\n");
246
247
248 }
249
250 /************************************************/
251
save_game(Game * game)252 void save_game(Game *game){
253 char filename[200];
254 FILE *file;
255
256 #ifndef WIN32_BUILD
257 struct passwd *pwp;
258
259
260 /* get user home dir */
261 if ( !(pwp = getpwuid(getuid()))){
262 // error
263 printf("attempt to get current user failed\n");
264 exit(0);
265 }
266
267 sprintf(filename, "%s/.moon_lander", pwp->pw_dir);
268 #endif
269
270 #ifdef WIN32_BUILD
271 sprintf(filename, "moon_lander.conf");
272 #endif
273
274 printf("saving game options in %s\n", filename);
275
276 if ( (file = fopen(filename, "w")) != NULL) {
277
278 fprintf(file,"%d %d %d %d %d", game->opt_num_lives, game->opt_lp_bonus,game->opt_lp_warn,
279 game->opt_prog_grav,game->opt_fancy_terrain);
280
281 }
282 else{
283 printf("cannot open file for saving: %s\n", filename);
284 }
285
286 fclose(file);
287 }
288
289 /************************************************/
290
load_game(Game * game)291 void load_game(Game *game){
292
293 char filename[200];
294 FILE *file;
295
296 #ifndef WIN32_BUILD
297 struct passwd *pwp;
298
299 /* get user home dir */
300 if ( !(pwp = getpwuid(getuid()))){
301 // error
302 printf("attempt to get current user failed\n");
303 exit(0);
304 }
305
306 sprintf(filename, "%s/.moon_lander", pwp->pw_dir);
307 #endif
308
309 #ifdef WIN32_BUILD
310 sprintf(filename, "moon_lander.conf");
311 #endif
312
313 printf("reading game options in %s\n", filename);
314
315 if ( (file = fopen(filename, "r")) != NULL) {
316
317 fscanf(file,"%d %d %d %d %d", &game->opt_num_lives, &game->opt_lp_bonus, &game->opt_lp_warn,
318 &game->opt_prog_grav, &game->opt_fancy_terrain);
319
320 }
321 else{
322 printf("cannot open file for reading: %s - loading defaults\n", filename);
323
324 /* defaults */
325 game->opt_num_lives = 3;
326 game->opt_lp_bonus = 1;
327 game->opt_lp_warn = 1;
328 game->opt_prog_grav = 1;
329 game->opt_fancy_terrain = 1;
330
331 return;
332 }
333
334 fclose(file);
335 }
336
337
338 /************************************************/
339
options(Game * game)340 void options (Game *game) {
341 int done = 0;
342 int *selected;
343 int position = 0;
344 char options[5][100];
345 char display_string[150];
346 char selected_text[2];
347 int count;
348 int value[5];
349 Uint8 *key_table;
350 SDL_Event event;
351
352 sprintf(options[0],"%s", "Fancy Terrain");
353 sprintf(options[1],"%s", "Progressive Gravity");
354 sprintf(options[2],"%s", "Landing Pad Speed Warning");
355 sprintf(options[3],"%s", "Variable Speed Landing Pads");
356 sprintf(options[4],"%s", "Number Of Ships");
357
358
359 /* clear event buffer */
360 while (SDL_PollEvent(&event)){};
361
362 while (done == 0) {
363
364 SDL_WaitEvent(&event);
365
366 if (event.type == SDL_QUIT) {
367 exit(0);
368 }
369
370 key_table = SDL_GetKeyState(NULL);
371
372 if (key_table[SDLK_q]){
373 exit(0);
374 }
375
376 if (key_table[SDLK_ESCAPE]){
377 done = 1;
378 }
379
380 if (key_table[SDLK_UP]){
381 position--;
382 if (position < 0){
383 position = 4;
384 }
385 }
386
387 if (key_table[SDLK_DOWN]){
388 position++;
389 if (position >4){
390 position = 0;
391 }
392 }
393
394 if (key_table[SDLK_RETURN]){
395 (*selected)++;
396
397 if (position == 4){
398 if (*selected > 5){
399 *selected = 1;
400 }
401 }
402 else{
403 if (*selected > 1){
404 *selected = 0;
405 }
406 }
407
408 }
409
410 /* point selected at proper value */
411
412 if (position == 0){
413 selected = &(game->opt_fancy_terrain);
414 }
415 else if (position == 1){
416 selected = &(game->opt_prog_grav);
417 }
418 else if (position == 2){
419 selected = &(game->opt_lp_warn);
420 }
421 else if (position == 3){
422 selected = &(game->opt_lp_bonus);
423 }
424 else if (position == 4){
425 selected = &(game->opt_num_lives);
426 }
427
428 value[0] = game->opt_fancy_terrain;
429 value[1] = game->opt_prog_grav;
430 value[2] = game->opt_lp_warn;
431 value[3] = game->opt_lp_bonus;
432 value[4] = game->opt_num_lives;
433
434
435 /* draw the options */
436 draw_sprite(game->screen, game->background);
437 DT_DrawText("OPTIONS", game->screen, game->big_font, 260, 50);
438 DT_DrawText("Arrow Keys Select", game->screen, game->small_font, 260, 75);
439 DT_DrawText("ENTER changes value", game->screen, game->small_font, 260, 90);
440
441 for (count = 0; count < 5; count ++) {
442
443 if (position == count) {
444 sprintf(selected_text,"%s","**");
445 }
446 else {
447 sprintf(selected_text,"%s"," ");
448 }
449
450 sprintf(display_string, "%s %s - %d", selected_text, options[count], value[count] );
451 DT_DrawText(display_string, game->screen, game->big_font, 50, 150 + (count * 50) );
452
453 }
454
455 delay(3);
456 SDL_Flip(game->screen);
457
458 } /* end while */
459
460 save_game(game);
461
462 /* clear event buffer */
463 delay(5);
464 while (SDL_PollEvent(&event)){};
465 }
466
467
468 /************************************************/
469
470
remaining_ships(Game * game)471 void remaining_ships(Game *game) {
472 int count;
473
474 // Draw in the remaining ships
475 for( count = 0; count < game->ships_remaining; count++ ) {
476 game->miniship.x = (22 * count);
477 game->miniship.y = 15;
478 draw_sprite(game->screen, game->miniship );
479 }
480
481 }
482
483
484 /************************************************/
485
486
DrawPixel(SDL_Surface * screen,Uint8 R,Uint8 G,Uint8 B,int x,int y)487 void DrawPixel(SDL_Surface *screen, Uint8 R, Uint8 G, Uint8 B, int x, int y)
488 {
489
490 Uint32 color = SDL_MapRGB(screen->format, R, G, B);
491 Uint16 *bufp;
492
493 bufp = (Uint16 *)screen->pixels + y*screen->pitch/2 + x;
494 *bufp = color;
495
496
497 }
498
499 /************************************************/
500
draw_line(SDL_Surface * screen,Uint8 R,Uint8 G,Uint8 B,int x,int y)501 void draw_line(SDL_Surface *screen, Uint8 R, Uint8 G, Uint8 B, int x, int y) {
502
503 for(; y < TERRAIN_YSIZE; y++){
504 DrawPixel(screen, R, G, B, x, y);
505 }
506
507 }
508
509 /************************************************/
510
511 /* This draws a line that is composed of n repeating gradients
512 implemented by BMD */
513
draw_terrain_line(SDL_Surface * screen,int x,int y)514 void draw_terrain_line( SDL_Surface *screen, int x, int y )
515 {
516 int gradient_iterations = 3;
517 int dark_color = 80;
518 int gradient_color_variance = 40;
519
520 int gradient_height = (TERRAIN_YSIZE-y)/gradient_iterations;
521
522 for(; y < TERRAIN_YSIZE; y++)
523 {
524 int height = TERRAIN_YSIZE-y;
525 double gradient_ratio = (double)(height%gradient_height)/gradient_height;
526 int color = gradient_ratio * gradient_color_variance + dark_color;
527 DrawPixel(screen, color, color, color, x, y);
528 }
529 }
530
531 /************************************************/
532
random_level(Game * game)533 void random_level(Game *game) {
534 SDL_Surface *tmp;
535 int x = 0;
536 int y = 0;
537 int yd = 0;
538 int miny = 0;
539 int maxy = 0;
540 int yfluct = 0;
541 int size = 0;
542 int max = 0;
543 float speed;
544 RGBcolor rgb;
545 float distance;
546 int xdiff;
547 int ydiff;
548 char filename[100];
549
550 //printf("random level\n");
551
552 game->current_level.num_landings = 0;
553 game->current_level.difficulty = game->difficulty;
554
555 // printf("getting new background\n");
556
557 get_new_background(game);
558
559
560 while (game->current_level.num_landings == 0){
561
562 // printf("starting while loop\n");
563
564 if (game->current_level.sprite.image != NULL){
565 SDL_FreeSurface(game->current_level.sprite.image);
566 }
567
568 sprintf(filename, "%simages/blank_terrain.gif", DATAPATH);
569 tmp = IMG_Load(filename);
570 if (tmp == NULL ) {
571 fprintf(stderr, "Couldn't load %s: %s\n", filename, SDL_GetError());
572 exit(1);
573 }
574
575 game->current_level.sprite.image = SDL_DisplayFormat(tmp);
576
577 SDL_FreeSurface(tmp);
578
579 SDL_LockSurface(game->current_level.sprite.image);
580
581 #ifndef WIN32_BUILD
582 srandom(time(NULL));
583
584 while ( (y > 230) || (y < 10) ){
585 y = random()%TERRAIN_YSIZE;
586 }
587
588 miny = ( (random()%(TERRAIN_YSIZE/2)) + 10);
589 maxy = ( (random()%(TERRAIN_YSIZE/2) + TERRAIN_YSIZE/2) -10 );
590 #endif
591
592 #ifdef WIN32_BUILD
593 srand(time(NULL));
594
595 while ( (y > 230) || (y < 10) ){
596 y = rand()%TERRAIN_YSIZE;
597 }
598
599 miny = ( (rand()%(TERRAIN_YSIZE/2)) + 10);
600 maxy = ( (rand()%(TERRAIN_YSIZE/2) + TERRAIN_YSIZE/2) -10 );
601 #endif
602
603 if (y > (TERRAIN_YSIZE/2)){
604 yd = -1;
605 }
606 else{
607 yd = 1;
608 }
609
610
611 /* start to draw */
612
613 for (x = 0; x < XSIZE; x++){
614
615 if ( (x % 3) == 0){
616 #ifndef WIN32_BUILD
617 yfluct = ( (random()%10) - 5);
618 #endif
619 #ifdef WIN32_BUILD
620 yfluct = ( (rand()%10) - 5);
621 #endif
622 }
623
624 if ( ( (y < maxy) && (y > miny)) || ( (y > maxy) && (yfluct < 1) )
625 || ( (y < maxy) && (yfluct > -1) ) ){
626
627 y = y + yfluct;
628
629 }
630
631 /* draw landscape */
632
633 if (game->opt_fancy_terrain){
634 draw_terrain_line(game->current_level.sprite.image, x, y);
635 }
636 else {
637 draw_line(game->current_level.sprite.image, 80, 80, 80, x, y);
638 }
639
640 /* check for change direction */
641
642 if (yd == 1){
643
644 if (y > maxy){
645
646 if ( (x < (XSIZE - 60) ) && (game->current_level.num_landings < 4) ){
647
648 /* landing pad */
649
650 size = (40 + (15 - ( game->difficulty / 2 ) ) );
651 max = x + size;
652
653 game->current_level.landing_x[game->current_level.num_landings] = x;
654 game->current_level.landing_y[game->current_level.num_landings] = (y + TERRAIN_YSIZE);;
655 game->current_level.landing_w[game->current_level.num_landings] = size;
656
657 /* get distance from center-top */
658 xdiff = ((XSIZE / 2) - x );
659 ydiff = ( y );
660
661 if (xdiff == 0){
662 distance = ydiff;
663 }
664 else if (ydiff == 0){
665 distance = xdiff;
666 }
667 else {
668 distance = sqrt( ( xdiff * xdiff ) + (ydiff * ydiff ) );
669 }
670
671 game->current_level.landing_speed[game->current_level.num_landings] = 1.00;
672 game->current_level.landing_score[game->current_level.num_landings] =
673 ( ( (16 - (size - 45) ) * 100) +
674 ( (distance / 4) * ( (game->difficulty / 2) + 1) ) );
675
676 // Default landing pad color is blue
677 rgb.r = 0;
678 rgb.g = 0;
679 rgb.b = 255;
680
681 /* ----------- bonus colored landing pads if on ------- */
682 if (game->opt_lp_bonus){
683 if( game->current_level.num_landings ) {
684 #ifndef WIN32_BUILD
685 speed = ( random() % 3 );
686 #endif
687
688 #ifdef WIN32_BUILD
689 speed = ( rand() % 3 );
690 #endif
691
692 // Magenta is for landings at .90
693 if( speed > 0 ) {
694 rgb.r = 255;
695 rgb.g = 0;
696 rgb.b = 255;
697 }
698 // Green for landings at .80
699 if( speed > 1 ) {
700 rgb.r = 0;
701 rgb.g = 255;
702 rgb.b = 0;
703 }
704
705 // Set the landing speed and score
706 game->current_level.landing_speed[game->current_level.num_landings] -= (speed * .1);
707 game->current_level.landing_score[game->current_level.num_landings] += (speed * 100);
708 }
709 }
710
711
712 game->current_level.landing_color[game->current_level.num_landings] = rgb;
713
714 // Write the landing pads onto the terrain
715 for (; x < max; x++){
716 DrawPixel(game->current_level.sprite.image, rgb.r, rgb.g, rgb.b, x, y);
717 DrawPixel(game->current_level.sprite.image, rgb.r, rgb.g, rgb.b, x, y+1);
718 DrawPixel(game->current_level.sprite.image, rgb.r, rgb.g, rgb.b, x, y+2);
719
720 if (game->opt_fancy_terrain){
721 draw_terrain_line(game->current_level.sprite.image, x, y + 3);
722 }
723 else {
724 draw_line(game->current_level.sprite.image, 80, 80, 80, x, y + 3);
725 }
726 }
727
728 x--;
729 game->current_level.num_landings++;
730 }
731
732 yd = -1;
733 #ifndef WIN32_BUILD
734 miny = ( (random()%(TERRAIN_YSIZE/2)) + 10);
735 maxy = ( (random()%(TERRAIN_YSIZE/2) + TERRAIN_YSIZE/2) - 25 );
736 #endif
737 #ifdef WIN32_BUILD
738 miny = ( (rand()%(TERRAIN_YSIZE/2)) + 10);
739 maxy = ( (rand()%(TERRAIN_YSIZE/2) + TERRAIN_YSIZE/2) - 25 );
740 #endif
741
742 }
743
744 }
745
746 if (yd == -1){
747 if (y < miny){
748 yd = 1;
749 #ifndef WIN32_BUILD
750 miny = ( (random()%(TERRAIN_YSIZE/2)) + 10);
751 maxy = ( (random()%(TERRAIN_YSIZE/2) + TERRAIN_YSIZE/2) - 10 );
752 #endif
753 #ifdef WIN32_BUILD
754 miny = ( (rand()%(TERRAIN_YSIZE/2)) + 10);
755 maxy = ( (rand()%(TERRAIN_YSIZE/2) + TERRAIN_YSIZE/2) - 10 );
756 #endif
757 }
758 }
759
760 y = y + yd;
761
762 }
763
764 SDL_UnlockSurface(game->current_level.sprite.image);
765
766 new_sprite_surface(&(game->current_level.sprite), game->current_level.sprite.image, 0, TERRAIN_YSIZE, 1);
767
768 game->current_level.fuel = (700 - (game->difficulty * 25));
769
770 if (game->current_level.fuel < 300){
771 game->current_level.fuel = 300;
772 }
773
774 }
775
776 }
777
778 /************************************************/
779
draw_score(Game * game,int landing_score)780 void draw_score(Game *game, int landing_score){
781 char display_string[100];
782 int count;
783
784 sprintf(display_string, "Fuel %d", game->fuel);
785
786 if (game->small_font > -1){
787 DT_DrawText(display_string, game->screen, game->small_font, 1, 1 );
788 }
789
790 sprintf(display_string, "X Velocity %.2f", game->ship.x_vel);
791
792 if (game->small_font > -1){
793 DT_DrawText(display_string, game->screen, game->small_font, 100, 1);
794 }
795
796 sprintf(display_string, "Y Velocity %.2f", game->ship.y_vel);
797
798 if (game->small_font > -1){
799 DT_DrawText(display_string, game->screen, game->small_font, 250, 1);
800 }
801
802 sprintf(display_string, "Score: %d", game->score);
803
804 if (game->small_font > -1){
805 DT_DrawText(display_string, game->screen, game->small_font, 500, 1);
806 }
807
808 if (landing_score){
809
810 for (count = 0; count < game->current_level.num_landings; count++){
811 sprintf(display_string, "%d", game->current_level.landing_score[count] );
812
813 if (game->small_font > -1){
814 DT_DrawText(display_string, game->screen, game->small_font,
815 ( game->current_level.landing_x[count] + 5 ),
816 ( game->current_level.landing_y[count] + 5 ));
817 }
818
819 }
820 }
821
822
823 }
824
825
826 /************************************************/
827
game_over(Game * game,int first_time)828 void game_over(Game *game, int first_time){
829
830 SDL_Event event;
831 int x;
832 int y = 375;
833 int done = 0;
834 int ticks = 0;
835 Uint8 *key_table;
836 int l_start;
837
838
839 if( game->demo_mode ) {
840 first_time = 1;
841 game->score = 0;
842 game->difficulty = 0;
843 game->ships_remaining = game->opt_num_lives;
844 game->gravity = 0.05;
845 }
846
847 if (first_time == 0){
848 /* if they just lost, show them thier score and stuff and then pause for a sec */
849 draw_sprite(game->screen, game->gameover_screen);
850 draw_sprite(game->screen, game->logo);
851 DT_DrawText("Game Over", game->screen, game->big_font, 252, 148 );
852 draw_score(game, 0);
853 draw_sprite(game->screen, game->magigames);
854
855 SDL_Flip(game->screen);
856 delay(75);
857 }
858
859 /* start between game animation */
860 l_start=60;
861
862
863
864 while (!done) {
865 ticks++;
866
867 draw_sprite(game->screen, game->gameover_screen);
868 draw_sprite(game->screen, game->logo);
869 draw_sprite(game->screen, game->magigames);
870
871 /* show the game name, etc */
872
873 /* if they just lost, show them thier score and stuff */
874
875 if (first_time == 0){
876 DT_DrawText("Game Over", game->screen, game->big_font, 252, 148 );
877 }
878
879 draw_score(game, 0);
880 DT_DrawText("Arrow keys control the ship", game->screen, game->big_font, 100, 100 );
881 DT_DrawText("Q quit P pause ESC options", game->screen, game->big_font, 75, 125 );
882 DT_DrawText("Press ENTER to play", game->screen, game->big_font, 175, 170 );
883
884 DT_DrawText("Score for each round = landing pad score + remaining fuel.", game->screen, game->small_font, 150, 280 );
885 DT_DrawText("Safe Landing requires X velocity < 0.5 and Y velocity < indicated by landing pad color.", game->screen, game->small_font, 55, 300 );
886 DT_DrawText("Free ship every 10,000 points", game->screen, game->small_font, 225, 340 );
887
888 /* do the pad display thing */
889 SDL_LockSurface(game->screen);
890 for (x=0; x < XSIZE; x++){
891
892 if ( (x > (XSIZE / 8 - 25) ) && ( x < (XSIZE / 8 + 30)) && (ticks > l_start * 1) && (ticks < (l_start * 5)) ){
893 DrawPixel(game->screen, 0, 0, 255, x, y);
894 DrawPixel(game->screen, 0, 0, 255, x, y+1);
895 DrawPixel(game->screen, 0, 0, 255, x, y+2);
896 }
897
898 if ( (x > (XSIZE / 2.67 - 25) ) && ( x < (XSIZE / 2.67 + 30)) && (game->opt_lp_warn)
899 && (ticks > (l_start * 2)) && (ticks < (l_start * 6) ) ){
900 DrawPixel(game->screen, 255, 0, 0, x, y);
901 DrawPixel(game->screen, 255, 0, 0, x, y+1);
902 DrawPixel(game->screen, 255, 0, 0, x, y+2);
903 }
904
905 if ( (x > (XSIZE / 1.6 - 25) ) && ( x < (XSIZE / 1.6 + 30)) && (game->opt_lp_bonus)
906 && (ticks > (l_start * 3)) && (ticks < (l_start * 7)) ){
907 DrawPixel(game->screen, 0, 255, 0, x, y);
908 DrawPixel(game->screen, 0, 255, 0, x, y+1);
909 DrawPixel(game->screen, 0, 255, 0, x, y+2);
910 }
911
912 if ( (x > (XSIZE / 1.14 - 25) ) && ( x < (XSIZE / 1.14 + 30)) && (game->opt_lp_bonus)
913 && (ticks > (l_start * 4)) && (ticks < (l_start * 8)) ){
914 DrawPixel(game->screen, 255, 0, 255, x, y);
915 DrawPixel(game->screen, 255, 0, 255, x, y+1);
916 DrawPixel(game->screen, 255, 0, 255, x, y+2);
917 }
918 }
919
920
921 SDL_UnlockSurface(game->screen);
922
923 if ( (ticks > (l_start * 1)) && (ticks < (l_start * 5) ) ){
924 DT_DrawText("Landing Vel. = 1.0", game->screen, game->small_font, (XSIZE / 8 - 50), y + 10 );
925 }
926
927 if ( (game->opt_lp_warn) && (ticks > (l_start * 2)) && (ticks < (l_start * 6) ) ){
928 DT_DrawText("Red = Too Fast!", game->screen, game->small_font, (XSIZE / 2.67 - 50), y + 10 );
929 }
930
931 if ( (game->opt_lp_bonus) && (ticks > (l_start * 3)) && (ticks < (l_start * 7) ) ){
932 DT_DrawText("Landing Vel. = 0.8", game->screen, game->small_font, (XSIZE / 1.6 - 50), y + 10 );
933 }
934
935 if ( (game->opt_lp_bonus) && (ticks > (l_start * 4)) && (ticks < (l_start * 8) ) ){
936 DT_DrawText("Landing Vel. = 0.9", game->screen, game->small_font, (XSIZE / 1.14 - 50), y + 10 );
937 }
938
939 if( ( game->opt_lp_bonus ) && ( ticks > ( l_start * 9)) ) {
940 game->score = 0;
941 game->difficulty = 0;
942 game->ships_remaining = 0;
943 game->gravity = 0.05;
944 game->state = AIGAME;
945 done = 1;
946 }
947
948 #ifndef NOSOUND
949 /* play a sound when the pads appear and dissapear */
950
951 if ( (ticks == (l_start * 1) ) || ((ticks == (l_start * 2)) && (game->opt_lp_warn))
952 || ((ticks == (l_start * 3)) && (game->opt_lp_bonus)) || ((ticks == (l_start * 4)) && (game->opt_lp_bonus)) ){
953 play_audio(game->on, 0);
954 }
955
956 if ( (ticks == (l_start * 5)) || ((ticks == (l_start * 6)) && (game->opt_lp_warn))
957 || ((ticks == (l_start * 7)) && (game->opt_lp_bonus)) || ((ticks == (l_start * 8)) && (game->opt_lp_bonus)) ){
958 play_audio(game->off, 0);
959 }
960 #endif
961
962 if (ticks > (l_start * 9) ) {
963 ticks = 0;
964 }
965 SDL_Flip(game->screen);
966
967
968 /* press ENTER to play */
969 SDL_PollEvent(&event);
970
971 if (event.type == SDL_QUIT){
972 exit(0);
973 }
974
975 key_table = SDL_GetKeyState(NULL);
976
977 if (key_table[SDLK_q]){
978 exit(0);
979 }
980
981
982 if (key_table[SDLK_RETURN]){
983 done = 1;
984 game->demo_mode = 0;
985 game->score = 0;
986 game->difficulty = 0;
987 game->ships_remaining = game->opt_num_lives;
988 game->gravity = 0.05;
989 game->state = NEWGAME;
990 }
991
992 if (key_table[SDLK_ESCAPE]){
993 options(game);
994 }
995
996 frame_rate_limiter(game);
997
998 } /* end while */
999
1000
1001 /* reset all the stuff for a new game */
1002
1003 game->score = 0;
1004 game->difficulty = 0;
1005 game->ships_remaining = (game->opt_num_lives - 1);
1006 game->gravity = 0.05;
1007
1008
1009
1010 }
1011
1012
1013 /************************************************/
1014
new_round(Game * game,int died_won)1015 void new_round(Game *game, int died_won) {
1016
1017 SDL_Event event;
1018 char display_string[100];
1019
1020
1021 //printf("new round\n");
1022
1023 /* clear event buffer */
1024
1025 while (SDL_PollEvent(&event)){};
1026
1027 /* reset ship */
1028 game->ship.x = XSIZE / 2;
1029 game->ship.y = 1;
1030 game->ship.y_vel=0;
1031 game->ship.x_vel=0;
1032
1033
1034 if (died_won == 0){ /* died */
1035 game->ships_remaining--;
1036 game->fuel = game->current_level.fuel;
1037 //level = current_level;
1038 }
1039
1040 else if (died_won == 1) { /* won */
1041 game->difficulty++;
1042
1043 /* get new level */
1044
1045
1046 random_level(game);
1047
1048 game->fuel = game->current_level.fuel;
1049
1050 /* prograssive gravity if on */
1051 if (game->opt_prog_grav){
1052 game->gravity = 0.05 + (game->difficulty * 0.001 );
1053 }
1054
1055
1056 }
1057 else if (died_won == 3) { /* starting new game */
1058
1059 random_level(game) ;
1060 game->fuel = game->current_level.fuel;
1061 }
1062
1063
1064
1065 /* draw start round screen */
1066
1067 draw_sprite(game->screen, game->background);
1068 remaining_ships(game );
1069 draw_sprite(game->screen, game->ship);
1070 draw_sprite(game->screen, game->current_level.sprite);
1071
1072 /* message 1 */
1073
1074 draw_score(game, 1);
1075
1076 if (game->difficulty == 4) {
1077 DT_DrawText("Not Bad", game->screen, game->big_font, 250, 250 );
1078 }
1079
1080 else if (game->difficulty == 9){
1081 DT_DrawText("You think you're hot shit, huh?", game->screen, game->big_font, 125, 250 );
1082 }
1083
1084 else if (game->difficulty == 14){
1085 DT_DrawText("Starfleet called, they want to", game->screen, game->big_font, 100, 235 );
1086 DT_DrawText("offer you a job", game->screen, game->big_font, 174, 260 );
1087 }
1088
1089 else if (game->difficulty == 19){
1090 DT_DrawText("The force is strong in you", game->screen, game->big_font, 125, 250 );
1091 }
1092
1093
1094 sprintf(display_string, "Level: %d", (game->difficulty) + 1);
1095 DT_DrawText(display_string, game->screen, game->big_font, 250, 150 );
1096
1097
1098 /* flip screen so they show up */
1099 #ifndef NOSOUND
1100 play_audio(game->ready, 1);
1101 #endif
1102 SDL_Flip(game->screen);
1103
1104 if( game->demo_mode == 1 ) {
1105 return;
1106 }
1107
1108 delay(75);
1109
1110 /* message 2 */
1111
1112 draw_sprite(game->screen, game->background);
1113 remaining_ships(game );
1114 draw_sprite(game->screen, game->ship);
1115 draw_sprite(game->screen, game->current_level.sprite);
1116
1117 draw_score(game, 1);
1118
1119 DT_DrawText("Ready...", game->screen, game->big_font, 250, 150 );
1120
1121 /* flip screen so they show up */
1122 #ifndef NOSOUND
1123 play_audio(game->ready, 1);
1124 #endif
1125 SDL_Flip(game->screen);
1126
1127 delay(70);
1128
1129 draw_sprite(game->screen, game->background);
1130 remaining_ships(game );
1131 draw_sprite(game->screen, game->ship);
1132 draw_sprite(game->screen, game->current_level.sprite);
1133 // Draw in the remaining ships
1134
1135 /* display fuel */
1136
1137 draw_score(game, 1);
1138
1139 DT_DrawText("GO!", game->screen, game->big_font, 290, 150 );
1140
1141 /* flip screen so they show up */
1142 #ifndef NOSOUND
1143 play_audio(game->go, 0);
1144 #endif
1145 SDL_Flip(game->screen);
1146
1147 delay(25);
1148
1149
1150 /* clear event buffer */
1151 while (SDL_PollEvent(&event)){}
1152
1153 }
1154
1155
1156 /************************************************/
1157
explode(Sprite exploder,Sprite terrain,Game * game)1158 void explode (Sprite exploder,
1159 Sprite terrain,
1160 Game *game
1161 ) {
1162
1163 int count;
1164
1165 #ifndef NOSOUND
1166 play_audio(game->explosion_a, 0);
1167 #endif
1168
1169 for (count = 1; count < 27; count++){
1170 game->explosion[count-1].x = ( (exploder.x + (exploder.w / 2)) - (game->explosion[count-1].w / 2) );
1171 game->explosion[count-1].y = ( (exploder.y + (exploder.h / 2)) - (game->explosion[count-1].h / 2) );
1172
1173 draw_sprite(game->screen, game->background);
1174 remaining_ships(game );
1175 draw_sprite(game->screen, terrain);
1176
1177 if (count < 26) {
1178 draw_sprite(game->screen, game->explosion[count-1]);
1179 }
1180
1181 /* display fuel */
1182
1183 draw_score(game, 1);
1184
1185
1186 /* Update the screen */
1187
1188 SDL_Flip(game->screen);
1189
1190 /* timer - so that things run at an even speed regardless of cpu speed */
1191
1192 frame_rate_limiter(game);
1193
1194
1195 }
1196
1197 delay(30);
1198
1199 }
1200
1201 /************************************************/
1202
win(Game * game,int bonus)1203 void win (Game *game, int bonus) {
1204
1205 game->score += game->current_level.landing_score[game->landing_pad];
1206
1207 #ifndef NOSOUND
1208 Mix_HaltChannel(1);
1209 /* congrats sound here */
1210 play_audio(game->eagle_landed, 0);
1211 #endif
1212
1213 draw_sprite(game->screen, game->background);
1214 remaining_ships(game );
1215 draw_sprite(game->screen, game->current_level.sprite);
1216 draw_score(game, 1);
1217 draw_sprite(game->screen, game->ship);
1218
1219 if (game->big_font > -1){
1220 DT_DrawText("Excellent", game->screen, game->big_font, (XSIZE / 2) - 66, (YSIZE / 3) - 9 );
1221 }
1222
1223 /* Update the screen */
1224 SDL_Flip(game->screen);
1225 delay(80);
1226
1227 if (bonus){
1228 game->ships_remaining++;
1229
1230 #ifndef NOSOUND
1231 play_audio(game->new_life, 1);
1232 #endif
1233
1234 draw_sprite(game->screen, game->background);
1235 remaining_ships(game );
1236 draw_sprite(game->screen, game->current_level.sprite);
1237 draw_score(game, 1);
1238 draw_sprite(game->screen, game->ship);
1239
1240 if (game->big_font > -1){
1241 DT_DrawText("Excellent", game->screen, game->big_font, (XSIZE / 2) - 66, (YSIZE / 3) - 9 );
1242 DT_DrawText("Bonus Ship", game->screen, game->big_font, (XSIZE / 2) - 70, (YSIZE / 3) + 40 );
1243 }
1244
1245 /* Update the screen */
1246
1247 SDL_Flip(game->screen);
1248 delay(80);
1249 }
1250
1251 }
1252
1253 /************************************************/
1254
gameai(int * left,int * right,int * down,Game * game)1255 void gameai( int *left,
1256 int *right,
1257 int *down,
1258 Game *game)
1259 {
1260 int count;
1261
1262 /* -------------------------------------------------------------
1263 Game AI -- written by Michael Heckman 07/17/2001
1264
1265 Ok, so we're going to divide the AI into several states:
1266
1267 0 => Figure out the direction
1268 1 => Burn until we're half way there
1269 2 => Burn in the opposite direction
1270 3 => once we've reached the pad, cancel out any remaining
1271 velocity.
1272 4 => Freefall with minor course changes
1273
1274 ------------------------------------------------------------- */
1275 *left = 0;
1276 *right = 0;
1277
1278 // AI State
1279 /* --- state 0, locate the pad and init variables --- */
1280 if( game->ai.state == 0 ) {
1281 game->ai.vdiff = 0;
1282
1283 // Find which pad we're going to take.
1284 game->ai.pad = 0;
1285 game->ai.distance = 9999;
1286 for( count = 0; count < game->current_level.num_landings; count++ ) {
1287 if( abs( 320 - game->current_level.landing_x[count] ) < game->ai.distance ) {
1288 game->ai.distance = abs( 320 - game->current_level.landing_x[count] );
1289 game->ai.pad = count;
1290 }
1291 }
1292 game->ai.max_y = game->current_level.landing_speed[game->ai.pad];
1293
1294 // Calculate the half the difference between our current position
1295 //and the landing pad
1296 game->ai.target = game->current_level.landing_x[game->ai.pad] + 1;
1297 game->ai.difference = ( abs( game->ship.x - game->ai.target ) / 2 );
1298
1299 // Decide if we're going left or right
1300 if( game->ai.target < game->ship.x ) {
1301 game->ai.difference = game->ship.x - game->ai.difference - 1;
1302 game->ai.direction = 0;
1303 }
1304 else {
1305 game->ai.difference = game->ship.x + game->ai.difference;
1306 game->ai.direction = 1;
1307 }
1308
1309 //printf( "game->ai.difference: %d %d\n", game->ai.difference, game->ai.state );
1310 }
1311
1312 // Stay under the final velocity
1313 if( game->ai.max_y < game->ship.y_vel ) {
1314 *down = 1;
1315 }
1316
1317 /* --- state 1 & 2, main flight --- */
1318 if( game->ai.direction == 0 && game->ai.state < 3 ) {
1319
1320 if( ( game->ai.state == 0 ) && ( game->ship.x > game->ai.difference ) ) {
1321 game->ai.state = 1;
1322 }
1323 if( ( game->ai.state == 1 ) && ( game->ship.x <= game->ai.difference ) ) {
1324 game->ai.state = 2;
1325 }
1326 if( ( game->ai.state == 2 ) && ( game->ship.x <= game->ai.target || game->ship.x_vel > 0 ) ) {
1327 game->ai.state = 3;
1328 }
1329
1330 if( game->ai.state == 1 )
1331 *left = 1;
1332
1333 if( game->ai.state == 2 )
1334 *right = 1;
1335
1336 //printf( "game->ship.x1: %f %d %d %f\n", game->ship.x, game->ai.state, ( game->ship.x <= game->ai.target ), game->ai.target );
1337 }
1338
1339 /* --- state 1 & 2, main flight --- */
1340 if( game->ai.direction == 1 && game->ai.state < 3 ) {
1341 if( (game->ai.state == 0) && (game->ship.x < game->ai.difference) ) {
1342 game->ai.state = 1;
1343 }
1344 if( (game->ai.state == 1) && (game->ship.x >= game->ai.difference) ) {
1345 game->ai.state = 2;
1346 }
1347 if( (game->ai.state == 2) && (game->ship.x >= game->ai.target || game->ship.x_vel < 0 ) ) {
1348 game->ai.state = 3;
1349 }
1350
1351 if( game->ai.state == 1 )
1352 *right = 1;
1353 if( game->ai.state == 2 )
1354 *left = 1;
1355
1356 //printf( "game->ship.x2: %f %d %d %f\n", game->ship.x, game->ai.state, ( game->ship.x >= game->ai.target ), game->ai.target );
1357
1358 }
1359
1360 /* --- state 3, bring x velocity close to zero --- */
1361 if( game->ai.state == 3 ) {
1362 if( game->ship.x_vel > 0.07 || game->ship.x_vel < -0.07 ) {
1363 if( game->ship.x_vel > 0 )
1364 *left = 1;
1365 else
1366 *right = 1;
1367 }
1368 else {
1369 game->ai.state = 4;
1370 game->ai.vdiff = game->ship.y + (( game->current_level.landing_y[game->ai.pad] - game->ship.y ) / 3);
1371 }
1372 //printf( "game->ship.x3: %f %d %d %f\n", game->ship.x, game->ai.state, ( game->ship.x >= game->ai.target ), game->ai.target );
1373 }
1374
1375 /* --- state 4, close in on the landing pad --- */
1376 if( game->ai.state == 4 ) {
1377 if( ( game->ship.x < game->ai.target ) || ( game->ship.x > game->ai.target + 2 ) || game->ship.x_vel != 0.0 ) {
1378 if( game->ship.x > game->ai.target + 2 ) {
1379 if( game->ship.x_vel > -0.07 )
1380 *left = 1;
1381 //printf( "C1: x_vel=%f vel=%d left=%d right=%d\n", game->ship.x_vel, ( game->ship.x_vel > -0.07 ), *left, *right );
1382 }
1383 if( game->ship.x < game->ai.target ) {
1384 if( game->ship.x_vel < 0.07 )
1385 *right = 1;
1386 //printf( "C2: x_vel=%f vel=%d left=%d right=%d\n", game->ship.x_vel, ( game->ship.x_vel < 0.07 ), *left, *right );
1387 }
1388 //printf( "C3: x_vel=%f vel=%d left=%d right=%d\n", game->ship.x_vel, ( game->ship.x_vel < 0.07 ), *left, *right );
1389 }
1390
1391 if( game->ship.y < (game->ai.vdiff + game->ship.y_vel ) )
1392 *down = 0;
1393
1394 //printf( "4: game->ship.x=%f state=%d target=%f x_vel=%f y_vel=%f vdiff=%f\n", game->ship.x, game->ai.state, game->ai.target, game->ship.x_vel, game->ship.y_vel, game->ai.vdiff );
1395 }
1396
1397 return;
1398 }
1399
1400
1401
1402 /****************************************************************/
1403 /* ---------------------- gameloop ---------------------------- */
1404
1405
gameloop(Game * game)1406 void gameloop(Game *game){
1407 short int collision = 0;
1408 int down = 0;
1409 int left = 0;
1410 int right = 0;
1411 int count = 0;
1412 int engine_on=0;
1413 int engine_on_past=0;
1414 int won=0;
1415 int odd_even=0;
1416 int x;
1417 Uint8 *key_table;
1418 SDL_Event event;
1419 int pause = 0;
1420 int pressed = 0;
1421 int appressed = 0;
1422 char display_string[100];
1423
1424 game->ai.state = 0;
1425
1426
1427 while (1) {
1428 /* zero out "show thrust" vars */
1429
1430 down=0;
1431 left=0;
1432 right=0;
1433 engine_on=0;
1434 won = 0;
1435 odd_even++;
1436
1437
1438 /* gravity */
1439
1440 if( !pause )
1441 game->ship.y_vel = game->ship.y_vel + game->gravity;
1442
1443 /* read keyboard */
1444
1445 SDL_PollEvent(&event);
1446
1447 if (event.type == SDL_QUIT){
1448 exit(0);
1449 }
1450
1451 key_table = SDL_GetKeyState(NULL);
1452
1453 if (key_table[SDLK_ESCAPE]){
1454 options(game);
1455 }
1456
1457 if (key_table[SDLK_RIGHT]){
1458 right = 1;
1459 }
1460
1461 if (key_table[SDLK_LEFT]){
1462 left = 1;
1463 }
1464
1465 if (key_table[SDLK_UP]){
1466 down = 1;
1467 }
1468
1469 if (key_table[SDLK_a]){
1470 // toggle
1471 if( !appressed ) {
1472 game->autopilot = (game->autopilot)?0:1;
1473 appressed++;
1474 if( game->autopilot == 1 ) {
1475 game->ai.state = 0;
1476 }
1477 }
1478 }
1479 else{
1480 if( appressed ) {
1481 appressed = 0;
1482 }
1483 }
1484
1485 if (key_table[SDLK_q]){
1486 exit(0);
1487 }
1488
1489 if( game->demo_mode && ( left || right || down || pause ) ) {
1490 collision = 1;
1491 }
1492
1493 // Toggle pause on/off
1494 if( key_table[SDLK_p] ) {
1495 if( !pressed ) {
1496 pause = (pause)?0:1;
1497 pressed++;
1498 if( pause ) {
1499 /* printf( "Pause pressed\n" ); */
1500 sprintf(display_string, "**PAUSED**");
1501
1502 if (game->small_font > -1){
1503 DT_DrawText(display_string, game->screen, game->small_font, 300, 20);
1504 }
1505 }
1506 }
1507 }
1508 else{
1509 if( pressed ) {
1510 /* printf( "Pause released\n" ); */
1511 pressed = 0;
1512 }
1513 }
1514
1515 if (key_table[SDLK_q]){
1516 exit(0);
1517 }
1518
1519 if( !pause ) {
1520
1521 if( game->demo_mode || game->autopilot ) {
1522 game->gravity = 0.05;
1523 gameai( &left, &right, &down, game );
1524 }
1525
1526 if( game->fuel > 0 ) {
1527 if( right == 1 ) {
1528 game->ship.x_vel = game->ship.x_vel + 0.07;
1529 game->fuel = game->fuel - 1;
1530 engine_on=1;
1531 }
1532
1533 if( left == 1) {
1534 game->ship.x_vel = game->ship.x_vel - 0.07;
1535 game->fuel = game->fuel - 1;
1536 engine_on=1;
1537 }
1538
1539 if( down == 1 && game->fuel > 1 ) {
1540 game->ship.y_vel = game->ship.y_vel - 0.10;
1541 game->fuel = game->fuel - 2;
1542 engine_on=1;
1543 }
1544 else {
1545 down = 0;
1546 }
1547 }
1548 else {
1549 left = right = down = 0;
1550 }
1551
1552 #ifndef NOSOUND
1553 if ( (engine_on == 1) && (! Mix_Playing(1) ) ){
1554 Mix_PlayChannel(1, game->engine, 0);
1555 }
1556
1557 if ( (engine_on == 0) && (engine_on_past == 1) ){
1558 Mix_HaltChannel(1);
1559 }
1560 #endif
1561
1562 engine_on_past = engine_on;
1563
1564 /* update ship position */
1565
1566 game->ship.x = game->ship.x + game->ship.x_vel;
1567 game->ship.y = game->ship.y + game->ship.y_vel;
1568
1569 /* update rocket exhaust position */
1570
1571 game->thrust.x = (game->ship.x + ( (game->ship.w - game->thrust.w) / 2));
1572 game->thrust.y = (game->ship.y + (game->ship.h -5));
1573
1574 game->thrustb.x = (game->ship.x + ( (game->ship.w - game->thrust.w) / 2));
1575 game->thrustb.y = (game->ship.y + (game->ship.h -5));
1576
1577 game->thrust_right.x = (game->ship.x - game->thrust_right.w) ;
1578 game->thrust_right.y = ( (game->ship.y + game->ship.h) - (game->thrust_right.h + 8) );
1579
1580 game->thrust_left.x = (game->ship.x + game->ship.w) ;
1581 game->thrust_left.y = ( (game->ship.y + game->ship.h) - (game->thrust_left.h + 8) );
1582
1583
1584 /* draw screen */
1585
1586 draw_sprite(game->screen, game->background);
1587 remaining_ships(game );
1588 draw_sprite(game->screen, game->ship);
1589 draw_sprite(game->screen, game->current_level.sprite);
1590
1591
1592 if( game->demo_mode ) {
1593 sprintf(display_string, "**DEMO MODE - Press Arrow Keys To Exit**");
1594 DT_DrawText(display_string, game->screen, game->small_font, 200, 20);
1595 }
1596
1597 // Write in the landing pads as red if you're going too fast - if on
1598 if (game->opt_lp_warn){
1599 for (count = 0; count < game->current_level.num_landings; count++){
1600 if( game->ship.y_vel > game->current_level.landing_speed[count] ) {
1601
1602 for( x = game->current_level.landing_x[count];
1603 x < game->current_level.landing_x[count] + game->current_level.landing_w[count]; x++){
1604
1605 DrawPixel(game->screen, 255, 0, 0, x, game->current_level.landing_y[count]);
1606 DrawPixel(game->screen, 255, 0, 0, x, game->current_level.landing_y[count]+1);
1607 DrawPixel(game->screen, 255, 0, 0, x, game->current_level.landing_y[count]+2);
1608 }
1609 }
1610 }
1611 }
1612
1613
1614 if (right == 1){
1615 draw_sprite(game->screen, game->thrust_right);
1616 }
1617
1618 if (down == 1){
1619 if ( (odd_even%2) == 0){
1620 draw_sprite(game->screen, game->thrust);
1621 }
1622 else{
1623 draw_sprite(game->screen, game->thrustb);
1624 }
1625 }
1626
1627 if (left == 1){
1628 draw_sprite(game->screen, game->thrust_left);
1629 }
1630
1631 /* display fuel */
1632
1633 draw_score(game, 1);
1634
1635 /* flip screen so they show up */
1636
1637 SDL_Flip(game->screen);
1638
1639 /* check if off screen and way low */
1640
1641 if (game->ship.y > YSIZE) {
1642 explode(game->ship, game->current_level.sprite, game );
1643
1644 if( !game->ships_remaining ) {
1645 game->landing_pad = count;
1646 game->state = GAMEOVER;
1647 return;
1648 }
1649 else {
1650 game->landing_pad = count;
1651 game->ai.state = 0;
1652 game->state = LOST;
1653 return;
1654 }
1655 }
1656
1657 /* collision detection */
1658 if( !collision )
1659 collision = collision_detect_perfect(game->ship, game->current_level.sprite);
1660
1661 if (collision > 0){
1662 collision = 0;
1663 /* landing detection */
1664
1665 for (count = 0; count < game->current_level.num_landings; count++){
1666
1667
1668 if ( ((game->ship.x + 2) > game->current_level.landing_x[count])
1669 && ( ((game->ship.x - 2) + game->ship.w) <
1670 (game->current_level.landing_x[count] + game->current_level.landing_w[count]) )
1671 && (game->ship.y_vel < game->current_level.landing_speed[count])
1672 && (game->ship.x_vel <0.5) && (game->ship.x_vel > -0.5)){
1673
1674 /* we landed! */
1675 won = 1;
1676
1677 if( game->demo_mode ) {
1678 game->landing_pad = count;
1679 win(game, 0);
1680 game->state = GAMEOVER;
1681 return;
1682 }
1683
1684
1685 // Bonus ship every 10000 points
1686 if( (game->score / 10000) <
1687 ((game->score + game->current_level.landing_score[count]) / 10000 ) ) {
1688 // (MLH) This would be a good place to play a sound
1689
1690 game->landing_pad = count;
1691 game->state = BONUS_SHIP;
1692 return;
1693 }
1694
1695 game->landing_pad = count;
1696 game->state = WON;
1697 return;
1698 }
1699
1700 }
1701
1702 if (won == 0){
1703
1704 /* didn't land */
1705
1706 explode(game->ship, game->current_level.sprite, game );
1707
1708 if( game->demo_mode ) {
1709 game->landing_pad = count;
1710 game->state = GAMEOVER;
1711 return;
1712 }
1713
1714 if( !game->ships_remaining ) {
1715 game->landing_pad = count;
1716 game->state = GAMEOVER;
1717 return;
1718 }
1719 else {
1720 game->landing_pad = count;
1721 game->ai.state = 0;
1722 game->state = LOST;
1723 return;
1724
1725 }
1726
1727 }
1728 }
1729 }
1730 else {
1731 SDL_Flip(game->screen);
1732 }
1733 /* timer - so that things run at an even speed regardless of cpu speed */
1734 frame_rate_limiter(game);
1735 }
1736
1737 }
1738
1739
1740
1741
1742 /************************************************/
1743 /******************* main *******************/
1744 /************************************************/
1745
1746
main(int argc,char ** argv)1747 int main(int argc, char **argv) {
1748 char name[100];
1749 int count;
1750 char filename[100];
1751 Game game;
1752
1753
1754 #ifndef NOSOUND
1755 printf( "Sound active\n" );
1756 #endif
1757
1758 #ifdef NOSOUND
1759 printf( "Sound disabled\n" );
1760 #endif
1761
1762 game.demo_mode = 0;
1763 game.autopilot = 0;
1764
1765 load_game(&game);
1766
1767 game.score = 0;
1768 game.difficulty = 0;
1769 game.ships_remaining = (game.opt_num_lives - 1);
1770 game.gravity = 0.05;
1771
1772 game.current_level.sprite.image = NULL;
1773 game.current_level.sprite.x = -1;
1774 game.background.image = NULL;
1775 game.background.x = -1;
1776 game.back_no = 0;
1777
1778
1779
1780 /* initialize SDL */
1781 sprintf(filename, "%simages/win_icon.bmp", DATAPATH);
1782 game.screen = init_sdl(XSIZE, YSIZE, "Moon Lander", filename);
1783
1784 printf("screen initialized\n");
1785
1786 /* initialize sprites */
1787
1788 sprintf(filename, "%simages/miniship2.bmp", DATAPATH);
1789 new_sprite(&(game.miniship), filename, 0, 0, 1, 0 );
1790
1791 sprintf(filename, "%simages/newship.png", DATAPATH);
1792 new_sprite(&(game.ship), filename, XSIZE / 2, 1, 1, 0);
1793
1794 sprintf(filename, "%simages/thrust1.png", DATAPATH);
1795 new_sprite(&(game.thrust), filename, 0, 0, 1, 0);
1796
1797 sprintf(filename, "%simages/thrust2.png", DATAPATH);
1798 new_sprite(&(game.thrustb), filename, 0, 0, 1, 0);
1799
1800 sprintf(filename, "%simages/thrust_left.bmp", DATAPATH);
1801 new_sprite(&(game.thrust_left), filename, 0, 0, 1, 0);
1802
1803 sprintf(filename, "%simages/thrust_right.bmp", DATAPATH);
1804 new_sprite(&(game.thrust_right), filename, 0, 0, 1, 0);
1805
1806 sprintf(filename, "%simages/logo.png", DATAPATH);
1807 new_sprite(&(game.logo), filename, 130, 25, 1, 0);
1808
1809 sprintf(filename, "%simages/backgrounds/red_plain.jpg", DATAPATH);
1810 new_sprite(&(game.gameover_screen), filename, 0, 0, 0, 0);
1811
1812 sprintf(filename, "%simages/magigames_steel.gif", DATAPATH);
1813 new_sprite(&(game.magigames), filename, 194, 410, 0, 0);
1814
1815 #ifndef NOSOUND
1816
1817
1818 sprintf(filename, "%ssounds/Blaster_1.wav", DATAPATH);
1819 game.on = new_audio(filename);
1820 Mix_VolumeChunk(game.on, 20);
1821
1822 sprintf(filename, "%ssounds/Retro_3.wav", DATAPATH);
1823 game.off = new_audio(filename);
1824 Mix_VolumeChunk(game.off, 20);
1825
1826 sprintf(filename, "%ssounds/jet_lp.wav", DATAPATH);
1827 game.engine = new_audio(filename);
1828 Mix_VolumeChunk(game.engine, 40);
1829
1830 sprintf(filename, "%ssounds/Space_Bubbles_2.wav", DATAPATH);
1831 game.new_life = new_audio(filename);
1832
1833 sprintf(filename, "%ssounds/beep1b.wav", DATAPATH);
1834 game.ready= new_audio(filename);
1835 Mix_VolumeChunk(game.ready, 50);
1836
1837 sprintf(filename, "%ssounds/honk.wav", DATAPATH);
1838 game.go = new_audio(filename);
1839 Mix_VolumeChunk(game.go, 100);
1840
1841 sprintf(filename, "%ssounds/explosion2.wav", DATAPATH);
1842 game.explosion_a = new_audio(filename);
1843
1844 sprintf(filename, "%ssounds/eagle_has_landed.wav", DATAPATH);
1845 game.eagle_landed = new_audio(filename);
1846 Mix_VolumeChunk(game.eagle_landed, 20);
1847
1848 #endif
1849
1850
1851
1852 /* intitalize timer */
1853
1854 game.ActualTime = SDL_GetTicks();
1855 game.LastTime = game.ActualTime;
1856
1857 /* load fonts */
1858
1859 sprintf(filename, "%sfonts/ConsoleFont.bmp", DATAPATH);
1860 game.small_font = DT_LoadFont(filename, TRANS_FONT) ;
1861
1862 sprintf(filename, "%sfonts/LargeFont.bmp", DATAPATH);
1863 game.big_font = DT_LoadFont(filename, TRANS_FONT) ;
1864
1865
1866 //printf("getting random level for first time\n");
1867 //random_level(&game);
1868
1869 /* load explosion sprites here, because it takes a second or two*/
1870
1871 for (count = 1; count < 26; count++){
1872 sprintf(name, "%simages/kablam/exp%02d.png",DATAPATH, count);
1873 new_sprite(&(game.explosion[count -1]), name, 0,0,1,200);
1874 }
1875
1876 game.state = FRESHRUN;
1877
1878
1879
1880 /* everything is now loaded up */
1881
1882
1883
1884 while(1){
1885
1886 #ifndef NOSOUND
1887 Mix_HaltChannel(1);
1888 #endif
1889
1890 switch(game.state){
1891
1892 case FRESHRUN:{
1893 game_over(&game, 1);
1894 break;
1895 }
1896
1897
1898 case GAMEOVER:{
1899 game_over(&game, 0);
1900 break;
1901 }
1902
1903 case LOST:{
1904 new_round(&game, 0);
1905 gameloop(&game);
1906 break;
1907 }
1908
1909 case WON:{
1910 win(&game, 0);
1911 new_round(&game, 1);
1912 gameloop(&game);
1913 break;
1914 }
1915
1916 case BONUS_SHIP:{
1917 win(&game, 1);
1918 new_round(&game, 1);
1919 gameloop(&game);
1920 break;
1921 }
1922
1923
1924 case NEWGAME:{
1925 game.demo_mode = 0;
1926 new_round(&game, 3);
1927 gameloop(&game);
1928 break;
1929 }
1930
1931 case AIGAME:{
1932 game.demo_mode = 1;
1933 new_round(&game, 3);
1934 gameloop(&game);
1935 break;
1936 }
1937
1938 } /* end switch */
1939 }
1940
1941
1942 return(0);
1943 }
1944