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 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
191 #error No keymap defined!
194 #define ABS(x) ((x)>0?(x):-(x))
196 #define RES MAX(LCD_WIDTH, LCD_HEIGHT)
197 #define LARGE_LCD RES >= 200
198 #define ENEMY_MISSILE_SURVIVAL_LENGTH RES/2
199 #define ASTEROID_SPEED RES/20
200 #define MISSILE_SURVIVAL_LENGTH 40
202 #define EXTRA_LIFE 250
204 #define MISSILE_SCALE 5000
206 #define EXPLOSION_LENGTH 20
208 #define HISCORE_FILE PLUGIN_GAMES_DIR "/astrorocks.hs"
210 #define MAX_NUM_ASTEROIDS 25
211 #define MAX_NUM_MISSILES 6
212 #define ENEMY_BIG_PROBABILITY_START 10
213 #define ENEMY_APPEAR_PROBABILITY_START 35
214 #define ENEMY_APPEAR_TIMING_START 1800
215 #define LITTLE_SHIP 2
217 #define SHOW_GAME_OVER_TIME 100
218 #define SHOW_LEVEL_TIME 50
219 #define START_LIVES 3
220 #define START_LEVEL 1
221 #define NUM_ASTEROID_VERTICES 10
222 #define NUM_SHIP_VERTICES 4
223 #define NUM_ENEMY_VERTICES 6
224 #define MAX_LEVEL MAX_NUM_ASTEROIDS
225 #define ENEMY_SPEED 4
226 #define ENEMY_START_X 0
227 #define ENEMY_START_Y 0
228 #define SIZE_ENEMY_COLLISION 5*SCALE
229 #define ATTRACT_FLIP_TIME 100
231 #define NUM_TRAIL_POINTS 70
232 #define NUM_ROTATIONS 16
234 #define SIN_COS_SCALE 10000
236 #define FAST_ROT_CW_SIN 873
237 #define FAST_ROT_CW_COS 9963
238 #define FAST_ROT_ACW_SIN -873
239 #define FAST_ROT_ACW_COS 9963
241 #define MEDIUM_ROT_CW_SIN 350
242 #define MEDIUM_ROT_CW_COS 9994
243 #define MEDIUM_ROT_ACW_SIN -350
244 #define MEDIUM_ROT_ACW_COS 9994
246 #define SLOW_ROT_CW_SIN 350
247 #define SLOW_ROT_CW_COS 9994
248 #define SLOW_ROT_ACW_SIN - 350
249 #define SLOW_ROT_ACW_COS 9994
251 #ifdef HAVE_LCD_COLOR
252 #define SHIP_ROT_CW_SIN 2419
253 #define SHIP_ROT_CW_COS 9702
254 #define SHIP_ROT_ACW_SIN -2419
255 #define SHIP_ROT_ACW_COS 9702
257 #define SHIP_ROT_CW_SIN 3827
258 #define SHIP_ROT_CW_COS 9239
259 #define SHIP_ROT_ACW_SIN -3827
260 #define SHIP_ROT_ACW_COS 9239
264 #define SCALED_WIDTH (LCD_WIDTH*SCALE)
265 #define SCALED_HEIGHT (LCD_HEIGHT*SCALE)
266 #define CENTER_LCD_X (LCD_WIDTH/2)
267 #define CENTER_LCD_Y (LCD_HEIGHT/2)
269 #define SHIP_EXPLOSION_COLOUR 1
270 #define ASTEROID_EXPLOSION_COLOUR 2
271 #define ENEMY_EXPLOSION_COLOUR 3
272 #define THRUST_COLOUR 4
274 #define ASTEROID_R 230
275 #define ASTEROID_G 200
276 #define ASTEROID_B 100
287 #ifdef HAVE_LCD_COLOR
288 #define COL_MISSILE LCD_RGBPACK(200,0,0)
289 #define COL_PLAYER LCD_RGBPACK(200,200,200)
290 #define COL_STARS LCD_WHITE
291 #define COL_ASTEROID LCD_RGBPACK(ASTEROID_R,ASTEROID_G,ASTEROID_B)
292 #define COL_TEXT LCD_RGBPACK(200,200,255)
293 #define COL_ENEMY LCD_RGBPACK(ENEMY_R,ENEMY_G,ENEMY_B)
294 #define SET_FG rb->lcd_set_foreground
295 #define SET_BG rb->lcd_set_background
301 /* The array of points that make up an asteroid */
302 static const short asteroid_one
[NUM_ASTEROID_VERTICES
*2] =
316 /* The array of points that make up an asteroid */
317 static const short asteroid_two
[NUM_ASTEROID_VERTICES
*2] =
331 /* The array of points that make up an asteroid */
332 static const short asteroid_three
[NUM_ASTEROID_VERTICES
*2] =
346 /* The array od points the make up the ship */
347 static const short ship_vertices
[NUM_SHIP_VERTICES
*2] =
362 /* The array of points the make up the bad spaceship */
363 static const short enemy_vertices
[NUM_ENEMY_VERTICES
*2] =
417 struct Point position
;
424 /* Asteroid structure, contains an array of points */
427 enum asteroid_type type
;
429 struct Point position
;
430 struct Point vertices
[NUM_ASTEROID_VERTICES
];
434 int explode_countdown
;
439 struct Point vertices
[NUM_SHIP_VERTICES
];
440 struct Point position
;
441 bool waiting_for_space
;
442 int explode_countdown
;
447 struct Point vertices
[NUM_ENEMY_VERTICES
];
448 struct Point position
;
449 int explode_countdown
;
450 long last_time_appeared
;
451 short size_probability
;
452 short appear_probability
;
458 struct Point position
;
459 struct Point oldpoint
;
463 static enum game_state game_state
;
464 static int asteroid_count
;
465 static int next_missile_count
;
466 static int next_thrust_count
;
467 static int num_lives
;
468 static int extra_life
;
469 static int show_level_timeout
;
470 static int attract_flip_timeout
;
471 static int show_game_over
;
472 static int current_level
;
473 static int current_score
;
474 static int high_score
;
475 static int space_check_size
= 30*SCALE
;
477 static bool enemy_on_screen
;
478 static char phscore
[30];
479 static struct Ship ship
;
480 static struct Point stars
[NUM_STARS
];
481 static struct Asteroid asteroids_array
[MAX_NUM_ASTEROIDS
];
482 static struct Missile missiles_array
[MAX_NUM_MISSILES
];
483 static struct Missile enemy_missile
;
484 static struct Enemy enemy
;
485 static struct Point lives_points
[NUM_SHIP_VERTICES
];
486 static struct TrailPoint trailPoints
[NUM_TRAIL_POINTS
];
488 void draw_and_move_asteroids(void);
489 void initialise_game(int nStartNum
);
491 bool is_asteroid_near_ship(struct Asteroid
* asteroid
);
492 bool is_point_within_asteroid(struct Asteroid
* asteroid
, struct Point
* point
);
494 void initialise_asteroid(struct Asteroid
* asteroid
, enum asteroid_type eType
);
495 void draw_polygon(struct Point
* vertices
, int px
, int py
, int num_vertices
);
496 void rotate_asteroid(struct Asteroid
* asteroid
);
497 void create_asteroid(enum asteroid_type type
, int x
, int y
);
498 void create_stars(void);
500 void initialise_ship(void);
501 void draw_and_move_ship(void);
502 void rotate_ship(int s
, int c
);
503 void thrust_ship(void);
505 void initialise_missile(struct Missile
* missile
);
506 void draw_and_move_missiles(void);
507 void fire_missile(void);
509 void animate_and_draw_explosion(struct Point
* point
, int num_points
, int xoffset
, int yoffset
);
510 void initialise_explosion(struct Point
* point
, int num_points
);
512 void move_point(struct Point
* point
);
513 void hyperspace(void);
514 void check_collisions(void);
515 void initialise_enemy(void);
516 void draw_and_move_enemy(void);
517 void draw_lives(void);
518 void drawstars(void);
519 bool is_ship_within_asteroid(struct Asteroid
* asteroid
);
523 /*Hi-Score reading and writing to file - this needs moving to the hi-score plugin lib as
530 /* clear the buffer we're about to load the highscore data into */
531 rb
->memset(phscore
, 0, sizeof(phscore
));
533 fd
= rb
->open(HISCORE_FILE
,O_RDWR
| O_CREAT
);
536 rb
->splash(HZ
, "Highscore file read error");
540 /* highscore used to %d, is now %d\n
541 Deal with no file or bad file */
542 rb
->read(fd
,phscore
, sizeof(phscore
));
544 compare
= rb
->atoi(phscore
);
546 if(high_score
> compare
)
548 rb
->lseek(fd
,0,SEEK_SET
);
549 rb
->fdprintf(fd
, "%d\n", high_score
);
552 high_score
= compare
;
557 bool point_in_poly(struct Point
* _point
, int num_vertices
, int x
, int y
)
566 pj
+= num_vertices
-1;
571 if((((pi
->y
<= y
) && (y
< pj
->y
)) || ((pj
->y
<= y
) && (y
< pi
->y
))) &&
572 (x
< (pj
->x
- pi
->x
) * (y
- pi
->y
) / (pj
->y
- pi
->y
) + pi
->x
))
575 if(n
== num_vertices
- 1)
586 void move_point(struct Point
* point
)
588 point
->x
+= point
->dx
;
589 point
->y
+= point
->dy
;
591 /*check bounds on the x-axis:*/
592 if(point
->x
>= SCALED_WIDTH
)
594 else if(point
->x
<= 0)
595 point
->x
= SCALED_WIDTH
;
597 /*Check bounds on the y-axis:*/
598 if(point
->y
>= SCALED_HEIGHT
)
600 else if(point
->y
<= 0)
601 point
->y
= SCALED_HEIGHT
;
604 void create_trail(struct TrailPoint
* tpoint
)
606 tpoint
->position
.dx
= -( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/10;
607 tpoint
->position
.dy
= -( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/10;
610 void create_explosion_trail(struct TrailPoint
* tpoint
)
612 tpoint
->position
.dx
= (rb
->rand()%5050)-2500;
613 tpoint
->position
.dy
= (rb
->rand()%5050)-2500;
616 void create_trail_blaze(int colour
, struct Point
* position
)
619 struct TrailPoint
* tpoint
;
622 if(colour
!= SHIP_EXPLOSION_COLOUR
)
624 numtoadd
= NUM_TRAIL_POINTS
/5;
630 numtoadd
= NUM_TRAIL_POINTS
/8;
631 xadd
= ship
.position
.x
;
632 yadd
= ship
.position
.y
;
635 /* give the point a random countdown timer, so they dissapears at different times */
636 tpoint
= trailPoints
;
637 n
= NUM_TRAIL_POINTS
;
640 if(tpoint
->alive
<= 0 && numtoadd
)
643 /* take a random x point anywhere between bottom two points of ship. */
644 /* ship.position.x; */
645 tpoint
->position
.x
= (ship
.vertices
[2].x
+ (rb
->rand()%18000)-9000) + position
->x
;
646 tpoint
->position
.y
= (ship
.vertices
[2].y
+ (rb
->rand()%18000)-9000) + position
->y
;
650 case SHIP_EXPLOSION_COLOUR
:
654 create_explosion_trail(tpoint
);
658 case ASTEROID_EXPLOSION_COLOUR
:
659 tpoint
->r
= ASTEROID_R
;
660 tpoint
->g
= ASTEROID_G
;
661 tpoint
->b
= ASTEROID_B
;
662 create_explosion_trail(tpoint
);
666 case ENEMY_EXPLOSION_COLOUR
:
670 create_explosion_trail(tpoint
);
675 tpoint
->r
= THRUST_R
;
676 tpoint
->g
= THRUST_G
;
677 tpoint
->b
= THRUST_B
;
678 create_trail(tpoint
);
683 /* add a proportional bit to the x and y based on dx and dy */
685 /* give the points a speed based on direction of travel - i.e. opposite */
686 tpoint
->position
.dx
+= position
->dx
;
687 tpoint
->position
.dy
+= position
->dy
;
693 /* find a space in the array of trail_points that is NULL or DEAD or whatever.
694 and place this one here. */
698 void draw_trail_blaze(void)
700 struct TrailPoint
* tpoint
;
701 /* loop through, if alive then move and draw.
702 when drawn, countdown it's timer.
704 tpoint
= trailPoints
;
705 int n
= NUM_TRAIL_POINTS
;
711 if(game_state
!= PAUSE_MODE
)
714 move_point(&(tpoint
->position
));
716 #ifdef HAVE_LCD_COLOR
717 /* intensity = tpoint->alive/2; */
718 if(tpoint
->r
>0)tpoint
->r
-=tpoint
->dec
;
719 if(tpoint
->g
>0)tpoint
->g
-=tpoint
->dec
;
720 if(tpoint
->b
>0)tpoint
->b
-=tpoint
->dec
;
721 SET_FG(LCD_RGBPACK(tpoint
->r
, tpoint
->g
, tpoint
->b
));
723 rb
->lcd_drawpixel(tpoint
->position
.x
/SCALE
, tpoint
->position
.y
/SCALE
);
729 /*Check if point is within a rectangle*/
730 bool is_point_within_rectangle(struct Point
* rect
, struct Point
* p
, int size
)
733 int aTLx
= rect
->x
- size
;
734 int aTLy
= rect
->y
- size
;
735 int aBRx
= rect
->x
+ size
;
736 int aBRy
= rect
->y
+ size
;
737 rb
->lcd_drawline( aTLx
/SCALE
, aTLy
/SCALE
, aBRx
/SCALE
, aTLy
/SCALE
);
738 rb
->lcd_drawline( aTLx
/SCALE
, aTLy
/SCALE
, aTLx
/SCALE
, aBRy
/SCALE
);
739 rb
->lcd_drawline( aTLx
/SCALE
, aBRy
/SCALE
, aBRx
/SCALE
, aBRy
/SCALE
);
740 rb
->lcd_drawline( aBRx
/SCALE
, aBRy
/SCALE
, aBRx
/SCALE
, aTLy
/SCALE
);
741 return (p
->x
> aTLx
&& p
->x
< aBRx
&& p
->y
> aTLy
&& p
->y
< aBRy
);
743 return (p
->x
> rect
->x
- size
&& p
->x
< rect
->x
+ size
&&
744 p
->y
> rect
->y
- size
&& p
->y
< rect
->y
+ size
);
749 void draw_polygon(struct Point
* vertices
, int px
, int py
, int num_vertices
)
751 int n
, t1
, t2
, oldX
, oldY
;
753 bool bDrawAll
= px
< WRAP_GAP
|| LCD_WIDTH
- px
< WRAP_GAP
||
754 py
< WRAP_GAP
|| LCD_HEIGHT
- py
< WRAP_GAP
;
758 oldX
= p
->x
/SCALE
+ px
;
759 oldY
= p
->y
/SCALE
+ py
;
761 for(n
= num_vertices
+1; --n
;)
763 t1
= p
->x
/SCALE
+ px
;
764 t2
= p
->y
/SCALE
+ py
;
766 rb
->lcd_drawline(oldX
, oldY
, t1
, t2
);
770 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
, t1
- LCD_WIDTH
, t2
);
771 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
, t1
+ LCD_WIDTH
, t2
);
772 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
+ LCD_HEIGHT
,
773 t1
- LCD_WIDTH
, t2
+ LCD_HEIGHT
);
774 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
+ LCD_HEIGHT
,
775 t1
+ LCD_WIDTH
, t2
+ LCD_HEIGHT
);
777 rb
->lcd_drawline(oldX
, oldY
- LCD_HEIGHT
, t1
, t2
- LCD_HEIGHT
);
778 rb
->lcd_drawline(oldX
, oldY
+ LCD_HEIGHT
, t1
, t2
+ LCD_HEIGHT
);
779 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
- LCD_HEIGHT
,
780 t1
- LCD_WIDTH
, t2
- LCD_HEIGHT
);
781 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
- LCD_HEIGHT
,
782 t1
+ LCD_WIDTH
, t2
- LCD_HEIGHT
);
790 void animate_and_draw_explosion(struct Point
* point
, int num_points
,
791 int xoffset
, int yoffset
)
794 for(n
= num_points
; --n
;)
796 if(game_state
!= PAUSE_MODE
)
798 point
->x
+= point
->dx
;
799 point
->y
+= point
->dy
;
801 rb
->lcd_fillrect( point
->x
/SCALE
+ xoffset
, point
->y
/SCALE
+ yoffset
,
802 POINT_SIZE
, POINT_SIZE
);
807 /*stop movement of ship, 'cos that's what happens when you go into hyperspace.*/
808 void hyperspace(void)
810 ship
.position
.dx
= ship
.position
.dy
= 0;
811 ship
.position
.x
= (rb
->rand()%SCALED_WIDTH
);
812 ship
.position
.y
= (rb
->rand()%SCALED_HEIGHT
);
815 void initialise_enemy(void)
821 if(rb
->rand()%100 > enemy
.size_probability
)
824 enemy
.size_probability
++;
825 if(enemy
.size_probability
< 90)
827 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
835 enemy_missile
.survived
= 0;
836 enemy_on_screen
= true;
837 enemy
.explode_countdown
= 0;
838 enemy
.last_time_appeared
= *rb
->current_tick
;
839 point
= enemy
.vertices
;
840 for(n
= 0; n
< NUM_ENEMY_VERTICES
+NUM_ENEMY_VERTICES
; n
+=2)
842 point
->x
= enemy_vertices
[n
];
843 point
->y
= enemy_vertices
[n
+1];
844 point
->x
*= SCALE
/size
;
845 point
->y
*= SCALE
/size
;
849 if(ship
.position
.x
>= SCALED_WIDTH
/2)
851 enemy
.position
.dx
= ENEMY_SPEED
;
852 enemy
.position
.x
= 0;
856 enemy
.position
.dx
= -ENEMY_SPEED
;
857 enemy
.position
.x
= SCALED_WIDTH
;
860 if(ship
.position
.y
>= SCALED_HEIGHT
/2)
862 enemy
.position
.dy
= ENEMY_SPEED
;
863 enemy
.position
.y
= 0;
867 enemy
.position
.dy
= -ENEMY_SPEED
;
868 enemy
.position
.y
= SCALED_HEIGHT
;
871 enemy
.position
.dx
*= SCALE
/10;
872 enemy
.position
.dy
*= SCALE
/10;
875 void draw_and_move_enemy(void)
877 int enemy_x
, enemy_y
;
884 enemy_x
= enemy
.position
.x
/SCALE
;
885 enemy_y
= enemy
.position
.y
/SCALE
;
886 if(!enemy
.explode_countdown
)
888 point
= enemy
.vertices
;
889 draw_polygon(enemy
.vertices
, enemy_x
, enemy_y
, NUM_ENEMY_VERTICES
);
890 rb
->lcd_drawline(enemy
.vertices
[0].x
/SCALE
+ enemy_x
,
891 enemy
.vertices
[0].y
/SCALE
+ enemy_y
,
892 enemy
.vertices
[3].x
/SCALE
+ enemy_x
,
893 enemy
.vertices
[3].y
/SCALE
+ enemy_y
);
895 if(game_state
!= PAUSE_MODE
)
897 enemy
.position
.x
+= enemy
.position
.dx
;
898 enemy
.position
.y
+= enemy
.position
.dy
;
901 if(enemy
.position
.x
> SCALED_WIDTH
|| enemy
.position
.x
< 0)
902 enemy_on_screen
= false;
904 if(enemy
.position
.y
> SCALED_HEIGHT
)
905 enemy
.position
.y
= 0;
906 else if(enemy
.position
.y
< 0)
907 enemy
.position
.y
= SCALED_HEIGHT
;
909 if( (rb
->rand()%1000) < 10)
910 enemy
.position
.dy
= -enemy
.position
.dy
;
915 /* animate_and_draw_explosion(enemy.vertices, NUM_ENEMY_VERTICES,
916 enemy_x, enemy.position.y/SCALE); */
917 if(game_state
!= PAUSE_MODE
)
919 enemy
.explode_countdown
--;
920 if(!enemy
.explode_countdown
)
921 enemy_on_screen
= false;
927 if( (*rb
->current_tick
- enemy
.last_time_appeared
) > enemy
.appear_timing
)
928 if(rb
->rand()%100 > enemy
.appear_probability
) initialise_enemy();
931 if(!enemy_missile
.survived
&& game_state
!= GAME_OVER
)
933 /*if no missile and the enemy is here and not exploding..then shoot baby!*/
934 if( !enemy
.explode_countdown
&& enemy_on_screen
&&
935 !ship
.waiting_for_space
&& (rb
->rand()%10) > 5 )
937 enemy_missile
.position
.x
= enemy
.position
.x
;
938 enemy_missile
.position
.y
= enemy
.position
.y
;
940 /*lame, needs to be sorted - it's trying to shoot at the ship*/
941 if(ABS(enemy
.position
.y
- ship
.position
.y
) <= 5*SCALE
)
943 enemy_missile
.position
.dy
= 0;
947 if( enemy
.position
.y
< ship
.position
.y
)
948 enemy_missile
.position
.dy
= 1;
950 enemy_missile
.position
.dy
= -1;
953 if(ABS(enemy
.position
.x
- ship
.position
.x
) <= 5*SCALE
)
954 enemy_missile
.position
.dx
= 0;
957 if( enemy
.position
.x
< ship
.position
.x
)
958 enemy_missile
.position
.dx
= 1;
960 enemy_missile
.position
.dx
= -1;
963 if(enemy_missile
.position
.dx
== 0 &&
964 enemy_missile
.position
.dy
== 0)
965 enemy_missile
.position
.dx
= enemy_missile
.position
.dy
= -1;
967 enemy_missile
.position
.dx
*= SCALE
;
968 enemy_missile
.position
.dy
*= SCALE
;
969 enemy_missile
.survived
= ENEMY_MISSILE_SURVIVAL_LENGTH
;
975 rb
->lcd_fillrect( enemy_missile
.position
.x
/SCALE
,
976 enemy_missile
.position
.y
/SCALE
,
977 POINT_SIZE
, POINT_SIZE
);
978 if(game_state
!= PAUSE_MODE
)
980 move_point(&enemy_missile
.position
);
981 enemy_missile
.survived
--;
987 * Lame method of collision
988 * detection. It's checking for collision
989 * between point and a big rectangle around the asteroid...
991 bool is_point_within_asteroid(struct Asteroid
* asteroid
, struct Point
* point
)
993 if( !is_point_within_rectangle(&asteroid
->position
, point
,
994 asteroid
->radius
+4*SCALE
) )
997 if(point_in_poly(asteroid
->vertices
, NUM_ASTEROID_VERTICES
,
998 point
->x
- asteroid
->position
.x
,
999 point
->y
- asteroid
->position
.y
))
1001 switch(asteroid
->type
)
1004 asteroid
->explode_countdown
= EXPLOSION_LENGTH
;
1005 create_trail_blaze(ASTEROID_EXPLOSION_COLOUR
, &asteroid
->position
);
1009 create_asteroid(MEDIUM
, asteroid
->position
.x
,
1010 asteroid
->position
.y
);
1011 create_asteroid(MEDIUM
, asteroid
->position
.x
,
1012 asteroid
->position
.y
);
1016 create_asteroid(SMALL
, asteroid
->position
.x
, asteroid
->position
.y
);
1017 create_asteroid(SMALL
, asteroid
->position
.x
, asteroid
->position
.y
);
1022 if(current_score
> extra_life
)
1025 extra_life
= current_score
+EXTRA_LIFE
;
1028 asteroid
->exists
= false;
1035 bool is_point_within_enemy(struct Point
* point
)
1037 if( is_point_within_rectangle(&enemy
.position
, point
, 7*SCALE
) )
1040 /*enemy_missile.survived = 0;*/
1041 enemy
.explode_countdown
= EXPLOSION_LENGTH
;
1042 /* initialise_explosion(enemy.vertices, NUM_ENEMY_VERTICES); */
1043 create_trail_blaze(ENEMY_EXPLOSION_COLOUR
, &enemy
.position
);
1050 bool is_ship_within_asteroid(struct Asteroid
* asteroid
)
1055 p
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1056 p
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1057 hit
|= is_point_within_asteroid(asteroid
, &p
);
1061 p
.x
= ship
.position
.x
+ ship
.vertices
[1].x
;
1062 p
.y
= ship
.position
.y
+ ship
.vertices
[1].y
;
1063 hit
|= is_point_within_asteroid(asteroid
, &p
);
1066 p
.x
= ship
.position
.x
+ ship
.vertices
[3].x
;
1067 p
.y
= ship
.position
.y
+ ship
.vertices
[3].y
;
1068 hit
|= is_point_within_asteroid(asteroid
, &p
);
1075 void initialise_explosion(struct Point
* point
, int num_points
)
1079 point
->x
+= point
->dx
;
1080 point
->y
+= point
->dy
;
1081 for(n
= num_points
; --n
;)
1083 point
->dx
= point
->x
;
1084 point
->dy
= point
->y
;
1090 /* Check for collsions between the missiles and the asteroids and the ship */
1091 void check_collisions(void)
1094 bool asteroids_onscreen
= false;
1095 struct Missile
* missile
;
1096 struct Asteroid
* asteroid
;
1097 bool ship_cant_be_placed
= false;
1099 asteroid
= asteroids_array
;
1100 m
= MAX_NUM_ASTEROIDS
;
1103 /*if the asteroids exists then test missile collision:*/
1104 if(asteroid
->exists
)
1106 missile
= missiles_array
;
1107 n
= MAX_NUM_MISSILES
;
1110 /*if the missiles exists:*/
1111 if(missile
->survived
> 0)
1113 /*has the missile hit the asteroid?*/
1114 if(is_point_within_asteroid(asteroid
, &missile
->position
)
1115 || is_point_within_asteroid(asteroid
,
1116 &missile
->oldpoint
))
1118 missile
->survived
= 0;
1125 /*now check collision with ship:*/
1126 if(asteroid
->exists
&& !ship
.waiting_for_space
&& !ship
.explode_countdown
)
1128 if(is_ship_within_asteroid(asteroid
))
1131 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1132 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1133 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1136 /*has the enemy missile blown something up?*/
1137 if(asteroid
->exists
&& enemy_missile
.survived
)
1139 if(is_point_within_asteroid(asteroid
, &enemy_missile
.position
))
1141 /*take that score back then:*/
1142 if(current_score
> 0) current_score
--;
1143 enemy_missile
.survived
= 0;
1146 /*if it still exists, check if ship is waiting for space:*/
1147 if(asteroid
->exists
&& ship
.waiting_for_space
)
1148 ship_cant_be_placed
|=
1149 is_point_within_rectangle(&ship
.position
,
1150 &asteroid
->position
,
1155 /*is an asteroid still exploding?*/
1156 if(asteroid
->explode_countdown
)
1157 asteroids_onscreen
= true;
1162 /*now check collision between ship and enemy*/
1163 if(enemy_on_screen
&& !ship
.waiting_for_space
&&
1164 !ship
.explode_countdown
&& !enemy
.explode_countdown
)
1166 /*has the enemy collided with the ship?*/
1167 if(is_point_within_enemy(&ship
.position
))
1169 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1170 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1171 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1172 create_trail_blaze(ENEMY_EXPLOSION_COLOUR
, &enemy
.position
);
1175 /*Now see if the enemy has been shot at by the ships missiles:*/
1176 missile
= missiles_array
;
1177 n
= MAX_NUM_MISSILES
;
1180 if(missile
->survived
> 0 &&
1181 is_point_within_enemy(&missile
->position
))
1183 missile
->survived
= 0;
1190 /*test collision with enemy missile and ship:*/
1191 if(!ship_cant_be_placed
&& enemy_missile
.survived
> 0 &&
1192 point_in_poly(ship
.vertices
, NUM_SHIP_VERTICES
,
1193 enemy_missile
.position
.x
- ship
.position
.x
,
1194 enemy_missile
.position
.y
- ship
.position
.y
))
1196 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1197 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1198 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1199 enemy_missile
.survived
= 0;
1200 enemy_missile
.position
.x
= enemy_missile
.position
.y
= 0;
1203 if(!ship_cant_be_placed
)
1204 ship
.waiting_for_space
= false;
1206 /*if all asteroids cleared then start again:*/
1207 if(asteroid_count
== 0 && !enemy_on_screen
&& !asteroids_onscreen
)
1210 game_state
= SHOW_LEVEL
;
1211 enemy
.appear_probability
+= 5;
1212 enemy
.appear_timing
-= 200;
1213 if( enemy
.appear_probability
> 100)
1214 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1215 show_level_timeout
= SHOW_LEVEL_TIME
;
1219 /*************************************************
1220 ** Creates a new asteroid of the given 4type (size)
1221 ** and at the given location.
1222 *************************************************/
1223 void create_asteroid(enum asteroid_type type
, int x
, int y
)
1225 struct Asteroid
* asteroid
;
1228 asteroid
= asteroids_array
;
1229 n
= MAX_NUM_ASTEROIDS
;
1232 if(!asteroid
->exists
&& !asteroid
->explode_countdown
)
1234 initialise_asteroid(asteroid
, type
);
1235 asteroid
->position
.x
= x
;
1236 asteroid
->position
.y
= y
;
1243 /* Initialise a missile */
1244 void initialise_missile(struct Missile
* missile
)
1246 missile
->position
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1247 missile
->position
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1248 missile
->position
.dx
= (ship
.vertices
[0].x
- ship
.vertices
[2].x
)/2;
1249 missile
->position
.dy
= (ship
.vertices
[0].y
- ship
.vertices
[2].y
)/2;
1250 missile
->survived
= MISSILE_SURVIVAL_LENGTH
;
1251 missile
->oldpoint
.x
= missile
->position
.x
;
1252 missile
->oldpoint
.y
= missile
->position
.y
;
1255 /* Draw and Move all the missiles */
1256 void draw_and_move_missiles(void)
1262 struct Missile
* missile
;
1263 missile
= missiles_array
;
1265 SET_FG(COL_MISSILE
);
1267 n
= MAX_NUM_MISSILES
;
1270 if(missile
->survived
)
1272 if(missile
->position
.dx
> 0)
1274 if(missile
->position
.x
>= missile
->oldpoint
.x
)
1276 p1x
= missile
->oldpoint
.x
;
1277 p2x
= missile
->position
.x
;
1282 p2x
= missile
->position
.x
;
1287 if(missile
->oldpoint
.x
>= missile
->position
.x
)
1289 p1x
= missile
->oldpoint
.x
;
1290 p2x
= missile
->position
.x
;
1294 p1x
= missile
->oldpoint
.x
;
1299 if(missile
->position
.dy
> 0)
1301 if(missile
->position
.y
>= missile
->oldpoint
.y
)
1303 p1y
= missile
->oldpoint
.y
;
1304 p2y
= missile
->position
.y
;
1309 p2y
= missile
->position
.y
;
1314 if(missile
->oldpoint
.y
>= missile
->position
.y
)
1316 p1y
= missile
->oldpoint
.y
;
1317 p2y
= missile
->position
.y
;
1321 p1y
= missile
->oldpoint
.y
;
1326 rb
->lcd_drawline( p1x
/SCALE
, p1y
/SCALE
, p2x
/SCALE
, p2y
/SCALE
);
1328 if(game_state
!= PAUSE_MODE
)
1330 missile
->oldpoint
.x
= missile
->position
.x
;
1331 missile
->oldpoint
.y
= missile
->position
.y
;
1332 move_point(&missile
->position
);
1333 missile
->survived
--;
1340 void draw_lives(void)
1343 int px
= (LCD_WIDTH
- num_lives
*4 - 1);
1345 int py
= (LCD_HEIGHT
-6);
1347 int py
= (LCD_HEIGHT
-4);
1355 draw_polygon(lives_points
, px
, py
, NUM_SHIP_VERTICES
);
1364 /*Fire the next missile*/
1365 void fire_missile(void)
1368 struct Missile
* missile
;
1370 if(!ship
.explode_countdown
&& !ship
.waiting_for_space
)
1372 missile
= missiles_array
;
1373 n
= MAX_NUM_MISSILES
;
1376 if(!missile
->survived
)
1378 initialise_missile(missile
);
1386 /* Initialise the passed Asteroid */
1387 void initialise_asteroid(struct Asteroid
* asteroid
, enum asteroid_type type
)
1391 struct Point
* point
;
1392 asteroid
->exists
= true;
1393 asteroid
->type
= type
;
1394 asteroid
->explode_countdown
= 0;
1396 /*Set the radius of the asteroid:*/
1397 asteroid
->radius
= (int)type
*SCALE
;
1399 /*shall we move Clockwise and Fast*/
1400 if((rb
->rand()%100)>75)
1402 asteroid
->speed_cos
= FAST_ROT_CW_COS
;
1403 asteroid
->speed_sin
= FAST_ROT_CW_SIN
;
1405 else if((rb
->rand()%100)>75)
1407 asteroid
->speed_cos
= FAST_ROT_ACW_COS
;
1408 asteroid
->speed_sin
= FAST_ROT_ACW_SIN
;
1410 else if((rb
->rand()%100)>75)
1412 asteroid
->speed_cos
= SLOW_ROT_ACW_COS
;
1413 asteroid
->speed_sin
= SLOW_ROT_ACW_SIN
;
1417 asteroid
->speed_cos
= SLOW_ROT_CW_COS
;
1418 asteroid
->speed_sin
= SLOW_ROT_CW_SIN
;
1421 b
= (rb
->rand()%100)>66;
1422 b2
= (rb
->rand()%100)>66;
1423 point
= asteroid
->vertices
;
1424 for(n
= 0; n
< NUM_ASTEROID_VERTICES
*2; n
+=2)
1428 point
->x
= asteroid_one
[n
];
1429 point
->y
= asteroid_one
[n
+1];
1433 point
->x
= asteroid_two
[n
];
1434 point
->y
= asteroid_two
[n
+1];
1438 point
->x
= asteroid_three
[n
];
1439 point
->y
= asteroid_three
[n
+1];
1442 point
->x
*= asteroid
->radius
/6;
1443 point
->y
*= asteroid
->radius
/6;
1448 asteroid
->radius
+= 6*SCALE
;
1449 if(asteroid
->type
== SMALL
)
1450 asteroid
->radius
/= 3;/*2*/
1451 else if(asteroid
->type
== LARGE
)
1452 asteroid
->radius
+= 3*SCALE
;/*2*/
1456 /*Set the position randomly:*/
1457 asteroid
->position
.x
= (rb
->rand()%SCALED_WIDTH
);
1458 asteroid
->position
.y
= (rb
->rand()%SCALED_HEIGHT
);
1460 asteroid
->position
.dx
= 0;
1461 while(asteroid
->position
.dx
== 0)
1462 asteroid
->position
.dx
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
1464 asteroid
->position
.dy
= 0;
1465 while(asteroid
->position
.dy
== 0)
1466 asteroid
->position
.dy
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
1468 asteroid
->position
.dx
*= SCALE
/10;
1469 asteroid
->position
.dy
*= SCALE
/10;
1471 b
= is_point_within_rectangle(&ship
.position
, &asteroid
->position
,
1475 /*Now rotate the asteroid a bit, so they all look a bit different*/
1476 for(n
=(rb
->rand()%30) + 2;--n
;)
1477 rotate_asteroid(asteroid
);
1479 /*great, we've created an asteroid, don't forget to increment the total:*/
1483 /*Initialise the ship*/
1484 void initialise_ship(void)
1486 struct Point
* point
;
1487 struct Point
* lives_point
;
1490 ship
.position
.x
= CENTER_LCD_X
;
1491 ship
.position
.y
= CENTER_LCD_Y
;
1492 ship
.position
.x
*= SCALE
;
1493 ship
.position
.y
*= SCALE
;
1494 ship
.position
.dx
= ship
.position
.dy
= 0;
1496 point
= ship
.vertices
;
1497 lives_point
= lives_points
;
1498 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+=2)
1500 point
->x
= ship_vertices
[n
];
1501 point
->y
= ship_vertices
[n
+1];
1508 ship
.position
.dx
= 0;
1509 ship
.position
.dy
= 0;
1510 ship
.explode_countdown
= 0;
1512 /*grab a copy of the ships points for the lives display:*/
1513 point
= ship
.vertices
;
1514 lives_point
= lives_points
;
1515 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+=2)
1517 lives_point
->x
= point
->x
;
1518 lives_point
->y
= point
->y
;
1524 void rotate_asteroid(struct Asteroid
* asteroid
)
1526 struct Point
* point
;
1530 point
= asteroid
->vertices
;
1531 for(n
= NUM_ASTEROID_VERTICES
+1; --n
;)
1534 point
->x
= xtemp
*asteroid
->speed_cos
/SIN_COS_SCALE
-
1535 point
->y
*asteroid
->speed_sin
/SIN_COS_SCALE
;
1536 point
->y
= point
->y
*asteroid
->speed_cos
/SIN_COS_SCALE
+
1537 xtemp
*asteroid
->speed_sin
/SIN_COS_SCALE
;
1542 /*************************************************
1543 ** Draws the ship, moves the ship and creates a new
1544 ** one if it's finished exploding.
1545 **************************************************/
1546 void draw_and_move_ship(void)
1548 int nxoffset
= ship
.position
.x
/SCALE
;
1549 int nyoffset
= ship
.position
.y
/SCALE
;
1551 if(!ship
.explode_countdown
)
1553 if(!ship
.waiting_for_space
)
1555 draw_polygon(ship
.vertices
, nxoffset
, nyoffset
, NUM_SHIP_VERTICES
);
1556 if(game_state
!= PAUSE_MODE
&& game_state
!= GAME_OVER
)
1558 move_point(&ship
.position
);
1564 /* animate_and_draw_explosion(ship.vertices, NUM_SHIP_VERTICES,
1565 ship.position.x/SCALE,
1566 ship.position.y/SCALE); */
1567 if(game_state
!= PAUSE_MODE
)
1569 ship
.explode_countdown
--;
1570 if(!ship
.explode_countdown
)
1575 show_game_over
= SHOW_GAME_OVER_TIME
;
1576 game_state
= GAME_OVER
;
1581 ship
.waiting_for_space
= true;
1588 void thrust_ship(void)
1590 if(!ship
.waiting_for_space
)
1592 ship
.position
.dx
+= ( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/20;
1593 ship
.position
.dy
+= ( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/20;
1594 /*if dx and dy are below a certain threshold, then set 'em to 0
1595 but to do this we need to ascertain if the spacehip as moved on screen
1596 for more than a certain amount. */
1598 create_trail_blaze(THRUST_COLOUR
, &ship
.position
);
1602 /**************************************************
1603 ** Rotate the ship using the passed sin & cos values
1604 ***************************************************/
1605 void rotate_ship(int c
, int s
)
1607 struct Point
* point
;
1611 if(!ship
.waiting_for_space
&& !ship
.explode_countdown
)
1613 point
= ship
.vertices
;
1614 for(n
=NUM_SHIP_VERTICES
+1;--n
;)
1617 point
->x
= xtemp
*c
/SIN_COS_SCALE
- point
->y
*s
/SIN_COS_SCALE
;
1618 point
->y
= point
->y
*c
/SIN_COS_SCALE
+ xtemp
*s
/SIN_COS_SCALE
;
1634 rb
->lcd_drawpixel(p
->x
, p
->y
);
1639 /*************************************************
1640 ** Draw And Move all Asteroids
1641 *************************************************/
1642 void draw_and_move_asteroids(void)
1645 struct Asteroid
* asteroid
;
1647 asteroid
= asteroids_array
;
1648 SET_FG(COL_ASTEROID
);
1650 n
= MAX_NUM_ASTEROIDS
;
1653 if(game_state
!= PAUSE_MODE
)
1655 if(asteroid
->exists
)
1657 move_point(&asteroid
->position
);
1658 rotate_asteroid(asteroid
);
1659 draw_polygon(asteroid
->vertices
, asteroid
->position
.x
/SCALE
,
1660 asteroid
->position
.y
/SCALE
,
1661 NUM_ASTEROID_VERTICES
);
1663 else if(asteroid
->explode_countdown
)
1665 /* animate_and_draw_explosion(asteroid->vertices,
1666 NUM_ASTEROID_VERTICES,
1667 asteroid->position.x/SCALE,
1668 asteroid->position.y/SCALE); */
1669 asteroid
->explode_countdown
--;
1674 if(asteroid
->exists
)
1675 draw_polygon(asteroid
->vertices
,
1676 asteroid
->position
.x
/SCALE
,
1677 asteroid
->position
.y
/SCALE
,
1678 NUM_ASTEROID_VERTICES
);
1684 void create_stars(void)
1686 struct TrailPoint
* tpoint
;
1694 p
->x
= (rb
->rand()%LCD_WIDTH
);
1695 p
->y
= (rb
->rand()%LCD_HEIGHT
);
1700 /* give the point a random countdown timer, so they dissapears at different
1702 tpoint
= trailPoints
;
1703 n
= NUM_TRAIL_POINTS
;
1711 /*************************************************
1712 ** Creates start_num number of new asteroids of
1714 **************************************************/
1715 void initialise_game(int start_num
)
1718 asteroid_count
= next_missile_count
= next_thrust_count
= 0;
1719 struct Asteroid
* asteroid
;
1720 struct Missile
* missile
;
1721 extra_life
= EXTRA_LIFE
;
1724 enemy_on_screen
= 0;
1725 enemy_missile
.survived
= 0;
1728 asteroid
= asteroids_array
;
1729 n
= MAX_NUM_ASTEROIDS
;
1732 asteroid
->exists
= false;
1736 /*make some LARGE asteroids*/
1737 for(n
= 0; n
< start_num
; n
++)
1738 initialise_asteroid(&asteroids_array
[n
], LARGE
);
1740 /*ensure all missiles are out of action: */
1741 missile
= missiles_array
;
1742 n
= MAX_NUM_MISSILES
;
1745 missile
->survived
=0;
1750 void start_attract_mode(void)
1752 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1753 enemy
.appear_timing
= ENEMY_APPEAR_TIMING_START
;
1755 num_lives
= START_LIVES
;
1757 attract_flip_timeout
= ATTRACT_FLIP_TIME
;
1758 game_state
= ATTRACT_MODE
;
1759 if(asteroid_count
< 3)
1760 initialise_game(current_level
);
1763 enum plugin_status
start_game(void)
1771 /*create stars once, and once only:*/
1778 /*game starts with at level 1
1780 start_attract_mode();
1785 end
= *rb
->current_tick
+ (CYCLETIME
* HZ
) / 1000;
1786 rb
->lcd_clear_display();
1791 if(attract_flip_timeout
< ATTRACT_FLIP_TIME
/2)
1793 rb
->lcd_putsxy(CENTER_LCD_X
- 39,
1794 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4,
1796 if(!attract_flip_timeout
)
1797 attract_flip_timeout
= ATTRACT_FLIP_TIME
;
1801 rb
->snprintf(s
, sizeof(s
), "Hi Score %d ", high_score
);
1802 rb
->lcd_putsxy(CENTER_LCD_X
- 30,
1803 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, s
);
1805 attract_flip_timeout
--;
1809 rb
->lcd_putsxy(CENTER_LCD_X
- 25,
1810 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, "Game Over");
1811 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1812 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1815 start_attract_mode();
1819 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1820 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1821 rb
->lcd_putsxy(CENTER_LCD_X
- 15,
1822 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, "pause");
1823 draw_and_move_missiles();
1825 draw_and_move_ship();
1829 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1830 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1831 draw_and_move_missiles();
1834 draw_and_move_ship();
1838 show_level_timeout
--;
1839 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1840 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1841 rb
->snprintf(level
, sizeof(level
), "stage %d ", current_level
);
1842 rb
->lcd_putsxy(CENTER_LCD_X
- 20,
1843 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, level
);
1844 draw_and_move_ship();
1846 if(!show_level_timeout
)
1848 initialise_game(current_level
);
1849 game_state
= PLAY_MODE
;
1856 draw_and_move_asteroids();
1857 draw_and_move_enemy();
1860 button
= rb
->button_get(false);
1862 #ifdef HAS_BUTTON_HOLD
1863 if (rb
->button_hold())
1864 game_state
= PAUSE_MODE
;
1870 if(game_state
== PLAY_MODE
)
1871 game_state
= PAUSE_MODE
;
1872 else if(game_state
== PAUSE_MODE
)
1873 game_state
= PLAY_MODE
;
1880 if(game_state
== ATTRACT_MODE
)
1882 else if(game_state
== GAME_OVER
)
1884 start_attract_mode();
1888 show_game_over
= SHOW_GAME_OVER_TIME
;
1889 game_state
= GAME_OVER
;
1893 case (AST_LEFT_REP
):
1895 if(game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
1896 rotate_ship(SHIP_ROT_ACW_COS
, SHIP_ROT_ACW_SIN
);
1899 case (AST_RIGHT_REP
):
1901 if(game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
1902 rotate_ship(SHIP_ROT_CW_COS
, SHIP_ROT_CW_SIN
);
1905 case (AST_THRUST_REP
):
1907 if((game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
) && !next_thrust_count
)
1910 next_thrust_count
= 5;
1914 case (AST_HYPERSPACE
):
1915 if(game_state
== PLAY_MODE
)
1917 /*maybe shield if it gets too hard */
1920 case (AST_FIRE_REP
):
1922 if(game_state
== ATTRACT_MODE
)
1924 current_level
= START_LEVEL
;
1926 initialise_game(current_level
);
1927 show_level_timeout
= SHOW_LEVEL_TIME
;
1928 game_state
= PLAY_MODE
;
1930 else if(game_state
== PLAY_MODE
)
1932 if(!next_missile_count
)
1935 next_missile_count
= 10;
1938 else if(game_state
== PAUSE_MODE
)
1940 game_state
= PLAY_MODE
;
1945 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
)
1946 return PLUGIN_USB_CONNECTED
;
1952 if(high_score
< current_score
)
1953 high_score
= current_score
;
1958 if(next_missile_count
)
1959 next_missile_count
--;
1961 if(next_thrust_count
)
1962 next_thrust_count
--;
1964 if (end
> *rb
->current_tick
)
1965 rb
->sleep(end
-*rb
->current_tick
);
1973 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
1975 enum plugin_status retval
;
1979 game_state
= ATTRACT_MODE
;
1982 rb
->lcd_set_backdrop(NULL
);
1984 /* universal font */
1985 rb
->lcd_setfont(FONT_SYSFIXED
);
1986 /* Turn off backlight timeout */
1987 backlight_force_on(rb
); /* backlight control in lib/helper.c */
1989 retval
= start_game();
1991 rb
->lcd_setfont(FONT_UI
);
1992 /* Turn on backlight timeout (revert to settings) */
1993 backlight_use_settings(rb
); /* backlight control in lib/helper.c */