1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 by Mat Holton
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
27 /******************************* Globals ***********************************/
28 static const struct plugin_api
* rb
; /* global api struct pointer */
29 /* variable button definitions */
30 #if CONFIG_KEYPAD == RECORDER_PAD
31 #define AST_PAUSE BUTTON_ON
32 #define AST_QUIT BUTTON_OFF
33 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
34 #define AST_THRUST BUTTON_UP
35 #define AST_HYPERSPACE BUTTON_DOWN
36 #define AST_LEFT BUTTON_LEFT
37 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
38 #define AST_RIGHT BUTTON_RIGHT
39 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
40 #define AST_FIRE BUTTON_PLAY
41 #define AST_FIRE_REP BUTTON_PLAY | BUTTON_REPEAT
43 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
44 #define AST_PAUSE BUTTON_ON
45 #define AST_QUIT BUTTON_OFF
46 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
47 #define AST_THRUST BUTTON_UP
48 #define AST_HYPERSPACE BUTTON_DOWN
49 #define AST_LEFT BUTTON_LEFT
50 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
51 #define AST_RIGHT BUTTON_RIGHT
52 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
53 #define AST_FIRE BUTTON_SELECT
54 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
56 #elif CONFIG_KEYPAD == ONDIO_PAD
57 #define AST_PAUSE (BUTTON_MENU | BUTTON_OFF)
58 #define AST_QUIT BUTTON_OFF
59 #define AST_THRUST BUTTON_UP
60 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
61 #define AST_HYPERSPACE BUTTON_DOWN
62 #define AST_LEFT BUTTON_LEFT
63 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
64 #define AST_RIGHT BUTTON_RIGHT
65 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
66 #define AST_FIRE BUTTON_MENU
67 #define AST_FIRE_REP BUTTON_MENU | BUTTON_REPEAT
69 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
70 (CONFIG_KEYPAD == IRIVER_H300_PAD)
71 #define AST_PAUSE BUTTON_REC
72 #define AST_QUIT BUTTON_OFF
73 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
74 #define AST_THRUST BUTTON_UP
75 #define AST_HYPERSPACE BUTTON_DOWN
76 #define AST_LEFT BUTTON_LEFT
77 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
78 #define AST_RIGHT BUTTON_RIGHT
79 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
80 #define AST_FIRE BUTTON_SELECT
81 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
83 #define AST_RC_QUIT BUTTON_RC_STOP
85 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
86 #define AST_PAUSE BUTTON_PLAY
87 #define AST_QUIT BUTTON_POWER
88 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
89 #define AST_THRUST BUTTON_UP
90 #define AST_HYPERSPACE BUTTON_DOWN
91 #define AST_LEFT BUTTON_LEFT
92 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
93 #define AST_RIGHT BUTTON_RIGHT
94 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
95 #define AST_FIRE BUTTON_SELECT
96 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
98 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
99 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
100 #define AST_PAUSE (BUTTON_SELECT | BUTTON_PLAY)
101 #define AST_QUIT (BUTTON_SELECT | BUTTON_MENU)
102 #define AST_THRUST BUTTON_MENU
103 #define AST_THRUST_REP (BUTTON_MENU | BUTTON_REPEAT)
104 #define AST_HYPERSPACE BUTTON_PLAY
105 #define AST_LEFT BUTTON_SCROLL_BACK
106 #define AST_LEFT_REP (BUTTON_SCROLL_BACK | BUTTON_REPEAT)
107 #define AST_RIGHT BUTTON_SCROLL_FWD
108 #define AST_RIGHT_REP (BUTTON_SCROLL_FWD | BUTTON_REPEAT)
109 #define AST_FIRE BUTTON_SELECT
110 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
112 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
113 #define AST_PAUSE BUTTON_A
114 #define AST_QUIT BUTTON_POWER
115 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
116 #define AST_THRUST BUTTON_UP
117 #define AST_HYPERSPACE BUTTON_DOWN
118 #define AST_LEFT BUTTON_LEFT
119 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
120 #define AST_RIGHT BUTTON_RIGHT
121 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
122 #define AST_FIRE BUTTON_SELECT
123 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
125 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
126 #define AST_PAUSE BUTTON_REC
127 #define AST_QUIT BUTTON_POWER
128 #define AST_THRUST_REP (BUTTON_UP | BUTTON_REPEAT)
129 #define AST_THRUST BUTTON_UP
130 #define AST_HYPERSPACE BUTTON_DOWN
131 #define AST_LEFT BUTTON_SCROLL_BACK
132 #define AST_LEFT_REP (BUTTON_SCROLL_BACK | BUTTON_REPEAT)
133 #define AST_RIGHT BUTTON_SCROLL_FWD
134 #define AST_RIGHT_REP (BUTTON_SCROLL_FWD | BUTTON_REPEAT)
135 #define AST_FIRE BUTTON_SELECT
136 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
138 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
139 #define AST_PAUSE BUTTON_REC
140 #define AST_QUIT BUTTON_POWER
141 #define AST_THRUST_REP (BUTTON_UP | BUTTON_REPEAT)
142 #define AST_THRUST BUTTON_UP
143 #define AST_HYPERSPACE BUTTON_DOWN
144 #define AST_LEFT BUTTON_LEFT
145 #define AST_LEFT_REP (BUTTON_LEFT | BUTTON_REPEAT)
146 #define AST_RIGHT BUTTON_RIGHT
147 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
148 #define AST_FIRE BUTTON_SELECT
149 #define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
151 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
152 #define AST_PAUSE BUTTON_PLAY
153 #define AST_QUIT BUTTON_POWER
154 #define AST_THRUST_REP BUTTON_SCROLL_UP | BUTTON_REPEAT
155 #define AST_THRUST BUTTON_SCROLL_UP
156 #define AST_HYPERSPACE BUTTON_SCROLL_DOWN
157 #define AST_LEFT BUTTON_LEFT
158 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
159 #define AST_RIGHT BUTTON_RIGHT
160 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
161 #define AST_FIRE BUTTON_REW
162 #define AST_FIRE_REP BUTTON_REW | BUTTON_REPEAT
164 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
165 #define AST_PAUSE BUTTON_PLAY
166 #define AST_QUIT BUTTON_BACK
167 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
168 #define AST_THRUST BUTTON_UP
169 #define AST_HYPERSPACE BUTTON_DOWN
170 #define AST_LEFT BUTTON_LEFT
171 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
172 #define AST_RIGHT BUTTON_RIGHT
173 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
174 #define AST_FIRE BUTTON_SELECT
175 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
177 #elif (CONFIG_KEYPAD == MROBE100_PAD)
178 #define AST_PAUSE BUTTON_DISPLAY
179 #define AST_QUIT BUTTON_POWER
180 #define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
181 #define AST_THRUST BUTTON_UP
182 #define AST_HYPERSPACE BUTTON_DOWN
183 #define AST_LEFT BUTTON_LEFT
184 #define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
185 #define AST_RIGHT BUTTON_RIGHT
186 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
187 #define AST_FIRE BUTTON_SELECT
188 #define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
190 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
191 #define AST_PAUSE BUTTON_RC_PLAY
192 #define AST_QUIT BUTTON_RC_REC
193 #define AST_THRUST_REP BUTTON_RC_VOL_UP | BUTTON_REPEAT
194 #define AST_THRUST BUTTON_RC_VOL_UP
195 #define AST_HYPERSPACE BUTTON_RC_VOL_DOWN
196 #define AST_LEFT BUTTON_RC_REW
197 #define AST_LEFT_REP (BUTTON_RC_REW | BUTTON_REPEAT)
198 #define AST_RIGHT BUTTON_RC_FF
199 #define AST_RIGHT_REP (BUTTON_RC_FF | BUTTON_REPEAT)
200 #define AST_FIRE BUTTON_RC_MODE
201 #define AST_FIRE_REP (BUTTON_RC_MODE | BUTTON_REPEAT)
203 #elif (CONFIG_KEYPAD == COWOND2_PAD)
204 #define AST_QUIT BUTTON_POWER
207 #error No keymap defined!
212 #define AST_PAUSE BUTTON_CENTER
215 #define AST_QUIT BUTTON_TOPLEFT
217 #ifndef AST_THRUST_REP
218 #define AST_THRUST_REP (BUTTON_TOPMIDDLE | BUTTON_REPEAT)
221 #define AST_THRUST BUTTON_TOPMIDDLE
223 #ifndef AST_HYPERSPACE
224 #define AST_HYPERSPACE BUTTON_TOPRIGHT
227 #define AST_LEFT BUTTON_MIDLEFT
230 #define AST_LEFT_REP (BUTTON_MIDLEFT | BUTTON_REPEAT)
233 #define AST_RIGHT BUTTON_MIDRIGHT
235 #ifndef AST_RIGHT_REP
236 #define AST_RIGHT_REP (BUTTON_MIDRIGHT | BUTTON_REPEAT)
239 #define AST_FIRE BUTTON_BOTTOMMIDDLE
242 #define AST_FIRE_REP (BUTTON_BOTTOMMIDDLE | BUTTON_MENU)
246 #define ABS(x) ((x)>0?(x):-(x))
248 #define RES MAX(LCD_WIDTH, LCD_HEIGHT)
249 #define LARGE_LCD RES >= 200
250 #define ENEMY_MISSILE_SURVIVAL_LENGTH RES/2
251 #define ASTEROID_SPEED RES/20
252 #define MISSILE_SURVIVAL_LENGTH 40
254 #define EXTRA_LIFE 250
256 #define MISSILE_SCALE 5000
258 #define EXPLOSION_LENGTH 20
260 #define HISCORE_FILE PLUGIN_GAMES_DIR "/astrorocks.hs"
262 #define MAX_NUM_ASTEROIDS 25
263 #define MAX_NUM_MISSILES 6
264 #define ENEMY_BIG_PROBABILITY_START 10
265 #define ENEMY_APPEAR_PROBABILITY_START 35
266 #define ENEMY_APPEAR_TIMING_START 1800
267 #define LITTLE_SHIP 2
269 #define SHOW_GAME_OVER_TIME 100
270 #define SHOW_LEVEL_TIME 50
271 #define START_LIVES 3
272 #define START_LEVEL 1
273 #define NUM_ASTEROID_VERTICES 10
274 #define NUM_SHIP_VERTICES 4
275 #define NUM_ENEMY_VERTICES 6
276 #define MAX_LEVEL MAX_NUM_ASTEROIDS
277 #define ENEMY_SPEED 4
278 #define ENEMY_START_X 0
279 #define ENEMY_START_Y 0
280 #define SIZE_ENEMY_COLLISION 5*SCALE
281 #define ATTRACT_FLIP_TIME 100
283 #define NUM_TRAIL_POINTS 70
284 #define NUM_ROTATIONS 16
286 #define SIN_COS_SCALE 10000
288 #define FAST_ROT_CW_SIN 873
289 #define FAST_ROT_CW_COS 9963
290 #define FAST_ROT_ACW_SIN -873
291 #define FAST_ROT_ACW_COS 9963
293 #define MEDIUM_ROT_CW_SIN 350
294 #define MEDIUM_ROT_CW_COS 9994
295 #define MEDIUM_ROT_ACW_SIN -350
296 #define MEDIUM_ROT_ACW_COS 9994
298 #define SLOW_ROT_CW_SIN 350
299 #define SLOW_ROT_CW_COS 9994
300 #define SLOW_ROT_ACW_SIN - 350
301 #define SLOW_ROT_ACW_COS 9994
303 #ifdef HAVE_LCD_COLOR
304 #define SHIP_ROT_CW_SIN 2419
305 #define SHIP_ROT_CW_COS 9702
306 #define SHIP_ROT_ACW_SIN -2419
307 #define SHIP_ROT_ACW_COS 9702
309 #define SHIP_ROT_CW_SIN 3827
310 #define SHIP_ROT_CW_COS 9239
311 #define SHIP_ROT_ACW_SIN -3827
312 #define SHIP_ROT_ACW_COS 9239
316 #define SCALED_WIDTH (LCD_WIDTH*SCALE)
317 #define SCALED_HEIGHT (LCD_HEIGHT*SCALE)
318 #define CENTER_LCD_X (LCD_WIDTH/2)
319 #define CENTER_LCD_Y (LCD_HEIGHT/2)
321 #define SHIP_EXPLOSION_COLOUR 1
322 #define ASTEROID_EXPLOSION_COLOUR 2
323 #define ENEMY_EXPLOSION_COLOUR 3
324 #define THRUST_COLOUR 4
326 #define ASTEROID_R 230
327 #define ASTEROID_G 200
328 #define ASTEROID_B 100
339 #ifdef HAVE_LCD_COLOR
340 #define COL_MISSILE LCD_RGBPACK(200,0,0)
341 #define COL_PLAYER LCD_RGBPACK(200,200,200)
342 #define COL_STARS LCD_WHITE
343 #define COL_ASTEROID LCD_RGBPACK(ASTEROID_R,ASTEROID_G,ASTEROID_B)
344 #define COL_TEXT LCD_RGBPACK(200,200,255)
345 #define COL_ENEMY LCD_RGBPACK(ENEMY_R,ENEMY_G,ENEMY_B)
346 #define SET_FG rb->lcd_set_foreground
347 #define SET_BG rb->lcd_set_background
353 /* The array of points that make up an asteroid */
354 static const short asteroid_one
[NUM_ASTEROID_VERTICES
*2] =
368 /* The array of points that make up an asteroid */
369 static const short asteroid_two
[NUM_ASTEROID_VERTICES
*2] =
383 /* The array of points that make up an asteroid */
384 static const short asteroid_three
[NUM_ASTEROID_VERTICES
*2] =
398 /* The array od points the make up the ship */
399 static const short ship_vertices
[NUM_SHIP_VERTICES
*2] =
414 /* The array of points the make up the bad spaceship */
415 static const short enemy_vertices
[NUM_ENEMY_VERTICES
*2] =
469 struct Point position
;
476 /* Asteroid structure, contains an array of points */
479 enum asteroid_type type
;
481 struct Point position
;
482 struct Point vertices
[NUM_ASTEROID_VERTICES
];
486 int explode_countdown
;
491 struct Point vertices
[NUM_SHIP_VERTICES
];
492 struct Point position
;
493 bool waiting_for_space
;
494 int explode_countdown
;
499 struct Point vertices
[NUM_ENEMY_VERTICES
];
500 struct Point position
;
501 int explode_countdown
;
502 long last_time_appeared
;
503 short size_probability
;
504 short appear_probability
;
510 struct Point position
;
511 struct Point oldpoint
;
515 static enum game_state game_state
;
516 static int asteroid_count
;
517 static int next_missile_count
;
518 static int next_thrust_count
;
519 static int num_lives
;
520 static int extra_life
;
521 static int show_level_timeout
;
522 static int attract_flip_timeout
;
523 static int show_game_over
;
524 static int current_level
;
525 static int current_score
;
526 static int high_score
;
527 static int space_check_size
= 30*SCALE
;
529 static bool enemy_on_screen
;
530 static char phscore
[30];
531 static struct Ship ship
;
532 static struct Point stars
[NUM_STARS
];
533 static struct Asteroid asteroids_array
[MAX_NUM_ASTEROIDS
];
534 static struct Missile missiles_array
[MAX_NUM_MISSILES
];
535 static struct Missile enemy_missile
;
536 static struct Enemy enemy
;
537 static struct Point lives_points
[NUM_SHIP_VERTICES
];
538 static struct TrailPoint trailPoints
[NUM_TRAIL_POINTS
];
540 void draw_and_move_asteroids(void);
541 void initialise_game(int nStartNum
);
543 bool is_asteroid_near_ship(struct Asteroid
* asteroid
);
544 bool is_point_within_asteroid(struct Asteroid
* asteroid
, struct Point
* point
);
546 void initialise_asteroid(struct Asteroid
* asteroid
, enum asteroid_type eType
);
547 void draw_polygon(struct Point
* vertices
, int px
, int py
, int num_vertices
);
548 void rotate_asteroid(struct Asteroid
* asteroid
);
549 void create_asteroid(enum asteroid_type type
, int x
, int y
);
550 void create_stars(void);
552 void initialise_ship(void);
553 void draw_and_move_ship(void);
554 void rotate_ship(int s
, int c
);
555 void thrust_ship(void);
557 void initialise_missile(struct Missile
* missile
);
558 void draw_and_move_missiles(void);
559 void fire_missile(void);
561 void animate_and_draw_explosion(struct Point
* point
, int num_points
, int xoffset
, int yoffset
);
562 void initialise_explosion(struct Point
* point
, int num_points
);
564 void move_point(struct Point
* point
);
565 void hyperspace(void);
566 void check_collisions(void);
567 void initialise_enemy(void);
568 void draw_and_move_enemy(void);
569 void draw_lives(void);
570 void drawstars(void);
571 bool is_ship_within_asteroid(struct Asteroid
* asteroid
);
575 /*Hi-Score reading and writing to file - this needs moving to the hi-score plugin lib as
582 /* clear the buffer we're about to load the highscore data into */
583 rb
->memset(phscore
, 0, sizeof(phscore
));
585 fd
= rb
->open(HISCORE_FILE
,O_RDWR
| O_CREAT
);
588 rb
->splash(HZ
, "Highscore file read error");
592 /* highscore used to %d, is now %d\n
593 Deal with no file or bad file */
594 rb
->read(fd
,phscore
, sizeof(phscore
));
596 compare
= rb
->atoi(phscore
);
598 if(high_score
> compare
)
600 rb
->lseek(fd
,0,SEEK_SET
);
601 rb
->fdprintf(fd
, "%d\n", high_score
);
604 high_score
= compare
;
609 bool point_in_poly(struct Point
* _point
, int num_vertices
, int x
, int y
)
618 pj
+= num_vertices
-1;
623 if((((pi
->y
<= y
) && (y
< pj
->y
)) || ((pj
->y
<= y
) && (y
< pi
->y
))) &&
624 (x
< (pj
->x
- pi
->x
) * (y
- pi
->y
) / (pj
->y
- pi
->y
) + pi
->x
))
627 if(n
== num_vertices
- 1)
638 void move_point(struct Point
* point
)
640 point
->x
+= point
->dx
;
641 point
->y
+= point
->dy
;
643 /*check bounds on the x-axis:*/
644 if(point
->x
>= SCALED_WIDTH
)
646 else if(point
->x
<= 0)
647 point
->x
= SCALED_WIDTH
;
649 /*Check bounds on the y-axis:*/
650 if(point
->y
>= SCALED_HEIGHT
)
652 else if(point
->y
<= 0)
653 point
->y
= SCALED_HEIGHT
;
656 void create_trail(struct TrailPoint
* tpoint
)
658 tpoint
->position
.dx
= -( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/10;
659 tpoint
->position
.dy
= -( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/10;
662 void create_explosion_trail(struct TrailPoint
* tpoint
)
664 tpoint
->position
.dx
= (rb
->rand()%5050)-2500;
665 tpoint
->position
.dy
= (rb
->rand()%5050)-2500;
668 void create_trail_blaze(int colour
, struct Point
* position
)
671 struct TrailPoint
* tpoint
;
674 if(colour
!= SHIP_EXPLOSION_COLOUR
)
676 numtoadd
= NUM_TRAIL_POINTS
/5;
682 numtoadd
= NUM_TRAIL_POINTS
/8;
683 xadd
= ship
.position
.x
;
684 yadd
= ship
.position
.y
;
687 /* give the point a random countdown timer, so they dissapears at different times */
688 tpoint
= trailPoints
;
689 n
= NUM_TRAIL_POINTS
;
692 if(tpoint
->alive
<= 0 && numtoadd
)
695 /* take a random x point anywhere between bottom two points of ship. */
696 /* ship.position.x; */
697 tpoint
->position
.x
= (ship
.vertices
[2].x
+ (rb
->rand()%18000)-9000) + position
->x
;
698 tpoint
->position
.y
= (ship
.vertices
[2].y
+ (rb
->rand()%18000)-9000) + position
->y
;
702 case SHIP_EXPLOSION_COLOUR
:
706 create_explosion_trail(tpoint
);
710 case ASTEROID_EXPLOSION_COLOUR
:
711 tpoint
->r
= ASTEROID_R
;
712 tpoint
->g
= ASTEROID_G
;
713 tpoint
->b
= ASTEROID_B
;
714 create_explosion_trail(tpoint
);
718 case ENEMY_EXPLOSION_COLOUR
:
722 create_explosion_trail(tpoint
);
727 tpoint
->r
= THRUST_R
;
728 tpoint
->g
= THRUST_G
;
729 tpoint
->b
= THRUST_B
;
730 create_trail(tpoint
);
735 /* add a proportional bit to the x and y based on dx and dy */
737 /* give the points a speed based on direction of travel - i.e. opposite */
738 tpoint
->position
.dx
+= position
->dx
;
739 tpoint
->position
.dy
+= position
->dy
;
745 /* find a space in the array of trail_points that is NULL or DEAD or whatever.
746 and place this one here. */
750 void draw_trail_blaze(void)
752 struct TrailPoint
* tpoint
;
753 /* loop through, if alive then move and draw.
754 when drawn, countdown it's timer.
756 tpoint
= trailPoints
;
757 int n
= NUM_TRAIL_POINTS
;
763 if(game_state
!= PAUSE_MODE
)
766 move_point(&(tpoint
->position
));
768 #ifdef HAVE_LCD_COLOR
769 /* intensity = tpoint->alive/2; */
770 if(tpoint
->r
>0)tpoint
->r
-=tpoint
->dec
;
771 if(tpoint
->g
>0)tpoint
->g
-=tpoint
->dec
;
772 if(tpoint
->b
>0)tpoint
->b
-=tpoint
->dec
;
773 SET_FG(LCD_RGBPACK(tpoint
->r
, tpoint
->g
, tpoint
->b
));
775 rb
->lcd_drawpixel(tpoint
->position
.x
/SCALE
, tpoint
->position
.y
/SCALE
);
781 /*Check if point is within a rectangle*/
782 bool is_point_within_rectangle(struct Point
* rect
, struct Point
* p
, int size
)
785 int aTLx
= rect
->x
- size
;
786 int aTLy
= rect
->y
- size
;
787 int aBRx
= rect
->x
+ size
;
788 int aBRy
= rect
->y
+ size
;
789 rb
->lcd_hline( aTLx
/SCALE
, aBRx
/SCALE
, aTLy
/SCALE
);
790 rb
->lcd_vline( aTLx
/SCALE
, aTLy
/SCALE
, aBRy
/SCALE
);
791 rb
->lcd_hline( aTLx
/SCALE
, aBRx
/SCALE
, aBRy
/SCALE
);
792 rb
->lcd_vline( aBRx
/SCALE
, aBRy
/SCALE
, aTLy
/SCALE
);
793 return (p
->x
> aTLx
&& p
->x
< aBRx
&& p
->y
> aTLy
&& p
->y
< aBRy
);
795 return (p
->x
> rect
->x
- size
&& p
->x
< rect
->x
+ size
&&
796 p
->y
> rect
->y
- size
&& p
->y
< rect
->y
+ size
);
801 void draw_polygon(struct Point
* vertices
, int px
, int py
, int num_vertices
)
803 int n
, t1
, t2
, oldX
, oldY
;
805 bool bDrawAll
= px
< WRAP_GAP
|| LCD_WIDTH
- px
< WRAP_GAP
||
806 py
< WRAP_GAP
|| LCD_HEIGHT
- py
< WRAP_GAP
;
810 oldX
= p
->x
/SCALE
+ px
;
811 oldY
= p
->y
/SCALE
+ py
;
813 for(n
= num_vertices
+1; --n
;)
815 t1
= p
->x
/SCALE
+ px
;
816 t2
= p
->y
/SCALE
+ py
;
818 rb
->lcd_drawline(oldX
, oldY
, t1
, t2
);
822 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
, t1
- LCD_WIDTH
, t2
);
823 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
, t1
+ LCD_WIDTH
, t2
);
824 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
+ LCD_HEIGHT
,
825 t1
- LCD_WIDTH
, t2
+ LCD_HEIGHT
);
826 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
+ LCD_HEIGHT
,
827 t1
+ LCD_WIDTH
, t2
+ LCD_HEIGHT
);
829 rb
->lcd_drawline(oldX
, oldY
- LCD_HEIGHT
, t1
, t2
- LCD_HEIGHT
);
830 rb
->lcd_drawline(oldX
, oldY
+ LCD_HEIGHT
, t1
, t2
+ LCD_HEIGHT
);
831 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
- LCD_HEIGHT
,
832 t1
- LCD_WIDTH
, t2
- LCD_HEIGHT
);
833 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
- LCD_HEIGHT
,
834 t1
+ LCD_WIDTH
, t2
- LCD_HEIGHT
);
842 void animate_and_draw_explosion(struct Point
* point
, int num_points
,
843 int xoffset
, int yoffset
)
846 for(n
= num_points
; --n
;)
848 if(game_state
!= PAUSE_MODE
)
850 point
->x
+= point
->dx
;
851 point
->y
+= point
->dy
;
853 rb
->lcd_fillrect( point
->x
/SCALE
+ xoffset
, point
->y
/SCALE
+ yoffset
,
854 POINT_SIZE
, POINT_SIZE
);
859 /*stop movement of ship, 'cos that's what happens when you go into hyperspace.*/
860 void hyperspace(void)
862 ship
.position
.dx
= ship
.position
.dy
= 0;
863 ship
.position
.x
= (rb
->rand()%SCALED_WIDTH
);
864 ship
.position
.y
= (rb
->rand()%SCALED_HEIGHT
);
867 void initialise_enemy(void)
873 if(rb
->rand()%100 > enemy
.size_probability
)
876 enemy
.size_probability
++;
877 if(enemy
.size_probability
< 90)
879 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
887 enemy_missile
.survived
= 0;
888 enemy_on_screen
= true;
889 enemy
.explode_countdown
= 0;
890 enemy
.last_time_appeared
= *rb
->current_tick
;
891 point
= enemy
.vertices
;
892 for(n
= 0; n
< NUM_ENEMY_VERTICES
+NUM_ENEMY_VERTICES
; n
+=2)
894 point
->x
= enemy_vertices
[n
];
895 point
->y
= enemy_vertices
[n
+1];
896 point
->x
*= SCALE
/size
;
897 point
->y
*= SCALE
/size
;
901 if(ship
.position
.x
>= SCALED_WIDTH
/2)
903 enemy
.position
.dx
= ENEMY_SPEED
;
904 enemy
.position
.x
= 0;
908 enemy
.position
.dx
= -ENEMY_SPEED
;
909 enemy
.position
.x
= SCALED_WIDTH
;
912 if(ship
.position
.y
>= SCALED_HEIGHT
/2)
914 enemy
.position
.dy
= ENEMY_SPEED
;
915 enemy
.position
.y
= 0;
919 enemy
.position
.dy
= -ENEMY_SPEED
;
920 enemy
.position
.y
= SCALED_HEIGHT
;
923 enemy
.position
.dx
*= SCALE
/10;
924 enemy
.position
.dy
*= SCALE
/10;
927 void draw_and_move_enemy(void)
929 int enemy_x
, enemy_y
;
936 enemy_x
= enemy
.position
.x
/SCALE
;
937 enemy_y
= enemy
.position
.y
/SCALE
;
938 if(!enemy
.explode_countdown
)
940 point
= enemy
.vertices
;
941 draw_polygon(enemy
.vertices
, enemy_x
, enemy_y
, NUM_ENEMY_VERTICES
);
942 rb
->lcd_drawline(enemy
.vertices
[0].x
/SCALE
+ enemy_x
,
943 enemy
.vertices
[0].y
/SCALE
+ enemy_y
,
944 enemy
.vertices
[3].x
/SCALE
+ enemy_x
,
945 enemy
.vertices
[3].y
/SCALE
+ enemy_y
);
947 if(game_state
!= PAUSE_MODE
)
949 enemy
.position
.x
+= enemy
.position
.dx
;
950 enemy
.position
.y
+= enemy
.position
.dy
;
953 if(enemy
.position
.x
> SCALED_WIDTH
|| enemy
.position
.x
< 0)
954 enemy_on_screen
= false;
956 if(enemy
.position
.y
> SCALED_HEIGHT
)
957 enemy
.position
.y
= 0;
958 else if(enemy
.position
.y
< 0)
959 enemy
.position
.y
= SCALED_HEIGHT
;
961 if( (rb
->rand()%1000) < 10)
962 enemy
.position
.dy
= -enemy
.position
.dy
;
967 /* animate_and_draw_explosion(enemy.vertices, NUM_ENEMY_VERTICES,
968 enemy_x, enemy.position.y/SCALE); */
969 if(game_state
!= PAUSE_MODE
)
971 enemy
.explode_countdown
--;
972 if(!enemy
.explode_countdown
)
973 enemy_on_screen
= false;
979 if( (*rb
->current_tick
- enemy
.last_time_appeared
) > enemy
.appear_timing
)
980 if(rb
->rand()%100 > enemy
.appear_probability
) initialise_enemy();
983 if(!enemy_missile
.survived
&& game_state
!= GAME_OVER
)
985 /*if no missile and the enemy is here and not exploding..then shoot baby!*/
986 if( !enemy
.explode_countdown
&& enemy_on_screen
&&
987 !ship
.waiting_for_space
&& (rb
->rand()%10) > 5 )
989 enemy_missile
.position
.x
= enemy
.position
.x
;
990 enemy_missile
.position
.y
= enemy
.position
.y
;
992 /*lame, needs to be sorted - it's trying to shoot at the ship*/
993 if(ABS(enemy
.position
.y
- ship
.position
.y
) <= 5*SCALE
)
995 enemy_missile
.position
.dy
= 0;
999 if( enemy
.position
.y
< ship
.position
.y
)
1000 enemy_missile
.position
.dy
= 1;
1002 enemy_missile
.position
.dy
= -1;
1005 if(ABS(enemy
.position
.x
- ship
.position
.x
) <= 5*SCALE
)
1006 enemy_missile
.position
.dx
= 0;
1009 if( enemy
.position
.x
< ship
.position
.x
)
1010 enemy_missile
.position
.dx
= 1;
1012 enemy_missile
.position
.dx
= -1;
1015 if(enemy_missile
.position
.dx
== 0 &&
1016 enemy_missile
.position
.dy
== 0)
1017 enemy_missile
.position
.dx
= enemy_missile
.position
.dy
= -1;
1019 enemy_missile
.position
.dx
*= SCALE
;
1020 enemy_missile
.position
.dy
*= SCALE
;
1021 enemy_missile
.survived
= ENEMY_MISSILE_SURVIVAL_LENGTH
;
1027 rb
->lcd_fillrect( enemy_missile
.position
.x
/SCALE
,
1028 enemy_missile
.position
.y
/SCALE
,
1029 POINT_SIZE
, POINT_SIZE
);
1030 if(game_state
!= PAUSE_MODE
)
1032 move_point(&enemy_missile
.position
);
1033 enemy_missile
.survived
--;
1039 * Lame method of collision
1040 * detection. It's checking for collision
1041 * between point and a big rectangle around the asteroid...
1042 *******************/
1043 bool is_point_within_asteroid(struct Asteroid
* asteroid
, struct Point
* point
)
1045 if( !is_point_within_rectangle(&asteroid
->position
, point
,
1046 asteroid
->radius
+4*SCALE
) )
1049 if(point_in_poly(asteroid
->vertices
, NUM_ASTEROID_VERTICES
,
1050 point
->x
- asteroid
->position
.x
,
1051 point
->y
- asteroid
->position
.y
))
1053 switch(asteroid
->type
)
1056 asteroid
->explode_countdown
= EXPLOSION_LENGTH
;
1057 create_trail_blaze(ASTEROID_EXPLOSION_COLOUR
, &asteroid
->position
);
1061 create_asteroid(MEDIUM
, asteroid
->position
.x
,
1062 asteroid
->position
.y
);
1063 create_asteroid(MEDIUM
, asteroid
->position
.x
,
1064 asteroid
->position
.y
);
1068 create_asteroid(SMALL
, asteroid
->position
.x
, asteroid
->position
.y
);
1069 create_asteroid(SMALL
, asteroid
->position
.x
, asteroid
->position
.y
);
1074 if(current_score
> extra_life
)
1077 extra_life
= current_score
+EXTRA_LIFE
;
1080 asteroid
->exists
= false;
1087 bool is_point_within_enemy(struct Point
* point
)
1089 if( is_point_within_rectangle(&enemy
.position
, point
, 7*SCALE
) )
1092 /*enemy_missile.survived = 0;*/
1093 enemy
.explode_countdown
= EXPLOSION_LENGTH
;
1094 /* initialise_explosion(enemy.vertices, NUM_ENEMY_VERTICES); */
1095 create_trail_blaze(ENEMY_EXPLOSION_COLOUR
, &enemy
.position
);
1102 bool is_ship_within_asteroid(struct Asteroid
* asteroid
)
1107 p
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1108 p
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1109 hit
|= is_point_within_asteroid(asteroid
, &p
);
1113 p
.x
= ship
.position
.x
+ ship
.vertices
[1].x
;
1114 p
.y
= ship
.position
.y
+ ship
.vertices
[1].y
;
1115 hit
|= is_point_within_asteroid(asteroid
, &p
);
1118 p
.x
= ship
.position
.x
+ ship
.vertices
[3].x
;
1119 p
.y
= ship
.position
.y
+ ship
.vertices
[3].y
;
1120 hit
|= is_point_within_asteroid(asteroid
, &p
);
1127 void initialise_explosion(struct Point
* point
, int num_points
)
1131 point
->x
+= point
->dx
;
1132 point
->y
+= point
->dy
;
1133 for(n
= num_points
; --n
;)
1135 point
->dx
= point
->x
;
1136 point
->dy
= point
->y
;
1142 /* Check for collsions between the missiles and the asteroids and the ship */
1143 void check_collisions(void)
1146 bool asteroids_onscreen
= false;
1147 struct Missile
* missile
;
1148 struct Asteroid
* asteroid
;
1149 bool ship_cant_be_placed
= false;
1151 asteroid
= asteroids_array
;
1152 m
= MAX_NUM_ASTEROIDS
;
1155 /*if the asteroids exists then test missile collision:*/
1156 if(asteroid
->exists
)
1158 missile
= missiles_array
;
1159 n
= MAX_NUM_MISSILES
;
1162 /*if the missiles exists:*/
1163 if(missile
->survived
> 0)
1165 /*has the missile hit the asteroid?*/
1166 if(is_point_within_asteroid(asteroid
, &missile
->position
)
1167 || is_point_within_asteroid(asteroid
,
1168 &missile
->oldpoint
))
1170 missile
->survived
= 0;
1177 /*now check collision with ship:*/
1178 if(asteroid
->exists
&& !ship
.waiting_for_space
&& !ship
.explode_countdown
)
1180 if(is_ship_within_asteroid(asteroid
))
1183 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1184 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1185 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1188 /*has the enemy missile blown something up?*/
1189 if(asteroid
->exists
&& enemy_missile
.survived
)
1191 if(is_point_within_asteroid(asteroid
, &enemy_missile
.position
))
1193 /*take that score back then:*/
1194 if(current_score
> 0) current_score
--;
1195 enemy_missile
.survived
= 0;
1198 /*if it still exists, check if ship is waiting for space:*/
1199 if(asteroid
->exists
&& ship
.waiting_for_space
)
1200 ship_cant_be_placed
|=
1201 is_point_within_rectangle(&ship
.position
,
1202 &asteroid
->position
,
1207 /*is an asteroid still exploding?*/
1208 if(asteroid
->explode_countdown
)
1209 asteroids_onscreen
= true;
1214 /*now check collision between ship and enemy*/
1215 if(enemy_on_screen
&& !ship
.waiting_for_space
&&
1216 !ship
.explode_countdown
&& !enemy
.explode_countdown
)
1218 /*has the enemy collided with the ship?*/
1219 if(is_point_within_enemy(&ship
.position
))
1221 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1222 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1223 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1224 create_trail_blaze(ENEMY_EXPLOSION_COLOUR
, &enemy
.position
);
1227 /*Now see if the enemy has been shot at by the ships missiles:*/
1228 missile
= missiles_array
;
1229 n
= MAX_NUM_MISSILES
;
1232 if(missile
->survived
> 0 &&
1233 is_point_within_enemy(&missile
->position
))
1235 missile
->survived
= 0;
1242 /*test collision with enemy missile and ship:*/
1243 if(!ship_cant_be_placed
&& enemy_missile
.survived
> 0 &&
1244 point_in_poly(ship
.vertices
, NUM_SHIP_VERTICES
,
1245 enemy_missile
.position
.x
- ship
.position
.x
,
1246 enemy_missile
.position
.y
- ship
.position
.y
))
1248 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1249 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1250 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1251 enemy_missile
.survived
= 0;
1252 enemy_missile
.position
.x
= enemy_missile
.position
.y
= 0;
1255 if(!ship_cant_be_placed
)
1256 ship
.waiting_for_space
= false;
1258 /*if all asteroids cleared then start again:*/
1259 if(asteroid_count
== 0 && !enemy_on_screen
&& !asteroids_onscreen
)
1262 game_state
= SHOW_LEVEL
;
1263 enemy
.appear_probability
+= 5;
1264 enemy
.appear_timing
-= 200;
1265 if( enemy
.appear_probability
> 100)
1266 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1267 show_level_timeout
= SHOW_LEVEL_TIME
;
1271 /*************************************************
1272 ** Creates a new asteroid of the given 4type (size)
1273 ** and at the given location.
1274 *************************************************/
1275 void create_asteroid(enum asteroid_type type
, int x
, int y
)
1277 struct Asteroid
* asteroid
;
1280 asteroid
= asteroids_array
;
1281 n
= MAX_NUM_ASTEROIDS
;
1284 if(!asteroid
->exists
&& !asteroid
->explode_countdown
)
1286 initialise_asteroid(asteroid
, type
);
1287 asteroid
->position
.x
= x
;
1288 asteroid
->position
.y
= y
;
1295 /* Initialise a missile */
1296 void initialise_missile(struct Missile
* missile
)
1298 missile
->position
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1299 missile
->position
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1300 missile
->position
.dx
= (ship
.vertices
[0].x
- ship
.vertices
[2].x
)/2;
1301 missile
->position
.dy
= (ship
.vertices
[0].y
- ship
.vertices
[2].y
)/2;
1302 missile
->survived
= MISSILE_SURVIVAL_LENGTH
;
1303 missile
->oldpoint
.x
= missile
->position
.x
;
1304 missile
->oldpoint
.y
= missile
->position
.y
;
1307 /* Draw and Move all the missiles */
1308 void draw_and_move_missiles(void)
1314 struct Missile
* missile
;
1315 missile
= missiles_array
;
1317 SET_FG(COL_MISSILE
);
1319 n
= MAX_NUM_MISSILES
;
1322 if(missile
->survived
)
1324 if(missile
->position
.dx
> 0)
1326 if(missile
->position
.x
>= missile
->oldpoint
.x
)
1328 p1x
= missile
->oldpoint
.x
;
1329 p2x
= missile
->position
.x
;
1334 p2x
= missile
->position
.x
;
1339 if(missile
->oldpoint
.x
>= missile
->position
.x
)
1341 p1x
= missile
->oldpoint
.x
;
1342 p2x
= missile
->position
.x
;
1346 p1x
= missile
->oldpoint
.x
;
1351 if(missile
->position
.dy
> 0)
1353 if(missile
->position
.y
>= missile
->oldpoint
.y
)
1355 p1y
= missile
->oldpoint
.y
;
1356 p2y
= missile
->position
.y
;
1361 p2y
= missile
->position
.y
;
1366 if(missile
->oldpoint
.y
>= missile
->position
.y
)
1368 p1y
= missile
->oldpoint
.y
;
1369 p2y
= missile
->position
.y
;
1373 p1y
= missile
->oldpoint
.y
;
1378 rb
->lcd_drawline( p1x
/SCALE
, p1y
/SCALE
, p2x
/SCALE
, p2y
/SCALE
);
1380 if(game_state
!= PAUSE_MODE
)
1382 missile
->oldpoint
.x
= missile
->position
.x
;
1383 missile
->oldpoint
.y
= missile
->position
.y
;
1384 move_point(&missile
->position
);
1385 missile
->survived
--;
1392 void draw_lives(void)
1395 int px
= (LCD_WIDTH
- num_lives
*4 - 1);
1397 int py
= (LCD_HEIGHT
-6);
1399 int py
= (LCD_HEIGHT
-4);
1407 draw_polygon(lives_points
, px
, py
, NUM_SHIP_VERTICES
);
1416 /*Fire the next missile*/
1417 void fire_missile(void)
1420 struct Missile
* missile
;
1422 if(!ship
.explode_countdown
&& !ship
.waiting_for_space
)
1424 missile
= missiles_array
;
1425 n
= MAX_NUM_MISSILES
;
1428 if(!missile
->survived
)
1430 initialise_missile(missile
);
1438 /* Initialise the passed Asteroid */
1439 void initialise_asteroid(struct Asteroid
* asteroid
, enum asteroid_type type
)
1443 struct Point
* point
;
1444 asteroid
->exists
= true;
1445 asteroid
->type
= type
;
1446 asteroid
->explode_countdown
= 0;
1448 /*Set the radius of the asteroid:*/
1449 asteroid
->radius
= (int)type
*SCALE
;
1451 /*shall we move Clockwise and Fast*/
1452 if((rb
->rand()%100)>75)
1454 asteroid
->speed_cos
= FAST_ROT_CW_COS
;
1455 asteroid
->speed_sin
= FAST_ROT_CW_SIN
;
1457 else if((rb
->rand()%100)>75)
1459 asteroid
->speed_cos
= FAST_ROT_ACW_COS
;
1460 asteroid
->speed_sin
= FAST_ROT_ACW_SIN
;
1462 else if((rb
->rand()%100)>75)
1464 asteroid
->speed_cos
= SLOW_ROT_ACW_COS
;
1465 asteroid
->speed_sin
= SLOW_ROT_ACW_SIN
;
1469 asteroid
->speed_cos
= SLOW_ROT_CW_COS
;
1470 asteroid
->speed_sin
= SLOW_ROT_CW_SIN
;
1473 b
= (rb
->rand()%100)>66;
1474 b2
= (rb
->rand()%100)>66;
1475 point
= asteroid
->vertices
;
1476 for(n
= 0; n
< NUM_ASTEROID_VERTICES
*2; n
+=2)
1480 point
->x
= asteroid_one
[n
];
1481 point
->y
= asteroid_one
[n
+1];
1485 point
->x
= asteroid_two
[n
];
1486 point
->y
= asteroid_two
[n
+1];
1490 point
->x
= asteroid_three
[n
];
1491 point
->y
= asteroid_three
[n
+1];
1494 point
->x
*= asteroid
->radius
/6;
1495 point
->y
*= asteroid
->radius
/6;
1500 asteroid
->radius
+= 6*SCALE
;
1501 if(asteroid
->type
== SMALL
)
1502 asteroid
->radius
/= 3;/*2*/
1503 else if(asteroid
->type
== LARGE
)
1504 asteroid
->radius
+= 3*SCALE
;/*2*/
1508 /*Set the position randomly:*/
1509 asteroid
->position
.x
= (rb
->rand()%SCALED_WIDTH
);
1510 asteroid
->position
.y
= (rb
->rand()%SCALED_HEIGHT
);
1512 asteroid
->position
.dx
= 0;
1513 while(asteroid
->position
.dx
== 0)
1514 asteroid
->position
.dx
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
1516 asteroid
->position
.dy
= 0;
1517 while(asteroid
->position
.dy
== 0)
1518 asteroid
->position
.dy
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
1520 asteroid
->position
.dx
*= SCALE
/10;
1521 asteroid
->position
.dy
*= SCALE
/10;
1523 b
= is_point_within_rectangle(&ship
.position
, &asteroid
->position
,
1527 /*Now rotate the asteroid a bit, so they all look a bit different*/
1528 for(n
=(rb
->rand()%30) + 2;--n
;)
1529 rotate_asteroid(asteroid
);
1531 /*great, we've created an asteroid, don't forget to increment the total:*/
1535 /*Initialise the ship*/
1536 void initialise_ship(void)
1538 struct Point
* point
;
1539 struct Point
* lives_point
;
1542 ship
.position
.x
= CENTER_LCD_X
;
1543 ship
.position
.y
= CENTER_LCD_Y
;
1544 ship
.position
.x
*= SCALE
;
1545 ship
.position
.y
*= SCALE
;
1546 ship
.position
.dx
= ship
.position
.dy
= 0;
1548 point
= ship
.vertices
;
1549 lives_point
= lives_points
;
1550 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+=2)
1552 point
->x
= ship_vertices
[n
];
1553 point
->y
= ship_vertices
[n
+1];
1560 ship
.position
.dx
= 0;
1561 ship
.position
.dy
= 0;
1562 ship
.explode_countdown
= 0;
1564 /*grab a copy of the ships points for the lives display:*/
1565 point
= ship
.vertices
;
1566 lives_point
= lives_points
;
1567 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+=2)
1569 lives_point
->x
= point
->x
;
1570 lives_point
->y
= point
->y
;
1576 void rotate_asteroid(struct Asteroid
* asteroid
)
1578 struct Point
* point
;
1582 point
= asteroid
->vertices
;
1583 for(n
= NUM_ASTEROID_VERTICES
+1; --n
;)
1586 point
->x
= xtemp
*asteroid
->speed_cos
/SIN_COS_SCALE
-
1587 point
->y
*asteroid
->speed_sin
/SIN_COS_SCALE
;
1588 point
->y
= point
->y
*asteroid
->speed_cos
/SIN_COS_SCALE
+
1589 xtemp
*asteroid
->speed_sin
/SIN_COS_SCALE
;
1594 /*************************************************
1595 ** Draws the ship, moves the ship and creates a new
1596 ** one if it's finished exploding.
1597 **************************************************/
1598 void draw_and_move_ship(void)
1600 int nxoffset
= ship
.position
.x
/SCALE
;
1601 int nyoffset
= ship
.position
.y
/SCALE
;
1603 if(!ship
.explode_countdown
)
1605 if(!ship
.waiting_for_space
)
1607 draw_polygon(ship
.vertices
, nxoffset
, nyoffset
, NUM_SHIP_VERTICES
);
1608 if(game_state
!= PAUSE_MODE
&& game_state
!= GAME_OVER
)
1610 move_point(&ship
.position
);
1616 /* animate_and_draw_explosion(ship.vertices, NUM_SHIP_VERTICES,
1617 ship.position.x/SCALE,
1618 ship.position.y/SCALE); */
1619 if(game_state
!= PAUSE_MODE
)
1621 ship
.explode_countdown
--;
1622 if(!ship
.explode_countdown
)
1627 show_game_over
= SHOW_GAME_OVER_TIME
;
1628 game_state
= GAME_OVER
;
1633 ship
.waiting_for_space
= true;
1640 void thrust_ship(void)
1642 if(!ship
.waiting_for_space
)
1644 ship
.position
.dx
+= ( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/20;
1645 ship
.position
.dy
+= ( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/20;
1646 /*if dx and dy are below a certain threshold, then set 'em to 0
1647 but to do this we need to ascertain if the spacehip as moved on screen
1648 for more than a certain amount. */
1650 create_trail_blaze(THRUST_COLOUR
, &ship
.position
);
1654 /**************************************************
1655 ** Rotate the ship using the passed sin & cos values
1656 ***************************************************/
1657 void rotate_ship(int c
, int s
)
1659 struct Point
* point
;
1663 if(!ship
.waiting_for_space
&& !ship
.explode_countdown
)
1665 point
= ship
.vertices
;
1666 for(n
=NUM_SHIP_VERTICES
+1;--n
;)
1669 point
->x
= xtemp
*c
/SIN_COS_SCALE
- point
->y
*s
/SIN_COS_SCALE
;
1670 point
->y
= point
->y
*c
/SIN_COS_SCALE
+ xtemp
*s
/SIN_COS_SCALE
;
1686 rb
->lcd_drawpixel(p
->x
, p
->y
);
1691 /*************************************************
1692 ** Draw And Move all Asteroids
1693 *************************************************/
1694 void draw_and_move_asteroids(void)
1697 struct Asteroid
* asteroid
;
1699 asteroid
= asteroids_array
;
1700 SET_FG(COL_ASTEROID
);
1702 n
= MAX_NUM_ASTEROIDS
;
1705 if(game_state
!= PAUSE_MODE
)
1707 if(asteroid
->exists
)
1709 move_point(&asteroid
->position
);
1710 rotate_asteroid(asteroid
);
1711 draw_polygon(asteroid
->vertices
, asteroid
->position
.x
/SCALE
,
1712 asteroid
->position
.y
/SCALE
,
1713 NUM_ASTEROID_VERTICES
);
1715 else if(asteroid
->explode_countdown
)
1717 /* animate_and_draw_explosion(asteroid->vertices,
1718 NUM_ASTEROID_VERTICES,
1719 asteroid->position.x/SCALE,
1720 asteroid->position.y/SCALE); */
1721 asteroid
->explode_countdown
--;
1726 if(asteroid
->exists
)
1727 draw_polygon(asteroid
->vertices
,
1728 asteroid
->position
.x
/SCALE
,
1729 asteroid
->position
.y
/SCALE
,
1730 NUM_ASTEROID_VERTICES
);
1736 void create_stars(void)
1738 struct TrailPoint
* tpoint
;
1746 p
->x
= (rb
->rand()%LCD_WIDTH
);
1747 p
->y
= (rb
->rand()%LCD_HEIGHT
);
1752 /* give the point a random countdown timer, so they dissapears at different
1754 tpoint
= trailPoints
;
1755 n
= NUM_TRAIL_POINTS
;
1763 /*************************************************
1764 ** Creates start_num number of new asteroids of
1766 **************************************************/
1767 void initialise_game(int start_num
)
1770 asteroid_count
= next_missile_count
= next_thrust_count
= 0;
1771 struct Asteroid
* asteroid
;
1772 struct Missile
* missile
;
1773 extra_life
= EXTRA_LIFE
;
1776 enemy_on_screen
= 0;
1777 enemy_missile
.survived
= 0;
1780 asteroid
= asteroids_array
;
1781 n
= MAX_NUM_ASTEROIDS
;
1784 asteroid
->exists
= false;
1788 /*make some LARGE asteroids*/
1789 for(n
= 0; n
< start_num
; n
++)
1790 initialise_asteroid(&asteroids_array
[n
], LARGE
);
1792 /*ensure all missiles are out of action: */
1793 missile
= missiles_array
;
1794 n
= MAX_NUM_MISSILES
;
1797 missile
->survived
=0;
1802 void start_attract_mode(void)
1804 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1805 enemy
.appear_timing
= ENEMY_APPEAR_TIMING_START
;
1807 num_lives
= START_LIVES
;
1809 attract_flip_timeout
= ATTRACT_FLIP_TIME
;
1810 game_state
= ATTRACT_MODE
;
1811 if(asteroid_count
< 3)
1812 initialise_game(current_level
);
1815 enum plugin_status
start_game(void)
1823 /*create stars once, and once only:*/
1830 /*game starts with at level 1
1832 start_attract_mode();
1837 end
= *rb
->current_tick
+ (CYCLETIME
* HZ
) / 1000;
1838 rb
->lcd_clear_display();
1843 if(attract_flip_timeout
< ATTRACT_FLIP_TIME
/2)
1845 rb
->lcd_putsxy(CENTER_LCD_X
- 39,
1846 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4,
1848 if(!attract_flip_timeout
)
1849 attract_flip_timeout
= ATTRACT_FLIP_TIME
;
1853 rb
->snprintf(s
, sizeof(s
), "Hi Score %d ", high_score
);
1854 rb
->lcd_putsxy(CENTER_LCD_X
- 30,
1855 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, s
);
1857 attract_flip_timeout
--;
1861 rb
->lcd_putsxy(CENTER_LCD_X
- 25,
1862 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, "Game Over");
1863 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1864 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1867 start_attract_mode();
1871 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1872 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1873 rb
->lcd_putsxy(CENTER_LCD_X
- 15,
1874 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, "pause");
1875 draw_and_move_missiles();
1877 draw_and_move_ship();
1881 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1882 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1883 draw_and_move_missiles();
1886 draw_and_move_ship();
1890 show_level_timeout
--;
1891 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1892 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1893 rb
->snprintf(level
, sizeof(level
), "stage %d ", current_level
);
1894 rb
->lcd_putsxy(CENTER_LCD_X
- 20,
1895 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, level
);
1896 draw_and_move_ship();
1898 if(!show_level_timeout
)
1900 initialise_game(current_level
);
1901 game_state
= PLAY_MODE
;
1908 draw_and_move_asteroids();
1909 draw_and_move_enemy();
1912 button
= rb
->button_get(false);
1914 #ifdef HAS_BUTTON_HOLD
1915 if (rb
->button_hold())
1916 game_state
= PAUSE_MODE
;
1922 if(game_state
== PLAY_MODE
)
1923 game_state
= PAUSE_MODE
;
1924 else if(game_state
== PAUSE_MODE
)
1925 game_state
= PLAY_MODE
;
1932 if(game_state
== ATTRACT_MODE
)
1934 else if(game_state
== GAME_OVER
)
1936 start_attract_mode();
1940 show_game_over
= SHOW_GAME_OVER_TIME
;
1941 game_state
= GAME_OVER
;
1945 case (AST_LEFT_REP
):
1947 if(game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
1948 rotate_ship(SHIP_ROT_ACW_COS
, SHIP_ROT_ACW_SIN
);
1951 case (AST_RIGHT_REP
):
1953 if(game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
1954 rotate_ship(SHIP_ROT_CW_COS
, SHIP_ROT_CW_SIN
);
1957 case (AST_THRUST_REP
):
1959 if((game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
) && !next_thrust_count
)
1962 next_thrust_count
= 5;
1966 case (AST_HYPERSPACE
):
1967 if(game_state
== PLAY_MODE
)
1969 /*maybe shield if it gets too hard */
1972 case (AST_FIRE_REP
):
1974 if(game_state
== ATTRACT_MODE
)
1976 current_level
= START_LEVEL
;
1978 initialise_game(current_level
);
1979 show_level_timeout
= SHOW_LEVEL_TIME
;
1980 game_state
= PLAY_MODE
;
1982 else if(game_state
== PLAY_MODE
)
1984 if(!next_missile_count
)
1987 next_missile_count
= 10;
1990 else if(game_state
== PAUSE_MODE
)
1992 game_state
= PLAY_MODE
;
1997 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
)
1998 return PLUGIN_USB_CONNECTED
;
2004 if(high_score
< current_score
)
2005 high_score
= current_score
;
2010 if(next_missile_count
)
2011 next_missile_count
--;
2013 if(next_thrust_count
)
2014 next_thrust_count
--;
2016 if (end
> *rb
->current_tick
)
2017 rb
->sleep(end
-*rb
->current_tick
);
2025 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
2027 enum plugin_status retval
;
2031 game_state
= ATTRACT_MODE
;
2034 rb
->lcd_set_backdrop(NULL
);
2036 /* universal font */
2037 rb
->lcd_setfont(FONT_SYSFIXED
);
2038 /* Turn off backlight timeout */
2039 backlight_force_on(rb
); /* backlight control in lib/helper.c */
2041 retval
= start_game();
2043 rb
->lcd_setfont(FONT_UI
);
2044 /* Turn on backlight timeout (revert to settings) */
2045 backlight_use_settings(rb
); /* backlight control in lib/helper.c */