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) || CONFIG_KEYPAD == MROBE500_PAD
201 #define AST_QUIT BUTTON_POWER
204 #error No keymap defined!
207 #ifdef HAVE_TOUCHSCREEN
209 #define AST_PAUSE BUTTON_CENTER
212 #define AST_QUIT BUTTON_TOPLEFT
214 #ifndef AST_THRUST_REP
215 #define AST_THRUST_REP (BUTTON_TOPMIDDLE | BUTTON_REPEAT)
218 #define AST_THRUST BUTTON_TOPMIDDLE
220 #ifndef AST_HYPERSPACE
221 #define AST_HYPERSPACE BUTTON_TOPRIGHT
224 #define AST_LEFT BUTTON_MIDLEFT
227 #define AST_LEFT_REP (BUTTON_MIDLEFT | BUTTON_REPEAT)
230 #define AST_RIGHT BUTTON_MIDRIGHT
232 #ifndef AST_RIGHT_REP
233 #define AST_RIGHT_REP (BUTTON_MIDRIGHT | BUTTON_REPEAT)
236 #define AST_FIRE BUTTON_BOTTOMMIDDLE
241 #define AST_FIRE_REP (BUTTON_BOTTOMMIDDLE | BUTTON_MENU)
243 #define AST_FIRE_REP BUTTON_BOTTOMMIDDLE | BUTTON_REPEAT
249 #define RES MAX(LCD_WIDTH, LCD_HEIGHT)
250 #define LARGE_LCD RES >= 200
251 #define ENEMY_MISSILE_SURVIVAL_LENGTH RES/2
252 #define ASTEROID_SPEED RES/20
253 #define MISSILE_SURVIVAL_LENGTH 40
257 #define EXTRA_LIFE 250
258 #define SPAWN_TIME 30
259 #define BLINK_TIME 10
261 #define MISSILE_SCALE 5000
263 #define EXPLOSION_LENGTH 20
266 #define MAX_NUM_ASTEROIDS 25
267 #define MAX_NUM_MISSILES 6
268 #define ENEMY_BIG_PROBABILITY_START 10
269 #define ENEMY_APPEAR_PROBABILITY_START 35
270 #define ENEMY_APPEAR_TIMING_START 1800
271 #define LITTLE_SHIP 2
273 #define SHOW_GAME_OVER_TIME 100
274 #define SHOW_LEVEL_TIME 50
275 #define START_LIVES 3
276 #define START_LEVEL 1
277 #define NUM_ASTEROID_VERTICES 10
278 #define NUM_SHIP_VERTICES 4
279 #define NUM_ENEMY_VERTICES 6
280 #define MAX_LEVEL MAX_NUM_ASTEROIDS
281 #define ENEMY_SPEED 4
282 #define SIZE_ENEMY_COLLISION 5*SCALE
284 #define NUM_TRAIL_POINTS 70
285 #define NUM_ROTATIONS 16
287 #define SIN_COS_SCALE 10000
289 #define FAST_ROT_CW_SIN 873
290 #define FAST_ROT_CW_COS 9963
291 #define FAST_ROT_ACW_SIN -873
292 #define FAST_ROT_ACW_COS 9963
294 #define MEDIUM_ROT_CW_SIN 350
295 #define MEDIUM_ROT_CW_COS 9994
296 #define MEDIUM_ROT_ACW_SIN -350
297 #define MEDIUM_ROT_ACW_COS 9994
299 #define SLOW_ROT_CW_SIN 350
300 #define SLOW_ROT_CW_COS 9994
301 #define SLOW_ROT_ACW_SIN - 350
302 #define SLOW_ROT_ACW_COS 9994
304 #ifdef HAVE_LCD_COLOR
305 #define SHIP_ROT_CW_SIN 2419
306 #define SHIP_ROT_CW_COS 9702
307 #define SHIP_ROT_ACW_SIN -2419
308 #define SHIP_ROT_ACW_COS 9702
310 #define SHIP_ROT_CW_SIN 3827
311 #define SHIP_ROT_CW_COS 9239
312 #define SHIP_ROT_ACW_SIN -3827
313 #define SHIP_ROT_ACW_COS 9239
317 #define SCALED_WIDTH (LCD_WIDTH*SCALE)
318 #define SCALED_HEIGHT (LCD_HEIGHT*SCALE)
319 #define CENTER_LCD_X (LCD_WIDTH/2)
320 #define CENTER_LCD_Y (LCD_HEIGHT/2)
322 #define SHIP_EXPLOSION_COLOUR 1
323 #define ASTEROID_EXPLOSION_COLOUR 2
324 #define ENEMY_EXPLOSION_COLOUR 3
325 #define THRUST_COLOUR 4
327 #define ASTEROID_R 230
328 #define ASTEROID_G 200
329 #define ASTEROID_B 100
340 #ifdef HAVE_LCD_COLOR
341 #define COL_MISSILE LCD_RGBPACK(200,0,0)
342 #define COL_PLAYER LCD_RGBPACK(200,200,200)
343 #define COL_INVULN LCD_RGBPACK(100,100,200)
344 #define COL_STARS LCD_WHITE
345 #define COL_ASTEROID LCD_RGBPACK(ASTEROID_R,ASTEROID_G,ASTEROID_B)
346 #define COL_TEXT LCD_RGBPACK(200,200,255)
347 #define COL_ENEMY LCD_RGBPACK(ENEMY_R,ENEMY_G,ENEMY_B)
348 #define SET_FG rb->lcd_set_foreground
349 #define SET_BG rb->lcd_set_background
357 #define HIGH_SCORE PLUGIN_GAMES_DIR "/spacerocks.score"
360 struct highscore highest
[NUM_SCORES
];
362 /* The array of points that make up an asteroid */
363 static const short asteroid_one
[NUM_ASTEROID_VERTICES
*2] =
377 /* The array of points that make up an asteroid */
378 static const short asteroid_two
[NUM_ASTEROID_VERTICES
*2] =
392 /* The array of points that make up an asteroid */
393 static const short asteroid_three
[NUM_ASTEROID_VERTICES
*2] =
407 /* The array od points the make up the ship */
408 static const short ship_vertices
[NUM_SHIP_VERTICES
*2] =
423 /* The array of points the make up the bad spaceship */
424 static const short enemy_vertices
[NUM_ENEMY_VERTICES
*2] =
477 struct Point position
;
484 /* Asteroid structure, contains an array of points */
487 enum asteroid_type type
;
489 struct Point position
;
490 struct Point vertices
[NUM_ASTEROID_VERTICES
];
494 int explode_countdown
;
499 struct Point vertices
[NUM_SHIP_VERTICES
];
500 struct Point position
;
501 bool waiting_for_space
;
504 int explode_countdown
;
509 struct Point vertices
[NUM_ENEMY_VERTICES
];
510 struct Point position
;
511 int explode_countdown
;
512 long last_time_appeared
;
513 short size_probability
;
514 short appear_probability
;
520 struct Point position
;
521 struct Point oldpoint
;
525 static enum game_state game_state
;
526 static int asteroid_count
;
527 static int next_missile_count
;
528 static int next_thrust_count
;
529 static int num_lives
;
530 static int extra_life
;
531 static int show_level_timeout
;
532 static int current_level
;
533 static int current_score
;
534 static int space_check_size
= 30*SCALE
;
536 static bool enemy_on_screen
;
537 static struct Ship ship
;
538 static struct Point stars
[NUM_STARS
];
539 static struct Asteroid asteroids_array
[MAX_NUM_ASTEROIDS
];
540 static struct Missile missiles_array
[MAX_NUM_MISSILES
];
541 static struct Missile enemy_missile
;
542 static struct Enemy enemy
;
543 static struct Point lives_points
[NUM_SHIP_VERTICES
];
544 static struct TrailPoint trailPoints
[NUM_TRAIL_POINTS
];
546 void draw_and_move_asteroids(void);
547 void initialise_game(int nStartNum
);
549 bool is_asteroid_near_ship(struct Asteroid
* asteroid
);
550 bool is_point_within_asteroid(struct Asteroid
* asteroid
, struct Point
* point
);
552 void initialise_asteroid(struct Asteroid
* asteroid
, enum asteroid_type eType
);
553 void draw_polygon(struct Point
* vertices
, int px
, int py
, int num_vertices
);
554 void rotate_asteroid(struct Asteroid
* asteroid
);
555 void create_asteroid(enum asteroid_type type
, int x
, int y
);
556 void create_stars(void);
558 void initialise_ship(void);
559 void draw_and_move_ship(void);
560 void rotate_ship(int s
, int c
);
561 void thrust_ship(void);
563 void initialise_missile(struct Missile
* missile
);
564 void draw_and_move_missiles(void);
565 void fire_missile(void);
567 void animate_and_draw_explosion(struct Point
* point
, int num_points
, int xoffset
, int yoffset
);
568 void initialise_explosion(struct Point
* point
, int num_points
);
570 void move_point(struct Point
* point
);
571 void hyperspace(void);
572 void check_collisions(void);
573 void initialise_enemy(void);
574 void draw_and_move_enemy(void);
575 void draw_lives(void);
576 void drawstars(void);
577 bool is_ship_within_asteroid(struct Asteroid
* asteroid
);
582 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
583 enemy
.appear_timing
= ENEMY_APPEAR_TIMING_START
;
584 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
585 current_level
= START_LEVEL
;
586 num_lives
= START_LIVES
;
589 initialise_game(current_level
);
590 show_level_timeout
= SHOW_LEVEL_TIME
;
591 game_state
= PLAY_MODE
;
594 static bool spacerocks_help(void)
596 rb
->lcd_setfont(FONT_UI
);
597 #define WORDS (sizeof help_text / sizeof (char*))
598 static char *help_text
[] = {
599 "Spacerocks", "", "Aim", "", "The", "goal", "of", "the", "game", "is",
600 "to", "blow", "up", "the", "asteroids", "and", "avoid", "being", "hit", "by",
601 "them.", "Also", "you'd", "better", "watch", "out", "for", "the", "UFOs!"
603 static struct style_text formation
[]={
604 { 0, TEXT_CENTER
|TEXT_UNDERLINE
},
608 #ifdef HAVE_LCD_COLOR
609 rb
->lcd_set_background(LCD_BLACK
);
610 rb
->lcd_set_foreground(LCD_WHITE
);
613 if (display_text(WORDS
, help_text
, formation
, NULL
)==PLUGIN_USB_CONNECTED
)
616 button
= rb
->button_get(true);
617 if (button
== SYS_USB_CONNECTED
) {
620 } while( ( button
== BUTTON_NONE
)
621 || ( button
& (BUTTON_REL
|BUTTON_REPEAT
) ) );
622 rb
->lcd_setfont(FONT_SYSFIXED
);
628 static int spacerocks_menu_cb(int action
, const struct menu_item_ex
*this_item
)
630 if(action
== ACTION_REQUEST_MENUITEM
631 && !_ingame
&& ((intptr_t)this_item
)==0)
632 return ACTION_EXIT_MENUITEM
;
636 static int spacerocks_menu(bool ingame
)
638 rb
->button_clear_queue();
643 MENUITEM_STRINGLIST (main_menu
, "Spacerocks Menu", spacerocks_menu_cb
,
652 choice
= rb
->do_menu(&main_menu
, &choice
, NULL
, false);
660 if(spacerocks_help())
664 highscore_show(NUM_SCORES
, highest
, NUM_SCORES
, true);
667 playback_control(NULL
);
671 case MENU_ATTACHED_USB
:
679 bool point_in_poly(struct Point
* _point
, int num_vertices
, int x
, int y
)
688 pj
+= num_vertices
-1;
693 if((((pi
->y
<= y
) && (y
< pj
->y
)) || ((pj
->y
<= y
) && (y
< pi
->y
))) &&
694 (x
< (pj
->x
- pi
->x
) * (y
- pi
->y
) / (pj
->y
- pi
->y
) + pi
->x
))
697 if(n
== num_vertices
- 1)
708 void move_point(struct Point
* point
)
710 point
->x
+= point
->dx
;
711 point
->y
+= point
->dy
;
713 /*check bounds on the x-axis:*/
714 if(point
->x
>= SCALED_WIDTH
)
716 else if(point
->x
<= 0)
717 point
->x
= SCALED_WIDTH
;
719 /*Check bounds on the y-axis:*/
720 if(point
->y
>= SCALED_HEIGHT
)
722 else if(point
->y
<= 0)
723 point
->y
= SCALED_HEIGHT
;
726 void create_trail(struct TrailPoint
* tpoint
)
728 tpoint
->position
.dx
= -( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/10;
729 tpoint
->position
.dy
= -( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/10;
732 void create_explosion_trail(struct TrailPoint
* tpoint
)
734 tpoint
->position
.dx
= (rb
->rand()%5050)-2500;
735 tpoint
->position
.dy
= (rb
->rand()%5050)-2500;
738 void create_trail_blaze(int colour
, struct Point
* position
)
741 struct TrailPoint
* tpoint
;
744 if(colour
!= SHIP_EXPLOSION_COLOUR
)
746 numtoadd
= NUM_TRAIL_POINTS
/5;
752 numtoadd
= NUM_TRAIL_POINTS
/8;
753 xadd
= ship
.position
.x
;
754 yadd
= ship
.position
.y
;
757 /* give the point a random countdown timer, so they dissapears at different times */
758 tpoint
= trailPoints
;
759 n
= NUM_TRAIL_POINTS
;
762 if(tpoint
->alive
<= 0 && numtoadd
)
765 /* take a random x point anywhere between bottom two points of ship. */
766 /* ship.position.x; */
767 tpoint
->position
.x
= (ship
.vertices
[2].x
+ (rb
->rand()%18000)-9000) + position
->x
;
768 tpoint
->position
.y
= (ship
.vertices
[2].y
+ (rb
->rand()%18000)-9000) + position
->y
;
772 case SHIP_EXPLOSION_COLOUR
:
776 create_explosion_trail(tpoint
);
780 case ASTEROID_EXPLOSION_COLOUR
:
781 tpoint
->r
= ASTEROID_R
;
782 tpoint
->g
= ASTEROID_G
;
783 tpoint
->b
= ASTEROID_B
;
784 create_explosion_trail(tpoint
);
788 case ENEMY_EXPLOSION_COLOUR
:
792 create_explosion_trail(tpoint
);
797 tpoint
->r
= THRUST_R
;
798 tpoint
->g
= THRUST_G
;
799 tpoint
->b
= THRUST_B
;
800 create_trail(tpoint
);
805 /* add a proportional bit to the x and y based on dx and dy */
807 /* give the points a speed based on direction of travel - i.e. opposite */
808 tpoint
->position
.dx
+= position
->dx
;
809 tpoint
->position
.dy
+= position
->dy
;
815 /* find a space in the array of trail_points that is NULL or DEAD or whatever.
816 and place this one here. */
820 void draw_trail_blaze(void)
822 struct TrailPoint
* tpoint
;
823 /* loop through, if alive then move and draw.
824 when drawn, countdown it's timer.
826 tpoint
= trailPoints
;
827 int n
= NUM_TRAIL_POINTS
;
833 if(game_state
!= PAUSE_MODE
)
836 move_point(&(tpoint
->position
));
838 #ifdef HAVE_LCD_COLOR
839 /* intensity = tpoint->alive/2; */
840 if(tpoint
->r
>0)tpoint
->r
-=tpoint
->dec
;
841 if(tpoint
->g
>0)tpoint
->g
-=tpoint
->dec
;
842 if(tpoint
->b
>0)tpoint
->b
-=tpoint
->dec
;
843 SET_FG(LCD_RGBPACK(tpoint
->r
, tpoint
->g
, tpoint
->b
));
845 rb
->lcd_drawpixel(tpoint
->position
.x
/SCALE
, tpoint
->position
.y
/SCALE
);
851 /*Check if point is within a rectangle*/
852 bool is_point_within_rectangle(struct Point
* rect
, struct Point
* p
, int size
)
855 int aTLx
= rect
->x
- size
;
856 int aTLy
= rect
->y
- size
;
857 int aBRx
= rect
->x
+ size
;
858 int aBRy
= rect
->y
+ size
;
859 rb
->lcd_hline( aTLx
/SCALE
, aBRx
/SCALE
, aTLy
/SCALE
);
860 rb
->lcd_vline( aTLx
/SCALE
, aTLy
/SCALE
, aBRy
/SCALE
);
861 rb
->lcd_hline( aTLx
/SCALE
, aBRx
/SCALE
, aBRy
/SCALE
);
862 rb
->lcd_vline( aBRx
/SCALE
, aBRy
/SCALE
, aTLy
/SCALE
);
863 return (p
->x
> aTLx
&& p
->x
< aBRx
&& p
->y
> aTLy
&& p
->y
< aBRy
);
865 return (p
->x
> rect
->x
- size
&& p
->x
< rect
->x
+ size
&&
866 p
->y
> rect
->y
- size
&& p
->y
< rect
->y
+ size
);
871 void draw_polygon(struct Point
* vertices
, int px
, int py
, int num_vertices
)
873 int n
, t1
, t2
, oldX
, oldY
;
875 bool bDrawAll
= px
< WRAP_GAP
|| LCD_WIDTH
- px
< WRAP_GAP
||
876 py
< WRAP_GAP
|| LCD_HEIGHT
- py
< WRAP_GAP
;
880 oldX
= p
->x
/SCALE
+ px
;
881 oldY
= p
->y
/SCALE
+ py
;
883 for(n
= num_vertices
+1; --n
;)
885 t1
= p
->x
/SCALE
+ px
;
886 t2
= p
->y
/SCALE
+ py
;
888 rb
->lcd_drawline(oldX
, oldY
, t1
, t2
);
892 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
, t1
- LCD_WIDTH
, t2
);
893 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
, t1
+ LCD_WIDTH
, t2
);
894 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
+ LCD_HEIGHT
,
895 t1
- LCD_WIDTH
, t2
+ LCD_HEIGHT
);
896 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
+ LCD_HEIGHT
,
897 t1
+ LCD_WIDTH
, t2
+ LCD_HEIGHT
);
899 rb
->lcd_drawline(oldX
, oldY
- LCD_HEIGHT
, t1
, t2
- LCD_HEIGHT
);
900 rb
->lcd_drawline(oldX
, oldY
+ LCD_HEIGHT
, t1
, t2
+ LCD_HEIGHT
);
901 rb
->lcd_drawline(oldX
- LCD_WIDTH
, oldY
- LCD_HEIGHT
,
902 t1
- LCD_WIDTH
, t2
- LCD_HEIGHT
);
903 rb
->lcd_drawline(oldX
+ LCD_WIDTH
, oldY
- LCD_HEIGHT
,
904 t1
+ LCD_WIDTH
, t2
- LCD_HEIGHT
);
912 void animate_and_draw_explosion(struct Point
* point
, int num_points
,
913 int xoffset
, int yoffset
)
916 for(n
= num_points
; --n
;)
918 if(game_state
!= PAUSE_MODE
)
920 point
->x
+= point
->dx
;
921 point
->y
+= point
->dy
;
923 rb
->lcd_fillrect( point
->x
/SCALE
+ xoffset
, point
->y
/SCALE
+ yoffset
,
924 POINT_SIZE
, POINT_SIZE
);
929 /*stop movement of ship, 'cos that's what happens when you go into hyperspace.*/
930 void hyperspace(void)
932 ship
.position
.dx
= ship
.position
.dy
= 0;
933 ship
.position
.x
= (rb
->rand()%SCALED_WIDTH
);
934 ship
.position
.y
= (rb
->rand()%SCALED_HEIGHT
);
937 void initialise_enemy(void)
943 if(rb
->rand()%100 > enemy
.size_probability
)
946 enemy
.size_probability
++;
947 if(enemy
.size_probability
< 90)
949 enemy
.size_probability
= ENEMY_BIG_PROBABILITY_START
;
957 enemy_missile
.survived
= 0;
958 enemy_on_screen
= true;
959 enemy
.explode_countdown
= 0;
960 enemy
.last_time_appeared
= *rb
->current_tick
;
961 point
= enemy
.vertices
;
962 for(n
= 0; n
< NUM_ENEMY_VERTICES
+NUM_ENEMY_VERTICES
; n
+=2)
964 point
->x
= enemy_vertices
[n
];
965 point
->y
= enemy_vertices
[n
+1];
966 point
->x
*= SCALE
/size
;
967 point
->y
*= SCALE
/size
;
971 if(ship
.position
.x
>= SCALED_WIDTH
/2)
973 enemy
.position
.dx
= ENEMY_SPEED
;
974 enemy
.position
.x
= 0;
978 enemy
.position
.dx
= -ENEMY_SPEED
;
979 enemy
.position
.x
= SCALED_WIDTH
;
982 if(ship
.position
.y
>= SCALED_HEIGHT
/2)
984 enemy
.position
.dy
= ENEMY_SPEED
;
985 enemy
.position
.y
= 0;
989 enemy
.position
.dy
= -ENEMY_SPEED
;
990 enemy
.position
.y
= SCALED_HEIGHT
;
993 enemy
.position
.dx
*= SCALE
/10;
994 enemy
.position
.dy
*= SCALE
/10;
997 void draw_and_move_enemy(void)
999 int enemy_x
, enemy_y
;
1000 struct Point
*point
;
1006 enemy_x
= enemy
.position
.x
/SCALE
;
1007 enemy_y
= enemy
.position
.y
/SCALE
;
1008 if(!enemy
.explode_countdown
)
1010 point
= enemy
.vertices
;
1011 draw_polygon(enemy
.vertices
, enemy_x
, enemy_y
, NUM_ENEMY_VERTICES
);
1012 rb
->lcd_drawline(enemy
.vertices
[0].x
/SCALE
+ enemy_x
,
1013 enemy
.vertices
[0].y
/SCALE
+ enemy_y
,
1014 enemy
.vertices
[3].x
/SCALE
+ enemy_x
,
1015 enemy
.vertices
[3].y
/SCALE
+ enemy_y
);
1017 if(game_state
!= PAUSE_MODE
)
1019 enemy
.position
.x
+= enemy
.position
.dx
;
1020 enemy
.position
.y
+= enemy
.position
.dy
;
1023 if(enemy
.position
.x
> SCALED_WIDTH
|| enemy
.position
.x
< 0)
1024 enemy_on_screen
= false;
1026 if(enemy
.position
.y
> SCALED_HEIGHT
)
1027 enemy
.position
.y
= 0;
1028 else if(enemy
.position
.y
< 0)
1029 enemy
.position
.y
= SCALED_HEIGHT
;
1031 if( (rb
->rand()%1000) < 10)
1032 enemy
.position
.dy
= -enemy
.position
.dy
;
1037 /* animate_and_draw_explosion(enemy.vertices, NUM_ENEMY_VERTICES,
1038 enemy_x, enemy.position.y/SCALE); */
1039 if(game_state
!= PAUSE_MODE
)
1041 enemy
.explode_countdown
--;
1042 if(!enemy
.explode_countdown
)
1043 enemy_on_screen
= false;
1049 if( (*rb
->current_tick
- enemy
.last_time_appeared
) > enemy
.appear_timing
)
1050 if(rb
->rand()%100 > enemy
.appear_probability
) initialise_enemy();
1053 if(!enemy_missile
.survived
&& game_state
!= GAME_OVER
)
1055 /*if no missile and the enemy is here and not exploding..then shoot baby!*/
1056 if( !enemy
.explode_countdown
&& enemy_on_screen
&&
1057 !ship
.waiting_for_space
&& (rb
->rand()%10) > 5 )
1059 enemy_missile
.position
.x
= enemy
.position
.x
;
1060 enemy_missile
.position
.y
= enemy
.position
.y
;
1062 /*lame, needs to be sorted - it's trying to shoot at the ship*/
1063 if(ABS(enemy
.position
.y
- ship
.position
.y
) <= 5*SCALE
)
1065 enemy_missile
.position
.dy
= 0;
1069 if( enemy
.position
.y
< ship
.position
.y
)
1070 enemy_missile
.position
.dy
= 1;
1072 enemy_missile
.position
.dy
= -1;
1075 if(ABS(enemy
.position
.x
- ship
.position
.x
) <= 5*SCALE
)
1076 enemy_missile
.position
.dx
= 0;
1079 if( enemy
.position
.x
< ship
.position
.x
)
1080 enemy_missile
.position
.dx
= 1;
1082 enemy_missile
.position
.dx
= -1;
1085 if(enemy_missile
.position
.dx
== 0 &&
1086 enemy_missile
.position
.dy
== 0)
1087 enemy_missile
.position
.dx
= enemy_missile
.position
.dy
= -1;
1089 enemy_missile
.position
.dx
*= SCALE
;
1090 enemy_missile
.position
.dy
*= SCALE
;
1091 enemy_missile
.survived
= ENEMY_MISSILE_SURVIVAL_LENGTH
;
1097 rb
->lcd_fillrect( enemy_missile
.position
.x
/SCALE
,
1098 enemy_missile
.position
.y
/SCALE
,
1099 POINT_SIZE
, POINT_SIZE
);
1100 if(game_state
!= PAUSE_MODE
)
1102 move_point(&enemy_missile
.position
);
1103 enemy_missile
.survived
--;
1109 * Lame method of collision
1110 * detection. It's checking for collision
1111 * between point and a big rectangle around the asteroid...
1112 *******************/
1113 bool is_point_within_asteroid(struct Asteroid
* asteroid
, struct Point
* point
)
1115 if( !is_point_within_rectangle(&asteroid
->position
, point
,
1116 asteroid
->radius
+4*SCALE
) )
1119 if(point_in_poly(asteroid
->vertices
, NUM_ASTEROID_VERTICES
,
1120 point
->x
- asteroid
->position
.x
,
1121 point
->y
- asteroid
->position
.y
))
1123 switch(asteroid
->type
)
1126 asteroid
->explode_countdown
= EXPLOSION_LENGTH
;
1127 create_trail_blaze(ASTEROID_EXPLOSION_COLOUR
, &asteroid
->position
);
1131 create_asteroid(MEDIUM
, asteroid
->position
.x
,
1132 asteroid
->position
.y
);
1133 create_asteroid(MEDIUM
, asteroid
->position
.x
,
1134 asteroid
->position
.y
);
1138 create_asteroid(SMALL
, asteroid
->position
.x
, asteroid
->position
.y
);
1139 create_asteroid(SMALL
, asteroid
->position
.x
, asteroid
->position
.y
);
1144 if(current_score
> extra_life
)
1147 extra_life
= current_score
+EXTRA_LIFE
;
1150 asteroid
->exists
= false;
1157 bool is_point_within_enemy(struct Point
* point
)
1159 if( is_point_within_rectangle(&enemy
.position
, point
, 7*SCALE
) )
1162 /*enemy_missile.survived = 0;*/
1163 enemy
.explode_countdown
= EXPLOSION_LENGTH
;
1164 /* initialise_explosion(enemy.vertices, NUM_ENEMY_VERTICES); */
1165 create_trail_blaze(ENEMY_EXPLOSION_COLOUR
, &enemy
.position
);
1172 bool is_ship_within_asteroid(struct Asteroid
* asteroid
)
1177 p
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1178 p
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1179 hit
|= is_point_within_asteroid(asteroid
, &p
);
1183 p
.x
= ship
.position
.x
+ ship
.vertices
[1].x
;
1184 p
.y
= ship
.position
.y
+ ship
.vertices
[1].y
;
1185 hit
|= is_point_within_asteroid(asteroid
, &p
);
1188 p
.x
= ship
.position
.x
+ ship
.vertices
[3].x
;
1189 p
.y
= ship
.position
.y
+ ship
.vertices
[3].y
;
1190 hit
|= is_point_within_asteroid(asteroid
, &p
);
1197 void initialise_explosion(struct Point
* point
, int num_points
)
1201 point
->x
+= point
->dx
;
1202 point
->y
+= point
->dy
;
1203 for(n
= num_points
; --n
;)
1205 point
->dx
= point
->x
;
1206 point
->dy
= point
->y
;
1212 /* Check for collsions between the missiles and the asteroids and the ship */
1213 void check_collisions(void)
1216 bool asteroids_onscreen
= false;
1217 struct Missile
* missile
;
1218 struct Asteroid
* asteroid
;
1219 bool ship_cant_be_placed
= false;
1221 asteroid
= asteroids_array
;
1222 m
= MAX_NUM_ASTEROIDS
;
1225 /*if the asteroids exists then test missile collision:*/
1226 if(asteroid
->exists
)
1228 missile
= missiles_array
;
1229 n
= MAX_NUM_MISSILES
;
1232 /*if the missiles exists:*/
1233 if(missile
->survived
> 0)
1235 /*has the missile hit the asteroid?*/
1236 if(is_point_within_asteroid(asteroid
, &missile
->position
)
1237 || is_point_within_asteroid(asteroid
,
1238 &missile
->oldpoint
))
1240 missile
->survived
= 0;
1247 /*now check collision with ship:*/
1248 if(asteroid
->exists
&& !ship
.waiting_for_space
&& !ship
.explode_countdown
)
1250 if(is_ship_within_asteroid(asteroid
))
1252 if (!ship
.invulnerable
)
1254 /*if not invulnerable, blow up ship*/
1255 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1256 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1257 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1261 /*has the enemy missile blown something up?*/
1262 if(asteroid
->exists
&& enemy_missile
.survived
)
1264 if(is_point_within_asteroid(asteroid
, &enemy_missile
.position
))
1266 /*take that score back then:*/
1267 if(current_score
> 0) current_score
--;
1268 enemy_missile
.survived
= 0;
1271 /*if it still exists, check if ship is waiting for space:*/
1272 if(asteroid
->exists
&& ship
.waiting_for_space
)
1273 ship_cant_be_placed
|=
1274 is_point_within_rectangle(&ship
.position
,
1275 &asteroid
->position
,
1280 /*is an asteroid still exploding?*/
1281 if(asteroid
->explode_countdown
)
1282 asteroids_onscreen
= true;
1287 /*now check collision between ship and enemy*/
1288 if(enemy_on_screen
&& !ship
.waiting_for_space
&&
1289 !ship
.explode_countdown
&& !enemy
.explode_countdown
)
1291 /*has the enemy collided with the ship?*/
1292 if(is_point_within_enemy(&ship
.position
))
1294 if (!ship
.invulnerable
)
1296 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1297 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1298 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1300 create_trail_blaze(ENEMY_EXPLOSION_COLOUR
, &enemy
.position
);
1303 /*Now see if the enemy has been shot at by the ships missiles:*/
1304 missile
= missiles_array
;
1305 n
= MAX_NUM_MISSILES
;
1308 if(missile
->survived
> 0 &&
1309 is_point_within_enemy(&missile
->position
))
1311 missile
->survived
= 0;
1318 /*test collision with enemy missile and ship:*/
1319 if(!ship_cant_be_placed
&& enemy_missile
.survived
> 0 &&
1320 point_in_poly(ship
.vertices
, NUM_SHIP_VERTICES
,
1321 enemy_missile
.position
.x
- ship
.position
.x
,
1322 enemy_missile
.position
.y
- ship
.position
.y
))
1324 if (!ship
.invulnerable
)
1326 ship
.explode_countdown
= EXPLOSION_LENGTH
;
1327 /* initialise_explosion(ship.vertices, NUM_SHIP_VERTICES); */
1328 create_trail_blaze(SHIP_EXPLOSION_COLOUR
, &ship
.position
);
1330 enemy_missile
.survived
= 0;
1331 enemy_missile
.position
.x
= enemy_missile
.position
.y
= 0;
1334 if(!ship_cant_be_placed
)
1335 ship
.waiting_for_space
= false;
1337 /*if all asteroids cleared then start again:*/
1338 if(asteroid_count
== 0 && !enemy_on_screen
&& !asteroids_onscreen
)
1341 game_state
= SHOW_LEVEL
;
1342 enemy
.appear_probability
+= 5;
1343 enemy
.appear_timing
-= 200;
1344 if( enemy
.appear_probability
> 100)
1345 enemy
.appear_probability
= ENEMY_APPEAR_PROBABILITY_START
;
1346 show_level_timeout
= SHOW_LEVEL_TIME
;
1350 /*************************************************
1351 ** Creates a new asteroid of the given 4type (size)
1352 ** and at the given location.
1353 *************************************************/
1354 void create_asteroid(enum asteroid_type type
, int x
, int y
)
1356 struct Asteroid
* asteroid
;
1359 asteroid
= asteroids_array
;
1360 n
= MAX_NUM_ASTEROIDS
;
1363 if(!asteroid
->exists
&& !asteroid
->explode_countdown
)
1365 initialise_asteroid(asteroid
, type
);
1366 asteroid
->position
.x
= x
;
1367 asteroid
->position
.y
= y
;
1374 /* Initialise a missile */
1375 void initialise_missile(struct Missile
* missile
)
1377 missile
->position
.x
= ship
.position
.x
+ ship
.vertices
[0].x
;
1378 missile
->position
.y
= ship
.position
.y
+ ship
.vertices
[0].y
;
1379 missile
->position
.dx
= (ship
.vertices
[0].x
- ship
.vertices
[2].x
)/2;
1380 missile
->position
.dy
= (ship
.vertices
[0].y
- ship
.vertices
[2].y
)/2;
1381 missile
->survived
= MISSILE_SURVIVAL_LENGTH
;
1382 missile
->oldpoint
.x
= missile
->position
.x
;
1383 missile
->oldpoint
.y
= missile
->position
.y
;
1386 /* Draw and Move all the missiles */
1387 void draw_and_move_missiles(void)
1393 struct Missile
* missile
;
1394 missile
= missiles_array
;
1396 SET_FG(COL_MISSILE
);
1398 n
= MAX_NUM_MISSILES
;
1401 if(missile
->survived
)
1403 if(missile
->position
.dx
> 0)
1405 if(missile
->position
.x
>= missile
->oldpoint
.x
)
1407 p1x
= missile
->oldpoint
.x
;
1408 p2x
= missile
->position
.x
;
1413 p2x
= missile
->position
.x
;
1418 if(missile
->oldpoint
.x
>= missile
->position
.x
)
1420 p1x
= missile
->oldpoint
.x
;
1421 p2x
= missile
->position
.x
;
1425 p1x
= missile
->oldpoint
.x
;
1430 if(missile
->position
.dy
> 0)
1432 if(missile
->position
.y
>= missile
->oldpoint
.y
)
1434 p1y
= missile
->oldpoint
.y
;
1435 p2y
= missile
->position
.y
;
1440 p2y
= missile
->position
.y
;
1445 if(missile
->oldpoint
.y
>= missile
->position
.y
)
1447 p1y
= missile
->oldpoint
.y
;
1448 p2y
= missile
->position
.y
;
1452 p1y
= missile
->oldpoint
.y
;
1457 rb
->lcd_drawline( p1x
/SCALE
, p1y
/SCALE
, p2x
/SCALE
, p2y
/SCALE
);
1459 if(game_state
!= PAUSE_MODE
)
1461 missile
->oldpoint
.x
= missile
->position
.x
;
1462 missile
->oldpoint
.y
= missile
->position
.y
;
1463 move_point(&missile
->position
);
1464 missile
->survived
--;
1471 void draw_lives(void)
1474 int px
= (LCD_WIDTH
- num_lives
*4 - 1);
1476 int py
= (LCD_HEIGHT
-6);
1478 int py
= (LCD_HEIGHT
-4);
1486 draw_polygon(lives_points
, px
, py
, NUM_SHIP_VERTICES
);
1495 /*Fire the next missile*/
1496 void fire_missile(void)
1499 struct Missile
* missile
;
1501 if(!ship
.explode_countdown
&& !ship
.waiting_for_space
)
1503 missile
= missiles_array
;
1504 n
= MAX_NUM_MISSILES
;
1507 if(!missile
->survived
)
1509 initialise_missile(missile
);
1517 /* Initialise the passed Asteroid */
1518 void initialise_asteroid(struct Asteroid
* asteroid
, enum asteroid_type type
)
1522 struct Point
* point
;
1523 asteroid
->exists
= true;
1524 asteroid
->type
= type
;
1525 asteroid
->explode_countdown
= 0;
1527 /*Set the radius of the asteroid:*/
1528 asteroid
->radius
= (int)type
*SCALE
;
1530 /*shall we move Clockwise and Fast*/
1531 if((rb
->rand()%100)>75)
1533 asteroid
->speed_cos
= FAST_ROT_CW_COS
;
1534 asteroid
->speed_sin
= FAST_ROT_CW_SIN
;
1536 else if((rb
->rand()%100)>75)
1538 asteroid
->speed_cos
= FAST_ROT_ACW_COS
;
1539 asteroid
->speed_sin
= FAST_ROT_ACW_SIN
;
1541 else if((rb
->rand()%100)>75)
1543 asteroid
->speed_cos
= SLOW_ROT_ACW_COS
;
1544 asteroid
->speed_sin
= SLOW_ROT_ACW_SIN
;
1548 asteroid
->speed_cos
= SLOW_ROT_CW_COS
;
1549 asteroid
->speed_sin
= SLOW_ROT_CW_SIN
;
1552 b
= (rb
->rand()%100)>66;
1553 b2
= (rb
->rand()%100)>66;
1554 point
= asteroid
->vertices
;
1555 for(n
= 0; n
< NUM_ASTEROID_VERTICES
*2; n
+=2)
1559 point
->x
= asteroid_one
[n
];
1560 point
->y
= asteroid_one
[n
+1];
1564 point
->x
= asteroid_two
[n
];
1565 point
->y
= asteroid_two
[n
+1];
1569 point
->x
= asteroid_three
[n
];
1570 point
->y
= asteroid_three
[n
+1];
1573 point
->x
*= asteroid
->radius
/6;
1574 point
->y
*= asteroid
->radius
/6;
1579 asteroid
->radius
+= 6*SCALE
;
1580 if(asteroid
->type
== SMALL
)
1581 asteroid
->radius
/= 3;/*2*/
1582 else if(asteroid
->type
== LARGE
)
1583 asteroid
->radius
+= 3*SCALE
;/*2*/
1587 /*Set the position randomly:*/
1588 asteroid
->position
.x
= (rb
->rand()%SCALED_WIDTH
);
1589 asteroid
->position
.y
= (rb
->rand()%SCALED_HEIGHT
);
1591 asteroid
->position
.dx
= 0;
1592 while(asteroid
->position
.dx
== 0)
1593 asteroid
->position
.dx
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
1595 asteroid
->position
.dy
= 0;
1596 while(asteroid
->position
.dy
== 0)
1597 asteroid
->position
.dy
= (rb
->rand()%ASTEROID_SPEED
)-ASTEROID_SPEED
/2;
1599 asteroid
->position
.dx
*= SCALE
/10;
1600 asteroid
->position
.dy
*= SCALE
/10;
1602 b
= is_point_within_rectangle(&ship
.position
, &asteroid
->position
,
1606 /*Now rotate the asteroid a bit, so they all look a bit different*/
1607 for(n
=(rb
->rand()%30) + 2;--n
;)
1608 rotate_asteroid(asteroid
);
1610 /*great, we've created an asteroid, don't forget to increment the total:*/
1614 /*Initialise the ship*/
1615 void initialise_ship(void)
1617 struct Point
* point
;
1618 struct Point
* lives_point
;
1621 ship
.position
.x
= CENTER_LCD_X
;
1622 ship
.position
.y
= CENTER_LCD_Y
;
1623 ship
.position
.x
*= SCALE
;
1624 ship
.position
.y
*= SCALE
;
1625 ship
.position
.dx
= ship
.position
.dy
= 0;
1626 ship
.spawn_time
= SPAWN_TIME
;
1627 ship
.invulnerable
= 1;
1629 point
= ship
.vertices
;
1630 lives_point
= lives_points
;
1631 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+=2)
1633 point
->x
= ship_vertices
[n
];
1634 point
->y
= ship_vertices
[n
+1];
1641 ship
.position
.dx
= 0;
1642 ship
.position
.dy
= 0;
1643 ship
.explode_countdown
= 0;
1645 /*grab a copy of the ships points for the lives display:*/
1646 point
= ship
.vertices
;
1647 lives_point
= lives_points
;
1648 for(n
= 0; n
< NUM_SHIP_VERTICES
*2; n
+=2)
1650 lives_point
->x
= point
->x
;
1651 lives_point
->y
= point
->y
;
1657 void rotate_asteroid(struct Asteroid
* asteroid
)
1659 struct Point
* point
;
1663 point
= asteroid
->vertices
;
1664 for(n
= NUM_ASTEROID_VERTICES
+1; --n
;)
1667 point
->x
= xtemp
*asteroid
->speed_cos
/SIN_COS_SCALE
-
1668 point
->y
*asteroid
->speed_sin
/SIN_COS_SCALE
;
1669 point
->y
= point
->y
*asteroid
->speed_cos
/SIN_COS_SCALE
+
1670 xtemp
*asteroid
->speed_sin
/SIN_COS_SCALE
;
1675 /*************************************************
1676 ** Draws the ship, moves the ship and creates a new
1677 ** one if it's finished exploding.
1678 **************************************************/
1679 void draw_and_move_ship(void)
1681 int nxoffset
= ship
.position
.x
/SCALE
;
1682 int nyoffset
= ship
.position
.y
/SCALE
;
1683 if (ship
.invulnerable
&& (ship
.spawn_time
> BLINK_TIME
|| ship
.spawn_time
% 2 == 0))
1691 if(!ship
.explode_countdown
)
1693 /* make sure ship is invulnerable until spawn time over */
1694 if (ship
.spawn_time
)
1697 if (ship
.spawn_time
<= 0)
1699 ship
.invulnerable
= 0;
1702 if(!ship
.waiting_for_space
)
1704 draw_polygon(ship
.vertices
, nxoffset
, nyoffset
, NUM_SHIP_VERTICES
);
1705 if(game_state
!= PAUSE_MODE
&& game_state
!= GAME_OVER
)
1707 move_point(&ship
.position
);
1713 /* animate_and_draw_explosion(ship.vertices, NUM_SHIP_VERTICES,
1714 ship.position.x/SCALE,
1715 ship.position.y/SCALE); */
1716 if(game_state
!= PAUSE_MODE
)
1718 ship
.explode_countdown
--;
1719 if(!ship
.explode_countdown
)
1724 game_state
= GAME_OVER
;
1729 ship
.waiting_for_space
= true;
1736 void thrust_ship(void)
1738 if(!ship
.waiting_for_space
)
1740 ship
.position
.dx
+= ( ship
.vertices
[0].x
- ship
.vertices
[2].x
)/20;
1741 ship
.position
.dy
+= ( ship
.vertices
[0].y
- ship
.vertices
[2].y
)/20;
1742 /*if dx and dy are below a certain threshold, then set 'em to 0
1743 but to do this we need to ascertain if the spacehip as moved on screen
1744 for more than a certain amount. */
1746 create_trail_blaze(THRUST_COLOUR
, &ship
.position
);
1750 /**************************************************
1751 ** Rotate the ship using the passed sin & cos values
1752 ***************************************************/
1753 void rotate_ship(int c
, int s
)
1755 struct Point
* point
;
1759 if(!ship
.waiting_for_space
&& !ship
.explode_countdown
)
1761 point
= ship
.vertices
;
1762 for(n
=NUM_SHIP_VERTICES
+1;--n
;)
1765 point
->x
= xtemp
*c
/SIN_COS_SCALE
- point
->y
*s
/SIN_COS_SCALE
;
1766 point
->y
= point
->y
*c
/SIN_COS_SCALE
+ xtemp
*s
/SIN_COS_SCALE
;
1782 rb
->lcd_drawpixel(p
->x
, p
->y
);
1787 /*************************************************
1788 ** Draw And Move all Asteroids
1789 *************************************************/
1790 void draw_and_move_asteroids(void)
1793 struct Asteroid
* asteroid
;
1795 asteroid
= asteroids_array
;
1796 SET_FG(COL_ASTEROID
);
1798 n
= MAX_NUM_ASTEROIDS
;
1801 if(game_state
!= PAUSE_MODE
)
1803 if(asteroid
->exists
)
1805 move_point(&asteroid
->position
);
1806 rotate_asteroid(asteroid
);
1807 draw_polygon(asteroid
->vertices
, asteroid
->position
.x
/SCALE
,
1808 asteroid
->position
.y
/SCALE
,
1809 NUM_ASTEROID_VERTICES
);
1811 else if(asteroid
->explode_countdown
)
1813 /* animate_and_draw_explosion(asteroid->vertices,
1814 NUM_ASTEROID_VERTICES,
1815 asteroid->position.x/SCALE,
1816 asteroid->position.y/SCALE); */
1817 asteroid
->explode_countdown
--;
1822 if(asteroid
->exists
)
1823 draw_polygon(asteroid
->vertices
,
1824 asteroid
->position
.x
/SCALE
,
1825 asteroid
->position
.y
/SCALE
,
1826 NUM_ASTEROID_VERTICES
);
1832 void create_stars(void)
1834 struct TrailPoint
* tpoint
;
1842 p
->x
= (rb
->rand()%LCD_WIDTH
);
1843 p
->y
= (rb
->rand()%LCD_HEIGHT
);
1848 /* give the point a random countdown timer, so they dissapears at different
1850 tpoint
= trailPoints
;
1851 n
= NUM_TRAIL_POINTS
;
1859 /*************************************************
1860 ** Creates start_num number of new asteroids of
1862 **************************************************/
1863 void initialise_game(int start_num
)
1866 asteroid_count
= next_missile_count
= next_thrust_count
= 0;
1867 struct Asteroid
* asteroid
;
1868 struct Missile
* missile
;
1869 extra_life
= EXTRA_LIFE
;
1872 enemy_on_screen
= 0;
1873 enemy_missile
.survived
= 0;
1876 asteroid
= asteroids_array
;
1877 n
= MAX_NUM_ASTEROIDS
;
1880 asteroid
->exists
= false;
1884 /*make some LARGE asteroids*/
1885 for(n
= 0; n
< start_num
; n
++)
1886 initialise_asteroid(&asteroids_array
[n
], LARGE
);
1888 /*ensure all missiles are out of action: */
1889 missile
= missiles_array
;
1890 n
= MAX_NUM_MISSILES
;
1893 missile
->survived
=0;
1898 static int spacerocks_game_loop(void)
1906 /*create stars once, and once only:*/
1909 if (spacerocks_menu(false)!=0)
1916 end
= *rb
->current_tick
+ (CYCLETIME
* HZ
) / 1000;
1917 rb
->lcd_clear_display();
1919 switch(game_state
) {
1921 rb
->splash (HZ
* 2, "Game Over");
1922 rb
->lcd_clear_display();
1923 position
=highscore_update(current_score
, current_level
, "",
1924 highest
,NUM_SCORES
);
1926 rb
->splash(HZ
*2, "New High Score");
1928 highscore_show(position
, highest
, NUM_SCORES
, true);
1929 if (spacerocks_menu(false)!=0)
1934 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1935 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1936 rb
->lcd_putsxy(CENTER_LCD_X
- 15,
1937 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, "pause");
1938 draw_and_move_missiles();
1940 draw_and_move_ship();
1944 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1945 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1946 draw_and_move_missiles();
1949 draw_and_move_ship();
1953 show_level_timeout
--;
1954 rb
->snprintf(s
, sizeof(s
), "score %d ", current_score
);
1955 rb
->lcd_putsxy(1,LCD_HEIGHT
-8, s
);
1956 rb
->snprintf(level
, sizeof(level
), "stage %d ", current_level
);
1957 rb
->lcd_putsxy(CENTER_LCD_X
- 20,
1958 CENTER_LCD_Y
+ CENTER_LCD_Y
/2 - 4, level
);
1959 draw_and_move_ship();
1961 if(!show_level_timeout
) {
1962 initialise_game(current_level
);
1963 game_state
= PLAY_MODE
;
1970 draw_and_move_asteroids();
1971 draw_and_move_enemy();
1975 #ifdef HAS_BUTTON_HOLD
1976 if (rb
->button_hold())
1977 game_state
= PAUSE_MODE
;
1980 button
= rb
->button_get(false);
1983 if (spacerocks_menu(true)!=0)
1988 if (game_state
== PAUSE_MODE
) {
1989 game_state
= PLAY_MODE
;
1992 else if (game_state
!= PLAY_MODE
)
1996 case (AST_LEFT
| BUTTON_REPEAT
):
1997 if(game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
1998 rotate_ship(SHIP_ROT_ACW_COS
, SHIP_ROT_ACW_SIN
);
2002 case (AST_RIGHT
| BUTTON_REPEAT
):
2003 if(game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
)
2004 rotate_ship(SHIP_ROT_CW_COS
, SHIP_ROT_CW_SIN
);
2008 case (AST_THRUST
| BUTTON_REPEAT
):
2009 if((game_state
== PLAY_MODE
|| game_state
== SHOW_LEVEL
) &&
2010 !next_thrust_count
) {
2012 next_thrust_count
= 5;
2016 case (AST_HYPERSPACE
):
2017 if(game_state
== PLAY_MODE
)
2019 /*maybe shield if it gets too hard */
2023 case (AST_FIRE
| BUTTON_REPEAT
):
2024 if(game_state
== PLAY_MODE
) {
2025 if(!next_missile_count
) {
2027 next_missile_count
= 10;
2030 else if(game_state
== PAUSE_MODE
) {
2031 game_state
= PLAY_MODE
;
2036 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
)
2037 return PLUGIN_USB_CONNECTED
;
2041 if(next_missile_count
)
2042 next_missile_count
--;
2044 if(next_thrust_count
)
2045 next_thrust_count
--;
2047 if (end
> *rb
->current_tick
)
2048 rb
->sleep(end
-*rb
->current_tick
);
2054 enum plugin_status
plugin_start(const void* parameter
)
2059 rb
->lcd_set_backdrop(NULL
);
2061 /* universal font */
2062 rb
->lcd_setfont(FONT_SYSFIXED
);
2063 /* Turn off backlight timeout */
2064 backlight_force_on(); /* backlight control in lib/helper.c */
2065 highscore_load(HIGH_SCORE
,highest
,NUM_SCORES
);
2066 spacerocks_game_loop();
2067 rb
->lcd_setfont(FONT_UI
);
2068 highscore_save(HIGH_SCORE
,highest
,NUM_SCORES
);
2069 /* Turn on backlight timeout (revert to settings) */
2070 backlight_use_settings(); /* backlight control in lib/helper.c */