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
223 #elif (CONFIG_KEYPAD == PBELL_VIBE500_PAD)
224 #define AST_PAUSE BUTTON_PLAY
225 #define AST_QUIT BUTTON_REC
226 #define AST_THRUST BUTTON_UP
227 #define AST_HYPERSPACE BUTTON_DOWN
228 #define AST_LEFT BUTTON_PREV
229 #define AST_RIGHT BUTTON_NEXT
230 #define AST_FIRE BUTTON_OK
233 #error No keymap defined!
236 #ifdef HAVE_TOUCHSCREEN
238 #define AST_PAUSE BUTTON_CENTER
241 #define AST_QUIT BUTTON_TOPLEFT
244 #define AST_THRUST BUTTON_TOPMIDDLE
246 #ifndef AST_HYPERSPACE
247 #define AST_HYPERSPACE BUTTON_TOPRIGHT
250 #define AST_LEFT BUTTON_MIDLEFT
253 #define AST_RIGHT BUTTON_MIDRIGHT
256 #define AST_FIRE BUTTON_BOTTOMMIDDLE
260 #define RES MAX(LCD_WIDTH, LCD_HEIGHT)
261 #define LARGE_LCD (RES >= 200)
267 #define WRAP_GAP (LARGE*SCALE*3)
269 #define START_LEVEL 1
270 #define SHOW_LEVEL_TIME 50
271 #define EXPLOSION_LENGTH 20
273 #define MAX_NUM_ASTEROIDS 25
274 #define MAX_NUM_MISSILES 6
276 #define NUM_TRAIL_POINTS 70
277 #define MAX_LEVEL MAX_NUM_ASTEROIDS
279 #define NUM_ASTEROID_VERTICES 10
280 #define NUM_SHIP_VERTICES 4
281 #define NUM_ENEMY_VERTICES 8
283 #define INVULNERABLE_TIME 30
284 #define BLINK_TIME 10
285 #define EXTRA_LIFE 250
286 #define START_LIVES 3
287 #define MISSILE_LIFE_LENGTH 40
289 #define ASTEROID_SPEED (RES/20)
290 #define SPACE_CHECK_SIZE 30*SCALE
293 #define SIZE_SHIP_COLLISION 8*SCALE
295 #define SIZE_SHIP_COLLISION 6*SCALE
298 #define LITTLE_SHIP 1
300 #define ENEMY_BIG_PROBABILITY_START 10
301 #define ENEMY_APPEAR_PROBABILITY_START 35
302 #define ENEMY_APPEAR_TIMING_START 600
303 #define ENEMY_SPEED 4
304 #define ENEMY_MISSILE_LIFE_LENGTH (RES/2)
306 #define SIZE_ENEMY_COLLISION 7*SCALE
308 #define SIZE_ENEMY_COLLISION 5*SCALE
311 #define SIN_COS_SCALE 10000
313 #define FAST_ROT_CW_SIN 873
314 #define FAST_ROT_CW_COS 9963
315 #define FAST_ROT_ACW_SIN -873
316 #define FAST_ROT_ACW_COS 9963
318 #define MEDIUM_ROT_CW_SIN 350
319 #define MEDIUM_ROT_CW_COS 9994
320 #define MEDIUM_ROT_ACW_SIN -350
321 #define MEDIUM_ROT_ACW_COS 9994
323 #define SLOW_ROT_CW_SIN 350
324 #define SLOW_ROT_CW_COS 9994
325 #define SLOW_ROT_ACW_SIN -350
326 #define SLOW_ROT_ACW_COS 9994
328 #ifdef HAVE_LCD_COLOR
329 #define SHIP_ROT_CW_SIN 2419
330 #define SHIP_ROT_CW_COS 9702
331 #define SHIP_ROT_ACW_SIN -2419
332 #define SHIP_ROT_ACW_COS 9702
334 #define SHIP_ROT_CW_SIN 3827
335 #define SHIP_ROT_CW_COS 9239
336 #define SHIP_ROT_ACW_SIN -3827
337 #define SHIP_ROT_ACW_COS 9239
341 #define SCALED_WIDTH (LCD_WIDTH*SCALE)
342 #define SCALED_HEIGHT (LCD_HEIGHT*SCALE)
343 #define CENTER_LCD_X (LCD_WIDTH/2)
344 #define CENTER_LCD_Y (LCD_HEIGHT/2)
346 #ifdef HAVE_LCD_COLOR
347 #define ASTEROID_R 230
348 #define ASTEROID_G 200
349 #define ASTEROID_B 100
360 #define COL_MISSILE LCD_RGBPACK(200,0,0)
361 #define COL_PLAYER LCD_RGBPACK(200,200,200)
362 #define COL_INVULN LCD_RGBPACK(100,100,200)
363 #define COL_STARS LCD_WHITE
364 #define COL_ASTEROID LCD_RGBPACK(ASTEROID_R,ASTEROID_G,ASTEROID_B)
365 #define COL_TEXT LCD_RGBPACK(200,200,255)
366 #define COL_ENEMY LCD_RGBPACK(ENEMY_R,ENEMY_G,ENEMY_B)
367 #define SET_FG rb->lcd_set_foreground
368 #define SET_BG rb->lcd_set_background
374 #define SCORE_FILE PLUGIN_GAMES_DIR "/spacerocks.score"
377 static struct highscore highscores
[NUM_SCORES
];
379 /* The array of points that make up an asteroid */
380 static const short asteroid_one
[NUM_ASTEROID_VERTICES
*2] =
394 /* The array of points that make up an asteroid */
395 static const short asteroid_two
[NUM_ASTEROID_VERTICES
*2] =
409 /* The array of points that make up an asteroid */
410 static const short asteroid_three
[NUM_ASTEROID_VERTICES
*2] =
424 /* The array of points the make up the ship */
425 static const short ship_vertices
[NUM_SHIP_VERTICES
*2] =
440 /* The array of points the make up the bad spaceship */
441 static const short enemy_vertices
[NUM_ENEMY_VERTICES
*2] =
503 struct Point position
;
505 #ifdef HAVE_LCD_COLOR
513 /* Asteroid structure, contains an array of points */
516 struct Point position
;
517 struct Point rotation
;
518 struct Point vertices
[NUM_ASTEROID_VERTICES
];
520 int explode_countdown
;
521 enum asteroid_type type
;
529 struct Point position
;
530 struct Point rotation
;
531 struct Point vertices
[NUM_SHIP_VERTICES
];
533 int explode_countdown
;
534 int invulnerable_time
;
539 struct Point position
;
540 struct Point vertices
[NUM_ENEMY_VERTICES
];
542 int explode_countdown
;
543 int appear_countdown
;
544 short size_probability
;
545 short appear_probability
;
551 struct Point position
;
552 struct Point oldpoint
;
556 static enum game_state game_state
;
557 static int asteroid_count
;
558 static int next_missile_count
;
559 static int next_thrust_count
;
560 static int num_lives
;
561 static int extra_life
;
562 static int show_level_timeout
;
563 static int current_level
;
564 static int current_score
;
566 static struct Ship ship
;
567 static struct Point stars
[NUM_STARS
];
568 static struct Asteroid asteroids_array
[MAX_NUM_ASTEROIDS
];
569 static struct Missile missiles_array
[MAX_NUM_MISSILES
];
570 static struct Missile enemy_missile
;
571 static struct Enemy enemy
;
572 static struct Point lives_points
[NUM_SHIP_VERTICES
];
573 static struct TrailPoint trail_points
[NUM_TRAIL_POINTS
];
575 /*************************************************
576 ** Handle polygon and point
577 *************************************************/
579 /* Check if point is in a polygon */
580 static bool is_point_in_polygon(struct Point
* vertices
, int num_vertices
,
588 if (x
< -SCALED_WIDTH
/2) x
+= SCALED_WIDTH
;
589 else if (x
> SCALED_WIDTH
/2) x
-= SCALED_WIDTH
;
590 if (y
< -SCALED_HEIGHT
/2) y
+= SCALED_HEIGHT
;
591 else if (y
> SCALED_HEIGHT
/2) y
-= SCALED_HEIGHT
;
594 pj
= vertices
+ num_vertices
-1;
599 if ((((pi
->y
<= y
) && (y
< pj
->y
)) || ((pj
->y
<= y
) && (y
< pi
->y
))) &&
600 (x
< (pj
->x
- pi
->x
) * (y
- pi
->y
) / (pj
->y
- pi
->y
) + pi
->x
))
610 /* Check if point is within a rectangle */
611 static bool is_point_within_rectangle(struct Point
* rect
, struct Point
* p
,
614 int dx
= p
->x
- rect
->x
;
615 int dy
= p
->y
- rect
->y
;
617 rb
->lcd_drawrect((rect
->x
- size
)/SCALE
, (rect
->y
- size
)/SCALE
,
618 (size
*2+1)/SCALE
, (size
*2+1)/SCALE
);
620 if (dx
< -SCALED_WIDTH
/2) dx
+= SCALED_WIDTH
;
621 else if (dx
> SCALED_WIDTH
/2) dx
-= SCALED_WIDTH
;
622 if (dy
< -SCALED_HEIGHT
/2) dy
+= SCALED_HEIGHT
;
623 else if (dy
> SCALED_HEIGHT
/2) dy
-= SCALED_HEIGHT
;
624 return (dx
> -size
&& dx
< size
&& dy
> -size
&& dy
< size
);
628 static void rotate_polygon(struct Point
* vertices
, int num_vertices
,
629 struct Point
* rotation
, int cos
, int sin
)
635 temp_x
= rotation
->x
;
636 temp_y
= rotation
->y
;
637 rotation
->x
= (temp_x
*cos
- temp_y
*sin
)/SIN_COS_SCALE
;
638 rotation
->y
= (temp_y
*cos
+ temp_x
*sin
)/SIN_COS_SCALE
;
639 #define MIN_SCALE (SIN_COS_SCALE-10)
640 #define MAX_SCALE (SIN_COS_SCALE+10)
641 /* normalize vector. this is not accurate but would be enough. */
642 temp_x
= rotation
->x
*rotation
->x
+ rotation
->y
*rotation
->y
;
643 if (temp_x
<= MIN_SCALE
*MIN_SCALE
)
645 rotation
->x
= rotation
->x
*SIN_COS_SCALE
/MIN_SCALE
;
646 rotation
->y
= rotation
->y
*SIN_COS_SCALE
/MIN_SCALE
;
648 else if (temp_x
>= MAX_SCALE
*MAX_SCALE
)
650 rotation
->x
= rotation
->x
*SIN_COS_SCALE
/MAX_SCALE
;
651 rotation
->y
= rotation
->y
*SIN_COS_SCALE
/MAX_SCALE
;
660 point
->x
= (point
->dx
*rotation
->x
- point
->dy
*rotation
->y
)/SIN_COS_SCALE
;
661 point
->y
= (point
->dy
*rotation
->x
+ point
->dx
*rotation
->y
)/SIN_COS_SCALE
;
667 static void draw_polygon(struct Point
* vertices
, int num_vertices
,
670 int n
, new_x
, new_y
, old_x
, old_y
;
674 if (px
> SCALED_WIDTH
- WRAP_GAP
)
676 if (py
> SCALED_HEIGHT
- WRAP_GAP
)
679 draw_wrap
= (px
< WRAP_GAP
|| py
< WRAP_GAP
);
681 p
= vertices
+ num_vertices
- 1;
682 old_x
= (p
->x
+ px
)/SCALE
;
683 old_y
= (p
->y
+ py
)/SCALE
;
688 new_x
= (p
->x
+ px
)/SCALE
;
689 new_y
= (p
->y
+ py
)/SCALE
;
691 rb
->lcd_drawline(old_x
, old_y
, new_x
, new_y
);
694 rb
->lcd_drawline(old_x
+ LCD_WIDTH
, old_y
, new_x
+ LCD_WIDTH
, new_y
);
695 rb
->lcd_drawline(old_x
, old_y
+ LCD_HEIGHT
, new_x
, new_y
+ LCD_HEIGHT
);
696 rb
->lcd_drawline(old_x
+ LCD_WIDTH
, old_y
+ LCD_HEIGHT
,
697 new_x
+ LCD_WIDTH
, new_y
+ LCD_HEIGHT
);
705 static void move_point(struct Point
* point
)
707 point
->x
+= point
->dx
;
708 point
->y
+= point
->dy
;
710 /* Check bounds on the x-axis: */
711 point
->x
%= SCALED_WIDTH
;
713 point
->x
+= SCALED_WIDTH
;
715 /* Check bounds on the y-axis: */
716 point
->y
%= SCALED_HEIGHT
;
718 point
->y
+= SCALED_HEIGHT
;
721 /*************************************************
722 ** Handle trail blaiz.
723 *************************************************/
725 static void create_ship_trail(struct TrailPoint
* tpoint
)
727 tpoint
->position
.x
+= ship
.vertices
[2].x
;
728 tpoint
->position
.y
+= ship
.vertices
[2].y
;
729 tpoint
->position
.dx
= -( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/10;
730 tpoint
->position
.dy
= -( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/10;
733 static void create_explosion_trail(struct TrailPoint
* tpoint
)
735 tpoint
->position
.dx
= (rb
->rand()%5001)-2500;
736 tpoint
->position
.dy
= (rb
->rand()%5001)-2500;
739 static void create_trail_blaze(int colour
, struct Point
* position
)
742 struct TrailPoint
* tpoint
;
745 if (colour
!= EXPLOSION_SHIP
)
747 numtoadd
= NUM_TRAIL_POINTS
/5;
751 numtoadd
= NUM_TRAIL_POINTS
/8;
754 /* give the point a random countdown timer, so they dissapears at different
756 tpoint
= trail_points
;
757 n
= NUM_TRAIL_POINTS
;
760 /* find a space in the array of trail_points that is NULL or DEAD or
761 whatever and place this one here. */
762 if (tpoint
->alive
<= 0)
764 /* take a random point near the position. */
765 tpoint
->position
.x
= (rb
->rand()%18000)-9000 + position
->x
;
766 tpoint
->position
.y
= (rb
->rand()%18000)-9000 + position
->y
;
771 create_explosion_trail(tpoint
);
773 #ifdef HAVE_LCD_COLOR
780 case EXPLOSION_ASTEROID
:
781 create_explosion_trail(tpoint
);
783 #ifdef HAVE_LCD_COLOR
784 tpoint
->r
= ASTEROID_R
;
785 tpoint
->g
= ASTEROID_G
;
786 tpoint
->b
= ASTEROID_B
;
790 case EXPLOSION_ENEMY
:
791 create_explosion_trail(tpoint
);
793 #ifdef HAVE_LCD_COLOR
800 case EXPLOSION_THRUST
:
801 create_ship_trail(tpoint
);
803 #ifdef HAVE_LCD_COLOR
804 tpoint
->r
= THRUST_R
;
805 tpoint
->g
= THRUST_G
;
806 tpoint
->b
= THRUST_B
;
812 /* give the points a speed based on direction of travel
814 tpoint
->position
.dx
+= position
->dx
;
815 tpoint
->position
.dy
+= position
->dy
;
825 static void draw_and_move_trail_blaze(void)
827 struct TrailPoint
* tpoint
;
830 /* loop through, if alive then move and draw.
831 when drawn, countdown it's timer.
834 tpoint
= trail_points
;
835 n
= NUM_TRAIL_POINTS
;
838 if (tpoint
->alive
> 0)
840 if (game_state
!= PAUSE_MODE
)
843 move_point(&(tpoint
->position
));
844 #ifdef HAVE_LCD_COLOR
845 /* intensity = tpoint->alive/2; */
846 if (tpoint
->r
>= tpoint
->dec
) tpoint
->r
-= tpoint
->dec
;
847 if (tpoint
->g
>= tpoint
->dec
) tpoint
->g
-= tpoint
->dec
;
848 if (tpoint
->b
>= tpoint
->dec
) tpoint
->b
-= tpoint
->dec
;
851 SET_FG(LCD_RGBPACK(tpoint
->r
, tpoint
->g
, tpoint
->b
));
852 rb
->lcd_drawpixel(tpoint
->position
.x
/SCALE
, tpoint
->position
.y
/SCALE
);
858 /*************************************************
860 *************************************************/
862 static void rotate_asteroid(struct Asteroid
* asteroid
)
864 rotate_polygon(asteroid
->vertices
, NUM_ASTEROID_VERTICES
,
866 asteroid
->speed_cos
, asteroid
->speed_sin
);
869 /* Initialise the passed Asteroid.
870 * if position is NULL, place it at the random loacation
871 * where ship doesn't exist
873 static void initialise_asteroid(struct Asteroid
* asteroid
,
874 enum asteroid_type type
, struct Point
*position
)
876 const short *asteroid_vertices
;
880 asteroid
->exists
= true;
881 asteroid
->explode_countdown
= 0;
882 asteroid
->type
= type
;
884 /* Set the radius of the asteroid: */
885 asteroid
->radius
= (int)type
*SCALE
*3;
887 /* shall we move Clockwise and Fast */
891 asteroid
->speed_cos
= FAST_ROT_CW_COS
;
892 asteroid
->speed_sin
= FAST_ROT_CW_SIN
;
896 asteroid
->speed_cos
= FAST_ROT_ACW_COS
;
897 asteroid
->speed_sin
= FAST_ROT_ACW_SIN
;
901 asteroid
->speed_cos
= SLOW_ROT_ACW_COS
;
902 asteroid
->speed_sin
= SLOW_ROT_ACW_SIN
;
906 asteroid
->speed_cos
= SLOW_ROT_CW_COS
;
907 asteroid
->speed_sin
= SLOW_ROT_CW_SIN
;
912 asteroid_vertices
= asteroid_one
;
914 asteroid_vertices
= asteroid_two
;
916 asteroid_vertices
= asteroid_three
;
918 point
= asteroid
->vertices
;
919 for(n
= 0; n
< NUM_ASTEROID_VERTICES
*2; n
+= 2)
921 point
->x
= asteroid_vertices
[n
];
922 point
->y
= asteroid_vertices
[n
+1];
923 point
->x
*= asteroid
->radius
/20;
924 point
->y
*= asteroid
->radius
/20;
925 /* dx and dy are used when rotate polygon */
926 point
->dx
= point
->x
;
927 point
->dy
= point
->y
;
934 /* Set the position randomly: */
935 asteroid
->position
.x
= (rb
->rand()%SCALED_WIDTH
);
936 asteroid
->position
.y
= (rb
->rand()%SCALED_HEIGHT
);
937 } while (is_point_within_rectangle(&ship
.position
, &asteroid
->position
,
942 asteroid
->position
.x
= position
->x
;
943 asteroid
->position
.y
= position
->y
;
947 asteroid
->position
.dx
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
948 } while (asteroid
->position
.dx
== 0);
951 asteroid
->position
.dy
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
952 } while (asteroid
->position
.dy
== 0);
954 asteroid
->position
.dx
*= SCALE
/10;
955 asteroid
->position
.dy
*= SCALE
/10;
957 asteroid
->rotation
.x
= SIN_COS_SCALE
;
958 asteroid
->rotation
.y
= 0;
960 /* Now rotate the asteroid a bit, so they all look a bit different */
961 for(n
= (rb
->rand()%30)+2; n
--; )
962 rotate_asteroid(asteroid
);
964 /* great, we've created an asteroid, don't forget to increment the total: */
969 * Creates a new asteroid of the given 4type (size) and at the given location.
971 static void create_asteroid(enum asteroid_type type
, struct Point
*position
)
973 struct Asteroid
* asteroid
;
976 asteroid
= asteroids_array
;
977 n
= MAX_NUM_ASTEROIDS
;
980 if (!asteroid
->exists
&& asteroid
->explode_countdown
<= 0)
982 initialise_asteroid(asteroid
, type
, position
);
989 /* Draw and move all asteroids */
990 static void draw_and_move_asteroids(void)
992 struct Asteroid
* asteroid
;
995 SET_FG(COL_ASTEROID
);
997 asteroid
= asteroids_array
;
998 n
= MAX_NUM_ASTEROIDS
;
1001 if (asteroid
->exists
)
1003 draw_polygon(asteroid
->vertices
, NUM_ASTEROID_VERTICES
,
1004 asteroid
->position
.x
, asteroid
->position
.y
);
1006 if (game_state
!= PAUSE_MODE
)
1008 if (asteroid
->exists
)
1010 move_point(&asteroid
->position
);
1011 rotate_asteroid(asteroid
);
1013 else if (asteroid
->explode_countdown
> 0)
1015 asteroid
->explode_countdown
--;
1022 static void explode_asteroid(struct Asteroid
* asteroid
)
1025 p
.dx
= asteroid
->position
.dx
;
1026 p
.dy
= asteroid
->position
.dy
;
1027 p
.x
= asteroid
->position
.x
;
1028 p
.y
= asteroid
->position
.y
;
1031 asteroid
->exists
= false;
1033 switch(asteroid
->type
)
1036 asteroid
->explode_countdown
= EXPLOSION_LENGTH
;
1037 create_trail_blaze(EXPLOSION_ASTEROID
, &p
);
1041 create_asteroid(SMALL
, &p
);
1042 create_asteroid(SMALL
, &p
);
1046 create_asteroid(MEDIUM
, &p
);
1047 create_asteroid(MEDIUM
, &p
);
1052 /*************************************************
1054 *************************************************/
1056 /* Initialise the ship */
1057 static void initialise_ship(void)
1059 struct Point
* point
;
1060 struct Point
* lives_point
;
1063 ship
.position
.x
= CENTER_LCD_X
* SCALE
;
1064 ship
.position
.y
= CENTER_LCD_Y
* SCALE
;
1065 ship
.position
.dx
= 0;
1066 ship
.position
.dy
= 0;
1067 ship
.rotation
.x
= SIN_COS_SCALE
;
1068 ship
.rotation
.y
= 0;
1070 ship
.explode_countdown
= 0;
1071 ship
.invulnerable_time
= INVULNERABLE_TIME
;
1073 point
= ship
.vertices
;
1074 lives_point
= lives_points
;
1075 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+= 2)
1077 point
->x
= ship_vertices
[n
];
1078 point
->y
= ship_vertices
[n
+1];
1081 /* dx and dy are used when rotate polygon */
1082 point
->dx
= point
->x
;
1083 point
->dy
= point
->y
;
1084 /* grab a copy of the ships points for the lives display: */
1085 lives_point
->x
= point
->x
;
1086 lives_point
->y
= point
->y
;
1094 * Draws the ship, moves the ship and creates a new
1095 * one if it's finished exploding.
1097 static void draw_and_move_ship(void)
1099 if (ship
.invulnerable_time
> BLINK_TIME
|| ship
.invulnerable_time
% 2 != 0)
1110 draw_polygon(ship
.vertices
, NUM_SHIP_VERTICES
,
1111 ship
.position
.x
, ship
.position
.y
);
1114 if (game_state
!= PAUSE_MODE
)
1118 if (ship
.invulnerable_time
> 0)
1119 ship
.invulnerable_time
--;
1120 move_point(&ship
.position
);
1122 else if (ship
.explode_countdown
> 0)
1124 ship
.explode_countdown
--;
1125 if (ship
.explode_countdown
<= 0)
1130 game_state
= GAME_OVER
;
1141 static void explode_ship(void)
1143 if (!ship
.invulnerable_time
)
1145 /* if not invulnerable, blow up ship */
1146 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1147 ship
.exists
= false;
1148 create_trail_blaze(EXPLOSION_SHIP
, &ship
.position
);
1152 /* Rotate the ship using the passed sin & cos values */
1153 static void rotate_ship(int cos
, int sin
)
1157 rotate_polygon(ship
.vertices
, NUM_SHIP_VERTICES
,
1158 &ship
.rotation
, cos
, sin
);
1162 static void thrust_ship(void)
1166 ship
.position
.dx
+= ( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/20;
1167 ship
.position
.dy
+= ( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/20;
1169 /* if dx and dy are below a certain threshold, then set 'em to 0
1170 but to do this we need to ascertain if the spacehip as moved on
1171 screen for more than a certain amount. */
1173 create_trail_blaze(EXPLOSION_THRUST
, &ship
.position
);
1177 /* stop movement of ship, 'cos that's what happens when you go into hyperspace. */
1178 static void hyperspace(void)
1182 ship
.position
.dx
= ship
.position
.dy
= 0;
1183 ship
.position
.x
= (rb
->rand()%SCALED_WIDTH
);
1184 ship
.position
.y
= (rb
->rand()%SCALED_HEIGHT
);
1188 static void draw_lives(void)
1192 int px
= (LCD_WIDTH
-1 - 4)*SCALE
;
1193 int py
= (LCD_HEIGHT
-1 - 6)*SCALE
;
1195 int px
= (LCD_WIDTH
-1 - 3)*SCALE
;
1196 int py
= (LCD_HEIGHT
-1 - 4)*SCALE
;
1204 draw_polygon(lives_points
, NUM_SHIP_VERTICES
, px
, py
);
1217 /* Initialise a missile */
1218 static void initialise_missile(struct Missile
* missile
)
1220 missile
->position
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1221 missile
->position
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1222 missile
->position
.dx
= (ship
.vertices
[0].x
- ship
.vertices
[2].x
)/2;
1223 missile
->position
.dy
= (ship
.vertices
[0].y
- ship
.vertices
[2].y
)/2;
1224 missile
->alive
= MISSILE_LIFE_LENGTH
;
1225 missile
->oldpoint
.x
= missile
->position
.x
;
1226 missile
->oldpoint
.y
= missile
->position
.y
;
1229 /* Fire the next missile */
1230 static void fire_missile(void)
1232 struct Missile
* missile
;
1237 missile
= missiles_array
;
1238 n
= MAX_NUM_MISSILES
;
1241 if (missile
->alive
<= 0)
1243 initialise_missile(missile
);
1251 /* Draw and Move all the missiles */
1252 static void draw_and_move_missiles(void)
1254 struct Missile
* missile
;
1255 struct Point vertices
[2];
1258 SET_FG(COL_MISSILE
);
1260 missile
= missiles_array
;
1261 n
= MAX_NUM_MISSILES
;
1264 if (missile
->alive
> 0)
1268 vertices
[1].x
= -missile
->position
.dx
;
1269 vertices
[1].y
= -missile
->position
.dy
;
1270 draw_polygon(vertices
, 2, missile
->position
.x
, missile
->position
.y
);
1272 if (game_state
!= PAUSE_MODE
)
1274 missile
->oldpoint
.x
= missile
->position
.x
;
1275 missile
->oldpoint
.y
= missile
->position
.y
;
1276 move_point(&missile
->position
);
1284 /*************************************************
1286 *************************************************/
1288 static void initialise_enemy(void)
1290 struct Point
* point
;
1294 if (rb
->rand()%100 > enemy
.size_probability
)
1297 enemy
.size_probability
++;
1298 if (enemy
.size_probability
> 90)
1300 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
1306 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
1309 enemy
.exists
= true;
1310 enemy
.explode_countdown
= 0;
1311 enemy
.appear_countdown
= enemy
.appear_timing
;
1313 point
= enemy
.vertices
;
1314 for(n
= 0; n
< NUM_ENEMY_VERTICES
*2; n
+= 2)
1316 point
->x
= enemy_vertices
[n
];
1317 point
->y
= enemy_vertices
[n
+1];
1318 point
->x
*= size
*SCALE
/2;
1319 point
->y
*= size
*SCALE
/2;
1323 if (ship
.position
.x
>= SCALED_WIDTH
/2)
1325 enemy
.position
.dx
= ENEMY_SPEED
;
1326 enemy
.position
.x
= 0;
1330 enemy
.position
.dx
= -ENEMY_SPEED
;
1331 enemy
.position
.x
= SCALED_WIDTH
;
1334 if (ship
.position
.y
>= SCALED_HEIGHT
/2)
1336 enemy
.position
.dy
= ENEMY_SPEED
;
1337 enemy
.position
.y
= 0;
1341 enemy
.position
.dy
= -ENEMY_SPEED
;
1342 enemy
.position
.y
= SCALED_HEIGHT
;
1345 enemy
.position
.dx
*= SCALE
/10;
1346 enemy
.position
.dy
*= SCALE
/10;
1349 static void draw_and_move_enemy(void)
1355 draw_polygon(enemy
.vertices
, NUM_ENEMY_VERTICES
,
1356 enemy
.position
.x
, enemy
.position
.y
);
1359 if (game_state
!= PAUSE_MODE
)
1363 enemy
.position
.x
+= enemy
.position
.dx
;
1364 enemy
.position
.y
+= enemy
.position
.dy
;
1366 if (enemy
.position
.x
> SCALED_WIDTH
|| enemy
.position
.x
< 0)
1367 enemy
.exists
= false;
1369 enemy
.position
.y
%= SCALED_HEIGHT
;
1370 if (enemy
.position
.y
< 0)
1371 enemy
.position
.y
+= SCALED_HEIGHT
;
1373 if ((rb
->rand()%1000) < 10)
1374 enemy
.position
.dy
= -enemy
.position
.dy
;
1376 else if (enemy
.explode_countdown
> 0)
1378 enemy
.explode_countdown
--;
1382 if (enemy
.appear_countdown
> 0)
1383 enemy
.appear_countdown
--;
1384 else if (rb
->rand()%100 >= enemy
.appear_probability
)
1389 if (enemy_missile
.alive
<= 0)
1391 /* if no missile and the enemy is here and not exploding..
1393 if (enemy
.exists
&& ship
.exists
&&
1394 game_state
== PLAY_MODE
&& (rb
->rand()%10) >= 5 )
1396 int dx
= ship
.position
.x
- enemy
.position
.x
;
1397 int dy
= ship
.position
.y
- enemy
.position
.y
;
1399 if (dx
< -SCALED_WIDTH
/2) dx
+= SCALED_WIDTH
;
1400 else if (dx
> SCALED_WIDTH
/2) dx
-= SCALED_WIDTH
;
1401 if (dy
< -SCALED_HEIGHT
/2) dy
+= SCALED_HEIGHT
;
1402 else if (dy
> SCALED_HEIGHT
/2) dy
-= SCALED_HEIGHT
;
1404 enemy_missile
.position
.x
= enemy
.position
.x
;
1405 enemy_missile
.position
.y
= enemy
.position
.y
;
1407 /* lame, needs to be sorted - it's trying to shoot at the ship */
1409 enemy_missile
.position
.dx
= -1;
1410 else if (dx
> 5*SCALE
)
1411 enemy_missile
.position
.dx
= 1;
1413 enemy_missile
.position
.dx
= 0;
1416 enemy_missile
.position
.dy
= -1;
1417 else if (dy
> 5*SCALE
)
1418 enemy_missile
.position
.dy
= 1;
1420 enemy_missile
.position
.dy
= 0;
1422 while (enemy_missile
.position
.dx
== 0 &&
1423 enemy_missile
.position
.dy
== 0)
1425 enemy_missile
.position
.dx
= rb
->rand()%2-1;
1426 enemy_missile
.position
.dy
= rb
->rand()%2-1;
1429 enemy_missile
.position
.dx
*= SCALE
;
1430 enemy_missile
.position
.dy
*= SCALE
;
1431 enemy_missile
.alive
= ENEMY_MISSILE_LIFE_LENGTH
;
1436 rb
->lcd_fillrect( enemy_missile
.position
.x
/SCALE
,
1437 enemy_missile
.position
.y
/SCALE
,
1438 POINT_SIZE
, POINT_SIZE
);
1439 if (game_state
!= PAUSE_MODE
)
1441 move_point(&enemy_missile
.position
);
1442 enemy_missile
.alive
--;
1447 /*************************************************
1448 ** Check collisions.
1449 *************************************************/
1451 /* Add score if missile hit asteroid or enemy */
1452 static void add_score(int val
)
1454 current_score
+= val
;
1455 if (current_score
>= extra_life
)
1458 extra_life
+= EXTRA_LIFE
;
1462 static bool is_point_within_asteroid(struct Asteroid
* asteroid
,
1463 struct Point
* point
)
1465 if (is_point_within_rectangle(&asteroid
->position
, point
, asteroid
->radius
)
1466 && is_point_in_polygon(asteroid
->vertices
, NUM_ASTEROID_VERTICES
,
1467 point
->x
- asteroid
->position
.x
,
1468 point
->y
- asteroid
->position
.y
))
1470 explode_asteroid(asteroid
);
1477 static bool is_point_within_ship(struct Point
* point
)
1479 if (is_point_within_rectangle(&ship
.position
, point
, SIZE_SHIP_COLLISION
)
1480 && is_point_in_polygon(ship
.vertices
, NUM_SHIP_VERTICES
,
1481 point
->x
- ship
.position
.x
,
1482 point
->y
- ship
.position
.y
))
1490 static bool is_point_within_enemy(struct Point
* point
)
1492 if (is_point_within_rectangle(&enemy
.position
, point
, SIZE_ENEMY_COLLISION
))
1495 enemy
.explode_countdown
= EXPLOSION_LENGTH
;
1496 enemy
.exists
= false;
1497 create_trail_blaze(EXPLOSION_ENEMY
, &enemy
.position
);
1504 static bool is_ship_within_asteroid(struct Asteroid
* asteroid
)
1508 if (!is_point_within_rectangle(&asteroid
->position
, &ship
.position
,
1509 asteroid
->radius
+SIZE_SHIP_COLLISION
))
1512 p
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1513 p
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1514 if (is_point_within_asteroid(asteroid
, &p
))
1517 p
.x
= ship
.position
.x
+ ship
.vertices
[1].x
;
1518 p
.y
= ship
.position
.y
+ ship
.vertices
[1].y
;
1519 if (is_point_within_asteroid(asteroid
, &p
))
1522 p
.x
= ship
.position
.x
+ ship
.vertices
[3].x
;
1523 p
.y
= ship
.position
.y
+ ship
.vertices
[3].y
;
1524 if (is_point_within_asteroid(asteroid
, &p
))
1530 /* Check for collsions between the missiles and the asteroids and the ship */
1531 static void check_collisions(void)
1533 struct Missile
* missile
;
1534 struct Asteroid
* asteroid
;
1536 bool asteroids_onscreen
= false;
1538 asteroid
= asteroids_array
;
1539 m
= MAX_NUM_ASTEROIDS
;
1542 /* if the asteroids exists then test missile collision: */
1543 if (asteroid
->exists
)
1545 missile
= missiles_array
;
1546 n
= MAX_NUM_MISSILES
;
1549 /* if the missiles exists: */
1550 if (missile
->alive
> 0)
1552 /* has the missile hit the asteroid? */
1553 if (is_point_within_asteroid(asteroid
, &missile
->position
) ||
1554 is_point_within_asteroid(asteroid
, &missile
->oldpoint
))
1564 /* now check collision with ship: */
1565 if (asteroid
->exists
&& ship
.exists
)
1567 if (is_ship_within_asteroid(asteroid
))
1574 /* has the enemy missile blown something up? */
1575 if (asteroid
->exists
&& enemy_missile
.alive
> 0)
1577 if (is_point_within_asteroid(asteroid
, &enemy_missile
.position
))
1579 enemy_missile
.alive
= 0;
1584 /* is an asteroid still exploding? */
1585 if (asteroid
->explode_countdown
> 0)
1586 asteroids_onscreen
= true;
1591 /* now check collision between ship and enemy */
1592 if (enemy
.exists
&& ship
.exists
)
1594 /* has the enemy collided with the ship? */
1595 if (is_point_within_enemy(&ship
.position
))
1598 create_trail_blaze(EXPLOSION_ENEMY
, &enemy
.position
);
1603 /* Now see if the enemy has been shot at by the ships missiles: */
1604 missile
= missiles_array
;
1605 n
= MAX_NUM_MISSILES
;
1608 if (missile
->alive
> 0 &&
1609 is_point_within_enemy(&missile
->position
))
1619 /* test collision with enemy missile and ship: */
1620 if (enemy_missile
.alive
> 0 && is_point_within_ship(&enemy_missile
.position
))
1623 enemy_missile
.alive
= 0;
1624 enemy_missile
.position
.x
= enemy_missile
.position
.y
= 0;
1627 /* if all asteroids cleared then start again: */
1628 if (asteroid_count
== 0 && !asteroids_onscreen
1629 && !enemy
.exists
&& enemy
.explode_countdown
<= 0)
1632 if (current_level
> MAX_LEVEL
)
1633 current_level
= START_LEVEL
;
1634 enemy
.appear_probability
+= 5;
1635 if (enemy
.appear_probability
>= 100)
1636 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1637 enemy
.appear_timing
-= 30;
1638 if (enemy
.appear_timing
< 30)
1639 enemy
.appear_timing
= 30;
1640 game_state
= SHOW_LEVEL
;
1641 show_level_timeout
= SHOW_LEVEL_TIME
;
1649 static void create_stars(void)
1658 p
->x
= (rb
->rand()%LCD_WIDTH
);
1659 p
->y
= (rb
->rand()%LCD_HEIGHT
);
1664 static void drawstars(void)
1675 rb
->lcd_drawpixel(p
->x
, p
->y
);
1680 /*************************************************
1681 ** Creates start_num number of new asteroids of
1683 **************************************************/
1684 static void initialise_level(int start_num
)
1686 struct Asteroid
* asteroid
;
1687 struct Missile
* missile
;
1688 struct TrailPoint
* tpoint
;
1690 asteroid_count
= next_missile_count
= next_thrust_count
= 0;
1694 enemy
.explode_countdown
= 0;
1695 enemy_missile
.alive
= 0;
1697 /* clear asteroids */
1698 asteroid
= asteroids_array
;
1699 n
= MAX_NUM_ASTEROIDS
;
1702 asteroid
->exists
= false;
1706 /* make some LARGE asteroids */
1707 for(n
= 0; n
< start_num
; n
++)
1708 initialise_asteroid(&asteroids_array
[n
], LARGE
, NULL
);
1710 /* ensure all missiles are out of action: */
1711 missile
= missiles_array
;
1712 n
= MAX_NUM_MISSILES
;
1719 tpoint
= trail_points
;
1720 n
= NUM_TRAIL_POINTS
;
1728 static void initialise_game(void)
1730 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1731 enemy
.appear_timing
= ENEMY_APPEAR_TIMING_START
;
1732 enemy
.appear_countdown
= enemy
.appear_timing
;
1733 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
1734 current_level
= START_LEVEL
;
1735 num_lives
= START_LIVES
;
1736 extra_life
= EXTRA_LIFE
;
1739 initialise_level(0);
1740 game_state
= SHOW_LEVEL
;
1741 show_level_timeout
= SHOW_LEVEL_TIME
;
1745 static bool spacerocks_help(void)
1747 static char *help_text
[] = {
1748 "Spacerocks", "", "Aim", "",
1749 "The", "goal", "of", "the", "game", "is", "to", "blow", "up",
1750 "the", "asteroids", "and", "avoid", "being", "hit", "by", "them.",
1751 "Also", "you'd", "better", "watch", "out", "for", "the", "UFOs!"
1753 static struct style_text formation
[]={
1754 { 0, TEXT_CENTER
|TEXT_UNDERLINE
},
1759 rb
->lcd_setfont(FONT_UI
);
1762 if (display_text(ARRAYLEN(help_text
), help_text
, formation
, NULL
, true))
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(-1, 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(SCORE_FILE
, 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(SCORE_FILE
, highscores
, NUM_SCORES
);
1999 /* Turn on backlight timeout (revert to settings) */
2000 backlight_use_settings(); /* backlight control in lib/helper.c */