1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2003 Mat Holton
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
23 Board consists of a WIDTHxHEIGHT grid. If board element is 0 then nothing is
24 there otherwise it is part of the snake or a wall.
26 Head and Tail are stored
31 #ifdef HAVE_LCD_BITMAP
38 #if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) && (LCD_DEPTH >= 1)
39 #include "snake2_header1.h"
40 #include "snake2_header2.h"
41 #include "snake2_left.h"
42 #include "snake2_right.h"
43 #include "snake2_bottom.h"
44 #define BMPHEIGHT_snake2_header BMPHEIGHT_snake2_header1
45 #define BMPWIDTH_snake2_header BMPWIDTH_snake2_header1
49 #if (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240)
50 #define MULTIPLIER 10 /*Modifier for porting on other screens*/
55 #define TOP_X1 34 /* x-coord of the upperleft item (game type) */
56 #define TOP_X2 281 /* x-coord of the upperright item (maze type) */
57 #define TOP_X3 42 /* x-coord of the lowerleft item (speed) */
58 #define TOP_X4 274 /* x-coord of the lowerright item (hi-score) */
59 #define TOP_Y1 4 /* y-coord of the top row of items */
60 #define TOP_Y2 25 /* y-coord of the bottom row of items */
61 #elif (LCD_WIDTH >= 240) && (LCD_HEIGHT >= 168)
73 #elif (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176)
85 #elif (LCD_WIDTH >= 176) && (LCD_HEIGHT >= 132)
97 #elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128)
118 /* variable button definitions */
119 #if CONFIG_KEYPAD == RECORDER_PAD
120 #define SNAKE2_LEFT BUTTON_LEFT
121 #define SNAKE2_RIGHT BUTTON_RIGHT
122 #define SNAKE2_UP BUTTON_UP
123 #define SNAKE2_DOWN BUTTON_DOWN
124 #define SNAKE2_QUIT BUTTON_OFF
125 #define SNAKE2_LEVEL_UP BUTTON_UP
126 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
127 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
128 #define SNAKE2_MAZE_LAST BUTTON_LEFT
129 #define SNAKE2_SELECT_TYPE BUTTON_F3
130 #define SNAKE2_PLAYPAUSE BUTTON_PLAY
131 #define SNAKE2_PLAYPAUSE_TEXT "Play"
133 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
134 #define SNAKE2_LEFT BUTTON_LEFT
135 #define SNAKE2_RIGHT BUTTON_RIGHT
136 #define SNAKE2_UP BUTTON_UP
137 #define SNAKE2_DOWN BUTTON_DOWN
138 #define SNAKE2_QUIT BUTTON_OFF
139 #define SNAKE2_LEVEL_UP BUTTON_UP
140 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
141 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
142 #define SNAKE2_MAZE_LAST BUTTON_LEFT
143 #define SNAKE2_SELECT_TYPE BUTTON_F3
144 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
145 #define SNAKE2_PLAYPAUSE_TEXT "Select"
147 #elif CONFIG_KEYPAD == ONDIO_PAD
148 #define SNAKE2_LEFT BUTTON_LEFT
149 #define SNAKE2_RIGHT BUTTON_RIGHT
150 #define SNAKE2_UP BUTTON_UP
151 #define SNAKE2_DOWN BUTTON_DOWN
152 #define SNAKE2_QUIT BUTTON_OFF
153 #define SNAKE2_LEVEL_UP BUTTON_UP
154 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
155 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
156 #define SNAKE2_SELECT_TYPE BUTTON_LEFT
157 #define SNAKE2_PLAYPAUSE BUTTON_MENU
158 #define SNAKE2_PLAYPAUSE_TEXT "Menu"
160 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
161 (CONFIG_KEYPAD == IRIVER_H300_PAD)
162 #define SNAKE2_LEFT BUTTON_LEFT
163 #define SNAKE2_RIGHT BUTTON_RIGHT
164 #define SNAKE2_UP BUTTON_UP
165 #define SNAKE2_DOWN BUTTON_DOWN
166 #define SNAKE2_QUIT BUTTON_OFF
167 #define SNAKE2_LEVEL_UP BUTTON_UP
168 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
169 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
170 #define SNAKE2_MAZE_LAST BUTTON_LEFT
171 #define SNAKE2_SELECT_TYPE BUTTON_MODE
172 #define SNAKE2_PLAYPAUSE BUTTON_ON
173 #define SNAKE2_PLAYPAUSE_TEXT "Play"
175 #define SNAKE2_RC_QUIT BUTTON_RC_STOP
176 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
177 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
178 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
179 #define SNAKE2_LEFT BUTTON_LEFT
180 #define SNAKE2_RIGHT BUTTON_RIGHT
181 #define SNAKE2_UP BUTTON_MENU
182 #define SNAKE2_DOWN BUTTON_PLAY
183 #define SNAKE2_QUIT (BUTTON_SELECT | BUTTON_MENU)
184 #define SNAKE2_LEVEL_UP BUTTON_SCROLL_FWD
185 #define SNAKE2_LEVEL_DOWN BUTTON_SCROLL_BACK
186 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
187 #define SNAKE2_MAZE_LAST BUTTON_LEFT
188 #define SNAKE2_SELECT_TYPE BUTTON_PLAY
189 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
190 #define SNAKE2_PLAYPAUSE_TEXT "Select"
192 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
193 #define SNAKE2_LEFT BUTTON_LEFT
194 #define SNAKE2_RIGHT BUTTON_RIGHT
195 #define SNAKE2_UP BUTTON_UP
196 #define SNAKE2_DOWN BUTTON_DOWN
197 #define SNAKE2_QUIT BUTTON_POWER
198 #define SNAKE2_LEVEL_UP BUTTON_UP
199 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
200 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
201 #define SNAKE2_MAZE_LAST BUTTON_LEFT
202 #define SNAKE2_SELECT_TYPE BUTTON_PLAY
203 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
204 #define SNAKE2_PLAYPAUSE_TEXT "Select"
206 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
207 #define SNAKE2_LEFT BUTTON_LEFT
208 #define SNAKE2_RIGHT BUTTON_RIGHT
209 #define SNAKE2_UP BUTTON_UP
210 #define SNAKE2_DOWN BUTTON_DOWN
211 #define SNAKE2_QUIT BUTTON_POWER
212 #define SNAKE2_LEVEL_UP BUTTON_UP
213 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
214 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
215 #define SNAKE2_MAZE_LAST BUTTON_LEFT
216 #define SNAKE2_SELECT_TYPE BUTTON_MENU
217 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
218 #define SNAKE2_PLAYPAUSE_TEXT "Select"
220 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
221 (CONFIG_KEYPAD == SANSA_C200_PAD)
222 #define SNAKE2_LEFT BUTTON_LEFT
223 #define SNAKE2_RIGHT BUTTON_RIGHT
224 #define SNAKE2_UP BUTTON_UP
225 #define SNAKE2_DOWN BUTTON_DOWN
226 #define SNAKE2_QUIT BUTTON_POWER
227 #define SNAKE2_LEVEL_UP BUTTON_UP
228 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
229 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
230 #define SNAKE2_MAZE_LAST BUTTON_LEFT
231 #define SNAKE2_SELECT_TYPE BUTTON_REC
232 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
233 #define SNAKE2_PLAYPAUSE_TEXT "Select"
235 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
236 #define SNAKE2_LEFT BUTTON_LEFT
237 #define SNAKE2_RIGHT BUTTON_RIGHT
238 #define SNAKE2_UP BUTTON_SCROLL_UP
239 #define SNAKE2_DOWN BUTTON_SCROLL_DOWN
240 #define SNAKE2_QUIT BUTTON_POWER
241 #define SNAKE2_LEVEL_UP BUTTON_SCROLL_UP
242 #define SNAKE2_LEVEL_DOWN BUTTON_SCROLL_DOWN
243 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
244 #define SNAKE2_MAZE_LAST BUTTON_LEFT
245 #define SNAKE2_SELECT_TYPE BUTTON_PLAY
246 #define SNAKE2_PLAYPAUSE BUTTON_FF
247 #define SNAKE2_PLAYPAUSE_TEXT "FF"
249 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
250 #define SNAKE2_LEFT BUTTON_LEFT
251 #define SNAKE2_RIGHT BUTTON_RIGHT
252 #define SNAKE2_UP BUTTON_UP
253 #define SNAKE2_DOWN BUTTON_DOWN
254 #define SNAKE2_QUIT BUTTON_BACK
255 #define SNAKE2_LEVEL_UP BUTTON_UP
256 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
257 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
258 #define SNAKE2_MAZE_LAST BUTTON_LEFT
259 #define SNAKE2_SELECT_TYPE BUTTON_MENU
260 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
261 #define SNAKE2_PLAYPAUSE_TEXT "Select"
263 #elif (CONFIG_KEYPAD == MROBE100_PAD)
264 #define SNAKE2_LEFT BUTTON_LEFT
265 #define SNAKE2_RIGHT BUTTON_RIGHT
266 #define SNAKE2_UP BUTTON_UP
267 #define SNAKE2_DOWN BUTTON_DOWN
268 #define SNAKE2_QUIT BUTTON_POWER
269 #define SNAKE2_LEVEL_UP BUTTON_UP
270 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
271 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
272 #define SNAKE2_MAZE_LAST BUTTON_LEFT
273 #define SNAKE2_SELECT_TYPE BUTTON_MENU
274 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
275 #define SNAKE2_PLAYPAUSE_TEXT "Select"
277 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
278 #define SNAKE2_LEFT BUTTON_RC_REW
279 #define SNAKE2_RIGHT BUTTON_RC_FF
280 #define SNAKE2_UP BUTTON_RC_VOL_UP
281 #define SNAKE2_DOWN BUTTON_RC_VOL_DOWN
282 #define SNAKE2_QUIT BUTTON_RC_REC
283 #define SNAKE2_LEVEL_UP BUTTON_RC_VOL_UP
284 #define SNAKE2_LEVEL_DOWN BUTTON_RC_VOL_DOWN
285 #define SNAKE2_MAZE_NEXT BUTTON_RC_FF
286 #define SNAKE2_MAZE_LAST BUTTON_RC_REW
287 #define SNAKE2_SELECT_TYPE BUTTON_RC_MODE
288 #define SNAKE2_PLAYPAUSE BUTTON_RC_PLAY
289 #define SNAKE2_PLAYPAUSE_TEXT "Play"
291 #elif (CONFIG_KEYPAD == COWOND2_PAD)
292 #define SNAKE2_QUIT BUTTON_POWER
295 #error No keymap defined!
300 #define SNAKE2_LEFT BUTTON_MIDLEFT
303 #define SNAKE2_RIGHT BUTTON_MIDRIGHT
306 #define SNAKE2_UP BUTTON_TOPMIDDLE
309 #define SNAKE2_DOWN BUTTON_BOTTOMMIDDLE
312 #define SNAKE2_QUIT BUTTON_TOPLEFT
314 #ifndef SNAKE2_LEVEL_UP
315 #define SNAKE2_LEVEL_UP BUTTON_TOPRIGHT
317 #ifndef SNAKE2_LEVEL_DOWN
318 #define SNAKE2_LEVEL_DOWN BUTTON_TOPLEFT
320 #ifndef SNAKE2_MAZE_NEXT
321 #define SNAKE2_MAZE_NEXT BUTTON_TOPMIDDLE
323 #ifndef SNAKE2_MAZE_LAST
324 #define SNAKE2_MAZE_LAST BUTTON_BOTTOMMIDDLE
326 #ifndef SNAKE2_SELECT_TYPE
327 #define SNAKE2_SELECT_TYPE BUTTON_BOTTOMLEFT
329 #ifndef SNAKE2_PLAYPAUSE
330 #define SNAKE2_PLAYPAUSE BUTTON_CENTER
332 #ifndef SNAKE2_PLAYPAUSE_TEXT
333 #define SNAKE2_PLAYPAUSE_TEXT "CENTER"
337 static int max_levels
= 0;
338 static char (*level_cache
)[HEIGHT
][WIDTH
];
340 /*Board itself - 2D int array*/
341 static int board
[WIDTH
][HEIGHT
];
343 Buffer for sorting movement (in case user presses two movements during a
346 static int ardirectionbuffer
[2];
347 static unsigned int score
, hiscore
= 0;
350 static int strwdt
,strhgt
; /*used for string width, height for orientation purposes*/
354 static int level
= 4, speed
= 5,dead
= 0, quit
= 0;
355 static int sillydir
= 0, num_levels
= 0;
356 static int level_from_file
= 0;
357 static struct plugin_api
* rb
;
358 static int headx
, heady
, tailx
, taily
, applecountdown
= 5;
359 static int game_type
= 0;
360 static int num_apples_to_get
=1;
361 static int num_apples_to_got
=0;
362 static int game_b_level
=0;
363 static int applecount
=0;
364 static char phscore
[30];
372 #define EAST_NORTH 32
373 #define EAST_SOUTH 64
374 #define WEST_NORTH 128
375 #define WEST_SOUTH 256
377 #define NORTH_EAST 512
378 #define NORTH_WEST 1024
379 #define SOUTH_EAST 2048
380 #define SOUTH_WEST 4096
382 #define LEVELS_FILE PLUGIN_GAMES_DIR "/snake2.levels"
383 #define HISCORE_FILE PLUGIN_GAMES_DIR "/snake2.hs"
385 int load_all_levels(void)
390 char buf
[64]; /* Larger than WIDTH, to allow for whitespace after the
393 /* Init the level_cache pointer and
394 calculate how many levels that will fit */
395 level_cache
= rb
->plugin_get_buffer((size_t *)&size
);
396 max_levels
= size
/ (HEIGHT
*WIDTH
);
401 if ((fd
= rb
->open(LEVELS_FILE
, O_RDONLY
)) < 0)
406 while(rb
->read_line(fd
, buf
, 64))
408 if(rb
->strlen(buf
) == 0) /* Separator? */
411 if(num_levels
> max_levels
)
413 rb
->splash(HZ
, "Too many levels in file");
419 rb
->memcpy(level_cache
[num_levels
][linecnt
], buf
, WIDTH
);
421 if(linecnt
== HEIGHT
)
431 /*Hi-Score reading and writing to file "/.rockbox/rocks/games/snake2.levels" function */
435 unsigned int compare
;
437 /* clear the buffer we're about to load the highscore data into */
438 rb
->memset(phscore
, 0, sizeof(phscore
));
440 fd
= rb
->open(HISCORE_FILE
,O_RDWR
| O_CREAT
);
442 /* highscore used to %d, is now %d\n
443 Deal with no file or bad file */
444 rb
->read(fd
,phscore
, sizeof(phscore
));
446 compare
= rb
->atoi(phscore
);
448 if(hiscore
> compare
){
449 rb
->lseek(fd
,0,SEEK_SET
);
450 rb
->fdprintf(fd
, "%d\n", hiscore
);
460 ** Completely clear the board of walls and/or snake */
462 void clear_board( void)
466 for (x
= 0; x
< WIDTH
; x
++)
468 for (y
= 0; y
< HEIGHT
; y
++)
475 int load_level( int level_number
)
479 for(y
= 0;y
< HEIGHT
;y
++)
481 for(x
= 0;x
< WIDTH
;x
++)
483 switch(level_cache
[level_number
][y
][x
])
503 ** Gets the currently chosen direction from the first place
504 ** in the direction buffer. If there is something in the
505 ** next part of the buffer then that is moved to the first place
507 void get_direction( void )
509 /*if 1st place is empty*/
510 if(ardirectionbuffer
[0] != -1)
512 /*return this direction*/
513 dir
= ardirectionbuffer
[0];
514 ardirectionbuffer
[0]=-1;
515 /*now see if one needs moving:*/
516 if(ardirectionbuffer
[1] != -1)
518 /*there's a move waiting to be done
519 so move it into the space:*/
520 ardirectionbuffer
[0] = ardirectionbuffer
[1];
521 ardirectionbuffer
[1] = -1;
527 ** Sets the direction
529 void set_direction(int newdir
)
531 if(ardirectionbuffer
[0] != newdir
)
533 /*if 1st place is empty*/
534 if(ardirectionbuffer
[0] == -1)
537 ardirectionbuffer
[0] = newdir
;
542 if(ardirectionbuffer
[0] != newdir
) ardirectionbuffer
[1] = newdir
;
545 if(frames
< 0) ardirectionbuffer
[0] = newdir
;
549 void new_level(int level
)
553 ardirectionbuffer
[0] = -1;
554 ardirectionbuffer
[1] = -1;
561 /*Create a small snake to start off with*/
562 board
[headx
][heady
] = dir
;
563 board
[headx
-1][heady
] = dir
;
564 board
[headx
-2][heady
] = dir
;
565 board
[headx
-3][heady
] = dir
;
566 board
[headx
-4][heady
] = dir
;
570 void init_snake(void)
576 new_level(level_from_file
);
580 ** Draws the apple. If it doesn't exist then
581 ** a new one get's created.
583 void draw_apple( void )
587 #if LCD_WIDTH >= 160 && LCD_HEIGHT >= 128
588 char pscore
[5], counter
[4];
590 rb
->lcd_bitmap(snake2_header2
,0,0,BMPWIDTH_snake2_header
, BMPHEIGHT_snake2_header
);
591 rb
->lcd_bitmap(snake2_left
,0,BMPHEIGHT_snake2_header
,BMPWIDTH_snake2_left
, BMPHEIGHT_snake2_left
);
592 rb
->lcd_bitmap(snake2_right
,LCD_WIDTH
-BMPWIDTH_snake2_right
,BMPHEIGHT_snake2_header
,BMPWIDTH_snake2_right
, BMPHEIGHT_snake2_right
);
593 rb
->lcd_bitmap(snake2_bottom
,0,BMPHEIGHT_snake2_header
+BMPHEIGHT_snake2_left
,BMPWIDTH_snake2_bottom
, BMPHEIGHT_snake2_bottom
);
595 rb
->snprintf(counter
,sizeof(counter
),"%d",applecount
);
596 rb
->lcd_getstringsize(counter
,&strwdt
,&strhgt
);
597 rb
->lcd_putsxy(TOP_X3
-strwdt
/2,TOP_Y2
,counter
);
599 rb
->snprintf(pscore
,sizeof(pscore
),"%d",score
);
600 rb
->lcd_getstringsize(pscore
,&strwdt
,&strhgt
);
601 rb
->lcd_putsxy(TOP_X4
-strwdt
/2,TOP_Y2
,pscore
);
608 x
= (rb
->rand() % (WIDTH
-1))+1;
609 y
= (rb
->rand() % (HEIGHT
-1))+1;
610 } while (board
[x
][y
]);
613 applex
= x
;appley
= y
;
615 rb
->lcd_fillrect((CENTER_X
+applex
*MULTIPLIER
)+1,CENTER_Y
+appley
*MULTIPLIER
,MODIFIER_2
,MODIFIER_1
);
616 rb
->lcd_fillrect(CENTER_X
+applex
*MULTIPLIER
,(CENTER_Y
+appley
*MULTIPLIER
)+1,MODIFIER_1
,MODIFIER_2
);
625 void draw_vertical_bit(int x
, int y
)
627 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+1,CENTER_Y
+y
*MULTIPLIER
,MODIFIER_2
,MODIFIER_1
);
636 void draw_horizontal_bit(int x
, int y
)
638 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
,CENTER_Y
+y
*MULTIPLIER
+1,MODIFIER_1
,MODIFIER_2
);
647 void draw_n_to_e_bit(int x
, int y
)
649 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+1,CENTER_Y
+y
*MULTIPLIER
+2,MODIFIER_2
,MODIFIER_2
);
650 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+2,CENTER_Y
+y
*MULTIPLIER
+1,MODIFIER_2
,MODIFIER_2
);
659 void draw_w_to_s_bit(int x
, int y
)
661 draw_n_to_e_bit(x
,y
);
670 void draw_n_to_w_bit(int x
, int y
)
672 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
,CENTER_Y
+y
*MULTIPLIER
+1,MODIFIER_2
,MODIFIER_2
);
673 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+1,CENTER_Y
+y
*MULTIPLIER
+2,MODIFIER_2
,MODIFIER_2
);
682 void draw_e_to_s_bit(int x
, int y
)
684 draw_n_to_w_bit(x
, y
);
693 void draw_s_to_e_bit(int x
, int y
)
695 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+1,CENTER_Y
+y
*MULTIPLIER
,MODIFIER_2
,MODIFIER_2
);
696 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+2,CENTER_Y
+y
*MULTIPLIER
+1,MODIFIER_2
,MODIFIER_2
);
705 void draw_w_to_n_bit(int x
, int y
)
707 draw_s_to_e_bit(x
,y
);
716 void draw_e_to_n_bit(int x
, int y
)
718 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+1,CENTER_Y
+y
*MULTIPLIER
,MODIFIER_2
,MODIFIER_2
);
719 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
,CENTER_Y
+y
*MULTIPLIER
+1,MODIFIER_2
,MODIFIER_2
);
728 void draw_s_to_w_bit(int x
, int y
)
730 draw_e_to_n_bit(x
, y
);
734 ** Draws a wall/obsticals
736 void draw_boundary ( void )
740 /*TODO: Load levels from file!*/
742 /*top and bottom line*/
743 for(x
=0; x
< WIDTH
; x
++)
746 board
[x
][HEIGHT
-1] = WEST
;
749 /*left and right lines*/
750 for(y
=0; y
< HEIGHT
; y
++)
753 board
[WIDTH
-1][y
] = SOUTH
;
757 board
[0][0] = NORTH_EAST
;
758 board
[WIDTH
-1][0] = EAST_SOUTH
;
759 board
[0][HEIGHT
-1] = SOUTH_EAST
;
760 board
[WIDTH
-1][HEIGHT
-1] = EAST_NORTH
;
764 ** Redraw the entire board
770 for (x
= 0; x
< WIDTH
; x
++)
772 for (y
= 0; y
< HEIGHT
; y
++)
777 rb
->lcd_fillrect((CENTER_X
+x
*MULTIPLIER
)+1,CENTER_Y
+y
*MULTIPLIER
,MODIFIER_2
,MODIFIER_1
);
778 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
,(CENTER_Y
+y
*MULTIPLIER
)+1,MODIFIER_1
,MODIFIER_2
);
785 draw_vertical_bit(x
,y
);
790 draw_horizontal_bit(x
,y
);
794 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
,CENTER_Y
+y
*MULTIPLIER
,MODIFIER_1
,MODIFIER_1
);
802 ** Draws the snake bit described by nCurrentBit at position x/y
803 ** deciding whether it's a corner bit by examing the nPrevious bit
805 void draw_snake_bit(int currentbit
, int previousbit
, int x
, int y
)
807 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
808 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
,CENTER_Y
+y
*MULTIPLIER
,MODIFIER_1
,MODIFIER_1
);
809 rb
->lcd_set_drawmode(DRMODE_SOLID
);
818 draw_vertical_bit(x
,y
);
822 draw_e_to_n_bit(x
,y
);
826 draw_w_to_n_bit(x
,y
);
836 draw_horizontal_bit(x
,y
);
840 draw_n_to_e_bit(x
,y
);
844 draw_s_to_e_bit(x
,y
);
854 draw_vertical_bit(x
,y
);
858 draw_e_to_s_bit(x
,y
);
862 draw_w_to_s_bit(x
,y
);
872 draw_horizontal_bit(x
,y
);
876 draw_s_to_w_bit(x
,y
);
880 draw_n_to_w_bit(x
,y
);
888 ** Death 'sequence' and end game stuff.
896 rb
->splash(HZ
*2, "Oops!");
898 rb
->lcd_clear_display();
902 rb
->lcd_getstringsize("You died!",&strwdt
,&strhgt
);
903 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
,"You died!");
905 rb
->snprintf(pscore
,sizeof(pscore
),"Your score: %d",score
);
906 rb
->lcd_getstringsize(pscore
,&strwdt
,&strhgt
);
907 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
* 2 + 2,pscore
);
912 rb
->lcd_getstringsize("New high score!",&strwdt
,&strhgt
);
913 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
* 4 + 2,"New high score!");
917 rb
->snprintf(phscore
,sizeof(phscore
),"High score: %d",hiscore
);
918 rb
->lcd_getstringsize(phscore
,&strwdt
,&strhgt
);
919 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
* 5,phscore
);
922 rb
->snprintf(phscore
,sizeof(phscore
),"Press %s...",SNAKE2_PLAYPAUSE_TEXT
);
923 rb
->lcd_getstringsize(phscore
,&strwdt
,&strhgt
);
924 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
* 7,phscore
);
930 button
=rb
->button_get(true);
933 case SNAKE2_PLAYPAUSE
:
943 ** Check for collision. TODO: Currently this
944 ** sets of the death sequence. What we want is it to only return a true/false
945 ** depending on whether a collision occured.
947 void collision ( int x
, int y
)
958 score
= score
+ (1 * level
);
965 if(num_apples_to_get
== num_apples_to_got
)
968 if(level_from_file
>= num_levels
)
971 /*and increase the number of apples to pick up
972 before level changes*/
973 num_apples_to_get
+=2;
976 rb
->splash(HZ
, "Level Completed!");
977 rb
->lcd_clear_display();
978 new_level(level_from_file
);
979 rb
->lcd_clear_display();
1003 /*this actually sets the dir variable.*/
1009 board
[headx
][heady
]=NORTH
;
1013 board
[headx
][heady
]=EAST
;
1017 board
[headx
][heady
]=SOUTH
;
1021 board
[headx
][heady
]=WEST
;
1036 rb
->lcd_fillrect(CENTER_X
+headx
*MULTIPLIER
,CENTER_Y
+heady
*MULTIPLIER
,MODIFIER_1
,MODIFIER_1
);
1039 if(applecountdown
<= 0)
1041 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
1042 rb
->lcd_fillrect(CENTER_X
+tailx
*MULTIPLIER
,CENTER_Y
+taily
*MULTIPLIER
,MODIFIER_1
,MODIFIER_1
);
1043 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1045 taildir
= board
[tailx
][taily
];
1046 board
[tailx
][taily
] = 0;
1083 int olddir
, noldx
, noldy
, temp
;
1090 if(heady
== HEIGHT
-1)
1095 olddir
= board
[headx
][temp
];
1104 olddir
= board
[temp
][heady
];
1113 olddir
= board
[headx
][temp
];
1117 if(headx
== WIDTH
-1)
1122 olddir
= board
[temp
][heady
];
1129 now redraw the bit that was
1130 the tail, to something snake-like:
1132 draw_snake_bit(dir
, olddir
, noldx
, noldy
);
1134 collision(headx
, heady
);
1139 void game_pause (void)
1143 rb
->lcd_clear_display();
1144 rb
->lcd_getstringsize("Paused",&strwdt
,&strhgt
);
1145 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,LCD_HEIGHT
/2,"Paused");
1150 button
= rb
->button_get(true);
1153 case SNAKE2_PLAYPAUSE
:
1154 rb
->lcd_clear_display();
1160 #ifdef SNAKE2_RC_QUIT
1161 case SNAKE2_RC_QUIT
:
1169 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
) {
1183 rb
->lcd_clear_display();
1192 if(frames
>0) frames
=0;
1206 /*it has, great set frames to a positive value again:*/
1216 rb
->sleep(HZ
/speed
);
1218 button
= rb
->button_get(false);
1220 #ifdef HAS_BUTTON_HOLD
1221 if (rb
->button_hold())
1222 button
= SNAKE2_PLAYPAUSE
;
1228 case SNAKE2_UP
| BUTTON_REPEAT
:
1229 if (dir
!= SOUTH
) set_direction(NORTH
);
1233 case SNAKE2_RIGHT
| BUTTON_REPEAT
:
1234 if (dir
!= WEST
) set_direction(EAST
);
1238 case SNAKE2_DOWN
| BUTTON_REPEAT
:
1239 if (dir
!= NORTH
) set_direction(SOUTH
);
1243 case SNAKE2_LEFT
| BUTTON_REPEAT
:
1244 if (dir
!= EAST
) set_direction(WEST
);
1247 #ifdef SNAKE2_RC_QUIT
1248 case SNAKE2_RC_QUIT
:
1254 case SNAKE2_PLAYPAUSE
:
1259 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
) {
1269 void game_init(void)
1280 load_level( level_from_file
);
1281 rb
->lcd_clear_display();
1287 #if LCD_WIDTH >= 160 && LCD_HEIGHT >= 128
1289 rb
->lcd_bitmap(snake2_header1
,0,0,BMPWIDTH_snake2_header
, BMPHEIGHT_snake2_header
);
1290 rb
->lcd_bitmap(snake2_left
,0,BMPHEIGHT_snake2_header
,BMPWIDTH_snake2_left
, BMPHEIGHT_snake2_left
);
1291 rb
->lcd_bitmap(snake2_right
,LCD_WIDTH
-BMPWIDTH_snake2_right
,BMPHEIGHT_snake2_header
,BMPWIDTH_snake2_right
, BMPHEIGHT_snake2_right
);
1292 rb
->lcd_bitmap(snake2_bottom
,0,BMPHEIGHT_snake2_header
+BMPHEIGHT_snake2_left
,BMPWIDTH_snake2_bottom
, BMPHEIGHT_snake2_bottom
);
1294 rb
->snprintf(plevel
,sizeof(plevel
),"%d",level
);
1295 rb
->lcd_getstringsize(plevel
,&strwdt
,&strhgt
);
1296 rb
->lcd_putsxy(TOP_X3
-strwdt
/2,TOP_Y2
, plevel
);
1298 rb
->snprintf(plevel
,sizeof(plevel
),"%d",level_from_file
);
1299 rb
->lcd_getstringsize(plevel
,&strwdt
,&strhgt
);
1300 rb
->lcd_putsxy(TOP_X2
-strwdt
/2,TOP_Y1
, plevel
);
1303 rb
->lcd_getstringsize("A",&strwdt
,&strhgt
);
1304 rb
->lcd_putsxy(TOP_X1
,TOP_Y1
,"A");
1307 rb
->lcd_getstringsize("B",&strwdt
,&strhgt
);
1308 rb
->lcd_putsxy(TOP_X1
,TOP_Y1
,"B");
1311 rb
->snprintf(phscore
,sizeof(phscore
),"%d",hiscore
);
1312 rb
->lcd_getstringsize(phscore
,&strwdt
,&strhgt
);
1313 rb
->lcd_putsxy(TOP_X4
-strwdt
/2,TOP_Y2
, phscore
);
1316 rb
->snprintf(plevel
,sizeof(plevel
),"Speed: %02d",level
);
1317 rb
->lcd_getstringsize("Speed: 00",&strwdt
,&strhgt
);
1318 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
+4, plevel
);
1320 rb
->snprintf(plevel
,sizeof(plevel
),"Maze: %d",level_from_file
);
1321 rb
->lcd_getstringsize(plevel
,&strwdt
,&strhgt
);
1322 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
*2+4, plevel
);
1325 rb
->lcd_getstringsize("Game Type: A ",&strwdt
,&strhgt
);
1326 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
*3+4,"Game Type: A");
1329 rb
->lcd_getstringsize("Game Type: B ",&strwdt
,&strhgt
);
1330 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
*3+4,"Game Type: B");
1333 rb
->snprintf(phscore
,sizeof(phscore
),"Hi Score: %d",hiscore
);
1334 rb
->lcd_getstringsize(phscore
,&strwdt
,&strhgt
);
1335 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
*4+4, phscore
);
1340 button
=rb
->button_get(true);
1343 case SNAKE2_LEVEL_UP
:
1344 case SNAKE2_LEVEL_UP
|BUTTON_REPEAT
:
1348 case SNAKE2_LEVEL_DOWN
:
1349 case SNAKE2_LEVEL_DOWN
|BUTTON_REPEAT
:
1357 case SNAKE2_PLAYPAUSE
:
1361 case SNAKE2_SELECT_TYPE
:
1362 if(game_type
==0)game_type
=1; else game_type
=0;
1364 case SNAKE2_MAZE_NEXT
:
1365 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
1366 rb
->lcd_fillrect(CENTER_X
, CENTER_Y
, CENTER_X
+WIDTH
*MULTIPLIER
,
1367 CENTER_Y
+HEIGHT
*MULTIPLIER
);
1368 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1369 if(level_from_file
< num_levels
)
1372 level_from_file
= 0;
1373 load_level( level_from_file
);
1376 #ifdef SNAKE2_MAZE_LAST
1377 case SNAKE2_MAZE_LAST
:
1378 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
1379 rb
->lcd_fillrect(CENTER_X
, CENTER_Y
, CENTER_X
+WIDTH
*MULTIPLIER
,
1380 CENTER_Y
+HEIGHT
*MULTIPLIER
);
1381 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1382 if(level_from_file
> 0)
1385 level_from_file
= num_levels
;
1386 load_level( level_from_file
);
1391 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
) {
1401 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
1406 /* Lets use the default font */
1407 rb
->lcd_setfont(FONT_SYSFIXED
);
1409 rb
->lcd_set_backdrop(NULL
);
1411 #ifdef HAVE_LCD_COLOR
1412 rb
->lcd_set_foreground(LCD_BLACK
);
1413 rb
->lcd_set_background(LCD_WHITE
);
1418 if (num_levels
== 0) {
1419 rb
->splash(HZ
*2, "Failed loading levels!");
1428 rb
->lcd_clear_display();
1441 return (quit
==1) ? PLUGIN_OK
: PLUGIN_USB_CONNECTED
;