diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/spacerocks.c | 1651 |
1 files changed, 812 insertions, 839 deletions
diff --git a/apps/plugins/spacerocks.c b/apps/plugins/spacerocks.c index 7e478d68ed..9a6f907d1e 100644 --- a/apps/plugins/spacerocks.c +++ b/apps/plugins/spacerocks.c | |||
@@ -277,42 +277,43 @@ CONFIG_KEYPAD == MROBE500_PAD | |||
277 | 277 | ||
278 | #define SHOW_COL 0 | 278 | #define SHOW_COL 0 |
279 | #define SCALE 5000 | 279 | #define SCALE 5000 |
280 | #define MISSILE_SCALE 5000 | 280 | #define WRAP_GAP 12*SCALE |
281 | #define WRAP_GAP 12 | ||
282 | #define POINT_SIZE 2 | 281 | #define POINT_SIZE 2 |
283 | #define SHOW_GAME_OVER_TIME 100 | 282 | #define START_LEVEL 1 |
284 | #define SHOW_LEVEL_TIME 50 | 283 | #define SHOW_LEVEL_TIME 50 |
285 | #define EXPLOSION_LENGTH 20 | 284 | #define EXPLOSION_LENGTH 20 |
286 | 285 | ||
287 | #define MAX_NUM_ASTEROIDS 25 | 286 | #define MAX_NUM_ASTEROIDS 25 |
288 | #define MAX_NUM_MISSILES 6 | 287 | #define MAX_NUM_MISSILES 6 |
289 | #define MAX_LEVEL MAX_NUM_ASTEROIDS | ||
290 | #define NUM_STARS 50 | 288 | #define NUM_STARS 50 |
291 | #define NUM_TRAIL_POINTS 70 | 289 | #define NUM_TRAIL_POINTS 70 |
292 | #define NUM_ROTATIONS 16 | 290 | #define MAX_LEVEL MAX_NUM_ASTEROIDS |
293 | 291 | ||
294 | #define NUM_ASTEROID_VERTICES 10 | 292 | #define NUM_ASTEROID_VERTICES 10 |
295 | #define NUM_SHIP_VERTICES 4 | 293 | #define NUM_SHIP_VERTICES 4 |
296 | #define NUM_ENEMY_VERTICES 6 | 294 | #define NUM_ENEMY_VERTICES 8 |
297 | 295 | ||
298 | #define SPAWN_TIME 30 | 296 | #define SPAWN_TIME 30 |
299 | #define BLINK_TIME 10 | 297 | #define BLINK_TIME 10 |
300 | #define EXTRA_LIFE 250 | 298 | #define EXTRA_LIFE 250 |
301 | #define START_LIVES 3 | 299 | #define START_LIVES 3 |
302 | #define START_LEVEL 1 | ||
303 | #define MISSILE_SURVIVAL_LENGTH 40 | 300 | #define MISSILE_SURVIVAL_LENGTH 40 |
304 | 301 | ||
305 | #define ASTEROID_SPEED (RES/20) | 302 | #define ASTEROID_SPEED (RES/20) |
306 | #define SPACE_CHECK_SIZE 30*SCALE | 303 | #define SPACE_CHECK_SIZE 30*SCALE |
307 | 304 | ||
308 | #define LITTLE_SHIP 2 | 305 | #define LITTLE_SHIP 1 |
309 | #define BIG_SHIP 1 | 306 | #define BIG_SHIP 2 |
310 | #define ENEMY_BIG_PROBABILITY_START 10 | 307 | #define ENEMY_BIG_PROBABILITY_START 10 |
311 | #define ENEMY_APPEAR_PROBABILITY_START 35 | 308 | #define ENEMY_APPEAR_PROBABILITY_START 35 |
312 | #define ENEMY_APPEAR_TIMING_START 1800 | 309 | #define ENEMY_APPEAR_TIMING_START 600 |
313 | #define ENEMY_SPEED 4 | 310 | #define ENEMY_SPEED 4 |
314 | #define ENEMY_MISSILE_SURVIVAL_LENGTH (RES/2) | 311 | #define ENEMY_MISSILE_SURVIVAL_LENGTH (RES/2) |
312 | #if (LARGE_LCD) | ||
313 | #define SIZE_ENEMY_COLLISION 7*SCALE | ||
314 | #else | ||
315 | #define SIZE_ENEMY_COLLISION 5*SCALE | 315 | #define SIZE_ENEMY_COLLISION 5*SCALE |
316 | #endif | ||
316 | 317 | ||
317 | #define SIN_COS_SCALE 10000 | 318 | #define SIN_COS_SCALE 10000 |
318 | 319 | ||
@@ -344,15 +345,10 @@ CONFIG_KEYPAD == MROBE500_PAD | |||
344 | #endif | 345 | #endif |
345 | 346 | ||
346 | 347 | ||
347 | #define SCALED_WIDTH (LCD_WIDTH*SCALE) | 348 | #define SCALED_WIDTH (LCD_WIDTH*SCALE) |
348 | #define SCALED_HEIGHT (LCD_HEIGHT*SCALE) | 349 | #define SCALED_HEIGHT (LCD_HEIGHT*SCALE) |
349 | #define CENTER_LCD_X (LCD_WIDTH/2) | 350 | #define CENTER_LCD_X (LCD_WIDTH/2) |
350 | #define CENTER_LCD_Y (LCD_HEIGHT/2) | 351 | #define CENTER_LCD_Y (LCD_HEIGHT/2) |
351 | |||
352 | #define SHIP_EXPLOSION_COLOUR 1 | ||
353 | #define ASTEROID_EXPLOSION_COLOUR 2 | ||
354 | #define ENEMY_EXPLOSION_COLOUR 3 | ||
355 | #define THRUST_COLOUR 4 | ||
356 | 352 | ||
357 | #ifdef HAVE_LCD_COLOR | 353 | #ifdef HAVE_LCD_COLOR |
358 | #define ASTEROID_R 230 | 354 | #define ASTEROID_R 230 |
@@ -385,7 +381,7 @@ CONFIG_KEYPAD == MROBE500_PAD | |||
385 | #define HIGH_SCORE PLUGIN_GAMES_DIR "/spacerocks.score" | 381 | #define HIGH_SCORE PLUGIN_GAMES_DIR "/spacerocks.score" |
386 | #define NUM_SCORES 5 | 382 | #define NUM_SCORES 5 |
387 | 383 | ||
388 | struct highscore highscores[NUM_SCORES]; | 384 | static struct highscore highscores[NUM_SCORES]; |
389 | 385 | ||
390 | /* The array of points that make up an asteroid */ | 386 | /* The array of points that make up an asteroid */ |
391 | static const short asteroid_one[NUM_ASTEROID_VERTICES*2] = | 387 | static const short asteroid_one[NUM_ASTEROID_VERTICES*2] = |
@@ -432,7 +428,7 @@ static const short asteroid_three[NUM_ASTEROID_VERTICES*2] = | |||
432 | -10, -8, | 428 | -10, -8, |
433 | }; | 429 | }; |
434 | 430 | ||
435 | /* The array od points the make up the ship */ | 431 | /* The array of points the make up the ship */ |
436 | static const short ship_vertices[NUM_SHIP_VERTICES*2] = | 432 | static const short ship_vertices[NUM_SHIP_VERTICES*2] = |
437 | { | 433 | { |
438 | #if (LARGE_LCD) | 434 | #if (LARGE_LCD) |
@@ -456,6 +452,8 @@ static const short enemy_vertices[NUM_ENEMY_VERTICES*2] = | |||
456 | -4, 4, | 452 | -4, 4, |
457 | 4, 4, | 453 | 4, 4, |
458 | 8, 0, | 454 | 8, 0, |
455 | -8, 0, | ||
456 | 8, 0, | ||
459 | 4, -4, | 457 | 4, -4, |
460 | -4, -4, | 458 | -4, -4, |
461 | #else | 459 | #else |
@@ -463,6 +461,8 @@ static const short enemy_vertices[NUM_ENEMY_VERTICES*2] = | |||
463 | -2, 2, | 461 | -2, 2, |
464 | 2, 2, | 462 | 2, 2, |
465 | 5, 0, | 463 | 5, 0, |
464 | -5, 0, | ||
465 | 5, 0, | ||
466 | 2, -2, | 466 | 2, -2, |
467 | -2, -2, | 467 | -2, -2, |
468 | #endif | 468 | #endif |
@@ -471,16 +471,24 @@ static const short enemy_vertices[NUM_ENEMY_VERTICES*2] = | |||
471 | enum asteroid_type | 471 | enum asteroid_type |
472 | { | 472 | { |
473 | #if (LARGE_LCD) | 473 | #if (LARGE_LCD) |
474 | SMALL = 2, | 474 | SMALL = 2, |
475 | MEDIUM = 4, | 475 | MEDIUM = 4, |
476 | LARGE = 6, | 476 | LARGE = 6, |
477 | #else | 477 | #else |
478 | SMALL = 1, | 478 | SMALL = 1, |
479 | MEDIUM = 2, | 479 | MEDIUM = 2, |
480 | LARGE = 3, | 480 | LARGE = 3, |
481 | #endif | 481 | #endif |
482 | }; | 482 | }; |
483 | 483 | ||
484 | enum explosion_type | ||
485 | { | ||
486 | EXPLOSION_SHIP, | ||
487 | EXPLOSION_ASTEROID, | ||
488 | EXPLOSION_ENEMY, | ||
489 | EXPLOSION_THRUST, | ||
490 | }; | ||
491 | |||
484 | enum game_state | 492 | enum game_state |
485 | { | 493 | { |
486 | GAME_OVER, | 494 | GAME_OVER, |
@@ -538,7 +546,7 @@ struct Enemy | |||
538 | struct Point position; | 546 | struct Point position; |
539 | bool exists; | 547 | bool exists; |
540 | int explode_countdown; | 548 | int explode_countdown; |
541 | long last_time_appeared; | 549 | int appear_countdown; |
542 | short size_probability; | 550 | short size_probability; |
543 | short appear_probability; | 551 | short appear_probability; |
544 | short appear_timing; | 552 | short appear_timing; |
@@ -570,197 +578,160 @@ static struct Enemy enemy; | |||
570 | static struct Point lives_points[NUM_SHIP_VERTICES]; | 578 | static struct Point lives_points[NUM_SHIP_VERTICES]; |
571 | static struct TrailPoint trail_points[NUM_TRAIL_POINTS]; | 579 | static struct TrailPoint trail_points[NUM_TRAIL_POINTS]; |
572 | 580 | ||
573 | void draw_and_move_asteroids(void); | 581 | /************************************************* |
574 | void initialise_game(int nStartNum); | 582 | ** Handle polygon and point |
575 | 583 | *************************************************/ | |
576 | bool is_asteroid_near_ship(struct Asteroid* asteroid); | ||
577 | bool is_point_within_asteroid(struct Asteroid* asteroid, struct Point* point); | ||
578 | |||
579 | void initialise_asteroid(struct Asteroid* asteroid, enum asteroid_type eType); | ||
580 | void draw_polygon(struct Point* vertices, int px, int py, int num_vertices); | ||
581 | void rotate_asteroid(struct Asteroid* asteroid); | ||
582 | void create_asteroid(enum asteroid_type type, int x, int y); | ||
583 | void create_stars(void); | ||
584 | 584 | ||
585 | void initialise_ship(void); | 585 | /* Check if point is in a polygon */ |
586 | void draw_and_move_ship(void); | 586 | static bool is_point_in_polygon(struct Point* vertices, int num_vertices, |
587 | void rotate_ship(int c, int s); | 587 | int x, int y) |
588 | void thrust_ship(void); | 588 | { |
589 | struct Point* pi; | ||
590 | struct Point* pj; | ||
591 | int n; | ||
592 | bool c = false; | ||
589 | 593 | ||
590 | void initialise_missile(struct Missile* missile); | 594 | if (x < -SCALED_WIDTH/2) x += SCALED_WIDTH; |
591 | void draw_and_move_missiles(void); | 595 | else if (x > SCALED_WIDTH/2) x -= SCALED_WIDTH; |
592 | void fire_missile(void); | 596 | if (y < -SCALED_HEIGHT/2) y += SCALED_HEIGHT; |
597 | else if (y > SCALED_HEIGHT/2) y -= SCALED_HEIGHT; | ||
593 | 598 | ||
594 | void animate_and_draw_explosion(struct Point* point, int num_points, int xoffset, int yoffset); | 599 | pi = vertices; |
595 | void initialise_explosion(struct Point* point, int num_points); | 600 | pj = vertices + num_vertices-1; |
596 | 601 | ||
597 | void move_point(struct Point* point); | 602 | n = num_vertices; |
598 | void hyperspace(void); | 603 | while (n--) |
599 | void check_collisions(void); | 604 | { |
600 | void initialise_enemy(void); | 605 | if ((((pi->y <= y) && (y < pj->y)) || ((pj->y <= y) && (y < pi->y))) && |
601 | void draw_and_move_enemy(void); | 606 | (x < (pj->x - pi->x) * (y - pi->y) / (pj->y - pi->y) + pi->x)) |
602 | void draw_lives(void); | 607 | c = !c; |
603 | void drawstars(void); | ||
604 | bool is_ship_within_asteroid(struct Asteroid* asteroid); | ||
605 | 608 | ||
609 | pj = pi; | ||
610 | pi++; | ||
611 | } | ||
606 | 612 | ||
607 | void init(void) | 613 | return c; |
608 | { | ||
609 | enemy.appear_probability = ENEMY_APPEAR_PROBABILITY_START; | ||
610 | enemy.appear_timing = ENEMY_APPEAR_TIMING_START; | ||
611 | enemy.size_probability = ENEMY_BIG_PROBABILITY_START; | ||
612 | current_level = START_LEVEL; | ||
613 | num_lives = START_LIVES; | ||
614 | extra_life = EXTRA_LIFE; | ||
615 | current_score = 0; | ||
616 | initialise_ship(); | ||
617 | initialise_game(current_level); | ||
618 | show_level_timeout = SHOW_LEVEL_TIME; | ||
619 | game_state = PLAY_MODE; | ||
620 | } | 614 | } |
621 | 615 | ||
622 | static bool spacerocks_help(void) | 616 | /* Check if point is within a rectangle */ |
617 | static bool is_point_within_rectangle(struct Point* rect, struct Point* p, | ||
618 | int size) | ||
623 | { | 619 | { |
624 | static char *help_text[] = { | 620 | int dx = p->x - rect->x; |
625 | "Spacerocks", "", "Aim", "", "The", "goal", "of", "the", "game", "is", | 621 | int dy = p->y - rect->y; |
626 | "to", "blow", "up", "the", "asteroids", "and", "avoid", "being", "hit", "by", | 622 | #if SHOW_COL |
627 | "them.", "Also", "you'd", "better", "watch", "out", "for", "the", "UFOs!" | 623 | rb->lcd_drawrect((rect->x - size)/SCALE, (rect->y - size)/SCALE, |
628 | }; | 624 | size*2/SCALE, size*2/SCALE); |
629 | static struct style_text formation[]={ | ||
630 | { 0, TEXT_CENTER|TEXT_UNDERLINE }, | ||
631 | { 2, C_RED }, | ||
632 | { -1, 0 } | ||
633 | }; | ||
634 | int button; | ||
635 | |||
636 | rb->lcd_setfont(FONT_UI); | ||
637 | #ifdef HAVE_LCD_COLOR | ||
638 | rb->lcd_set_background(LCD_BLACK); | ||
639 | rb->lcd_set_foreground(LCD_WHITE); | ||
640 | #endif | 625 | #endif |
641 | if (display_text(ARRAYLEN(help_text), help_text, formation, NULL) | 626 | if (dx < -SCALED_WIDTH/2) dx += SCALED_WIDTH; |
642 | ==PLUGIN_USB_CONNECTED) | 627 | else if (dx > SCALED_WIDTH/2) dx -= SCALED_WIDTH; |
643 | return true; | 628 | if (dy < -SCALED_HEIGHT/2) dy += SCALED_HEIGHT; |
644 | do { | 629 | else if (dy > SCALED_HEIGHT/2) dy -= SCALED_HEIGHT; |
645 | button = rb->button_get(true); | 630 | return (dx > -size && dx < size && dy > -size && dy < size); |
646 | if (button == SYS_USB_CONNECTED) | ||
647 | return true; | ||
648 | } while( ( button == BUTTON_NONE ) | ||
649 | || ( button & (BUTTON_REL|BUTTON_REPEAT) ) ); | ||
650 | rb->lcd_setfont(FONT_SYSFIXED); | ||
651 | |||
652 | return false; | ||
653 | } | 631 | } |
654 | 632 | ||
655 | static bool _ingame; | 633 | /* Rotate polygon */ |
656 | static int spacerocks_menu_cb(int action, const struct menu_item_ex *this_item) | 634 | static void rotate_polygon(struct Point* vertices, int num_vertices, |
635 | int cos, int sin) | ||
657 | { | 636 | { |
658 | if(action == ACTION_REQUEST_MENUITEM | 637 | struct Point* point; |
659 | && !_ingame && ((intptr_t)this_item)==0) | 638 | int n; |
660 | return ACTION_EXIT_MENUITEM; | 639 | long temp_x, temp_y; |
661 | return action; | ||
662 | } | ||
663 | |||
664 | static int spacerocks_menu(bool ingame) | ||
665 | { | ||
666 | int choice = 0; | ||
667 | |||
668 | _ingame = ingame; | ||
669 | |||
670 | MENUITEM_STRINGLIST(main_menu, "Spacerocks Menu", spacerocks_menu_cb, | ||
671 | "Resume Game", "Start New Game", | ||
672 | "Help", "High Scores", | ||
673 | "Playback Control", "Quit"); | ||
674 | rb->button_clear_queue(); | ||
675 | 640 | ||
676 | while (1) | 641 | point = vertices; |
642 | n = num_vertices; | ||
643 | while (n--) | ||
677 | { | 644 | { |
678 | switch (rb->do_menu(&main_menu, &choice, NULL, false)) | 645 | temp_x = point->x; |
679 | { | 646 | temp_y = point->y; |
680 | case 0: | 647 | point->x = temp_x*cos/SIN_COS_SCALE - temp_y*sin/SIN_COS_SCALE; |
681 | return 0; | 648 | point->y = temp_y*cos/SIN_COS_SCALE + temp_x*sin/SIN_COS_SCALE; |
682 | case 1: | 649 | point++; |
683 | init(); | ||
684 | return 0; | ||
685 | case 2: | ||
686 | if(spacerocks_help()) | ||
687 | return 1; | ||
688 | break; | ||
689 | case 3: | ||
690 | highscore_show(NUM_SCORES, highscores, NUM_SCORES, true); | ||
691 | break; | ||
692 | case 4: | ||
693 | playback_control(NULL); | ||
694 | break; | ||
695 | case 5: | ||
696 | return 1; | ||
697 | case MENU_ATTACHED_USB: | ||
698 | return 1; | ||
699 | default: | ||
700 | break; | ||
701 | } | ||
702 | } | 650 | } |
703 | } | 651 | } |
704 | 652 | ||
705 | bool point_in_poly(struct Point* point, int num_vertices, int x, int y) | 653 | /* Draw polygon */ |
654 | static void draw_polygon(struct Point* vertices, int num_vertices, | ||
655 | int px, int py) | ||
706 | { | 656 | { |
707 | struct Point* pi; | 657 | int n, new_x, new_y, old_x, old_y; |
708 | struct Point* pj; | 658 | struct Point *p; |
709 | int n; | 659 | bool bDrawAll = (px < WRAP_GAP || SCALED_WIDTH - px < WRAP_GAP || |
710 | bool c = false; | 660 | py < WRAP_GAP || SCALED_HEIGHT - py < WRAP_GAP); |
711 | |||
712 | pi = point; | ||
713 | pj = point + num_vertices-1; | ||
714 | 661 | ||
662 | p = vertices + num_vertices - 1; | ||
663 | old_x = (p->x + px)/SCALE; | ||
664 | old_y = (p->y + py)/SCALE; | ||
665 | p = vertices; | ||
715 | n = num_vertices; | 666 | n = num_vertices; |
716 | while(n--) | 667 | while(n--) |
717 | { | 668 | { |
718 | if((((pi->y <= y) && (y < pj->y)) || ((pj->y <= y) && (y < pi->y))) && | 669 | new_x = (p->x + px)/SCALE; |
719 | (x < (pj->x - pi->x) * (y - pi->y) / (pj->y - pi->y) + pi->x)) | 670 | new_y = (p->y + py)/SCALE; |
720 | c = !c; | ||
721 | 671 | ||
722 | pj = pi; | 672 | rb->lcd_drawline(old_x, old_y, new_x, new_y); |
723 | pi++; | ||
724 | } | ||
725 | 673 | ||
726 | return c; | 674 | if(bDrawAll) |
675 | { | ||
676 | rb->lcd_drawline(old_x - LCD_WIDTH, old_y, new_x - LCD_WIDTH, new_y); | ||
677 | rb->lcd_drawline(old_x + LCD_WIDTH, old_y, new_x + LCD_WIDTH, new_y); | ||
678 | rb->lcd_drawline(old_x - LCD_WIDTH, old_y + LCD_HEIGHT, | ||
679 | new_x - LCD_WIDTH, new_y + LCD_HEIGHT); | ||
680 | rb->lcd_drawline(old_x + LCD_WIDTH, old_y + LCD_HEIGHT, | ||
681 | new_x + LCD_WIDTH, new_y + LCD_HEIGHT); | ||
682 | |||
683 | rb->lcd_drawline(old_x, old_y - LCD_HEIGHT, new_x, new_y - LCD_HEIGHT); | ||
684 | rb->lcd_drawline(old_x, old_y + LCD_HEIGHT, new_x, new_y + LCD_HEIGHT); | ||
685 | rb->lcd_drawline(old_x - LCD_WIDTH, old_y - LCD_HEIGHT, | ||
686 | new_x - LCD_WIDTH, new_y - LCD_HEIGHT); | ||
687 | rb->lcd_drawline(old_x + LCD_WIDTH, old_y - LCD_HEIGHT, | ||
688 | new_x + LCD_WIDTH, new_y - LCD_HEIGHT); | ||
689 | } | ||
690 | old_x = new_x; | ||
691 | old_y = new_y; | ||
692 | p++; | ||
693 | } | ||
727 | } | 694 | } |
728 | 695 | ||
729 | void move_point(struct Point* point) | 696 | static void move_point(struct Point* point) |
730 | { | 697 | { |
731 | point->x += point->dx; | 698 | point->x += point->dx; |
732 | point->y += point->dy; | 699 | point->y += point->dy; |
733 | 700 | ||
734 | /*check bounds on the x-axis:*/ | 701 | /* Check bounds on the x-axis: */ |
735 | point->x %= SCALED_WIDTH; | 702 | point->x %= SCALED_WIDTH; |
736 | if(point->x < 0) | 703 | if (point->x < 0) |
737 | point->x += SCALED_WIDTH; | 704 | point->x += SCALED_WIDTH; |
738 | 705 | ||
739 | /*Check bounds on the y-axis:*/ | 706 | /* Check bounds on the y-axis: */ |
740 | point->y %= SCALED_HEIGHT; | 707 | point->y %= SCALED_HEIGHT; |
741 | if(point->y < 0) | 708 | if (point->y < 0) |
742 | point->y += SCALED_HEIGHT; | 709 | point->y += SCALED_HEIGHT; |
743 | } | 710 | } |
744 | 711 | ||
745 | void create_ship_trail(struct TrailPoint* tpoint) | 712 | /************************************************* |
713 | ** Handle trail blaiz. | ||
714 | *************************************************/ | ||
715 | |||
716 | static void create_ship_trail(struct TrailPoint* tpoint) | ||
746 | { | 717 | { |
747 | tpoint->position.dx = -( ship.vertices[0].x - ship.vertices[2].x )/10; | 718 | tpoint->position.dx = -( ship.vertices[0].x - ship.vertices[2].x )/10; |
748 | tpoint->position.dy = -( ship.vertices[0].y - ship.vertices[2].y )/10; | 719 | tpoint->position.dy = -( ship.vertices[0].y - ship.vertices[2].y )/10; |
749 | } | 720 | } |
750 | 721 | ||
751 | void create_explosion_trail(struct TrailPoint* tpoint) | 722 | static void create_explosion_trail(struct TrailPoint* tpoint) |
752 | { | 723 | { |
753 | tpoint->position.dx = (rb->rand()%5001)-2500; | 724 | tpoint->position.dx = (rb->rand()%5001)-2500; |
754 | tpoint->position.dy = (rb->rand()%5001)-2500; | 725 | tpoint->position.dy = (rb->rand()%5001)-2500; |
755 | } | 726 | } |
756 | 727 | ||
757 | void create_trail_blaze(int colour, struct Point* position) | 728 | static void create_trail_blaze(int colour, struct Point* position) |
758 | { | 729 | { |
759 | int numtoadd; | 730 | int numtoadd; |
760 | struct TrailPoint* tpoint; | 731 | struct TrailPoint* tpoint; |
761 | int n; | 732 | int n; |
762 | 733 | ||
763 | if(colour != SHIP_EXPLOSION_COLOUR) | 734 | if (colour != EXPLOSION_SHIP) |
764 | { | 735 | { |
765 | numtoadd = NUM_TRAIL_POINTS/5; | 736 | numtoadd = NUM_TRAIL_POINTS/5; |
766 | } | 737 | } |
@@ -773,25 +744,22 @@ void create_trail_blaze(int colour, struct Point* position) | |||
773 | times */ | 744 | times */ |
774 | tpoint = trail_points; | 745 | tpoint = trail_points; |
775 | n = NUM_TRAIL_POINTS; | 746 | n = NUM_TRAIL_POINTS; |
776 | while(n-- && numtoadd) | 747 | while (n-- && numtoadd) |
777 | { | 748 | { |
778 | /* find a space in the array of trail_points that is NULL or DEAD or | 749 | /* find a space in the array of trail_points that is NULL or DEAD or |
779 | whatever and place this one here. */ | 750 | whatever and place this one here. */ |
780 | if(tpoint->alive <= 0) | 751 | if (!tpoint->alive) |
781 | { | 752 | { |
782 | numtoadd--; | 753 | numtoadd--; |
783 | /* take a random x point anywhere between bottom two points of ship. */ | 754 | /* take a random point near the position. */ |
784 | /* ship.position.x; */ | 755 | tpoint->position.x = (rb->rand()%18000)-9000 + position->x; |
785 | tpoint->position.x = (ship.vertices[2].x + (rb->rand()%18000)-9000) | 756 | tpoint->position.y = (rb->rand()%18000)-9000 + position->y; |
786 | + position->x; | ||
787 | tpoint->position.y = (ship.vertices[2].y + (rb->rand()%18000)-9000) | ||
788 | + position->y; | ||
789 | 757 | ||
790 | switch(colour) | 758 | switch(colour) |
791 | { | 759 | { |
792 | case SHIP_EXPLOSION_COLOUR: | 760 | case EXPLOSION_SHIP: |
793 | create_explosion_trail(tpoint); | 761 | create_explosion_trail(tpoint); |
794 | tpoint->alive = 510; | 762 | tpoint->alive = 51; |
795 | #ifdef HAVE_LCD_COLOR | 763 | #ifdef HAVE_LCD_COLOR |
796 | tpoint->r = SHIP_R; | 764 | tpoint->r = SHIP_R; |
797 | tpoint->g = SHIP_G; | 765 | tpoint->g = SHIP_G; |
@@ -799,9 +767,9 @@ void create_trail_blaze(int colour, struct Point* position) | |||
799 | tpoint->dec = 2; | 767 | tpoint->dec = 2; |
800 | #endif | 768 | #endif |
801 | break; | 769 | break; |
802 | case ASTEROID_EXPLOSION_COLOUR: | 770 | case EXPLOSION_ASTEROID: |
803 | create_explosion_trail(tpoint); | 771 | create_explosion_trail(tpoint); |
804 | tpoint->alive = 510; | 772 | tpoint->alive = 51; |
805 | #ifdef HAVE_LCD_COLOR | 773 | #ifdef HAVE_LCD_COLOR |
806 | tpoint->r = ASTEROID_R; | 774 | tpoint->r = ASTEROID_R; |
807 | tpoint->g = ASTEROID_G; | 775 | tpoint->g = ASTEROID_G; |
@@ -809,9 +777,9 @@ void create_trail_blaze(int colour, struct Point* position) | |||
809 | tpoint->dec = 2; | 777 | tpoint->dec = 2; |
810 | #endif | 778 | #endif |
811 | break; | 779 | break; |
812 | case ENEMY_EXPLOSION_COLOUR: | 780 | case EXPLOSION_ENEMY: |
813 | create_explosion_trail(tpoint); | 781 | create_explosion_trail(tpoint); |
814 | tpoint->alive = 510; | 782 | tpoint->alive = 51; |
815 | #ifdef HAVE_LCD_COLOR | 783 | #ifdef HAVE_LCD_COLOR |
816 | tpoint->r = ENEMY_R; | 784 | tpoint->r = ENEMY_R; |
817 | tpoint->g = ENEMY_G; | 785 | tpoint->g = ENEMY_G; |
@@ -819,9 +787,9 @@ void create_trail_blaze(int colour, struct Point* position) | |||
819 | tpoint->dec = 2; | 787 | tpoint->dec = 2; |
820 | #endif | 788 | #endif |
821 | break; | 789 | break; |
822 | case THRUST_COLOUR: | 790 | case EXPLOSION_THRUST: |
823 | create_ship_trail(tpoint); | 791 | create_ship_trail(tpoint); |
824 | tpoint->alive = 175; | 792 | tpoint->alive = 17; |
825 | #ifdef HAVE_LCD_COLOR | 793 | #ifdef HAVE_LCD_COLOR |
826 | tpoint->r = THRUST_R; | 794 | tpoint->r = THRUST_R; |
827 | tpoint->g = THRUST_G; | 795 | tpoint->g = THRUST_G; |
@@ -840,7 +808,7 @@ void create_trail_blaze(int colour, struct Point* position) | |||
840 | } | 808 | } |
841 | } | 809 | } |
842 | 810 | ||
843 | void draw_trail_blaze(void) | 811 | static void draw_and_move_trail_blaze(void) |
844 | { | 812 | { |
845 | struct TrailPoint* tpoint; | 813 | struct TrailPoint* tpoint; |
846 | int n; | 814 | int n; |
@@ -851,125 +819,429 @@ void draw_trail_blaze(void) | |||
851 | 819 | ||
852 | tpoint = trail_points; | 820 | tpoint = trail_points; |
853 | n = NUM_TRAIL_POINTS; | 821 | n = NUM_TRAIL_POINTS; |
854 | while(n--) | 822 | while (n--) |
855 | { | 823 | { |
856 | if(tpoint->alive) | 824 | if (tpoint->alive) |
857 | { | 825 | { |
858 | if(game_state != PAUSE_MODE) | 826 | if (game_state != PAUSE_MODE) |
859 | { | 827 | { |
860 | tpoint->alive -= 10; | 828 | tpoint->alive--; |
861 | move_point(&(tpoint->position)); | 829 | move_point(&(tpoint->position)); |
862 | } | ||
863 | #ifdef HAVE_LCD_COLOR | 830 | #ifdef HAVE_LCD_COLOR |
864 | /* intensity = tpoint->alive/2; */ | 831 | /* intensity = tpoint->alive/2; */ |
865 | if(tpoint->r >= tpoint->dec) tpoint->r -= tpoint->dec; | 832 | if (tpoint->r >= tpoint->dec) tpoint->r -= tpoint->dec; |
866 | if(tpoint->g >= tpoint->dec) tpoint->g -= tpoint->dec; | 833 | if (tpoint->g >= tpoint->dec) tpoint->g -= tpoint->dec; |
867 | if(tpoint->b >= tpoint->dec) tpoint->b -= tpoint->dec; | 834 | if (tpoint->b >= tpoint->dec) tpoint->b -= tpoint->dec; |
868 | SET_FG(LCD_RGBPACK(tpoint->r, tpoint->g, tpoint->b)); | ||
869 | #endif | 835 | #endif |
836 | } | ||
837 | SET_FG(LCD_RGBPACK(tpoint->r, tpoint->g, tpoint->b)); | ||
870 | rb->lcd_drawpixel(tpoint->position.x/SCALE, tpoint->position.y/SCALE); | 838 | rb->lcd_drawpixel(tpoint->position.x/SCALE, tpoint->position.y/SCALE); |
871 | } | 839 | } |
872 | tpoint++; | 840 | tpoint++; |
873 | } | 841 | } |
874 | } | 842 | } |
875 | 843 | ||
876 | /*Check if point is within a rectangle*/ | 844 | /************************************************* |
877 | bool is_point_within_rectangle(struct Point* rect, struct Point* p, int size) | 845 | ** Handle asteroid. |
846 | *************************************************/ | ||
847 | |||
848 | static void rotate_asteroid(struct Asteroid* asteroid) | ||
878 | { | 849 | { |
879 | #if SHOW_COL | 850 | rotate_polygon(asteroid->vertices, NUM_ASTEROID_VERTICES, |
880 | int aTLx = rect->x - size; | 851 | asteroid->speed_cos, asteroid->speed_sin); |
881 | int aTLy = rect->y - size; | ||
882 | int aBRx = rect->x + size; | ||
883 | int aBRy = rect->y + size; | ||
884 | rb->lcd_hline( aTLx/SCALE, aBRx/SCALE, aTLy/SCALE); | ||
885 | rb->lcd_vline( aTLx/SCALE, aTLy/SCALE, aBRy/SCALE); | ||
886 | rb->lcd_hline( aTLx/SCALE, aBRx/SCALE, aBRy/SCALE); | ||
887 | rb->lcd_vline( aBRx/SCALE, aBRy/SCALE, aTLy/SCALE); | ||
888 | return (p->x > aTLx && p->x < aBRx && p->y > aTLy && p->y < aBRy); | ||
889 | #else | ||
890 | return (p->x > rect->x - size && p->x < rect->x + size && | ||
891 | p->y > rect->y - size && p->y < rect->y + size); | ||
892 | #endif | ||
893 | } | 852 | } |
894 | 853 | ||
895 | /* Draw polygon */ | 854 | /* Initialise the passed Asteroid. |
896 | void draw_polygon(struct Point* vertices, int px, int py, int num_vertices) | 855 | * if position is NULL, place it at the random loacation |
856 | * where ship doesn't exist | ||
857 | */ | ||
858 | static void initialise_asteroid(struct Asteroid* asteroid, | ||
859 | enum asteroid_type type, struct Point *position) | ||
897 | { | 860 | { |
898 | int n, t1, t2, oldX, oldY; | 861 | const short *asteroid_vertices; |
899 | struct Point *p; | 862 | struct Point* point; |
900 | bool bDrawAll = px < WRAP_GAP || LCD_WIDTH - px < WRAP_GAP || | 863 | int n; |
901 | py < WRAP_GAP || LCD_HEIGHT - py < WRAP_GAP; | ||
902 | 864 | ||
903 | p = vertices + num_vertices - 1; | 865 | asteroid->exists = true; |
904 | oldX = p->x/SCALE + px; | 866 | asteroid->type = type; |
905 | oldY = p->y/SCALE + py; | 867 | asteroid->explode_countdown = 0; |
906 | p = vertices; | 868 | |
907 | n = num_vertices; | 869 | /* Set the radius of the asteroid: */ |
908 | while(n--) | 870 | asteroid->radius = (int)type*SCALE*3; |
871 | |||
872 | /* shall we move Clockwise and Fast */ | ||
873 | n = rb->rand()%100; | ||
874 | if (n < 25) | ||
909 | { | 875 | { |
910 | t1 = p->x/SCALE + px; | 876 | asteroid->speed_cos = FAST_ROT_CW_COS; |
911 | t2 = p->y/SCALE + py; | 877 | asteroid->speed_sin = FAST_ROT_CW_SIN; |
878 | } | ||
879 | else if (n < 50) | ||
880 | { | ||
881 | asteroid->speed_cos = FAST_ROT_ACW_COS; | ||
882 | asteroid->speed_sin = FAST_ROT_ACW_SIN; | ||
883 | } | ||
884 | else if (n < 75) | ||
885 | { | ||
886 | asteroid->speed_cos = SLOW_ROT_ACW_COS; | ||
887 | asteroid->speed_sin = SLOW_ROT_ACW_SIN; | ||
888 | } | ||
889 | else | ||
890 | { | ||
891 | asteroid->speed_cos = SLOW_ROT_CW_COS; | ||
892 | asteroid->speed_sin = SLOW_ROT_CW_SIN; | ||
893 | } | ||
912 | 894 | ||
913 | rb->lcd_drawline(oldX, oldY, t1, t2); | 895 | n = rb->rand()%99; |
896 | if (n < 33) | ||
897 | asteroid_vertices = asteroid_one; | ||
898 | else if (n < 66) | ||
899 | asteroid_vertices = asteroid_two; | ||
900 | else | ||
901 | asteroid_vertices = asteroid_three; | ||
914 | 902 | ||
915 | if(bDrawAll) | 903 | point = asteroid->vertices; |
904 | for(n = 0; n < NUM_ASTEROID_VERTICES*2; n += 2) | ||
905 | { | ||
906 | point->x = asteroid_vertices[n]; | ||
907 | point->y = asteroid_vertices[n+1]; | ||
908 | point->x *= asteroid->radius/20; | ||
909 | point->y *= asteroid->radius/20; | ||
910 | point++; | ||
911 | } | ||
912 | |||
913 | if (!position) | ||
914 | { | ||
915 | do { | ||
916 | /* Set the position randomly: */ | ||
917 | asteroid->position.x = (rb->rand()%SCALED_WIDTH); | ||
918 | asteroid->position.y = (rb->rand()%SCALED_HEIGHT); | ||
919 | } while (is_point_within_rectangle(&ship.position, &asteroid->position, | ||
920 | SPACE_CHECK_SIZE)); | ||
921 | } | ||
922 | else | ||
923 | { | ||
924 | asteroid->position.x = position->x; | ||
925 | asteroid->position.y = position->y; | ||
926 | } | ||
927 | |||
928 | do { | ||
929 | asteroid->position.dx = (rb->rand()%ASTEROID_SPEED)-ASTEROID_SPEED/2; | ||
930 | } while (asteroid->position.dx == 0); | ||
931 | |||
932 | do { | ||
933 | asteroid->position.dy = (rb->rand()%ASTEROID_SPEED)-ASTEROID_SPEED/2; | ||
934 | } while (asteroid->position.dy == 0); | ||
935 | |||
936 | asteroid->position.dx *= SCALE/10; | ||
937 | asteroid->position.dy *= SCALE/10; | ||
938 | |||
939 | /* Now rotate the asteroid a bit, so they all look a bit different */ | ||
940 | for(n = (rb->rand()%30)+2; n--; ) | ||
941 | rotate_asteroid(asteroid); | ||
942 | |||
943 | /* great, we've created an asteroid, don't forget to increment the total: */ | ||
944 | asteroid_count++; | ||
945 | } | ||
946 | |||
947 | /* | ||
948 | * Creates a new asteroid of the given 4type (size) and at the given location. | ||
949 | */ | ||
950 | static void create_asteroid(enum asteroid_type type, struct Point *position) | ||
951 | { | ||
952 | struct Asteroid* asteroid; | ||
953 | int n; | ||
954 | |||
955 | asteroid = asteroids_array; | ||
956 | n = MAX_NUM_ASTEROIDS; | ||
957 | while (n--) | ||
958 | { | ||
959 | if (!asteroid->exists && !asteroid->explode_countdown) | ||
916 | { | 960 | { |
917 | rb->lcd_drawline(oldX - LCD_WIDTH, oldY, t1 - LCD_WIDTH, t2); | 961 | initialise_asteroid(asteroid, type, position); |
918 | rb->lcd_drawline(oldX + LCD_WIDTH, oldY, t1 + LCD_WIDTH, t2); | 962 | break; |
919 | rb->lcd_drawline(oldX - LCD_WIDTH, oldY + LCD_HEIGHT, | ||
920 | t1 - LCD_WIDTH, t2 + LCD_HEIGHT); | ||
921 | rb->lcd_drawline(oldX + LCD_WIDTH, oldY + LCD_HEIGHT, | ||
922 | t1 + LCD_WIDTH, t2 + LCD_HEIGHT); | ||
923 | |||
924 | rb->lcd_drawline(oldX, oldY - LCD_HEIGHT, t1, t2 - LCD_HEIGHT); | ||
925 | rb->lcd_drawline(oldX, oldY + LCD_HEIGHT, t1, t2 + LCD_HEIGHT); | ||
926 | rb->lcd_drawline(oldX - LCD_WIDTH, oldY - LCD_HEIGHT, | ||
927 | t1 - LCD_WIDTH, t2 - LCD_HEIGHT); | ||
928 | rb->lcd_drawline(oldX + LCD_WIDTH, oldY - LCD_HEIGHT, | ||
929 | t1 + LCD_WIDTH, t2 - LCD_HEIGHT); | ||
930 | } | 963 | } |
931 | oldX = t1; | 964 | asteroid++; |
932 | oldY = t2; | ||
933 | p++; | ||
934 | } | 965 | } |
935 | } | 966 | } |
936 | 967 | ||
937 | void animate_and_draw_explosion(struct Point* point, int num_points, | 968 | /* Draw and move all asteroids */ |
938 | int xoffset, int yoffset) | 969 | static void draw_and_move_asteroids(void) |
939 | { | 970 | { |
940 | int n = num_points; | 971 | struct Asteroid* asteroid; |
941 | while(n--) | 972 | int n; |
973 | |||
974 | SET_FG(COL_ASTEROID); | ||
975 | |||
976 | asteroid = asteroids_array; | ||
977 | n = MAX_NUM_ASTEROIDS; | ||
978 | while (n--) | ||
942 | { | 979 | { |
943 | if(game_state != PAUSE_MODE) | 980 | if (game_state != PAUSE_MODE) |
944 | { | 981 | { |
945 | point->x += point->dx; | 982 | if (asteroid->exists) |
946 | point->y += point->dy; | 983 | { |
984 | move_point(&asteroid->position); | ||
985 | rotate_asteroid(asteroid); | ||
986 | } | ||
987 | else if (asteroid->explode_countdown) | ||
988 | { | ||
989 | asteroid->explode_countdown--; | ||
990 | } | ||
947 | } | 991 | } |
948 | rb->lcd_fillrect( point->x/SCALE + xoffset, point->y/SCALE + yoffset, | 992 | if (asteroid->exists) |
949 | POINT_SIZE, POINT_SIZE ); | 993 | { |
994 | draw_polygon(asteroid->vertices, NUM_ASTEROID_VERTICES, | ||
995 | asteroid->position.x, asteroid->position.y); | ||
996 | } | ||
997 | asteroid++; | ||
998 | } | ||
999 | } | ||
1000 | |||
1001 | /************************************************* | ||
1002 | ** Handle ship. | ||
1003 | *************************************************/ | ||
1004 | |||
1005 | /* Initialise the ship */ | ||
1006 | static void initialise_ship(void) | ||
1007 | { | ||
1008 | struct Point* point; | ||
1009 | struct Point* lives_point; | ||
1010 | int n; | ||
1011 | |||
1012 | ship.position.x = CENTER_LCD_X * SCALE; | ||
1013 | ship.position.y = CENTER_LCD_Y * SCALE; | ||
1014 | ship.position.dx = 0; | ||
1015 | ship.position.dy = 0; | ||
1016 | ship.explode_countdown = 0; | ||
1017 | ship.spawn_time = SPAWN_TIME; | ||
1018 | ship.invulnerable = 1; | ||
1019 | |||
1020 | point = ship.vertices; | ||
1021 | lives_point = lives_points; | ||
1022 | for(n = 0; n < NUM_SHIP_VERTICES*2; n += 2) | ||
1023 | { | ||
1024 | point->x = ship_vertices[n]; | ||
1025 | point->y = ship_vertices[n+1]; | ||
1026 | point->x *= SCALE; | ||
1027 | point->y *= SCALE; | ||
1028 | /* grab a copy of the ships points for the lives display: */ | ||
1029 | lives_point->x = point->x; | ||
1030 | lives_point->y = point->y; | ||
1031 | |||
950 | point++; | 1032 | point++; |
1033 | lives_point++; | ||
1034 | } | ||
1035 | } | ||
1036 | |||
1037 | /* | ||
1038 | * Draws the ship, moves the ship and creates a new | ||
1039 | * one if it's finished exploding. | ||
1040 | */ | ||
1041 | static void draw_and_move_ship(void) | ||
1042 | { | ||
1043 | if (ship.invulnerable && | ||
1044 | (ship.spawn_time > BLINK_TIME || ship.spawn_time % 2 == 0)) | ||
1045 | { | ||
1046 | SET_FG(COL_INVULN); | ||
1047 | } | ||
1048 | else | ||
1049 | { | ||
1050 | SET_FG(COL_PLAYER); | ||
1051 | } | ||
1052 | |||
1053 | if (!ship.explode_countdown) | ||
1054 | { | ||
1055 | /* make sure ship is invulnerable until spawn time over */ | ||
1056 | if (game_state != PAUSE_MODE) | ||
1057 | { | ||
1058 | if (ship.spawn_time) | ||
1059 | { | ||
1060 | ship.spawn_time--; | ||
1061 | if (ship.spawn_time <= 0) | ||
1062 | { | ||
1063 | ship.invulnerable = 0; | ||
1064 | } | ||
1065 | } | ||
1066 | } | ||
1067 | if (!ship.waiting_for_space) | ||
1068 | { | ||
1069 | draw_polygon(ship.vertices, NUM_SHIP_VERTICES, | ||
1070 | ship.position.x, ship.position.y); | ||
1071 | if (game_state != PAUSE_MODE && game_state != GAME_OVER) | ||
1072 | { | ||
1073 | move_point(&ship.position); | ||
1074 | } | ||
1075 | } | ||
1076 | } | ||
1077 | else | ||
1078 | { | ||
1079 | if (game_state != PAUSE_MODE) | ||
1080 | { | ||
1081 | ship.explode_countdown--; | ||
1082 | if (!ship.explode_countdown) | ||
1083 | { | ||
1084 | num_lives--; | ||
1085 | if (!num_lives) | ||
1086 | { | ||
1087 | game_state = GAME_OVER; | ||
1088 | } | ||
1089 | else | ||
1090 | { | ||
1091 | initialise_ship(); | ||
1092 | ship.waiting_for_space = true; | ||
1093 | } | ||
1094 | } | ||
1095 | } | ||
1096 | } | ||
1097 | } | ||
1098 | |||
1099 | /* Rotate the ship using the passed sin & cos values */ | ||
1100 | static void rotate_ship(int cos, int sin) | ||
1101 | { | ||
1102 | if (!ship.waiting_for_space && !ship.explode_countdown) | ||
1103 | { | ||
1104 | rotate_polygon(ship.vertices, NUM_SHIP_VERTICES, cos, sin); | ||
951 | } | 1105 | } |
952 | } | 1106 | } |
953 | 1107 | ||
954 | /*stop movement of ship, 'cos that's what happens when you go into hyperspace.*/ | 1108 | static void thrust_ship(void) |
955 | void hyperspace(void) | ||
956 | { | 1109 | { |
957 | ship.position.dx = ship.position.dy = 0; | 1110 | if (!ship.waiting_for_space && !ship.explode_countdown) |
958 | ship.position.x = (rb->rand()%SCALED_WIDTH); | 1111 | { |
959 | ship.position.y = (rb->rand()%SCALED_HEIGHT); | 1112 | ship.position.dx += ( ship.vertices[0].x - ship.vertices[2].x )/20; |
1113 | ship.position.dy += ( ship.vertices[0].y - ship.vertices[2].y )/20; | ||
1114 | |||
1115 | /* if dx and dy are below a certain threshold, then set 'em to 0 | ||
1116 | but to do this we need to ascertain if the spacehip as moved on | ||
1117 | screen for more than a certain amount. */ | ||
1118 | |||
1119 | create_trail_blaze(EXPLOSION_THRUST, &ship.position); | ||
1120 | } | ||
960 | } | 1121 | } |
961 | 1122 | ||
962 | void initialise_enemy(void) | 1123 | /* stop movement of ship, 'cos that's what happens when you go into hyperspace. */ |
1124 | static void hyperspace(void) | ||
1125 | { | ||
1126 | if (!ship.waiting_for_space && !ship.explode_countdown) | ||
1127 | { | ||
1128 | ship.position.dx = ship.position.dy = 0; | ||
1129 | ship.position.x = (rb->rand()%SCALED_WIDTH); | ||
1130 | ship.position.y = (rb->rand()%SCALED_HEIGHT); | ||
1131 | } | ||
1132 | } | ||
1133 | |||
1134 | static void draw_lives(void) | ||
1135 | { | ||
1136 | int n; | ||
1137 | #if (LARGE_LCD) | ||
1138 | int px = (LCD_WIDTH-1 - 4)*SCALE; | ||
1139 | int py = (LCD_HEIGHT-1 - 6)*SCALE; | ||
1140 | #else | ||
1141 | int px = (LCD_WIDTH-1 - 3)*SCALE; | ||
1142 | int py = (LCD_HEIGHT-1 - 4)*SCALE; | ||
1143 | #endif | ||
1144 | |||
1145 | SET_FG(COL_PLAYER); | ||
1146 | |||
1147 | n = num_lives-1; | ||
1148 | while (n--) | ||
1149 | { | ||
1150 | draw_polygon(lives_points, NUM_SHIP_VERTICES, px, py); | ||
1151 | #if (LARGE_LCD) | ||
1152 | px -= 8*SCALE; | ||
1153 | #else | ||
1154 | px -= 6*SCALE; | ||
1155 | #endif | ||
1156 | } | ||
1157 | } | ||
1158 | |||
1159 | /* | ||
1160 | * missile | ||
1161 | */ | ||
1162 | |||
1163 | /* Initialise a missile */ | ||
1164 | static void initialise_missile(struct Missile* missile) | ||
1165 | { | ||
1166 | missile->position.x = ship.position.x + ship.vertices[0].x; | ||
1167 | missile->position.y = ship.position.y + ship.vertices[0].y; | ||
1168 | missile->position.dx = (ship.vertices[0].x - ship.vertices[2].x)/2; | ||
1169 | missile->position.dy = (ship.vertices[0].y - ship.vertices[2].y)/2; | ||
1170 | missile->survived = MISSILE_SURVIVAL_LENGTH; | ||
1171 | missile->oldpoint.x = missile->position.x; | ||
1172 | missile->oldpoint.y = missile->position.y; | ||
1173 | } | ||
1174 | |||
1175 | /* Fire the next missile */ | ||
1176 | static void fire_missile(void) | ||
1177 | { | ||
1178 | struct Missile* missile; | ||
1179 | int n; | ||
1180 | |||
1181 | if (!ship.explode_countdown && !ship.waiting_for_space) | ||
1182 | { | ||
1183 | missile = missiles_array; | ||
1184 | n = MAX_NUM_MISSILES; | ||
1185 | while (n--) | ||
1186 | { | ||
1187 | if (!missile->survived) | ||
1188 | { | ||
1189 | initialise_missile(missile); | ||
1190 | break; | ||
1191 | } | ||
1192 | missile++; | ||
1193 | } | ||
1194 | } | ||
1195 | } | ||
1196 | |||
1197 | /* Draw and Move all the missiles */ | ||
1198 | static void draw_and_move_missiles(void) | ||
1199 | { | ||
1200 | struct Missile* missile; | ||
1201 | struct Point vertices[2]; | ||
1202 | int n; | ||
1203 | |||
1204 | SET_FG(COL_MISSILE); | ||
1205 | |||
1206 | missile = missiles_array; | ||
1207 | n = MAX_NUM_MISSILES; | ||
1208 | while (n--) | ||
1209 | { | ||
1210 | if (missile->survived) | ||
1211 | { | ||
1212 | vertices[0].x = 0; | ||
1213 | vertices[0].y = 0; | ||
1214 | vertices[1].x = -missile->position.dx; | ||
1215 | vertices[1].y = -missile->position.dy; | ||
1216 | draw_polygon(vertices, 2, missile->position.x, missile->position.y); | ||
1217 | |||
1218 | if (game_state != PAUSE_MODE) | ||
1219 | { | ||
1220 | missile->oldpoint.x = missile->position.x; | ||
1221 | missile->oldpoint.y = missile->position.y; | ||
1222 | move_point(&missile->position); | ||
1223 | missile->survived--; | ||
1224 | } | ||
1225 | } | ||
1226 | missile++; | ||
1227 | } | ||
1228 | } | ||
1229 | |||
1230 | /************************************************* | ||
1231 | ** Handle enemy. | ||
1232 | *************************************************/ | ||
1233 | |||
1234 | static void initialise_enemy(void) | ||
963 | { | 1235 | { |
964 | struct Point* point; | 1236 | struct Point* point; |
965 | int n; | 1237 | int n; |
966 | int size; | 1238 | int size; |
967 | 1239 | ||
968 | if(rb->rand()%100 > enemy.size_probability) | 1240 | if (rb->rand()%100 > enemy.size_probability) |
969 | { | 1241 | { |
970 | size = BIG_SHIP; | 1242 | size = BIG_SHIP; |
971 | enemy.size_probability++; | 1243 | enemy.size_probability++; |
972 | if(enemy.size_probability > 90) | 1244 | if (enemy.size_probability > 90) |
973 | { | 1245 | { |
974 | enemy.size_probability = ENEMY_BIG_PROBABILITY_START; | 1246 | enemy.size_probability = ENEMY_BIG_PROBABILITY_START; |
975 | } | 1247 | } |
@@ -980,130 +1252,132 @@ void initialise_enemy(void) | |||
980 | enemy.size_probability = ENEMY_BIG_PROBABILITY_START; | 1252 | enemy.size_probability = ENEMY_BIG_PROBABILITY_START; |
981 | } | 1253 | } |
982 | 1254 | ||
983 | enemy_missile.survived = 0; | ||
984 | enemy.exists = true; | 1255 | enemy.exists = true; |
985 | enemy.explode_countdown = 0; | 1256 | enemy.explode_countdown = 0; |
986 | enemy.last_time_appeared = *rb->current_tick; | 1257 | enemy.appear_countdown = enemy.appear_timing; |
1258 | |||
987 | point = enemy.vertices; | 1259 | point = enemy.vertices; |
988 | for(n = 0; n < NUM_ENEMY_VERTICES*2; n += 2) | 1260 | for(n = 0; n < NUM_ENEMY_VERTICES*2; n += 2) |
989 | { | 1261 | { |
990 | point->x = enemy_vertices[n]; | 1262 | point->x = enemy_vertices[n]; |
991 | point->y = enemy_vertices[n+1]; | 1263 | point->y = enemy_vertices[n+1]; |
992 | point->x *= SCALE/size; | 1264 | point->x *= size*SCALE/2; |
993 | point->y *= SCALE/size; | 1265 | point->y *= size*SCALE/2; |
994 | point++; | 1266 | point++; |
995 | } | 1267 | } |
996 | 1268 | ||
997 | if(ship.position.x >= SCALED_WIDTH/2) | 1269 | if (ship.position.x >= SCALED_WIDTH/2) |
998 | { | 1270 | { |
999 | enemy.position.dx = ENEMY_SPEED; | 1271 | enemy.position.dx = ENEMY_SPEED; |
1000 | enemy.position.x = 0; | 1272 | enemy.position.x = 0; |
1001 | } | 1273 | } |
1002 | else | 1274 | else |
1003 | { | 1275 | { |
1004 | enemy.position.dx = -ENEMY_SPEED; | 1276 | enemy.position.dx = -ENEMY_SPEED; |
1005 | enemy.position.x = SCALED_WIDTH; | 1277 | enemy.position.x = SCALED_WIDTH; |
1006 | } | 1278 | } |
1007 | 1279 | ||
1008 | if(ship.position.y >= SCALED_HEIGHT/2) | 1280 | if (ship.position.y >= SCALED_HEIGHT/2) |
1009 | { | 1281 | { |
1010 | enemy.position.dy = ENEMY_SPEED; | 1282 | enemy.position.dy = ENEMY_SPEED; |
1011 | enemy.position.y = 0; | 1283 | enemy.position.y = 0; |
1012 | } | 1284 | } |
1013 | else | 1285 | else |
1014 | { | 1286 | { |
1015 | enemy.position.dy = -ENEMY_SPEED; | 1287 | enemy.position.dy = -ENEMY_SPEED; |
1016 | enemy.position.y = SCALED_HEIGHT; | 1288 | enemy.position.y = SCALED_HEIGHT; |
1017 | } | 1289 | } |
1018 | 1290 | ||
1019 | enemy.position.dx *= SCALE/10; | 1291 | enemy.position.dx *= SCALE/10; |
1020 | enemy.position.dy *= SCALE/10; | 1292 | enemy.position.dy *= SCALE/10; |
1021 | } | 1293 | } |
1022 | 1294 | ||
1023 | void draw_and_move_enemy(void) | 1295 | static void draw_and_move_enemy(void) |
1024 | { | 1296 | { |
1025 | int enemy_x, enemy_y; | ||
1026 | |||
1027 | SET_FG(COL_ENEMY); | 1297 | SET_FG(COL_ENEMY); |
1028 | 1298 | ||
1029 | if(enemy.exists) | 1299 | if (enemy.exists) |
1030 | { | 1300 | { |
1031 | enemy_x = enemy.position.x/SCALE; | 1301 | if (!enemy.explode_countdown) |
1032 | enemy_y = enemy.position.y/SCALE; | ||
1033 | if(!enemy.explode_countdown) | ||
1034 | { | 1302 | { |
1035 | draw_polygon(enemy.vertices, enemy_x, enemy_y, NUM_ENEMY_VERTICES); | 1303 | draw_polygon(enemy.vertices, NUM_ENEMY_VERTICES, |
1036 | rb->lcd_drawline(enemy.vertices[0].x/SCALE + enemy_x, | 1304 | enemy.position.x, enemy.position.y); |
1037 | enemy.vertices[0].y/SCALE + enemy_y, | ||
1038 | enemy.vertices[3].x/SCALE + enemy_x, | ||
1039 | enemy.vertices[3].y/SCALE + enemy_y); | ||
1040 | 1305 | ||
1041 | if(game_state != PAUSE_MODE) | 1306 | if (game_state != PAUSE_MODE) |
1042 | { | 1307 | { |
1043 | enemy.position.x += enemy.position.dx; | 1308 | enemy.position.x += enemy.position.dx; |
1044 | enemy.position.y += enemy.position.dy; | 1309 | enemy.position.y += enemy.position.dy; |
1045 | 1310 | ||
1046 | if(enemy.position.x > SCALED_WIDTH || enemy.position.x < 0) | 1311 | if (enemy.position.x > SCALED_WIDTH || enemy.position.x < 0) |
1047 | enemy.exists = false; | 1312 | enemy.exists = false; |
1048 | 1313 | ||
1049 | if(enemy.position.y > SCALED_HEIGHT) | 1314 | enemy.position.y %= SCALED_HEIGHT; |
1050 | enemy.position.y = 0; | 1315 | if (enemy.position.y < 0) |
1051 | else if(enemy.position.y < 0) | 1316 | enemy.position.y += SCALED_HEIGHT; |
1052 | enemy.position.y = SCALED_HEIGHT; | ||
1053 | 1317 | ||
1054 | if((rb->rand()%1000) < 10) | 1318 | if ((rb->rand()%1000) < 10) |
1055 | enemy.position.dy = -enemy.position.dy; | 1319 | enemy.position.dy = -enemy.position.dy; |
1056 | } | 1320 | } |
1057 | } | 1321 | } |
1058 | else | 1322 | else |
1059 | { | 1323 | { |
1060 | /* animate_and_draw_explosion(enemy.vertices, NUM_ENEMY_VERTICES, | 1324 | if (game_state != PAUSE_MODE) |
1061 | enemy_x, enemy.position.y/SCALE); */ | ||
1062 | if(game_state != PAUSE_MODE) | ||
1063 | { | 1325 | { |
1064 | enemy.explode_countdown--; | 1326 | enemy.explode_countdown--; |
1065 | if(!enemy.explode_countdown) | 1327 | if (!enemy.explode_countdown) |
1328 | { | ||
1066 | enemy.exists = false; | 1329 | enemy.exists = false; |
1330 | } | ||
1067 | } | 1331 | } |
1068 | } | 1332 | } |
1069 | } | 1333 | } |
1070 | else | 1334 | else |
1071 | { | 1335 | { |
1072 | if (TIME_AFTER(*rb->current_tick, | 1336 | if (game_state != PAUSE_MODE) |
1073 | enemy.last_time_appeared+enemy.appear_timing)) | ||
1074 | { | 1337 | { |
1075 | if(rb->rand()%100 >= enemy.appear_probability) | 1338 | if (enemy.appear_countdown) |
1339 | enemy.appear_countdown--; | ||
1340 | else if (rb->rand()%100 >= enemy.appear_probability) | ||
1076 | initialise_enemy(); | 1341 | initialise_enemy(); |
1077 | } | 1342 | } |
1078 | } | 1343 | } |
1079 | 1344 | ||
1080 | if(!enemy_missile.survived) | 1345 | if (!enemy_missile.survived) |
1081 | { | 1346 | { |
1082 | /*if no missile and the enemy is here and not exploding..then shoot baby!*/ | 1347 | /* if no missile and the enemy is here and not exploding.. |
1083 | if( !enemy.explode_countdown && enemy.exists && | 1348 | then shoot baby! */ |
1349 | if (!enemy.explode_countdown && enemy.exists && | ||
1084 | !ship.waiting_for_space && game_state == PLAY_MODE && | 1350 | !ship.waiting_for_space && game_state == PLAY_MODE && |
1085 | (rb->rand()%10) >= 5 ) | 1351 | (rb->rand()%10) >= 5 ) |
1086 | { | 1352 | { |
1087 | enemy_missile.position.x = enemy.position.x; | 1353 | int dx = ship.position.x - enemy.position.x; |
1088 | enemy_missile.position.y = enemy.position.y; | 1354 | int dy = ship.position.y - enemy.position.y; |
1089 | 1355 | ||
1090 | /*lame, needs to be sorted - it's trying to shoot at the ship*/ | 1356 | if (dx < -SCALED_WIDTH/2) dx += SCALED_WIDTH; |
1091 | if(ABS(enemy.position.y - ship.position.y) <= 5*SCALE) | 1357 | else if (dx > SCALED_WIDTH/2) dx -= SCALED_WIDTH; |
1092 | enemy_missile.position.dy = 0; | 1358 | if (dy < -SCALED_HEIGHT/2) dy += SCALED_HEIGHT; |
1093 | else if( enemy.position.y < ship.position.y) | 1359 | else if (dy > SCALED_HEIGHT/2) dy -= SCALED_HEIGHT; |
1094 | enemy_missile.position.dy = 1; | ||
1095 | else | ||
1096 | enemy_missile.position.dy = -1; | ||
1097 | 1360 | ||
1098 | if(ABS(enemy.position.x - ship.position.x) <= 5*SCALE) | 1361 | enemy_missile.position.x = enemy.position.x; |
1099 | enemy_missile.position.dx = 0; | 1362 | enemy_missile.position.y = enemy.position.y; |
1100 | else if( enemy.position.x < ship.position.x) | 1363 | |
1364 | /* lame, needs to be sorted - it's trying to shoot at the ship */ | ||
1365 | if (dx < -5*SCALE) | ||
1366 | enemy_missile.position.dx = -1; | ||
1367 | else if (dx > 5*SCALE) | ||
1101 | enemy_missile.position.dx = 1; | 1368 | enemy_missile.position.dx = 1; |
1102 | else | 1369 | else |
1103 | enemy_missile.position.dx = -1; | 1370 | enemy_missile.position.dx = 0; |
1104 | 1371 | ||
1105 | while(enemy_missile.position.dx == 0 && | 1372 | if (dy < -5*SCALE) |
1106 | enemy_missile.position.dy == 0) | 1373 | enemy_missile.position.dy = -1; |
1374 | else if (dy > 5*SCALE) | ||
1375 | enemy_missile.position.dy = 1; | ||
1376 | else | ||
1377 | enemy_missile.position.dy = 0; | ||
1378 | |||
1379 | while (enemy_missile.position.dx == 0 && | ||
1380 | enemy_missile.position.dy == 0) | ||
1107 | { | 1381 | { |
1108 | enemy_missile.position.dx = rb->rand()%2-1; | 1382 | enemy_missile.position.dx = rb->rand()%2-1; |
1109 | enemy_missile.position.dy = rb->rand()%2-1; | 1383 | enemy_missile.position.dy = rb->rand()%2-1; |
@@ -1119,7 +1393,7 @@ void draw_and_move_enemy(void) | |||
1119 | rb->lcd_fillrect( enemy_missile.position.x/SCALE, | 1393 | rb->lcd_fillrect( enemy_missile.position.x/SCALE, |
1120 | enemy_missile.position.y/SCALE, | 1394 | enemy_missile.position.y/SCALE, |
1121 | POINT_SIZE, POINT_SIZE ); | 1395 | POINT_SIZE, POINT_SIZE ); |
1122 | if(game_state != PAUSE_MODE) | 1396 | if (game_state != PAUSE_MODE) |
1123 | { | 1397 | { |
1124 | move_point(&enemy_missile.position); | 1398 | move_point(&enemy_missile.position); |
1125 | enemy_missile.survived--; | 1399 | enemy_missile.survived--; |
@@ -1127,24 +1401,28 @@ void draw_and_move_enemy(void) | |||
1127 | } | 1401 | } |
1128 | } | 1402 | } |
1129 | 1403 | ||
1130 | void add_score(int val) | 1404 | /************************************************* |
1405 | ** Check collisions. | ||
1406 | *************************************************/ | ||
1407 | |||
1408 | /* Add score if missile hit asteroid or enemy */ | ||
1409 | static void add_score(int val) | ||
1131 | { | 1410 | { |
1132 | current_score += val; | 1411 | current_score += val; |
1133 | if(current_score >= extra_life) | 1412 | if (current_score >= extra_life) |
1134 | { | 1413 | { |
1135 | num_lives++; | 1414 | num_lives++; |
1136 | extra_life += EXTRA_LIFE; | 1415 | extra_life += EXTRA_LIFE; |
1137 | } | 1416 | } |
1138 | } | 1417 | } |
1139 | 1418 | ||
1140 | bool is_point_within_asteroid(struct Asteroid* asteroid, struct Point* point) | 1419 | static bool is_point_within_asteroid(struct Asteroid* asteroid, |
1420 | struct Point* point) | ||
1141 | { | 1421 | { |
1142 | if(!is_point_within_rectangle(&asteroid->position, point, asteroid->radius)) | 1422 | if (is_point_within_rectangle(&asteroid->position, point, asteroid->radius) |
1143 | return false; | 1423 | && is_point_in_polygon(asteroid->vertices, NUM_ASTEROID_VERTICES, |
1144 | 1424 | point->x - asteroid->position.x, | |
1145 | if(point_in_poly(asteroid->vertices, NUM_ASTEROID_VERTICES, | 1425 | point->y - asteroid->position.y)) |
1146 | point->x - asteroid->position.x, | ||
1147 | point->y - asteroid->position.y)) | ||
1148 | { | 1426 | { |
1149 | struct Point p; | 1427 | struct Point p; |
1150 | p.dx = asteroid->position.dx; | 1428 | p.dx = asteroid->position.dx; |
@@ -1159,17 +1437,17 @@ bool is_point_within_asteroid(struct Asteroid* asteroid, struct Point* point) | |||
1159 | { | 1437 | { |
1160 | case SMALL: | 1438 | case SMALL: |
1161 | asteroid->explode_countdown = EXPLOSION_LENGTH; | 1439 | asteroid->explode_countdown = EXPLOSION_LENGTH; |
1162 | create_trail_blaze(ASTEROID_EXPLOSION_COLOUR, &p); | 1440 | create_trail_blaze(EXPLOSION_ASTEROID, &p); |
1163 | break; | 1441 | break; |
1164 | 1442 | ||
1165 | case MEDIUM: | 1443 | case MEDIUM: |
1166 | create_asteroid(SMALL, p.x, p.y); | 1444 | create_asteroid(SMALL, &p); |
1167 | create_asteroid(SMALL, p.x, p.y); | 1445 | create_asteroid(SMALL, &p); |
1168 | break; | 1446 | break; |
1169 | 1447 | ||
1170 | case LARGE: | 1448 | case LARGE: |
1171 | create_asteroid(MEDIUM, p.x, p.y); | 1449 | create_asteroid(MEDIUM, &p); |
1172 | create_asteroid(MEDIUM, p.x, p.y); | 1450 | create_asteroid(MEDIUM, &p); |
1173 | break; | 1451 | break; |
1174 | } | 1452 | } |
1175 | return true; | 1453 | return true; |
@@ -1178,60 +1456,43 @@ bool is_point_within_asteroid(struct Asteroid* asteroid, struct Point* point) | |||
1178 | return false; | 1456 | return false; |
1179 | } | 1457 | } |
1180 | 1458 | ||
1181 | bool is_point_within_enemy(struct Point* point) | 1459 | static bool is_point_within_enemy(struct Point* point) |
1182 | { | 1460 | { |
1183 | if( is_point_within_rectangle(&enemy.position, point, 7*SCALE) ) | 1461 | if (is_point_within_rectangle(&enemy.position, point, SIZE_ENEMY_COLLISION)) |
1184 | { | 1462 | { |
1185 | add_score(5); | 1463 | add_score(5); |
1186 | /* enemy_missile.survived = 0; */ | ||
1187 | enemy.explode_countdown = EXPLOSION_LENGTH; | 1464 | enemy.explode_countdown = EXPLOSION_LENGTH; |
1188 | /* initialise_explosion(enemy.vertices, NUM_ENEMY_VERTICES); */ | 1465 | create_trail_blaze(EXPLOSION_ENEMY, &enemy.position); |
1189 | create_trail_blaze(ENEMY_EXPLOSION_COLOUR, &enemy.position); | ||
1190 | return true; | 1466 | return true; |
1191 | } | 1467 | } |
1192 | else | 1468 | else |
1193 | return false; | 1469 | return false; |
1194 | } | 1470 | } |
1195 | 1471 | ||
1196 | bool is_ship_within_asteroid(struct Asteroid* asteroid) | 1472 | static bool is_ship_within_asteroid(struct Asteroid* asteroid) |
1197 | { | 1473 | { |
1198 | struct Point p; | 1474 | struct Point p; |
1199 | 1475 | ||
1200 | p.x = ship.position.x + ship.vertices[0].x; | 1476 | p.x = ship.position.x + ship.vertices[0].x; |
1201 | p.y = ship.position.y + ship.vertices[0].y; | 1477 | p.y = ship.position.y + ship.vertices[0].y; |
1202 | if(is_point_within_asteroid(asteroid, &p)) | 1478 | if (is_point_within_asteroid(asteroid, &p)) |
1203 | return true; | 1479 | return true; |
1204 | 1480 | ||
1205 | p.x = ship.position.x + ship.vertices[1].x; | 1481 | p.x = ship.position.x + ship.vertices[1].x; |
1206 | p.y = ship.position.y + ship.vertices[1].y; | 1482 | p.y = ship.position.y + ship.vertices[1].y; |
1207 | if(is_point_within_asteroid(asteroid, &p)) | 1483 | if (is_point_within_asteroid(asteroid, &p)) |
1208 | return true; | 1484 | return true; |
1209 | 1485 | ||
1210 | p.x = ship.position.x + ship.vertices[3].x; | 1486 | p.x = ship.position.x + ship.vertices[3].x; |
1211 | p.y = ship.position.y + ship.vertices[3].y; | 1487 | p.y = ship.position.y + ship.vertices[3].y; |
1212 | if(is_point_within_asteroid(asteroid, &p)) | 1488 | if (is_point_within_asteroid(asteroid, &p)) |
1213 | return true; | 1489 | return true; |
1214 | 1490 | ||
1215 | return false; | 1491 | return false; |
1216 | } | 1492 | } |
1217 | 1493 | ||
1218 | void initialise_explosion(struct Point* point, int num_points) | ||
1219 | { | ||
1220 | int n; | ||
1221 | |||
1222 | point->x += point->dx; | ||
1223 | point->y += point->dy; | ||
1224 | n = num_points; | ||
1225 | while(n--) | ||
1226 | { | ||
1227 | point->dx = point->x; | ||
1228 | point->dy = point->y; | ||
1229 | point++; | ||
1230 | } | ||
1231 | } | ||
1232 | |||
1233 | /* Check for collsions between the missiles and the asteroids and the ship */ | 1494 | /* Check for collsions between the missiles and the asteroids and the ship */ |
1234 | void check_collisions(void) | 1495 | static void check_collisions(void) |
1235 | { | 1496 | { |
1236 | struct Missile* missile; | 1497 | struct Missile* missile; |
1237 | struct Asteroid* asteroid; | 1498 | struct Asteroid* asteroid; |
@@ -1241,21 +1502,21 @@ void check_collisions(void) | |||
1241 | 1502 | ||
1242 | asteroid = asteroids_array; | 1503 | asteroid = asteroids_array; |
1243 | m = MAX_NUM_ASTEROIDS; | 1504 | m = MAX_NUM_ASTEROIDS; |
1244 | while(m--) | 1505 | while (m--) |
1245 | { | 1506 | { |
1246 | /*if the asteroids exists then test missile collision:*/ | 1507 | /* if the asteroids exists then test missile collision: */ |
1247 | if (asteroid->exists) | 1508 | if (asteroid->exists) |
1248 | { | 1509 | { |
1249 | missile = missiles_array; | 1510 | missile = missiles_array; |
1250 | n = MAX_NUM_MISSILES; | 1511 | n = MAX_NUM_MISSILES; |
1251 | while(n--) | 1512 | while (n--) |
1252 | { | 1513 | { |
1253 | /*if the missiles exists:*/ | 1514 | /* if the missiles exists: */ |
1254 | if(missile->survived > 0) | 1515 | if (missile->survived > 0) |
1255 | { | 1516 | { |
1256 | /*has the missile hit the asteroid?*/ | 1517 | /* has the missile hit the asteroid? */ |
1257 | if(is_point_within_asteroid(asteroid, &missile->position) || | 1518 | if (is_point_within_asteroid(asteroid, &missile->position) || |
1258 | is_point_within_asteroid(asteroid, &missile->oldpoint)) | 1519 | is_point_within_asteroid(asteroid, &missile->oldpoint)) |
1259 | { | 1520 | { |
1260 | add_score(1); | 1521 | add_score(1); |
1261 | missile->survived = 0; | 1522 | missile->survived = 0; |
@@ -1265,7 +1526,7 @@ void check_collisions(void) | |||
1265 | missile++; | 1526 | missile++; |
1266 | } | 1527 | } |
1267 | 1528 | ||
1268 | /*now check collision with ship:*/ | 1529 | /* now check collision with ship: */ |
1269 | if (asteroid->exists && !ship.waiting_for_space && !ship.explode_countdown) | 1530 | if (asteroid->exists && !ship.waiting_for_space && !ship.explode_countdown) |
1270 | { | 1531 | { |
1271 | if (is_ship_within_asteroid(asteroid)) | 1532 | if (is_ship_within_asteroid(asteroid)) |
@@ -1273,22 +1534,21 @@ void check_collisions(void) | |||
1273 | add_score(1); | 1534 | add_score(1); |
1274 | if (!ship.invulnerable) | 1535 | if (!ship.invulnerable) |
1275 | { | 1536 | { |
1276 | /*if not invulnerable, blow up ship*/ | 1537 | /* if not invulnerable, blow up ship */ |
1277 | ship.explode_countdown = EXPLOSION_LENGTH; | 1538 | ship.explode_countdown = EXPLOSION_LENGTH; |
1278 | /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */ | 1539 | create_trail_blaze(EXPLOSION_SHIP, &ship.position); |
1279 | create_trail_blaze(SHIP_EXPLOSION_COLOUR, &ship.position); | ||
1280 | } | 1540 | } |
1281 | } | 1541 | } |
1282 | 1542 | ||
1283 | /*has the enemy missile blown something up?*/ | 1543 | /* has the enemy missile blown something up? */ |
1284 | if (asteroid->exists && enemy_missile.survived) | 1544 | if (asteroid->exists && enemy_missile.survived) |
1285 | { | 1545 | { |
1286 | if(is_point_within_asteroid(asteroid, &enemy_missile.position)) | 1546 | if (is_point_within_asteroid(asteroid, &enemy_missile.position)) |
1287 | { | 1547 | { |
1288 | enemy_missile.survived = 0; | 1548 | enemy_missile.survived = 0; |
1289 | } | 1549 | } |
1290 | 1550 | ||
1291 | /*if it still exists, check if ship is waiting for space:*/ | 1551 | /* if it still exists, check if ship is waiting for space: */ |
1292 | if (asteroid->exists && ship.waiting_for_space) | 1552 | if (asteroid->exists && ship.waiting_for_space) |
1293 | { | 1553 | { |
1294 | ship_cant_be_placed |= | 1554 | ship_cant_be_placed |= |
@@ -1300,35 +1560,34 @@ void check_collisions(void) | |||
1300 | } | 1560 | } |
1301 | } | 1561 | } |
1302 | 1562 | ||
1303 | /*is an asteroid still exploding?*/ | 1563 | /* is an asteroid still exploding? */ |
1304 | if (asteroid->explode_countdown) | 1564 | if (asteroid->explode_countdown) |
1305 | asteroids_onscreen = true; | 1565 | asteroids_onscreen = true; |
1306 | 1566 | ||
1307 | asteroid++; | 1567 | asteroid++; |
1308 | } | 1568 | } |
1309 | 1569 | ||
1310 | /*now check collision between ship and enemy*/ | 1570 | /* now check collision between ship and enemy */ |
1311 | if(enemy.exists && !enemy.explode_countdown && | 1571 | if (enemy.exists && !enemy.explode_countdown && |
1312 | !ship.waiting_for_space && !ship.explode_countdown) | 1572 | !ship.waiting_for_space && !ship.explode_countdown) |
1313 | { | 1573 | { |
1314 | /*has the enemy collided with the ship?*/ | 1574 | /* has the enemy collided with the ship? */ |
1315 | if(is_point_within_enemy(&ship.position)) | 1575 | if (is_point_within_enemy(&ship.position)) |
1316 | { | 1576 | { |
1317 | if (!ship.invulnerable) | 1577 | if (!ship.invulnerable) |
1318 | { | 1578 | { |
1319 | ship.explode_countdown = EXPLOSION_LENGTH; | 1579 | ship.explode_countdown = EXPLOSION_LENGTH; |
1320 | /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */ | 1580 | create_trail_blaze(EXPLOSION_SHIP, &ship.position); |
1321 | create_trail_blaze(SHIP_EXPLOSION_COLOUR, &ship.position); | ||
1322 | } | 1581 | } |
1323 | create_trail_blaze(ENEMY_EXPLOSION_COLOUR, &enemy.position); | 1582 | create_trail_blaze(EXPLOSION_ENEMY, &enemy.position); |
1324 | } | 1583 | } |
1325 | 1584 | ||
1326 | if (enemy.exists && !enemy.explode_countdown) | 1585 | if (enemy.exists && !enemy.explode_countdown) |
1327 | { | 1586 | { |
1328 | /*Now see if the enemy has been shot at by the ships missiles:*/ | 1587 | /* Now see if the enemy has been shot at by the ships missiles: */ |
1329 | missile = missiles_array; | 1588 | missile = missiles_array; |
1330 | n = MAX_NUM_MISSILES; | 1589 | n = MAX_NUM_MISSILES; |
1331 | while(n--) | 1590 | while (n--) |
1332 | { | 1591 | { |
1333 | if (missile->survived > 0 && | 1592 | if (missile->survived > 0 && |
1334 | is_point_within_enemy(&missile->position)) | 1593 | is_point_within_enemy(&missile->position)) |
@@ -1341,387 +1600,59 @@ void check_collisions(void) | |||
1341 | } | 1600 | } |
1342 | } | 1601 | } |
1343 | 1602 | ||
1344 | /*test collision with enemy missile and ship:*/ | 1603 | /* test collision with enemy missile and ship: */ |
1345 | if (!ship_cant_be_placed && enemy_missile.survived > 0 && | 1604 | if (!ship_cant_be_placed && enemy_missile.survived > 0 && |
1346 | point_in_poly(ship.vertices, NUM_SHIP_VERTICES, | 1605 | is_point_in_polygon(ship.vertices, NUM_SHIP_VERTICES, |
1347 | enemy_missile.position.x - ship.position.x, | 1606 | enemy_missile.position.x - ship.position.x, |
1348 | enemy_missile.position.y - ship.position.y)) | 1607 | enemy_missile.position.y - ship.position.y)) |
1349 | { | 1608 | { |
1350 | if (!ship.invulnerable) | 1609 | if (!ship.invulnerable) |
1351 | { | 1610 | { |
1352 | ship.explode_countdown = EXPLOSION_LENGTH; | 1611 | ship.explode_countdown = EXPLOSION_LENGTH; |
1353 | /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */ | 1612 | create_trail_blaze(EXPLOSION_SHIP, &ship.position); |
1354 | create_trail_blaze(SHIP_EXPLOSION_COLOUR, &ship.position); | ||
1355 | } | 1613 | } |
1356 | enemy_missile.survived = 0; | 1614 | enemy_missile.survived = 0; |
1357 | enemy_missile.position.x = enemy_missile.position.y = 0; | 1615 | enemy_missile.position.x = enemy_missile.position.y = 0; |
1358 | } | 1616 | } |
1359 | 1617 | ||
1360 | if(!ship_cant_be_placed) | 1618 | if (!ship_cant_be_placed) |
1361 | ship.waiting_for_space = false; | 1619 | ship.waiting_for_space = false; |
1362 | 1620 | ||
1363 | /*if all asteroids cleared then start again:*/ | 1621 | /* if all asteroids cleared then start again: */ |
1364 | if(asteroid_count == 0 && !enemy.exists && !asteroids_onscreen) | 1622 | if (asteroid_count == 0 && !enemy.exists && !asteroids_onscreen) |
1365 | { | 1623 | { |
1366 | current_level++; | 1624 | current_level++; |
1367 | game_state = SHOW_LEVEL; | ||
1368 | enemy.appear_probability += 5; | 1625 | enemy.appear_probability += 5; |
1369 | enemy.appear_timing -= 200; | ||
1370 | if (enemy.appear_probability >= 100) | 1626 | if (enemy.appear_probability >= 100) |
1371 | enemy.appear_probability = ENEMY_APPEAR_PROBABILITY_START; | 1627 | enemy.appear_probability = ENEMY_APPEAR_PROBABILITY_START; |
1628 | enemy.appear_timing -= 30; | ||
1629 | if (enemy.appear_timing < 30) | ||
1630 | enemy.appear_timing = 30; | ||
1631 | game_state = SHOW_LEVEL; | ||
1372 | show_level_timeout = SHOW_LEVEL_TIME; | 1632 | show_level_timeout = SHOW_LEVEL_TIME; |
1373 | } | 1633 | } |
1374 | } | 1634 | } |
1375 | 1635 | ||
1376 | /************************************************* | 1636 | /* |
1377 | ** Creates a new asteroid of the given 4type (size) | 1637 | * stars |
1378 | ** and at the given location. | 1638 | */ |
1379 | *************************************************/ | ||
1380 | void create_asteroid(enum asteroid_type type, int x, int y) | ||
1381 | { | ||
1382 | struct Asteroid* asteroid; | ||
1383 | int n; | ||
1384 | |||
1385 | asteroid = asteroids_array; | ||
1386 | n = MAX_NUM_ASTEROIDS; | ||
1387 | while(n--) | ||
1388 | { | ||
1389 | if(!asteroid->exists && !asteroid->explode_countdown) | ||
1390 | { | ||
1391 | initialise_asteroid(asteroid, type); | ||
1392 | asteroid->position.x = x; | ||
1393 | asteroid->position.y = y; | ||
1394 | break; | ||
1395 | } | ||
1396 | asteroid++; | ||
1397 | } | ||
1398 | } | ||
1399 | |||
1400 | /* Initialise a missile */ | ||
1401 | void initialise_missile(struct Missile* missile) | ||
1402 | { | ||
1403 | missile->position.x = ship.position.x + ship.vertices[0].x; | ||
1404 | missile->position.y = ship.position.y + ship.vertices[0].y; | ||
1405 | missile->position.dx = (ship.vertices[0].x - ship.vertices[2].x)/2; | ||
1406 | missile->position.dy = (ship.vertices[0].y - ship.vertices[2].y)/2; | ||
1407 | missile->survived = MISSILE_SURVIVAL_LENGTH; | ||
1408 | missile->oldpoint.x = missile->position.x; | ||
1409 | missile->oldpoint.y = missile->position.y; | ||
1410 | } | ||
1411 | |||
1412 | /* Draw and Move all the missiles */ | ||
1413 | void draw_and_move_missiles(void) | ||
1414 | { | ||
1415 | struct Missile* missile; | ||
1416 | struct Point vertices[2]; | ||
1417 | int n; | ||
1418 | |||
1419 | SET_FG(COL_MISSILE); | ||
1420 | |||
1421 | missile = missiles_array; | ||
1422 | n = MAX_NUM_MISSILES; | ||
1423 | while(n--) | ||
1424 | { | ||
1425 | if(missile->survived) | ||
1426 | { | ||
1427 | vertices[0].x = 0; | ||
1428 | vertices[0].y = 0; | ||
1429 | vertices[1].x = -missile->position.dx; | ||
1430 | vertices[1].y = -missile->position.dy; | ||
1431 | draw_polygon(vertices, missile->position.x/SCALE, | ||
1432 | missile->position.y/SCALE, 2); | ||
1433 | |||
1434 | if(game_state != PAUSE_MODE) | ||
1435 | { | ||
1436 | missile->oldpoint.x = missile->position.x; | ||
1437 | missile->oldpoint.y = missile->position.y; | ||
1438 | move_point(&missile->position); | ||
1439 | missile->survived--; | ||
1440 | } | ||
1441 | } | ||
1442 | missile++; | ||
1443 | } | ||
1444 | } | ||
1445 | |||
1446 | void draw_lives(void) | ||
1447 | { | ||
1448 | int n; | ||
1449 | #if (LARGE_LCD) | ||
1450 | int px = (LCD_WIDTH-1 - 4); | ||
1451 | int py = (LCD_HEIGHT-1 - 6); | ||
1452 | #else | ||
1453 | int px = (LCD_WIDTH-1 - 3); | ||
1454 | int py = (LCD_HEIGHT-1 - 4); | ||
1455 | #endif | ||
1456 | |||
1457 | SET_FG(COL_PLAYER); | ||
1458 | |||
1459 | n = num_lives-1; | ||
1460 | while(n--) | ||
1461 | { | ||
1462 | draw_polygon(lives_points, px, py, NUM_SHIP_VERTICES); | ||
1463 | #if (LARGE_LCD) | ||
1464 | px -= 8; | ||
1465 | #else | ||
1466 | px -= 6; | ||
1467 | #endif | ||
1468 | } | ||
1469 | } | ||
1470 | |||
1471 | /*Fire the next missile*/ | ||
1472 | void fire_missile(void) | ||
1473 | { | ||
1474 | struct Missile* missile; | ||
1475 | int n; | ||
1476 | |||
1477 | if (!ship.explode_countdown && !ship.waiting_for_space) | ||
1478 | { | ||
1479 | missile = missiles_array; | ||
1480 | n = MAX_NUM_MISSILES; | ||
1481 | while(n--) | ||
1482 | { | ||
1483 | if(!missile->survived) | ||
1484 | { | ||
1485 | initialise_missile(missile); | ||
1486 | break; | ||
1487 | } | ||
1488 | missile++; | ||
1489 | } | ||
1490 | } | ||
1491 | } | ||
1492 | |||
1493 | /* Initialise the passed Asteroid */ | ||
1494 | void initialise_asteroid(struct Asteroid* asteroid, enum asteroid_type type) | ||
1495 | { | ||
1496 | const short *asteroid_vertices; | ||
1497 | struct Point* point; | ||
1498 | int n; | ||
1499 | |||
1500 | asteroid->exists = true; | ||
1501 | asteroid->type = type; | ||
1502 | asteroid->explode_countdown = 0; | ||
1503 | |||
1504 | /*Set the radius of the asteroid:*/ | ||
1505 | asteroid->radius = (int)type*SCALE*3; | ||
1506 | |||
1507 | /*shall we move Clockwise and Fast*/ | ||
1508 | n = rb->rand()%100; | ||
1509 | if(n < 25) | ||
1510 | { | ||
1511 | asteroid->speed_cos = FAST_ROT_CW_COS; | ||
1512 | asteroid->speed_sin = FAST_ROT_CW_SIN; | ||
1513 | } | ||
1514 | else if(n < 50) | ||
1515 | { | ||
1516 | asteroid->speed_cos = FAST_ROT_ACW_COS; | ||
1517 | asteroid->speed_sin = FAST_ROT_ACW_SIN; | ||
1518 | } | ||
1519 | else if(n < 75) | ||
1520 | { | ||
1521 | asteroid->speed_cos = SLOW_ROT_ACW_COS; | ||
1522 | asteroid->speed_sin = SLOW_ROT_ACW_SIN; | ||
1523 | } | ||
1524 | else | ||
1525 | { | ||
1526 | asteroid->speed_cos = SLOW_ROT_CW_COS; | ||
1527 | asteroid->speed_sin = SLOW_ROT_CW_SIN; | ||
1528 | } | ||
1529 | |||
1530 | n = rb->rand()%99; | ||
1531 | if (n < 33) | ||
1532 | asteroid_vertices = asteroid_one; | ||
1533 | else if (n < 66) | ||
1534 | asteroid_vertices = asteroid_two; | ||
1535 | else | ||
1536 | asteroid_vertices = asteroid_three; | ||
1537 | |||
1538 | point = asteroid->vertices; | ||
1539 | for(n = 0; n < NUM_ASTEROID_VERTICES*2; n += 2) | ||
1540 | { | ||
1541 | point->x = asteroid_vertices[n]; | ||
1542 | point->y = asteroid_vertices[n+1]; | ||
1543 | point->x *= asteroid->radius/20; | ||
1544 | point->y *= asteroid->radius/20; | ||
1545 | point++; | ||
1546 | } | ||
1547 | |||
1548 | do | ||
1549 | { | ||
1550 | /*Set the position randomly:*/ | ||
1551 | asteroid->position.x = (rb->rand()%SCALED_WIDTH); | ||
1552 | asteroid->position.y = (rb->rand()%SCALED_HEIGHT); | ||
1553 | } while (is_point_within_rectangle(&ship.position, &asteroid->position, | ||
1554 | SPACE_CHECK_SIZE)); | ||
1555 | |||
1556 | do { | ||
1557 | asteroid->position.dx = (rb->rand()%ASTEROID_SPEED)-ASTEROID_SPEED/2; | ||
1558 | } while (asteroid->position.dx == 0); | ||
1559 | |||
1560 | do { | ||
1561 | asteroid->position.dy = (rb->rand()%ASTEROID_SPEED)-ASTEROID_SPEED/2; | ||
1562 | } while (asteroid->position.dy == 0); | ||
1563 | |||
1564 | asteroid->position.dx *= SCALE/10; | ||
1565 | asteroid->position.dy *= SCALE/10; | ||
1566 | |||
1567 | /*Now rotate the asteroid a bit, so they all look a bit different*/ | ||
1568 | for(n = (rb->rand()%30)+2; n--; ) | ||
1569 | rotate_asteroid(asteroid); | ||
1570 | |||
1571 | /*great, we've created an asteroid, don't forget to increment the total:*/ | ||
1572 | asteroid_count++; | ||
1573 | } | ||
1574 | |||
1575 | /*Initialise the ship*/ | ||
1576 | void initialise_ship(void) | ||
1577 | { | ||
1578 | struct Point* point; | ||
1579 | struct Point* lives_point; | ||
1580 | int n; | ||
1581 | |||
1582 | ship.position.x = CENTER_LCD_X * SCALE; | ||
1583 | ship.position.y = CENTER_LCD_Y * SCALE; | ||
1584 | ship.position.dx = 0; | ||
1585 | ship.position.dy = 0; | ||
1586 | ship.explode_countdown = 0; | ||
1587 | ship.spawn_time = SPAWN_TIME; | ||
1588 | ship.invulnerable = 1; | ||
1589 | |||
1590 | point = ship.vertices; | ||
1591 | lives_point = lives_points; | ||
1592 | for(n = 0; n < NUM_SHIP_VERTICES*2; n += 2) | ||
1593 | { | ||
1594 | point->x = ship_vertices[n]; | ||
1595 | point->y = ship_vertices[n+1]; | ||
1596 | point->x *= SCALE; | ||
1597 | point->y *= SCALE; | ||
1598 | /*grab a copy of the ships points for the lives display:*/ | ||
1599 | lives_point->x = point->x; | ||
1600 | lives_point->y = point->y; | ||
1601 | |||
1602 | point++; | ||
1603 | lives_point++; | ||
1604 | } | ||
1605 | } | ||
1606 | 1639 | ||
1607 | void rotate_asteroid(struct Asteroid* asteroid) | 1640 | static void create_stars(void) |
1608 | { | 1641 | { |
1609 | struct Point* point; | 1642 | struct Point* p; |
1610 | int n; | 1643 | int n; |
1611 | long xtemp; | ||
1612 | |||
1613 | point = asteroid->vertices; | ||
1614 | for(n = NUM_ASTEROID_VERTICES+1; --n;) | ||
1615 | { | ||
1616 | xtemp = point->x; | ||
1617 | point->x = xtemp*asteroid->speed_cos/SIN_COS_SCALE - | ||
1618 | point->y*asteroid->speed_sin/SIN_COS_SCALE; | ||
1619 | point->y = point->y*asteroid->speed_cos/SIN_COS_SCALE + | ||
1620 | xtemp*asteroid->speed_sin/SIN_COS_SCALE; | ||
1621 | point++; | ||
1622 | } | ||
1623 | } | ||
1624 | 1644 | ||
1625 | /************************************************* | 1645 | p = stars; |
1626 | ** Draws the ship, moves the ship and creates a new | 1646 | n = NUM_STARS; |
1627 | ** one if it's finished exploding. | 1647 | while (n--) |
1628 | **************************************************/ | ||
1629 | void draw_and_move_ship(void) | ||
1630 | { | ||
1631 | if (ship.invulnerable && | ||
1632 | (ship.spawn_time > BLINK_TIME || ship.spawn_time % 2 == 0)) | ||
1633 | { | ||
1634 | SET_FG(COL_INVULN); | ||
1635 | } | ||
1636 | else | ||
1637 | { | ||
1638 | SET_FG(COL_PLAYER); | ||
1639 | } | ||
1640 | |||
1641 | if(!ship.explode_countdown) | ||
1642 | { | ||
1643 | /* make sure ship is invulnerable until spawn time over */ | ||
1644 | if (ship.spawn_time) | ||
1645 | { | ||
1646 | ship.spawn_time--; | ||
1647 | if (ship.spawn_time <= 0) | ||
1648 | { | ||
1649 | ship.invulnerable = 0; | ||
1650 | } | ||
1651 | } | ||
1652 | if(!ship.waiting_for_space) | ||
1653 | { | ||
1654 | draw_polygon(ship.vertices, ship.position.x/SCALE, | ||
1655 | ship.position.y/SCALE, NUM_SHIP_VERTICES); | ||
1656 | if(game_state != PAUSE_MODE && game_state != GAME_OVER) | ||
1657 | { | ||
1658 | move_point(&ship.position); | ||
1659 | } | ||
1660 | } | ||
1661 | } | ||
1662 | else | ||
1663 | { | ||
1664 | /* animate_and_draw_explosion(ship.vertices, NUM_SHIP_VERTICES, | ||
1665 | ship.position.x/SCALE, | ||
1666 | ship.position.y/SCALE); */ | ||
1667 | if(game_state != PAUSE_MODE) | ||
1668 | { | ||
1669 | ship.explode_countdown--; | ||
1670 | if(!ship.explode_countdown) | ||
1671 | { | ||
1672 | num_lives--; | ||
1673 | if(!num_lives) | ||
1674 | { | ||
1675 | game_state = GAME_OVER; | ||
1676 | } | ||
1677 | else | ||
1678 | { | ||
1679 | initialise_ship(); | ||
1680 | ship.waiting_for_space = true; | ||
1681 | } | ||
1682 | } | ||
1683 | } | ||
1684 | } | ||
1685 | } | ||
1686 | |||
1687 | void thrust_ship(void) | ||
1688 | { | ||
1689 | if(!ship.waiting_for_space) | ||
1690 | { | ||
1691 | ship.position.dx += ( ship.vertices[0].x - ship.vertices[2].x )/20; | ||
1692 | ship.position.dy += ( ship.vertices[0].y - ship.vertices[2].y )/20; | ||
1693 | |||
1694 | /*if dx and dy are below a certain threshold, then set 'em to 0 | ||
1695 | but to do this we need to ascertain if the spacehip as moved on screen | ||
1696 | for more than a certain amount. */ | ||
1697 | |||
1698 | create_trail_blaze(THRUST_COLOUR, &ship.position); | ||
1699 | } | ||
1700 | } | ||
1701 | |||
1702 | /************************************************** | ||
1703 | ** Rotate the ship using the passed sin & cos values | ||
1704 | ***************************************************/ | ||
1705 | void rotate_ship(int c, int s) | ||
1706 | { | ||
1707 | struct Point* point; | ||
1708 | int n; | ||
1709 | long xtemp; | ||
1710 | |||
1711 | if(!ship.waiting_for_space && !ship.explode_countdown) | ||
1712 | { | 1648 | { |
1713 | point = ship.vertices; | 1649 | p->x = (rb->rand()%LCD_WIDTH); |
1714 | for(n=NUM_SHIP_VERTICES+1;--n;) | 1650 | p->y = (rb->rand()%LCD_HEIGHT); |
1715 | { | 1651 | p++; |
1716 | xtemp = point->x; | ||
1717 | point->x = xtemp*c/SIN_COS_SCALE - point->y*s/SIN_COS_SCALE; | ||
1718 | point->y = point->y*c/SIN_COS_SCALE + xtemp*s/SIN_COS_SCALE; | ||
1719 | point++; | ||
1720 | } | ||
1721 | } | 1652 | } |
1722 | } | 1653 | } |
1723 | 1654 | ||
1724 | void drawstars() | 1655 | static void drawstars(void) |
1725 | { | 1656 | { |
1726 | struct Point* p; | 1657 | struct Point* p; |
1727 | int n; | 1658 | int n; |
@@ -1730,7 +1661,7 @@ void drawstars() | |||
1730 | 1661 | ||
1731 | p = stars; | 1662 | p = stars; |
1732 | n = NUM_STARS; | 1663 | n = NUM_STARS; |
1733 | while(n--) | 1664 | while (n--) |
1734 | { | 1665 | { |
1735 | rb->lcd_drawpixel(p->x , p->y); | 1666 | rb->lcd_drawpixel(p->x , p->y); |
1736 | p++; | 1667 | p++; |
@@ -1738,126 +1669,165 @@ void drawstars() | |||
1738 | } | 1669 | } |
1739 | 1670 | ||
1740 | /************************************************* | 1671 | /************************************************* |
1741 | ** Draw And Move all Asteroids | 1672 | ** Creates start_num number of new asteroids of |
1742 | *************************************************/ | 1673 | ** full size. |
1743 | void draw_and_move_asteroids(void) | 1674 | **************************************************/ |
1675 | static void initialise_level(int start_num) | ||
1744 | { | 1676 | { |
1745 | struct Asteroid* asteroid; | 1677 | struct Asteroid* asteroid; |
1678 | struct Missile* missile; | ||
1679 | struct TrailPoint* tpoint; | ||
1746 | int n; | 1680 | int n; |
1681 | asteroid_count = next_missile_count = next_thrust_count = 0; | ||
1747 | 1682 | ||
1748 | SET_FG(COL_ASTEROID); | 1683 | /* no enemy */ |
1684 | enemy.exists = 0; | ||
1685 | enemy_missile.survived = 0; | ||
1749 | 1686 | ||
1687 | /* clear asteroids */ | ||
1750 | asteroid = asteroids_array; | 1688 | asteroid = asteroids_array; |
1751 | n = MAX_NUM_ASTEROIDS; | 1689 | n = MAX_NUM_ASTEROIDS; |
1752 | while(n--) | 1690 | while (n--) |
1753 | { | 1691 | { |
1754 | if(game_state != PAUSE_MODE) | 1692 | asteroid->exists = false; |
1755 | { | ||
1756 | if(asteroid->exists) | ||
1757 | { | ||
1758 | move_point(&asteroid->position); | ||
1759 | rotate_asteroid(asteroid); | ||
1760 | draw_polygon(asteroid->vertices, asteroid->position.x/SCALE, | ||
1761 | asteroid->position.y/SCALE, NUM_ASTEROID_VERTICES); | ||
1762 | } | ||
1763 | else if(asteroid->explode_countdown) | ||
1764 | { | ||
1765 | /* animate_and_draw_explosion(asteroid->vertices, | ||
1766 | NUM_ASTEROID_VERTICES, | ||
1767 | asteroid->position.x/SCALE, | ||
1768 | asteroid->position.y/SCALE); */ | ||
1769 | asteroid->explode_countdown--; | ||
1770 | } | ||
1771 | } | ||
1772 | else | ||
1773 | { | ||
1774 | if(asteroid->exists) | ||
1775 | draw_polygon(asteroid->vertices, asteroid->position.x/SCALE, | ||
1776 | asteroid->position.y/SCALE, NUM_ASTEROID_VERTICES); | ||
1777 | } | ||
1778 | asteroid++; | 1693 | asteroid++; |
1779 | } | 1694 | } |
1780 | } | ||
1781 | 1695 | ||
1782 | void create_stars(void) | 1696 | /* make some LARGE asteroids */ |
1783 | { | 1697 | for(n = 0; n < start_num; n++) |
1784 | struct TrailPoint* tpoint; | 1698 | initialise_asteroid(&asteroids_array[n], LARGE, NULL); |
1785 | struct Point* p; | ||
1786 | int n; | ||
1787 | 1699 | ||
1788 | p = stars; | 1700 | /* ensure all missiles are out of action: */ |
1789 | n = NUM_STARS; | 1701 | missile = missiles_array; |
1790 | while(n--) | 1702 | n = MAX_NUM_MISSILES; |
1703 | while (n--) | ||
1791 | { | 1704 | { |
1792 | p->x = (rb->rand()%LCD_WIDTH); | 1705 | missile->survived = 0; |
1793 | p->y = (rb->rand()%LCD_HEIGHT); | 1706 | missile++; |
1794 | p++; | ||
1795 | } | 1707 | } |
1796 | 1708 | ||
1797 | tpoint = trail_points; | 1709 | tpoint = trail_points; |
1798 | n = NUM_TRAIL_POINTS; | 1710 | n = NUM_TRAIL_POINTS; |
1799 | while(--n) | 1711 | while (n--) |
1800 | { | 1712 | { |
1801 | tpoint->alive = 0; | 1713 | tpoint->alive = 0; |
1802 | tpoint++; | 1714 | tpoint++; |
1803 | } | 1715 | } |
1804 | } | 1716 | } |
1805 | 1717 | ||
1806 | /************************************************* | 1718 | static void initialise_game(void) |
1807 | ** Creates start_num number of new asteroids of | ||
1808 | ** full size. | ||
1809 | **************************************************/ | ||
1810 | void initialise_game(int start_num) | ||
1811 | { | 1719 | { |
1812 | struct Asteroid* asteroid; | 1720 | enemy.appear_probability = ENEMY_APPEAR_PROBABILITY_START; |
1813 | struct Missile* missile; | 1721 | enemy.appear_timing = ENEMY_APPEAR_TIMING_START; |
1814 | int n; | 1722 | enemy.appear_countdown = enemy.appear_timing; |
1815 | asteroid_count = next_missile_count = next_thrust_count = 0; | 1723 | enemy.size_probability = ENEMY_BIG_PROBABILITY_START; |
1724 | current_level = START_LEVEL; | ||
1725 | num_lives = START_LIVES; | ||
1726 | extra_life = EXTRA_LIFE; | ||
1727 | current_score = 0; | ||
1728 | initialise_ship(); | ||
1729 | initialise_level(0); | ||
1730 | game_state = SHOW_LEVEL; | ||
1731 | show_level_timeout = SHOW_LEVEL_TIME; | ||
1732 | } | ||
1816 | 1733 | ||
1817 | /*no enemy*/ | 1734 | /* menu stuff */ |
1818 | enemy.exists = 0; | 1735 | static bool spacerocks_help(void) |
1819 | enemy_missile.survived = 0; | 1736 | { |
1737 | static char *help_text[] = { | ||
1738 | "Spacerocks", "", "Aim", "", "The", "goal", "of", "the", "game", "is", | ||
1739 | "to", "blow", "up", "the", "asteroids", "and", "avoid", "being", "hit", "by", | ||
1740 | "them.", "Also", "you'd", "better", "watch", "out", "for", "the", "UFOs!" | ||
1741 | }; | ||
1742 | static struct style_text formation[]={ | ||
1743 | { 0, TEXT_CENTER|TEXT_UNDERLINE }, | ||
1744 | { 2, C_RED }, | ||
1745 | { -1, 0 } | ||
1746 | }; | ||
1747 | int button; | ||
1820 | 1748 | ||
1821 | /*clear asteroids*/ | 1749 | rb->lcd_setfont(FONT_UI); |
1822 | asteroid = asteroids_array; | 1750 | #ifdef HAVE_LCD_COLOR |
1823 | n = MAX_NUM_ASTEROIDS; | 1751 | rb->lcd_set_background(LCD_BLACK); |
1824 | while(n--) | 1752 | rb->lcd_set_foreground(LCD_WHITE); |
1825 | { | 1753 | #endif |
1826 | asteroid->exists = false; | 1754 | if (display_text(ARRAYLEN(help_text), help_text, formation, NULL) |
1827 | asteroid++; | 1755 | == PLUGIN_USB_CONNECTED) |
1828 | } | 1756 | return true; |
1757 | do { | ||
1758 | button = rb->button_get(true); | ||
1759 | if (button == SYS_USB_CONNECTED) | ||
1760 | return true; | ||
1761 | } while( ( button == BUTTON_NONE ) | ||
1762 | || ( button & (BUTTON_REL|BUTTON_REPEAT) ) ); | ||
1763 | rb->lcd_setfont(FONT_SYSFIXED); | ||
1829 | 1764 | ||
1830 | /*make some LARGE asteroids*/ | 1765 | return false; |
1831 | for(n = 0; n < start_num; n++) | 1766 | } |
1832 | initialise_asteroid(&asteroids_array[n], LARGE); | ||
1833 | 1767 | ||
1834 | /*ensure all missiles are out of action: */ | 1768 | #define PLUGIN_OTHER 10 |
1835 | missile = missiles_array; | 1769 | static bool ingame; |
1836 | n = MAX_NUM_MISSILES; | 1770 | static int spacerocks_menu_cb(int action, const struct menu_item_ex *this_item) |
1837 | while(--n) | 1771 | { |
1772 | if (action == ACTION_REQUEST_MENUITEM | ||
1773 | && !ingame && ((intptr_t)this_item)==0) | ||
1774 | return ACTION_EXIT_MENUITEM; | ||
1775 | return action; | ||
1776 | } | ||
1777 | |||
1778 | static int spacerocks_menu(void) | ||
1779 | { | ||
1780 | int selection = 0; | ||
1781 | MENUITEM_STRINGLIST(main_menu, "Spacerocks Menu", spacerocks_menu_cb, | ||
1782 | "Resume Game", "Start New Game", | ||
1783 | "Help", "High Scores", | ||
1784 | "Playback Control", "Quit"); | ||
1785 | rb->button_clear_queue(); | ||
1786 | |||
1787 | while (1) | ||
1838 | { | 1788 | { |
1839 | missile->survived = 0; | 1789 | switch (rb->do_menu(&main_menu, &selection, NULL, false)) |
1840 | missile++; | 1790 | { |
1791 | case 0: | ||
1792 | return PLUGIN_OTHER; | ||
1793 | case 1: | ||
1794 | initialise_game(); | ||
1795 | return PLUGIN_OTHER; | ||
1796 | case 2: | ||
1797 | if (spacerocks_help()) | ||
1798 | return PLUGIN_USB_CONNECTED; | ||
1799 | break; | ||
1800 | case 3: | ||
1801 | highscore_show(NUM_SCORES, highscores, NUM_SCORES, true); | ||
1802 | break; | ||
1803 | case 4: | ||
1804 | playback_control(NULL); | ||
1805 | break; | ||
1806 | case 5: | ||
1807 | return PLUGIN_OK; | ||
1808 | case MENU_ATTACHED_USB: | ||
1809 | return PLUGIN_USB_CONNECTED; | ||
1810 | default: | ||
1811 | break; | ||
1812 | } | ||
1841 | } | 1813 | } |
1842 | } | 1814 | } |
1843 | 1815 | ||
1844 | static int spacerocks_game_loop(void) | 1816 | static int spacerocks_game_loop(void) |
1845 | { | 1817 | { |
1846 | char s[20]; | 1818 | char str[20]; |
1847 | char level[10]; | ||
1848 | int button; | 1819 | int button; |
1849 | int end; | 1820 | int end; |
1850 | int position; | 1821 | int position; |
1822 | int ret; | ||
1851 | 1823 | ||
1852 | /*create stars once, and once only:*/ | 1824 | if ((ret = spacerocks_menu()) != PLUGIN_OTHER) |
1853 | create_stars(); | 1825 | return ret; |
1854 | |||
1855 | if (spacerocks_menu(false)!=0) | ||
1856 | return 0; | ||
1857 | 1826 | ||
1858 | SET_BG(LCD_BLACK); | 1827 | SET_BG(LCD_BLACK); |
1859 | 1828 | ||
1860 | while(true) | 1829 | ingame = true; |
1830 | while (true) | ||
1861 | { | 1831 | { |
1862 | end = *rb->current_tick + (CYCLETIME * HZ) / 1000; | 1832 | end = *rb->current_tick + (CYCLETIME * HZ) / 1000; |
1863 | rb->lcd_clear_display(); | 1833 | rb->lcd_clear_display(); |
@@ -1865,6 +1835,7 @@ static int spacerocks_game_loop(void) | |||
1865 | switch(game_state) | 1835 | switch(game_state) |
1866 | { | 1836 | { |
1867 | case GAME_OVER: | 1837 | case GAME_OVER: |
1838 | ingame = false; | ||
1868 | rb->splash (HZ * 2, "Game Over"); | 1839 | rb->splash (HZ * 2, "Game Over"); |
1869 | rb->lcd_clear_display(); | 1840 | rb->lcd_clear_display(); |
1870 | position = highscore_update(current_score, current_level, "", | 1841 | position = highscore_update(current_score, current_level, "", |
@@ -1875,13 +1846,12 @@ static int spacerocks_game_loop(void) | |||
1875 | rb->splash(HZ*2, "New High Score"); | 1846 | rb->splash(HZ*2, "New High Score"); |
1876 | highscore_show(position, highscores, NUM_SCORES, true); | 1847 | highscore_show(position, highscores, NUM_SCORES, true); |
1877 | } | 1848 | } |
1878 | if (spacerocks_menu(false)!=0) | 1849 | return PLUGIN_OTHER; |
1879 | return 0; | ||
1880 | break; | 1850 | break; |
1881 | 1851 | ||
1882 | case PAUSE_MODE: | 1852 | case PAUSE_MODE: |
1883 | rb->snprintf(s, sizeof(s), "score %d ", current_score); | 1853 | rb->snprintf(str, sizeof(str), "score %d ", current_score); |
1884 | rb->lcd_putsxy(1,LCD_HEIGHT-8, s); | 1854 | rb->lcd_putsxy(1,LCD_HEIGHT-8, str); |
1885 | rb->lcd_putsxy(CENTER_LCD_X - 15, | 1855 | rb->lcd_putsxy(CENTER_LCD_X - 15, |
1886 | CENTER_LCD_Y + CENTER_LCD_Y/2 - 4, "pause"); | 1856 | CENTER_LCD_Y + CENTER_LCD_Y/2 - 4, "pause"); |
1887 | draw_and_move_missiles(); | 1857 | draw_and_move_missiles(); |
@@ -1890,8 +1860,8 @@ static int spacerocks_game_loop(void) | |||
1890 | break; | 1860 | break; |
1891 | 1861 | ||
1892 | case PLAY_MODE: | 1862 | case PLAY_MODE: |
1893 | rb->snprintf(s, sizeof(s), "score %d ", current_score); | 1863 | rb->snprintf(str, sizeof(str), "score %d ", current_score); |
1894 | rb->lcd_putsxy(1,LCD_HEIGHT-8, s); | 1864 | rb->lcd_putsxy(1, LCD_HEIGHT-8, str); |
1895 | draw_and_move_missiles(); | 1865 | draw_and_move_missiles(); |
1896 | draw_lives(); | 1866 | draw_lives(); |
1897 | check_collisions(); | 1867 | check_collisions(); |
@@ -1899,23 +1869,22 @@ static int spacerocks_game_loop(void) | |||
1899 | break; | 1869 | break; |
1900 | 1870 | ||
1901 | case SHOW_LEVEL: | 1871 | case SHOW_LEVEL: |
1902 | rb->snprintf(s, sizeof(s), "score %d ", current_score); | 1872 | rb->snprintf(str, sizeof(str), "score %d ", current_score); |
1903 | rb->lcd_putsxy(1,LCD_HEIGHT-8, s); | 1873 | rb->lcd_putsxy(1, LCD_HEIGHT-8, str); |
1904 | rb->snprintf(level, sizeof(level), "stage %d ", current_level); | 1874 | rb->snprintf(str, sizeof(str), "stage %d ", current_level); |
1905 | rb->lcd_putsxy(CENTER_LCD_X - 20, | 1875 | rb->lcd_putsxy(CENTER_LCD_X - 20, |
1906 | CENTER_LCD_Y + CENTER_LCD_Y/2 - 4, level); | 1876 | CENTER_LCD_Y + CENTER_LCD_Y/2 - 4, str); |
1907 | draw_and_move_ship(); | ||
1908 | draw_lives(); | 1877 | draw_lives(); |
1878 | draw_and_move_ship(); | ||
1909 | show_level_timeout--; | 1879 | show_level_timeout--; |
1910 | if(!show_level_timeout) | 1880 | if (!show_level_timeout) |
1911 | { | 1881 | { |
1912 | initialise_game(current_level); | 1882 | initialise_level(current_level); |
1913 | game_state = PLAY_MODE; | 1883 | game_state = PLAY_MODE; |
1914 | draw_lives(); | ||
1915 | } | 1884 | } |
1916 | break; | 1885 | break; |
1917 | } | 1886 | } |
1918 | draw_trail_blaze(); | 1887 | draw_and_move_trail_blaze(); |
1919 | drawstars(); | 1888 | drawstars(); |
1920 | draw_and_move_asteroids(); | 1889 | draw_and_move_asteroids(); |
1921 | draw_and_move_enemy(); | 1890 | draw_and_move_enemy(); |
@@ -1930,8 +1899,7 @@ static int spacerocks_game_loop(void) | |||
1930 | switch(button) | 1899 | switch(button) |
1931 | { | 1900 | { |
1932 | case(AST_QUIT): | 1901 | case(AST_QUIT): |
1933 | if (spacerocks_menu(true)!=0) | 1902 | return PLUGIN_OTHER; |
1934 | return 0; | ||
1935 | break; | 1903 | break; |
1936 | #ifdef AST_PAUSE | 1904 | #ifdef AST_PAUSE |
1937 | case(AST_PAUSE): | 1905 | case(AST_PAUSE): |
@@ -1943,19 +1911,19 @@ static int spacerocks_game_loop(void) | |||
1943 | #endif | 1911 | #endif |
1944 | case (AST_LEFT): | 1912 | case (AST_LEFT): |
1945 | case (AST_LEFT | BUTTON_REPEAT): | 1913 | case (AST_LEFT | BUTTON_REPEAT): |
1946 | if(game_state == PLAY_MODE || game_state == SHOW_LEVEL) | 1914 | if (game_state == PLAY_MODE || game_state == SHOW_LEVEL) |
1947 | rotate_ship(SHIP_ROT_ACW_COS, SHIP_ROT_ACW_SIN); | 1915 | rotate_ship(SHIP_ROT_ACW_COS, SHIP_ROT_ACW_SIN); |
1948 | break; | 1916 | break; |
1949 | 1917 | ||
1950 | case (AST_RIGHT): | 1918 | case (AST_RIGHT): |
1951 | case (AST_RIGHT | BUTTON_REPEAT): | 1919 | case (AST_RIGHT | BUTTON_REPEAT): |
1952 | if(game_state == PLAY_MODE || game_state == SHOW_LEVEL) | 1920 | if (game_state == PLAY_MODE || game_state == SHOW_LEVEL) |
1953 | rotate_ship(SHIP_ROT_CW_COS, SHIP_ROT_CW_SIN); | 1921 | rotate_ship(SHIP_ROT_CW_COS, SHIP_ROT_CW_SIN); |
1954 | break; | 1922 | break; |
1955 | 1923 | ||
1956 | case (AST_THRUST): | 1924 | case (AST_THRUST): |
1957 | case (AST_THRUST | BUTTON_REPEAT): | 1925 | case (AST_THRUST | BUTTON_REPEAT): |
1958 | if(game_state == PLAY_MODE || game_state == SHOW_LEVEL) | 1926 | if (game_state == PLAY_MODE || game_state == SHOW_LEVEL) |
1959 | { | 1927 | { |
1960 | if (!next_thrust_count) | 1928 | if (!next_thrust_count) |
1961 | { | 1929 | { |
@@ -1966,9 +1934,9 @@ static int spacerocks_game_loop(void) | |||
1966 | break; | 1934 | break; |
1967 | 1935 | ||
1968 | case (AST_HYPERSPACE): | 1936 | case (AST_HYPERSPACE): |
1969 | if(game_state == PLAY_MODE) | 1937 | if (game_state == PLAY_MODE) |
1970 | hyperspace(); | 1938 | hyperspace(); |
1971 | /*maybe shield if it gets too hard */ | 1939 | /* maybe shield if it gets too hard */ |
1972 | break; | 1940 | break; |
1973 | 1941 | ||
1974 | case (AST_FIRE): | 1942 | case (AST_FIRE): |
@@ -1991,10 +1959,10 @@ static int spacerocks_game_loop(void) | |||
1991 | break; | 1959 | break; |
1992 | } | 1960 | } |
1993 | 1961 | ||
1994 | if(next_missile_count) | 1962 | if (next_missile_count) |
1995 | next_missile_count--; | 1963 | next_missile_count--; |
1996 | 1964 | ||
1997 | if(next_thrust_count) | 1965 | if (next_thrust_count) |
1998 | next_thrust_count--; | 1966 | next_thrust_count--; |
1999 | 1967 | ||
2000 | if (TIME_BEFORE(*rb->current_tick, end)) | 1968 | if (TIME_BEFORE(*rb->current_tick, end)) |
@@ -2007,6 +1975,7 @@ static int spacerocks_game_loop(void) | |||
2007 | enum plugin_status plugin_start(const void* parameter) | 1975 | enum plugin_status plugin_start(const void* parameter) |
2008 | { | 1976 | { |
2009 | (void)parameter; | 1977 | (void)parameter; |
1978 | int ret = PLUGIN_OTHER; | ||
2010 | 1979 | ||
2011 | #if LCD_DEPTH > 1 | 1980 | #if LCD_DEPTH > 1 |
2012 | rb->lcd_set_backdrop(NULL); | 1981 | rb->lcd_set_backdrop(NULL); |
@@ -2017,12 +1986,16 @@ enum plugin_status plugin_start(const void* parameter) | |||
2017 | backlight_force_on(); /* backlight control in lib/helper.c */ | 1986 | backlight_force_on(); /* backlight control in lib/helper.c */ |
2018 | highscore_load(HIGH_SCORE, highscores, NUM_SCORES); | 1987 | highscore_load(HIGH_SCORE, highscores, NUM_SCORES); |
2019 | 1988 | ||
2020 | spacerocks_game_loop(); | 1989 | /* create stars once, and once only: */ |
1990 | create_stars(); | ||
1991 | |||
1992 | while (ret == PLUGIN_OTHER) | ||
1993 | ret = spacerocks_game_loop(); | ||
2021 | 1994 | ||
2022 | rb->lcd_setfont(FONT_UI); | 1995 | rb->lcd_setfont(FONT_UI); |
2023 | highscore_save(HIGH_SCORE, highscores, NUM_SCORES); | 1996 | highscore_save(HIGH_SCORE, highscores, NUM_SCORES); |
2024 | /* Turn on backlight timeout (revert to settings) */ | 1997 | /* Turn on backlight timeout (revert to settings) */ |
2025 | backlight_use_settings(); /* backlight control in lib/helper.c */ | 1998 | backlight_use_settings(); /* backlight control in lib/helper.c */ |
2026 | 1999 | ||
2027 | return PLUGIN_OK; | 2000 | return ret; |
2028 | } | 2001 | } |