1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2003 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 ****************************************************************************/
25 Board consists of a WIDTHxHEIGHT grid. If board element is 0 then nothing is
26 there otherwise it is part of the snake or a wall.
28 Head and Tail are stored
33 #ifdef HAVE_LCD_BITMAP
40 #if (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) && (LCD_DEPTH >= 1)
41 #include "pluginbitmaps/snake2_header1.h"
42 #include "pluginbitmaps/snake2_header2.h"
43 #include "pluginbitmaps/snake2_left.h"
44 #include "pluginbitmaps/snake2_right.h"
45 #include "pluginbitmaps/snake2_bottom.h"
46 #define BMPHEIGHT_snake2_header BMPHEIGHT_snake2_header1
47 #define BMPWIDTH_snake2_header BMPWIDTH_snake2_header1
51 #if (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240)
52 #define MULTIPLIER 10 /*Modifier for porting on other screens*/
57 #define TOP_X1 34 /* x-coord of the upperleft item (game type) */
58 #define TOP_X2 281 /* x-coord of the upperright item (maze type) */
59 #define TOP_X3 42 /* x-coord of the lowerleft item (speed) */
60 #define TOP_X4 274 /* x-coord of the lowerright item (hi-score) */
61 #define TOP_Y1 4 /* y-coord of the top row of items */
62 #define TOP_Y2 25 /* y-coord of the bottom row of items */
63 #elif (LCD_WIDTH >= 240) && (LCD_HEIGHT >= 168)
75 #elif (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176)
87 #elif (LCD_WIDTH >= 176) && (LCD_HEIGHT >= 132)
99 #elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128)
120 /* variable button definitions */
121 #if CONFIG_KEYPAD == RECORDER_PAD
122 #define SNAKE2_LEFT BUTTON_LEFT
123 #define SNAKE2_RIGHT BUTTON_RIGHT
124 #define SNAKE2_UP BUTTON_UP
125 #define SNAKE2_DOWN BUTTON_DOWN
126 #define SNAKE2_QUIT BUTTON_OFF
127 #define SNAKE2_LEVEL_UP BUTTON_UP
128 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
129 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
130 #define SNAKE2_MAZE_LAST BUTTON_LEFT
131 #define SNAKE2_SELECT_TYPE BUTTON_F3
132 #define SNAKE2_PLAYPAUSE BUTTON_PLAY
133 #define SNAKE2_PLAYPAUSE_TEXT "Play"
135 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
136 #define SNAKE2_LEFT BUTTON_LEFT
137 #define SNAKE2_RIGHT BUTTON_RIGHT
138 #define SNAKE2_UP BUTTON_UP
139 #define SNAKE2_DOWN BUTTON_DOWN
140 #define SNAKE2_QUIT BUTTON_OFF
141 #define SNAKE2_LEVEL_UP BUTTON_UP
142 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
143 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
144 #define SNAKE2_MAZE_LAST BUTTON_LEFT
145 #define SNAKE2_SELECT_TYPE BUTTON_F3
146 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
147 #define SNAKE2_PLAYPAUSE_TEXT "Select"
149 #elif CONFIG_KEYPAD == ONDIO_PAD
150 #define SNAKE2_LEFT BUTTON_LEFT
151 #define SNAKE2_RIGHT BUTTON_RIGHT
152 #define SNAKE2_UP BUTTON_UP
153 #define SNAKE2_DOWN BUTTON_DOWN
154 #define SNAKE2_QUIT BUTTON_OFF
155 #define SNAKE2_LEVEL_UP BUTTON_UP
156 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
157 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
158 #define SNAKE2_SELECT_TYPE BUTTON_LEFT
159 #define SNAKE2_PLAYPAUSE BUTTON_MENU
160 #define SNAKE2_PLAYPAUSE_TEXT "Menu"
162 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
163 (CONFIG_KEYPAD == IRIVER_H300_PAD)
164 #define SNAKE2_LEFT BUTTON_LEFT
165 #define SNAKE2_RIGHT BUTTON_RIGHT
166 #define SNAKE2_UP BUTTON_UP
167 #define SNAKE2_DOWN BUTTON_DOWN
168 #define SNAKE2_QUIT BUTTON_OFF
169 #define SNAKE2_LEVEL_UP BUTTON_UP
170 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
171 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
172 #define SNAKE2_MAZE_LAST BUTTON_LEFT
173 #define SNAKE2_SELECT_TYPE BUTTON_MODE
174 #define SNAKE2_PLAYPAUSE BUTTON_ON
175 #define SNAKE2_PLAYPAUSE_TEXT "Play"
177 #define SNAKE2_RC_QUIT BUTTON_RC_STOP
178 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
179 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
180 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
181 #define SNAKE2_LEFT BUTTON_LEFT
182 #define SNAKE2_RIGHT BUTTON_RIGHT
183 #define SNAKE2_UP BUTTON_MENU
184 #define SNAKE2_DOWN BUTTON_PLAY
185 #define SNAKE2_QUIT (BUTTON_SELECT | BUTTON_MENU)
186 #define SNAKE2_LEVEL_UP BUTTON_SCROLL_FWD
187 #define SNAKE2_LEVEL_DOWN BUTTON_SCROLL_BACK
188 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
189 #define SNAKE2_MAZE_LAST BUTTON_LEFT
190 #define SNAKE2_SELECT_TYPE BUTTON_PLAY
191 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
192 #define SNAKE2_PLAYPAUSE_TEXT "Select"
194 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
195 #define SNAKE2_LEFT BUTTON_LEFT
196 #define SNAKE2_RIGHT BUTTON_RIGHT
197 #define SNAKE2_UP BUTTON_UP
198 #define SNAKE2_DOWN BUTTON_DOWN
199 #define SNAKE2_QUIT BUTTON_POWER
200 #define SNAKE2_LEVEL_UP BUTTON_UP
201 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
202 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
203 #define SNAKE2_MAZE_LAST BUTTON_LEFT
204 #define SNAKE2_SELECT_TYPE BUTTON_PLAY
205 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
206 #define SNAKE2_PLAYPAUSE_TEXT "Select"
208 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
209 #define SNAKE2_LEFT BUTTON_LEFT
210 #define SNAKE2_RIGHT BUTTON_RIGHT
211 #define SNAKE2_UP BUTTON_UP
212 #define SNAKE2_DOWN BUTTON_DOWN
213 #define SNAKE2_QUIT BUTTON_POWER
214 #define SNAKE2_LEVEL_UP BUTTON_UP
215 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
216 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
217 #define SNAKE2_MAZE_LAST BUTTON_LEFT
218 #define SNAKE2_SELECT_TYPE BUTTON_MENU
219 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
220 #define SNAKE2_PLAYPAUSE_TEXT "Select"
222 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
223 (CONFIG_KEYPAD == SANSA_C200_PAD)
224 #define SNAKE2_LEFT BUTTON_LEFT
225 #define SNAKE2_RIGHT BUTTON_RIGHT
226 #define SNAKE2_UP BUTTON_UP
227 #define SNAKE2_DOWN BUTTON_DOWN
228 #define SNAKE2_QUIT BUTTON_POWER
229 #define SNAKE2_LEVEL_UP BUTTON_UP
230 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
231 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
232 #define SNAKE2_MAZE_LAST BUTTON_LEFT
233 #define SNAKE2_SELECT_TYPE BUTTON_REC
234 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
235 #define SNAKE2_PLAYPAUSE_TEXT "Select"
237 #elif (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
238 (CONFIG_KEYPAD == SANSA_M200_PAD)
239 #define SNAKE2_LEFT BUTTON_LEFT
240 #define SNAKE2_RIGHT BUTTON_RIGHT
241 #define SNAKE2_UP BUTTON_UP
242 #define SNAKE2_DOWN BUTTON_DOWN
243 #define SNAKE2_QUIT BUTTON_POWER
244 #define SNAKE2_LEVEL_UP BUTTON_UP
245 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
246 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
247 #define SNAKE2_MAZE_LAST BUTTON_LEFT
248 #define SNAKE2_SELECT_TYPE BUTTON_VOL_UP
249 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
250 #define SNAKE2_PLAYPAUSE_TEXT "Select"
252 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
253 #define SNAKE2_LEFT BUTTON_LEFT
254 #define SNAKE2_RIGHT BUTTON_RIGHT
255 #define SNAKE2_UP BUTTON_UP
256 #define SNAKE2_DOWN BUTTON_DOWN
257 #define SNAKE2_QUIT (BUTTON_HOME|BUTTON_REPEAT)
258 #define SNAKE2_LEVEL_UP BUTTON_UP
259 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
260 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
261 #define SNAKE2_MAZE_LAST BUTTON_LEFT
262 #define SNAKE2_SELECT_TYPE BUTTON_SELECT|BUTTON_REL
263 #define SNAKE2_PLAYPAUSE BUTTON_SELECT|BUTTON_REPEAT
264 #define SNAKE2_PLAYPAUSE_TEXT "Hold Select"
266 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
267 #define SNAKE2_LEFT BUTTON_LEFT
268 #define SNAKE2_RIGHT BUTTON_RIGHT
269 #define SNAKE2_UP BUTTON_SCROLL_UP
270 #define SNAKE2_DOWN BUTTON_SCROLL_DOWN
271 #define SNAKE2_QUIT BUTTON_POWER
272 #define SNAKE2_LEVEL_UP BUTTON_SCROLL_UP
273 #define SNAKE2_LEVEL_DOWN BUTTON_SCROLL_DOWN
274 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
275 #define SNAKE2_MAZE_LAST BUTTON_LEFT
276 #define SNAKE2_SELECT_TYPE BUTTON_PLAY
277 #define SNAKE2_PLAYPAUSE BUTTON_FF
278 #define SNAKE2_PLAYPAUSE_TEXT "FF"
280 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
281 #define SNAKE2_LEFT BUTTON_LEFT
282 #define SNAKE2_RIGHT BUTTON_RIGHT
283 #define SNAKE2_UP BUTTON_UP
284 #define SNAKE2_DOWN BUTTON_DOWN
285 #define SNAKE2_QUIT BUTTON_BACK
286 #define SNAKE2_LEVEL_UP BUTTON_UP
287 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
288 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
289 #define SNAKE2_MAZE_LAST BUTTON_LEFT
290 #define SNAKE2_SELECT_TYPE BUTTON_MENU
291 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
292 #define SNAKE2_PLAYPAUSE_TEXT "Select"
294 #elif (CONFIG_KEYPAD == MROBE100_PAD)
295 #define SNAKE2_LEFT BUTTON_LEFT
296 #define SNAKE2_RIGHT BUTTON_RIGHT
297 #define SNAKE2_UP BUTTON_UP
298 #define SNAKE2_DOWN BUTTON_DOWN
299 #define SNAKE2_QUIT BUTTON_POWER
300 #define SNAKE2_LEVEL_UP BUTTON_UP
301 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
302 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
303 #define SNAKE2_MAZE_LAST BUTTON_LEFT
304 #define SNAKE2_SELECT_TYPE BUTTON_MENU
305 #define SNAKE2_PLAYPAUSE BUTTON_SELECT
306 #define SNAKE2_PLAYPAUSE_TEXT "Select"
308 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
309 #define SNAKE2_LEFT BUTTON_RC_REW
310 #define SNAKE2_RIGHT BUTTON_RC_FF
311 #define SNAKE2_UP BUTTON_RC_VOL_UP
312 #define SNAKE2_DOWN BUTTON_RC_VOL_DOWN
313 #define SNAKE2_QUIT BUTTON_RC_REC
314 #define SNAKE2_LEVEL_UP BUTTON_RC_VOL_UP
315 #define SNAKE2_LEVEL_DOWN BUTTON_RC_VOL_DOWN
316 #define SNAKE2_MAZE_NEXT BUTTON_RC_FF
317 #define SNAKE2_MAZE_LAST BUTTON_RC_REW
318 #define SNAKE2_SELECT_TYPE BUTTON_RC_MODE
319 #define SNAKE2_PLAYPAUSE BUTTON_RC_PLAY
320 #define SNAKE2_PLAYPAUSE_TEXT "Play"
322 #elif (CONFIG_KEYPAD == COWOND2_PAD)
323 #define SNAKE2_QUIT BUTTON_POWER
325 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
326 #define SNAKE2_LEFT BUTTON_LEFT
327 #define SNAKE2_RIGHT BUTTON_RIGHT
328 #define SNAKE2_UP BUTTON_UP
329 #define SNAKE2_DOWN BUTTON_DOWN
330 #define SNAKE2_QUIT BUTTON_BACK
331 #define SNAKE2_LEVEL_UP BUTTON_UP
332 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
333 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
334 #define SNAKE2_MAZE_LAST BUTTON_LEFT
335 #define SNAKE2_SELECT_TYPE BUTTON_MENU
336 #define SNAKE2_PLAYPAUSE BUTTON_PLAY
337 #define SNAKE2_PLAYPAUSE_TEXT "Play"
339 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
340 #define SNAKE2_LEFT BUTTON_LEFT
341 #define SNAKE2_RIGHT BUTTON_RIGHT
342 #define SNAKE2_UP BUTTON_UP
343 #define SNAKE2_DOWN BUTTON_DOWN
344 #define SNAKE2_QUIT BUTTON_POWER
345 #define SNAKE2_LEVEL_UP BUTTON_UP
346 #define SNAKE2_LEVEL_DOWN BUTTON_DOWN
347 #define SNAKE2_MAZE_NEXT BUTTON_RIGHT
348 #define SNAKE2_MAZE_LAST BUTTON_LEFT
349 #define SNAKE2_SELECT_TYPE BUTTON_MENU
350 #define SNAKE2_PLAYPAUSE BUTTON_VIEW
351 #define SNAKE2_PLAYPAUSE_TEXT "View"
353 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || CONFIG_KEYPAD == MROBE500_PAD
354 #define SNAKE2_QUIT BUTTON_POWER
357 #error No keymap defined!
360 #ifdef HAVE_TOUCHSCREEN
362 #define SNAKE2_LEFT BUTTON_MIDLEFT
365 #define SNAKE2_RIGHT BUTTON_MIDRIGHT
368 #define SNAKE2_UP BUTTON_TOPMIDDLE
371 #define SNAKE2_DOWN BUTTON_BOTTOMMIDDLE
374 #define SNAKE2_QUIT BUTTON_TOPLEFT
376 #ifndef SNAKE2_LEVEL_UP
377 #define SNAKE2_LEVEL_UP BUTTON_TOPRIGHT
379 #ifndef SNAKE2_LEVEL_DOWN
380 #define SNAKE2_LEVEL_DOWN BUTTON_TOPLEFT
382 #ifndef SNAKE2_MAZE_NEXT
383 #define SNAKE2_MAZE_NEXT BUTTON_TOPMIDDLE
385 #ifndef SNAKE2_MAZE_LAST
386 #define SNAKE2_MAZE_LAST BUTTON_BOTTOMMIDDLE
388 #ifndef SNAKE2_SELECT_TYPE
389 #define SNAKE2_SELECT_TYPE BUTTON_BOTTOMLEFT
391 #ifndef SNAKE2_PLAYPAUSE
392 #define SNAKE2_PLAYPAUSE BUTTON_CENTER
394 #ifndef SNAKE2_PLAYPAUSE_TEXT
395 #define SNAKE2_PLAYPAUSE_TEXT "CENTER"
399 static int max_levels
= 0;
400 static char (*level_cache
)[HEIGHT
][WIDTH
];
402 /*Board itself - 2D int array*/
403 static int board
[WIDTH
][HEIGHT
];
405 Buffer for sorting movement (in case user presses two movements during a
408 static int ardirectionbuffer
[2];
409 static unsigned int score
, hiscore
= 0;
412 static int strwdt
,strhgt
; /*used for string width, height for orientation purposes*/
416 static int level
= 4, speed
= 5,dead
= 0, quit
= 0;
417 static int sillydir
= 0, num_levels
= 0;
418 static int level_from_file
= 0;
419 static int headx
, heady
, tailx
, taily
, applecountdown
= 5;
420 static int game_type
= 0;
421 static int num_apples_to_get
=1;
422 static int num_apples_to_got
=0;
423 static int game_b_level
=0;
424 static int applecount
=0;
425 static char phscore
[30];
433 #define EAST_NORTH 32
434 #define EAST_SOUTH 64
435 #define WEST_NORTH 128
436 #define WEST_SOUTH 256
438 #define NORTH_EAST 512
439 #define NORTH_WEST 1024
440 #define SOUTH_EAST 2048
441 #define SOUTH_WEST 4096
443 #define LEVELS_FILE PLUGIN_GAMES_DIR "/snake2.levels"
444 #define HISCORE_FILE PLUGIN_GAMES_DIR "/snake2.hs"
446 int load_all_levels(void)
451 char buf
[64]; /* Larger than WIDTH, to allow for whitespace after the
454 /* Init the level_cache pointer and
455 calculate how many levels that will fit */
456 level_cache
= rb
->plugin_get_buffer((size_t *)&size
);
457 max_levels
= size
/ (HEIGHT
*WIDTH
);
462 if ((fd
= rb
->open(LEVELS_FILE
, O_RDONLY
)) < 0)
467 while(rb
->read_line(fd
, buf
, 64))
469 if(rb
->strlen(buf
) == 0) /* Separator? */
472 if(num_levels
> max_levels
)
474 rb
->splash(HZ
, "Too many levels in file");
480 rb
->memcpy(level_cache
[num_levels
][linecnt
], buf
, WIDTH
);
482 if(linecnt
== HEIGHT
)
492 /*Hi-Score reading and writing to file "/.rockbox/rocks/games/snake2.levels" function */
496 unsigned int compare
;
498 /* clear the buffer we're about to load the highscore data into */
499 rb
->memset(phscore
, 0, sizeof(phscore
));
501 fd
= rb
->open(HISCORE_FILE
,O_RDWR
| O_CREAT
);
503 /* highscore used to %d, is now %d\n
504 Deal with no file or bad file */
505 rb
->read(fd
,phscore
, sizeof(phscore
));
507 compare
= rb
->atoi(phscore
);
509 if(hiscore
> compare
){
510 rb
->lseek(fd
,0,SEEK_SET
);
511 rb
->fdprintf(fd
, "%d\n", hiscore
);
521 ** Completely clear the board of walls and/or snake */
523 void clear_board( void)
527 for (x
= 0; x
< WIDTH
; x
++)
529 for (y
= 0; y
< HEIGHT
; y
++)
536 int load_level( int level_number
)
540 for(y
= 0;y
< HEIGHT
;y
++)
542 for(x
= 0;x
< WIDTH
;x
++)
544 switch(level_cache
[level_number
][y
][x
])
564 ** Gets the currently chosen direction from the first place
565 ** in the direction buffer. If there is something in the
566 ** next part of the buffer then that is moved to the first place
568 void get_direction( void )
570 /*if 1st place is empty*/
571 if(ardirectionbuffer
[0] != -1)
573 /*return this direction*/
574 dir
= ardirectionbuffer
[0];
575 ardirectionbuffer
[0]=-1;
576 /*now see if one needs moving:*/
577 if(ardirectionbuffer
[1] != -1)
579 /*there's a move waiting to be done
580 so move it into the space:*/
581 ardirectionbuffer
[0] = ardirectionbuffer
[1];
582 ardirectionbuffer
[1] = -1;
588 ** Sets the direction
590 void set_direction(int newdir
)
592 if(ardirectionbuffer
[0] != newdir
)
594 /*if 1st place is empty*/
595 if(ardirectionbuffer
[0] == -1)
598 ardirectionbuffer
[0] = newdir
;
603 if(ardirectionbuffer
[0] != newdir
) ardirectionbuffer
[1] = newdir
;
606 if(frames
< 0) ardirectionbuffer
[0] = newdir
;
610 void new_level(int level
)
614 ardirectionbuffer
[0] = -1;
615 ardirectionbuffer
[1] = -1;
622 /*Create a small snake to start off with*/
623 board
[headx
][heady
] = dir
;
624 board
[headx
-1][heady
] = dir
;
625 board
[headx
-2][heady
] = dir
;
626 board
[headx
-3][heady
] = dir
;
627 board
[headx
-4][heady
] = dir
;
631 void init_snake(void)
637 new_level(level_from_file
);
641 ** Draws the apple. If it doesn't exist then
642 ** a new one get's created.
644 void draw_apple( void )
648 #if LCD_WIDTH >= 160 && LCD_HEIGHT >= 128
649 char pscore
[5], counter
[4];
651 rb
->lcd_bitmap(snake2_header2
,0,0,BMPWIDTH_snake2_header
, BMPHEIGHT_snake2_header
);
652 rb
->lcd_bitmap(snake2_left
,0,BMPHEIGHT_snake2_header
,BMPWIDTH_snake2_left
, BMPHEIGHT_snake2_left
);
653 rb
->lcd_bitmap(snake2_right
,LCD_WIDTH
-BMPWIDTH_snake2_right
,BMPHEIGHT_snake2_header
,BMPWIDTH_snake2_right
, BMPHEIGHT_snake2_right
);
654 rb
->lcd_bitmap(snake2_bottom
,0,BMPHEIGHT_snake2_header
+BMPHEIGHT_snake2_left
,BMPWIDTH_snake2_bottom
, BMPHEIGHT_snake2_bottom
);
656 rb
->snprintf(counter
,sizeof(counter
),"%d",applecount
);
657 rb
->lcd_getstringsize(counter
,&strwdt
,&strhgt
);
658 rb
->lcd_putsxy(TOP_X3
-strwdt
/2,TOP_Y2
,counter
);
660 rb
->snprintf(pscore
,sizeof(pscore
),"%d",score
);
661 rb
->lcd_getstringsize(pscore
,&strwdt
,&strhgt
);
662 rb
->lcd_putsxy(TOP_X4
-strwdt
/2,TOP_Y2
,pscore
);
669 x
= (rb
->rand() % (WIDTH
-1))+1;
670 y
= (rb
->rand() % (HEIGHT
-1))+1;
671 } while (board
[x
][y
]);
674 applex
= x
;appley
= y
;
676 rb
->lcd_fillrect((CENTER_X
+applex
*MULTIPLIER
)+1,CENTER_Y
+appley
*MULTIPLIER
,MODIFIER_2
,MODIFIER_1
);
677 rb
->lcd_fillrect(CENTER_X
+applex
*MULTIPLIER
,(CENTER_Y
+appley
*MULTIPLIER
)+1,MODIFIER_1
,MODIFIER_2
);
686 void draw_vertical_bit(int x
, int y
)
688 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+1,CENTER_Y
+y
*MULTIPLIER
,MODIFIER_2
,MODIFIER_1
);
697 void draw_horizontal_bit(int x
, int y
)
699 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
,CENTER_Y
+y
*MULTIPLIER
+1,MODIFIER_1
,MODIFIER_2
);
708 void draw_n_to_e_bit(int x
, int y
)
710 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+1,CENTER_Y
+y
*MULTIPLIER
+2,MODIFIER_2
,MODIFIER_2
);
711 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+2,CENTER_Y
+y
*MULTIPLIER
+1,MODIFIER_2
,MODIFIER_2
);
720 void draw_w_to_s_bit(int x
, int y
)
722 draw_n_to_e_bit(x
,y
);
731 void draw_n_to_w_bit(int x
, int y
)
733 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
,CENTER_Y
+y
*MULTIPLIER
+1,MODIFIER_2
,MODIFIER_2
);
734 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+1,CENTER_Y
+y
*MULTIPLIER
+2,MODIFIER_2
,MODIFIER_2
);
743 void draw_e_to_s_bit(int x
, int y
)
745 draw_n_to_w_bit(x
, y
);
754 void draw_s_to_e_bit(int x
, int y
)
756 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+1,CENTER_Y
+y
*MULTIPLIER
,MODIFIER_2
,MODIFIER_2
);
757 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+2,CENTER_Y
+y
*MULTIPLIER
+1,MODIFIER_2
,MODIFIER_2
);
766 void draw_w_to_n_bit(int x
, int y
)
768 draw_s_to_e_bit(x
,y
);
777 void draw_e_to_n_bit(int x
, int y
)
779 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
+1,CENTER_Y
+y
*MULTIPLIER
,MODIFIER_2
,MODIFIER_2
);
780 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
,CENTER_Y
+y
*MULTIPLIER
+1,MODIFIER_2
,MODIFIER_2
);
789 void draw_s_to_w_bit(int x
, int y
)
791 draw_e_to_n_bit(x
, y
);
795 ** Draws a wall/obsticals
797 void draw_boundary ( void )
801 /*TODO: Load levels from file!*/
803 /*top and bottom line*/
804 for(x
=0; x
< WIDTH
; x
++)
807 board
[x
][HEIGHT
-1] = WEST
;
810 /*left and right lines*/
811 for(y
=0; y
< HEIGHT
; y
++)
814 board
[WIDTH
-1][y
] = SOUTH
;
818 board
[0][0] = NORTH_EAST
;
819 board
[WIDTH
-1][0] = EAST_SOUTH
;
820 board
[0][HEIGHT
-1] = SOUTH_EAST
;
821 board
[WIDTH
-1][HEIGHT
-1] = EAST_NORTH
;
825 ** Redraw the entire board
831 for (x
= 0; x
< WIDTH
; x
++)
833 for (y
= 0; y
< HEIGHT
; y
++)
838 rb
->lcd_fillrect((CENTER_X
+x
*MULTIPLIER
)+1,CENTER_Y
+y
*MULTIPLIER
,MODIFIER_2
,MODIFIER_1
);
839 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
,(CENTER_Y
+y
*MULTIPLIER
)+1,MODIFIER_1
,MODIFIER_2
);
846 draw_vertical_bit(x
,y
);
851 draw_horizontal_bit(x
,y
);
855 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
,CENTER_Y
+y
*MULTIPLIER
,MODIFIER_1
,MODIFIER_1
);
863 ** Draws the snake bit described by nCurrentBit at position x/y
864 ** deciding whether it's a corner bit by examing the nPrevious bit
866 void draw_snake_bit(int currentbit
, int previousbit
, int x
, int y
)
868 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
869 rb
->lcd_fillrect(CENTER_X
+x
*MULTIPLIER
,CENTER_Y
+y
*MULTIPLIER
,MODIFIER_1
,MODIFIER_1
);
870 rb
->lcd_set_drawmode(DRMODE_SOLID
);
879 draw_vertical_bit(x
,y
);
883 draw_e_to_n_bit(x
,y
);
887 draw_w_to_n_bit(x
,y
);
897 draw_horizontal_bit(x
,y
);
901 draw_n_to_e_bit(x
,y
);
905 draw_s_to_e_bit(x
,y
);
915 draw_vertical_bit(x
,y
);
919 draw_e_to_s_bit(x
,y
);
923 draw_w_to_s_bit(x
,y
);
933 draw_horizontal_bit(x
,y
);
937 draw_s_to_w_bit(x
,y
);
941 draw_n_to_w_bit(x
,y
);
949 ** Death 'sequence' and end game stuff.
957 rb
->splash(HZ
*2, "Oops!");
959 rb
->lcd_clear_display();
963 rb
->lcd_getstringsize("You died!",&strwdt
,&strhgt
);
964 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
,"You died!");
966 rb
->snprintf(pscore
,sizeof(pscore
),"Your score: %d",score
);
967 rb
->lcd_getstringsize(pscore
,&strwdt
,&strhgt
);
968 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
* 2 + 2,pscore
);
973 rb
->lcd_getstringsize("New high score!",&strwdt
,&strhgt
);
974 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
* 4 + 2,"New high score!");
978 rb
->snprintf(phscore
,sizeof(phscore
),"High score: %d",hiscore
);
979 rb
->lcd_getstringsize(phscore
,&strwdt
,&strhgt
);
980 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
* 5,phscore
);
983 rb
->snprintf(phscore
,sizeof(phscore
),"Press %s...",SNAKE2_PLAYPAUSE_TEXT
);
984 rb
->lcd_getstringsize(phscore
,&strwdt
,&strhgt
);
985 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
* 7,phscore
);
991 button
=rb
->button_get(true);
994 case SNAKE2_PLAYPAUSE
:
1004 ** Check for collision. TODO: Currently this
1005 ** sets of the death sequence. What we want is it to only return a true/false
1006 ** depending on whether a collision occured.
1008 void collision ( int x
, int y
)
1013 switch (board
[x
][y
])
1019 score
= score
+ (1 * level
);
1026 if(num_apples_to_get
== num_apples_to_got
)
1029 if(level_from_file
>= num_levels
)
1031 level_from_file
= 1;
1032 /*and increase the number of apples to pick up
1033 before level changes*/
1034 num_apples_to_get
+=2;
1037 rb
->splash(HZ
, "Level Completed!");
1038 rb
->lcd_clear_display();
1039 new_level(level_from_file
);
1040 rb
->lcd_clear_display();
1045 num_apples_to_got
++;
1064 /*this actually sets the dir variable.*/
1070 board
[headx
][heady
]=NORTH
;
1074 board
[headx
][heady
]=EAST
;
1078 board
[headx
][heady
]=SOUTH
;
1082 board
[headx
][heady
]=WEST
;
1097 rb
->lcd_fillrect(CENTER_X
+headx
*MULTIPLIER
,CENTER_Y
+heady
*MULTIPLIER
,MODIFIER_1
,MODIFIER_1
);
1100 if(applecountdown
<= 0)
1102 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
1103 rb
->lcd_fillrect(CENTER_X
+tailx
*MULTIPLIER
,CENTER_Y
+taily
*MULTIPLIER
,MODIFIER_1
,MODIFIER_1
);
1104 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1106 taildir
= board
[tailx
][taily
];
1107 board
[tailx
][taily
] = 0;
1144 int olddir
, noldx
, noldy
, temp
;
1151 if(heady
== HEIGHT
-1)
1156 olddir
= board
[headx
][temp
];
1165 olddir
= board
[temp
][heady
];
1174 olddir
= board
[headx
][temp
];
1178 if(headx
== WIDTH
-1)
1183 olddir
= board
[temp
][heady
];
1190 now redraw the bit that was
1191 the tail, to something snake-like:
1193 draw_snake_bit(dir
, olddir
, noldx
, noldy
);
1195 collision(headx
, heady
);
1200 void game_pause (void)
1204 rb
->lcd_clear_display();
1205 rb
->lcd_getstringsize("Paused",&strwdt
,&strhgt
);
1206 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,LCD_HEIGHT
/2,"Paused");
1211 button
= rb
->button_get(true);
1214 case SNAKE2_PLAYPAUSE
:
1215 rb
->lcd_clear_display();
1221 #ifdef SNAKE2_RC_QUIT
1222 case SNAKE2_RC_QUIT
:
1230 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
) {
1244 rb
->lcd_clear_display();
1253 if(frames
>0) frames
=0;
1267 /*it has, great set frames to a positive value again:*/
1277 rb
->sleep(HZ
/speed
);
1279 button
= rb
->button_get(false);
1281 #ifdef HAS_BUTTON_HOLD
1282 if (rb
->button_hold())
1283 button
= SNAKE2_PLAYPAUSE
;
1289 case SNAKE2_UP
| BUTTON_REPEAT
:
1290 if (dir
!= SOUTH
) set_direction(NORTH
);
1294 case SNAKE2_RIGHT
| BUTTON_REPEAT
:
1295 if (dir
!= WEST
) set_direction(EAST
);
1299 case SNAKE2_DOWN
| BUTTON_REPEAT
:
1300 if (dir
!= NORTH
) set_direction(SOUTH
);
1304 case SNAKE2_LEFT
| BUTTON_REPEAT
:
1305 if (dir
!= EAST
) set_direction(WEST
);
1308 #ifdef SNAKE2_RC_QUIT
1309 case SNAKE2_RC_QUIT
:
1315 case SNAKE2_PLAYPAUSE
:
1320 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
) {
1330 void game_init(void)
1341 load_level( level_from_file
);
1342 rb
->lcd_clear_display();
1348 #if LCD_WIDTH >= 160 && LCD_HEIGHT >= 128
1350 rb
->lcd_bitmap(snake2_header1
,0,0,BMPWIDTH_snake2_header
, BMPHEIGHT_snake2_header
);
1351 rb
->lcd_bitmap(snake2_left
,0,BMPHEIGHT_snake2_header
,BMPWIDTH_snake2_left
, BMPHEIGHT_snake2_left
);
1352 rb
->lcd_bitmap(snake2_right
,LCD_WIDTH
-BMPWIDTH_snake2_right
,BMPHEIGHT_snake2_header
,BMPWIDTH_snake2_right
, BMPHEIGHT_snake2_right
);
1353 rb
->lcd_bitmap(snake2_bottom
,0,BMPHEIGHT_snake2_header
+BMPHEIGHT_snake2_left
,BMPWIDTH_snake2_bottom
, BMPHEIGHT_snake2_bottom
);
1355 rb
->snprintf(plevel
,sizeof(plevel
),"%d",level
);
1356 rb
->lcd_getstringsize(plevel
,&strwdt
,&strhgt
);
1357 rb
->lcd_putsxy(TOP_X3
-strwdt
/2,TOP_Y2
, plevel
);
1359 rb
->snprintf(plevel
,sizeof(plevel
),"%d",level_from_file
);
1360 rb
->lcd_getstringsize(plevel
,&strwdt
,&strhgt
);
1361 rb
->lcd_putsxy(TOP_X2
-strwdt
/2,TOP_Y1
, plevel
);
1364 rb
->lcd_getstringsize("A",&strwdt
,&strhgt
);
1365 rb
->lcd_putsxy(TOP_X1
,TOP_Y1
,"A");
1368 rb
->lcd_getstringsize("B",&strwdt
,&strhgt
);
1369 rb
->lcd_putsxy(TOP_X1
,TOP_Y1
,"B");
1372 rb
->snprintf(phscore
,sizeof(phscore
),"%d",hiscore
);
1373 rb
->lcd_getstringsize(phscore
,&strwdt
,&strhgt
);
1374 rb
->lcd_putsxy(TOP_X4
-strwdt
/2,TOP_Y2
, phscore
);
1377 rb
->snprintf(plevel
,sizeof(plevel
),"Speed: %02d",level
);
1378 rb
->lcd_getstringsize("Speed: 00",&strwdt
,&strhgt
);
1379 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
+4, plevel
);
1381 rb
->snprintf(plevel
,sizeof(plevel
),"Maze: %d",level_from_file
);
1382 rb
->lcd_getstringsize(plevel
,&strwdt
,&strhgt
);
1383 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
*2+4, plevel
);
1386 rb
->lcd_getstringsize("Game Type: A ",&strwdt
,&strhgt
);
1387 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
*3+4,"Game Type: A");
1390 rb
->lcd_getstringsize("Game Type: B ",&strwdt
,&strhgt
);
1391 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
*3+4,"Game Type: B");
1394 rb
->snprintf(phscore
,sizeof(phscore
),"Hi Score: %d",hiscore
);
1395 rb
->lcd_getstringsize(phscore
,&strwdt
,&strhgt
);
1396 rb
->lcd_putsxy((LCD_WIDTH
- strwdt
)/2,strhgt
*4+4, phscore
);
1401 button
=rb
->button_get(true);
1404 case SNAKE2_LEVEL_UP
:
1405 case SNAKE2_LEVEL_UP
|BUTTON_REPEAT
:
1409 case SNAKE2_LEVEL_DOWN
:
1410 case SNAKE2_LEVEL_DOWN
|BUTTON_REPEAT
:
1418 case SNAKE2_PLAYPAUSE
:
1422 case SNAKE2_SELECT_TYPE
:
1423 if(game_type
==0)game_type
=1; else game_type
=0;
1425 case SNAKE2_MAZE_NEXT
:
1426 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
1427 rb
->lcd_fillrect(CENTER_X
, CENTER_Y
, CENTER_X
+WIDTH
*MULTIPLIER
,
1428 CENTER_Y
+HEIGHT
*MULTIPLIER
);
1429 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1430 if(level_from_file
< num_levels
)
1433 level_from_file
= 0;
1434 load_level( level_from_file
);
1437 #ifdef SNAKE2_MAZE_LAST
1438 case SNAKE2_MAZE_LAST
:
1439 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_INVERSEVID
);
1440 rb
->lcd_fillrect(CENTER_X
, CENTER_Y
, CENTER_X
+WIDTH
*MULTIPLIER
,
1441 CENTER_Y
+HEIGHT
*MULTIPLIER
);
1442 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1443 if(level_from_file
> 0)
1446 level_from_file
= num_levels
;
1447 load_level( level_from_file
);
1452 if (rb
->default_event_handler(button
)==SYS_USB_CONNECTED
) {
1462 enum plugin_status
plugin_start(const void* parameter
)
1466 /* Lets use the default font */
1467 rb
->lcd_setfont(FONT_SYSFIXED
);
1469 rb
->lcd_set_backdrop(NULL
);
1471 #ifdef HAVE_LCD_COLOR
1472 rb
->lcd_set_foreground(LCD_BLACK
);
1473 rb
->lcd_set_background(LCD_WHITE
);
1478 if (num_levels
== 0) {
1479 rb
->splash(HZ
*2, "Failed loading levels!");
1488 rb
->lcd_clear_display();
1501 return (quit
==1) ? PLUGIN_OK
: PLUGIN_USB_CONNECTED
;