1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 by Mat Holton
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 #include "lib/display_text.h"
24 #include "lib/helper.h"
25 #include "lib/highscore.h"
26 #include "lib/playback_control.h"
30 /* variable button definitions */
31 #if CONFIG_KEYPAD == RECORDER_PAD
32 #define AST_PAUSE BUTTON_ON
33 #define AST_QUIT BUTTON_OFF
34 #define AST_THRUST BUTTON_UP
35 #define AST_HYPERSPACE BUTTON_DOWN
36 #define AST_LEFT BUTTON_LEFT
37 #define AST_RIGHT BUTTON_RIGHT
38 #define AST_FIRE BUTTON_PLAY
40 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
41 #define AST_PAUSE BUTTON_ON
42 #define AST_QUIT BUTTON_OFF
43 #define AST_THRUST BUTTON_UP
44 #define AST_HYPERSPACE BUTTON_DOWN
45 #define AST_LEFT BUTTON_LEFT
46 #define AST_RIGHT BUTTON_RIGHT
47 #define AST_FIRE BUTTON_SELECT
49 #elif CONFIG_KEYPAD == ONDIO_PAD
50 #define AST_PAUSE (BUTTON_MENU | BUTTON_OFF)
51 #define AST_QUIT BUTTON_OFF
52 #define AST_THRUST BUTTON_UP
53 #define AST_HYPERSPACE BUTTON_DOWN
54 #define AST_LEFT BUTTON_LEFT
55 #define AST_RIGHT BUTTON_RIGHT
56 #define AST_FIRE BUTTON_MENU
58 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
59 (CONFIG_KEYPAD == IRIVER_H300_PAD)
60 #define AST_PAUSE BUTTON_REC
61 #define AST_QUIT BUTTON_OFF
62 #define AST_THRUST BUTTON_UP
63 #define AST_HYPERSPACE BUTTON_DOWN
64 #define AST_LEFT BUTTON_LEFT
65 #define AST_RIGHT BUTTON_RIGHT
66 #define AST_FIRE BUTTON_SELECT
68 #define AST_RC_QUIT BUTTON_RC_STOP
70 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
71 #define AST_PAUSE BUTTON_PLAY
72 #define AST_QUIT BUTTON_POWER
73 #define AST_THRUST BUTTON_UP
74 #define AST_HYPERSPACE BUTTON_DOWN
75 #define AST_LEFT BUTTON_LEFT
76 #define AST_RIGHT BUTTON_RIGHT
77 #define AST_FIRE BUTTON_SELECT
79 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
80 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
81 #define AST_PAUSE (BUTTON_SELECT | BUTTON_PLAY)
82 #define AST_QUIT (BUTTON_SELECT | BUTTON_MENU)
83 #define AST_THRUST BUTTON_MENU
84 #define AST_HYPERSPACE BUTTON_PLAY
85 #define AST_LEFT BUTTON_SCROLL_BACK
86 #define AST_RIGHT BUTTON_SCROLL_FWD
87 #define AST_FIRE BUTTON_SELECT
89 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
90 #define AST_PAUSE BUTTON_A
91 #define AST_QUIT BUTTON_POWER
92 #define AST_THRUST BUTTON_UP
93 #define AST_HYPERSPACE BUTTON_DOWN
94 #define AST_LEFT BUTTON_LEFT
95 #define AST_RIGHT BUTTON_RIGHT
96 #define AST_FIRE BUTTON_SELECT
98 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
99 #define AST_PAUSE BUTTON_REC
100 #define AST_QUIT BUTTON_POWER
101 #define AST_THRUST BUTTON_UP
102 #define AST_HYPERSPACE BUTTON_DOWN
103 #define AST_LEFT BUTTON_SCROLL_BACK
104 #define AST_RIGHT BUTTON_SCROLL_FWD
105 #define AST_FIRE BUTTON_SELECT
107 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
108 #define AST_PAUSE (BUTTON_SELECT | BUTTON_UP)
109 #define AST_QUIT (BUTTON_HOME|BUTTON_REPEAT)
110 #define AST_THRUST BUTTON_UP
111 #define AST_HYPERSPACE BUTTON_DOWN
112 #define AST_LEFT BUTTON_SCROLL_BACK
113 #define AST_RIGHT BUTTON_SCROLL_FWD
114 #define AST_FIRE BUTTON_SELECT
116 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
117 #define AST_PAUSE BUTTON_REC
118 #define AST_QUIT BUTTON_POWER
119 #define AST_THRUST BUTTON_UP
120 #define AST_HYPERSPACE BUTTON_DOWN
121 #define AST_LEFT BUTTON_LEFT
122 #define AST_RIGHT BUTTON_RIGHT
123 #define AST_FIRE BUTTON_SELECT
125 #elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
126 #define AST_PAUSE BUTTON_HOME
127 #define AST_QUIT BUTTON_POWER
128 #define AST_THRUST BUTTON_UP
129 #define AST_HYPERSPACE BUTTON_DOWN
130 #define AST_LEFT BUTTON_LEFT
131 #define AST_RIGHT BUTTON_RIGHT
132 #define AST_FIRE BUTTON_SELECT
134 #elif (CONFIG_KEYPAD == SANSA_M200_PAD)
135 #define AST_PAUSE (BUTTON_SELECT | BUTTON_UP)
136 #define AST_QUIT BUTTON_POWER
137 #define AST_THRUST BUTTON_UP
138 #define AST_HYPERSPACE BUTTON_DOWN
139 #define AST_LEFT BUTTON_LEFT
140 #define AST_RIGHT BUTTON_RIGHT
141 #define AST_FIRE (BUTTON_SELECT | BUTTON_REL)
143 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
144 #define AST_PAUSE BUTTON_PLAY
145 #define AST_QUIT BUTTON_POWER
146 #define AST_THRUST BUTTON_SCROLL_UP
147 #define AST_HYPERSPACE BUTTON_SCROLL_DOWN
148 #define AST_LEFT BUTTON_LEFT
149 #define AST_RIGHT BUTTON_RIGHT
150 #define AST_FIRE BUTTON_REW
152 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
153 #define AST_PAUSE BUTTON_PLAY
154 #define AST_QUIT BUTTON_BACK
155 #define AST_THRUST BUTTON_UP
156 #define AST_HYPERSPACE BUTTON_DOWN
157 #define AST_LEFT BUTTON_LEFT
158 #define AST_RIGHT BUTTON_RIGHT
159 #define AST_FIRE BUTTON_SELECT
161 #elif (CONFIG_KEYPAD == MROBE100_PAD)
162 #define AST_PAUSE BUTTON_DISPLAY
163 #define AST_QUIT BUTTON_POWER
164 #define AST_THRUST BUTTON_UP
165 #define AST_HYPERSPACE BUTTON_DOWN
166 #define AST_LEFT BUTTON_LEFT
167 #define AST_RIGHT BUTTON_RIGHT
168 #define AST_FIRE BUTTON_SELECT
170 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
171 #define AST_PAUSE BUTTON_RC_PLAY
172 #define AST_QUIT BUTTON_RC_REC
173 #define AST_THRUST BUTTON_RC_VOL_UP
174 #define AST_HYPERSPACE BUTTON_RC_VOL_DOWN
175 #define AST_LEFT BUTTON_RC_REW
176 #define AST_RIGHT BUTTON_RC_FF
177 #define AST_FIRE BUTTON_RC_MODE
179 #elif (CONFIG_KEYPAD == COWOND2_PAD)
180 #define AST_QUIT BUTTON_POWER
182 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
183 #define AST_PAUSE BUTTON_PLAY
184 #define AST_QUIT BUTTON_BACK
185 #define AST_THRUST BUTTON_UP
186 #define AST_HYPERSPACE BUTTON_DOWN
187 #define AST_LEFT BUTTON_LEFT
188 #define AST_RIGHT BUTTON_RIGHT
189 #define AST_FIRE BUTTON_SELECT
191 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
192 #define AST_PAUSE BUTTON_VIEW
193 #define AST_QUIT BUTTON_POWER
194 #define AST_THRUST BUTTON_UP
195 #define AST_HYPERSPACE BUTTON_DOWN
196 #define AST_LEFT BUTTON_LEFT
197 #define AST_RIGHT BUTTON_RIGHT
198 #define AST_FIRE BUTTON_PLAYLIST
200 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || \
201 (CONFIG_KEYPAD == ONDAVX777_PAD) || \
202 CONFIG_KEYPAD == MROBE500_PAD
203 #define AST_QUIT BUTTON_POWER
205 #elif (CONFIG_KEYPAD == SAMSUNG_YH_PAD)
206 #define AST_PAUSE BUTTON_FFWD
207 #define AST_QUIT BUTTON_REC
208 #define AST_THRUST_REP (BUTTON_UP | BUTTON_REW)
209 #define AST_THRUST BUTTON_UP
210 #define AST_HYPERSPACE BUTTON_DOWN
211 #define AST_LEFT BUTTON_LEFT
212 #define AST_LEFT_REP (BUTTON_LEFT | BUTTON_REW)
213 #define AST_RIGHT BUTTON_RIGHT
214 #define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REW)
215 #define AST_FIRE BUTTON_PLAY
216 #define AST_FIRE_REP (BUTTON_PLAY | BUTTON_REW)
219 #error No keymap defined!
222 #ifdef HAVE_TOUCHSCREEN
224 #define AST_PAUSE BUTTON_CENTER
227 #define AST_QUIT BUTTON_TOPLEFT
229 #ifndef AST_THRUST_REP
230 #define AST_THRUST_REP (BUTTON_TOPMIDDLE | BUTTON_REPEAT)
233 #define AST_THRUST BUTTON_TOPMIDDLE
235 #ifndef AST_HYPERSPACE
236 #define AST_HYPERSPACE BUTTON_TOPRIGHT
239 #define AST_LEFT BUTTON_MIDLEFT
242 #define AST_LEFT_REP (BUTTON_MIDLEFT | BUTTON_REPEAT)
245 #define AST_RIGHT BUTTON_MIDRIGHT
247 #ifndef AST_RIGHT_REP
248 #define AST_RIGHT_REP (BUTTON_MIDRIGHT | BUTTON_REPEAT)
251 #define AST_FIRE BUTTON_BOTTOMMIDDLE
256 #define AST_FIRE_REP (BUTTON_BOTTOMMIDDLE | BUTTON_MENU)
258 #define AST_FIRE_REP BUTTON_BOTTOMMIDDLE | BUTTON_REPEAT
264 #define RES MAX(LCD_WIDTH, LCD_HEIGHT)
265 #define LARGE_LCD RES >= 200
266 #define ENEMY_MISSILE_SURVIVAL_LENGTH RES/2
267 #define ASTEROID_SPEED RES/20
268 #define MISSILE_SURVIVAL_LENGTH 40
272 #define EXTRA_LIFE 250
273 #define SPAWN_TIME 30
274 #define BLINK_TIME 10
276 #define MISSILE_SCALE 5000
278 #define EXPLOSION_LENGTH 20
281 #define MAX_NUM_ASTEROIDS 25
282 #define MAX_NUM_MISSILES 6
283 #define ENEMY_BIG_PROBABILITY_START 10
284 #define ENEMY_APPEAR_PROBABILITY_START 35
285 #define ENEMY_APPEAR_TIMING_START 1800
286 #define LITTLE_SHIP 2
288 #define SHOW_GAME_OVER_TIME 100
289 #define SHOW_LEVEL_TIME 50
290 #define START_LIVES 3
291 #define START_LEVEL 1
292 #define NUM_ASTEROID_VERTICES 10
293 #define NUM_SHIP_VERTICES 4
294 #define NUM_ENEMY_VERTICES 6
295 #define MAX_LEVEL MAX_NUM_ASTEROIDS
296 #define ENEMY_SPEED 4
297 #define SIZE_ENEMY_COLLISION 5*SCALE
299 #define NUM_TRAIL_POINTS 70
300 #define NUM_ROTATIONS 16
302 #define SIN_COS_SCALE 10000
304 #define FAST_ROT_CW_SIN 873
305 #define FAST_ROT_CW_COS 9963
306 #define FAST_ROT_ACW_SIN -873
307 #define FAST_ROT_ACW_COS 9963
309 #define MEDIUM_ROT_CW_SIN 350
310 #define MEDIUM_ROT_CW_COS 9994
311 #define MEDIUM_ROT_ACW_SIN -350
312 #define MEDIUM_ROT_ACW_COS 9994
314 #define SLOW_ROT_CW_SIN 350
315 #define SLOW_ROT_CW_COS 9994
316 #define SLOW_ROT_ACW_SIN - 350
317 #define SLOW_ROT_ACW_COS 9994
319 #ifdef HAVE_LCD_COLOR
320 #define SHIP_ROT_CW_SIN 2419
321 #define SHIP_ROT_CW_COS 9702
322 #define SHIP_ROT_ACW_SIN -2419
323 #define SHIP_ROT_ACW_COS 9702
325 #define SHIP_ROT_CW_SIN 3827
326 #define SHIP_ROT_CW_COS 9239
327 #define SHIP_ROT_ACW_SIN -3827
328 #define SHIP_ROT_ACW_COS 9239
332 #define SCALED_WIDTH (LCD_WIDTH*SCALE)
333 #define SCALED_HEIGHT (LCD_HEIGHT*SCALE)
334 #define CENTER_LCD_X (LCD_WIDTH/2)
335 #define CENTER_LCD_Y (LCD_HEIGHT/2)
337 #define SHIP_EXPLOSION_COLOUR 1
338 #define ASTEROID_EXPLOSION_COLOUR 2
339 #define ENEMY_EXPLOSION_COLOUR 3
340 #define THRUST_COLOUR 4
342 #define ASTEROID_R 230
343 #define ASTEROID_G 200
344 #define ASTEROID_B 100
355 #ifdef HAVE_LCD_COLOR
356 #define COL_MISSILE LCD_RGBPACK(200,0,0)
357 #define COL_PLAYER LCD_RGBPACK(200,200,200)
358 #define COL_INVULN LCD_RGBPACK(100,100,200)
359 #define COL_STARS LCD_WHITE
360 #define COL_ASTEROID LCD_RGBPACK(ASTEROID_R,ASTEROID_G,ASTEROID_B)
361 #define COL_TEXT LCD_RGBPACK(200,200,255)
362 #define COL_ENEMY LCD_RGBPACK(ENEMY_R,ENEMY_G,ENEMY_B)
363 #define SET_FG rb->lcd_set_foreground
364 #define SET_BG rb->lcd_set_background
372 #define HIGH_SCORE PLUGIN_GAMES_DIR "/spacerocks.score"
375 struct highscore highest
[NUM_SCORES
];
377 /* The array of points that make up an asteroid */
378 static const short asteroid_one
[NUM_ASTEROID_VERTICES
*2] =
392 /* The array of points that make up an asteroid */
393 static const short asteroid_two
[NUM_ASTEROID_VERTICES
*2] =
407 /* The array of points that make up an asteroid */
408 static const short asteroid_three
[NUM_ASTEROID_VERTICES
*2] =
422 /* The array od points the make up the ship */
423 static const short ship_vertices
[NUM_SHIP_VERTICES
*2] =
438 /* The array of points the make up the bad spaceship */
439 static const short enemy_vertices
[NUM_ENEMY_VERTICES
*2] =
492 struct Point position
;
499 /* Asteroid structure, contains an array of points */
502 enum asteroid_type type
;
504 struct Point position
;
505 struct Point vertices
[NUM_ASTEROID_VERTICES
];
509 int explode_countdown
;
514 struct Point vertices
[NUM_SHIP_VERTICES
];
515 struct Point position
;
516 bool waiting_for_space
;
519 int explode_countdown
;
524 struct Point vertices
[NUM_ENEMY_VERTICES
];
525 struct Point position
;
526 int explode_countdown
;
527 long last_time_appeared
;
528 short size_probability
;
529 short appear_probability
;
535 struct Point position
;
536 struct Point oldpoint
;
540 static enum game_state game_state
;
541 static int asteroid_count
;
542 static int next_missile_count
;
543 static int next_thrust_count
;
544 static int num_lives
;
545 static int extra_life
;
546 static int show_level_timeout
;
547 static int current_level
;
548 static int current_score
;
549 static int space_check_size
= 30*SCALE
;
551 static bool enemy_on_screen
;
552 static struct Ship ship
;
553 static struct Point stars
[NUM_STARS
];
554 static struct Asteroid asteroids_array
[MAX_NUM_ASTEROIDS
];
555 static struct Missile missiles_array
[MAX_NUM_MISSILES
];
556 static struct Missile enemy_missile
;
557 static struct Enemy enemy
;
558 static struct Point lives_points
[NUM_SHIP_VERTICES
];
559 static struct TrailPoint trailPoints
[NUM_TRAIL_POINTS
];
561 void draw_and_move_asteroids(void);
562 void initialise_game(int nStartNum
);
564 bool is_asteroid_near_ship(struct Asteroid
* asteroid
);
565 bool is_point_within_asteroid(struct Asteroid
* asteroid
, struct Point
* point
);
567 void initialise_asteroid(struct Asteroid
* asteroid
, enum asteroid_type eType
);
568 void draw_polygon(struct Point
* vertices
, int px
, int py
, int num_vertices
);
569 void rotate_asteroid(struct Asteroid
* asteroid
);
570 void create_asteroid(enum asteroid_type type
, int x
, int y
);
571 void create_stars(void);
573 void initialise_ship(void);
574 void draw_and_move_ship(void);
575 void rotate_ship(int s
, int c
);
576 void thrust_ship(void);
578 void initialise_missile(struct Missile
* missile
);
579 void draw_and_move_missiles(void);
580 void fire_missile(void);
582 void animate_and_draw_explosion(struct Point
* point
, int num_points
, int xoffset
, int yoffset
);
583 void initialise_explosion(struct Point
* point
, int num_points
);
585 void move_point(struct Point
* point
);
586 void hyperspace(void);
587 void check_collisions(void);
588 void initialise_enemy(void);
589 void draw_and_move_enemy(void);
590 void draw_lives(void);
591 void drawstars(void);
592 bool is_ship_within_asteroid(struct Asteroid
* asteroid
);
597 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
598 enemy
.appear_timing
= ENEMY_APPEAR_TIMING_START
;
599 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
600 current_level
= START_LEVEL
;
601 num_lives
= START_LIVES
;
604 initialise_game(current_level
);
605 show_level_timeout
= SHOW_LEVEL_TIME
;
606 game_state
= PLAY_MODE
;
609 static bool spacerocks_help(void)
611 rb
->lcd_setfont(FONT_UI
);
612 #define WORDS (sizeof help_text / sizeof (char*))
613 static char *help_text
[] = {
614 "Spacerocks", "", "Aim", "", "The", "goal", "of", "the", "game", "is",
615 "to", "blow", "up", "the", "asteroids", "and", "avoid", "being", "hit", "by",
616 "them.", "Also", "you'd", "better", "watch", "out", "for", "the", "UFOs!"
618 static struct style_text formation
[]={
619 { 0, TEXT_CENTER
|TEXT_UNDERLINE
},
623 #ifdef HAVE_LCD_COLOR
624 rb
->lcd_set_background(LCD_BLACK
);
625 rb
->lcd_set_foreground(LCD_WHITE
);
628 if (display_text(WORDS
, help_text
, formation
, NULL
)==PLUGIN_USB_CONNECTED
)
631 button
= rb
->button_get(true);
632 if (button
== SYS_USB_CONNECTED
) {
635 } while( ( button
== BUTTON_NONE
)
636 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
637 rb
->lcd_setfont(FONT_SYSFIXED
);
643 static int spacerocks_menu_cb(int action
, const struct menu_item_ex
*this_item
)
645 if(action
== ACTION_REQUEST_MENUITEM
646 && !_ingame
&& ((intptr_t)this_item
)==0)
647 return ACTION_EXIT_MENUITEM
;
651 static int spacerocks_menu(bool ingame
)
653 rb
->button_clear_queue();
658 MENUITEM_STRINGLIST (main_menu
, "Spacerocks Menu", spacerocks_menu_cb
,
667 choice
= rb
->do_menu(&main_menu
, &choice
, NULL
, false);
675 if(spacerocks_help())
679 highscore_show(NUM_SCORES
, highest
, NUM_SCORES
, true);
682 playback_control(NULL
);
686 case MENU_ATTACHED_USB
:
694 bool point_in_poly(struct Point
* _point
, int num_vertices
, int x
, int y
)
703 pj
+= num_vertices
-1;
708 if((((pi
->y
<= y
) && (y
< pj
->y
)) || ((pj
->y
<= y
) && (y
< pi
->y
))) &&
709 (x
< (pj
->x
- pi
->x
) * (y
- pi
->y
) / (pj
->y
- pi
->y
) + pi
->x
))
712 if(n
== num_vertices
- 1)
723 void move_point(struct Point
* point
)
725 point
->x
+= point
->dx
;
726 point
->y
+= point
->dy
;
728 /*check bounds on the x-axis:*/
729 if(point
->x
>= SCALED_WIDTH
)
731 else if(point
->x
<= 0)
732 point
->x
= SCALED_WIDTH
;
734 /*Check bounds on the y-axis:*/
735 if(point
->y
>= SCALED_HEIGHT
)
737 else if(point
->y
<= 0)
738 point
->y
= SCALED_HEIGHT
;
741 void create_trail(struct TrailPoint
* tpoint
)
743 tpoint
->position
.dx
= -( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/10;
744 tpoint
->position
.dy
= -( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/10;
747 void create_explosion_trail(struct TrailPoint
* tpoint
)
749 tpoint
->position
.dx
= (rb
->rand()%5050)-2500;
750 tpoint
->position
.dy
= (rb
->rand()%5050)-2500;
753 void create_trail_blaze(int colour
, struct Point
* position
)
756 struct TrailPoint
* tpoint
;
759 if(colour
!= SHIP_EXPLOSION_COLOUR
)
761 numtoadd
= NUM_TRAIL_POINTS
/5;
767 numtoadd
= NUM_TRAIL_POINTS
/8;
768 xadd
= ship
.position
.x
;
769 yadd
= ship
.position
.y
;
772 /* give the point a random countdown timer, so they dissapears at different times */
773 tpoint
= trailPoints
;
774 n
= NUM_TRAIL_POINTS
;
777 if(tpoint
->alive
<= 0 && numtoadd
)
780 /* take a random x point anywhere between bottom two points of ship. */
781 /* ship.position.x; */
782 tpoint
->position
.x
= (ship
.vertices
[2].x
+ (rb
->rand()%18000)-9000) + position
->x
;
783 tpoint
->position
.y
= (ship
.vertices
[2].y
+ (rb
->rand()%18000)-9000) + position
->y
;
787 case SHIP_EXPLOSION_COLOUR
:
791 create_explosion_trail(tpoint
);
795 case ASTEROID_EXPLOSION_COLOUR
:
796 tpoint
->r
= ASTEROID_R
;
797 tpoint
->g
= ASTEROID_G
;
798 tpoint
->b
= ASTEROID_B
;
799 create_explosion_trail(tpoint
);
803 case ENEMY_EXPLOSION_COLOUR
:
807 create_explosion_trail(tpoint
);
812 tpoint
->r
= THRUST_R
;
813 tpoint
->g
= THRUST_G
;
814 tpoint
->b
= THRUST_B
;
815 create_trail(tpoint
);
820 /* add a proportional bit to the x and y based on dx and dy */
822 /* give the points a speed based on direction of travel - i.e. opposite */
823 tpoint
->position
.dx
+= position
->dx
;
824 tpoint
->position
.dy
+= position
->dy
;
830 /* find a space in the array of trail_points that is NULL or DEAD or whatever.
831 and place this one here. */
835 void draw_trail_blaze(void)
837 struct TrailPoint
* tpoint
;
838 /* loop through, if alive then move and draw.
839 when drawn, countdown it's timer.
841 tpoint
= trailPoints
;
842 int n
= NUM_TRAIL_POINTS
;
848 if(game_state
!= PAUSE_MODE
)
851 move_point(&(tpoint
->position
));
853 #ifdef HAVE_LCD_COLOR
854 /* intensity = tpoint->alive/2; */
855 if(tpoint
->r
>0)tpoint
->r
-=tpoint
->dec
;
856 if(tpoint
->g
>0)tpoint
->g
-=tpoint
->dec
;
857 if(tpoint
->b
>0)tpoint
->b
-=tpoint
->dec
;
858 SET_FG(LCD_RGBPACK(tpoint
->r
, tpoint
->g
, tpoint
->b
));
860 rb
->lcd_drawpixel(tpoint
->position
.x
/SCALE
, tpoint
->position
.y
/SCALE
);
866 /*Check if point is within a rectangle*/
867 bool is_point_within_rectangle(struct Point
* rect
, struct Point
* p
, int size
)
870 int aTLx
= rect
->x
- size
;
871 int aTLy
= rect
->y
- size
;
872 int aBRx
= rect
->x
+ size
;
873 int aBRy
= rect
->y
+ size
;
874 rb
->lcd_hline( aTLx
/SCALE
, aBRx
/SCALE
, aTLy
/SCALE
);
875 rb
->lcd_vline( aTLx
/SCALE
, aTLy
/SCALE
, aBRy
/SCALE
);
876 rb
->lcd_hline( aTLx
/SCALE
, aBRx
/SCALE
, aBRy
/SCALE
);
877 rb
->lcd_vline( aBRx
/SCALE
, aBRy
/SCALE
, aTLy
/SCALE
);
878 return (p
->x
> aTLx
&& p
->x
< aBRx
&& p
->y
> aTLy
&& p
->y
< aBRy
);
880 return (p
->x
> rect
->x
- size
&& p
->x
< rect
->x
+ size
&&
881 p
->y
> rect
->y
- size
&& p
->y
< rect
->y
+ size
);
886 void draw_polygon(struct Point
* vertices
, int px
, int py
, int num_vertices
)
888 int n
, t1
, t2
, oldX
, oldY
;
890 bool bDrawAll
= px
< WRAP_GAP
|| LCD_WIDTH
- px
< WRAP_GAP
||
891 py
< WRAP_GAP
|| LCD_HEIGHT
- py
< WRAP_GAP
;
895 oldX
= p
->x
/SCALE
+ px
;
896 oldY
= p
->y
/SCALE
+ py
;
898 for(n
= num_vertices
+1; --n
;)
900 t1
= p
->x
/SCALE
+ px
;
901 t2
= p
->y
/SCALE
+ py
;
903 rb
->lcd_drawline(oldX
, oldY
, t1
, t2
);
907 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
, t1
- LCD_WIDTH
, t2
);
908 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
, t1
+ LCD_WIDTH
, t2
);
909 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
+ LCD_HEIGHT
,
910 t1
- LCD_WIDTH
, t2
+ LCD_HEIGHT
);
911 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
+ LCD_HEIGHT
,
912 t1
+ LCD_WIDTH
, t2
+ LCD_HEIGHT
);
914 rb
->lcd_drawline(oldX
, oldY
- LCD_HEIGHT
, t1
, t2
- LCD_HEIGHT
);
915 rb
->lcd_drawline(oldX
, oldY
+ LCD_HEIGHT
, t1
, t2
+ LCD_HEIGHT
);
916 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
- LCD_HEIGHT
,
917 t1
- LCD_WIDTH
, t2
- LCD_HEIGHT
);
918 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
- LCD_HEIGHT
,
919 t1
+ LCD_WIDTH
, t2
- LCD_HEIGHT
);
927 void animate_and_draw_explosion(struct Point
* point
, int num_points
,
928 int xoffset
, int yoffset
)
931 for(n
= num_points
; --n
;)
933 if(game_state
!= PAUSE_MODE
)
935 point
->x
+= point
->dx
;
936 point
->y
+= point
->dy
;
938 rb
->lcd_fillrect( point
->x
/SCALE
+ xoffset
, point
->y
/SCALE
+ yoffset
,
939 POINT_SIZE
, POINT_SIZE
);
944 /*stop movement of ship, 'cos that's what happens when you go into hyperspace.*/
945 void hyperspace(void)
947 ship
.position
.dx
= ship
.position
.dy
= 0;
948 ship
.position
.x
= (rb
->rand()%SCALED_WIDTH
);
949 ship
.position
.y
= (rb
->rand()%SCALED_HEIGHT
);
952 void initialise_enemy(void)
958 if(rb
->rand()%100 > enemy
.size_probability
)
961 enemy
.size_probability
++;
962 if(enemy
.size_probability
< 90)
964 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
972 enemy_missile
.survived
= 0;
973 enemy_on_screen
= true;
974 enemy
.explode_countdown
= 0;
975 enemy
.last_time_appeared
= *rb
->current_tick
;
976 point
= enemy
.vertices
;
977 for(n
= 0; n
< NUM_ENEMY_VERTICES
+NUM_ENEMY_VERTICES
; n
+=2)
979 point
->x
= enemy_vertices
[n
];
980 point
->y
= enemy_vertices
[n
+1];
981 point
->x
*= SCALE
/size
;
982 point
->y
*= SCALE
/size
;
986 if(ship
.position
.x
>= SCALED_WIDTH
/2)
988 enemy
.position
.dx
= ENEMY_SPEED
;
989 enemy
.position
.x
= 0;
993 enemy
.position
.dx
= -ENEMY_SPEED
;
994 enemy
.position
.x
= SCALED_WIDTH
;
997 if(ship
.position
.y
>= SCALED_HEIGHT
/2)
999 enemy
.position
.dy
= ENEMY_SPEED
;
1000 enemy
.position
.y
= 0;
1004 enemy
.position
.dy
= -ENEMY_SPEED
;
1005 enemy
.position
.y
= SCALED_HEIGHT
;
1008 enemy
.position
.dx
*= SCALE
/10;
1009 enemy
.position
.dy
*= SCALE
/10;
1012 void draw_and_move_enemy(void)
1014 int enemy_x
, enemy_y
;
1015 struct Point
*point
;
1021 enemy_x
= enemy
.position
.x
/SCALE
;
1022 enemy_y
= enemy
.position
.y
/SCALE
;
1023 if(!enemy
.explode_countdown
)
1025 point
= enemy
.vertices
;
1026 draw_polygon(enemy
.vertices
, enemy_x
, enemy_y
, NUM_ENEMY_VERTICES
);
1027 rb
->lcd_drawline(enemy
.vertices
[0].x
/SCALE
+ enemy_x
,
1028 enemy
.vertices
[0].y
/SCALE
+ enemy_y
,
1029 enemy
.vertices
[3].x
/SCALE
+ enemy_x
,
1030 enemy
.vertices
[3].y
/SCALE
+ enemy_y
);
1032 if(game_state
!= PAUSE_MODE
)
1034 enemy
.position
.x
+= enemy
.position
.dx
;
1035 enemy
.position
.y
+= enemy
.position
.dy
;
1038 if(enemy
.position
.x
> SCALED_WIDTH
|| enemy
.position
.x
< 0)
1039 enemy_on_screen
= false;
1041 if(enemy
.position
.y
> SCALED_HEIGHT
)
1042 enemy
.position
.y
= 0;
1043 else if(enemy
.position
.y
< 0)
1044 enemy
.position
.y
= SCALED_HEIGHT
;
1046 if( (rb
->rand()%1000) < 10)
1047 enemy
.position
.dy
= -enemy
.position
.dy
;
1052 /* animate_and_draw_explosion(enemy.vertices, NUM_ENEMY_VERTICES,
1053 enemy_x, enemy.position.y/SCALE); */
1054 if(game_state
!= PAUSE_MODE
)
1056 enemy
.explode_countdown
--;
1057 if(!enemy
.explode_countdown
)
1058 enemy_on_screen
= false;
1064 if( (*rb
->current_tick
- enemy
.last_time_appeared
) > enemy
.appear_timing
)
1065 if(rb
->rand()%100 > enemy
.appear_probability
) initialise_enemy();
1068 if(!enemy_missile
.survived
&& game_state
!= GAME_OVER
)
1070 /*if no missile and the enemy is here and not exploding..then shoot baby!*/
1071 if( !enemy
.explode_countdown
&& enemy_on_screen
&&
1072 !ship
.waiting_for_space
&& (rb
->rand()%10) > 5 )
1074 enemy_missile
.position
.x
= enemy
.position
.x
;
1075 enemy_missile
.position
.y
= enemy
.position
.y
;
1077 /*lame, needs to be sorted - it's trying to shoot at the ship*/
1078 if(ABS(enemy
.position
.y
- ship
.position
.y
) <= 5*SCALE
)
1080 enemy_missile
.position
.dy
= 0;
1084 if( enemy
.position
.y
< ship
.position
.y
)
1085 enemy_missile
.position
.dy
= 1;
1087 enemy_missile
.position
.dy
= -1;
1090 if(ABS(enemy
.position
.x
- ship
.position
.x
) <= 5*SCALE
)
1091 enemy_missile
.position
.dx
= 0;
1094 if( enemy
.position
.x
< ship
.position
.x
)
1095 enemy_missile
.position
.dx
= 1;
1097 enemy_missile
.position
.dx
= -1;
1100 if(enemy_missile
.position
.dx
== 0 &&
1101 enemy_missile
.position
.dy
== 0)
1102 enemy_missile
.position
.dx
= enemy_missile
.position
.dy
= -1;
1104 enemy_missile
.position
.dx
*= SCALE
;
1105 enemy_missile
.position
.dy
*= SCALE
;
1106 enemy_missile
.survived
= ENEMY_MISSILE_SURVIVAL_LENGTH
;
1112 rb
->lcd_fillrect( enemy_missile
.position
.x
/SCALE
,
1113 enemy_missile
.position
.y
/SCALE
,
1114 POINT_SIZE
, POINT_SIZE
);
1115 if(game_state
!= PAUSE_MODE
)
1117 move_point(&enemy_missile
.position
);
1118 enemy_missile
.survived
--;
1124 * Lame method of collision
1125 * detection. It's checking for collision
1126 * between point and a big rectangle around the asteroid...
1127 *******************/
1128 bool is_point_within_asteroid(struct Asteroid
* asteroid
, struct Point
* point
)
1130 if( !is_point_within_rectangle(&asteroid
->position
, point
,
1131 asteroid
->radius
+4*SCALE
) )
1134 if(point_in_poly(asteroid
->vertices
, NUM_ASTEROID_VERTICES
,
1135 point
->x
- asteroid
->position
.x
,
1136 point
->y
- asteroid
->position
.y
))
1138 switch(asteroid
->type
)
1141 asteroid
->explode_countdown
= EXPLOSION_LENGTH
;
1142 create_trail_blaze(ASTEROID_EXPLOSION_COLOUR
, &asteroid
->position
);
1146 create_asteroid(MEDIUM
, asteroid
->position
.x
,
1147 asteroid
->position
.y
);
1148 create_asteroid(MEDIUM
, asteroid
->position
.x
,
1149 asteroid
->position
.y
);
1153 create_asteroid(SMALL
, asteroid
->position
.x
, asteroid
->position
.y
);
1154 create_asteroid(SMALL
, asteroid
->position
.x
, asteroid
->position
.y
);
1159 if(current_score
> extra_life
)
1162 extra_life
= current_score
+EXTRA_LIFE
;
1165 asteroid
->exists
= false;
1172 bool is_point_within_enemy(struct Point
* point
)
1174 if( is_point_within_rectangle(&enemy
.position
, point
, 7*SCALE
) )
1177 /*enemy_missile.survived = 0;*/
1178 enemy
.explode_countdown
= EXPLOSION_LENGTH
;
1179 /* initialise_explosion(enemy.vertices, NUM_ENEMY_VERTICES); */
1180 create_trail_blaze(ENEMY_EXPLOSION_COLOUR
, &enemy
.position
);
1187 bool is_ship_within_asteroid(struct Asteroid
* asteroid
)
1192 p
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1193 p
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1194 hit
|= is_point_within_asteroid(asteroid
, &p
);
1198 p
.x
= ship
.position
.x
+ ship
.vertices
[1].x
;
1199 p
.y
= ship
.position
.y
+ ship
.vertices
[1].y
;
1200 hit
|= is_point_within_asteroid(asteroid
, &p
);
1203 p
.x
= ship
.position
.x
+ ship
.vertices
[3].x
;
1204 p
.y
= ship
.position
.y
+ ship
.vertices
[3].y
;
1205 hit
|= is_point_within_asteroid(asteroid
, &p
);
1212 void initialise_explosion(struct Point
* point
, int num_points
)
1216 point
->x
+= point
->dx
;
1217 point
->y
+= point
->dy
;
1218 for(n
= num_points
; --n
;)
1220 point
->dx
= point
->x
;
1221 point
->dy
= point
->y
;
1227 /* Check for collsions between the missiles and the asteroids and the ship */
1228 void check_collisions(void)
1231 bool asteroids_onscreen
= false;
1232 struct Missile
* missile
;
1233 struct Asteroid
* asteroid
;
1234 bool ship_cant_be_placed
= false;
1236 asteroid
= asteroids_array
;
1237 m
= MAX_NUM_ASTEROIDS
;
1240 /*if the asteroids exists then test missile collision:*/
1241 if(asteroid
->exists
)
1243 missile
= missiles_array
;
1244 n
= MAX_NUM_MISSILES
;
1247 /*if the missiles exists:*/
1248 if(missile
->survived
> 0)
1250 /*has the missile hit the asteroid?*/
1251 if(is_point_within_asteroid(asteroid
, &missile
->position
)
1252 || is_point_within_asteroid(asteroid
,
1253 &missile
->oldpoint
))
1255 missile
->survived
= 0;
1262 /*now check collision with ship:*/
1263 if(asteroid
->exists
&& !ship
.waiting_for_space
&& !ship
.explode_countdown
)
1265 if(is_ship_within_asteroid(asteroid
))
1267 if (!ship
.invulnerable
)
1269 /*if not invulnerable, blow up ship*/
1270 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1271 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1272 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1276 /*has the enemy missile blown something up?*/
1277 if(asteroid
->exists
&& enemy_missile
.survived
)
1279 if(is_point_within_asteroid(asteroid
, &enemy_missile
.position
))
1281 /*take that score back then:*/
1282 if(current_score
> 0) current_score
--;
1283 enemy_missile
.survived
= 0;
1286 /*if it still exists, check if ship is waiting for space:*/
1287 if(asteroid
->exists
&& ship
.waiting_for_space
)
1288 ship_cant_be_placed
|=
1289 is_point_within_rectangle(&ship
.position
,
1290 &asteroid
->position
,
1295 /*is an asteroid still exploding?*/
1296 if(asteroid
->explode_countdown
)
1297 asteroids_onscreen
= true;
1302 /*now check collision between ship and enemy*/
1303 if(enemy_on_screen
&& !ship
.waiting_for_space
&&
1304 !ship
.explode_countdown
&& !enemy
.explode_countdown
)
1306 /*has the enemy collided with the ship?*/
1307 if(is_point_within_enemy(&ship
.position
))
1309 if (!ship
.invulnerable
)
1311 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1312 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1313 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1315 create_trail_blaze(ENEMY_EXPLOSION_COLOUR
, &enemy
.position
);
1318 /*Now see if the enemy has been shot at by the ships missiles:*/
1319 missile
= missiles_array
;
1320 n
= MAX_NUM_MISSILES
;
1323 if(missile
->survived
> 0 &&
1324 is_point_within_enemy(&missile
->position
))
1326 missile
->survived
= 0;
1333 /*test collision with enemy missile and ship:*/
1334 if(!ship_cant_be_placed
&& enemy_missile
.survived
> 0 &&
1335 point_in_poly(ship
.vertices
, NUM_SHIP_VERTICES
,
1336 enemy_missile
.position
.x
- ship
.position
.x
,
1337 enemy_missile
.position
.y
- ship
.position
.y
))
1339 if (!ship
.invulnerable
)
1341 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1342 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1343 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1345 enemy_missile
.survived
= 0;
1346 enemy_missile
.position
.x
= enemy_missile
.position
.y
= 0;
1349 if(!ship_cant_be_placed
)
1350 ship
.waiting_for_space
= false;
1352 /*if all asteroids cleared then start again:*/
1353 if(asteroid_count
== 0 && !enemy_on_screen
&& !asteroids_onscreen
)
1356 game_state
= SHOW_LEVEL
;
1357 enemy
.appear_probability
+= 5;
1358 enemy
.appear_timing
-= 200;
1359 if( enemy
.appear_probability
> 100)
1360 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1361 show_level_timeout
= SHOW_LEVEL_TIME
;
1365 /*************************************************
1366 ** Creates a new asteroid of the given 4type (size)
1367 ** and at the given location.
1368 *************************************************/
1369 void create_asteroid(enum asteroid_type type
, int x
, int y
)
1371 struct Asteroid
* asteroid
;
1374 asteroid
= asteroids_array
;
1375 n
= MAX_NUM_ASTEROIDS
;
1378 if(!asteroid
->exists
&& !asteroid
->explode_countdown
)
1380 initialise_asteroid(asteroid
, type
);
1381 asteroid
->position
.x
= x
;
1382 asteroid
->position
.y
= y
;
1389 /* Initialise a missile */
1390 void initialise_missile(struct Missile
* missile
)
1392 missile
->position
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1393 missile
->position
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1394 missile
->position
.dx
= (ship
.vertices
[0].x
- ship
.vertices
[2].x
)/2;
1395 missile
->position
.dy
= (ship
.vertices
[0].y
- ship
.vertices
[2].y
)/2;
1396 missile
->survived
= MISSILE_SURVIVAL_LENGTH
;
1397 missile
->oldpoint
.x
= missile
->position
.x
;
1398 missile
->oldpoint
.y
= missile
->position
.y
;
1401 /* Draw and Move all the missiles */
1402 void draw_and_move_missiles(void)
1408 struct Missile
* missile
;
1409 missile
= missiles_array
;
1411 SET_FG(COL_MISSILE
);
1413 n
= MAX_NUM_MISSILES
;
1416 if(missile
->survived
)
1418 if(missile
->position
.dx
> 0)
1420 if(missile
->position
.x
>= missile
->oldpoint
.x
)
1422 p1x
= missile
->oldpoint
.x
;
1423 p2x
= missile
->position
.x
;
1428 p2x
= missile
->position
.x
;
1433 if(missile
->oldpoint
.x
>= missile
->position
.x
)
1435 p1x
= missile
->oldpoint
.x
;
1436 p2x
= missile
->position
.x
;
1440 p1x
= missile
->oldpoint
.x
;
1445 if(missile
->position
.dy
> 0)
1447 if(missile
->position
.y
>= missile
->oldpoint
.y
)
1449 p1y
= missile
->oldpoint
.y
;
1450 p2y
= missile
->position
.y
;
1455 p2y
= missile
->position
.y
;
1460 if(missile
->oldpoint
.y
>= missile
->position
.y
)
1462 p1y
= missile
->oldpoint
.y
;
1463 p2y
= missile
->position
.y
;
1467 p1y
= missile
->oldpoint
.y
;
1472 rb
->lcd_drawline( p1x
/SCALE
, p1y
/SCALE
, p2x
/SCALE
, p2y
/SCALE
);
1474 if(game_state
!= PAUSE_MODE
)
1476 missile
->oldpoint
.x
= missile
->position
.x
;
1477 missile
->oldpoint
.y
= missile
->position
.y
;
1478 move_point(&missile
->position
);
1479 missile
->survived
--;
1486 void draw_lives(void)
1489 int px
= (LCD_WIDTH
- num_lives
*4 - 1);
1491 int py
= (LCD_HEIGHT
-6);
1493 int py
= (LCD_HEIGHT
-4);
1501 draw_polygon(lives_points
, px
, py
, NUM_SHIP_VERTICES
);
1510 /*Fire the next missile*/
1511 void fire_missile(void)
1514 struct Missile
* missile
;
1516 if(!ship
.explode_countdown
&& !ship
.waiting_for_space
)
1518 missile
= missiles_array
;
1519 n
= MAX_NUM_MISSILES
;
1522 if(!missile
->survived
)
1524 initialise_missile(missile
);
1532 /* Initialise the passed Asteroid */
1533 void initialise_asteroid(struct Asteroid
* asteroid
, enum asteroid_type type
)
1537 struct Point
* point
;
1538 asteroid
->exists
= true;
1539 asteroid
->type
= type
;
1540 asteroid
->explode_countdown
= 0;
1542 /*Set the radius of the asteroid:*/
1543 asteroid
->radius
= (int)type
*SCALE
;
1545 /*shall we move Clockwise and Fast*/
1546 if((rb
->rand()%100)>75)
1548 asteroid
->speed_cos
= FAST_ROT_CW_COS
;
1549 asteroid
->speed_sin
= FAST_ROT_CW_SIN
;
1551 else if((rb
->rand()%100)>75)
1553 asteroid
->speed_cos
= FAST_ROT_ACW_COS
;
1554 asteroid
->speed_sin
= FAST_ROT_ACW_SIN
;
1556 else if((rb
->rand()%100)>75)
1558 asteroid
->speed_cos
= SLOW_ROT_ACW_COS
;
1559 asteroid
->speed_sin
= SLOW_ROT_ACW_SIN
;
1563 asteroid
->speed_cos
= SLOW_ROT_CW_COS
;
1564 asteroid
->speed_sin
= SLOW_ROT_CW_SIN
;
1567 b
= (rb
->rand()%100)>66;
1568 b2
= (rb
->rand()%100)>66;
1569 point
= asteroid
->vertices
;
1570 for(n
= 0; n
< NUM_ASTEROID_VERTICES
*2; n
+=2)
1574 point
->x
= asteroid_one
[n
];
1575 point
->y
= asteroid_one
[n
+1];
1579 point
->x
= asteroid_two
[n
];
1580 point
->y
= asteroid_two
[n
+1];
1584 point
->x
= asteroid_three
[n
];
1585 point
->y
= asteroid_three
[n
+1];
1588 point
->x
*= asteroid
->radius
/6;
1589 point
->y
*= asteroid
->radius
/6;
1594 asteroid
->radius
+= 6*SCALE
;
1595 if(asteroid
->type
== SMALL
)
1596 asteroid
->radius
/= 3;/*2*/
1597 else if(asteroid
->type
== LARGE
)
1598 asteroid
->radius
+= 3*SCALE
;/*2*/
1602 /*Set the position randomly:*/
1603 asteroid
->position
.x
= (rb
->rand()%SCALED_WIDTH
);
1604 asteroid
->position
.y
= (rb
->rand()%SCALED_HEIGHT
);
1606 asteroid
->position
.dx
= 0;
1607 while(asteroid
->position
.dx
== 0)
1608 asteroid
->position
.dx
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
1610 asteroid
->position
.dy
= 0;
1611 while(asteroid
->position
.dy
== 0)
1612 asteroid
->position
.dy
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
1614 asteroid
->position
.dx
*= SCALE
/10;
1615 asteroid
->position
.dy
*= SCALE
/10;
1617 b
= is_point_within_rectangle(&ship
.position
, &asteroid
->position
,
1621 /*Now rotate the asteroid a bit, so they all look a bit different*/
1622 for(n
=(rb
->rand()%30) + 2;--n
;)
1623 rotate_asteroid(asteroid
);
1625 /*great, we've created an asteroid, don't forget to increment the total:*/
1629 /*Initialise the ship*/
1630 void initialise_ship(void)
1632 struct Point
* point
;
1633 struct Point
* lives_point
;
1636 ship
.position
.x
= CENTER_LCD_X
;
1637 ship
.position
.y
= CENTER_LCD_Y
;
1638 ship
.position
.x
*= SCALE
;
1639 ship
.position
.y
*= SCALE
;
1640 ship
.position
.dx
= ship
.position
.dy
= 0;
1641 ship
.spawn_time
= SPAWN_TIME
;
1642 ship
.invulnerable
= 1;
1644 point
= ship
.vertices
;
1645 lives_point
= lives_points
;
1646 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+=2)
1648 point
->x
= ship_vertices
[n
];
1649 point
->y
= ship_vertices
[n
+1];
1656 ship
.position
.dx
= 0;
1657 ship
.position
.dy
= 0;
1658 ship
.explode_countdown
= 0;
1660 /*grab a copy of the ships points for the lives display:*/
1661 point
= ship
.vertices
;
1662 lives_point
= lives_points
;
1663 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+=2)
1665 lives_point
->x
= point
->x
;
1666 lives_point
->y
= point
->y
;
1672 void rotate_asteroid(struct Asteroid
* asteroid
)
1674 struct Point
* point
;
1678 point
= asteroid
->vertices
;
1679 for(n
= NUM_ASTEROID_VERTICES
+1; --n
;)
1682 point
->x
= xtemp
*asteroid
->speed_cos
/SIN_COS_SCALE
-
1683 point
->y
*asteroid
->speed_sin
/SIN_COS_SCALE
;
1684 point
->y
= point
->y
*asteroid
->speed_cos
/SIN_COS_SCALE
+
1685 xtemp
*asteroid
->speed_sin
/SIN_COS_SCALE
;
1690 /*************************************************
1691 ** Draws the ship, moves the ship and creates a new
1692 ** one if it's finished exploding.
1693 **************************************************/
1694 void draw_and_move_ship(void)
1696 int nxoffset
= ship
.position
.x
/SCALE
;
1697 int nyoffset
= ship
.position
.y
/SCALE
;
1698 if (ship
.invulnerable
&& (ship
.spawn_time
> BLINK_TIME
|| ship
.spawn_time
% 2 == 0))
1706 if(!ship
.explode_countdown
)
1708 /* make sure ship is invulnerable until spawn time over */
1709 if (ship
.spawn_time
)
1712 if (ship
.spawn_time
<= 0)
1714 ship
.invulnerable
= 0;
1717 if(!ship
.waiting_for_space
)
1719 draw_polygon(ship
.vertices
, nxoffset
, nyoffset
, NUM_SHIP_VERTICES
);
1720 if(game_state
!= PAUSE_MODE
&& game_state
!= GAME_OVER
)
1722 move_point(&ship
.position
);
1728 /* animate_and_draw_explosion(ship.vertices, NUM_SHIP_VERTICES,
1729 ship.position.x/SCALE,
1730 ship.position.y/SCALE); */
1731 if(game_state
!= PAUSE_MODE
)
1733 ship
.explode_countdown
--;
1734 if(!ship
.explode_countdown
)
1739 game_state
= GAME_OVER
;
1744 ship
.waiting_for_space
= true;
1751 void thrust_ship(void)
1753 if(!ship
.waiting_for_space
)
1755 ship
.position
.dx
+= ( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/20;
1756 ship
.position
.dy
+= ( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/20;
1757 /*if dx and dy are below a certain threshold, then set 'em to 0
1758 but to do this we need to ascertain if the spacehip as moved on screen
1759 for more than a certain amount. */
1761 create_trail_blaze(THRUST_COLOUR
, &ship
.position
);
1765 /**************************************************
1766 ** Rotate the ship using the passed sin & cos values
1767 ***************************************************/
1768 void rotate_ship(int c
, int s
)
1770 struct Point
* point
;
1774 if(!ship
.waiting_for_space
&& !ship
.explode_countdown
)
1776 point
= ship
.vertices
;
1777 for(n
=NUM_SHIP_VERTICES
+1;--n
;)
1780 point
->x
= xtemp
*c
/SIN_COS_SCALE
- point
->y
*s
/SIN_COS_SCALE
;
1781 point
->y
= point
->y
*c
/SIN_COS_SCALE
+ xtemp
*s
/SIN_COS_SCALE
;
1797 rb
->lcd_drawpixel(p
->x
, p
->y
);
1802 /*************************************************
1803 ** Draw And Move all Asteroids
1804 *************************************************/
1805 void draw_and_move_asteroids(void)
1808 struct Asteroid
* asteroid
;
1810 asteroid
= asteroids_array
;
1811 SET_FG(COL_ASTEROID
);
1813 n
= MAX_NUM_ASTEROIDS
;
1816 if(game_state
!= PAUSE_MODE
)
1818 if(asteroid
->exists
)
1820 move_point(&asteroid
->position
);
1821 rotate_asteroid(asteroid
);
1822 draw_polygon(asteroid
->vertices
, asteroid
->position
.x
/SCALE
,
1823 asteroid
->position
.y
/SCALE
,
1824 NUM_ASTEROID_VERTICES
);
1826 else if(asteroid
->explode_countdown
)
1828 /* animate_and_draw_explosion(asteroid->vertices,
1829 NUM_ASTEROID_VERTICES,
1830 asteroid->position.x/SCALE,
1831 asteroid->position.y/SCALE); */
1832 asteroid
->explode_countdown
--;
1837 if(asteroid
->exists
)
1838 draw_polygon(asteroid
->vertices
,
1839 asteroid
->position
.x
/SCALE
,
1840 asteroid
->position
.y
/SCALE
,
1841 NUM_ASTEROID_VERTICES
);
1847 void create_stars(void)
1849 struct TrailPoint
* tpoint
;
1857 p
->x
= (rb
->rand()%LCD_WIDTH
);
1858 p
->y
= (rb
->rand()%LCD_HEIGHT
);
1863 /* give the point a random countdown timer, so they dissapears at different
1865 tpoint
= trailPoints
;
1866 n
= NUM_TRAIL_POINTS
;
1874 /*************************************************
1875 ** Creates start_num number of new asteroids of
1877 **************************************************/
1878 void initialise_game(int start_num
)
1881 asteroid_count
= next_missile_count
= next_thrust_count
= 0;
1882 struct Asteroid
* asteroid
;
1883 struct Missile
* missile
;
1884 extra_life
= EXTRA_LIFE
;
1887 enemy_on_screen
= 0;
1888 enemy_missile
.survived
= 0;
1891 asteroid
= asteroids_array
;
1892 n
= MAX_NUM_ASTEROIDS
;
1895 asteroid
->exists
= false;
1899 /*make some LARGE asteroids*/
1900 for(n
= 0; n
< start_num
; n
++)
1901 initialise_asteroid(&asteroids_array
[n
], LARGE
);
1903 /*ensure all missiles are out of action: */
1904 missile
= missiles_array
;
1905 n
= MAX_NUM_MISSILES
;
1908 missile
->survived
=0;
1913 static int spacerocks_game_loop(void)
1921 /*create stars once, and once only:*/
1924 if (spacerocks_menu(false)!=0)
1931 end
= *rb
->current_tick
+ (CYCLETIME
* HZ
) / 1000;
1932 rb
->lcd_clear_display();
1934 switch(game_state
) {
1936 rb
->splash (HZ
* 2, "Game Over");
1937 rb
->lcd_clear_display();
1938 position
=highscore_update(current_score
, current_level
, "",
1939 highest
,NUM_SCORES
);
1941 rb
->splash(HZ
*2, "New High Score");
1943 highscore_show(position
, highest
, NUM_SCORES
, true);
1944 if (spacerocks_menu(false)!=0)
1949 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1950 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1951 rb
->lcd_putsxy(CENTER_LCD_X
- 15,
1952 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, "pause");
1953 draw_and_move_missiles();
1955 draw_and_move_ship();
1959 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1960 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1961 draw_and_move_missiles();
1964 draw_and_move_ship();
1968 show_level_timeout
--;
1969 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1970 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1971 rb
->snprintf(level
, sizeof(level
), "stage %d ", current_level
);
1972 rb
->lcd_putsxy(CENTER_LCD_X
- 20,
1973 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, level
);
1974 draw_and_move_ship();
1976 if(!show_level_timeout
) {
1977 initialise_game(current_level
);
1978 game_state
= PLAY_MODE
;
1985 draw_and_move_asteroids();
1986 draw_and_move_enemy();
1990 #ifdef HAS_BUTTON_HOLD
1991 if (rb
->button_hold())
1992 game_state
= PAUSE_MODE
;
1995 button
= rb
->button_get(false);
1998 if (spacerocks_menu(true)!=0)
2003 if (game_state
== PAUSE_MODE
) {
2004 game_state
= PLAY_MODE
;
2007 else if (game_state
!= PLAY_MODE
)
2011 case (AST_LEFT
| BUTTON_REPEAT
):
2012 if(game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
2013 rotate_ship(SHIP_ROT_ACW_COS
, SHIP_ROT_ACW_SIN
);
2017 case (AST_RIGHT
| BUTTON_REPEAT
):
2018 if(game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
2019 rotate_ship(SHIP_ROT_CW_COS
, SHIP_ROT_CW_SIN
);
2023 case (AST_THRUST
| BUTTON_REPEAT
):
2024 if((game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
) &&
2025 !next_thrust_count
) {
2027 next_thrust_count
= 5;
2031 case (AST_HYPERSPACE
):
2032 if(game_state
== PLAY_MODE
)
2034 /*maybe shield if it gets too hard */
2038 case (AST_FIRE
| BUTTON_REPEAT
):
2039 if(game_state
== PLAY_MODE
) {
2040 if(!next_missile_count
) {
2042 next_missile_count
= 10;
2045 else if(game_state
== PAUSE_MODE
) {
2046 game_state
= PLAY_MODE
;
2051 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
)
2052 return PLUGIN_USB_CONNECTED
;
2056 if(next_missile_count
)
2057 next_missile_count
--;
2059 if(next_thrust_count
)
2060 next_thrust_count
--;
2062 if (TIME_BEFORE(*rb
->current_tick
, end
))
2063 rb
->sleep(end
-*rb
->current_tick
);
2069 enum plugin_status
plugin_start(const void* parameter
)
2074 rb
->lcd_set_backdrop(NULL
);
2076 /* universal font */
2077 rb
->lcd_setfont(FONT_SYSFIXED
);
2078 /* Turn off backlight timeout */
2079 backlight_force_on(); /* backlight control in lib/helper.c */
2080 highscore_load(HIGH_SCORE
,highest
,NUM_SCORES
);
2081 spacerocks_game_loop();
2082 rb
->lcd_setfont(FONT_UI
);
2083 highscore_save(HIGH_SCORE
,highest
,NUM_SCORES
);
2084 /* Turn on backlight timeout (revert to settings) */
2085 backlight_use_settings(); /* backlight control in lib/helper.c */