summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/SOURCES2
-rwxr-xr-xapps/plugins/spacerocks.c1601
2 files changed, 1603 insertions, 0 deletions
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 70edca4dc1..e0f1c5ba83 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -94,6 +94,8 @@ rockboy.c
94xobox.c 94xobox.c
95#endif 95#endif
96 96
97spacerocks.c
98
97#endif /* HAVE_LCD_BITMAP */ 99#endif /* HAVE_LCD_BITMAP */
98 100
99#ifdef HAVE_LCD_CHARCELLS /* Player model only */ 101#ifdef HAVE_LCD_CHARCELLS /* Player model only */
diff --git a/apps/plugins/spacerocks.c b/apps/plugins/spacerocks.c
new file mode 100755
index 0000000000..67b5dd047e
--- /dev/null
+++ b/apps/plugins/spacerocks.c
@@ -0,0 +1,1601 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Mat Holton
11 *
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.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "plugin.h"
21#include "math.h"
22#include "stdio.h"
23PLUGIN_HEADER
24
25/******************************* Globals ***********************************/
26static struct plugin_api* rb; /* global api struct pointer */
27/* variable button definitions */
28#if CONFIG_KEYPAD == RECORDER_PAD
29#define AST_PAUSE BUTTON_ON
30#define AST_QUIT BUTTON_OFF
31#define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
32#define AST_THRUST BUTTON_UP
33#define AST_HYPERSPACE BUTTON_DOWN
34#define AST_LEFT BUTTON_LEFT
35#define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
36#define AST_RIGHT BUTTON_RIGHT
37#define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
38#define AST_FIRE BUTTON_PLAY
39#define AST_FIRE_REP BUTTON_PLAY | BUTTON_REPEAT
40
41#elif CONFIG_KEYPAD == ONDIO_PAD
42#define AST_PAUSE BUTTON_ON
43#define AST_QUIT BUTTON_OFF
44#define AST_THRUST BUTTON_UP
45#define AST_HYPERSPACE BUTTON_DOWN
46#define AST_LEFT BUTTON_LEFT
47#define AST_RIGHT BUTTON_RIGHT
48#define AST_FIRE BUTTON_MENU
49
50#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
51 (CONFIG_KEYPAD == IRIVER_H300_PAD)
52#define AST_PAUSE BUTTON_REC
53#define AST_QUIT BUTTON_OFF
54#define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
55#define AST_THRUST BUTTON_UP
56#define AST_HYPERSPACE BUTTON_DOWN
57#define AST_LEFT BUTTON_LEFT
58#define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
59#define AST_RIGHT BUTTON_RIGHT
60#define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
61#define AST_FIRE BUTTON_SELECT
62#define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
63
64#elif (CONFIG_KEYPAD == IAUDIO_X5_PAD)
65#define AST_PAUSE BUTTON_PLAY
66#define AST_QUIT BUTTON_POWER
67#define AST_THRUST_REP BUTTON_UP | BUTTON_REPEAT
68#define AST_THRUST BUTTON_UP
69#define AST_HYPERSPACE BUTTON_DOWN
70#define AST_LEFT BUTTON_LEFT
71#define AST_LEFT_REP BUTTON_LEFT | BUTTON_REPEAT
72#define AST_RIGHT BUTTON_RIGHT
73#define AST_RIGHT_REP (BUTTON_RIGHT | BUTTON_REPEAT)
74#define AST_FIRE BUTTON_SELECT
75#define AST_FIRE_REP BUTTON_SELECT | BUTTON_REPEAT
76
77#elif (CONFIG_KEYPAD == IPOD_4G_PAD)
78#define AST_PAUSE (BUTTON_SELECT | BUTTON_PLAY)
79#define AST_QUIT (BUTTON_SELECT | BUTTON_MENU)
80#define AST_THRUST BUTTON_MENU
81#define AST_THRUST_REP (BUTTON_MENU | BUTTON_REPEAT)
82#define AST_HYPERSPACE BUTTON_PLAY
83#define AST_LEFT BUTTON_SCROLL_BACK
84#define AST_LEFT_REP (BUTTON_SCROLL_BACK | BUTTON_REPEAT)
85#define AST_RIGHT BUTTON_SCROLL_FWD
86#define AST_RIGHT_REP (BUTTON_SCROLL_FWD | BUTTON_REPEAT)
87#define AST_FIRE BUTTON_SELECT
88#define AST_FIRE_REP (BUTTON_SELECT | BUTTON_REPEAT)
89#endif
90
91#define SHOW_COL 0
92#define HISCORE_FILE PLUGIN_DIR "/astrorocks.hs"
93#define POINT_SIZE 2
94#define MAX_NUM_ASTEROIDS 25
95#define MAX_NUM_MISSILES 6
96#define ABS(x) ((x)>0?(x):-(x))
97
98#define SCALE 5000
99#define MISSILE_SCALE 5000
100#define WRAP_GAP 12
101#define EXPLOSION_LENGTH 35
102
103#if CONFIG_KEYPAD == RECORDER_PAD || CONFIG_KEYPAD == ONDIO_PAD
104 #define ENEMY_MISSILE_SURVIVAL_LENGTH 65
105 #define MISSILE_SURVIVAL_LENGTH 40
106#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
107 (CONFIG_KEYPAD == IRIVER_H300_PAD) || \
108 (CONFIG_KEYPAD == IAUDIO_X5_PAD) || \
109 (CONFIG_KEYPAD == IPOD_4G_PAD)
110 #define ENEMY_MISSILE_SURVIVAL_LENGTH 120
111 #define MISSILE_SURVIVAL_LENGTH 80
112#endif
113
114#define SHOW_GAME_OVER_TIME 100
115#define SHOW_LEVEL_TIME 50
116#define START_LIVES 3
117#define START_LEVEL 1
118#define NUM_ASTEROID_VERTICES 10
119#define NUM_SHIP_VERTICES 4
120#define NUM_ENEMY_VERTICES 6
121#define MAX_LEVEL MAX_NUM_ASTEROIDS
122#define ENEMY_SPEED 4
123#define ENEMY_START_X 0
124#define ENEMY_START_Y 0
125#define SIZE_ENEMY_COLLISION 5*SCALE
126#define ATTRACT_FLIP_TIME 100
127#define NUM_STARS 50
128#define NUM_ROTATIONS 16
129
130#define SIN_COS_SCALE 10000
131#define SHIP_ROT_CW_SIN 3827
132#define SHIP_ROT_CW_COS 9239
133#define SHIP_ROT_ACW_SIN -3827
134#define SHIP_ROT_ACW_COS 9239
135
136#define FAST_ROT_CW_SIN 873
137#define FAST_ROT_CW_COS 9963
138#define FAST_ROT_ACW_SIN -873
139#define FAST_ROT_ACW_COS 9963
140
141#define MEDIUM_ROT_CW_SIN 350
142#define MEDIUM_ROT_CW_COS 9994
143#define MEDIUM_ROT_ACW_SIN -350
144#define MEDIUM_ROT_ACW_COS 9994
145
146#define SLOW_ROT_CW_SIN 350
147#define SLOW_ROT_CW_COS 9994
148#define SLOW_ROT_ACW_SIN - 350
149#define SLOW_ROT_ACW_COS 9994
150
151#define SCALED_WIDTH (LCD_WIDTH*SCALE)
152#define SCALED_HEIGHT (LCD_HEIGHT*SCALE)
153#define CENTER_LCD_X (LCD_WIDTH/2)
154#define CENTER_LCD_Y (LCD_HEIGHT/2)
155
156enum asteroid_type
157{
158 SMALL = 1,
159 MEDIUM = 2,
160 LARGE = 3,
161};
162
163enum game_state
164{
165 GAME_OVER,
166 ATTRACT_MODE,
167 SHOW_LEVEL,
168 PLAY_MODE,
169 PAUSE_MODE
170};
171
172struct Point
173{
174 int x;
175 int y;
176 int dx;
177 int dy;
178};
179
180/* Asteroid structure, contains an array of points */
181struct Asteroid
182{
183 enum asteroid_type type;
184 bool exists;
185 struct Point position;
186 struct Point vertices[NUM_ASTEROID_VERTICES];
187 int radius;
188 long speed_cos;
189 long speed_sin;
190 int explode_countdown;
191};
192
193struct Ship
194{
195 struct Point vertices[NUM_SHIP_VERTICES];
196 struct Point position;
197 bool waiting_for_space;
198 int explode_countdown;
199};
200
201struct Enemy
202{
203 struct Point vertices[NUM_ENEMY_VERTICES];
204 struct Point position;
205 int explode_countdown;
206};
207
208struct Missile
209{
210 struct Point position;
211 struct Point oldpoint;
212 int survived;
213};
214
215static enum game_state game_state;
216static int asteroid_count;
217static int next_missile_count;
218static int next_thrust_count;
219static int num_lives;
220static int show_level_timeout;
221static int attract_flip_timeout;
222static int show_game_over;
223static int current_level;
224static int current_score;
225static int high_score;
226static int space_check_size = 20*SCALE;
227
228static bool enemy_on_screen;
229static char phscore[30];
230static struct Ship ship;
231static struct Point stars[NUM_STARS];
232static struct Asteroid asteroids_array[MAX_NUM_ASTEROIDS];
233static struct Missile missiles_array[MAX_NUM_MISSILES];
234static struct Missile enemy_missile;
235static struct Enemy enemy;
236static struct Point lives_points[NUM_SHIP_VERTICES];
237
238void draw_and_move_asteroids(void);
239void initialise_game(int nStartNum);
240
241bool is_asteroid_near_ship(struct Asteroid* asteroid);
242bool is_point_within_asteroid(struct Asteroid* asteroid, struct Point* point);
243
244void initialise_asteroid(struct Asteroid* asteroid, enum asteroid_type eType);
245void draw_polygon(struct Point* vertices, int px, int py, int num_vertices);
246void rotate_asteroid(struct Asteroid* asteroid);
247void create_asteroid(enum asteroid_type type, int x, int y);
248void create_stars(void);
249
250void initialise_ship(void);
251void draw_and_move_ship(void);
252void rotate_ship(int s, int c);
253void thrust_ship(void);
254
255void initialise_missile(struct Missile* missile);
256void draw_and_move_missiles(void);
257void fire_missile(void);
258
259void animate_and_draw_explosion(struct Point* point, int num_points, int xoffset, int yoffset);
260void initialise_explosion(struct Point* point, int num_points);
261
262void move_point(struct Point* point);
263void hyperspace(void);
264void check_collisions(void);
265void initialise_enemy(void);
266void draw_and_move_enemy(void);
267void draw_lives(void);
268void drawstars(void);
269bool is_ship_within_asteroid(struct Asteroid* asteroid);
270
271/* The array of points that make up an asteroid */
272static const short asteroid_one[NUM_ASTEROID_VERTICES*2] =
273{
274 -1, -6,
275 2, -4,
276 4, -7,
277 8, -4,
278 7, 0,
279 10, 1,
280 6, 7,
281 -2, 7,
282 -5, 3,
283 -5, -4
284};
285
286/* The array of points that make up an asteroid */
287static const short asteroid_two[NUM_ASTEROID_VERTICES*2] =
288{
289 -1, -6,
290 2, -8,
291 3, -7,
292 8, -4,
293 7, 0,
294 10, 1,
295 6, 7,
296 -2, 7,
297 -5, 3,
298 -5, -4
299};
300
301/* The array of points that make up an asteroid */
302static const short asteroid_three[NUM_ASTEROID_VERTICES*2] =
303{
304 -1, -6,
305 2, -8,
306 3, -7,
307 1, -4,
308 7, 0,
309 10, 1,
310 6, 7,
311 -2, 7,
312 -8, 3,
313 -5, -4
314};
315
316/* The array od points the make up the ship */
317static const short ship_vertices[NUM_SHIP_VERTICES*2] =
318{
319 0,-4,
320 3, 4,
321 0, 1,
322 -3, 4
323};
324
325/* The array of points the make up the bad spaceship */
326static const short enemy_vertices[NUM_ENEMY_VERTICES*2] =
327{
328 -5, 0,
329 -2, 2,
330 2, 2,
331 5, 0,
332 2, -2,
333 -2, -2
334};
335
336/*Hi-Score reading and writing to file - this needs moving to the hi-score plugin lib as
337a 3rd function */
338void iohiscore(void)
339{
340 int fd;
341 int compare;
342
343 /* clear the buffer we're about to load the highscore data into */
344 rb->memset(phscore, 0, sizeof(phscore));
345
346 fd = rb->open(HISCORE_FILE,O_RDWR | O_CREAT);
347
348 /* highscore used to %d, is now %d\n
349 Deal with no file or bad file */
350 rb->read(fd,phscore, sizeof(phscore));
351
352 compare = rb->atoi(phscore);
353
354 if(high_score > compare){
355 rb->lseek(fd,0,SEEK_SET);
356 rb->fdprintf(fd, "%d\n", high_score);
357 }
358 else
359 high_score = compare;
360
361 rb->close(fd);
362}
363
364bool point_in_poly(struct Point* _point, int num_vertices, int x, int y)
365{
366 struct Point* pi;
367 struct Point* pj;
368 int n;
369 bool c = false;
370
371 pi = _point;
372 pj = _point;
373 pj += num_vertices-1;
374
375 n = num_vertices;
376 while(n--)
377 {
378 if((((pi->y <= y) && (y < pj->y)) || ((pj->y <= y) && (y < pi->y))) &&
379 (x < (pj->x - pi->x) * (y - pi->y) / (pj->y - pi->y) + pi->x))
380 c = !c;
381
382 if(n == num_vertices - 1)
383 pj = _point;
384 else
385 pj++;
386
387 pi++;
388 }
389
390 return c;
391}
392
393void move_point(struct Point* point)
394{
395 point->x += point->dx;
396 point->y += point->dy;
397
398 /*check bounds on the x-axis:*/
399 if(point->x >= SCALED_WIDTH)
400 point->x = 0;
401 else if(point->x <= 0)
402 point->x = SCALED_WIDTH;
403
404 /*Check bounds on the y-axis:*/
405 if(point->y >= SCALED_HEIGHT)
406 point->y = 0;
407 else if(point->y <= 0)
408 point->y = SCALED_HEIGHT;
409}
410
411/*Check if point is within a rectangle*/
412bool is_point_within_rectangle(struct Point* rect, struct Point* p, int size)
413{
414#if SHOW_COL
415 int aTLx = rect->x - size;
416 int aTLy = rect->y - size;
417 int aBRx = rect->x + size;
418 int aBRy = rect->y + size;
419 rb->lcd_drawline( aTLx/SCALE, aTLy/SCALE, aBRx/SCALE, aTLy/SCALE);
420 rb->lcd_drawline( aTLx/SCALE, aTLy/SCALE, aTLx/SCALE, aBRy/SCALE);
421 rb->lcd_drawline( aTLx/SCALE, aBRy/SCALE, aBRx/SCALE, aBRy/SCALE);
422 rb->lcd_drawline( aBRx/SCALE, aBRy/SCALE, aBRx/SCALE, aTLy/SCALE);
423 return (p->x > aTLx && p->x < aBRx && p->y > aTLy && p->y < aBRy);
424#else
425 return (p->x > rect->x - size && p->x < rect->x + size &&
426 p->y > rect->y - size && p->y < rect->y + size);
427#endif
428}
429
430/* Draw polygon */
431void draw_polygon(struct Point* vertices, int px, int py, int num_vertices)
432{
433 int n, t1, t2, oldX, oldY;
434 struct Point *p;
435 bool bDrawAll = px < WRAP_GAP || LCD_WIDTH - px < WRAP_GAP ||
436 py < WRAP_GAP || LCD_HEIGHT - py < WRAP_GAP;
437
438 p = vertices;
439 p += num_vertices-1;
440 oldX = p->x/SCALE + px;
441 oldY = p->y/SCALE + py;
442 p = vertices;
443 for(n = num_vertices+1; --n;)
444 {
445 t1 = p->x/SCALE + px;
446 t2 = p->y/SCALE + py;
447
448 rb->lcd_drawline(oldX, oldY, t1, t2);
449
450 if(bDrawAll)
451 {
452 rb->lcd_drawline(oldX - LCD_WIDTH, oldY, t1 - LCD_WIDTH, t2);
453 rb->lcd_drawline(oldX + LCD_WIDTH, oldY, t1 + LCD_WIDTH, t2);
454 rb->lcd_drawline(oldX - LCD_WIDTH, oldY + LCD_HEIGHT,
455 t1 - LCD_WIDTH, t2 + LCD_HEIGHT);
456 rb->lcd_drawline(oldX + LCD_WIDTH, oldY + LCD_HEIGHT,
457 t1 + LCD_WIDTH, t2 + LCD_HEIGHT);
458
459 rb->lcd_drawline(oldX, oldY - LCD_HEIGHT, t1, t2 - LCD_HEIGHT);
460 rb->lcd_drawline(oldX, oldY + LCD_HEIGHT, t1, t2 + LCD_HEIGHT);
461 rb->lcd_drawline(oldX - LCD_WIDTH, oldY - LCD_HEIGHT,
462 t1 - LCD_WIDTH, t2 - LCD_HEIGHT);
463 rb->lcd_drawline(oldX + LCD_WIDTH, oldY - LCD_HEIGHT,
464 t1 + LCD_WIDTH, t2 - LCD_HEIGHT);
465 }
466 oldX = t1;
467 oldY = t2;
468 p++;
469 }
470}
471
472void animate_and_draw_explosion(struct Point* point, int num_points,
473 int xoffset, int yoffset)
474{
475 int n;
476 for(n = num_points; --n;)
477 {
478 if(game_state != PAUSE_MODE)
479 {
480 point->x += point->dx;
481 point->y += point->dy;
482 }
483 rb->lcd_fillrect( point->x/SCALE + xoffset, point->y/SCALE + yoffset,
484 POINT_SIZE, POINT_SIZE);
485 point++;
486 }
487}
488
489/*stop movement of ship, 'cos that's what happens when you go into hyperspace.*/
490void hyperspace(void)
491{
492 ship.position.dx = ship.position.dy = 0;
493 ship.position.x = (rb->rand()%SCALED_WIDTH);
494 ship.position.y = (rb->rand()%SCALED_HEIGHT);
495}
496
497void initialise_enemy(void)
498{
499 struct Point* point;
500 int n;
501
502 enemy_missile.survived = 0;
503 enemy_on_screen = true;
504 enemy.explode_countdown = 0;
505
506 point = enemy.vertices;
507 for(n = 0; n < NUM_ENEMY_VERTICES+NUM_ENEMY_VERTICES; n+=2)
508 {
509 point->x = enemy_vertices[n];
510 point->y = enemy_vertices[n+1];
511 point->x *= SCALE;
512 point->y *= SCALE;
513 point++;
514 }
515
516 if(ship.position.x >= SCALED_WIDTH/2)
517 {
518 enemy.position.dx = ENEMY_SPEED;
519 enemy.position.x = 0;
520 }
521 else
522 {
523 enemy.position.dx = -ENEMY_SPEED;
524 enemy.position.x = SCALED_WIDTH;
525 }
526
527 if(ship.position.y >= SCALED_HEIGHT/2)
528 {
529 enemy.position.dy = ENEMY_SPEED;
530 enemy.position.y = 0;
531 }
532 else
533 {
534 enemy.position.dy = -ENEMY_SPEED;
535 enemy.position.y = SCALED_HEIGHT;
536 }
537
538 enemy.position.dx *= SCALE/10;
539 enemy.position.dy *= SCALE/10;
540}
541
542void draw_and_move_enemy(void)
543{
544 int enemy_x, enemy_y;
545 struct Point *point;
546
547 if(enemy_on_screen)
548 {
549 enemy_x = enemy.position.x/SCALE;
550 enemy_y = enemy.position.y/SCALE;
551 if(!enemy.explode_countdown)
552 {
553 point = enemy.vertices;
554 draw_polygon(enemy.vertices, enemy_x, enemy_y, NUM_ENEMY_VERTICES);
555 rb->lcd_drawline(enemy.vertices[0].x/SCALE + enemy_x,
556 enemy.vertices[0].y/SCALE + enemy_y,
557 enemy.vertices[3].x/SCALE + enemy_x,
558 enemy.vertices[3].y/SCALE + enemy_y);
559
560 if(game_state != PAUSE_MODE)
561 {
562 enemy.position.x += enemy.position.dx;
563 enemy.position.y += enemy.position.dy;
564 }
565
566 if(enemy.position.x > SCALED_WIDTH || enemy.position.x < 0)
567 enemy_on_screen = false;
568
569 if(enemy.position.y > SCALED_HEIGHT)
570 enemy.position.y = 0;
571 else if(enemy.position.y < 0)
572 enemy.position.y = SCALED_HEIGHT;
573
574 if( (rb->rand()%1000) < 10)
575 enemy.position.dy = -enemy.position.dy;
576 }
577 else
578 {
579
580 animate_and_draw_explosion(enemy.vertices, NUM_ENEMY_VERTICES,
581 enemy_x, enemy.position.y/SCALE);
582 if(game_state != PAUSE_MODE)
583 {
584 enemy.explode_countdown--;
585 if(!enemy.explode_countdown)
586 enemy_on_screen = false;
587 }
588 }
589 }
590 else
591 {
592 if( (rb->rand()%1000) < 2 )
593 initialise_enemy();
594 }
595
596 if(!enemy_missile.survived && game_state != GAME_OVER)
597 {
598 /*if no missile and the enemy is here and not exploding..then shoot baby!*/
599 if( !enemy.explode_countdown && enemy_on_screen &&
600 !ship.waiting_for_space && (rb->rand()%10) > 5 )
601 {
602 enemy_missile.position.x = enemy.position.x;
603 enemy_missile.position.y = enemy.position.y;
604
605 /*lame, needs to be sorted - it's trying to shoot at the ship*/
606 if(ABS(enemy.position.y - ship.position.y) <= 5*SCALE)
607 {
608 enemy_missile.position.dy = 0;
609 }
610 else
611 {
612 if( enemy.position.y < ship.position.y)
613 enemy_missile.position.dy = 1;
614 else
615 enemy_missile.position.dy = -1;
616 }
617
618 if(ABS(enemy.position.x - ship.position.x) <= 5*SCALE)
619 enemy_missile.position.dx = 0;
620 else
621 {
622 if( enemy.position.x < ship.position.x)
623 enemy_missile.position.dx = 1;
624 else
625 enemy_missile.position.dx = -1;
626 }
627
628 if(enemy_missile.position.dx == 0 &&
629 enemy_missile.position.dy == 0)
630 enemy_missile.position.dx = enemy_missile.position.dy = -1;
631
632 enemy_missile.position.dx *= SCALE;
633 enemy_missile.position.dy *= SCALE;
634 enemy_missile.survived = ENEMY_MISSILE_SURVIVAL_LENGTH;
635
636 }
637 }
638 else
639 {
640 rb->lcd_fillrect( enemy_missile.position.x/SCALE,
641 enemy_missile.position.y/SCALE,
642 POINT_SIZE, POINT_SIZE);
643 if(game_state != PAUSE_MODE)
644 {
645 move_point(&enemy_missile.position);
646 enemy_missile.survived--;
647 }
648 }
649}
650
651/******************
652* Lame method of collision
653* detection. It's checking for collision
654* between point and a big rectangle around the asteroid...
655*******************/
656bool is_point_within_asteroid(struct Asteroid* asteroid, struct Point* point)
657{
658 if( !is_point_within_rectangle(&asteroid->position, point,
659 asteroid->radius+4*SCALE) )
660 return false;
661
662 if(point_in_poly(asteroid->vertices, NUM_ASTEROID_VERTICES,
663 point->x - asteroid->position.x,
664 point->y - asteroid->position.y))
665 {
666 switch(asteroid->type)
667 {
668 case(SMALL):
669 asteroid->explode_countdown = EXPLOSION_LENGTH;
670 initialise_explosion(asteroid->vertices, NUM_ASTEROID_VERTICES);
671 break;
672
673 case(LARGE):
674 create_asteroid(MEDIUM, asteroid->position.x,
675 asteroid->position.y);
676 create_asteroid(MEDIUM, asteroid->position.x,
677 asteroid->position.y);
678 break;
679
680 case(MEDIUM):
681 create_asteroid(SMALL, asteroid->position.x, asteroid->position.y);
682 create_asteroid(SMALL, asteroid->position.x, asteroid->position.y);
683 break;
684 }
685
686 current_score++;
687 asteroid_count--;
688 asteroid->exists = false;
689 return true;
690 }
691 else
692 return false;
693}
694
695bool is_point_within_enemy(struct Point* point)
696{
697 if( is_point_within_rectangle(&enemy.position, point, 5*SCALE) )
698 {
699 current_score += 5;
700 /*enemy_missile.survived = 0;*/
701 enemy.explode_countdown = EXPLOSION_LENGTH;
702 initialise_explosion(enemy.vertices, NUM_ENEMY_VERTICES);
703 return true;
704 }
705 else
706 return false;
707}
708
709bool is_ship_within_asteroid(struct Asteroid* asteroid)
710{
711 bool hit = false;
712 struct Point p;
713
714 p.x = ship.position.x + ship.vertices[0].x;
715 p.y = ship.position.y + ship.vertices[0].y;
716 hit |= is_point_within_asteroid(asteroid, &p);
717
718 if(!hit)
719 {
720 p.x = ship.position.x + ship.vertices[1].x;
721 p.y = ship.position.y + ship.vertices[1].y;
722 hit |= is_point_within_asteroid(asteroid, &p);
723 if(!hit)
724 {
725 p.x = ship.position.x + ship.vertices[3].x;
726 p.y = ship.position.y + ship.vertices[3].y;
727 hit |= is_point_within_asteroid(asteroid, &p);
728 }
729 }
730
731 return hit;
732}
733
734void initialise_explosion(struct Point* point, int num_points)
735{
736 int n;
737
738 point->x += point->dx;
739 point->y += point->dy;
740 for(n = num_points; --n;)
741 {
742 point->dx = point->x;
743 point->dy = point->y;
744 point++;
745 }
746}
747
748/* Check for collsions between the missiles and the asteroids and the ship */
749void check_collisions(void)
750{
751 int m, n;
752 bool asteroids_onscreen = false;
753 struct Missile* missile;
754 struct Asteroid* asteroid;
755 bool ship_cant_be_placed = false;
756
757 asteroid = asteroids_array;
758 m = MAX_NUM_ASTEROIDS;
759 while(--m)
760 {
761 /*if the asteroids exists then test missile collision:*/
762 if(asteroid->exists)
763 {
764 missile = missiles_array;
765 n = MAX_NUM_MISSILES;
766 while(--n)
767 {
768 /*if the missiles exists:*/
769 if(missile->survived > 0)
770 {
771 /*has the missile hit the asteroid?*/
772 if(is_point_within_asteroid(asteroid, &missile->position)
773 || is_point_within_asteroid(asteroid,
774 &missile->oldpoint))
775 {
776 missile->survived = 0;
777 break;
778 }
779 }
780 missile++;
781 }
782 }
783
784 /*If it exists now, check ship collision:*/
785 if(asteroid->exists)
786 {
787 /*now check collision with ship:*/
788 if(!ship.waiting_for_space && !ship.explode_countdown)
789 {
790 if(is_ship_within_asteroid(asteroid))
791 {
792 /*blow up ship*/
793 ship.explode_countdown = EXPLOSION_LENGTH;
794 initialise_explosion(ship.vertices, NUM_SHIP_VERTICES);
795 }
796 }
797 }
798
799 /*has the enemy missile blown something up?*/
800 if(asteroid->exists && enemy_missile.survived)
801 {
802 if(is_point_within_asteroid(asteroid, &enemy_missile.position))
803 {
804 /*take that score back then:*/
805 if(current_score > 0) current_score--;
806 enemy_missile.survived = 0;
807 }
808 }
809
810 /*if it still exists, check if ship is waiting for space:*/
811 if(asteroid->exists && ship.waiting_for_space)
812 ship_cant_be_placed |=
813 is_point_within_rectangle(&ship.position,
814 &asteroid->position,
815 space_check_size);
816
817 /*is an asteroid still exploding?*/
818 if(asteroid->explode_countdown)
819 asteroids_onscreen = true;
820
821 asteroid++;
822 }
823
824 /*now check collision between ship and enemy*/
825 if(enemy_on_screen && !ship.waiting_for_space &&
826 !ship.explode_countdown && !enemy.explode_countdown)
827 {
828 /*has the enemy collided with the ship?*/
829 if(is_point_within_enemy(&ship.position))
830 {
831 ship.explode_countdown = EXPLOSION_LENGTH;
832 initialise_explosion(ship.vertices, NUM_SHIP_VERTICES);
833 }
834
835 /*Now see if the enemy has been shot at by the ships missiles:*/
836 missile = missiles_array;
837 n = MAX_NUM_MISSILES;
838 while(--n)
839 {
840 if(missile->survived > 0 &&
841 is_point_within_enemy(&missile->position))
842 {
843 missile->survived = 0;
844 break;
845 }
846 }
847 }
848
849 /*test collision with enemy missile and ship:*/
850 if(!ship_cant_be_placed && enemy_missile.survived > 0 &&
851 point_in_poly(ship.vertices, NUM_SHIP_VERTICES,
852 enemy_missile.position.x - ship.position.x,
853 enemy_missile.position.y - ship.position.y))
854 {
855 ship.explode_countdown = EXPLOSION_LENGTH;
856 initialise_explosion(ship.vertices, NUM_SHIP_VERTICES);
857 enemy_missile.survived = 0;
858 enemy_missile.position.x = enemy_missile.position.y = 0;
859 }
860
861 if(!ship_cant_be_placed)
862 ship.waiting_for_space = false;
863
864 /*if all asteroids cleared then start again:*/
865 if(asteroid_count == 0 && !enemy_on_screen && !asteroids_onscreen)
866 {
867 current_level++;
868 game_state = SHOW_LEVEL;
869 show_level_timeout = SHOW_LEVEL_TIME;
870 }
871}
872
873/*************************************************
874** Creates a new asteroid of the given 4type (size)
875** and at the given location.
876*************************************************/
877void create_asteroid(enum asteroid_type type, int x, int y)
878{
879 struct Asteroid* asteroid;
880 int n;
881
882 asteroid = asteroids_array;
883 n = MAX_NUM_ASTEROIDS;
884 while(--n)
885 {
886 if(!asteroid->exists && !asteroid->explode_countdown)
887 {
888 initialise_asteroid(asteroid, type);
889 asteroid->position.x = x;
890 asteroid->position.y = y;
891 break;
892 }
893 asteroid++;
894 }
895}
896
897/* Initialise a missile */
898void initialise_missile(struct Missile* missile)
899{
900 missile->position.x = ship.position.x;
901 missile->position.y = ship.position.y;
902 missile->position.dx = (ship.vertices[0].x - ship.vertices[2].x)/2;
903 missile->position.dy = (ship.vertices[0].y - ship.vertices[2].y)/2;
904 missile->survived = MISSILE_SURVIVAL_LENGTH;
905 missile->oldpoint.x = missile->position.x;
906 missile->oldpoint.y = missile->position.y;
907}
908
909/* Draw and Move all the missiles */
910void draw_and_move_missiles(void)
911{
912 int n;
913 int p1x, p1y;
914 int p2x, p2y;
915
916 struct Missile* missile;
917 missile = missiles_array;
918 n = MAX_NUM_MISSILES;
919 while(--n)
920 {
921 if(missile->survived)
922 {
923 if(missile->position.dx > 0)
924 {
925 if(missile->position.x >= missile->oldpoint.x)
926 {
927 p1x = missile->oldpoint.x;
928 p2x = missile->position.x;
929 }
930 else
931 {
932 p1x = 0;
933 p2x = missile->position.x;
934 }
935 }
936 else
937 {
938 if(missile->oldpoint.x >= missile->position.x)
939 {
940 p1x = missile->oldpoint.x;
941 p2x = missile->position.x;
942 }
943 else
944 {
945 p1x = missile->oldpoint.x;
946 p2x = LCD_WIDTH;
947 }
948 }
949
950 if(missile->position.dy > 0)
951 {
952 if(missile->position.y >= missile->oldpoint.y)
953 {
954 p1y = missile->oldpoint.y;
955 p2y = missile->position.y;
956 }
957 else
958 {
959 p1y = 0;
960 p2y = missile->position.y;
961 }
962 }
963 else
964 {
965 if(missile->oldpoint.y >= missile->position.y)
966 {
967 p1y = missile->oldpoint.y;
968 p2y = missile->position.y;
969 }
970 else
971 {
972 p1y = missile->oldpoint.y;
973 p2y = LCD_HEIGHT;
974 }
975 }
976
977 rb->lcd_drawline( p1x/SCALE, p1y/SCALE, p2x/SCALE, p2y/SCALE);
978
979 if(game_state != PAUSE_MODE)
980 {
981 missile->oldpoint.x = missile->position.x;
982 missile->oldpoint.y = missile->position.y;
983 move_point(&missile->position);
984 missile->survived--;
985 }
986 }
987 missile++;
988 }
989}
990
991void draw_lives(void)
992{
993 int n;
994 int px = (LCD_WIDTH - num_lives*4 - 1);
995 int py = (LCD_HEIGHT-4);
996
997 n = num_lives;
998 while(--n)
999 {
1000 draw_polygon(lives_points, px, py, NUM_SHIP_VERTICES);
1001 px += 6;
1002 }
1003}
1004
1005/*Fire the next missile*/
1006void fire_missile(void)
1007{
1008 int n;
1009 struct Missile* missile;
1010
1011 if(!ship.explode_countdown && !ship.waiting_for_space)
1012 {
1013 missile = missiles_array;
1014 n = MAX_NUM_MISSILES;
1015 while(--n)
1016 {
1017 if(!missile->survived)
1018 {
1019 initialise_missile(missile);
1020 break;
1021 }
1022 missile++;
1023 }
1024 }
1025}
1026
1027/* Initialise the passed Asteroid */
1028void initialise_asteroid(struct Asteroid* asteroid, enum asteroid_type type)
1029{
1030 int n;
1031 bool b,b2;
1032 struct Point* point;
1033 asteroid->exists = true;
1034 asteroid->type = type;
1035 asteroid->explode_countdown = 0;
1036
1037 /*Set the radius of the asteroid:*/
1038 asteroid->radius = (int)type;
1039
1040 /*shall we move Clockwise and Fast*/
1041 if((rb->rand()%100)>75)
1042 {
1043 asteroid->speed_cos = FAST_ROT_CW_COS;
1044 asteroid->speed_sin = FAST_ROT_CW_SIN;
1045 }
1046 else if((rb->rand()%100)>75)
1047 {
1048 asteroid->speed_cos = FAST_ROT_ACW_COS;
1049 asteroid->speed_sin = FAST_ROT_ACW_SIN;
1050 }
1051 else if((rb->rand()%100)>75)
1052 {
1053 asteroid->speed_cos = SLOW_ROT_ACW_COS;
1054 asteroid->speed_sin = SLOW_ROT_ACW_SIN;
1055 }
1056 else
1057 {
1058 asteroid->speed_cos = SLOW_ROT_CW_COS;
1059 asteroid->speed_sin = SLOW_ROT_CW_SIN;
1060 }
1061
1062 b = (rb->rand()%100)>66;
1063 b2 = (rb->rand()%100)>66;
1064 point = asteroid->vertices;
1065 for(n = 0; n < NUM_ASTEROID_VERTICES*2; n+=2)
1066 {
1067 if(b)
1068 {
1069 point->x = asteroid_one[n]*asteroid->radius/2;
1070 point->y = asteroid_one[n+1]*asteroid->radius/2;
1071 }
1072 else if( b2 )
1073 {
1074 point->x = asteroid_two[n]*asteroid->radius/2;
1075 point->y = asteroid_two[n+1]*asteroid->radius/2;
1076 }
1077 else
1078 {
1079 point->x = asteroid_three[n]*asteroid->radius/2;
1080 point->y = asteroid_three[n+1]*asteroid->radius/2;
1081 }
1082 point->x *= SCALE;
1083 point->y *= SCALE;
1084 point++;
1085 }
1086
1087 asteroid->radius *= SCALE/2;
1088
1089 if(asteroid->type == LARGE)
1090 asteroid->radius *= 7;
1091 else if(asteroid->type == MEDIUM)
1092 asteroid->radius *= 4;
1093 else if(asteroid->type == SMALL)
1094 asteroid->radius /= 2;
1095
1096 b = true;
1097 while(b)
1098 {
1099 /*Set the position randomly:*/
1100 asteroid->position.x = (rb->rand()%SCALED_WIDTH);
1101 asteroid->position.y = (rb->rand()%SCALED_HEIGHT);
1102
1103 asteroid->position.dx = 0;
1104 while(asteroid->position.dx == 0)
1105 asteroid->position.dx = (rb->rand()%10)-5;
1106
1107 asteroid->position.dy = 0;
1108 while(asteroid->position.dy == 0)
1109 asteroid->position.dy = (rb->rand()%10)-5;
1110
1111 asteroid->position.dx *= SCALE/10;
1112 asteroid->position.dy *= SCALE/10;
1113
1114 b = is_point_within_rectangle(&ship.position, &asteroid->position,
1115 space_check_size);
1116 }
1117
1118 /*Now rotate the asteroid a bit, so they all look a bit different*/
1119 for(n=(rb->rand()%30) + 2;--n;)
1120 rotate_asteroid(asteroid);
1121
1122 /*great, we've created an asteroid, don't forget to increment the total:*/
1123 asteroid_count++;
1124}
1125
1126/*Initialise the ship*/
1127void initialise_ship(void)
1128{
1129 struct Point* point;
1130 struct Point* lives_point;
1131 int n;
1132
1133 ship.position.x = CENTER_LCD_X;
1134 ship.position.y = CENTER_LCD_Y;
1135 ship.position.x *= SCALE;
1136 ship.position.y *= SCALE;
1137 ship.position.dx = ship.position.dy = 0;
1138
1139 point = ship.vertices;
1140 lives_point = lives_points;
1141 for(n = 0; n < NUM_SHIP_VERTICES*2; n+=2)
1142 {
1143 point->x = ship_vertices[n];
1144 point->y = ship_vertices[n+1];
1145 point->x *= SCALE;
1146 point->y *= SCALE;
1147 point++;
1148 lives_point++;
1149 }
1150
1151 ship.position.dx = 0;
1152 ship.position.dy = 0;
1153 ship.explode_countdown = 0;
1154
1155 /*hack-o-rama-city-arizona, take it out to see what happens:*/
1156 for(n=17;--n;)
1157 rotate_ship(SHIP_ROT_ACW_COS, SHIP_ROT_ACW_SIN);
1158
1159 /*grab a copy of the ships points for the lives display:*/
1160 point = ship.vertices;
1161 lives_point = lives_points;
1162 for(n = 0; n < NUM_SHIP_VERTICES*2; n+=2)
1163 {
1164 lives_point->x = point->x;
1165 lives_point->y = point->y;
1166 lives_point++;
1167 point++;
1168 }
1169}
1170
1171void rotate_asteroid(struct Asteroid* asteroid)
1172{
1173 struct Point* point;
1174 int n;
1175 long xtemp;
1176
1177 point = asteroid->vertices;
1178 for(n = NUM_ASTEROID_VERTICES+1; --n;)
1179 {
1180 xtemp = point->x;
1181 point->x = xtemp*asteroid->speed_cos/SIN_COS_SCALE -
1182 point->y*asteroid->speed_sin/SIN_COS_SCALE;
1183 point->y = point->y*asteroid->speed_cos/SIN_COS_SCALE +
1184 xtemp*asteroid->speed_sin/SIN_COS_SCALE;
1185 point++;
1186 }
1187}
1188
1189/*************************************************
1190** Draws the ship, moves the ship and creates a new
1191** one if it's finished exploding.
1192**************************************************/
1193void draw_and_move_ship(void)
1194{
1195 int nxoffset = ship.position.x/SCALE;
1196 int nyoffset = ship.position.y/SCALE;
1197 if(!ship.explode_countdown)
1198 {
1199 if(!ship.waiting_for_space)
1200 draw_polygon(ship.vertices, nxoffset, nyoffset, NUM_SHIP_VERTICES);
1201 }
1202 else
1203 {
1204 animate_and_draw_explosion(ship.vertices, NUM_SHIP_VERTICES,
1205 ship.position.x/SCALE,
1206 ship.position.y/SCALE);
1207 if(game_state != PAUSE_MODE)
1208 {
1209 ship.explode_countdown--;
1210 if(!ship.explode_countdown)
1211 {
1212 num_lives--;
1213 if(!num_lives)
1214 {
1215 show_game_over = SHOW_GAME_OVER_TIME;
1216 game_state = GAME_OVER;
1217 }
1218 else
1219 {
1220 initialise_ship();
1221 ship.waiting_for_space = true;
1222 }
1223 }
1224 }
1225 }
1226
1227 if(game_state != PAUSE_MODE && game_state != GAME_OVER)
1228 move_point(&ship.position);
1229}
1230
1231void thrust_ship(void)
1232{
1233 if(!ship.waiting_for_space)
1234 {
1235 ship.position.dx += ( ship.vertices[0].x - ship.vertices[2].x )/10;
1236 ship.position.dy += ( ship.vertices[0].y - ship.vertices[2].y )/10;
1237 /*if dx and dy are below a certain threshold, then set 'em to 0*/
1238 }
1239}
1240
1241/**************************************************
1242** Rotate the ship using the passed sin & cos values
1243***************************************************/
1244void rotate_ship(int c, int s)
1245{
1246 struct Point* point;
1247 int n;
1248 double xtemp;
1249
1250 if(!ship.waiting_for_space && !ship.explode_countdown)
1251 {
1252 point = ship.vertices;
1253 for(n=NUM_SHIP_VERTICES+1;--n;)
1254 {
1255 xtemp = point->x;
1256 point->x = xtemp*c/SIN_COS_SCALE - point->y*s/SIN_COS_SCALE;
1257 point->y = point->y*c/SIN_COS_SCALE + xtemp*s/SIN_COS_SCALE;
1258 point++;
1259 }
1260 }
1261}
1262
1263void drawstars()
1264{
1265 struct Point* p;
1266 int n = NUM_STARS;
1267
1268 p = stars;
1269 while(--n)
1270 {
1271 rb->lcd_drawpixel(p->x , p->y);
1272 p++;
1273 }
1274}
1275
1276/*************************************************
1277** Draw And Move all Asteroids
1278*************************************************/
1279void draw_and_move_asteroids(void)
1280{
1281 int n;
1282 struct Asteroid* asteroid;
1283
1284 asteroid = asteroids_array;
1285 n = MAX_NUM_ASTEROIDS;
1286 while(--n)
1287 {
1288 if(game_state != PAUSE_MODE)
1289 {
1290 if(asteroid->exists)
1291 {
1292 move_point(&asteroid->position);
1293 rotate_asteroid(asteroid);
1294 draw_polygon(asteroid->vertices, asteroid->position.x/SCALE,
1295 asteroid->position.y/SCALE,
1296 NUM_ASTEROID_VERTICES);
1297 }
1298 else if(asteroid->explode_countdown)
1299 {
1300 animate_and_draw_explosion(asteroid->vertices,
1301 NUM_ASTEROID_VERTICES,
1302 asteroid->position.x/SCALE,
1303 asteroid->position.y/SCALE);
1304 if(game_state != PAUSE_MODE)
1305 asteroid->explode_countdown--;
1306 }
1307 }
1308 else
1309 {
1310 if(asteroid->exists)
1311 draw_polygon(asteroid->vertices,
1312 asteroid->position.x/SCALE,
1313 asteroid->position.y/SCALE,
1314 NUM_ASTEROID_VERTICES);
1315 }
1316 asteroid++;
1317 }
1318}
1319
1320void create_stars(void)
1321{
1322 struct Point* p;
1323 int n;
1324
1325 p = stars;
1326 n = NUM_STARS;
1327 while(--n)
1328 {
1329 p->x = (rb->rand()%LCD_WIDTH);
1330 p->y = (rb->rand()%LCD_HEIGHT);
1331 p++;
1332 }
1333}
1334
1335/*************************************************
1336** Creates start_num number of new asteroids of
1337** full size.
1338**************************************************/
1339void initialise_game(int start_num)
1340{
1341 int n;
1342 asteroid_count = next_missile_count = next_thrust_count = 0;
1343 struct Asteroid* asteroid;
1344 struct Missile* missile;
1345
1346 /*no enemy*/
1347 enemy_on_screen = 0;
1348 enemy_missile.survived = 0;
1349
1350 /*clear asteroids*/
1351 asteroid = asteroids_array;
1352 n = MAX_NUM_ASTEROIDS;
1353 while(--n)
1354 {
1355 asteroid->exists = false;
1356 asteroid++;
1357 }
1358
1359 /*make some LARGE asteroids*/
1360 for(n = 0; n < start_num; n++)
1361 initialise_asteroid(&asteroids_array[n], LARGE);
1362
1363 /*ensure all missiles are out of action: */
1364 missile = missiles_array;
1365 n = MAX_NUM_MISSILES;
1366 while(--n)
1367 {
1368 missile->survived=0;
1369 missile++;
1370 }
1371}
1372
1373void start_attract_mode(void)
1374{
1375 current_level = 5;
1376 num_lives = START_LIVES;
1377 current_score = 0;
1378 attract_flip_timeout = ATTRACT_FLIP_TIME;
1379 game_state = ATTRACT_MODE;
1380 if(asteroid_count < 3)
1381 initialise_game(current_level);
1382}
1383
1384enum plugin_status start_game(void)
1385{
1386 char s[20];
1387 char level[10];
1388 int button;
1389 int end;
1390 int CYCLETIME = 30;
1391
1392 /*create stars once, and once only:*/
1393 create_stars();
1394
1395 while(true)
1396 {
1397 /*game starts with at level 1
1398 with 1 asteroid.*/
1399 start_attract_mode();
1400
1401 /*Main loop*/
1402 while(true)
1403 {
1404 end = *rb->current_tick + (CYCLETIME * HZ) / 1000;
1405 rb->lcd_clear_display();
1406 switch(game_state)
1407 {
1408 case(ATTRACT_MODE):
1409 if(attract_flip_timeout < ATTRACT_FLIP_TIME/2)
1410 {
1411 rb->lcd_putsxy(CENTER_LCD_X - 39,
1412 CENTER_LCD_Y + CENTER_LCD_Y/2 - 4,
1413 "Fire to Start");
1414 if(!attract_flip_timeout)
1415 attract_flip_timeout = ATTRACT_FLIP_TIME;
1416 }
1417 else
1418 {
1419 rb->snprintf(s, sizeof(s), "Hi Score %d ", high_score);
1420 rb->lcd_putsxy(CENTER_LCD_X - 30,
1421 CENTER_LCD_Y + CENTER_LCD_Y/2 - 4, s);
1422 }
1423 attract_flip_timeout--;
1424 break;
1425
1426 case(GAME_OVER):
1427 rb->lcd_putsxy(CENTER_LCD_X - 25,
1428 CENTER_LCD_Y + CENTER_LCD_Y/2 - 4, "Game Over");
1429 rb->snprintf(s, sizeof(s), "score %d ", current_score);
1430 rb->lcd_putsxy(1,LCD_HEIGHT-8, s);
1431 show_game_over--;
1432 if(!show_game_over)
1433 start_attract_mode();
1434 break;
1435
1436 case(PAUSE_MODE):
1437 rb->snprintf(s, sizeof(s), "score %d ", current_score);
1438 rb->lcd_putsxy(1,LCD_HEIGHT-8, s);
1439 rb->lcd_putsxy(CENTER_LCD_X - 15,
1440 CENTER_LCD_Y + CENTER_LCD_Y/2 - 4, "pause");
1441 draw_and_move_missiles();
1442 draw_lives();
1443 draw_and_move_ship();
1444 break;
1445
1446 case(PLAY_MODE):
1447 rb->snprintf(s, sizeof(s), "score %d ", current_score);
1448 rb->lcd_putsxy(1,LCD_HEIGHT-8, s);
1449 draw_and_move_missiles();
1450 draw_lives();
1451 check_collisions();
1452 draw_and_move_ship();
1453 break;
1454
1455 case(SHOW_LEVEL):
1456 show_level_timeout--;
1457 rb->snprintf(s, sizeof(s), "score %d ", current_score);
1458 rb->lcd_putsxy(1,LCD_HEIGHT-8, s);
1459 rb->snprintf(level, sizeof(level), "stage %d ", current_level);
1460 rb->lcd_putsxy(CENTER_LCD_X - 20,
1461 CENTER_LCD_Y + CENTER_LCD_Y/2 - 4, level);
1462 draw_and_move_ship();
1463 draw_lives();
1464 if(!show_level_timeout)
1465 {
1466 initialise_game(current_level);
1467 game_state = PLAY_MODE;
1468 draw_lives();
1469 }
1470 break;
1471 }
1472 drawstars();
1473 draw_and_move_asteroids();
1474 draw_and_move_enemy();
1475
1476 rb->lcd_update();
1477 button = rb->button_get(false);
1478 switch(button)
1479 {
1480 case(AST_PAUSE):
1481 if(game_state == PLAY_MODE)
1482 game_state = PAUSE_MODE;
1483 else if(game_state == PAUSE_MODE)
1484 game_state = PLAY_MODE;
1485 break;
1486
1487 case(AST_QUIT):
1488 if(game_state == ATTRACT_MODE)
1489 return PLUGIN_OK;
1490 else if(game_state == GAME_OVER)
1491 {
1492 start_attract_mode();
1493 }
1494 else
1495 {
1496 show_game_over = SHOW_GAME_OVER_TIME;
1497 game_state = GAME_OVER;
1498 }
1499 break;
1500
1501 case (AST_LEFT_REP):
1502 case (AST_LEFT):
1503 if(game_state == PLAY_MODE || game_state == SHOW_LEVEL)
1504 rotate_ship(SHIP_ROT_ACW_COS, SHIP_ROT_ACW_SIN);
1505 break;
1506
1507 case (AST_RIGHT_REP):
1508 case (AST_RIGHT):
1509 if(game_state == PLAY_MODE || game_state == SHOW_LEVEL)
1510 rotate_ship(SHIP_ROT_CW_COS, SHIP_ROT_CW_SIN);
1511 break;
1512
1513 case (AST_THRUST_REP):
1514 case (AST_THRUST):
1515 if((game_state == PLAY_MODE || game_state == SHOW_LEVEL) && !next_thrust_count)
1516 {
1517 thrust_ship();
1518 next_thrust_count = 5;
1519 }
1520 break;
1521
1522 case (AST_HYPERSPACE):
1523 if(game_state == PLAY_MODE)
1524 hyperspace();
1525 /*maybe shield if it gets too hard */
1526 break;
1527
1528 case (AST_FIRE_REP):
1529 case (AST_FIRE):
1530 if(game_state == ATTRACT_MODE)
1531 {
1532 current_level = START_LEVEL;
1533 initialise_ship();
1534 initialise_game(current_level);
1535 show_level_timeout = SHOW_LEVEL_TIME;
1536 game_state = PLAY_MODE;
1537 }
1538 else if(game_state == PLAY_MODE)
1539 {
1540 if(!next_missile_count)
1541 {
1542 fire_missile();
1543 next_missile_count = 10;
1544 }
1545 }
1546 else if(game_state == PAUSE_MODE)
1547 {
1548 game_state = PLAY_MODE;
1549 }
1550 break;
1551
1552 default:
1553 if (rb->default_event_handler(button)==SYS_USB_CONNECTED)
1554 return PLUGIN_USB_CONNECTED;
1555 break;
1556 }
1557
1558 if(!num_lives)
1559 {
1560 if(high_score < current_score)
1561 high_score = current_score;
1562 if(!show_game_over)
1563 break;
1564 }
1565
1566 if(next_missile_count)
1567 next_missile_count--;
1568
1569 if(next_thrust_count)
1570 next_thrust_count--;
1571
1572 if (end > *rb->current_tick)
1573 rb->sleep(end-*rb->current_tick);
1574 else
1575 rb->yield();
1576 }
1577
1578 }
1579}
1580
1581enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
1582{
1583 enum plugin_status retval;
1584
1585 (void)(parameter);
1586 rb = api;
1587
1588 game_state = ATTRACT_MODE;
1589
1590 /* universal font */
1591 rb->lcd_setfont(FONT_SYSFIXED);
1592 rb->backlight_set_timeout(1);
1593 iohiscore();
1594 retval = start_game();
1595 iohiscore();
1596 rb->lcd_setfont(FONT_UI);
1597 /* restore normal backlight setting*/
1598 rb->backlight_set_timeout(rb->global_settings->backlight_timeout);
1599
1600 return retval;
1601}