1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 by Mat Holton
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 #include "lib/display_text.h"
24 #include "lib/helper.h"
25 #include "lib/highscore.h"
26 #include "lib/playback_control.h"
30 /* variable button definitions */
31 #if CONFIG_KEYPAD == RECORDER_PAD
32 #define AST_PAUSE BUTTON_ON
33 #define AST_QUIT BUTTON_OFF
34 #define AST_THRUST BUTTON_UP
35 #define AST_HYPERSPACE BUTTON_DOWN
36 #define AST_LEFT BUTTON_LEFT
37 #define AST_RIGHT BUTTON_RIGHT
38 #define AST_FIRE BUTTON_PLAY
40 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
41 #define AST_PAUSE BUTTON_ON
42 #define AST_QUIT BUTTON_OFF
43 #define AST_THRUST BUTTON_UP
44 #define AST_HYPERSPACE BUTTON_DOWN
45 #define AST_LEFT BUTTON_LEFT
46 #define AST_RIGHT BUTTON_RIGHT
47 #define AST_FIRE BUTTON_SELECT
49 #elif CONFIG_KEYPAD == ONDIO_PAD
50 #define AST_PAUSE (BUTTON_MENU | BUTTON_OFF)
51 #define AST_QUIT BUTTON_OFF
52 #define AST_THRUST BUTTON_UP
53 #define AST_HYPERSPACE BUTTON_DOWN
54 #define AST_LEFT BUTTON_LEFT
55 #define AST_RIGHT BUTTON_RIGHT
56 #define AST_FIRE BUTTON_MENU
58 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
59 (CONFIG_KEYPAD == IRIVER_H300_PAD)
60 #define AST_PAUSE BUTTON_REC
61 #define AST_QUIT BUTTON_OFF
62 #define AST_THRUST BUTTON_UP
63 #define AST_HYPERSPACE BUTTON_DOWN
64 #define AST_LEFT BUTTON_LEFT
65 #define AST_RIGHT BUTTON_RIGHT
66 #define AST_FIRE BUTTON_SELECT
68 #define AST_RC_QUIT BUTTON_RC_STOP
70 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
71 #define AST_PAUSE BUTTON_PLAY
72 #define AST_QUIT BUTTON_POWER
73 #define AST_THRUST BUTTON_UP
74 #define AST_HYPERSPACE BUTTON_DOWN
75 #define AST_LEFT BUTTON_LEFT
76 #define AST_RIGHT BUTTON_RIGHT
77 #define AST_FIRE BUTTON_SELECT
79 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
80 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
81 #define AST_PAUSE (BUTTON_SELECT | BUTTON_PLAY)
82 #define AST_QUIT (BUTTON_SELECT | BUTTON_MENU)
83 #define AST_THRUST BUTTON_MENU
84 #define AST_HYPERSPACE BUTTON_PLAY
85 #define AST_LEFT BUTTON_SCROLL_BACK
86 #define AST_RIGHT BUTTON_SCROLL_FWD
87 #define AST_FIRE BUTTON_SELECT
89 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
90 #define AST_PAUSE BUTTON_A
91 #define AST_QUIT BUTTON_POWER
92 #define AST_THRUST BUTTON_UP
93 #define AST_HYPERSPACE BUTTON_DOWN
94 #define AST_LEFT BUTTON_LEFT
95 #define AST_RIGHT BUTTON_RIGHT
96 #define AST_FIRE BUTTON_SELECT
98 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
99 #define AST_PAUSE BUTTON_REC
100 #define AST_QUIT BUTTON_POWER
101 #define AST_THRUST BUTTON_UP
102 #define AST_HYPERSPACE BUTTON_DOWN
103 #define AST_LEFT BUTTON_SCROLL_BACK
104 #define AST_RIGHT BUTTON_SCROLL_FWD
105 #define AST_FIRE BUTTON_SELECT
107 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
108 #define AST_PAUSE (BUTTON_SELECT | BUTTON_UP)
109 #define AST_QUIT (BUTTON_HOME|BUTTON_REPEAT)
110 #define AST_THRUST BUTTON_UP
111 #define AST_HYPERSPACE BUTTON_DOWN
112 #define AST_LEFT BUTTON_SCROLL_BACK
113 #define AST_RIGHT BUTTON_SCROLL_FWD
114 #define AST_FIRE BUTTON_SELECT
116 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
117 #define AST_PAUSE BUTTON_REC
118 #define AST_QUIT BUTTON_POWER
119 #define AST_THRUST BUTTON_UP
120 #define AST_HYPERSPACE BUTTON_DOWN
121 #define AST_LEFT BUTTON_LEFT
122 #define AST_RIGHT BUTTON_RIGHT
123 #define AST_FIRE BUTTON_SELECT
125 #elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
126 #define AST_PAUSE BUTTON_HOME
127 #define AST_QUIT BUTTON_POWER
128 #define AST_THRUST BUTTON_UP
129 #define AST_HYPERSPACE BUTTON_DOWN
130 #define AST_LEFT BUTTON_LEFT
131 #define AST_RIGHT BUTTON_RIGHT
132 #define AST_FIRE BUTTON_SELECT
134 #elif (CONFIG_KEYPAD == SANSA_M200_PAD)
135 #define AST_PAUSE (BUTTON_SELECT | BUTTON_UP)
136 #define AST_QUIT BUTTON_POWER
137 #define AST_THRUST BUTTON_UP
138 #define AST_HYPERSPACE BUTTON_DOWN
139 #define AST_LEFT BUTTON_LEFT
140 #define AST_RIGHT BUTTON_RIGHT
141 #define AST_FIRE (BUTTON_SELECT | BUTTON_REL)
143 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
144 #define AST_PAUSE BUTTON_PLAY
145 #define AST_QUIT BUTTON_POWER
146 #define AST_THRUST BUTTON_SCROLL_UP
147 #define AST_HYPERSPACE BUTTON_SCROLL_DOWN
148 #define AST_LEFT BUTTON_LEFT
149 #define AST_RIGHT BUTTON_RIGHT
150 #define AST_FIRE BUTTON_REW
152 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
153 #define AST_PAUSE BUTTON_PLAY
154 #define AST_QUIT BUTTON_BACK
155 #define AST_THRUST BUTTON_UP
156 #define AST_HYPERSPACE BUTTON_DOWN
157 #define AST_LEFT BUTTON_LEFT
158 #define AST_RIGHT BUTTON_RIGHT
159 #define AST_FIRE BUTTON_SELECT
161 #elif (CONFIG_KEYPAD == MROBE100_PAD)
162 #define AST_PAUSE BUTTON_DISPLAY
163 #define AST_QUIT BUTTON_POWER
164 #define AST_THRUST BUTTON_UP
165 #define AST_HYPERSPACE BUTTON_DOWN
166 #define AST_LEFT BUTTON_LEFT
167 #define AST_RIGHT BUTTON_RIGHT
168 #define AST_FIRE BUTTON_SELECT
170 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
171 #define AST_PAUSE BUTTON_RC_PLAY
172 #define AST_QUIT BUTTON_RC_REC
173 #define AST_THRUST BUTTON_RC_VOL_UP
174 #define AST_HYPERSPACE BUTTON_RC_VOL_DOWN
175 #define AST_LEFT BUTTON_RC_REW
176 #define AST_RIGHT BUTTON_RC_FF
177 #define AST_FIRE BUTTON_RC_MODE
179 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
180 #define AST_QUIT BUTTON_POWER
182 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
183 #define AST_PAUSE BUTTON_PLAY
184 #define AST_QUIT BUTTON_BACK
185 #define AST_THRUST BUTTON_UP
186 #define AST_HYPERSPACE BUTTON_DOWN
187 #define AST_LEFT BUTTON_LEFT
188 #define AST_RIGHT BUTTON_RIGHT
189 #define AST_FIRE BUTTON_SELECT
191 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
192 #define AST_PAUSE BUTTON_VIEW
193 #define AST_QUIT BUTTON_POWER
194 #define AST_THRUST BUTTON_UP
195 #define AST_HYPERSPACE BUTTON_DOWN
196 #define AST_LEFT BUTTON_LEFT
197 #define AST_RIGHT BUTTON_RIGHT
198 #define AST_FIRE BUTTON_PLAYLIST
200 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
201 #define AST_PAUSE BUTTON_RIGHT
202 #define AST_QUIT BUTTON_POWER
203 #define AST_THRUST BUTTON_UP
204 #define AST_HYPERSPACE BUTTON_DOWN
205 #define AST_LEFT BUTTON_PREV
206 #define AST_RIGHT BUTTON_NEXT
207 #define AST_FIRE BUTTON_LEFT
209 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || \
210 (CONFIG_KEYPAD == ONDAVX777_PAD) || \
211 (CONFIG_KEYPAD == MROBE500_PAD)
212 #define AST_QUIT BUTTON_POWER
214 #elif (CONFIG_KEYPAD == SAMSUNG_YH_PAD)
215 #define AST_PAUSE BUTTON_FFWD
216 #define AST_QUIT BUTTON_REC
217 #define AST_THRUST BUTTON_UP
218 #define AST_HYPERSPACE BUTTON_DOWN
219 #define AST_LEFT BUTTON_LEFT
220 #define AST_RIGHT BUTTON_RIGHT
221 #define AST_FIRE BUTTON_PLAY
224 #error No keymap defined!
227 #ifdef HAVE_TOUCHSCREEN
229 #define AST_PAUSE BUTTON_CENTER
232 #define AST_QUIT BUTTON_TOPLEFT
235 #define AST_THRUST BUTTON_TOPMIDDLE
237 #ifndef AST_HYPERSPACE
238 #define AST_HYPERSPACE BUTTON_TOPRIGHT
241 #define AST_LEFT BUTTON_MIDLEFT
244 #define AST_RIGHT BUTTON_MIDRIGHT
247 #define AST_FIRE BUTTON_BOTTOMMIDDLE
251 #define RES MAX(LCD_WIDTH, LCD_HEIGHT)
252 #define LARGE_LCD (RES >= 200)
258 #define WRAP_GAP (LARGE*SCALE*3)
260 #define START_LEVEL 1
261 #define SHOW_LEVEL_TIME 50
262 #define EXPLOSION_LENGTH 20
264 #define MAX_NUM_ASTEROIDS 25
265 #define MAX_NUM_MISSILES 6
267 #define NUM_TRAIL_POINTS 70
268 #define MAX_LEVEL MAX_NUM_ASTEROIDS
270 #define NUM_ASTEROID_VERTICES 10
271 #define NUM_SHIP_VERTICES 4
272 #define NUM_ENEMY_VERTICES 8
274 #define INVULNERABLE_TIME 30
275 #define BLINK_TIME 10
276 #define EXTRA_LIFE 250
277 #define START_LIVES 3
278 #define MISSILE_LIFE_LENGTH 40
280 #define ASTEROID_SPEED (RES/20)
281 #define SPACE_CHECK_SIZE 30*SCALE
284 #define SIZE_SHIP_COLLISION 8*SCALE
286 #define SIZE_SHIP_COLLISION 6*SCALE
289 #define LITTLE_SHIP 1
291 #define ENEMY_BIG_PROBABILITY_START 10
292 #define ENEMY_APPEAR_PROBABILITY_START 35
293 #define ENEMY_APPEAR_TIMING_START 600
294 #define ENEMY_SPEED 4
295 #define ENEMY_MISSILE_LIFE_LENGTH (RES/2)
297 #define SIZE_ENEMY_COLLISION 7*SCALE
299 #define SIZE_ENEMY_COLLISION 5*SCALE
302 #define SIN_COS_SCALE 10000
304 #define FAST_ROT_CW_SIN 873
305 #define FAST_ROT_CW_COS 9963
306 #define FAST_ROT_ACW_SIN -873
307 #define FAST_ROT_ACW_COS 9963
309 #define MEDIUM_ROT_CW_SIN 350
310 #define MEDIUM_ROT_CW_COS 9994
311 #define MEDIUM_ROT_ACW_SIN -350
312 #define MEDIUM_ROT_ACW_COS 9994
314 #define SLOW_ROT_CW_SIN 350
315 #define SLOW_ROT_CW_COS 9994
316 #define SLOW_ROT_ACW_SIN -350
317 #define SLOW_ROT_ACW_COS 9994
319 #ifdef HAVE_LCD_COLOR
320 #define SHIP_ROT_CW_SIN 2419
321 #define SHIP_ROT_CW_COS 9702
322 #define SHIP_ROT_ACW_SIN -2419
323 #define SHIP_ROT_ACW_COS 9702
325 #define SHIP_ROT_CW_SIN 3827
326 #define SHIP_ROT_CW_COS 9239
327 #define SHIP_ROT_ACW_SIN -3827
328 #define SHIP_ROT_ACW_COS 9239
332 #define SCALED_WIDTH (LCD_WIDTH*SCALE)
333 #define SCALED_HEIGHT (LCD_HEIGHT*SCALE)
334 #define CENTER_LCD_X (LCD_WIDTH/2)
335 #define CENTER_LCD_Y (LCD_HEIGHT/2)
337 #ifdef HAVE_LCD_COLOR
338 #define ASTEROID_R 230
339 #define ASTEROID_G 200
340 #define ASTEROID_B 100
351 #define COL_MISSILE LCD_RGBPACK(200,0,0)
352 #define COL_PLAYER LCD_RGBPACK(200,200,200)
353 #define COL_INVULN LCD_RGBPACK(100,100,200)
354 #define COL_STARS LCD_WHITE
355 #define COL_ASTEROID LCD_RGBPACK(ASTEROID_R,ASTEROID_G,ASTEROID_B)
356 #define COL_TEXT LCD_RGBPACK(200,200,255)
357 #define COL_ENEMY LCD_RGBPACK(ENEMY_R,ENEMY_G,ENEMY_B)
358 #define SET_FG rb->lcd_set_foreground
359 #define SET_BG rb->lcd_set_background
365 #define HIGH_SCORE PLUGIN_GAMES_DIR "/spacerocks.score"
368 static struct highscore highscores
[NUM_SCORES
];
370 /* The array of points that make up an asteroid */
371 static const short asteroid_one
[NUM_ASTEROID_VERTICES
*2] =
385 /* The array of points that make up an asteroid */
386 static const short asteroid_two
[NUM_ASTEROID_VERTICES
*2] =
400 /* The array of points that make up an asteroid */
401 static const short asteroid_three
[NUM_ASTEROID_VERTICES
*2] =
415 /* The array of points the make up the ship */
416 static const short ship_vertices
[NUM_SHIP_VERTICES
*2] =
431 /* The array of points the make up the bad spaceship */
432 static const short enemy_vertices
[NUM_ENEMY_VERTICES
*2] =
494 struct Point position
;
496 #ifdef HAVE_LCD_COLOR
504 /* Asteroid structure, contains an array of points */
507 struct Point position
;
508 struct Point rotation
;
509 struct Point vertices
[NUM_ASTEROID_VERTICES
];
511 int explode_countdown
;
512 enum asteroid_type type
;
520 struct Point position
;
521 struct Point rotation
;
522 struct Point vertices
[NUM_SHIP_VERTICES
];
524 int explode_countdown
;
525 int invulnerable_time
;
530 struct Point position
;
531 struct Point vertices
[NUM_ENEMY_VERTICES
];
533 int explode_countdown
;
534 int appear_countdown
;
535 short size_probability
;
536 short appear_probability
;
542 struct Point position
;
543 struct Point oldpoint
;
547 static enum game_state game_state
;
548 static int asteroid_count
;
549 static int next_missile_count
;
550 static int next_thrust_count
;
551 static int num_lives
;
552 static int extra_life
;
553 static int show_level_timeout
;
554 static int current_level
;
555 static int current_score
;
557 static struct Ship ship
;
558 static struct Point stars
[NUM_STARS
];
559 static struct Asteroid asteroids_array
[MAX_NUM_ASTEROIDS
];
560 static struct Missile missiles_array
[MAX_NUM_MISSILES
];
561 static struct Missile enemy_missile
;
562 static struct Enemy enemy
;
563 static struct Point lives_points
[NUM_SHIP_VERTICES
];
564 static struct TrailPoint trail_points
[NUM_TRAIL_POINTS
];
566 /*************************************************
567 ** Handle polygon and point
568 *************************************************/
570 /* Check if point is in a polygon */
571 static bool is_point_in_polygon(struct Point
* vertices
, int num_vertices
,
579 if (x
< -SCALED_WIDTH
/2) x
+= SCALED_WIDTH
;
580 else if (x
> SCALED_WIDTH
/2) x
-= SCALED_WIDTH
;
581 if (y
< -SCALED_HEIGHT
/2) y
+= SCALED_HEIGHT
;
582 else if (y
> SCALED_HEIGHT
/2) y
-= SCALED_HEIGHT
;
585 pj
= vertices
+ num_vertices
-1;
590 if ((((pi
->y
<= y
) && (y
< pj
->y
)) || ((pj
->y
<= y
) && (y
< pi
->y
))) &&
591 (x
< (pj
->x
- pi
->x
) * (y
- pi
->y
) / (pj
->y
- pi
->y
) + pi
->x
))
601 /* Check if point is within a rectangle */
602 static bool is_point_within_rectangle(struct Point
* rect
, struct Point
* p
,
605 int dx
= p
->x
- rect
->x
;
606 int dy
= p
->y
- rect
->y
;
608 rb
->lcd_drawrect((rect
->x
- size
)/SCALE
, (rect
->y
- size
)/SCALE
,
609 (size
*2+1)/SCALE
, (size
*2+1)/SCALE
);
611 if (dx
< -SCALED_WIDTH
/2) dx
+= SCALED_WIDTH
;
612 else if (dx
> SCALED_WIDTH
/2) dx
-= SCALED_WIDTH
;
613 if (dy
< -SCALED_HEIGHT
/2) dy
+= SCALED_HEIGHT
;
614 else if (dy
> SCALED_HEIGHT
/2) dy
-= SCALED_HEIGHT
;
615 return (dx
> -size
&& dx
< size
&& dy
> -size
&& dy
< size
);
619 static void rotate_polygon(struct Point
* vertices
, int num_vertices
,
620 struct Point
* rotation
, int cos
, int sin
)
626 temp_x
= rotation
->x
;
627 temp_y
= rotation
->y
;
628 rotation
->x
= (temp_x
*cos
- temp_y
*sin
)/SIN_COS_SCALE
;
629 rotation
->y
= (temp_y
*cos
+ temp_x
*sin
)/SIN_COS_SCALE
;
630 #define MIN_SCALE (SIN_COS_SCALE-10)
631 #define MAX_SCALE (SIN_COS_SCALE+10)
632 /* normalize vector. this is not accurate but would be enough. */
633 temp_x
= rotation
->x
*rotation
->x
+ rotation
->y
*rotation
->y
;
634 if (temp_x
<= MIN_SCALE
*MIN_SCALE
)
636 rotation
->x
= rotation
->x
*SIN_COS_SCALE
/MIN_SCALE
;
637 rotation
->y
= rotation
->y
*SIN_COS_SCALE
/MIN_SCALE
;
639 else if (temp_x
>= MAX_SCALE
*MAX_SCALE
)
641 rotation
->x
= rotation
->x
*SIN_COS_SCALE
/MAX_SCALE
;
642 rotation
->y
= rotation
->y
*SIN_COS_SCALE
/MAX_SCALE
;
651 point
->x
= (point
->dx
*rotation
->x
- point
->dy
*rotation
->y
)/SIN_COS_SCALE
;
652 point
->y
= (point
->dy
*rotation
->x
+ point
->dx
*rotation
->y
)/SIN_COS_SCALE
;
658 static void draw_polygon(struct Point
* vertices
, int num_vertices
,
661 int n
, new_x
, new_y
, old_x
, old_y
;
665 if (px
> SCALED_WIDTH
- WRAP_GAP
)
667 if (py
> SCALED_HEIGHT
- WRAP_GAP
)
670 draw_wrap
= (px
< WRAP_GAP
|| py
< WRAP_GAP
);
672 p
= vertices
+ num_vertices
- 1;
673 old_x
= (p
->x
+ px
)/SCALE
;
674 old_y
= (p
->y
+ py
)/SCALE
;
679 new_x
= (p
->x
+ px
)/SCALE
;
680 new_y
= (p
->y
+ py
)/SCALE
;
682 rb
->lcd_drawline(old_x
, old_y
, new_x
, new_y
);
685 rb
->lcd_drawline(old_x
+ LCD_WIDTH
, old_y
, new_x
+ LCD_WIDTH
, new_y
);
686 rb
->lcd_drawline(old_x
, old_y
+ LCD_HEIGHT
, new_x
, 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
);
696 static void move_point(struct Point
* point
)
698 point
->x
+= point
->dx
;
699 point
->y
+= point
->dy
;
701 /* Check bounds on the x-axis: */
702 point
->x
%= SCALED_WIDTH
;
704 point
->x
+= SCALED_WIDTH
;
706 /* Check bounds on the y-axis: */
707 point
->y
%= SCALED_HEIGHT
;
709 point
->y
+= SCALED_HEIGHT
;
712 /*************************************************
713 ** Handle trail blaiz.
714 *************************************************/
716 static void create_ship_trail(struct TrailPoint
* tpoint
)
718 tpoint
->position
.x
+= ship
.vertices
[2].x
;
719 tpoint
->position
.y
+= ship
.vertices
[2].y
;
720 tpoint
->position
.dx
= -( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/10;
721 tpoint
->position
.dy
= -( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/10;
724 static void create_explosion_trail(struct TrailPoint
* tpoint
)
726 tpoint
->position
.dx
= (rb
->rand()%5001)-2500;
727 tpoint
->position
.dy
= (rb
->rand()%5001)-2500;
730 static void create_trail_blaze(int colour
, struct Point
* position
)
733 struct TrailPoint
* tpoint
;
736 if (colour
!= EXPLOSION_SHIP
)
738 numtoadd
= NUM_TRAIL_POINTS
/5;
742 numtoadd
= NUM_TRAIL_POINTS
/8;
745 /* give the point a random countdown timer, so they dissapears at different
747 tpoint
= trail_points
;
748 n
= NUM_TRAIL_POINTS
;
751 /* find a space in the array of trail_points that is NULL or DEAD or
752 whatever and place this one here. */
753 if (tpoint
->alive
<= 0)
755 /* take a random point near the position. */
756 tpoint
->position
.x
= (rb
->rand()%18000)-9000 + position
->x
;
757 tpoint
->position
.y
= (rb
->rand()%18000)-9000 + position
->y
;
762 create_explosion_trail(tpoint
);
764 #ifdef HAVE_LCD_COLOR
771 case EXPLOSION_ASTEROID
:
772 create_explosion_trail(tpoint
);
774 #ifdef HAVE_LCD_COLOR
775 tpoint
->r
= ASTEROID_R
;
776 tpoint
->g
= ASTEROID_G
;
777 tpoint
->b
= ASTEROID_B
;
781 case EXPLOSION_ENEMY
:
782 create_explosion_trail(tpoint
);
784 #ifdef HAVE_LCD_COLOR
791 case EXPLOSION_THRUST
:
792 create_ship_trail(tpoint
);
794 #ifdef HAVE_LCD_COLOR
795 tpoint
->r
= THRUST_R
;
796 tpoint
->g
= THRUST_G
;
797 tpoint
->b
= THRUST_B
;
803 /* give the points a speed based on direction of travel
805 tpoint
->position
.dx
+= position
->dx
;
806 tpoint
->position
.dy
+= position
->dy
;
816 static void draw_and_move_trail_blaze(void)
818 struct TrailPoint
* tpoint
;
821 /* loop through, if alive then move and draw.
822 when drawn, countdown it's timer.
825 tpoint
= trail_points
;
826 n
= NUM_TRAIL_POINTS
;
829 if (tpoint
->alive
> 0)
831 if (game_state
!= PAUSE_MODE
)
834 move_point(&(tpoint
->position
));
835 #ifdef HAVE_LCD_COLOR
836 /* intensity = tpoint->alive/2; */
837 if (tpoint
->r
>= tpoint
->dec
) tpoint
->r
-= tpoint
->dec
;
838 if (tpoint
->g
>= tpoint
->dec
) tpoint
->g
-= tpoint
->dec
;
839 if (tpoint
->b
>= tpoint
->dec
) tpoint
->b
-= tpoint
->dec
;
842 SET_FG(LCD_RGBPACK(tpoint
->r
, tpoint
->g
, tpoint
->b
));
843 rb
->lcd_drawpixel(tpoint
->position
.x
/SCALE
, tpoint
->position
.y
/SCALE
);
849 /*************************************************
851 *************************************************/
853 static void rotate_asteroid(struct Asteroid
* asteroid
)
855 rotate_polygon(asteroid
->vertices
, NUM_ASTEROID_VERTICES
,
857 asteroid
->speed_cos
, asteroid
->speed_sin
);
860 /* Initialise the passed Asteroid.
861 * if position is NULL, place it at the random loacation
862 * where ship doesn't exist
864 static void initialise_asteroid(struct Asteroid
* asteroid
,
865 enum asteroid_type type
, struct Point
*position
)
867 const short *asteroid_vertices
;
871 asteroid
->exists
= true;
872 asteroid
->explode_countdown
= 0;
873 asteroid
->type
= type
;
875 /* Set the radius of the asteroid: */
876 asteroid
->radius
= (int)type
*SCALE
*3;
878 /* shall we move Clockwise and Fast */
882 asteroid
->speed_cos
= FAST_ROT_CW_COS
;
883 asteroid
->speed_sin
= FAST_ROT_CW_SIN
;
887 asteroid
->speed_cos
= FAST_ROT_ACW_COS
;
888 asteroid
->speed_sin
= FAST_ROT_ACW_SIN
;
892 asteroid
->speed_cos
= SLOW_ROT_ACW_COS
;
893 asteroid
->speed_sin
= SLOW_ROT_ACW_SIN
;
897 asteroid
->speed_cos
= SLOW_ROT_CW_COS
;
898 asteroid
->speed_sin
= SLOW_ROT_CW_SIN
;
903 asteroid_vertices
= asteroid_one
;
905 asteroid_vertices
= asteroid_two
;
907 asteroid_vertices
= asteroid_three
;
909 point
= asteroid
->vertices
;
910 for(n
= 0; n
< NUM_ASTEROID_VERTICES
*2; n
+= 2)
912 point
->x
= asteroid_vertices
[n
];
913 point
->y
= asteroid_vertices
[n
+1];
914 point
->x
*= asteroid
->radius
/20;
915 point
->y
*= asteroid
->radius
/20;
916 /* dx and dy are used when rotate polygon */
917 point
->dx
= point
->x
;
918 point
->dy
= point
->y
;
925 /* Set the position randomly: */
926 asteroid
->position
.x
= (rb
->rand()%SCALED_WIDTH
);
927 asteroid
->position
.y
= (rb
->rand()%SCALED_HEIGHT
);
928 } while (is_point_within_rectangle(&ship
.position
, &asteroid
->position
,
933 asteroid
->position
.x
= position
->x
;
934 asteroid
->position
.y
= position
->y
;
938 asteroid
->position
.dx
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
939 } while (asteroid
->position
.dx
== 0);
942 asteroid
->position
.dy
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
943 } while (asteroid
->position
.dy
== 0);
945 asteroid
->position
.dx
*= SCALE
/10;
946 asteroid
->position
.dy
*= SCALE
/10;
948 asteroid
->rotation
.x
= SIN_COS_SCALE
;
949 asteroid
->rotation
.y
= 0;
951 /* Now rotate the asteroid a bit, so they all look a bit different */
952 for(n
= (rb
->rand()%30)+2; n
--; )
953 rotate_asteroid(asteroid
);
955 /* great, we've created an asteroid, don't forget to increment the total: */
960 * Creates a new asteroid of the given 4type (size) and at the given location.
962 static void create_asteroid(enum asteroid_type type
, struct Point
*position
)
964 struct Asteroid
* asteroid
;
967 asteroid
= asteroids_array
;
968 n
= MAX_NUM_ASTEROIDS
;
971 if (!asteroid
->exists
&& asteroid
->explode_countdown
<= 0)
973 initialise_asteroid(asteroid
, type
, position
);
980 /* Draw and move all asteroids */
981 static void draw_and_move_asteroids(void)
983 struct Asteroid
* asteroid
;
986 SET_FG(COL_ASTEROID
);
988 asteroid
= asteroids_array
;
989 n
= MAX_NUM_ASTEROIDS
;
992 if (asteroid
->exists
)
994 draw_polygon(asteroid
->vertices
, NUM_ASTEROID_VERTICES
,
995 asteroid
->position
.x
, asteroid
->position
.y
);
997 if (game_state
!= PAUSE_MODE
)
999 if (asteroid
->exists
)
1001 move_point(&asteroid
->position
);
1002 rotate_asteroid(asteroid
);
1004 else if (asteroid
->explode_countdown
> 0)
1006 asteroid
->explode_countdown
--;
1013 static void explode_asteroid(struct Asteroid
* asteroid
)
1016 p
.dx
= asteroid
->position
.dx
;
1017 p
.dy
= asteroid
->position
.dy
;
1018 p
.x
= asteroid
->position
.x
;
1019 p
.y
= asteroid
->position
.y
;
1022 asteroid
->exists
= false;
1024 switch(asteroid
->type
)
1027 asteroid
->explode_countdown
= EXPLOSION_LENGTH
;
1028 create_trail_blaze(EXPLOSION_ASTEROID
, &p
);
1032 create_asteroid(SMALL
, &p
);
1033 create_asteroid(SMALL
, &p
);
1037 create_asteroid(MEDIUM
, &p
);
1038 create_asteroid(MEDIUM
, &p
);
1043 /*************************************************
1045 *************************************************/
1047 /* Initialise the ship */
1048 static void initialise_ship(void)
1050 struct Point
* point
;
1051 struct Point
* lives_point
;
1054 ship
.position
.x
= CENTER_LCD_X
* SCALE
;
1055 ship
.position
.y
= CENTER_LCD_Y
* SCALE
;
1056 ship
.position
.dx
= 0;
1057 ship
.position
.dy
= 0;
1058 ship
.rotation
.x
= SIN_COS_SCALE
;
1059 ship
.rotation
.y
= 0;
1061 ship
.explode_countdown
= 0;
1062 ship
.invulnerable_time
= INVULNERABLE_TIME
;
1064 point
= ship
.vertices
;
1065 lives_point
= lives_points
;
1066 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+= 2)
1068 point
->x
= ship_vertices
[n
];
1069 point
->y
= ship_vertices
[n
+1];
1072 /* dx and dy are used when rotate polygon */
1073 point
->dx
= point
->x
;
1074 point
->dy
= point
->y
;
1075 /* grab a copy of the ships points for the lives display: */
1076 lives_point
->x
= point
->x
;
1077 lives_point
->y
= point
->y
;
1085 * Draws the ship, moves the ship and creates a new
1086 * one if it's finished exploding.
1088 static void draw_and_move_ship(void)
1090 if (ship
.invulnerable_time
> BLINK_TIME
|| ship
.invulnerable_time
% 2 != 0)
1101 draw_polygon(ship
.vertices
, NUM_SHIP_VERTICES
,
1102 ship
.position
.x
, ship
.position
.y
);
1105 if (game_state
!= PAUSE_MODE
)
1109 if (ship
.invulnerable_time
> 0)
1110 ship
.invulnerable_time
--;
1111 move_point(&ship
.position
);
1113 else if (ship
.explode_countdown
> 0)
1115 ship
.explode_countdown
--;
1116 if (ship
.explode_countdown
<= 0)
1121 game_state
= GAME_OVER
;
1132 static void explode_ship(void)
1134 if (!ship
.invulnerable_time
)
1136 /* if not invulnerable, blow up ship */
1137 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1138 ship
.exists
= false;
1139 create_trail_blaze(EXPLOSION_SHIP
, &ship
.position
);
1143 /* Rotate the ship using the passed sin & cos values */
1144 static void rotate_ship(int cos
, int sin
)
1148 rotate_polygon(ship
.vertices
, NUM_SHIP_VERTICES
,
1149 &ship
.rotation
, cos
, sin
);
1153 static void thrust_ship(void)
1157 ship
.position
.dx
+= ( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/20;
1158 ship
.position
.dy
+= ( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/20;
1160 /* if dx and dy are below a certain threshold, then set 'em to 0
1161 but to do this we need to ascertain if the spacehip as moved on
1162 screen for more than a certain amount. */
1164 create_trail_blaze(EXPLOSION_THRUST
, &ship
.position
);
1168 /* stop movement of ship, 'cos that's what happens when you go into hyperspace. */
1169 static void hyperspace(void)
1173 ship
.position
.dx
= ship
.position
.dy
= 0;
1174 ship
.position
.x
= (rb
->rand()%SCALED_WIDTH
);
1175 ship
.position
.y
= (rb
->rand()%SCALED_HEIGHT
);
1179 static void draw_lives(void)
1183 int px
= (LCD_WIDTH
-1 - 4)*SCALE
;
1184 int py
= (LCD_HEIGHT
-1 - 6)*SCALE
;
1186 int px
= (LCD_WIDTH
-1 - 3)*SCALE
;
1187 int py
= (LCD_HEIGHT
-1 - 4)*SCALE
;
1195 draw_polygon(lives_points
, NUM_SHIP_VERTICES
, px
, py
);
1208 /* Initialise a missile */
1209 static void initialise_missile(struct Missile
* missile
)
1211 missile
->position
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1212 missile
->position
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1213 missile
->position
.dx
= (ship
.vertices
[0].x
- ship
.vertices
[2].x
)/2;
1214 missile
->position
.dy
= (ship
.vertices
[0].y
- ship
.vertices
[2].y
)/2;
1215 missile
->alive
= MISSILE_LIFE_LENGTH
;
1216 missile
->oldpoint
.x
= missile
->position
.x
;
1217 missile
->oldpoint
.y
= missile
->position
.y
;
1220 /* Fire the next missile */
1221 static void fire_missile(void)
1223 struct Missile
* missile
;
1228 missile
= missiles_array
;
1229 n
= MAX_NUM_MISSILES
;
1232 if (missile
->alive
<= 0)
1234 initialise_missile(missile
);
1242 /* Draw and Move all the missiles */
1243 static void draw_and_move_missiles(void)
1245 struct Missile
* missile
;
1246 struct Point vertices
[2];
1249 SET_FG(COL_MISSILE
);
1251 missile
= missiles_array
;
1252 n
= MAX_NUM_MISSILES
;
1255 if (missile
->alive
> 0)
1259 vertices
[1].x
= -missile
->position
.dx
;
1260 vertices
[1].y
= -missile
->position
.dy
;
1261 draw_polygon(vertices
, 2, missile
->position
.x
, missile
->position
.y
);
1263 if (game_state
!= PAUSE_MODE
)
1265 missile
->oldpoint
.x
= missile
->position
.x
;
1266 missile
->oldpoint
.y
= missile
->position
.y
;
1267 move_point(&missile
->position
);
1275 /*************************************************
1277 *************************************************/
1279 static void initialise_enemy(void)
1281 struct Point
* point
;
1285 if (rb
->rand()%100 > enemy
.size_probability
)
1288 enemy
.size_probability
++;
1289 if (enemy
.size_probability
> 90)
1291 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
1297 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
1300 enemy
.exists
= true;
1301 enemy
.explode_countdown
= 0;
1302 enemy
.appear_countdown
= enemy
.appear_timing
;
1304 point
= enemy
.vertices
;
1305 for(n
= 0; n
< NUM_ENEMY_VERTICES
*2; n
+= 2)
1307 point
->x
= enemy_vertices
[n
];
1308 point
->y
= enemy_vertices
[n
+1];
1309 point
->x
*= size
*SCALE
/2;
1310 point
->y
*= size
*SCALE
/2;
1314 if (ship
.position
.x
>= SCALED_WIDTH
/2)
1316 enemy
.position
.dx
= ENEMY_SPEED
;
1317 enemy
.position
.x
= 0;
1321 enemy
.position
.dx
= -ENEMY_SPEED
;
1322 enemy
.position
.x
= SCALED_WIDTH
;
1325 if (ship
.position
.y
>= SCALED_HEIGHT
/2)
1327 enemy
.position
.dy
= ENEMY_SPEED
;
1328 enemy
.position
.y
= 0;
1332 enemy
.position
.dy
= -ENEMY_SPEED
;
1333 enemy
.position
.y
= SCALED_HEIGHT
;
1336 enemy
.position
.dx
*= SCALE
/10;
1337 enemy
.position
.dy
*= SCALE
/10;
1340 static void draw_and_move_enemy(void)
1346 draw_polygon(enemy
.vertices
, NUM_ENEMY_VERTICES
,
1347 enemy
.position
.x
, enemy
.position
.y
);
1350 if (game_state
!= PAUSE_MODE
)
1354 enemy
.position
.x
+= enemy
.position
.dx
;
1355 enemy
.position
.y
+= enemy
.position
.dy
;
1357 if (enemy
.position
.x
> SCALED_WIDTH
|| enemy
.position
.x
< 0)
1358 enemy
.exists
= false;
1360 enemy
.position
.y
%= SCALED_HEIGHT
;
1361 if (enemy
.position
.y
< 0)
1362 enemy
.position
.y
+= SCALED_HEIGHT
;
1364 if ((rb
->rand()%1000) < 10)
1365 enemy
.position
.dy
= -enemy
.position
.dy
;
1367 else if (enemy
.explode_countdown
> 0)
1369 enemy
.explode_countdown
--;
1373 if (enemy
.appear_countdown
> 0)
1374 enemy
.appear_countdown
--;
1375 else if (rb
->rand()%100 >= enemy
.appear_probability
)
1380 if (enemy_missile
.alive
<= 0)
1382 /* if no missile and the enemy is here and not exploding..
1384 if (enemy
.exists
&& ship
.exists
&&
1385 game_state
== PLAY_MODE
&& (rb
->rand()%10) >= 5 )
1387 int dx
= ship
.position
.x
- enemy
.position
.x
;
1388 int dy
= ship
.position
.y
- enemy
.position
.y
;
1390 if (dx
< -SCALED_WIDTH
/2) dx
+= SCALED_WIDTH
;
1391 else if (dx
> SCALED_WIDTH
/2) dx
-= SCALED_WIDTH
;
1392 if (dy
< -SCALED_HEIGHT
/2) dy
+= SCALED_HEIGHT
;
1393 else if (dy
> SCALED_HEIGHT
/2) dy
-= SCALED_HEIGHT
;
1395 enemy_missile
.position
.x
= enemy
.position
.x
;
1396 enemy_missile
.position
.y
= enemy
.position
.y
;
1398 /* lame, needs to be sorted - it's trying to shoot at the ship */
1400 enemy_missile
.position
.dx
= -1;
1401 else if (dx
> 5*SCALE
)
1402 enemy_missile
.position
.dx
= 1;
1404 enemy_missile
.position
.dx
= 0;
1407 enemy_missile
.position
.dy
= -1;
1408 else if (dy
> 5*SCALE
)
1409 enemy_missile
.position
.dy
= 1;
1411 enemy_missile
.position
.dy
= 0;
1413 while (enemy_missile
.position
.dx
== 0 &&
1414 enemy_missile
.position
.dy
== 0)
1416 enemy_missile
.position
.dx
= rb
->rand()%2-1;
1417 enemy_missile
.position
.dy
= rb
->rand()%2-1;
1420 enemy_missile
.position
.dx
*= SCALE
;
1421 enemy_missile
.position
.dy
*= SCALE
;
1422 enemy_missile
.alive
= ENEMY_MISSILE_LIFE_LENGTH
;
1427 rb
->lcd_fillrect( enemy_missile
.position
.x
/SCALE
,
1428 enemy_missile
.position
.y
/SCALE
,
1429 POINT_SIZE
, POINT_SIZE
);
1430 if (game_state
!= PAUSE_MODE
)
1432 move_point(&enemy_missile
.position
);
1433 enemy_missile
.alive
--;
1438 /*************************************************
1439 ** Check collisions.
1440 *************************************************/
1442 /* Add score if missile hit asteroid or enemy */
1443 static void add_score(int val
)
1445 current_score
+= val
;
1446 if (current_score
>= extra_life
)
1449 extra_life
+= EXTRA_LIFE
;
1453 static bool is_point_within_asteroid(struct Asteroid
* asteroid
,
1454 struct Point
* point
)
1456 if (is_point_within_rectangle(&asteroid
->position
, point
, asteroid
->radius
)
1457 && is_point_in_polygon(asteroid
->vertices
, NUM_ASTEROID_VERTICES
,
1458 point
->x
- asteroid
->position
.x
,
1459 point
->y
- asteroid
->position
.y
))
1461 explode_asteroid(asteroid
);
1468 static bool is_point_within_ship(struct Point
* point
)
1470 if (is_point_within_rectangle(&ship
.position
, point
, SIZE_SHIP_COLLISION
)
1471 && is_point_in_polygon(ship
.vertices
, NUM_SHIP_VERTICES
,
1472 point
->x
- ship
.position
.x
,
1473 point
->y
- ship
.position
.y
))
1481 static bool is_point_within_enemy(struct Point
* point
)
1483 if (is_point_within_rectangle(&enemy
.position
, point
, SIZE_ENEMY_COLLISION
))
1486 enemy
.explode_countdown
= EXPLOSION_LENGTH
;
1487 enemy
.exists
= false;
1488 create_trail_blaze(EXPLOSION_ENEMY
, &enemy
.position
);
1495 static bool is_ship_within_asteroid(struct Asteroid
* asteroid
)
1499 if (!is_point_within_rectangle(&asteroid
->position
, &ship
.position
,
1500 asteroid
->radius
+SIZE_SHIP_COLLISION
))
1503 p
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1504 p
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1505 if (is_point_within_asteroid(asteroid
, &p
))
1508 p
.x
= ship
.position
.x
+ ship
.vertices
[1].x
;
1509 p
.y
= ship
.position
.y
+ ship
.vertices
[1].y
;
1510 if (is_point_within_asteroid(asteroid
, &p
))
1513 p
.x
= ship
.position
.x
+ ship
.vertices
[3].x
;
1514 p
.y
= ship
.position
.y
+ ship
.vertices
[3].y
;
1515 if (is_point_within_asteroid(asteroid
, &p
))
1521 /* Check for collsions between the missiles and the asteroids and the ship */
1522 static void check_collisions(void)
1524 struct Missile
* missile
;
1525 struct Asteroid
* asteroid
;
1527 bool asteroids_onscreen
= false;
1529 asteroid
= asteroids_array
;
1530 m
= MAX_NUM_ASTEROIDS
;
1533 /* if the asteroids exists then test missile collision: */
1534 if (asteroid
->exists
)
1536 missile
= missiles_array
;
1537 n
= MAX_NUM_MISSILES
;
1540 /* if the missiles exists: */
1541 if (missile
->alive
> 0)
1543 /* has the missile hit the asteroid? */
1544 if (is_point_within_asteroid(asteroid
, &missile
->position
) ||
1545 is_point_within_asteroid(asteroid
, &missile
->oldpoint
))
1555 /* now check collision with ship: */
1556 if (asteroid
->exists
&& ship
.exists
)
1558 if (is_ship_within_asteroid(asteroid
))
1565 /* has the enemy missile blown something up? */
1566 if (asteroid
->exists
&& enemy_missile
.alive
> 0)
1568 if (is_point_within_asteroid(asteroid
, &enemy_missile
.position
))
1570 enemy_missile
.alive
= 0;
1575 /* is an asteroid still exploding? */
1576 if (asteroid
->explode_countdown
> 0)
1577 asteroids_onscreen
= true;
1582 /* now check collision between ship and enemy */
1583 if (enemy
.exists
&& ship
.exists
)
1585 /* has the enemy collided with the ship? */
1586 if (is_point_within_enemy(&ship
.position
))
1589 create_trail_blaze(EXPLOSION_ENEMY
, &enemy
.position
);
1594 /* Now see if the enemy has been shot at by the ships missiles: */
1595 missile
= missiles_array
;
1596 n
= MAX_NUM_MISSILES
;
1599 if (missile
->alive
> 0 &&
1600 is_point_within_enemy(&missile
->position
))
1610 /* test collision with enemy missile and ship: */
1611 if (enemy_missile
.alive
> 0 && is_point_within_ship(&enemy_missile
.position
))
1614 enemy_missile
.alive
= 0;
1615 enemy_missile
.position
.x
= enemy_missile
.position
.y
= 0;
1618 /* if all asteroids cleared then start again: */
1619 if (asteroid_count
== 0 && !asteroids_onscreen
1620 && !enemy
.exists
&& enemy
.explode_countdown
<= 0)
1623 if (current_level
> MAX_LEVEL
)
1624 current_level
= START_LEVEL
;
1625 enemy
.appear_probability
+= 5;
1626 if (enemy
.appear_probability
>= 100)
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
;
1632 show_level_timeout
= SHOW_LEVEL_TIME
;
1640 static void create_stars(void)
1649 p
->x
= (rb
->rand()%LCD_WIDTH
);
1650 p
->y
= (rb
->rand()%LCD_HEIGHT
);
1655 static void drawstars(void)
1666 rb
->lcd_drawpixel(p
->x
, p
->y
);
1671 /*************************************************
1672 ** Creates start_num number of new asteroids of
1674 **************************************************/
1675 static void initialise_level(int start_num
)
1677 struct Asteroid
* asteroid
;
1678 struct Missile
* missile
;
1679 struct TrailPoint
* tpoint
;
1681 asteroid_count
= next_missile_count
= next_thrust_count
= 0;
1685 enemy
.explode_countdown
= 0;
1686 enemy_missile
.alive
= 0;
1688 /* clear asteroids */
1689 asteroid
= asteroids_array
;
1690 n
= MAX_NUM_ASTEROIDS
;
1693 asteroid
->exists
= false;
1697 /* make some LARGE asteroids */
1698 for(n
= 0; n
< start_num
; n
++)
1699 initialise_asteroid(&asteroids_array
[n
], LARGE
, NULL
);
1701 /* ensure all missiles are out of action: */
1702 missile
= missiles_array
;
1703 n
= MAX_NUM_MISSILES
;
1710 tpoint
= trail_points
;
1711 n
= NUM_TRAIL_POINTS
;
1719 static void initialise_game(void)
1721 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1722 enemy
.appear_timing
= ENEMY_APPEAR_TIMING_START
;
1723 enemy
.appear_countdown
= enemy
.appear_timing
;
1724 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
1725 current_level
= START_LEVEL
;
1726 num_lives
= START_LIVES
;
1727 extra_life
= EXTRA_LIFE
;
1730 initialise_level(0);
1731 game_state
= SHOW_LEVEL
;
1732 show_level_timeout
= SHOW_LEVEL_TIME
;
1736 static bool spacerocks_help(void)
1738 static char *help_text
[] = {
1739 "Spacerocks", "", "Aim", "", "The", "goal", "of", "the", "game", "is",
1740 "to", "blow", "up", "the", "asteroids", "and", "avoid", "being", "hit", "by",
1741 "them.", "Also", "you'd", "better", "watch", "out", "for", "the", "UFOs!"
1743 static struct style_text formation
[]={
1744 { 0, TEXT_CENTER
|TEXT_UNDERLINE
},
1750 rb
->lcd_setfont(FONT_UI
);
1751 #ifdef HAVE_LCD_COLOR
1752 rb
->lcd_set_background(LCD_BLACK
);
1753 rb
->lcd_set_foreground(LCD_WHITE
);
1755 if (display_text(ARRAYLEN(help_text
), help_text
, formation
, NULL
)
1756 == PLUGIN_USB_CONNECTED
)
1759 button
= rb
->button_get(true);
1760 if (button
== SYS_USB_CONNECTED
)
1762 } while( ( button
== BUTTON_NONE
)
1763 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
1764 rb
->lcd_setfont(FONT_SYSFIXED
);
1769 #define PLUGIN_OTHER 10
1771 static int spacerocks_menu_cb(int action
, const struct menu_item_ex
*this_item
)
1773 if (action
== ACTION_REQUEST_MENUITEM
1774 && !ingame
&& ((intptr_t)this_item
)==0)
1775 return ACTION_EXIT_MENUITEM
;
1779 static int spacerocks_menu(void)
1782 MENUITEM_STRINGLIST(main_menu
, "Spacerocks Menu", spacerocks_menu_cb
,
1783 "Resume Game", "Start New Game",
1784 "Help", "High Scores",
1785 "Playback Control", "Quit");
1786 rb
->button_clear_queue();
1790 switch (rb
->do_menu(&main_menu
, &selection
, NULL
, false))
1793 return PLUGIN_OTHER
;
1796 return PLUGIN_OTHER
;
1798 if (spacerocks_help())
1799 return PLUGIN_USB_CONNECTED
;
1802 highscore_show(NUM_SCORES
, highscores
, NUM_SCORES
, true);
1805 playback_control(NULL
);
1809 case MENU_ATTACHED_USB
:
1810 return PLUGIN_USB_CONNECTED
;
1817 static int spacerocks_game_loop(void)
1825 if ((ret
= spacerocks_menu()) != PLUGIN_OTHER
)
1833 end
= *rb
->current_tick
+ (CYCLETIME
* HZ
) / 1000;
1834 rb
->lcd_clear_display();
1840 rb
->splash (HZ
* 2, "Game Over");
1841 rb
->lcd_clear_display();
1842 position
= highscore_update(current_score
, current_level
, "",
1843 highscores
, NUM_SCORES
);
1847 rb
->splash(HZ
*2, "New High Score");
1848 highscore_show(position
, highscores
, NUM_SCORES
, true);
1850 return PLUGIN_OTHER
;
1854 rb
->snprintf(str
, sizeof(str
), "score %d ", current_score
);
1855 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, str
);
1856 rb
->lcd_putsxy(CENTER_LCD_X
- 15,
1857 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, "pause");
1858 draw_and_move_missiles();
1860 draw_and_move_ship();
1864 rb
->snprintf(str
, sizeof(str
), "score %d ", current_score
);
1865 rb
->lcd_putsxy(1, LCD_HEIGHT
-8, str
);
1866 draw_and_move_missiles();
1869 draw_and_move_ship();
1873 rb
->snprintf(str
, sizeof(str
), "score %d ", current_score
);
1874 rb
->lcd_putsxy(1, LCD_HEIGHT
-8, str
);
1875 rb
->snprintf(str
, sizeof(str
), "stage %d ", current_level
);
1876 rb
->lcd_putsxy(CENTER_LCD_X
- 20,
1877 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, str
);
1879 draw_and_move_ship();
1880 show_level_timeout
--;
1881 if (show_level_timeout
<= 0)
1883 initialise_level(current_level
);
1884 game_state
= PLAY_MODE
;
1888 draw_and_move_trail_blaze();
1890 draw_and_move_asteroids();
1891 draw_and_move_enemy();
1895 #ifdef HAS_BUTTON_HOLD
1896 if (rb
->button_hold() && game_state
== PLAY_MODE
)
1897 game_state
= PAUSE_MODE
;
1899 button
= rb
->button_get(false);
1903 return PLUGIN_OTHER
;
1907 if (game_state
== PAUSE_MODE
)
1908 game_state
= PLAY_MODE
;
1909 else if (game_state
== PLAY_MODE
)
1910 game_state
= PAUSE_MODE
;
1914 case (AST_LEFT
| BUTTON_REPEAT
):
1915 if (game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
1916 rotate_ship(SHIP_ROT_ACW_COS
, SHIP_ROT_ACW_SIN
);
1920 case (AST_RIGHT
| BUTTON_REPEAT
):
1921 if (game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
1922 rotate_ship(SHIP_ROT_CW_COS
, SHIP_ROT_CW_SIN
);
1926 case (AST_THRUST
| BUTTON_REPEAT
):
1927 if (game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
1929 if (next_thrust_count
<= 0)
1931 next_thrust_count
= 5;
1937 case (AST_HYPERSPACE
):
1938 if (game_state
== PLAY_MODE
)
1940 /* maybe shield if it gets too hard */
1944 case (AST_FIRE
| BUTTON_REPEAT
):
1945 if (game_state
== PLAY_MODE
)
1947 if (next_missile_count
<= 0)
1950 next_missile_count
= 10;
1953 else if(game_state
== PAUSE_MODE
)
1954 game_state
= PLAY_MODE
;
1958 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
)
1959 return PLUGIN_USB_CONNECTED
;
1963 if (next_missile_count
> 0)
1964 next_missile_count
--;
1966 if (next_thrust_count
> 0)
1967 next_thrust_count
--;
1969 if (TIME_BEFORE(*rb
->current_tick
, end
))
1970 rb
->sleep(end
-*rb
->current_tick
);
1976 enum plugin_status
plugin_start(const void* parameter
)
1979 int ret
= PLUGIN_OTHER
;
1982 rb
->lcd_set_backdrop(NULL
);
1984 /* universal font */
1985 rb
->lcd_setfont(FONT_SYSFIXED
);
1986 /* Turn off backlight timeout */
1987 backlight_force_on(); /* backlight control in lib/helper.c */
1988 highscore_load(HIGH_SCORE
, highscores
, NUM_SCORES
);
1989 rb
->srand(*rb
->current_tick
);
1991 /* create stars once, and once only: */
1994 while (ret
== PLUGIN_OTHER
)
1995 ret
= spacerocks_game_loop();
1997 rb
->lcd_setfont(FONT_UI
);
1998 highscore_save(HIGH_SCORE
, highscores
, NUM_SCORES
);
1999 /* Turn on backlight timeout (revert to settings) */
2000 backlight_use_settings(); /* backlight control in lib/helper.c */