Minor corrections to the .colours file editing; added .colours to the list of support...
[kugel-rb.git] / apps / plugins / spacerocks.c
blob0891906b126330feaa15991ebd11c44b4bc54699
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
22 #include "plugin.h"
23 #include "lib/helper.h"
25 PLUGIN_HEADER
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_HOME
139 #define AST_QUIT BUTTON_POWER
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 #else
271 #error No keymap defined!
272 #endif
274 #ifdef HAVE_TOUCHSCREEN
275 #ifndef AST_PAUSE
276 #define AST_PAUSE BUTTON_CENTER
277 #endif
278 #ifndef AST_QUIT
279 #define AST_QUIT BUTTON_TOPLEFT
280 #endif
281 #ifndef AST_THRUST_REP
282 #define AST_THRUST_REP (BUTTON_TOPMIDDLE | BUTTON_REPEAT)
283 #endif
284 #ifndef AST_THRUST
285 #define AST_THRUST BUTTON_TOPMIDDLE
286 #endif
287 #ifndef AST_HYPERSPACE
288 #define AST_HYPERSPACE BUTTON_TOPRIGHT
289 #endif
290 #ifndef AST_LEFT
291 #define AST_LEFT BUTTON_MIDLEFT
292 #endif
293 #ifndef AST_LEFT_REP
294 #define AST_LEFT_REP (BUTTON_MIDLEFT | BUTTON_REPEAT)
295 #endif
296 #ifndef AST_RIGHT
297 #define AST_RIGHT BUTTON_MIDRIGHT
298 #endif
299 #ifndef AST_RIGHT_REP
300 #define AST_RIGHT_REP (BUTTON_MIDRIGHT | BUTTON_REPEAT)
301 #endif
302 #ifndef AST_FIRE
303 #define AST_FIRE BUTTON_BOTTOMMIDDLE
304 #endif
305 #ifndef AST_FIRE_REP
306 #define AST_FIRE_REP (BUTTON_BOTTOMMIDDLE | BUTTON_MENU)
307 #endif
308 #endif
310 #define ABS(x) ((x)>0?(x):-(x))
312 #define RES MAX(LCD_WIDTH, LCD_HEIGHT)
313 #define LARGE_LCD RES >= 200
314 #define ENEMY_MISSILE_SURVIVAL_LENGTH RES/2
315 #define ASTEROID_SPEED RES/20
316 #define MISSILE_SURVIVAL_LENGTH 40
318 #define EXTRA_LIFE 250
319 #define SCALE 5000
320 #define MISSILE_SCALE 5000
321 #define WRAP_GAP 12
322 #define EXPLOSION_LENGTH 20
323 #define SHOW_COL 0
324 #define HISCORE_FILE PLUGIN_GAMES_DIR "/astrorocks.hs"
325 #define POINT_SIZE 2
326 #define MAX_NUM_ASTEROIDS 25
327 #define MAX_NUM_MISSILES 6
328 #define ENEMY_BIG_PROBABILITY_START 10
329 #define ENEMY_APPEAR_PROBABILITY_START 35
330 #define ENEMY_APPEAR_TIMING_START 1800
331 #define LITTLE_SHIP 2
332 #define BIG_SHIP 1
333 #define SHOW_GAME_OVER_TIME 100
334 #define SHOW_LEVEL_TIME 50
335 #define START_LIVES 3
336 #define START_LEVEL 1
337 #define NUM_ASTEROID_VERTICES 10
338 #define NUM_SHIP_VERTICES 4
339 #define NUM_ENEMY_VERTICES 6
340 #define MAX_LEVEL MAX_NUM_ASTEROIDS
341 #define ENEMY_SPEED 4
342 #define ENEMY_START_X 0
343 #define ENEMY_START_Y 0
344 #define SIZE_ENEMY_COLLISION 5*SCALE
345 #define ATTRACT_FLIP_TIME 100
346 #define NUM_STARS 50
347 #define NUM_TRAIL_POINTS 70
348 #define NUM_ROTATIONS 16
350 #define SIN_COS_SCALE 10000
352 #define FAST_ROT_CW_SIN 873
353 #define FAST_ROT_CW_COS 9963
354 #define FAST_ROT_ACW_SIN -873
355 #define FAST_ROT_ACW_COS 9963
357 #define MEDIUM_ROT_CW_SIN 350
358 #define MEDIUM_ROT_CW_COS 9994
359 #define MEDIUM_ROT_ACW_SIN -350
360 #define MEDIUM_ROT_ACW_COS 9994
362 #define SLOW_ROT_CW_SIN 350
363 #define SLOW_ROT_CW_COS 9994
364 #define SLOW_ROT_ACW_SIN - 350
365 #define SLOW_ROT_ACW_COS 9994
367 #ifdef HAVE_LCD_COLOR
368 #define SHIP_ROT_CW_SIN 2419
369 #define SHIP_ROT_CW_COS 9702
370 #define SHIP_ROT_ACW_SIN -2419
371 #define SHIP_ROT_ACW_COS 9702
372 #else
373 #define SHIP_ROT_CW_SIN 3827
374 #define SHIP_ROT_CW_COS 9239
375 #define SHIP_ROT_ACW_SIN -3827
376 #define SHIP_ROT_ACW_COS 9239
377 #endif
380 #define SCALED_WIDTH (LCD_WIDTH*SCALE)
381 #define SCALED_HEIGHT (LCD_HEIGHT*SCALE)
382 #define CENTER_LCD_X (LCD_WIDTH/2)
383 #define CENTER_LCD_Y (LCD_HEIGHT/2)
385 #define SHIP_EXPLOSION_COLOUR 1
386 #define ASTEROID_EXPLOSION_COLOUR 2
387 #define ENEMY_EXPLOSION_COLOUR 3
388 #define THRUST_COLOUR 4
390 #define ASTEROID_R 230
391 #define ASTEROID_G 200
392 #define ASTEROID_B 100
393 #define SHIP_R 255
394 #define SHIP_G 255
395 #define SHIP_B 255
396 #define ENEMY_R 50
397 #define ENEMY_G 220
398 #define ENEMY_B 50
399 #define THRUST_R 200
400 #define THRUST_G 200
401 #define THRUST_B 0
403 #ifdef HAVE_LCD_COLOR
404 #define COL_MISSILE LCD_RGBPACK(200,0,0)
405 #define COL_PLAYER LCD_RGBPACK(200,200,200)
406 #define COL_STARS LCD_WHITE
407 #define COL_ASTEROID LCD_RGBPACK(ASTEROID_R,ASTEROID_G,ASTEROID_B)
408 #define COL_TEXT LCD_RGBPACK(200,200,255)
409 #define COL_ENEMY LCD_RGBPACK(ENEMY_R,ENEMY_G,ENEMY_B)
410 #define SET_FG rb->lcd_set_foreground
411 #define SET_BG rb->lcd_set_background
412 #else
413 #define SET_FG(x)
414 #define SET_BG(x)
415 #endif
417 /* The array of points that make up an asteroid */
418 static const short asteroid_one[NUM_ASTEROID_VERTICES*2] =
420 -2, -12,
421 4, -8,
422 8, -14,
423 16, -5,
424 14, 0,
425 20, 2,
426 12, 14,
427 -4, 14,
428 -10, 6,
429 -10, -8
432 /* The array of points that make up an asteroid */
433 static const short asteroid_two[NUM_ASTEROID_VERTICES*2] =
435 -2, -12,
436 4, -16,
437 6, -14,
438 16, -8,
439 14, 0,
440 20, 2,
441 12, 14,
442 -4, 14,
443 -10, 6,
444 -10, -8
447 /* The array of points that make up an asteroid */
448 static const short asteroid_three[NUM_ASTEROID_VERTICES*2] =
450 -2, -12,
451 4, -16,
452 6, -14,
453 2, -8,
454 14, 0,
455 20, 2,
456 12, 14,
457 -4, 14,
458 -16, 6,
459 -10, -8
462 /* The array od points the make up the ship */
463 static const short ship_vertices[NUM_SHIP_VERTICES*2] =
465 #if(LARGE_LCD)
466 0,-6,
467 4, 6,
468 0, 2,
469 -4, 6
470 #else
471 0,-4,
472 3, 4,
473 0, 1,
474 -3, 4
475 #endif
478 /* The array of points the make up the bad spaceship */
479 static const short enemy_vertices[NUM_ENEMY_VERTICES*2] =
481 #if(LARGE_LCD)
482 -8, 0,
483 -4, 4,
484 4, 4,
485 8, 0,
486 4, -4,
487 -4, -4
488 #else
489 -5, 0,
490 -2, 2,
491 2, 2,
492 5, 0,
493 2, -2,
494 -2, -2
495 #endif
499 enum asteroid_type
501 #if(LARGE_LCD)
502 SMALL = 2,
503 MEDIUM = 4,
504 LARGE = 6,
505 #else
506 SMALL = 1,
507 MEDIUM = 2,
508 LARGE = 3,
509 #endif
513 enum game_state
515 GAME_OVER,
516 ATTRACT_MODE,
517 SHOW_LEVEL,
518 PLAY_MODE,
519 PAUSE_MODE
522 struct Point
524 int x;
525 int y;
526 int dx;
527 int dy;
530 struct TrailPoint
532 int alive;
533 struct Point position;
534 short r;
535 short g;
536 short b;
537 short dec;
540 /* Asteroid structure, contains an array of points */
541 struct Asteroid
543 enum asteroid_type type;
544 bool exists;
545 struct Point position;
546 struct Point vertices[NUM_ASTEROID_VERTICES];
547 int radius;
548 long speed_cos;
549 long speed_sin;
550 int explode_countdown;
553 struct Ship
555 struct Point vertices[NUM_SHIP_VERTICES];
556 struct Point position;
557 bool waiting_for_space;
558 int explode_countdown;
561 struct Enemy
563 struct Point vertices[NUM_ENEMY_VERTICES];
564 struct Point position;
565 int explode_countdown;
566 long last_time_appeared;
567 short size_probability;
568 short appear_probability;
569 short appear_timing;
572 struct Missile
574 struct Point position;
575 struct Point oldpoint;
576 int survived;
579 static enum game_state game_state;
580 static int asteroid_count;
581 static int next_missile_count;
582 static int next_thrust_count;
583 static int num_lives;
584 static int extra_life;
585 static int show_level_timeout;
586 static int attract_flip_timeout;
587 static int show_game_over;
588 static int current_level;
589 static int current_score;
590 static int high_score;
591 static int space_check_size = 30*SCALE;
593 static bool enemy_on_screen;
594 static char phscore[30];
595 static struct Ship ship;
596 static struct Point stars[NUM_STARS];
597 static struct Asteroid asteroids_array[MAX_NUM_ASTEROIDS];
598 static struct Missile missiles_array[MAX_NUM_MISSILES];
599 static struct Missile enemy_missile;
600 static struct Enemy enemy;
601 static struct Point lives_points[NUM_SHIP_VERTICES];
602 static struct TrailPoint trailPoints[NUM_TRAIL_POINTS];
604 void draw_and_move_asteroids(void);
605 void initialise_game(int nStartNum);
607 bool is_asteroid_near_ship(struct Asteroid* asteroid);
608 bool is_point_within_asteroid(struct Asteroid* asteroid, struct Point* point);
610 void initialise_asteroid(struct Asteroid* asteroid, enum asteroid_type eType);
611 void draw_polygon(struct Point* vertices, int px, int py, int num_vertices);
612 void rotate_asteroid(struct Asteroid* asteroid);
613 void create_asteroid(enum asteroid_type type, int x, int y);
614 void create_stars(void);
616 void initialise_ship(void);
617 void draw_and_move_ship(void);
618 void rotate_ship(int s, int c);
619 void thrust_ship(void);
621 void initialise_missile(struct Missile* missile);
622 void draw_and_move_missiles(void);
623 void fire_missile(void);
625 void animate_and_draw_explosion(struct Point* point, int num_points, int xoffset, int yoffset);
626 void initialise_explosion(struct Point* point, int num_points);
628 void move_point(struct Point* point);
629 void hyperspace(void);
630 void check_collisions(void);
631 void initialise_enemy(void);
632 void draw_and_move_enemy(void);
633 void draw_lives(void);
634 void drawstars(void);
635 bool is_ship_within_asteroid(struct Asteroid* asteroid);
639 /*Hi-Score reading and writing to file - this needs moving to the hi-score plugin lib as
640 a 3rd function */
641 void iohiscore(void)
643 int fd;
644 int compare;
646 /* clear the buffer we're about to load the highscore data into */
647 rb->memset(phscore, 0, sizeof(phscore));
649 fd = rb->open(HISCORE_FILE,O_RDWR | O_CREAT);
650 if(fd < 0)
652 rb->splash(HZ, "Highscore file read error");
653 return;
656 /* highscore used to %d, is now %d\n
657 Deal with no file or bad file */
658 rb->read(fd,phscore, sizeof(phscore));
660 compare = rb->atoi(phscore);
662 if(high_score > compare)
664 rb->lseek(fd,0,SEEK_SET);
665 rb->fdprintf(fd, "%d\n", high_score);
667 else
668 high_score = compare;
670 rb->close(fd);
673 bool point_in_poly(struct Point* _point, int num_vertices, int x, int y)
675 struct Point* pi;
676 struct Point* pj;
677 int n;
678 bool c = false;
680 pi = _point;
681 pj = _point;
682 pj += num_vertices-1;
684 n = num_vertices;
685 while(n--)
687 if((((pi->y <= y) && (y < pj->y)) || ((pj->y <= y) && (y < pi->y))) &&
688 (x < (pj->x - pi->x) * (y - pi->y) / (pj->y - pi->y) + pi->x))
689 c = !c;
691 if(n == num_vertices - 1)
692 pj = _point;
693 else
694 pj++;
696 pi++;
699 return c;
702 void move_point(struct Point* point)
704 point->x += point->dx;
705 point->y += point->dy;
707 /*check bounds on the x-axis:*/
708 if(point->x >= SCALED_WIDTH)
709 point->x = 0;
710 else if(point->x <= 0)
711 point->x = SCALED_WIDTH;
713 /*Check bounds on the y-axis:*/
714 if(point->y >= SCALED_HEIGHT)
715 point->y = 0;
716 else if(point->y <= 0)
717 point->y = SCALED_HEIGHT;
720 void create_trail(struct TrailPoint* tpoint)
722 tpoint->position.dx = -( ship.vertices[0].x - ship.vertices[2].x )/10;
723 tpoint->position.dy = -( ship.vertices[0].y - ship.vertices[2].y )/10;
726 void create_explosion_trail(struct TrailPoint* tpoint)
728 tpoint->position.dx = (rb->rand()%5050)-2500;
729 tpoint->position.dy = (rb->rand()%5050)-2500;
732 void create_trail_blaze(int colour, struct Point* position)
734 int numtoadd;
735 struct TrailPoint* tpoint;
736 int n;
737 int xadd,yadd;
738 if(colour != SHIP_EXPLOSION_COLOUR)
740 numtoadd = NUM_TRAIL_POINTS/5;
741 xadd = position->x;
742 yadd = position->y;
744 else
746 numtoadd = NUM_TRAIL_POINTS/8;
747 xadd = ship.position.x;
748 yadd = ship.position.y;
751 /* give the point a random countdown timer, so they dissapears at different times */
752 tpoint = trailPoints;
753 n = NUM_TRAIL_POINTS;
754 while(--n)
756 if(tpoint->alive <= 0 && numtoadd)
758 numtoadd--;
759 /* take a random x point anywhere between bottom two points of ship. */
760 /* ship.position.x; */
761 tpoint->position.x = (ship.vertices[2].x + (rb->rand()%18000)-9000) + position->x;
762 tpoint->position.y = (ship.vertices[2].y + (rb->rand()%18000)-9000) + position->y;
764 switch(colour)
766 case SHIP_EXPLOSION_COLOUR:
767 tpoint->r = 255;
768 tpoint->g = 255;
769 tpoint->b = 255;
770 create_explosion_trail(tpoint);
771 tpoint->alive = 510;
772 tpoint->dec = 2;
773 break;
774 case ASTEROID_EXPLOSION_COLOUR:
775 tpoint->r = ASTEROID_R;
776 tpoint->g = ASTEROID_G;
777 tpoint->b = ASTEROID_B;
778 create_explosion_trail(tpoint);
779 tpoint->alive = 510;
780 tpoint->dec = 2;
781 break;
782 case ENEMY_EXPLOSION_COLOUR:
783 tpoint->r = ENEMY_R;
784 tpoint->g = ENEMY_G;
785 tpoint->b = ENEMY_B;
786 create_explosion_trail(tpoint);
787 tpoint->alive = 510;
788 tpoint->dec = 2;
789 break;
790 case THRUST_COLOUR:
791 tpoint->r = THRUST_R;
792 tpoint->g = THRUST_G;
793 tpoint->b = THRUST_B;
794 create_trail(tpoint);
795 tpoint->alive = 175;
796 tpoint->dec = 4;
797 break;
799 /* add a proportional bit to the x and y based on dx and dy */
801 /* give the points a speed based on direction of travel - i.e. opposite */
802 tpoint->position.dx += position->dx;
803 tpoint->position.dy += position->dy;
807 tpoint++;
809 /* find a space in the array of trail_points that is NULL or DEAD or whatever.
810 and place this one here. */
814 void draw_trail_blaze(void)
816 struct TrailPoint* tpoint;
817 /* loop through, if alive then move and draw.
818 when drawn, countdown it's timer.
819 if zero kill it! */
820 tpoint = trailPoints;
821 int n = NUM_TRAIL_POINTS;
823 while(--n)
825 if(tpoint->alive)
827 if(game_state != PAUSE_MODE)
829 tpoint->alive-=10;
830 move_point(&(tpoint->position));
832 #ifdef HAVE_LCD_COLOR
833 /* intensity = tpoint->alive/2; */
834 if(tpoint->r>0)tpoint->r-=tpoint->dec;
835 if(tpoint->g>0)tpoint->g-=tpoint->dec;
836 if(tpoint->b>0)tpoint->b-=tpoint->dec;
837 SET_FG(LCD_RGBPACK(tpoint->r, tpoint->g, tpoint->b));
838 #endif
839 rb->lcd_drawpixel(tpoint->position.x/SCALE , tpoint->position.y/SCALE);
841 tpoint++;
845 /*Check if point is within a rectangle*/
846 bool is_point_within_rectangle(struct Point* rect, struct Point* p, int size)
848 #if SHOW_COL
849 int aTLx = rect->x - size;
850 int aTLy = rect->y - size;
851 int aBRx = rect->x + size;
852 int aBRy = rect->y + size;
853 rb->lcd_hline( aTLx/SCALE, aBRx/SCALE, aTLy/SCALE);
854 rb->lcd_vline( aTLx/SCALE, aTLy/SCALE, aBRy/SCALE);
855 rb->lcd_hline( aTLx/SCALE, aBRx/SCALE, aBRy/SCALE);
856 rb->lcd_vline( aBRx/SCALE, aBRy/SCALE, aTLy/SCALE);
857 return (p->x > aTLx && p->x < aBRx && p->y > aTLy && p->y < aBRy);
858 #else
859 return (p->x > rect->x - size && p->x < rect->x + size &&
860 p->y > rect->y - size && p->y < rect->y + size);
861 #endif
864 /* Draw polygon */
865 void draw_polygon(struct Point* vertices, int px, int py, int num_vertices)
867 int n, t1, t2, oldX, oldY;
868 struct Point *p;
869 bool bDrawAll = px < WRAP_GAP || LCD_WIDTH - px < WRAP_GAP ||
870 py < WRAP_GAP || LCD_HEIGHT - py < WRAP_GAP;
872 p = vertices;
873 p += num_vertices-1;
874 oldX = p->x/SCALE + px;
875 oldY = p->y/SCALE + py;
876 p = vertices;
877 for(n = num_vertices+1; --n;)
879 t1 = p->x/SCALE + px;
880 t2 = p->y/SCALE + py;
882 rb->lcd_drawline(oldX, oldY, t1, t2);
884 if(bDrawAll)
886 rb->lcd_drawline(oldX - LCD_WIDTH, oldY, t1 - LCD_WIDTH, t2);
887 rb->lcd_drawline(oldX + LCD_WIDTH, oldY, t1 + LCD_WIDTH, t2);
888 rb->lcd_drawline(oldX - LCD_WIDTH, oldY + LCD_HEIGHT,
889 t1 - LCD_WIDTH, t2 + LCD_HEIGHT);
890 rb->lcd_drawline(oldX + LCD_WIDTH, oldY + LCD_HEIGHT,
891 t1 + LCD_WIDTH, t2 + LCD_HEIGHT);
893 rb->lcd_drawline(oldX, oldY - LCD_HEIGHT, t1, t2 - LCD_HEIGHT);
894 rb->lcd_drawline(oldX, oldY + LCD_HEIGHT, t1, t2 + LCD_HEIGHT);
895 rb->lcd_drawline(oldX - LCD_WIDTH, oldY - LCD_HEIGHT,
896 t1 - LCD_WIDTH, t2 - LCD_HEIGHT);
897 rb->lcd_drawline(oldX + LCD_WIDTH, oldY - LCD_HEIGHT,
898 t1 + LCD_WIDTH, t2 - LCD_HEIGHT);
900 oldX = t1;
901 oldY = t2;
902 p++;
906 void animate_and_draw_explosion(struct Point* point, int num_points,
907 int xoffset, int yoffset)
909 int n;
910 for(n = num_points; --n;)
912 if(game_state != PAUSE_MODE)
914 point->x += point->dx;
915 point->y += point->dy;
917 rb->lcd_fillrect( point->x/SCALE + xoffset, point->y/SCALE + yoffset,
918 POINT_SIZE, POINT_SIZE);
919 point++;
923 /*stop movement of ship, 'cos that's what happens when you go into hyperspace.*/
924 void hyperspace(void)
926 ship.position.dx = ship.position.dy = 0;
927 ship.position.x = (rb->rand()%SCALED_WIDTH);
928 ship.position.y = (rb->rand()%SCALED_HEIGHT);
931 void initialise_enemy(void)
933 struct Point* point;
934 int n;
935 int size;
937 if(rb->rand()%100 > enemy.size_probability)
939 size = BIG_SHIP;
940 enemy.size_probability++;
941 if(enemy.size_probability < 90)
943 enemy.size_probability = ENEMY_BIG_PROBABILITY_START;
946 else
948 size = LITTLE_SHIP;
951 enemy_missile.survived = 0;
952 enemy_on_screen = true;
953 enemy.explode_countdown = 0;
954 enemy.last_time_appeared = *rb->current_tick;
955 point = enemy.vertices;
956 for(n = 0; n < NUM_ENEMY_VERTICES+NUM_ENEMY_VERTICES; n+=2)
958 point->x = enemy_vertices[n];
959 point->y = enemy_vertices[n+1];
960 point->x *= SCALE/size;
961 point->y *= SCALE/size;
962 point++;
965 if(ship.position.x >= SCALED_WIDTH/2)
967 enemy.position.dx = ENEMY_SPEED;
968 enemy.position.x = 0;
970 else
972 enemy.position.dx = -ENEMY_SPEED;
973 enemy.position.x = SCALED_WIDTH;
976 if(ship.position.y >= SCALED_HEIGHT/2)
978 enemy.position.dy = ENEMY_SPEED;
979 enemy.position.y = 0;
981 else
983 enemy.position.dy = -ENEMY_SPEED;
984 enemy.position.y = SCALED_HEIGHT;
987 enemy.position.dx *= SCALE/10;
988 enemy.position.dy *= SCALE/10;
991 void draw_and_move_enemy(void)
993 int enemy_x, enemy_y;
994 struct Point *point;
996 SET_FG(COL_ENEMY);
998 if(enemy_on_screen)
1000 enemy_x = enemy.position.x/SCALE;
1001 enemy_y = enemy.position.y/SCALE;
1002 if(!enemy.explode_countdown)
1004 point = enemy.vertices;
1005 draw_polygon(enemy.vertices, enemy_x, enemy_y, NUM_ENEMY_VERTICES);
1006 rb->lcd_drawline(enemy.vertices[0].x/SCALE + enemy_x,
1007 enemy.vertices[0].y/SCALE + enemy_y,
1008 enemy.vertices[3].x/SCALE + enemy_x,
1009 enemy.vertices[3].y/SCALE + enemy_y);
1011 if(game_state != PAUSE_MODE)
1013 enemy.position.x += enemy.position.dx;
1014 enemy.position.y += enemy.position.dy;
1017 if(enemy.position.x > SCALED_WIDTH || enemy.position.x < 0)
1018 enemy_on_screen = false;
1020 if(enemy.position.y > SCALED_HEIGHT)
1021 enemy.position.y = 0;
1022 else if(enemy.position.y < 0)
1023 enemy.position.y = SCALED_HEIGHT;
1025 if( (rb->rand()%1000) < 10)
1026 enemy.position.dy = -enemy.position.dy;
1028 else
1031 /* animate_and_draw_explosion(enemy.vertices, NUM_ENEMY_VERTICES,
1032 enemy_x, enemy.position.y/SCALE); */
1033 if(game_state != PAUSE_MODE)
1035 enemy.explode_countdown--;
1036 if(!enemy.explode_countdown)
1037 enemy_on_screen = false;
1041 else
1043 if( (*rb->current_tick - enemy.last_time_appeared) > enemy.appear_timing)
1044 if(rb->rand()%100 > enemy.appear_probability) initialise_enemy();
1047 if(!enemy_missile.survived && game_state != GAME_OVER)
1049 /*if no missile and the enemy is here and not exploding..then shoot baby!*/
1050 if( !enemy.explode_countdown && enemy_on_screen &&
1051 !ship.waiting_for_space && (rb->rand()%10) > 5 )
1053 enemy_missile.position.x = enemy.position.x;
1054 enemy_missile.position.y = enemy.position.y;
1056 /*lame, needs to be sorted - it's trying to shoot at the ship*/
1057 if(ABS(enemy.position.y - ship.position.y) <= 5*SCALE)
1059 enemy_missile.position.dy = 0;
1061 else
1063 if( enemy.position.y < ship.position.y)
1064 enemy_missile.position.dy = 1;
1065 else
1066 enemy_missile.position.dy = -1;
1069 if(ABS(enemy.position.x - ship.position.x) <= 5*SCALE)
1070 enemy_missile.position.dx = 0;
1071 else
1073 if( enemy.position.x < ship.position.x)
1074 enemy_missile.position.dx = 1;
1075 else
1076 enemy_missile.position.dx = -1;
1079 if(enemy_missile.position.dx == 0 &&
1080 enemy_missile.position.dy == 0)
1081 enemy_missile.position.dx = enemy_missile.position.dy = -1;
1083 enemy_missile.position.dx *= SCALE;
1084 enemy_missile.position.dy *= SCALE;
1085 enemy_missile.survived = ENEMY_MISSILE_SURVIVAL_LENGTH;
1089 else
1091 rb->lcd_fillrect( enemy_missile.position.x/SCALE,
1092 enemy_missile.position.y/SCALE,
1093 POINT_SIZE, POINT_SIZE);
1094 if(game_state != PAUSE_MODE)
1096 move_point(&enemy_missile.position);
1097 enemy_missile.survived--;
1102 /******************
1103 * Lame method of collision
1104 * detection. It's checking for collision
1105 * between point and a big rectangle around the asteroid...
1106 *******************/
1107 bool is_point_within_asteroid(struct Asteroid* asteroid, struct Point* point)
1109 if( !is_point_within_rectangle(&asteroid->position, point,
1110 asteroid->radius+4*SCALE) )
1111 return false;
1113 if(point_in_poly(asteroid->vertices, NUM_ASTEROID_VERTICES,
1114 point->x - asteroid->position.x,
1115 point->y - asteroid->position.y))
1117 switch(asteroid->type)
1119 case(SMALL):
1120 asteroid->explode_countdown = EXPLOSION_LENGTH;
1121 create_trail_blaze(ASTEROID_EXPLOSION_COLOUR, &asteroid->position);
1122 break;
1124 case(LARGE):
1125 create_asteroid(MEDIUM, asteroid->position.x,
1126 asteroid->position.y);
1127 create_asteroid(MEDIUM, asteroid->position.x,
1128 asteroid->position.y);
1129 break;
1131 case(MEDIUM):
1132 create_asteroid(SMALL, asteroid->position.x, asteroid->position.y);
1133 create_asteroid(SMALL, asteroid->position.x, asteroid->position.y);
1134 break;
1137 current_score++;
1138 if(current_score > extra_life)
1140 num_lives++;
1141 extra_life = current_score+EXTRA_LIFE;
1143 asteroid_count--;
1144 asteroid->exists = false;
1145 return true;
1147 else
1148 return false;
1151 bool is_point_within_enemy(struct Point* point)
1153 if( is_point_within_rectangle(&enemy.position, point, 7*SCALE) )
1155 current_score += 5;
1156 /*enemy_missile.survived = 0;*/
1157 enemy.explode_countdown = EXPLOSION_LENGTH;
1158 /* initialise_explosion(enemy.vertices, NUM_ENEMY_VERTICES); */
1159 create_trail_blaze(ENEMY_EXPLOSION_COLOUR, &enemy.position);
1160 return true;
1162 else
1163 return false;
1166 bool is_ship_within_asteroid(struct Asteroid* asteroid)
1168 bool hit = false;
1169 struct Point p;
1171 p.x = ship.position.x + ship.vertices[0].x;
1172 p.y = ship.position.y + ship.vertices[0].y;
1173 hit |= is_point_within_asteroid(asteroid, &p);
1175 if(!hit)
1177 p.x = ship.position.x + ship.vertices[1].x;
1178 p.y = ship.position.y + ship.vertices[1].y;
1179 hit |= is_point_within_asteroid(asteroid, &p);
1180 if(!hit)
1182 p.x = ship.position.x + ship.vertices[3].x;
1183 p.y = ship.position.y + ship.vertices[3].y;
1184 hit |= is_point_within_asteroid(asteroid, &p);
1188 return hit;
1191 void initialise_explosion(struct Point* point, int num_points)
1193 int n;
1195 point->x += point->dx;
1196 point->y += point->dy;
1197 for(n = num_points; --n;)
1199 point->dx = point->x;
1200 point->dy = point->y;
1201 point++;
1206 /* Check for collsions between the missiles and the asteroids and the ship */
1207 void check_collisions(void)
1209 int m, n;
1210 bool asteroids_onscreen = false;
1211 struct Missile* missile;
1212 struct Asteroid* asteroid;
1213 bool ship_cant_be_placed = false;
1215 asteroid = asteroids_array;
1216 m = MAX_NUM_ASTEROIDS;
1217 while(--m)
1219 /*if the asteroids exists then test missile collision:*/
1220 if(asteroid->exists)
1222 missile = missiles_array;
1223 n = MAX_NUM_MISSILES;
1224 while(--n)
1226 /*if the missiles exists:*/
1227 if(missile->survived > 0)
1229 /*has the missile hit the asteroid?*/
1230 if(is_point_within_asteroid(asteroid, &missile->position)
1231 || is_point_within_asteroid(asteroid,
1232 &missile->oldpoint))
1234 missile->survived = 0;
1235 break;
1238 missile++;
1241 /*now check collision with ship:*/
1242 if(asteroid->exists && !ship.waiting_for_space && !ship.explode_countdown)
1244 if(is_ship_within_asteroid(asteroid))
1246 /*blow up ship*/
1247 ship.explode_countdown = EXPLOSION_LENGTH;
1248 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1249 create_trail_blaze(SHIP_EXPLOSION_COLOUR, &ship.position);
1252 /*has the enemy missile blown something up?*/
1253 if(asteroid->exists && enemy_missile.survived)
1255 if(is_point_within_asteroid(asteroid, &enemy_missile.position))
1257 /*take that score back then:*/
1258 if(current_score > 0) current_score--;
1259 enemy_missile.survived = 0;
1262 /*if it still exists, check if ship is waiting for space:*/
1263 if(asteroid->exists && ship.waiting_for_space)
1264 ship_cant_be_placed |=
1265 is_point_within_rectangle(&ship.position,
1266 &asteroid->position,
1267 space_check_size);
1271 /*is an asteroid still exploding?*/
1272 if(asteroid->explode_countdown)
1273 asteroids_onscreen = true;
1275 asteroid++;
1278 /*now check collision between ship and enemy*/
1279 if(enemy_on_screen && !ship.waiting_for_space &&
1280 !ship.explode_countdown && !enemy.explode_countdown)
1282 /*has the enemy collided with the ship?*/
1283 if(is_point_within_enemy(&ship.position))
1285 ship.explode_countdown = EXPLOSION_LENGTH;
1286 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1287 create_trail_blaze(SHIP_EXPLOSION_COLOUR, &ship.position);
1288 create_trail_blaze(ENEMY_EXPLOSION_COLOUR, &enemy.position);
1291 /*Now see if the enemy has been shot at by the ships missiles:*/
1292 missile = missiles_array;
1293 n = MAX_NUM_MISSILES;
1294 while(--n)
1296 if(missile->survived > 0 &&
1297 is_point_within_enemy(&missile->position))
1299 missile->survived = 0;
1300 break;
1302 missile++;
1306 /*test collision with enemy missile and ship:*/
1307 if(!ship_cant_be_placed && enemy_missile.survived > 0 &&
1308 point_in_poly(ship.vertices, NUM_SHIP_VERTICES,
1309 enemy_missile.position.x - ship.position.x,
1310 enemy_missile.position.y - ship.position.y))
1312 ship.explode_countdown = EXPLOSION_LENGTH;
1313 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1314 create_trail_blaze(SHIP_EXPLOSION_COLOUR, &ship.position);
1315 enemy_missile.survived = 0;
1316 enemy_missile.position.x = enemy_missile.position.y = 0;
1319 if(!ship_cant_be_placed)
1320 ship.waiting_for_space = false;
1322 /*if all asteroids cleared then start again:*/
1323 if(asteroid_count == 0 && !enemy_on_screen && !asteroids_onscreen)
1325 current_level++;
1326 game_state = SHOW_LEVEL;
1327 enemy.appear_probability += 5;
1328 enemy.appear_timing -= 200;
1329 if( enemy.appear_probability > 100)
1330 enemy.appear_probability = ENEMY_APPEAR_PROBABILITY_START;
1331 show_level_timeout = SHOW_LEVEL_TIME;
1335 /*************************************************
1336 ** Creates a new asteroid of the given 4type (size)
1337 ** and at the given location.
1338 *************************************************/
1339 void create_asteroid(enum asteroid_type type, int x, int y)
1341 struct Asteroid* asteroid;
1342 int n;
1344 asteroid = asteroids_array;
1345 n = MAX_NUM_ASTEROIDS;
1346 while(--n)
1348 if(!asteroid->exists && !asteroid->explode_countdown)
1350 initialise_asteroid(asteroid, type);
1351 asteroid->position.x = x;
1352 asteroid->position.y = y;
1353 break;
1355 asteroid++;
1359 /* Initialise a missile */
1360 void initialise_missile(struct Missile* missile)
1362 missile->position.x = ship.position.x + ship.vertices[0].x;
1363 missile->position.y = ship.position.y + ship.vertices[0].y;
1364 missile->position.dx = (ship.vertices[0].x - ship.vertices[2].x)/2;
1365 missile->position.dy = (ship.vertices[0].y - ship.vertices[2].y)/2;
1366 missile->survived = MISSILE_SURVIVAL_LENGTH;
1367 missile->oldpoint.x = missile->position.x;
1368 missile->oldpoint.y = missile->position.y;
1371 /* Draw and Move all the missiles */
1372 void draw_and_move_missiles(void)
1374 int n;
1375 int p1x, p1y;
1376 int p2x, p2y;
1378 struct Missile* missile;
1379 missile = missiles_array;
1381 SET_FG(COL_MISSILE);
1383 n = MAX_NUM_MISSILES;
1384 while(--n)
1386 if(missile->survived)
1388 if(missile->position.dx > 0)
1390 if(missile->position.x >= missile->oldpoint.x)
1392 p1x = missile->oldpoint.x;
1393 p2x = missile->position.x;
1395 else
1397 p1x = 0;
1398 p2x = missile->position.x;
1401 else
1403 if(missile->oldpoint.x >= missile->position.x)
1405 p1x = missile->oldpoint.x;
1406 p2x = missile->position.x;
1408 else
1410 p1x = missile->oldpoint.x;
1411 p2x = LCD_WIDTH;
1415 if(missile->position.dy > 0)
1417 if(missile->position.y >= missile->oldpoint.y)
1419 p1y = missile->oldpoint.y;
1420 p2y = missile->position.y;
1422 else
1424 p1y = 0;
1425 p2y = missile->position.y;
1428 else
1430 if(missile->oldpoint.y >= missile->position.y)
1432 p1y = missile->oldpoint.y;
1433 p2y = missile->position.y;
1435 else
1437 p1y = missile->oldpoint.y;
1438 p2y = LCD_HEIGHT;
1442 rb->lcd_drawline( p1x/SCALE, p1y/SCALE, p2x/SCALE, p2y/SCALE);
1444 if(game_state != PAUSE_MODE)
1446 missile->oldpoint.x = missile->position.x;
1447 missile->oldpoint.y = missile->position.y;
1448 move_point(&missile->position);
1449 missile->survived--;
1452 missile++;
1456 void draw_lives(void)
1458 int n;
1459 int px = (LCD_WIDTH - num_lives*4 - 1);
1460 #if(LARGE_LCD)
1461 int py = (LCD_HEIGHT-6);
1462 #else
1463 int py = (LCD_HEIGHT-4);
1464 #endif
1466 SET_FG(COL_PLAYER);
1468 n = num_lives;
1469 while(--n)
1471 draw_polygon(lives_points, px, py, NUM_SHIP_VERTICES);
1472 #if(LARGE_LCD)
1473 px += 8;
1474 #else
1475 px += 6;
1476 #endif
1480 /*Fire the next missile*/
1481 void fire_missile(void)
1483 int n;
1484 struct Missile* missile;
1486 if(!ship.explode_countdown && !ship.waiting_for_space)
1488 missile = missiles_array;
1489 n = MAX_NUM_MISSILES;
1490 while(--n)
1492 if(!missile->survived)
1494 initialise_missile(missile);
1495 break;
1497 missile++;
1502 /* Initialise the passed Asteroid */
1503 void initialise_asteroid(struct Asteroid* asteroid, enum asteroid_type type)
1505 int n;
1506 bool b,b2;
1507 struct Point* point;
1508 asteroid->exists = true;
1509 asteroid->type = type;
1510 asteroid->explode_countdown = 0;
1512 /*Set the radius of the asteroid:*/
1513 asteroid->radius = (int)type*SCALE;
1515 /*shall we move Clockwise and Fast*/
1516 if((rb->rand()%100)>75)
1518 asteroid->speed_cos = FAST_ROT_CW_COS;
1519 asteroid->speed_sin = FAST_ROT_CW_SIN;
1521 else if((rb->rand()%100)>75)
1523 asteroid->speed_cos = FAST_ROT_ACW_COS;
1524 asteroid->speed_sin = FAST_ROT_ACW_SIN;
1526 else if((rb->rand()%100)>75)
1528 asteroid->speed_cos = SLOW_ROT_ACW_COS;
1529 asteroid->speed_sin = SLOW_ROT_ACW_SIN;
1531 else
1533 asteroid->speed_cos = SLOW_ROT_CW_COS;
1534 asteroid->speed_sin = SLOW_ROT_CW_SIN;
1537 b = (rb->rand()%100)>66;
1538 b2 = (rb->rand()%100)>66;
1539 point = asteroid->vertices;
1540 for(n = 0; n < NUM_ASTEROID_VERTICES*2; n+=2)
1542 if(b)
1544 point->x = asteroid_one[n];
1545 point->y = asteroid_one[n+1];
1547 else if( b2 )
1549 point->x = asteroid_two[n];
1550 point->y = asteroid_two[n+1];
1552 else
1554 point->x = asteroid_three[n];
1555 point->y = asteroid_three[n+1];
1558 point->x *= asteroid->radius/6;
1559 point->y *= asteroid->radius/6;
1560 point++;
1564 asteroid->radius += 6*SCALE;
1565 if(asteroid->type == SMALL)
1566 asteroid->radius /= 3;/*2*/
1567 else if(asteroid->type == LARGE)
1568 asteroid->radius += 3*SCALE;/*2*/
1569 b = true;
1570 while(b)
1572 /*Set the position randomly:*/
1573 asteroid->position.x = (rb->rand()%SCALED_WIDTH);
1574 asteroid->position.y = (rb->rand()%SCALED_HEIGHT);
1576 asteroid->position.dx = 0;
1577 while(asteroid->position.dx == 0)
1578 asteroid->position.dx = (rb->rand()%ASTEROID_SPEED)-ASTEROID_SPEED/2;
1580 asteroid->position.dy = 0;
1581 while(asteroid->position.dy == 0)
1582 asteroid->position.dy = (rb->rand()%ASTEROID_SPEED)-ASTEROID_SPEED/2;
1584 asteroid->position.dx *= SCALE/10;
1585 asteroid->position.dy *= SCALE/10;
1587 b = is_point_within_rectangle(&ship.position, &asteroid->position,
1588 space_check_size);
1591 /*Now rotate the asteroid a bit, so they all look a bit different*/
1592 for(n=(rb->rand()%30) + 2;--n;)
1593 rotate_asteroid(asteroid);
1595 /*great, we've created an asteroid, don't forget to increment the total:*/
1596 asteroid_count++;
1599 /*Initialise the ship*/
1600 void initialise_ship(void)
1602 struct Point* point;
1603 struct Point* lives_point;
1604 int n;
1606 ship.position.x = CENTER_LCD_X;
1607 ship.position.y = CENTER_LCD_Y;
1608 ship.position.x *= SCALE;
1609 ship.position.y *= SCALE;
1610 ship.position.dx = ship.position.dy = 0;
1612 point = ship.vertices;
1613 lives_point = lives_points;
1614 for(n = 0; n < NUM_SHIP_VERTICES*2; n+=2)
1616 point->x = ship_vertices[n];
1617 point->y = ship_vertices[n+1];
1618 point->x *= SCALE;
1619 point->y *= SCALE;
1620 point++;
1621 lives_point++;
1624 ship.position.dx = 0;
1625 ship.position.dy = 0;
1626 ship.explode_countdown = 0;
1628 /*grab a copy of the ships points for the lives display:*/
1629 point = ship.vertices;
1630 lives_point = lives_points;
1631 for(n = 0; n < NUM_SHIP_VERTICES*2; n+=2)
1633 lives_point->x = point->x;
1634 lives_point->y = point->y;
1635 lives_point++;
1636 point++;
1640 void rotate_asteroid(struct Asteroid* asteroid)
1642 struct Point* point;
1643 int n;
1644 long xtemp;
1646 point = asteroid->vertices;
1647 for(n = NUM_ASTEROID_VERTICES+1; --n;)
1649 xtemp = point->x;
1650 point->x = xtemp*asteroid->speed_cos/SIN_COS_SCALE -
1651 point->y*asteroid->speed_sin/SIN_COS_SCALE;
1652 point->y = point->y*asteroid->speed_cos/SIN_COS_SCALE +
1653 xtemp*asteroid->speed_sin/SIN_COS_SCALE;
1654 point++;
1658 /*************************************************
1659 ** Draws the ship, moves the ship and creates a new
1660 ** one if it's finished exploding.
1661 **************************************************/
1662 void draw_and_move_ship(void)
1664 int nxoffset = ship.position.x/SCALE;
1665 int nyoffset = ship.position.y/SCALE;
1666 SET_FG(COL_PLAYER);
1667 if(!ship.explode_countdown)
1669 if(!ship.waiting_for_space)
1671 draw_polygon(ship.vertices, nxoffset, nyoffset, NUM_SHIP_VERTICES);
1672 if(game_state != PAUSE_MODE && game_state != GAME_OVER)
1674 move_point(&ship.position);
1678 else
1680 /* animate_and_draw_explosion(ship.vertices, NUM_SHIP_VERTICES,
1681 ship.position.x/SCALE,
1682 ship.position.y/SCALE); */
1683 if(game_state != PAUSE_MODE)
1685 ship.explode_countdown--;
1686 if(!ship.explode_countdown)
1688 num_lives--;
1689 if(!num_lives)
1691 show_game_over = SHOW_GAME_OVER_TIME;
1692 game_state = GAME_OVER;
1694 else
1696 initialise_ship();
1697 ship.waiting_for_space = true;
1704 void thrust_ship(void)
1706 if(!ship.waiting_for_space)
1708 ship.position.dx += ( ship.vertices[0].x - ship.vertices[2].x )/20;
1709 ship.position.dy += ( ship.vertices[0].y - ship.vertices[2].y )/20;
1710 /*if dx and dy are below a certain threshold, then set 'em to 0
1711 but to do this we need to ascertain if the spacehip as moved on screen
1712 for more than a certain amount. */
1714 create_trail_blaze(THRUST_COLOUR, &ship.position);
1718 /**************************************************
1719 ** Rotate the ship using the passed sin & cos values
1720 ***************************************************/
1721 void rotate_ship(int c, int s)
1723 struct Point* point;
1724 int n;
1725 double xtemp;
1727 if(!ship.waiting_for_space && !ship.explode_countdown)
1729 point = ship.vertices;
1730 for(n=NUM_SHIP_VERTICES+1;--n;)
1732 xtemp = point->x;
1733 point->x = xtemp*c/SIN_COS_SCALE - point->y*s/SIN_COS_SCALE;
1734 point->y = point->y*c/SIN_COS_SCALE + xtemp*s/SIN_COS_SCALE;
1735 point++;
1740 void drawstars()
1742 struct Point* p;
1743 int n = NUM_STARS;
1745 p = stars;
1746 SET_FG(COL_STARS);
1748 while(--n)
1750 rb->lcd_drawpixel(p->x , p->y);
1751 p++;
1755 /*************************************************
1756 ** Draw And Move all Asteroids
1757 *************************************************/
1758 void draw_and_move_asteroids(void)
1760 int n;
1761 struct Asteroid* asteroid;
1763 asteroid = asteroids_array;
1764 SET_FG(COL_ASTEROID);
1766 n = MAX_NUM_ASTEROIDS;
1767 while(--n)
1769 if(game_state != PAUSE_MODE)
1771 if(asteroid->exists)
1773 move_point(&asteroid->position);
1774 rotate_asteroid(asteroid);
1775 draw_polygon(asteroid->vertices, asteroid->position.x/SCALE,
1776 asteroid->position.y/SCALE,
1777 NUM_ASTEROID_VERTICES);
1779 else if(asteroid->explode_countdown)
1781 /* animate_and_draw_explosion(asteroid->vertices,
1782 NUM_ASTEROID_VERTICES,
1783 asteroid->position.x/SCALE,
1784 asteroid->position.y/SCALE); */
1785 asteroid->explode_countdown--;
1788 else
1790 if(asteroid->exists)
1791 draw_polygon(asteroid->vertices,
1792 asteroid->position.x/SCALE,
1793 asteroid->position.y/SCALE,
1794 NUM_ASTEROID_VERTICES);
1796 asteroid++;
1800 void create_stars(void)
1802 struct TrailPoint* tpoint;
1803 struct Point* p;
1804 int n;
1806 p = stars;
1807 n = NUM_STARS;
1808 while(--n)
1810 p->x = (rb->rand()%LCD_WIDTH);
1811 p->y = (rb->rand()%LCD_HEIGHT);
1812 p++;
1816 /* give the point a random countdown timer, so they dissapears at different
1817 times */
1818 tpoint = trailPoints;
1819 n = NUM_TRAIL_POINTS;
1820 while(--n)
1822 tpoint->alive = 0;
1823 tpoint++;
1827 /*************************************************
1828 ** Creates start_num number of new asteroids of
1829 ** full size.
1830 **************************************************/
1831 void initialise_game(int start_num)
1833 int n;
1834 asteroid_count = next_missile_count = next_thrust_count = 0;
1835 struct Asteroid* asteroid;
1836 struct Missile* missile;
1837 extra_life = EXTRA_LIFE;
1839 /*no enemy*/
1840 enemy_on_screen = 0;
1841 enemy_missile.survived = 0;
1843 /*clear asteroids*/
1844 asteroid = asteroids_array;
1845 n = MAX_NUM_ASTEROIDS;
1846 while(--n)
1848 asteroid->exists = false;
1849 asteroid++;
1852 /*make some LARGE asteroids*/
1853 for(n = 0; n < start_num; n++)
1854 initialise_asteroid(&asteroids_array[n], LARGE);
1856 /*ensure all missiles are out of action: */
1857 missile = missiles_array;
1858 n = MAX_NUM_MISSILES;
1859 while(--n)
1861 missile->survived=0;
1862 missile++;
1866 void start_attract_mode(void)
1868 enemy.appear_probability = ENEMY_APPEAR_PROBABILITY_START;
1869 enemy.appear_timing = ENEMY_APPEAR_TIMING_START;
1870 current_level = 5;
1871 num_lives = START_LIVES;
1872 current_score = 0;
1873 attract_flip_timeout = ATTRACT_FLIP_TIME;
1874 game_state = ATTRACT_MODE;
1875 if(asteroid_count < 3)
1876 initialise_game(current_level);
1879 enum plugin_status start_game(void)
1881 char s[20];
1882 char level[10];
1883 int button;
1884 int end;
1885 int CYCLETIME = 30;
1887 /*create stars once, and once only:*/
1888 create_stars();
1890 SET_BG(LCD_BLACK);
1892 while(true)
1894 /*game starts with at level 1
1895 with 1 asteroid.*/
1896 start_attract_mode();
1898 /*Main loop*/
1899 while(true)
1901 end = *rb->current_tick + (CYCLETIME * HZ) / 1000;
1902 rb->lcd_clear_display();
1903 SET_FG(COL_TEXT);
1904 switch(game_state)
1906 case(ATTRACT_MODE):
1907 if(attract_flip_timeout < ATTRACT_FLIP_TIME/2)
1909 rb->lcd_putsxy(CENTER_LCD_X - 39,
1910 CENTER_LCD_Y + CENTER_LCD_Y/2 - 4,
1911 "Fire to Start");
1912 if(!attract_flip_timeout)
1913 attract_flip_timeout = ATTRACT_FLIP_TIME;
1915 else
1917 rb->snprintf(s, sizeof(s), "Hi Score %d ", high_score);
1918 rb->lcd_putsxy(CENTER_LCD_X - 30,
1919 CENTER_LCD_Y + CENTER_LCD_Y/2 - 4, s);
1921 attract_flip_timeout--;
1922 break;
1924 case(GAME_OVER):
1925 rb->lcd_putsxy(CENTER_LCD_X - 25,
1926 CENTER_LCD_Y + CENTER_LCD_Y/2 - 4, "Game Over");
1927 rb->snprintf(s, sizeof(s), "score %d ", current_score);
1928 rb->lcd_putsxy(1,LCD_HEIGHT-8, s);
1929 show_game_over--;
1930 if(!show_game_over)
1931 start_attract_mode();
1932 break;
1934 case(PAUSE_MODE):
1935 rb->snprintf(s, sizeof(s), "score %d ", current_score);
1936 rb->lcd_putsxy(1,LCD_HEIGHT-8, s);
1937 rb->lcd_putsxy(CENTER_LCD_X - 15,
1938 CENTER_LCD_Y + CENTER_LCD_Y/2 - 4, "pause");
1939 draw_and_move_missiles();
1940 draw_lives();
1941 draw_and_move_ship();
1942 break;
1944 case(PLAY_MODE):
1945 rb->snprintf(s, sizeof(s), "score %d ", current_score);
1946 rb->lcd_putsxy(1,LCD_HEIGHT-8, s);
1947 draw_and_move_missiles();
1948 draw_lives();
1949 check_collisions();
1950 draw_and_move_ship();
1951 break;
1953 case(SHOW_LEVEL):
1954 show_level_timeout--;
1955 rb->snprintf(s, sizeof(s), "score %d ", current_score);
1956 rb->lcd_putsxy(1,LCD_HEIGHT-8, s);
1957 rb->snprintf(level, sizeof(level), "stage %d ", current_level);
1958 rb->lcd_putsxy(CENTER_LCD_X - 20,
1959 CENTER_LCD_Y + CENTER_LCD_Y/2 - 4, level);
1960 draw_and_move_ship();
1961 draw_lives();
1962 if(!show_level_timeout)
1964 initialise_game(current_level);
1965 game_state = PLAY_MODE;
1966 draw_lives();
1968 break;
1970 draw_trail_blaze();
1971 drawstars();
1972 draw_and_move_asteroids();
1973 draw_and_move_enemy();
1975 rb->lcd_update();
1976 button = rb->button_get(false);
1978 #ifdef HAS_BUTTON_HOLD
1979 if (rb->button_hold())
1980 game_state = PAUSE_MODE;
1981 #endif
1983 switch(button)
1985 case(AST_PAUSE):
1986 if(game_state == PLAY_MODE)
1987 game_state = PAUSE_MODE;
1988 else if(game_state == PAUSE_MODE)
1989 game_state = PLAY_MODE;
1990 break;
1992 #ifdef AST_RC_QUIT
1993 case AST_RC_QUIT:
1994 #endif
1995 case(AST_QUIT):
1996 if(game_state == ATTRACT_MODE)
1997 return PLUGIN_OK;
1998 else if(game_state == GAME_OVER)
2000 start_attract_mode();
2002 else
2004 show_game_over = SHOW_GAME_OVER_TIME;
2005 game_state = GAME_OVER;
2007 break;
2009 case (AST_LEFT_REP):
2010 case (AST_LEFT):
2011 if(game_state == PLAY_MODE || game_state == SHOW_LEVEL)
2012 rotate_ship(SHIP_ROT_ACW_COS, SHIP_ROT_ACW_SIN);
2013 break;
2015 case (AST_RIGHT_REP):
2016 case (AST_RIGHT):
2017 if(game_state == PLAY_MODE || game_state == SHOW_LEVEL)
2018 rotate_ship(SHIP_ROT_CW_COS, SHIP_ROT_CW_SIN);
2019 break;
2021 case (AST_THRUST_REP):
2022 case (AST_THRUST):
2023 if((game_state == PLAY_MODE || game_state == SHOW_LEVEL) && !next_thrust_count)
2025 thrust_ship();
2026 next_thrust_count = 5;
2028 break;
2030 case (AST_HYPERSPACE):
2031 if(game_state == PLAY_MODE)
2032 hyperspace();
2033 /*maybe shield if it gets too hard */
2034 break;
2036 case (AST_FIRE_REP):
2037 case (AST_FIRE):
2038 if(game_state == ATTRACT_MODE)
2040 current_level = START_LEVEL;
2041 initialise_ship();
2042 initialise_game(current_level);
2043 show_level_timeout = SHOW_LEVEL_TIME;
2044 game_state = PLAY_MODE;
2046 else if(game_state == PLAY_MODE)
2048 if(!next_missile_count)
2050 fire_missile();
2051 next_missile_count = 10;
2054 else if(game_state == PAUSE_MODE)
2056 game_state = PLAY_MODE;
2058 break;
2060 default:
2061 if (rb->default_event_handler(button)==SYS_USB_CONNECTED)
2062 return PLUGIN_USB_CONNECTED;
2063 break;
2066 if(!num_lives)
2068 if(high_score < current_score)
2069 high_score = current_score;
2070 if(!show_game_over)
2071 break;
2074 if(next_missile_count)
2075 next_missile_count--;
2077 if(next_thrust_count)
2078 next_thrust_count--;
2080 if (end > *rb->current_tick)
2081 rb->sleep(end-*rb->current_tick);
2082 else
2083 rb->yield();
2089 enum plugin_status plugin_start(const void* parameter)
2091 enum plugin_status retval;
2092 (void)(parameter);
2094 game_state = ATTRACT_MODE;
2096 #if LCD_DEPTH > 1
2097 rb->lcd_set_backdrop(NULL);
2098 #endif
2099 /* universal font */
2100 rb->lcd_setfont(FONT_SYSFIXED);
2101 /* Turn off backlight timeout */
2102 backlight_force_on(); /* backlight control in lib/helper.c */
2103 iohiscore();
2104 retval = start_game();
2105 iohiscore();
2106 rb->lcd_setfont(FONT_UI);
2107 /* Turn on backlight timeout (revert to settings) */
2108 backlight_use_settings(); /* backlight control in lib/helper.c */
2109 return retval;