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/helper.h"
27 /******************************* Globals ***********************************/
28 /* variable button definitions */
29 #if CONFIG_KEYPAD == RECORDER_PAD
30 #define AST_PAUSE BUTTON_ON
31 #define AST_QUIT BUTTON_OFF
32 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
33 #define AST_THRUST BUTTON_UP
34 #define AST_HYPERSPACE BUTTON_DOWN
35 #define AST_LEFT BUTTON_LEFT
36 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
37 #define AST_RIGHT BUTTON_RIGHT
38 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
39 #define AST_FIRE BUTTON_PLAY
40 #define AST_FIRE_REP BUTTON_PLAY | BUTTON_REPEAT
42 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
43 #define AST_PAUSE BUTTON_ON
44 #define AST_QUIT BUTTON_OFF
45 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
46 #define AST_THRUST BUTTON_UP
47 #define AST_HYPERSPACE BUTTON_DOWN
48 #define AST_LEFT BUTTON_LEFT
49 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
50 #define AST_RIGHT BUTTON_RIGHT
51 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
52 #define AST_FIRE BUTTON_SELECT
53 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
55 #elif CONFIG_KEYPAD == ONDIO_PAD
56 #define AST_PAUSE (BUTTON_MENU | BUTTON_OFF)
57 #define AST_QUIT BUTTON_OFF
58 #define AST_THRUST BUTTON_UP
59 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
60 #define AST_HYPERSPACE BUTTON_DOWN
61 #define AST_LEFT BUTTON_LEFT
62 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
63 #define AST_RIGHT BUTTON_RIGHT
64 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
65 #define AST_FIRE BUTTON_MENU
66 #define AST_FIRE_REP BUTTON_MENU | BUTTON_REPEAT
68 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
69 (CONFIG_KEYPAD == IRIVER_H300_PAD)
70 #define AST_PAUSE BUTTON_REC
71 #define AST_QUIT BUTTON_OFF
72 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
73 #define AST_THRUST BUTTON_UP
74 #define AST_HYPERSPACE BUTTON_DOWN
75 #define AST_LEFT BUTTON_LEFT
76 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
77 #define AST_RIGHT BUTTON_RIGHT
78 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
79 #define AST_FIRE BUTTON_SELECT
80 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
82 #define AST_RC_QUIT BUTTON_RC_STOP
84 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
85 #define AST_PAUSE BUTTON_PLAY
86 #define AST_QUIT BUTTON_POWER
87 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
88 #define AST_THRUST BUTTON_UP
89 #define AST_HYPERSPACE BUTTON_DOWN
90 #define AST_LEFT BUTTON_LEFT
91 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
92 #define AST_RIGHT BUTTON_RIGHT
93 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
94 #define AST_FIRE BUTTON_SELECT
95 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
97 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
98 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
99 #define AST_PAUSE (BUTTON_SELECT | BUTTON_PLAY)
100 #define AST_QUIT (BUTTON_SELECT | BUTTON_MENU)
101 #define AST_THRUST BUTTON_MENU
102 #define AST_THRUST_REP (BUTTON_MENU | BUTTON_REPEAT)
103 #define AST_HYPERSPACE BUTTON_PLAY
104 #define AST_LEFT BUTTON_SCROLL_BACK
105 #define AST_LEFT_REP (BUTTON_SCROLL_BACK | BUTTON_REPEAT)
106 #define AST_RIGHT BUTTON_SCROLL_FWD
107 #define AST_RIGHT_REP (BUTTON_SCROLL_FWD | BUTTON_REPEAT)
108 #define AST_FIRE BUTTON_SELECT
109 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
111 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
112 #define AST_PAUSE BUTTON_A
113 #define AST_QUIT BUTTON_POWER
114 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
115 #define AST_THRUST BUTTON_UP
116 #define AST_HYPERSPACE BUTTON_DOWN
117 #define AST_LEFT BUTTON_LEFT
118 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
119 #define AST_RIGHT BUTTON_RIGHT
120 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
121 #define AST_FIRE BUTTON_SELECT
122 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
124 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
125 #define AST_PAUSE BUTTON_REC
126 #define AST_QUIT BUTTON_POWER
127 #define AST_THRUST_REP (BUTTON_UP | BUTTON_REPEAT)
128 #define AST_THRUST BUTTON_UP
129 #define AST_HYPERSPACE BUTTON_DOWN
130 #define AST_LEFT BUTTON_SCROLL_BACK
131 #define AST_LEFT_REP (BUTTON_SCROLL_BACK | BUTTON_REPEAT)
132 #define AST_RIGHT BUTTON_SCROLL_FWD
133 #define AST_RIGHT_REP (BUTTON_SCROLL_FWD | BUTTON_REPEAT)
134 #define AST_FIRE BUTTON_SELECT
135 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
137 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
138 #define AST_PAUSE (BUTTON_SELECT | BUTTON_UP)
139 #define AST_QUIT (BUTTON_HOME|BUTTON_REPEAT)
140 #define AST_THRUST_REP (BUTTON_UP | BUTTON_REPEAT)
141 #define AST_THRUST BUTTON_UP
142 #define AST_HYPERSPACE BUTTON_DOWN
143 #define AST_LEFT BUTTON_SCROLL_BACK
144 #define AST_LEFT_REP (BUTTON_SCROLL_BACK | BUTTON_REPEAT)
145 #define AST_RIGHT BUTTON_SCROLL_FWD
146 #define AST_RIGHT_REP (BUTTON_SCROLL_FWD | BUTTON_REPEAT)
147 #define AST_FIRE BUTTON_SELECT
148 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
150 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
151 #define AST_PAUSE BUTTON_REC
152 #define AST_QUIT BUTTON_POWER
153 #define AST_THRUST_REP (BUTTON_UP | BUTTON_REPEAT)
154 #define AST_THRUST BUTTON_UP
155 #define AST_HYPERSPACE BUTTON_DOWN
156 #define AST_LEFT BUTTON_LEFT
157 #define AST_LEFT_REP (BUTTON_LEFT | BUTTON_REPEAT)
158 #define AST_RIGHT BUTTON_RIGHT
159 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
160 #define AST_FIRE BUTTON_SELECT
161 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
163 #elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
164 #define AST_PAUSE BUTTON_HOME
165 #define AST_QUIT BUTTON_POWER
166 #define AST_THRUST_REP (BUTTON_UP | BUTTON_REPEAT)
167 #define AST_THRUST BUTTON_UP
168 #define AST_HYPERSPACE BUTTON_DOWN
169 #define AST_LEFT BUTTON_LEFT
170 #define AST_LEFT_REP (BUTTON_LEFT | BUTTON_REPEAT)
171 #define AST_RIGHT BUTTON_RIGHT
172 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
173 #define AST_FIRE BUTTON_SELECT
174 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
176 #elif (CONFIG_KEYPAD == SANSA_M200_PAD)
177 #define AST_PAUSE (BUTTON_SELECT | BUTTON_UP)
178 #define AST_QUIT BUTTON_POWER
179 #define AST_THRUST_REP (BUTTON_UP | BUTTON_REPEAT)
180 #define AST_THRUST BUTTON_UP
181 #define AST_HYPERSPACE BUTTON_DOWN
182 #define AST_LEFT BUTTON_LEFT
183 #define AST_LEFT_REP (BUTTON_LEFT | BUTTON_REPEAT)
184 #define AST_RIGHT BUTTON_RIGHT
185 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
186 #define AST_FIRE (BUTTON_SELECT | BUTTON_REL)
187 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
189 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
190 #define AST_PAUSE BUTTON_PLAY
191 #define AST_QUIT BUTTON_POWER
192 #define AST_THRUST_REP BUTTON_SCROLL_UP | BUTTON_REPEAT
193 #define AST_THRUST BUTTON_SCROLL_UP
194 #define AST_HYPERSPACE BUTTON_SCROLL_DOWN
195 #define AST_LEFT BUTTON_LEFT
196 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
197 #define AST_RIGHT BUTTON_RIGHT
198 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
199 #define AST_FIRE BUTTON_REW
200 #define AST_FIRE_REP BUTTON_REW | BUTTON_REPEAT
202 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
203 #define AST_PAUSE BUTTON_PLAY
204 #define AST_QUIT BUTTON_BACK
205 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
206 #define AST_THRUST BUTTON_UP
207 #define AST_HYPERSPACE BUTTON_DOWN
208 #define AST_LEFT BUTTON_LEFT
209 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
210 #define AST_RIGHT BUTTON_RIGHT
211 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
212 #define AST_FIRE BUTTON_SELECT
213 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
215 #elif (CONFIG_KEYPAD == MROBE100_PAD)
216 #define AST_PAUSE BUTTON_DISPLAY
217 #define AST_QUIT BUTTON_POWER
218 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
219 #define AST_THRUST BUTTON_UP
220 #define AST_HYPERSPACE BUTTON_DOWN
221 #define AST_LEFT BUTTON_LEFT
222 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
223 #define AST_RIGHT BUTTON_RIGHT
224 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
225 #define AST_FIRE BUTTON_SELECT
226 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
228 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
229 #define AST_PAUSE BUTTON_RC_PLAY
230 #define AST_QUIT BUTTON_RC_REC
231 #define AST_THRUST_REP BUTTON_RC_VOL_UP | BUTTON_REPEAT
232 #define AST_THRUST BUTTON_RC_VOL_UP
233 #define AST_HYPERSPACE BUTTON_RC_VOL_DOWN
234 #define AST_LEFT BUTTON_RC_REW
235 #define AST_LEFT_REP (BUTTON_RC_REW | BUTTON_REPEAT)
236 #define AST_RIGHT BUTTON_RC_FF
237 #define AST_RIGHT_REP (BUTTON_RC_FF | BUTTON_REPEAT)
238 #define AST_FIRE BUTTON_RC_MODE
239 #define AST_FIRE_REP (BUTTON_RC_MODE | BUTTON_REPEAT)
241 #elif (CONFIG_KEYPAD == COWOND2_PAD)
242 #define AST_QUIT BUTTON_POWER
244 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
245 #define AST_PAUSE BUTTON_PLAY
246 #define AST_QUIT BUTTON_BACK
247 #define AST_THRUST_REP (BUTTON_UP | BUTTON_REPEAT)
248 #define AST_THRUST BUTTON_UP
249 #define AST_HYPERSPACE BUTTON_DOWN
250 #define AST_LEFT BUTTON_LEFT
251 #define AST_LEFT_REP (BUTTON_LEFT | BUTTON_REPEAT)
252 #define AST_RIGHT BUTTON_RIGHT
253 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
254 #define AST_FIRE BUTTON_SELECT
255 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
257 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
258 #define AST_PAUSE BUTTON_VIEW
259 #define AST_QUIT BUTTON_POWER
260 #define AST_THRUST_REP (BUTTON_UP | BUTTON_REPEAT)
261 #define AST_THRUST BUTTON_UP
262 #define AST_HYPERSPACE BUTTON_DOWN
263 #define AST_LEFT BUTTON_LEFT
264 #define AST_LEFT_REP (BUTTON_LEFT | BUTTON_REPEAT)
265 #define AST_RIGHT BUTTON_RIGHT
266 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
267 #define AST_FIRE BUTTON_PLAYLIST
268 #define AST_FIRE_REP (BUTTON_PLAYLIST | BUTTON_REPEAT)
270 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || CONFIG_KEYPAD == MROBE500_PAD
271 #define AST_QUIT BUTTON_POWER
274 #error No keymap defined!
277 #ifdef HAVE_TOUCHSCREEN
279 #define AST_PAUSE BUTTON_CENTER
282 #define AST_QUIT BUTTON_TOPLEFT
284 #ifndef AST_THRUST_REP
285 #define AST_THRUST_REP (BUTTON_TOPMIDDLE | BUTTON_REPEAT)
288 #define AST_THRUST BUTTON_TOPMIDDLE
290 #ifndef AST_HYPERSPACE
291 #define AST_HYPERSPACE BUTTON_TOPRIGHT
294 #define AST_LEFT BUTTON_MIDLEFT
297 #define AST_LEFT_REP (BUTTON_MIDLEFT | BUTTON_REPEAT)
300 #define AST_RIGHT BUTTON_MIDRIGHT
302 #ifndef AST_RIGHT_REP
303 #define AST_RIGHT_REP (BUTTON_MIDRIGHT | BUTTON_REPEAT)
306 #define AST_FIRE BUTTON_BOTTOMMIDDLE
311 #define AST_FIRE_REP (BUTTON_BOTTOMMIDDLE | BUTTON_MENU)
313 #define AST_FIRE_REP BUTTON_BOTTOMMIDDLE | BUTTON_REPEAT
319 #define ABS(x) ((x)>0?(x):-(x))
321 #define RES MAX(LCD_WIDTH, LCD_HEIGHT)
322 #define LARGE_LCD RES >= 200
323 #define ENEMY_MISSILE_SURVIVAL_LENGTH RES/2
324 #define ASTEROID_SPEED RES/20
325 #define MISSILE_SURVIVAL_LENGTH 40
327 #define EXTRA_LIFE 250
328 #define SPAWN_TIME 30
329 #define BLINK_TIME 10
331 #define MISSILE_SCALE 5000
333 #define EXPLOSION_LENGTH 20
335 #define HISCORE_FILE PLUGIN_GAMES_DIR "/astrorocks.hs"
337 #define MAX_NUM_ASTEROIDS 25
338 #define MAX_NUM_MISSILES 6
339 #define ENEMY_BIG_PROBABILITY_START 10
340 #define ENEMY_APPEAR_PROBABILITY_START 35
341 #define ENEMY_APPEAR_TIMING_START 1800
342 #define LITTLE_SHIP 2
344 #define SHOW_GAME_OVER_TIME 100
345 #define SHOW_LEVEL_TIME 50
346 #define START_LIVES 3
347 #define START_LEVEL 1
348 #define NUM_ASTEROID_VERTICES 10
349 #define NUM_SHIP_VERTICES 4
350 #define NUM_ENEMY_VERTICES 6
351 #define MAX_LEVEL MAX_NUM_ASTEROIDS
352 #define ENEMY_SPEED 4
353 #define ENEMY_START_X 0
354 #define ENEMY_START_Y 0
355 #define SIZE_ENEMY_COLLISION 5*SCALE
356 #define ATTRACT_FLIP_TIME 100
358 #define NUM_TRAIL_POINTS 70
359 #define NUM_ROTATIONS 16
361 #define SIN_COS_SCALE 10000
363 #define FAST_ROT_CW_SIN 873
364 #define FAST_ROT_CW_COS 9963
365 #define FAST_ROT_ACW_SIN -873
366 #define FAST_ROT_ACW_COS 9963
368 #define MEDIUM_ROT_CW_SIN 350
369 #define MEDIUM_ROT_CW_COS 9994
370 #define MEDIUM_ROT_ACW_SIN -350
371 #define MEDIUM_ROT_ACW_COS 9994
373 #define SLOW_ROT_CW_SIN 350
374 #define SLOW_ROT_CW_COS 9994
375 #define SLOW_ROT_ACW_SIN - 350
376 #define SLOW_ROT_ACW_COS 9994
378 #ifdef HAVE_LCD_COLOR
379 #define SHIP_ROT_CW_SIN 2419
380 #define SHIP_ROT_CW_COS 9702
381 #define SHIP_ROT_ACW_SIN -2419
382 #define SHIP_ROT_ACW_COS 9702
384 #define SHIP_ROT_CW_SIN 3827
385 #define SHIP_ROT_CW_COS 9239
386 #define SHIP_ROT_ACW_SIN -3827
387 #define SHIP_ROT_ACW_COS 9239
391 #define SCALED_WIDTH (LCD_WIDTH*SCALE)
392 #define SCALED_HEIGHT (LCD_HEIGHT*SCALE)
393 #define CENTER_LCD_X (LCD_WIDTH/2)
394 #define CENTER_LCD_Y (LCD_HEIGHT/2)
396 #define SHIP_EXPLOSION_COLOUR 1
397 #define ASTEROID_EXPLOSION_COLOUR 2
398 #define ENEMY_EXPLOSION_COLOUR 3
399 #define THRUST_COLOUR 4
401 #define ASTEROID_R 230
402 #define ASTEROID_G 200
403 #define ASTEROID_B 100
414 #ifdef HAVE_LCD_COLOR
415 #define COL_MISSILE LCD_RGBPACK(200,0,0)
416 #define COL_PLAYER LCD_RGBPACK(200,200,200)
417 #define COL_INVULN LCD_RGBPACK(100,100,200)
418 #define COL_STARS LCD_WHITE
419 #define COL_ASTEROID LCD_RGBPACK(ASTEROID_R,ASTEROID_G,ASTEROID_B)
420 #define COL_TEXT LCD_RGBPACK(200,200,255)
421 #define COL_ENEMY LCD_RGBPACK(ENEMY_R,ENEMY_G,ENEMY_B)
422 #define SET_FG rb->lcd_set_foreground
423 #define SET_BG rb->lcd_set_background
429 /* The array of points that make up an asteroid */
430 static const short asteroid_one
[NUM_ASTEROID_VERTICES
*2] =
444 /* The array of points that make up an asteroid */
445 static const short asteroid_two
[NUM_ASTEROID_VERTICES
*2] =
459 /* The array of points that make up an asteroid */
460 static const short asteroid_three
[NUM_ASTEROID_VERTICES
*2] =
474 /* The array od points the make up the ship */
475 static const short ship_vertices
[NUM_SHIP_VERTICES
*2] =
490 /* The array of points the make up the bad spaceship */
491 static const short enemy_vertices
[NUM_ENEMY_VERTICES
*2] =
545 struct Point position
;
552 /* Asteroid structure, contains an array of points */
555 enum asteroid_type type
;
557 struct Point position
;
558 struct Point vertices
[NUM_ASTEROID_VERTICES
];
562 int explode_countdown
;
567 struct Point vertices
[NUM_SHIP_VERTICES
];
568 struct Point position
;
569 bool waiting_for_space
;
572 int explode_countdown
;
577 struct Point vertices
[NUM_ENEMY_VERTICES
];
578 struct Point position
;
579 int explode_countdown
;
580 long last_time_appeared
;
581 short size_probability
;
582 short appear_probability
;
588 struct Point position
;
589 struct Point oldpoint
;
593 static enum game_state game_state
;
594 static int asteroid_count
;
595 static int next_missile_count
;
596 static int next_thrust_count
;
597 static int num_lives
;
598 static int extra_life
;
599 static int show_level_timeout
;
600 static int attract_flip_timeout
;
601 static int show_game_over
;
602 static int current_level
;
603 static int current_score
;
604 static int high_score
;
605 static int space_check_size
= 30*SCALE
;
607 static bool enemy_on_screen
;
608 static char phscore
[30];
609 static struct Ship ship
;
610 static struct Point stars
[NUM_STARS
];
611 static struct Asteroid asteroids_array
[MAX_NUM_ASTEROIDS
];
612 static struct Missile missiles_array
[MAX_NUM_MISSILES
];
613 static struct Missile enemy_missile
;
614 static struct Enemy enemy
;
615 static struct Point lives_points
[NUM_SHIP_VERTICES
];
616 static struct TrailPoint trailPoints
[NUM_TRAIL_POINTS
];
618 void draw_and_move_asteroids(void);
619 void initialise_game(int nStartNum
);
621 bool is_asteroid_near_ship(struct Asteroid
* asteroid
);
622 bool is_point_within_asteroid(struct Asteroid
* asteroid
, struct Point
* point
);
624 void initialise_asteroid(struct Asteroid
* asteroid
, enum asteroid_type eType
);
625 void draw_polygon(struct Point
* vertices
, int px
, int py
, int num_vertices
);
626 void rotate_asteroid(struct Asteroid
* asteroid
);
627 void create_asteroid(enum asteroid_type type
, int x
, int y
);
628 void create_stars(void);
630 void initialise_ship(void);
631 void draw_and_move_ship(void);
632 void rotate_ship(int s
, int c
);
633 void thrust_ship(void);
635 void initialise_missile(struct Missile
* missile
);
636 void draw_and_move_missiles(void);
637 void fire_missile(void);
639 void animate_and_draw_explosion(struct Point
* point
, int num_points
, int xoffset
, int yoffset
);
640 void initialise_explosion(struct Point
* point
, int num_points
);
642 void move_point(struct Point
* point
);
643 void hyperspace(void);
644 void check_collisions(void);
645 void initialise_enemy(void);
646 void draw_and_move_enemy(void);
647 void draw_lives(void);
648 void drawstars(void);
649 bool is_ship_within_asteroid(struct Asteroid
* asteroid
);
653 /*Hi-Score reading and writing to file - this needs moving to the hi-score plugin lib as
660 /* clear the buffer we're about to load the highscore data into */
661 rb
->memset(phscore
, 0, sizeof(phscore
));
663 fd
= rb
->open(HISCORE_FILE
,O_RDWR
| O_CREAT
);
666 rb
->splash(HZ
, "Highscore file read error");
670 /* highscore used to %d, is now %d\n
671 Deal with no file or bad file */
672 rb
->read(fd
,phscore
, sizeof(phscore
));
674 compare
= rb
->atoi(phscore
);
676 if(high_score
> compare
)
678 rb
->lseek(fd
,0,SEEK_SET
);
679 rb
->fdprintf(fd
, "%d\n", high_score
);
682 high_score
= compare
;
687 bool point_in_poly(struct Point
* _point
, int num_vertices
, int x
, int y
)
696 pj
+= num_vertices
-1;
701 if((((pi
->y
<= y
) && (y
< pj
->y
)) || ((pj
->y
<= y
) && (y
< pi
->y
))) &&
702 (x
< (pj
->x
- pi
->x
) * (y
- pi
->y
) / (pj
->y
- pi
->y
) + pi
->x
))
705 if(n
== num_vertices
- 1)
716 void move_point(struct Point
* point
)
718 point
->x
+= point
->dx
;
719 point
->y
+= point
->dy
;
721 /*check bounds on the x-axis:*/
722 if(point
->x
>= SCALED_WIDTH
)
724 else if(point
->x
<= 0)
725 point
->x
= SCALED_WIDTH
;
727 /*Check bounds on the y-axis:*/
728 if(point
->y
>= SCALED_HEIGHT
)
730 else if(point
->y
<= 0)
731 point
->y
= SCALED_HEIGHT
;
734 void create_trail(struct TrailPoint
* tpoint
)
736 tpoint
->position
.dx
= -( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/10;
737 tpoint
->position
.dy
= -( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/10;
740 void create_explosion_trail(struct TrailPoint
* tpoint
)
742 tpoint
->position
.dx
= (rb
->rand()%5050)-2500;
743 tpoint
->position
.dy
= (rb
->rand()%5050)-2500;
746 void create_trail_blaze(int colour
, struct Point
* position
)
749 struct TrailPoint
* tpoint
;
752 if(colour
!= SHIP_EXPLOSION_COLOUR
)
754 numtoadd
= NUM_TRAIL_POINTS
/5;
760 numtoadd
= NUM_TRAIL_POINTS
/8;
761 xadd
= ship
.position
.x
;
762 yadd
= ship
.position
.y
;
765 /* give the point a random countdown timer, so they dissapears at different times */
766 tpoint
= trailPoints
;
767 n
= NUM_TRAIL_POINTS
;
770 if(tpoint
->alive
<= 0 && numtoadd
)
773 /* take a random x point anywhere between bottom two points of ship. */
774 /* ship.position.x; */
775 tpoint
->position
.x
= (ship
.vertices
[2].x
+ (rb
->rand()%18000)-9000) + position
->x
;
776 tpoint
->position
.y
= (ship
.vertices
[2].y
+ (rb
->rand()%18000)-9000) + position
->y
;
780 case SHIP_EXPLOSION_COLOUR
:
784 create_explosion_trail(tpoint
);
788 case ASTEROID_EXPLOSION_COLOUR
:
789 tpoint
->r
= ASTEROID_R
;
790 tpoint
->g
= ASTEROID_G
;
791 tpoint
->b
= ASTEROID_B
;
792 create_explosion_trail(tpoint
);
796 case ENEMY_EXPLOSION_COLOUR
:
800 create_explosion_trail(tpoint
);
805 tpoint
->r
= THRUST_R
;
806 tpoint
->g
= THRUST_G
;
807 tpoint
->b
= THRUST_B
;
808 create_trail(tpoint
);
813 /* add a proportional bit to the x and y based on dx and dy */
815 /* give the points a speed based on direction of travel - i.e. opposite */
816 tpoint
->position
.dx
+= position
->dx
;
817 tpoint
->position
.dy
+= position
->dy
;
823 /* find a space in the array of trail_points that is NULL or DEAD or whatever.
824 and place this one here. */
828 void draw_trail_blaze(void)
830 struct TrailPoint
* tpoint
;
831 /* loop through, if alive then move and draw.
832 when drawn, countdown it's timer.
834 tpoint
= trailPoints
;
835 int n
= NUM_TRAIL_POINTS
;
841 if(game_state
!= PAUSE_MODE
)
844 move_point(&(tpoint
->position
));
846 #ifdef HAVE_LCD_COLOR
847 /* intensity = tpoint->alive/2; */
848 if(tpoint
->r
>0)tpoint
->r
-=tpoint
->dec
;
849 if(tpoint
->g
>0)tpoint
->g
-=tpoint
->dec
;
850 if(tpoint
->b
>0)tpoint
->b
-=tpoint
->dec
;
851 SET_FG(LCD_RGBPACK(tpoint
->r
, tpoint
->g
, tpoint
->b
));
853 rb
->lcd_drawpixel(tpoint
->position
.x
/SCALE
, tpoint
->position
.y
/SCALE
);
859 /*Check if point is within a rectangle*/
860 bool is_point_within_rectangle(struct Point
* rect
, struct Point
* p
, int size
)
863 int aTLx
= rect
->x
- size
;
864 int aTLy
= rect
->y
- size
;
865 int aBRx
= rect
->x
+ size
;
866 int aBRy
= rect
->y
+ size
;
867 rb
->lcd_hline( aTLx
/SCALE
, aBRx
/SCALE
, aTLy
/SCALE
);
868 rb
->lcd_vline( aTLx
/SCALE
, aTLy
/SCALE
, aBRy
/SCALE
);
869 rb
->lcd_hline( aTLx
/SCALE
, aBRx
/SCALE
, aBRy
/SCALE
);
870 rb
->lcd_vline( aBRx
/SCALE
, aBRy
/SCALE
, aTLy
/SCALE
);
871 return (p
->x
> aTLx
&& p
->x
< aBRx
&& p
->y
> aTLy
&& p
->y
< aBRy
);
873 return (p
->x
> rect
->x
- size
&& p
->x
< rect
->x
+ size
&&
874 p
->y
> rect
->y
- size
&& p
->y
< rect
->y
+ size
);
879 void draw_polygon(struct Point
* vertices
, int px
, int py
, int num_vertices
)
881 int n
, t1
, t2
, oldX
, oldY
;
883 bool bDrawAll
= px
< WRAP_GAP
|| LCD_WIDTH
- px
< WRAP_GAP
||
884 py
< WRAP_GAP
|| LCD_HEIGHT
- py
< WRAP_GAP
;
888 oldX
= p
->x
/SCALE
+ px
;
889 oldY
= p
->y
/SCALE
+ py
;
891 for(n
= num_vertices
+1; --n
;)
893 t1
= p
->x
/SCALE
+ px
;
894 t2
= p
->y
/SCALE
+ py
;
896 rb
->lcd_drawline(oldX
, oldY
, t1
, t2
);
900 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
, t1
- LCD_WIDTH
, t2
);
901 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
, t1
+ LCD_WIDTH
, t2
);
902 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
+ LCD_HEIGHT
,
903 t1
- LCD_WIDTH
, t2
+ LCD_HEIGHT
);
904 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
+ LCD_HEIGHT
,
905 t1
+ LCD_WIDTH
, t2
+ LCD_HEIGHT
);
907 rb
->lcd_drawline(oldX
, oldY
- LCD_HEIGHT
, t1
, t2
- LCD_HEIGHT
);
908 rb
->lcd_drawline(oldX
, oldY
+ LCD_HEIGHT
, t1
, t2
+ LCD_HEIGHT
);
909 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
- LCD_HEIGHT
,
910 t1
- LCD_WIDTH
, t2
- LCD_HEIGHT
);
911 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
- LCD_HEIGHT
,
912 t1
+ LCD_WIDTH
, t2
- LCD_HEIGHT
);
920 void animate_and_draw_explosion(struct Point
* point
, int num_points
,
921 int xoffset
, int yoffset
)
924 for(n
= num_points
; --n
;)
926 if(game_state
!= PAUSE_MODE
)
928 point
->x
+= point
->dx
;
929 point
->y
+= point
->dy
;
931 rb
->lcd_fillrect( point
->x
/SCALE
+ xoffset
, point
->y
/SCALE
+ yoffset
,
932 POINT_SIZE
, POINT_SIZE
);
937 /*stop movement of ship, 'cos that's what happens when you go into hyperspace.*/
938 void hyperspace(void)
940 ship
.position
.dx
= ship
.position
.dy
= 0;
941 ship
.position
.x
= (rb
->rand()%SCALED_WIDTH
);
942 ship
.position
.y
= (rb
->rand()%SCALED_HEIGHT
);
945 void initialise_enemy(void)
951 if(rb
->rand()%100 > enemy
.size_probability
)
954 enemy
.size_probability
++;
955 if(enemy
.size_probability
< 90)
957 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
965 enemy_missile
.survived
= 0;
966 enemy_on_screen
= true;
967 enemy
.explode_countdown
= 0;
968 enemy
.last_time_appeared
= *rb
->current_tick
;
969 point
= enemy
.vertices
;
970 for(n
= 0; n
< NUM_ENEMY_VERTICES
+NUM_ENEMY_VERTICES
; n
+=2)
972 point
->x
= enemy_vertices
[n
];
973 point
->y
= enemy_vertices
[n
+1];
974 point
->x
*= SCALE
/size
;
975 point
->y
*= SCALE
/size
;
979 if(ship
.position
.x
>= SCALED_WIDTH
/2)
981 enemy
.position
.dx
= ENEMY_SPEED
;
982 enemy
.position
.x
= 0;
986 enemy
.position
.dx
= -ENEMY_SPEED
;
987 enemy
.position
.x
= SCALED_WIDTH
;
990 if(ship
.position
.y
>= SCALED_HEIGHT
/2)
992 enemy
.position
.dy
= ENEMY_SPEED
;
993 enemy
.position
.y
= 0;
997 enemy
.position
.dy
= -ENEMY_SPEED
;
998 enemy
.position
.y
= SCALED_HEIGHT
;
1001 enemy
.position
.dx
*= SCALE
/10;
1002 enemy
.position
.dy
*= SCALE
/10;
1005 void draw_and_move_enemy(void)
1007 int enemy_x
, enemy_y
;
1008 struct Point
*point
;
1014 enemy_x
= enemy
.position
.x
/SCALE
;
1015 enemy_y
= enemy
.position
.y
/SCALE
;
1016 if(!enemy
.explode_countdown
)
1018 point
= enemy
.vertices
;
1019 draw_polygon(enemy
.vertices
, enemy_x
, enemy_y
, NUM_ENEMY_VERTICES
);
1020 rb
->lcd_drawline(enemy
.vertices
[0].x
/SCALE
+ enemy_x
,
1021 enemy
.vertices
[0].y
/SCALE
+ enemy_y
,
1022 enemy
.vertices
[3].x
/SCALE
+ enemy_x
,
1023 enemy
.vertices
[3].y
/SCALE
+ enemy_y
);
1025 if(game_state
!= PAUSE_MODE
)
1027 enemy
.position
.x
+= enemy
.position
.dx
;
1028 enemy
.position
.y
+= enemy
.position
.dy
;
1031 if(enemy
.position
.x
> SCALED_WIDTH
|| enemy
.position
.x
< 0)
1032 enemy_on_screen
= false;
1034 if(enemy
.position
.y
> SCALED_HEIGHT
)
1035 enemy
.position
.y
= 0;
1036 else if(enemy
.position
.y
< 0)
1037 enemy
.position
.y
= SCALED_HEIGHT
;
1039 if( (rb
->rand()%1000) < 10)
1040 enemy
.position
.dy
= -enemy
.position
.dy
;
1045 /* animate_and_draw_explosion(enemy.vertices, NUM_ENEMY_VERTICES,
1046 enemy_x, enemy.position.y/SCALE); */
1047 if(game_state
!= PAUSE_MODE
)
1049 enemy
.explode_countdown
--;
1050 if(!enemy
.explode_countdown
)
1051 enemy_on_screen
= false;
1057 if( (*rb
->current_tick
- enemy
.last_time_appeared
) > enemy
.appear_timing
)
1058 if(rb
->rand()%100 > enemy
.appear_probability
) initialise_enemy();
1061 if(!enemy_missile
.survived
&& game_state
!= GAME_OVER
)
1063 /*if no missile and the enemy is here and not exploding..then shoot baby!*/
1064 if( !enemy
.explode_countdown
&& enemy_on_screen
&&
1065 !ship
.waiting_for_space
&& (rb
->rand()%10) > 5 )
1067 enemy_missile
.position
.x
= enemy
.position
.x
;
1068 enemy_missile
.position
.y
= enemy
.position
.y
;
1070 /*lame, needs to be sorted - it's trying to shoot at the ship*/
1071 if(ABS(enemy
.position
.y
- ship
.position
.y
) <= 5*SCALE
)
1073 enemy_missile
.position
.dy
= 0;
1077 if( enemy
.position
.y
< ship
.position
.y
)
1078 enemy_missile
.position
.dy
= 1;
1080 enemy_missile
.position
.dy
= -1;
1083 if(ABS(enemy
.position
.x
- ship
.position
.x
) <= 5*SCALE
)
1084 enemy_missile
.position
.dx
= 0;
1087 if( enemy
.position
.x
< ship
.position
.x
)
1088 enemy_missile
.position
.dx
= 1;
1090 enemy_missile
.position
.dx
= -1;
1093 if(enemy_missile
.position
.dx
== 0 &&
1094 enemy_missile
.position
.dy
== 0)
1095 enemy_missile
.position
.dx
= enemy_missile
.position
.dy
= -1;
1097 enemy_missile
.position
.dx
*= SCALE
;
1098 enemy_missile
.position
.dy
*= SCALE
;
1099 enemy_missile
.survived
= ENEMY_MISSILE_SURVIVAL_LENGTH
;
1105 rb
->lcd_fillrect( enemy_missile
.position
.x
/SCALE
,
1106 enemy_missile
.position
.y
/SCALE
,
1107 POINT_SIZE
, POINT_SIZE
);
1108 if(game_state
!= PAUSE_MODE
)
1110 move_point(&enemy_missile
.position
);
1111 enemy_missile
.survived
--;
1117 * Lame method of collision
1118 * detection. It's checking for collision
1119 * between point and a big rectangle around the asteroid...
1120 *******************/
1121 bool is_point_within_asteroid(struct Asteroid
* asteroid
, struct Point
* point
)
1123 if( !is_point_within_rectangle(&asteroid
->position
, point
,
1124 asteroid
->radius
+4*SCALE
) )
1127 if(point_in_poly(asteroid
->vertices
, NUM_ASTEROID_VERTICES
,
1128 point
->x
- asteroid
->position
.x
,
1129 point
->y
- asteroid
->position
.y
))
1131 switch(asteroid
->type
)
1134 asteroid
->explode_countdown
= EXPLOSION_LENGTH
;
1135 create_trail_blaze(ASTEROID_EXPLOSION_COLOUR
, &asteroid
->position
);
1139 create_asteroid(MEDIUM
, asteroid
->position
.x
,
1140 asteroid
->position
.y
);
1141 create_asteroid(MEDIUM
, asteroid
->position
.x
,
1142 asteroid
->position
.y
);
1146 create_asteroid(SMALL
, asteroid
->position
.x
, asteroid
->position
.y
);
1147 create_asteroid(SMALL
, asteroid
->position
.x
, asteroid
->position
.y
);
1152 if(current_score
> extra_life
)
1155 extra_life
= current_score
+EXTRA_LIFE
;
1158 asteroid
->exists
= false;
1165 bool is_point_within_enemy(struct Point
* point
)
1167 if( is_point_within_rectangle(&enemy
.position
, point
, 7*SCALE
) )
1170 /*enemy_missile.survived = 0;*/
1171 enemy
.explode_countdown
= EXPLOSION_LENGTH
;
1172 /* initialise_explosion(enemy.vertices, NUM_ENEMY_VERTICES); */
1173 create_trail_blaze(ENEMY_EXPLOSION_COLOUR
, &enemy
.position
);
1180 bool is_ship_within_asteroid(struct Asteroid
* asteroid
)
1185 p
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1186 p
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1187 hit
|= is_point_within_asteroid(asteroid
, &p
);
1191 p
.x
= ship
.position
.x
+ ship
.vertices
[1].x
;
1192 p
.y
= ship
.position
.y
+ ship
.vertices
[1].y
;
1193 hit
|= is_point_within_asteroid(asteroid
, &p
);
1196 p
.x
= ship
.position
.x
+ ship
.vertices
[3].x
;
1197 p
.y
= ship
.position
.y
+ ship
.vertices
[3].y
;
1198 hit
|= is_point_within_asteroid(asteroid
, &p
);
1205 void initialise_explosion(struct Point
* point
, int num_points
)
1209 point
->x
+= point
->dx
;
1210 point
->y
+= point
->dy
;
1211 for(n
= num_points
; --n
;)
1213 point
->dx
= point
->x
;
1214 point
->dy
= point
->y
;
1220 /* Check for collsions between the missiles and the asteroids and the ship */
1221 void check_collisions(void)
1224 bool asteroids_onscreen
= false;
1225 struct Missile
* missile
;
1226 struct Asteroid
* asteroid
;
1227 bool ship_cant_be_placed
= false;
1229 asteroid
= asteroids_array
;
1230 m
= MAX_NUM_ASTEROIDS
;
1233 /*if the asteroids exists then test missile collision:*/
1234 if(asteroid
->exists
)
1236 missile
= missiles_array
;
1237 n
= MAX_NUM_MISSILES
;
1240 /*if the missiles exists:*/
1241 if(missile
->survived
> 0)
1243 /*has the missile hit the asteroid?*/
1244 if(is_point_within_asteroid(asteroid
, &missile
->position
)
1245 || is_point_within_asteroid(asteroid
,
1246 &missile
->oldpoint
))
1248 missile
->survived
= 0;
1255 /*now check collision with ship:*/
1256 if(asteroid
->exists
&& !ship
.waiting_for_space
&& !ship
.explode_countdown
)
1258 if(is_ship_within_asteroid(asteroid
))
1260 if (!ship
.invulnerable
)
1262 /*if not invulnerable, blow up ship*/
1263 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1264 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1265 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1269 /*has the enemy missile blown something up?*/
1270 if(asteroid
->exists
&& enemy_missile
.survived
)
1272 if(is_point_within_asteroid(asteroid
, &enemy_missile
.position
))
1274 /*take that score back then:*/
1275 if(current_score
> 0) current_score
--;
1276 enemy_missile
.survived
= 0;
1279 /*if it still exists, check if ship is waiting for space:*/
1280 if(asteroid
->exists
&& ship
.waiting_for_space
)
1281 ship_cant_be_placed
|=
1282 is_point_within_rectangle(&ship
.position
,
1283 &asteroid
->position
,
1288 /*is an asteroid still exploding?*/
1289 if(asteroid
->explode_countdown
)
1290 asteroids_onscreen
= true;
1295 /*now check collision between ship and enemy*/
1296 if(enemy_on_screen
&& !ship
.waiting_for_space
&&
1297 !ship
.explode_countdown
&& !enemy
.explode_countdown
)
1299 /*has the enemy collided with the ship?*/
1300 if(is_point_within_enemy(&ship
.position
))
1302 if (!ship
.invulnerable
)
1304 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1305 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1306 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1308 create_trail_blaze(ENEMY_EXPLOSION_COLOUR
, &enemy
.position
);
1311 /*Now see if the enemy has been shot at by the ships missiles:*/
1312 missile
= missiles_array
;
1313 n
= MAX_NUM_MISSILES
;
1316 if(missile
->survived
> 0 &&
1317 is_point_within_enemy(&missile
->position
))
1319 missile
->survived
= 0;
1326 /*test collision with enemy missile and ship:*/
1327 if(!ship_cant_be_placed
&& enemy_missile
.survived
> 0 &&
1328 point_in_poly(ship
.vertices
, NUM_SHIP_VERTICES
,
1329 enemy_missile
.position
.x
- ship
.position
.x
,
1330 enemy_missile
.position
.y
- ship
.position
.y
))
1332 if (!ship
.invulnerable
)
1334 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1335 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1336 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1338 enemy_missile
.survived
= 0;
1339 enemy_missile
.position
.x
= enemy_missile
.position
.y
= 0;
1342 if(!ship_cant_be_placed
)
1343 ship
.waiting_for_space
= false;
1345 /*if all asteroids cleared then start again:*/
1346 if(asteroid_count
== 0 && !enemy_on_screen
&& !asteroids_onscreen
)
1349 game_state
= SHOW_LEVEL
;
1350 enemy
.appear_probability
+= 5;
1351 enemy
.appear_timing
-= 200;
1352 if( enemy
.appear_probability
> 100)
1353 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1354 show_level_timeout
= SHOW_LEVEL_TIME
;
1358 /*************************************************
1359 ** Creates a new asteroid of the given 4type (size)
1360 ** and at the given location.
1361 *************************************************/
1362 void create_asteroid(enum asteroid_type type
, int x
, int y
)
1364 struct Asteroid
* asteroid
;
1367 asteroid
= asteroids_array
;
1368 n
= MAX_NUM_ASTEROIDS
;
1371 if(!asteroid
->exists
&& !asteroid
->explode_countdown
)
1373 initialise_asteroid(asteroid
, type
);
1374 asteroid
->position
.x
= x
;
1375 asteroid
->position
.y
= y
;
1382 /* Initialise a missile */
1383 void initialise_missile(struct Missile
* missile
)
1385 missile
->position
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1386 missile
->position
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1387 missile
->position
.dx
= (ship
.vertices
[0].x
- ship
.vertices
[2].x
)/2;
1388 missile
->position
.dy
= (ship
.vertices
[0].y
- ship
.vertices
[2].y
)/2;
1389 missile
->survived
= MISSILE_SURVIVAL_LENGTH
;
1390 missile
->oldpoint
.x
= missile
->position
.x
;
1391 missile
->oldpoint
.y
= missile
->position
.y
;
1394 /* Draw and Move all the missiles */
1395 void draw_and_move_missiles(void)
1401 struct Missile
* missile
;
1402 missile
= missiles_array
;
1404 SET_FG(COL_MISSILE
);
1406 n
= MAX_NUM_MISSILES
;
1409 if(missile
->survived
)
1411 if(missile
->position
.dx
> 0)
1413 if(missile
->position
.x
>= missile
->oldpoint
.x
)
1415 p1x
= missile
->oldpoint
.x
;
1416 p2x
= missile
->position
.x
;
1421 p2x
= missile
->position
.x
;
1426 if(missile
->oldpoint
.x
>= missile
->position
.x
)
1428 p1x
= missile
->oldpoint
.x
;
1429 p2x
= missile
->position
.x
;
1433 p1x
= missile
->oldpoint
.x
;
1438 if(missile
->position
.dy
> 0)
1440 if(missile
->position
.y
>= missile
->oldpoint
.y
)
1442 p1y
= missile
->oldpoint
.y
;
1443 p2y
= missile
->position
.y
;
1448 p2y
= missile
->position
.y
;
1453 if(missile
->oldpoint
.y
>= missile
->position
.y
)
1455 p1y
= missile
->oldpoint
.y
;
1456 p2y
= missile
->position
.y
;
1460 p1y
= missile
->oldpoint
.y
;
1465 rb
->lcd_drawline( p1x
/SCALE
, p1y
/SCALE
, p2x
/SCALE
, p2y
/SCALE
);
1467 if(game_state
!= PAUSE_MODE
)
1469 missile
->oldpoint
.x
= missile
->position
.x
;
1470 missile
->oldpoint
.y
= missile
->position
.y
;
1471 move_point(&missile
->position
);
1472 missile
->survived
--;
1479 void draw_lives(void)
1482 int px
= (LCD_WIDTH
- num_lives
*4 - 1);
1484 int py
= (LCD_HEIGHT
-6);
1486 int py
= (LCD_HEIGHT
-4);
1494 draw_polygon(lives_points
, px
, py
, NUM_SHIP_VERTICES
);
1503 /*Fire the next missile*/
1504 void fire_missile(void)
1507 struct Missile
* missile
;
1509 if(!ship
.explode_countdown
&& !ship
.waiting_for_space
)
1511 missile
= missiles_array
;
1512 n
= MAX_NUM_MISSILES
;
1515 if(!missile
->survived
)
1517 initialise_missile(missile
);
1525 /* Initialise the passed Asteroid */
1526 void initialise_asteroid(struct Asteroid
* asteroid
, enum asteroid_type type
)
1530 struct Point
* point
;
1531 asteroid
->exists
= true;
1532 asteroid
->type
= type
;
1533 asteroid
->explode_countdown
= 0;
1535 /*Set the radius of the asteroid:*/
1536 asteroid
->radius
= (int)type
*SCALE
;
1538 /*shall we move Clockwise and Fast*/
1539 if((rb
->rand()%100)>75)
1541 asteroid
->speed_cos
= FAST_ROT_CW_COS
;
1542 asteroid
->speed_sin
= FAST_ROT_CW_SIN
;
1544 else if((rb
->rand()%100)>75)
1546 asteroid
->speed_cos
= FAST_ROT_ACW_COS
;
1547 asteroid
->speed_sin
= FAST_ROT_ACW_SIN
;
1549 else if((rb
->rand()%100)>75)
1551 asteroid
->speed_cos
= SLOW_ROT_ACW_COS
;
1552 asteroid
->speed_sin
= SLOW_ROT_ACW_SIN
;
1556 asteroid
->speed_cos
= SLOW_ROT_CW_COS
;
1557 asteroid
->speed_sin
= SLOW_ROT_CW_SIN
;
1560 b
= (rb
->rand()%100)>66;
1561 b2
= (rb
->rand()%100)>66;
1562 point
= asteroid
->vertices
;
1563 for(n
= 0; n
< NUM_ASTEROID_VERTICES
*2; n
+=2)
1567 point
->x
= asteroid_one
[n
];
1568 point
->y
= asteroid_one
[n
+1];
1572 point
->x
= asteroid_two
[n
];
1573 point
->y
= asteroid_two
[n
+1];
1577 point
->x
= asteroid_three
[n
];
1578 point
->y
= asteroid_three
[n
+1];
1581 point
->x
*= asteroid
->radius
/6;
1582 point
->y
*= asteroid
->radius
/6;
1587 asteroid
->radius
+= 6*SCALE
;
1588 if(asteroid
->type
== SMALL
)
1589 asteroid
->radius
/= 3;/*2*/
1590 else if(asteroid
->type
== LARGE
)
1591 asteroid
->radius
+= 3*SCALE
;/*2*/
1595 /*Set the position randomly:*/
1596 asteroid
->position
.x
= (rb
->rand()%SCALED_WIDTH
);
1597 asteroid
->position
.y
= (rb
->rand()%SCALED_HEIGHT
);
1599 asteroid
->position
.dx
= 0;
1600 while(asteroid
->position
.dx
== 0)
1601 asteroid
->position
.dx
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
1603 asteroid
->position
.dy
= 0;
1604 while(asteroid
->position
.dy
== 0)
1605 asteroid
->position
.dy
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
1607 asteroid
->position
.dx
*= SCALE
/10;
1608 asteroid
->position
.dy
*= SCALE
/10;
1610 b
= is_point_within_rectangle(&ship
.position
, &asteroid
->position
,
1614 /*Now rotate the asteroid a bit, so they all look a bit different*/
1615 for(n
=(rb
->rand()%30) + 2;--n
;)
1616 rotate_asteroid(asteroid
);
1618 /*great, we've created an asteroid, don't forget to increment the total:*/
1622 /*Initialise the ship*/
1623 void initialise_ship(void)
1625 struct Point
* point
;
1626 struct Point
* lives_point
;
1629 ship
.position
.x
= CENTER_LCD_X
;
1630 ship
.position
.y
= CENTER_LCD_Y
;
1631 ship
.position
.x
*= SCALE
;
1632 ship
.position
.y
*= SCALE
;
1633 ship
.position
.dx
= ship
.position
.dy
= 0;
1634 ship
.spawn_time
= SPAWN_TIME
;
1635 ship
.invulnerable
= 1;
1637 point
= ship
.vertices
;
1638 lives_point
= lives_points
;
1639 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+=2)
1641 point
->x
= ship_vertices
[n
];
1642 point
->y
= ship_vertices
[n
+1];
1649 ship
.position
.dx
= 0;
1650 ship
.position
.dy
= 0;
1651 ship
.explode_countdown
= 0;
1653 /*grab a copy of the ships points for the lives display:*/
1654 point
= ship
.vertices
;
1655 lives_point
= lives_points
;
1656 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+=2)
1658 lives_point
->x
= point
->x
;
1659 lives_point
->y
= point
->y
;
1665 void rotate_asteroid(struct Asteroid
* asteroid
)
1667 struct Point
* point
;
1671 point
= asteroid
->vertices
;
1672 for(n
= NUM_ASTEROID_VERTICES
+1; --n
;)
1675 point
->x
= xtemp
*asteroid
->speed_cos
/SIN_COS_SCALE
-
1676 point
->y
*asteroid
->speed_sin
/SIN_COS_SCALE
;
1677 point
->y
= point
->y
*asteroid
->speed_cos
/SIN_COS_SCALE
+
1678 xtemp
*asteroid
->speed_sin
/SIN_COS_SCALE
;
1683 /*************************************************
1684 ** Draws the ship, moves the ship and creates a new
1685 ** one if it's finished exploding.
1686 **************************************************/
1687 void draw_and_move_ship(void)
1689 int nxoffset
= ship
.position
.x
/SCALE
;
1690 int nyoffset
= ship
.position
.y
/SCALE
;
1691 if (ship
.invulnerable
&& (ship
.spawn_time
> BLINK_TIME
|| ship
.spawn_time
% 2 == 0))
1699 if(!ship
.explode_countdown
)
1701 /* make sure ship is invulnerable until spawn time over */
1702 if (ship
.spawn_time
)
1705 if (ship
.spawn_time
<= 0)
1707 ship
.invulnerable
= 0;
1710 if(!ship
.waiting_for_space
)
1712 draw_polygon(ship
.vertices
, nxoffset
, nyoffset
, NUM_SHIP_VERTICES
);
1713 if(game_state
!= PAUSE_MODE
&& game_state
!= GAME_OVER
)
1715 move_point(&ship
.position
);
1721 /* animate_and_draw_explosion(ship.vertices, NUM_SHIP_VERTICES,
1722 ship.position.x/SCALE,
1723 ship.position.y/SCALE); */
1724 if(game_state
!= PAUSE_MODE
)
1726 ship
.explode_countdown
--;
1727 if(!ship
.explode_countdown
)
1732 show_game_over
= SHOW_GAME_OVER_TIME
;
1733 game_state
= GAME_OVER
;
1738 ship
.waiting_for_space
= true;
1745 void thrust_ship(void)
1747 if(!ship
.waiting_for_space
)
1749 ship
.position
.dx
+= ( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/20;
1750 ship
.position
.dy
+= ( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/20;
1751 /*if dx and dy are below a certain threshold, then set 'em to 0
1752 but to do this we need to ascertain if the spacehip as moved on screen
1753 for more than a certain amount. */
1755 create_trail_blaze(THRUST_COLOUR
, &ship
.position
);
1759 /**************************************************
1760 ** Rotate the ship using the passed sin & cos values
1761 ***************************************************/
1762 void rotate_ship(int c
, int s
)
1764 struct Point
* point
;
1768 if(!ship
.waiting_for_space
&& !ship
.explode_countdown
)
1770 point
= ship
.vertices
;
1771 for(n
=NUM_SHIP_VERTICES
+1;--n
;)
1774 point
->x
= xtemp
*c
/SIN_COS_SCALE
- point
->y
*s
/SIN_COS_SCALE
;
1775 point
->y
= point
->y
*c
/SIN_COS_SCALE
+ xtemp
*s
/SIN_COS_SCALE
;
1791 rb
->lcd_drawpixel(p
->x
, p
->y
);
1796 /*************************************************
1797 ** Draw And Move all Asteroids
1798 *************************************************/
1799 void draw_and_move_asteroids(void)
1802 struct Asteroid
* asteroid
;
1804 asteroid
= asteroids_array
;
1805 SET_FG(COL_ASTEROID
);
1807 n
= MAX_NUM_ASTEROIDS
;
1810 if(game_state
!= PAUSE_MODE
)
1812 if(asteroid
->exists
)
1814 move_point(&asteroid
->position
);
1815 rotate_asteroid(asteroid
);
1816 draw_polygon(asteroid
->vertices
, asteroid
->position
.x
/SCALE
,
1817 asteroid
->position
.y
/SCALE
,
1818 NUM_ASTEROID_VERTICES
);
1820 else if(asteroid
->explode_countdown
)
1822 /* animate_and_draw_explosion(asteroid->vertices,
1823 NUM_ASTEROID_VERTICES,
1824 asteroid->position.x/SCALE,
1825 asteroid->position.y/SCALE); */
1826 asteroid
->explode_countdown
--;
1831 if(asteroid
->exists
)
1832 draw_polygon(asteroid
->vertices
,
1833 asteroid
->position
.x
/SCALE
,
1834 asteroid
->position
.y
/SCALE
,
1835 NUM_ASTEROID_VERTICES
);
1841 void create_stars(void)
1843 struct TrailPoint
* tpoint
;
1851 p
->x
= (rb
->rand()%LCD_WIDTH
);
1852 p
->y
= (rb
->rand()%LCD_HEIGHT
);
1857 /* give the point a random countdown timer, so they dissapears at different
1859 tpoint
= trailPoints
;
1860 n
= NUM_TRAIL_POINTS
;
1868 /*************************************************
1869 ** Creates start_num number of new asteroids of
1871 **************************************************/
1872 void initialise_game(int start_num
)
1875 asteroid_count
= next_missile_count
= next_thrust_count
= 0;
1876 struct Asteroid
* asteroid
;
1877 struct Missile
* missile
;
1878 extra_life
= EXTRA_LIFE
;
1881 enemy_on_screen
= 0;
1882 enemy_missile
.survived
= 0;
1885 asteroid
= asteroids_array
;
1886 n
= MAX_NUM_ASTEROIDS
;
1889 asteroid
->exists
= false;
1893 /*make some LARGE asteroids*/
1894 for(n
= 0; n
< start_num
; n
++)
1895 initialise_asteroid(&asteroids_array
[n
], LARGE
);
1897 /*ensure all missiles are out of action: */
1898 missile
= missiles_array
;
1899 n
= MAX_NUM_MISSILES
;
1902 missile
->survived
=0;
1907 void start_attract_mode(void)
1909 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1910 enemy
.appear_timing
= ENEMY_APPEAR_TIMING_START
;
1912 num_lives
= START_LIVES
;
1914 attract_flip_timeout
= ATTRACT_FLIP_TIME
;
1915 game_state
= ATTRACT_MODE
;
1916 if(asteroid_count
< 3)
1917 initialise_game(current_level
);
1920 enum plugin_status
start_game(void)
1928 /*create stars once, and once only:*/
1935 /*game starts with at level 1
1937 start_attract_mode();
1942 end
= *rb
->current_tick
+ (CYCLETIME
* HZ
) / 1000;
1943 rb
->lcd_clear_display();
1948 if(attract_flip_timeout
< ATTRACT_FLIP_TIME
/2)
1950 rb
->lcd_putsxy(CENTER_LCD_X
- 39,
1951 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4,
1953 if(!attract_flip_timeout
)
1954 attract_flip_timeout
= ATTRACT_FLIP_TIME
;
1958 rb
->snprintf(s
, sizeof(s
), "Hi Score %d ", high_score
);
1959 rb
->lcd_putsxy(CENTER_LCD_X
- 30,
1960 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, s
);
1962 attract_flip_timeout
--;
1966 rb
->lcd_putsxy(CENTER_LCD_X
- 25,
1967 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, "Game Over");
1968 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1969 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1972 start_attract_mode();
1976 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1977 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1978 rb
->lcd_putsxy(CENTER_LCD_X
- 15,
1979 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, "pause");
1980 draw_and_move_missiles();
1982 draw_and_move_ship();
1986 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1987 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1988 draw_and_move_missiles();
1991 draw_and_move_ship();
1995 show_level_timeout
--;
1996 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1997 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1998 rb
->snprintf(level
, sizeof(level
), "stage %d ", current_level
);
1999 rb
->lcd_putsxy(CENTER_LCD_X
- 20,
2000 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, level
);
2001 draw_and_move_ship();
2003 if(!show_level_timeout
)
2005 initialise_game(current_level
);
2006 game_state
= PLAY_MODE
;
2013 draw_and_move_asteroids();
2014 draw_and_move_enemy();
2017 button
= rb
->button_get(false);
2019 #ifdef HAS_BUTTON_HOLD
2020 if (rb
->button_hold() && game_state
== PLAY_MODE
)
2021 game_state
= PAUSE_MODE
;
2027 if(game_state
== PLAY_MODE
)
2028 game_state
= PAUSE_MODE
;
2029 else if(game_state
== PAUSE_MODE
)
2030 game_state
= PLAY_MODE
;
2037 if(game_state
== ATTRACT_MODE
)
2039 else if(game_state
== GAME_OVER
)
2041 start_attract_mode();
2045 show_game_over
= SHOW_GAME_OVER_TIME
;
2046 game_state
= GAME_OVER
;
2050 case (AST_LEFT_REP
):
2052 if(game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
2053 rotate_ship(SHIP_ROT_ACW_COS
, SHIP_ROT_ACW_SIN
);
2056 case (AST_RIGHT_REP
):
2058 if(game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
2059 rotate_ship(SHIP_ROT_CW_COS
, SHIP_ROT_CW_SIN
);
2062 case (AST_THRUST_REP
):
2064 if((game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
) && !next_thrust_count
)
2067 next_thrust_count
= 5;
2071 case (AST_HYPERSPACE
):
2072 if(game_state
== PLAY_MODE
)
2074 /*maybe shield if it gets too hard */
2077 case (AST_FIRE_REP
):
2079 if(game_state
== ATTRACT_MODE
)
2081 current_level
= START_LEVEL
;
2083 initialise_game(current_level
);
2084 show_level_timeout
= SHOW_LEVEL_TIME
;
2085 game_state
= PLAY_MODE
;
2087 else if(game_state
== PLAY_MODE
)
2089 if(!next_missile_count
)
2092 next_missile_count
= 10;
2095 else if(game_state
== PAUSE_MODE
)
2097 game_state
= PLAY_MODE
;
2102 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
)
2103 return PLUGIN_USB_CONNECTED
;
2109 if(high_score
< current_score
)
2110 high_score
= current_score
;
2115 if(next_missile_count
)
2116 next_missile_count
--;
2118 if(next_thrust_count
)
2119 next_thrust_count
--;
2121 if (end
> *rb
->current_tick
)
2122 rb
->sleep(end
-*rb
->current_tick
);
2130 enum plugin_status
plugin_start(const void* parameter
)
2132 enum plugin_status retval
;
2135 game_state
= ATTRACT_MODE
;
2138 rb
->lcd_set_backdrop(NULL
);
2140 /* universal font */
2141 rb
->lcd_setfont(FONT_SYSFIXED
);
2142 /* Turn off backlight timeout */
2143 backlight_force_on(); /* backlight control in lib/helper.c */
2145 retval
= start_game();
2147 rb
->lcd_setfont(FONT_UI
);
2148 /* Turn on backlight timeout (revert to settings) */
2149 backlight_use_settings(); /* backlight control in lib/helper.c */