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 ****************************************************************************/
29 /******************************* Globals ***********************************/
30 static const struct plugin_api
* rb
; /* global api struct pointer */
31 /* variable button definitions */
32 #if CONFIG_KEYPAD == RECORDER_PAD
33 #define AST_PAUSE BUTTON_ON
34 #define AST_QUIT BUTTON_OFF
35 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
36 #define AST_THRUST BUTTON_UP
37 #define AST_HYPERSPACE BUTTON_DOWN
38 #define AST_LEFT BUTTON_LEFT
39 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
40 #define AST_RIGHT BUTTON_RIGHT
41 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
42 #define AST_FIRE BUTTON_PLAY
43 #define AST_FIRE_REP BUTTON_PLAY | BUTTON_REPEAT
45 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
46 #define AST_PAUSE BUTTON_ON
47 #define AST_QUIT BUTTON_OFF
48 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
49 #define AST_THRUST BUTTON_UP
50 #define AST_HYPERSPACE BUTTON_DOWN
51 #define AST_LEFT BUTTON_LEFT
52 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
53 #define AST_RIGHT BUTTON_RIGHT
54 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
55 #define AST_FIRE BUTTON_SELECT
56 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
58 #elif CONFIG_KEYPAD == ONDIO_PAD
59 #define AST_PAUSE (BUTTON_MENU | BUTTON_OFF)
60 #define AST_QUIT BUTTON_OFF
61 #define AST_THRUST BUTTON_UP
62 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
63 #define AST_HYPERSPACE BUTTON_DOWN
64 #define AST_LEFT BUTTON_LEFT
65 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
66 #define AST_RIGHT BUTTON_RIGHT
67 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
68 #define AST_FIRE BUTTON_MENU
69 #define AST_FIRE_REP BUTTON_MENU | BUTTON_REPEAT
71 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
72 (CONFIG_KEYPAD == IRIVER_H300_PAD)
73 #define AST_PAUSE BUTTON_REC
74 #define AST_QUIT BUTTON_OFF
75 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
76 #define AST_THRUST BUTTON_UP
77 #define AST_HYPERSPACE BUTTON_DOWN
78 #define AST_LEFT BUTTON_LEFT
79 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
80 #define AST_RIGHT BUTTON_RIGHT
81 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
82 #define AST_FIRE BUTTON_SELECT
83 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
85 #define AST_RC_QUIT BUTTON_RC_STOP
87 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
88 #define AST_PAUSE BUTTON_PLAY
89 #define AST_QUIT BUTTON_POWER
90 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
91 #define AST_THRUST BUTTON_UP
92 #define AST_HYPERSPACE BUTTON_DOWN
93 #define AST_LEFT BUTTON_LEFT
94 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
95 #define AST_RIGHT BUTTON_RIGHT
96 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
97 #define AST_FIRE BUTTON_SELECT
98 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
100 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
101 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
102 #define AST_PAUSE (BUTTON_SELECT | BUTTON_PLAY)
103 #define AST_QUIT (BUTTON_SELECT | BUTTON_MENU)
104 #define AST_THRUST BUTTON_MENU
105 #define AST_THRUST_REP (BUTTON_MENU | BUTTON_REPEAT)
106 #define AST_HYPERSPACE BUTTON_PLAY
107 #define AST_LEFT BUTTON_SCROLL_BACK
108 #define AST_LEFT_REP (BUTTON_SCROLL_BACK | BUTTON_REPEAT)
109 #define AST_RIGHT BUTTON_SCROLL_FWD
110 #define AST_RIGHT_REP (BUTTON_SCROLL_FWD | BUTTON_REPEAT)
111 #define AST_FIRE BUTTON_SELECT
112 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
114 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
115 #define AST_PAUSE BUTTON_A
116 #define AST_QUIT BUTTON_POWER
117 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
118 #define AST_THRUST BUTTON_UP
119 #define AST_HYPERSPACE BUTTON_DOWN
120 #define AST_LEFT BUTTON_LEFT
121 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
122 #define AST_RIGHT BUTTON_RIGHT
123 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
124 #define AST_FIRE BUTTON_SELECT
125 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
127 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
128 #define AST_PAUSE BUTTON_REC
129 #define AST_QUIT BUTTON_POWER
130 #define AST_THRUST_REP (BUTTON_UP | BUTTON_REPEAT)
131 #define AST_THRUST BUTTON_UP
132 #define AST_HYPERSPACE BUTTON_DOWN
133 #define AST_LEFT BUTTON_SCROLL_BACK
134 #define AST_LEFT_REP (BUTTON_SCROLL_BACK | BUTTON_REPEAT)
135 #define AST_RIGHT BUTTON_SCROLL_FWD
136 #define AST_RIGHT_REP (BUTTON_SCROLL_FWD | BUTTON_REPEAT)
137 #define AST_FIRE BUTTON_SELECT
138 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
140 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
141 #define AST_PAUSE BUTTON_REC
142 #define AST_QUIT BUTTON_POWER
143 #define AST_THRUST_REP (BUTTON_UP | BUTTON_REPEAT)
144 #define AST_THRUST BUTTON_UP
145 #define AST_HYPERSPACE BUTTON_DOWN
146 #define AST_LEFT BUTTON_LEFT
147 #define AST_LEFT_REP (BUTTON_LEFT | BUTTON_REPEAT)
148 #define AST_RIGHT BUTTON_RIGHT
149 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
150 #define AST_FIRE BUTTON_SELECT
151 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
153 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
154 #define AST_PAUSE BUTTON_PLAY
155 #define AST_QUIT BUTTON_POWER
156 #define AST_THRUST_REP BUTTON_SCROLL_UP | BUTTON_REPEAT
157 #define AST_THRUST BUTTON_SCROLL_UP
158 #define AST_HYPERSPACE BUTTON_SCROLL_DOWN
159 #define AST_LEFT BUTTON_LEFT
160 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
161 #define AST_RIGHT BUTTON_RIGHT
162 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
163 #define AST_FIRE BUTTON_REW
164 #define AST_FIRE_REP BUTTON_REW | BUTTON_REPEAT
166 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
167 #define AST_PAUSE BUTTON_PLAY
168 #define AST_QUIT BUTTON_BACK
169 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
170 #define AST_THRUST BUTTON_UP
171 #define AST_HYPERSPACE BUTTON_DOWN
172 #define AST_LEFT BUTTON_LEFT
173 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
174 #define AST_RIGHT BUTTON_RIGHT
175 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
176 #define AST_FIRE BUTTON_SELECT
177 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
179 #elif (CONFIG_KEYPAD == MROBE100_PAD)
180 #define AST_PAUSE BUTTON_DISPLAY
181 #define AST_QUIT BUTTON_POWER
182 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
183 #define AST_THRUST BUTTON_UP
184 #define AST_HYPERSPACE BUTTON_DOWN
185 #define AST_LEFT BUTTON_LEFT
186 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
187 #define AST_RIGHT BUTTON_RIGHT
188 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
189 #define AST_FIRE BUTTON_SELECT
190 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
192 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
193 #define AST_PAUSE BUTTON_RC_PLAY
194 #define AST_QUIT BUTTON_RC_REC
195 #define AST_THRUST_REP BUTTON_RC_VOL_UP | BUTTON_REPEAT
196 #define AST_THRUST BUTTON_RC_VOL_UP
197 #define AST_HYPERSPACE BUTTON_RC_VOL_DOWN
198 #define AST_LEFT BUTTON_RC_REW
199 #define AST_LEFT_REP (BUTTON_RC_REW | BUTTON_REPEAT)
200 #define AST_RIGHT BUTTON_RC_FF
201 #define AST_RIGHT_REP (BUTTON_RC_FF | BUTTON_REPEAT)
202 #define AST_FIRE BUTTON_RC_MODE
203 #define AST_FIRE_REP (BUTTON_RC_MODE | BUTTON_REPEAT)
205 #elif (CONFIG_KEYPAD == COWOND2_PAD)
206 #define AST_QUIT BUTTON_POWER
209 #error No keymap defined!
214 #define AST_PAUSE BUTTON_CENTER
217 #define AST_QUIT BUTTON_TOPLEFT
219 #ifndef AST_THRUST_REP
220 #define AST_THRUST_REP (BUTTON_TOPMIDDLE | BUTTON_REPEAT)
223 #define AST_THRUST BUTTON_TOPMIDDLE
225 #ifndef AST_HYPERSPACE
226 #define AST_HYPERSPACE BUTTON_TOPRIGHT
229 #define AST_LEFT BUTTON_MIDLEFT
232 #define AST_LEFT_REP (BUTTON_MIDLEFT | BUTTON_REPEAT)
235 #define AST_RIGHT BUTTON_MIDRIGHT
237 #ifndef AST_RIGHT_REP
238 #define AST_RIGHT_REP (BUTTON_MIDRIGHT | BUTTON_REPEAT)
241 #define AST_FIRE BUTTON_BOTTOMMIDDLE
244 #define AST_FIRE_REP (BUTTON_BOTTOMMIDDLE | BUTTON_MENU)
248 #define ABS(x) ((x)>0?(x):-(x))
250 #define RES MAX(LCD_WIDTH, LCD_HEIGHT)
251 #define LARGE_LCD RES >= 200
252 #define ENEMY_MISSILE_SURVIVAL_LENGTH RES/2
253 #define ASTEROID_SPEED RES/20
254 #define MISSILE_SURVIVAL_LENGTH 40
256 #define EXTRA_LIFE 250
258 #define MISSILE_SCALE 5000
260 #define EXPLOSION_LENGTH 20
262 #define HISCORE_FILE PLUGIN_GAMES_DIR "/astrorocks.hs"
264 #define MAX_NUM_ASTEROIDS 25
265 #define MAX_NUM_MISSILES 6
266 #define ENEMY_BIG_PROBABILITY_START 10
267 #define ENEMY_APPEAR_PROBABILITY_START 35
268 #define ENEMY_APPEAR_TIMING_START 1800
269 #define LITTLE_SHIP 2
271 #define SHOW_GAME_OVER_TIME 100
272 #define SHOW_LEVEL_TIME 50
273 #define START_LIVES 3
274 #define START_LEVEL 1
275 #define NUM_ASTEROID_VERTICES 10
276 #define NUM_SHIP_VERTICES 4
277 #define NUM_ENEMY_VERTICES 6
278 #define MAX_LEVEL MAX_NUM_ASTEROIDS
279 #define ENEMY_SPEED 4
280 #define ENEMY_START_X 0
281 #define ENEMY_START_Y 0
282 #define SIZE_ENEMY_COLLISION 5*SCALE
283 #define ATTRACT_FLIP_TIME 100
285 #define NUM_TRAIL_POINTS 70
286 #define NUM_ROTATIONS 16
288 #define SIN_COS_SCALE 10000
290 #define FAST_ROT_CW_SIN 873
291 #define FAST_ROT_CW_COS 9963
292 #define FAST_ROT_ACW_SIN -873
293 #define FAST_ROT_ACW_COS 9963
295 #define MEDIUM_ROT_CW_SIN 350
296 #define MEDIUM_ROT_CW_COS 9994
297 #define MEDIUM_ROT_ACW_SIN -350
298 #define MEDIUM_ROT_ACW_COS 9994
300 #define SLOW_ROT_CW_SIN 350
301 #define SLOW_ROT_CW_COS 9994
302 #define SLOW_ROT_ACW_SIN - 350
303 #define SLOW_ROT_ACW_COS 9994
305 #ifdef HAVE_LCD_COLOR
306 #define SHIP_ROT_CW_SIN 2419
307 #define SHIP_ROT_CW_COS 9702
308 #define SHIP_ROT_ACW_SIN -2419
309 #define SHIP_ROT_ACW_COS 9702
311 #define SHIP_ROT_CW_SIN 3827
312 #define SHIP_ROT_CW_COS 9239
313 #define SHIP_ROT_ACW_SIN -3827
314 #define SHIP_ROT_ACW_COS 9239
318 #define SCALED_WIDTH (LCD_WIDTH*SCALE)
319 #define SCALED_HEIGHT (LCD_HEIGHT*SCALE)
320 #define CENTER_LCD_X (LCD_WIDTH/2)
321 #define CENTER_LCD_Y (LCD_HEIGHT/2)
323 #define SHIP_EXPLOSION_COLOUR 1
324 #define ASTEROID_EXPLOSION_COLOUR 2
325 #define ENEMY_EXPLOSION_COLOUR 3
326 #define THRUST_COLOUR 4
328 #define ASTEROID_R 230
329 #define ASTEROID_G 200
330 #define ASTEROID_B 100
341 #ifdef HAVE_LCD_COLOR
342 #define COL_MISSILE LCD_RGBPACK(200,0,0)
343 #define COL_PLAYER LCD_RGBPACK(200,200,200)
344 #define COL_STARS LCD_WHITE
345 #define COL_ASTEROID LCD_RGBPACK(ASTEROID_R,ASTEROID_G,ASTEROID_B)
346 #define COL_TEXT LCD_RGBPACK(200,200,255)
347 #define COL_ENEMY LCD_RGBPACK(ENEMY_R,ENEMY_G,ENEMY_B)
348 #define SET_FG rb->lcd_set_foreground
349 #define SET_BG rb->lcd_set_background
355 /* The array of points that make up an asteroid */
356 static const short asteroid_one
[NUM_ASTEROID_VERTICES
*2] =
370 /* The array of points that make up an asteroid */
371 static const short asteroid_two
[NUM_ASTEROID_VERTICES
*2] =
385 /* The array of points that make up an asteroid */
386 static const short asteroid_three
[NUM_ASTEROID_VERTICES
*2] =
400 /* The array od points the make up the ship */
401 static const short ship_vertices
[NUM_SHIP_VERTICES
*2] =
416 /* The array of points the make up the bad spaceship */
417 static const short enemy_vertices
[NUM_ENEMY_VERTICES
*2] =
471 struct Point position
;
478 /* Asteroid structure, contains an array of points */
481 enum asteroid_type type
;
483 struct Point position
;
484 struct Point vertices
[NUM_ASTEROID_VERTICES
];
488 int explode_countdown
;
493 struct Point vertices
[NUM_SHIP_VERTICES
];
494 struct Point position
;
495 bool waiting_for_space
;
496 int explode_countdown
;
501 struct Point vertices
[NUM_ENEMY_VERTICES
];
502 struct Point position
;
503 int explode_countdown
;
504 long last_time_appeared
;
505 short size_probability
;
506 short appear_probability
;
512 struct Point position
;
513 struct Point oldpoint
;
517 static enum game_state game_state
;
518 static int asteroid_count
;
519 static int next_missile_count
;
520 static int next_thrust_count
;
521 static int num_lives
;
522 static int extra_life
;
523 static int show_level_timeout
;
524 static int attract_flip_timeout
;
525 static int show_game_over
;
526 static int current_level
;
527 static int current_score
;
528 static int high_score
;
529 static int space_check_size
= 30*SCALE
;
531 static bool enemy_on_screen
;
532 static char phscore
[30];
533 static struct Ship ship
;
534 static struct Point stars
[NUM_STARS
];
535 static struct Asteroid asteroids_array
[MAX_NUM_ASTEROIDS
];
536 static struct Missile missiles_array
[MAX_NUM_MISSILES
];
537 static struct Missile enemy_missile
;
538 static struct Enemy enemy
;
539 static struct Point lives_points
[NUM_SHIP_VERTICES
];
540 static struct TrailPoint trailPoints
[NUM_TRAIL_POINTS
];
542 void draw_and_move_asteroids(void);
543 void initialise_game(int nStartNum
);
545 bool is_asteroid_near_ship(struct Asteroid
* asteroid
);
546 bool is_point_within_asteroid(struct Asteroid
* asteroid
, struct Point
* point
);
548 void initialise_asteroid(struct Asteroid
* asteroid
, enum asteroid_type eType
);
549 void draw_polygon(struct Point
* vertices
, int px
, int py
, int num_vertices
);
550 void rotate_asteroid(struct Asteroid
* asteroid
);
551 void create_asteroid(enum asteroid_type type
, int x
, int y
);
552 void create_stars(void);
554 void initialise_ship(void);
555 void draw_and_move_ship(void);
556 void rotate_ship(int s
, int c
);
557 void thrust_ship(void);
559 void initialise_missile(struct Missile
* missile
);
560 void draw_and_move_missiles(void);
561 void fire_missile(void);
563 void animate_and_draw_explosion(struct Point
* point
, int num_points
, int xoffset
, int yoffset
);
564 void initialise_explosion(struct Point
* point
, int num_points
);
566 void move_point(struct Point
* point
);
567 void hyperspace(void);
568 void check_collisions(void);
569 void initialise_enemy(void);
570 void draw_and_move_enemy(void);
571 void draw_lives(void);
572 void drawstars(void);
573 bool is_ship_within_asteroid(struct Asteroid
* asteroid
);
577 /*Hi-Score reading and writing to file - this needs moving to the hi-score plugin lib as
584 /* clear the buffer we're about to load the highscore data into */
585 rb
->memset(phscore
, 0, sizeof(phscore
));
587 fd
= rb
->open(HISCORE_FILE
,O_RDWR
| O_CREAT
);
590 rb
->splash(HZ
, "Highscore file read error");
594 /* highscore used to %d, is now %d\n
595 Deal with no file or bad file */
596 rb
->read(fd
,phscore
, sizeof(phscore
));
598 compare
= rb
->atoi(phscore
);
600 if(high_score
> compare
)
602 rb
->lseek(fd
,0,SEEK_SET
);
603 rb
->fdprintf(fd
, "%d\n", high_score
);
606 high_score
= compare
;
611 bool point_in_poly(struct Point
* _point
, int num_vertices
, int x
, int y
)
620 pj
+= num_vertices
-1;
625 if((((pi
->y
<= y
) && (y
< pj
->y
)) || ((pj
->y
<= y
) && (y
< pi
->y
))) &&
626 (x
< (pj
->x
- pi
->x
) * (y
- pi
->y
) / (pj
->y
- pi
->y
) + pi
->x
))
629 if(n
== num_vertices
- 1)
640 void move_point(struct Point
* point
)
642 point
->x
+= point
->dx
;
643 point
->y
+= point
->dy
;
645 /*check bounds on the x-axis:*/
646 if(point
->x
>= SCALED_WIDTH
)
648 else if(point
->x
<= 0)
649 point
->x
= SCALED_WIDTH
;
651 /*Check bounds on the y-axis:*/
652 if(point
->y
>= SCALED_HEIGHT
)
654 else if(point
->y
<= 0)
655 point
->y
= SCALED_HEIGHT
;
658 void create_trail(struct TrailPoint
* tpoint
)
660 tpoint
->position
.dx
= -( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/10;
661 tpoint
->position
.dy
= -( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/10;
664 void create_explosion_trail(struct TrailPoint
* tpoint
)
666 tpoint
->position
.dx
= (rb
->rand()%5050)-2500;
667 tpoint
->position
.dy
= (rb
->rand()%5050)-2500;
670 void create_trail_blaze(int colour
, struct Point
* position
)
673 struct TrailPoint
* tpoint
;
676 if(colour
!= SHIP_EXPLOSION_COLOUR
)
678 numtoadd
= NUM_TRAIL_POINTS
/5;
684 numtoadd
= NUM_TRAIL_POINTS
/8;
685 xadd
= ship
.position
.x
;
686 yadd
= ship
.position
.y
;
689 /* give the point a random countdown timer, so they dissapears at different times */
690 tpoint
= trailPoints
;
691 n
= NUM_TRAIL_POINTS
;
694 if(tpoint
->alive
<= 0 && numtoadd
)
697 /* take a random x point anywhere between bottom two points of ship. */
698 /* ship.position.x; */
699 tpoint
->position
.x
= (ship
.vertices
[2].x
+ (rb
->rand()%18000)-9000) + position
->x
;
700 tpoint
->position
.y
= (ship
.vertices
[2].y
+ (rb
->rand()%18000)-9000) + position
->y
;
704 case SHIP_EXPLOSION_COLOUR
:
708 create_explosion_trail(tpoint
);
712 case ASTEROID_EXPLOSION_COLOUR
:
713 tpoint
->r
= ASTEROID_R
;
714 tpoint
->g
= ASTEROID_G
;
715 tpoint
->b
= ASTEROID_B
;
716 create_explosion_trail(tpoint
);
720 case ENEMY_EXPLOSION_COLOUR
:
724 create_explosion_trail(tpoint
);
729 tpoint
->r
= THRUST_R
;
730 tpoint
->g
= THRUST_G
;
731 tpoint
->b
= THRUST_B
;
732 create_trail(tpoint
);
737 /* add a proportional bit to the x and y based on dx and dy */
739 /* give the points a speed based on direction of travel - i.e. opposite */
740 tpoint
->position
.dx
+= position
->dx
;
741 tpoint
->position
.dy
+= position
->dy
;
747 /* find a space in the array of trail_points that is NULL or DEAD or whatever.
748 and place this one here. */
752 void draw_trail_blaze(void)
754 struct TrailPoint
* tpoint
;
755 /* loop through, if alive then move and draw.
756 when drawn, countdown it's timer.
758 tpoint
= trailPoints
;
759 int n
= NUM_TRAIL_POINTS
;
765 if(game_state
!= PAUSE_MODE
)
768 move_point(&(tpoint
->position
));
770 #ifdef HAVE_LCD_COLOR
771 /* intensity = tpoint->alive/2; */
772 if(tpoint
->r
>0)tpoint
->r
-=tpoint
->dec
;
773 if(tpoint
->g
>0)tpoint
->g
-=tpoint
->dec
;
774 if(tpoint
->b
>0)tpoint
->b
-=tpoint
->dec
;
775 SET_FG(LCD_RGBPACK(tpoint
->r
, tpoint
->g
, tpoint
->b
));
777 rb
->lcd_drawpixel(tpoint
->position
.x
/SCALE
, tpoint
->position
.y
/SCALE
);
783 /*Check if point is within a rectangle*/
784 bool is_point_within_rectangle(struct Point
* rect
, struct Point
* p
, int size
)
787 int aTLx
= rect
->x
- size
;
788 int aTLy
= rect
->y
- size
;
789 int aBRx
= rect
->x
+ size
;
790 int aBRy
= rect
->y
+ size
;
791 rb
->lcd_hline( aTLx
/SCALE
, aBRx
/SCALE
, aTLy
/SCALE
);
792 rb
->lcd_vline( aTLx
/SCALE
, aTLy
/SCALE
, aBRy
/SCALE
);
793 rb
->lcd_hline( aTLx
/SCALE
, aBRx
/SCALE
, aBRy
/SCALE
);
794 rb
->lcd_vline( aBRx
/SCALE
, aBRy
/SCALE
, aTLy
/SCALE
);
795 return (p
->x
> aTLx
&& p
->x
< aBRx
&& p
->y
> aTLy
&& p
->y
< aBRy
);
797 return (p
->x
> rect
->x
- size
&& p
->x
< rect
->x
+ size
&&
798 p
->y
> rect
->y
- size
&& p
->y
< rect
->y
+ size
);
803 void draw_polygon(struct Point
* vertices
, int px
, int py
, int num_vertices
)
805 int n
, t1
, t2
, oldX
, oldY
;
807 bool bDrawAll
= px
< WRAP_GAP
|| LCD_WIDTH
- px
< WRAP_GAP
||
808 py
< WRAP_GAP
|| LCD_HEIGHT
- py
< WRAP_GAP
;
812 oldX
= p
->x
/SCALE
+ px
;
813 oldY
= p
->y
/SCALE
+ py
;
815 for(n
= num_vertices
+1; --n
;)
817 t1
= p
->x
/SCALE
+ px
;
818 t2
= p
->y
/SCALE
+ py
;
820 rb
->lcd_drawline(oldX
, oldY
, t1
, t2
);
824 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
, t1
- LCD_WIDTH
, t2
);
825 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
, t1
+ LCD_WIDTH
, t2
);
826 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
+ LCD_HEIGHT
,
827 t1
- LCD_WIDTH
, t2
+ LCD_HEIGHT
);
828 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
+ LCD_HEIGHT
,
829 t1
+ LCD_WIDTH
, t2
+ LCD_HEIGHT
);
831 rb
->lcd_drawline(oldX
, oldY
- LCD_HEIGHT
, t1
, t2
- LCD_HEIGHT
);
832 rb
->lcd_drawline(oldX
, oldY
+ LCD_HEIGHT
, t1
, t2
+ LCD_HEIGHT
);
833 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
- LCD_HEIGHT
,
834 t1
- LCD_WIDTH
, t2
- LCD_HEIGHT
);
835 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
- LCD_HEIGHT
,
836 t1
+ LCD_WIDTH
, t2
- LCD_HEIGHT
);
844 void animate_and_draw_explosion(struct Point
* point
, int num_points
,
845 int xoffset
, int yoffset
)
848 for(n
= num_points
; --n
;)
850 if(game_state
!= PAUSE_MODE
)
852 point
->x
+= point
->dx
;
853 point
->y
+= point
->dy
;
855 rb
->lcd_fillrect( point
->x
/SCALE
+ xoffset
, point
->y
/SCALE
+ yoffset
,
856 POINT_SIZE
, POINT_SIZE
);
861 /*stop movement of ship, 'cos that's what happens when you go into hyperspace.*/
862 void hyperspace(void)
864 ship
.position
.dx
= ship
.position
.dy
= 0;
865 ship
.position
.x
= (rb
->rand()%SCALED_WIDTH
);
866 ship
.position
.y
= (rb
->rand()%SCALED_HEIGHT
);
869 void initialise_enemy(void)
875 if(rb
->rand()%100 > enemy
.size_probability
)
878 enemy
.size_probability
++;
879 if(enemy
.size_probability
< 90)
881 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
889 enemy_missile
.survived
= 0;
890 enemy_on_screen
= true;
891 enemy
.explode_countdown
= 0;
892 enemy
.last_time_appeared
= *rb
->current_tick
;
893 point
= enemy
.vertices
;
894 for(n
= 0; n
< NUM_ENEMY_VERTICES
+NUM_ENEMY_VERTICES
; n
+=2)
896 point
->x
= enemy_vertices
[n
];
897 point
->y
= enemy_vertices
[n
+1];
898 point
->x
*= SCALE
/size
;
899 point
->y
*= SCALE
/size
;
903 if(ship
.position
.x
>= SCALED_WIDTH
/2)
905 enemy
.position
.dx
= ENEMY_SPEED
;
906 enemy
.position
.x
= 0;
910 enemy
.position
.dx
= -ENEMY_SPEED
;
911 enemy
.position
.x
= SCALED_WIDTH
;
914 if(ship
.position
.y
>= SCALED_HEIGHT
/2)
916 enemy
.position
.dy
= ENEMY_SPEED
;
917 enemy
.position
.y
= 0;
921 enemy
.position
.dy
= -ENEMY_SPEED
;
922 enemy
.position
.y
= SCALED_HEIGHT
;
925 enemy
.position
.dx
*= SCALE
/10;
926 enemy
.position
.dy
*= SCALE
/10;
929 void draw_and_move_enemy(void)
931 int enemy_x
, enemy_y
;
938 enemy_x
= enemy
.position
.x
/SCALE
;
939 enemy_y
= enemy
.position
.y
/SCALE
;
940 if(!enemy
.explode_countdown
)
942 point
= enemy
.vertices
;
943 draw_polygon(enemy
.vertices
, enemy_x
, enemy_y
, NUM_ENEMY_VERTICES
);
944 rb
->lcd_drawline(enemy
.vertices
[0].x
/SCALE
+ enemy_x
,
945 enemy
.vertices
[0].y
/SCALE
+ enemy_y
,
946 enemy
.vertices
[3].x
/SCALE
+ enemy_x
,
947 enemy
.vertices
[3].y
/SCALE
+ enemy_y
);
949 if(game_state
!= PAUSE_MODE
)
951 enemy
.position
.x
+= enemy
.position
.dx
;
952 enemy
.position
.y
+= enemy
.position
.dy
;
955 if(enemy
.position
.x
> SCALED_WIDTH
|| enemy
.position
.x
< 0)
956 enemy_on_screen
= false;
958 if(enemy
.position
.y
> SCALED_HEIGHT
)
959 enemy
.position
.y
= 0;
960 else if(enemy
.position
.y
< 0)
961 enemy
.position
.y
= SCALED_HEIGHT
;
963 if( (rb
->rand()%1000) < 10)
964 enemy
.position
.dy
= -enemy
.position
.dy
;
969 /* animate_and_draw_explosion(enemy.vertices, NUM_ENEMY_VERTICES,
970 enemy_x, enemy.position.y/SCALE); */
971 if(game_state
!= PAUSE_MODE
)
973 enemy
.explode_countdown
--;
974 if(!enemy
.explode_countdown
)
975 enemy_on_screen
= false;
981 if( (*rb
->current_tick
- enemy
.last_time_appeared
) > enemy
.appear_timing
)
982 if(rb
->rand()%100 > enemy
.appear_probability
) initialise_enemy();
985 if(!enemy_missile
.survived
&& game_state
!= GAME_OVER
)
987 /*if no missile and the enemy is here and not exploding..then shoot baby!*/
988 if( !enemy
.explode_countdown
&& enemy_on_screen
&&
989 !ship
.waiting_for_space
&& (rb
->rand()%10) > 5 )
991 enemy_missile
.position
.x
= enemy
.position
.x
;
992 enemy_missile
.position
.y
= enemy
.position
.y
;
994 /*lame, needs to be sorted - it's trying to shoot at the ship*/
995 if(ABS(enemy
.position
.y
- ship
.position
.y
) <= 5*SCALE
)
997 enemy_missile
.position
.dy
= 0;
1001 if( enemy
.position
.y
< ship
.position
.y
)
1002 enemy_missile
.position
.dy
= 1;
1004 enemy_missile
.position
.dy
= -1;
1007 if(ABS(enemy
.position
.x
- ship
.position
.x
) <= 5*SCALE
)
1008 enemy_missile
.position
.dx
= 0;
1011 if( enemy
.position
.x
< ship
.position
.x
)
1012 enemy_missile
.position
.dx
= 1;
1014 enemy_missile
.position
.dx
= -1;
1017 if(enemy_missile
.position
.dx
== 0 &&
1018 enemy_missile
.position
.dy
== 0)
1019 enemy_missile
.position
.dx
= enemy_missile
.position
.dy
= -1;
1021 enemy_missile
.position
.dx
*= SCALE
;
1022 enemy_missile
.position
.dy
*= SCALE
;
1023 enemy_missile
.survived
= ENEMY_MISSILE_SURVIVAL_LENGTH
;
1029 rb
->lcd_fillrect( enemy_missile
.position
.x
/SCALE
,
1030 enemy_missile
.position
.y
/SCALE
,
1031 POINT_SIZE
, POINT_SIZE
);
1032 if(game_state
!= PAUSE_MODE
)
1034 move_point(&enemy_missile
.position
);
1035 enemy_missile
.survived
--;
1041 * Lame method of collision
1042 * detection. It's checking for collision
1043 * between point and a big rectangle around the asteroid...
1044 *******************/
1045 bool is_point_within_asteroid(struct Asteroid
* asteroid
, struct Point
* point
)
1047 if( !is_point_within_rectangle(&asteroid
->position
, point
,
1048 asteroid
->radius
+4*SCALE
) )
1051 if(point_in_poly(asteroid
->vertices
, NUM_ASTEROID_VERTICES
,
1052 point
->x
- asteroid
->position
.x
,
1053 point
->y
- asteroid
->position
.y
))
1055 switch(asteroid
->type
)
1058 asteroid
->explode_countdown
= EXPLOSION_LENGTH
;
1059 create_trail_blaze(ASTEROID_EXPLOSION_COLOUR
, &asteroid
->position
);
1063 create_asteroid(MEDIUM
, asteroid
->position
.x
,
1064 asteroid
->position
.y
);
1065 create_asteroid(MEDIUM
, asteroid
->position
.x
,
1066 asteroid
->position
.y
);
1070 create_asteroid(SMALL
, asteroid
->position
.x
, asteroid
->position
.y
);
1071 create_asteroid(SMALL
, asteroid
->position
.x
, asteroid
->position
.y
);
1076 if(current_score
> extra_life
)
1079 extra_life
= current_score
+EXTRA_LIFE
;
1082 asteroid
->exists
= false;
1089 bool is_point_within_enemy(struct Point
* point
)
1091 if( is_point_within_rectangle(&enemy
.position
, point
, 7*SCALE
) )
1094 /*enemy_missile.survived = 0;*/
1095 enemy
.explode_countdown
= EXPLOSION_LENGTH
;
1096 /* initialise_explosion(enemy.vertices, NUM_ENEMY_VERTICES); */
1097 create_trail_blaze(ENEMY_EXPLOSION_COLOUR
, &enemy
.position
);
1104 bool is_ship_within_asteroid(struct Asteroid
* asteroid
)
1109 p
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1110 p
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1111 hit
|= is_point_within_asteroid(asteroid
, &p
);
1115 p
.x
= ship
.position
.x
+ ship
.vertices
[1].x
;
1116 p
.y
= ship
.position
.y
+ ship
.vertices
[1].y
;
1117 hit
|= is_point_within_asteroid(asteroid
, &p
);
1120 p
.x
= ship
.position
.x
+ ship
.vertices
[3].x
;
1121 p
.y
= ship
.position
.y
+ ship
.vertices
[3].y
;
1122 hit
|= is_point_within_asteroid(asteroid
, &p
);
1129 void initialise_explosion(struct Point
* point
, int num_points
)
1133 point
->x
+= point
->dx
;
1134 point
->y
+= point
->dy
;
1135 for(n
= num_points
; --n
;)
1137 point
->dx
= point
->x
;
1138 point
->dy
= point
->y
;
1144 /* Check for collsions between the missiles and the asteroids and the ship */
1145 void check_collisions(void)
1148 bool asteroids_onscreen
= false;
1149 struct Missile
* missile
;
1150 struct Asteroid
* asteroid
;
1151 bool ship_cant_be_placed
= false;
1153 asteroid
= asteroids_array
;
1154 m
= MAX_NUM_ASTEROIDS
;
1157 /*if the asteroids exists then test missile collision:*/
1158 if(asteroid
->exists
)
1160 missile
= missiles_array
;
1161 n
= MAX_NUM_MISSILES
;
1164 /*if the missiles exists:*/
1165 if(missile
->survived
> 0)
1167 /*has the missile hit the asteroid?*/
1168 if(is_point_within_asteroid(asteroid
, &missile
->position
)
1169 || is_point_within_asteroid(asteroid
,
1170 &missile
->oldpoint
))
1172 missile
->survived
= 0;
1179 /*now check collision with ship:*/
1180 if(asteroid
->exists
&& !ship
.waiting_for_space
&& !ship
.explode_countdown
)
1182 if(is_ship_within_asteroid(asteroid
))
1185 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1186 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1187 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1190 /*has the enemy missile blown something up?*/
1191 if(asteroid
->exists
&& enemy_missile
.survived
)
1193 if(is_point_within_asteroid(asteroid
, &enemy_missile
.position
))
1195 /*take that score back then:*/
1196 if(current_score
> 0) current_score
--;
1197 enemy_missile
.survived
= 0;
1200 /*if it still exists, check if ship is waiting for space:*/
1201 if(asteroid
->exists
&& ship
.waiting_for_space
)
1202 ship_cant_be_placed
|=
1203 is_point_within_rectangle(&ship
.position
,
1204 &asteroid
->position
,
1209 /*is an asteroid still exploding?*/
1210 if(asteroid
->explode_countdown
)
1211 asteroids_onscreen
= true;
1216 /*now check collision between ship and enemy*/
1217 if(enemy_on_screen
&& !ship
.waiting_for_space
&&
1218 !ship
.explode_countdown
&& !enemy
.explode_countdown
)
1220 /*has the enemy collided with the ship?*/
1221 if(is_point_within_enemy(&ship
.position
))
1223 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1224 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1225 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1226 create_trail_blaze(ENEMY_EXPLOSION_COLOUR
, &enemy
.position
);
1229 /*Now see if the enemy has been shot at by the ships missiles:*/
1230 missile
= missiles_array
;
1231 n
= MAX_NUM_MISSILES
;
1234 if(missile
->survived
> 0 &&
1235 is_point_within_enemy(&missile
->position
))
1237 missile
->survived
= 0;
1244 /*test collision with enemy missile and ship:*/
1245 if(!ship_cant_be_placed
&& enemy_missile
.survived
> 0 &&
1246 point_in_poly(ship
.vertices
, NUM_SHIP_VERTICES
,
1247 enemy_missile
.position
.x
- ship
.position
.x
,
1248 enemy_missile
.position
.y
- ship
.position
.y
))
1250 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1251 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1252 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1253 enemy_missile
.survived
= 0;
1254 enemy_missile
.position
.x
= enemy_missile
.position
.y
= 0;
1257 if(!ship_cant_be_placed
)
1258 ship
.waiting_for_space
= false;
1260 /*if all asteroids cleared then start again:*/
1261 if(asteroid_count
== 0 && !enemy_on_screen
&& !asteroids_onscreen
)
1264 game_state
= SHOW_LEVEL
;
1265 enemy
.appear_probability
+= 5;
1266 enemy
.appear_timing
-= 200;
1267 if( enemy
.appear_probability
> 100)
1268 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1269 show_level_timeout
= SHOW_LEVEL_TIME
;
1273 /*************************************************
1274 ** Creates a new asteroid of the given 4type (size)
1275 ** and at the given location.
1276 *************************************************/
1277 void create_asteroid(enum asteroid_type type
, int x
, int y
)
1279 struct Asteroid
* asteroid
;
1282 asteroid
= asteroids_array
;
1283 n
= MAX_NUM_ASTEROIDS
;
1286 if(!asteroid
->exists
&& !asteroid
->explode_countdown
)
1288 initialise_asteroid(asteroid
, type
);
1289 asteroid
->position
.x
= x
;
1290 asteroid
->position
.y
= y
;
1297 /* Initialise a missile */
1298 void initialise_missile(struct Missile
* missile
)
1300 missile
->position
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1301 missile
->position
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1302 missile
->position
.dx
= (ship
.vertices
[0].x
- ship
.vertices
[2].x
)/2;
1303 missile
->position
.dy
= (ship
.vertices
[0].y
- ship
.vertices
[2].y
)/2;
1304 missile
->survived
= MISSILE_SURVIVAL_LENGTH
;
1305 missile
->oldpoint
.x
= missile
->position
.x
;
1306 missile
->oldpoint
.y
= missile
->position
.y
;
1309 /* Draw and Move all the missiles */
1310 void draw_and_move_missiles(void)
1316 struct Missile
* missile
;
1317 missile
= missiles_array
;
1319 SET_FG(COL_MISSILE
);
1321 n
= MAX_NUM_MISSILES
;
1324 if(missile
->survived
)
1326 if(missile
->position
.dx
> 0)
1328 if(missile
->position
.x
>= missile
->oldpoint
.x
)
1330 p1x
= missile
->oldpoint
.x
;
1331 p2x
= missile
->position
.x
;
1336 p2x
= missile
->position
.x
;
1341 if(missile
->oldpoint
.x
>= missile
->position
.x
)
1343 p1x
= missile
->oldpoint
.x
;
1344 p2x
= missile
->position
.x
;
1348 p1x
= missile
->oldpoint
.x
;
1353 if(missile
->position
.dy
> 0)
1355 if(missile
->position
.y
>= missile
->oldpoint
.y
)
1357 p1y
= missile
->oldpoint
.y
;
1358 p2y
= missile
->position
.y
;
1363 p2y
= missile
->position
.y
;
1368 if(missile
->oldpoint
.y
>= missile
->position
.y
)
1370 p1y
= missile
->oldpoint
.y
;
1371 p2y
= missile
->position
.y
;
1375 p1y
= missile
->oldpoint
.y
;
1380 rb
->lcd_drawline( p1x
/SCALE
, p1y
/SCALE
, p2x
/SCALE
, p2y
/SCALE
);
1382 if(game_state
!= PAUSE_MODE
)
1384 missile
->oldpoint
.x
= missile
->position
.x
;
1385 missile
->oldpoint
.y
= missile
->position
.y
;
1386 move_point(&missile
->position
);
1387 missile
->survived
--;
1394 void draw_lives(void)
1397 int px
= (LCD_WIDTH
- num_lives
*4 - 1);
1399 int py
= (LCD_HEIGHT
-6);
1401 int py
= (LCD_HEIGHT
-4);
1409 draw_polygon(lives_points
, px
, py
, NUM_SHIP_VERTICES
);
1418 /*Fire the next missile*/
1419 void fire_missile(void)
1422 struct Missile
* missile
;
1424 if(!ship
.explode_countdown
&& !ship
.waiting_for_space
)
1426 missile
= missiles_array
;
1427 n
= MAX_NUM_MISSILES
;
1430 if(!missile
->survived
)
1432 initialise_missile(missile
);
1440 /* Initialise the passed Asteroid */
1441 void initialise_asteroid(struct Asteroid
* asteroid
, enum asteroid_type type
)
1445 struct Point
* point
;
1446 asteroid
->exists
= true;
1447 asteroid
->type
= type
;
1448 asteroid
->explode_countdown
= 0;
1450 /*Set the radius of the asteroid:*/
1451 asteroid
->radius
= (int)type
*SCALE
;
1453 /*shall we move Clockwise and Fast*/
1454 if((rb
->rand()%100)>75)
1456 asteroid
->speed_cos
= FAST_ROT_CW_COS
;
1457 asteroid
->speed_sin
= FAST_ROT_CW_SIN
;
1459 else if((rb
->rand()%100)>75)
1461 asteroid
->speed_cos
= FAST_ROT_ACW_COS
;
1462 asteroid
->speed_sin
= FAST_ROT_ACW_SIN
;
1464 else if((rb
->rand()%100)>75)
1466 asteroid
->speed_cos
= SLOW_ROT_ACW_COS
;
1467 asteroid
->speed_sin
= SLOW_ROT_ACW_SIN
;
1471 asteroid
->speed_cos
= SLOW_ROT_CW_COS
;
1472 asteroid
->speed_sin
= SLOW_ROT_CW_SIN
;
1475 b
= (rb
->rand()%100)>66;
1476 b2
= (rb
->rand()%100)>66;
1477 point
= asteroid
->vertices
;
1478 for(n
= 0; n
< NUM_ASTEROID_VERTICES
*2; n
+=2)
1482 point
->x
= asteroid_one
[n
];
1483 point
->y
= asteroid_one
[n
+1];
1487 point
->x
= asteroid_two
[n
];
1488 point
->y
= asteroid_two
[n
+1];
1492 point
->x
= asteroid_three
[n
];
1493 point
->y
= asteroid_three
[n
+1];
1496 point
->x
*= asteroid
->radius
/6;
1497 point
->y
*= asteroid
->radius
/6;
1502 asteroid
->radius
+= 6*SCALE
;
1503 if(asteroid
->type
== SMALL
)
1504 asteroid
->radius
/= 3;/*2*/
1505 else if(asteroid
->type
== LARGE
)
1506 asteroid
->radius
+= 3*SCALE
;/*2*/
1510 /*Set the position randomly:*/
1511 asteroid
->position
.x
= (rb
->rand()%SCALED_WIDTH
);
1512 asteroid
->position
.y
= (rb
->rand()%SCALED_HEIGHT
);
1514 asteroid
->position
.dx
= 0;
1515 while(asteroid
->position
.dx
== 0)
1516 asteroid
->position
.dx
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
1518 asteroid
->position
.dy
= 0;
1519 while(asteroid
->position
.dy
== 0)
1520 asteroid
->position
.dy
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
1522 asteroid
->position
.dx
*= SCALE
/10;
1523 asteroid
->position
.dy
*= SCALE
/10;
1525 b
= is_point_within_rectangle(&ship
.position
, &asteroid
->position
,
1529 /*Now rotate the asteroid a bit, so they all look a bit different*/
1530 for(n
=(rb
->rand()%30) + 2;--n
;)
1531 rotate_asteroid(asteroid
);
1533 /*great, we've created an asteroid, don't forget to increment the total:*/
1537 /*Initialise the ship*/
1538 void initialise_ship(void)
1540 struct Point
* point
;
1541 struct Point
* lives_point
;
1544 ship
.position
.x
= CENTER_LCD_X
;
1545 ship
.position
.y
= CENTER_LCD_Y
;
1546 ship
.position
.x
*= SCALE
;
1547 ship
.position
.y
*= SCALE
;
1548 ship
.position
.dx
= ship
.position
.dy
= 0;
1550 point
= ship
.vertices
;
1551 lives_point
= lives_points
;
1552 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+=2)
1554 point
->x
= ship_vertices
[n
];
1555 point
->y
= ship_vertices
[n
+1];
1562 ship
.position
.dx
= 0;
1563 ship
.position
.dy
= 0;
1564 ship
.explode_countdown
= 0;
1566 /*grab a copy of the ships points for the lives display:*/
1567 point
= ship
.vertices
;
1568 lives_point
= lives_points
;
1569 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+=2)
1571 lives_point
->x
= point
->x
;
1572 lives_point
->y
= point
->y
;
1578 void rotate_asteroid(struct Asteroid
* asteroid
)
1580 struct Point
* point
;
1584 point
= asteroid
->vertices
;
1585 for(n
= NUM_ASTEROID_VERTICES
+1; --n
;)
1588 point
->x
= xtemp
*asteroid
->speed_cos
/SIN_COS_SCALE
-
1589 point
->y
*asteroid
->speed_sin
/SIN_COS_SCALE
;
1590 point
->y
= point
->y
*asteroid
->speed_cos
/SIN_COS_SCALE
+
1591 xtemp
*asteroid
->speed_sin
/SIN_COS_SCALE
;
1596 /*************************************************
1597 ** Draws the ship, moves the ship and creates a new
1598 ** one if it's finished exploding.
1599 **************************************************/
1600 void draw_and_move_ship(void)
1602 int nxoffset
= ship
.position
.x
/SCALE
;
1603 int nyoffset
= ship
.position
.y
/SCALE
;
1605 if(!ship
.explode_countdown
)
1607 if(!ship
.waiting_for_space
)
1609 draw_polygon(ship
.vertices
, nxoffset
, nyoffset
, NUM_SHIP_VERTICES
);
1610 if(game_state
!= PAUSE_MODE
&& game_state
!= GAME_OVER
)
1612 move_point(&ship
.position
);
1618 /* animate_and_draw_explosion(ship.vertices, NUM_SHIP_VERTICES,
1619 ship.position.x/SCALE,
1620 ship.position.y/SCALE); */
1621 if(game_state
!= PAUSE_MODE
)
1623 ship
.explode_countdown
--;
1624 if(!ship
.explode_countdown
)
1629 show_game_over
= SHOW_GAME_OVER_TIME
;
1630 game_state
= GAME_OVER
;
1635 ship
.waiting_for_space
= true;
1642 void thrust_ship(void)
1644 if(!ship
.waiting_for_space
)
1646 ship
.position
.dx
+= ( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/20;
1647 ship
.position
.dy
+= ( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/20;
1648 /*if dx and dy are below a certain threshold, then set 'em to 0
1649 but to do this we need to ascertain if the spacehip as moved on screen
1650 for more than a certain amount. */
1652 create_trail_blaze(THRUST_COLOUR
, &ship
.position
);
1656 /**************************************************
1657 ** Rotate the ship using the passed sin & cos values
1658 ***************************************************/
1659 void rotate_ship(int c
, int s
)
1661 struct Point
* point
;
1665 if(!ship
.waiting_for_space
&& !ship
.explode_countdown
)
1667 point
= ship
.vertices
;
1668 for(n
=NUM_SHIP_VERTICES
+1;--n
;)
1671 point
->x
= xtemp
*c
/SIN_COS_SCALE
- point
->y
*s
/SIN_COS_SCALE
;
1672 point
->y
= point
->y
*c
/SIN_COS_SCALE
+ xtemp
*s
/SIN_COS_SCALE
;
1688 rb
->lcd_drawpixel(p
->x
, p
->y
);
1693 /*************************************************
1694 ** Draw And Move all Asteroids
1695 *************************************************/
1696 void draw_and_move_asteroids(void)
1699 struct Asteroid
* asteroid
;
1701 asteroid
= asteroids_array
;
1702 SET_FG(COL_ASTEROID
);
1704 n
= MAX_NUM_ASTEROIDS
;
1707 if(game_state
!= PAUSE_MODE
)
1709 if(asteroid
->exists
)
1711 move_point(&asteroid
->position
);
1712 rotate_asteroid(asteroid
);
1713 draw_polygon(asteroid
->vertices
, asteroid
->position
.x
/SCALE
,
1714 asteroid
->position
.y
/SCALE
,
1715 NUM_ASTEROID_VERTICES
);
1717 else if(asteroid
->explode_countdown
)
1719 /* animate_and_draw_explosion(asteroid->vertices,
1720 NUM_ASTEROID_VERTICES,
1721 asteroid->position.x/SCALE,
1722 asteroid->position.y/SCALE); */
1723 asteroid
->explode_countdown
--;
1728 if(asteroid
->exists
)
1729 draw_polygon(asteroid
->vertices
,
1730 asteroid
->position
.x
/SCALE
,
1731 asteroid
->position
.y
/SCALE
,
1732 NUM_ASTEROID_VERTICES
);
1738 void create_stars(void)
1740 struct TrailPoint
* tpoint
;
1748 p
->x
= (rb
->rand()%LCD_WIDTH
);
1749 p
->y
= (rb
->rand()%LCD_HEIGHT
);
1754 /* give the point a random countdown timer, so they dissapears at different
1756 tpoint
= trailPoints
;
1757 n
= NUM_TRAIL_POINTS
;
1765 /*************************************************
1766 ** Creates start_num number of new asteroids of
1768 **************************************************/
1769 void initialise_game(int start_num
)
1772 asteroid_count
= next_missile_count
= next_thrust_count
= 0;
1773 struct Asteroid
* asteroid
;
1774 struct Missile
* missile
;
1775 extra_life
= EXTRA_LIFE
;
1778 enemy_on_screen
= 0;
1779 enemy_missile
.survived
= 0;
1782 asteroid
= asteroids_array
;
1783 n
= MAX_NUM_ASTEROIDS
;
1786 asteroid
->exists
= false;
1790 /*make some LARGE asteroids*/
1791 for(n
= 0; n
< start_num
; n
++)
1792 initialise_asteroid(&asteroids_array
[n
], LARGE
);
1794 /*ensure all missiles are out of action: */
1795 missile
= missiles_array
;
1796 n
= MAX_NUM_MISSILES
;
1799 missile
->survived
=0;
1804 void start_attract_mode(void)
1806 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1807 enemy
.appear_timing
= ENEMY_APPEAR_TIMING_START
;
1809 num_lives
= START_LIVES
;
1811 attract_flip_timeout
= ATTRACT_FLIP_TIME
;
1812 game_state
= ATTRACT_MODE
;
1813 if(asteroid_count
< 3)
1814 initialise_game(current_level
);
1817 enum plugin_status
start_game(void)
1825 /*create stars once, and once only:*/
1832 /*game starts with at level 1
1834 start_attract_mode();
1839 end
= *rb
->current_tick
+ (CYCLETIME
* HZ
) / 1000;
1840 rb
->lcd_clear_display();
1845 if(attract_flip_timeout
< ATTRACT_FLIP_TIME
/2)
1847 rb
->lcd_putsxy(CENTER_LCD_X
- 39,
1848 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4,
1850 if(!attract_flip_timeout
)
1851 attract_flip_timeout
= ATTRACT_FLIP_TIME
;
1855 rb
->snprintf(s
, sizeof(s
), "Hi Score %d ", high_score
);
1856 rb
->lcd_putsxy(CENTER_LCD_X
- 30,
1857 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, s
);
1859 attract_flip_timeout
--;
1863 rb
->lcd_putsxy(CENTER_LCD_X
- 25,
1864 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, "Game Over");
1865 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1866 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1869 start_attract_mode();
1873 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1874 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1875 rb
->lcd_putsxy(CENTER_LCD_X
- 15,
1876 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, "pause");
1877 draw_and_move_missiles();
1879 draw_and_move_ship();
1883 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1884 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1885 draw_and_move_missiles();
1888 draw_and_move_ship();
1892 show_level_timeout
--;
1893 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1894 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1895 rb
->snprintf(level
, sizeof(level
), "stage %d ", current_level
);
1896 rb
->lcd_putsxy(CENTER_LCD_X
- 20,
1897 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, level
);
1898 draw_and_move_ship();
1900 if(!show_level_timeout
)
1902 initialise_game(current_level
);
1903 game_state
= PLAY_MODE
;
1910 draw_and_move_asteroids();
1911 draw_and_move_enemy();
1914 button
= rb
->button_get(false);
1916 #ifdef HAS_BUTTON_HOLD
1917 if (rb
->button_hold())
1918 game_state
= PAUSE_MODE
;
1924 if(game_state
== PLAY_MODE
)
1925 game_state
= PAUSE_MODE
;
1926 else if(game_state
== PAUSE_MODE
)
1927 game_state
= PLAY_MODE
;
1934 if(game_state
== ATTRACT_MODE
)
1936 else if(game_state
== GAME_OVER
)
1938 start_attract_mode();
1942 show_game_over
= SHOW_GAME_OVER_TIME
;
1943 game_state
= GAME_OVER
;
1947 case (AST_LEFT_REP
):
1949 if(game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
1950 rotate_ship(SHIP_ROT_ACW_COS
, SHIP_ROT_ACW_SIN
);
1953 case (AST_RIGHT_REP
):
1955 if(game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
1956 rotate_ship(SHIP_ROT_CW_COS
, SHIP_ROT_CW_SIN
);
1959 case (AST_THRUST_REP
):
1961 if((game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
) && !next_thrust_count
)
1964 next_thrust_count
= 5;
1968 case (AST_HYPERSPACE
):
1969 if(game_state
== PLAY_MODE
)
1971 /*maybe shield if it gets too hard */
1974 case (AST_FIRE_REP
):
1976 if(game_state
== ATTRACT_MODE
)
1978 current_level
= START_LEVEL
;
1980 initialise_game(current_level
);
1981 show_level_timeout
= SHOW_LEVEL_TIME
;
1982 game_state
= PLAY_MODE
;
1984 else if(game_state
== PLAY_MODE
)
1986 if(!next_missile_count
)
1989 next_missile_count
= 10;
1992 else if(game_state
== PAUSE_MODE
)
1994 game_state
= PLAY_MODE
;
1999 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
)
2000 return PLUGIN_USB_CONNECTED
;
2006 if(high_score
< current_score
)
2007 high_score
= current_score
;
2012 if(next_missile_count
)
2013 next_missile_count
--;
2015 if(next_thrust_count
)
2016 next_thrust_count
--;
2018 if (end
> *rb
->current_tick
)
2019 rb
->sleep(end
-*rb
->current_tick
);
2027 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
2029 enum plugin_status retval
;
2033 game_state
= ATTRACT_MODE
;
2036 rb
->lcd_set_backdrop(NULL
);
2038 /* universal font */
2039 rb
->lcd_setfont(FONT_SYSFIXED
);
2040 /* Turn off backlight timeout */
2041 backlight_force_on(rb
); /* backlight control in lib/helper.c */
2043 retval
= start_game();
2045 rb
->lcd_setfont(FONT_UI
);
2046 /* Turn on backlight timeout (revert to settings) */
2047 backlight_use_settings(rb
); /* backlight control in lib/helper.c */