1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005, 2006 Ben Basha (Paprica)
11 * Copyright (C) 2009 Karl Kurbjun
12 * check_lines is based off an explanation and expanded math presented by Paul
13 * Bourke: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
26 #include "lib/configfile.h"
27 #include "lib/display_text.h"
28 #include "lib/helper.h"
29 #include "lib/highscore.h"
30 #include "lib/playback_control.h"
32 #include "pluginbitmaps/brickmania_pads.h"
33 #include "pluginbitmaps/brickmania_short_pads.h"
34 #include "pluginbitmaps/brickmania_long_pads.h"
35 #include "pluginbitmaps/brickmania_bricks.h"
36 #include "pluginbitmaps/brickmania_powerups.h"
37 #include "pluginbitmaps/brickmania_ball.h"
38 #include "pluginbitmaps/brickmania_gameover.h"
40 #ifdef HAVE_LCD_COLOR /* currently no transparency for non-colour */
41 #include "pluginbitmaps/brickmania_break.h"
53 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
54 (CONFIG_KEYPAD == IRIVER_H300_PAD)
55 #define CONTINUE_TEXT "Press NAVI To Continue"
56 #define QUIT BUTTON_OFF
57 #define LEFT BUTTON_LEFT
58 #define RIGHT BUTTON_RIGHT
59 #define SELECT BUTTON_SELECT
61 #define DOWN BUTTON_DOWN
62 #define RC_QUIT BUTTON_RC_STOP
64 #elif CONFIG_KEYPAD == ONDIO_PAD
65 #define CONTINUE_TEXT "MENU To Continue"
66 #define QUIT BUTTON_OFF
67 #define LEFT BUTTON_LEFT
68 #define RIGHT BUTTON_RIGHT
69 #define SELECT BUTTON_MENU
71 #define DOWN BUTTON_DOWN
73 #elif CONFIG_KEYPAD == RECORDER_PAD
74 #define QUIT BUTTON_OFF
75 #define LEFT BUTTON_LEFT
76 #define RIGHT BUTTON_RIGHT
77 #define SELECT BUTTON_PLAY
79 #define DOWN BUTTON_DOWN
81 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
82 #define QUIT BUTTON_OFF
83 #define LEFT BUTTON_LEFT
84 #define RIGHT BUTTON_RIGHT
85 #define SELECT BUTTON_SELECT
87 #define DOWN BUTTON_DOWN
89 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
90 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
91 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
92 #define QUIT BUTTON_MENU
93 #define LEFT BUTTON_LEFT
94 #define RIGHT BUTTON_RIGHT
95 #define SELECT BUTTON_SELECT
96 #define UP BUTTON_SCROLL_BACK
97 #define DOWN BUTTON_SCROLL_FWD
98 #define SCROLL_FWD(x) ((x) & BUTTON_SCROLL_FWD)
99 #define SCROLL_BACK(x) ((x) & BUTTON_SCROLL_BACK)
101 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
102 #define QUIT BUTTON_POWER
103 #define LEFT BUTTON_LEFT
104 #define RIGHT BUTTON_RIGHT
105 #define SELECT BUTTON_SELECT
107 #define DOWN BUTTON_DOWN
109 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
110 #define QUIT BUTTON_POWER
111 #define LEFT BUTTON_LEFT
112 #define RIGHT BUTTON_RIGHT
113 #define SELECT BUTTON_PLAY
115 #define DOWN BUTTON_DOWN
117 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
118 #define QUIT BUTTON_POWER
119 #define LEFT BUTTON_LEFT
120 #define RIGHT BUTTON_RIGHT
121 #define SELECT BUTTON_SELECT
123 #define DOWN BUTTON_DOWN
124 #define SCROLL_FWD(x) ((x) & BUTTON_SCROLL_FWD)
125 #define SCROLL_BACK(x) ((x) & BUTTON_SCROLL_BACK)
128 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
129 #define QUIT (BUTTON_HOME|BUTTON_REPEAT)
130 #define LEFT BUTTON_LEFT
131 #define RIGHT BUTTON_RIGHT
132 #define SELECT BUTTON_SELECT
134 #define DOWN BUTTON_DOWN
136 #define SCROLL_FWD(x) ((x) & BUTTON_SCROLL_FWD)
137 #define SCROLL_BACK(x) ((x) & BUTTON_SCROLL_BACK)
140 #elif CONFIG_KEYPAD == SANSA_C200_PAD || \
141 CONFIG_KEYPAD == SANSA_CLIP_PAD || \
142 CONFIG_KEYPAD == SANSA_M200_PAD || \
143 CONFIG_KEYPAD == SANSA_CONNECT_PAD
144 #define QUIT BUTTON_POWER
145 #define LEFT BUTTON_LEFT
146 #define RIGHT BUTTON_RIGHT
147 #define ALTLEFT BUTTON_VOL_DOWN
148 #define ALTRIGHT BUTTON_VOL_UP
149 #define SELECT BUTTON_SELECT
151 #define DOWN BUTTON_DOWN
153 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
154 #define QUIT BUTTON_POWER
155 #define LEFT BUTTON_LEFT
156 #define RIGHT BUTTON_RIGHT
157 #define SELECT BUTTON_PLAY
158 #define UP BUTTON_SCROLL_UP
159 #define DOWN BUTTON_SCROLL_DOWN
161 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD \
162 || CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
163 #define QUIT BUTTON_BACK
164 #define LEFT BUTTON_LEFT
165 #define RIGHT BUTTON_RIGHT
166 #define SELECT BUTTON_SELECT
168 #define DOWN BUTTON_DOWN
170 #elif (CONFIG_KEYPAD == MROBE100_PAD)
171 #define QUIT BUTTON_POWER
172 #define LEFT BUTTON_LEFT
173 #define RIGHT BUTTON_RIGHT
174 #define SELECT BUTTON_SELECT
176 #define DOWN BUTTON_DOWN
178 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
179 #define CONTINUE_TEXT "PLAY To Continue"
180 #define QUIT BUTTON_RC_REC
181 #define LEFT BUTTON_RC_REW
182 #define RIGHT BUTTON_RC_FF
183 #define SELECT BUTTON_RC_PLAY
184 #define UP BUTTON_RC_VOL_UP
185 #define DOWN BUTTON_RC_VOL_DOWN
186 #define RC_QUIT BUTTON_REC
188 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
189 #define QUIT BUTTON_BACK
190 #define LEFT BUTTON_LEFT
191 #define RIGHT BUTTON_RIGHT
192 #define SELECT BUTTON_SELECT
194 #define DOWN BUTTON_DOWN
196 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
197 #define QUIT BUTTON_POWER
198 #define LEFT BUTTON_LEFT
199 #define RIGHT BUTTON_RIGHT
200 #define SELECT BUTTON_SELECT
202 #define DOWN BUTTON_DOWN
204 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
205 #define QUIT BUTTON_POWER
206 #define LEFT BUTTON_LEFT
207 #define RIGHT BUTTON_RIGHT
208 #define SELECT BUTTON_PLAY
210 #define DOWN BUTTON_DOWN
212 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
213 #define QUIT BUTTON_POWER
214 #define LEFT BUTTON_PREV
215 #define RIGHT BUTTON_NEXT
216 #define SELECT BUTTON_PLAY
218 #define DOWN BUTTON_DOWN
220 #elif CONFIG_KEYPAD == COWON_D2_PAD
221 #define CONTINUE_TEXT "MENU To Continue"
222 #define QUIT BUTTON_POWER
223 #define LEFT BUTTON_MINUS
224 #define RIGHT BUTTON_PLUS
225 #define SELECT BUTTON_MENU
227 #elif CONFIG_KEYPAD == ONDAVX747_PAD
228 #define QUIT BUTTON_POWER
229 #define LEFT BUTTON_VOL_DOWN
230 #define RIGHT BUTTON_VOL_UP
231 #define SELECT BUTTON_MENU
232 #elif CONFIG_KEYPAD == ONDAVX777_PAD
233 #define QUIT BUTTON_POWER
235 #elif CONFIG_KEYPAD == MROBE500_PAD
236 #define QUIT BUTTON_POWER
238 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
239 #define QUIT BUTTON_FFWD
240 #define SELECT BUTTON_PLAY
241 #define LEFT BUTTON_LEFT
242 #define RIGHT BUTTON_RIGHT
244 #define DOWN BUTTON_DOWN
246 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
247 #define QUIT BUTTON_REC
248 #define LEFT BUTTON_PREV
249 #define RIGHT BUTTON_NEXT
250 #define ALTLEFT BUTTON_MENU
251 #define ALTRIGHT BUTTON_PLAY
252 #define SELECT BUTTON_OK
254 #define DOWN BUTTON_DOWN
256 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
257 #define QUIT (BUTTON_REC|BUTTON_PLAY)
258 #define LEFT BUTTON_VOL_DOWN
259 #define RIGHT BUTTON_VOL_UP
260 #define SELECT BUTTON_FUNC
261 #define UP BUTTON_REW
262 #define DOWN BUTTON_FF
264 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
265 #define QUIT (BUTTON_MENU|BUTTON_REPEAT)
266 #define LEFT BUTTON_REW
267 #define RIGHT BUTTON_FF
268 #define SELECT BUTTON_ENTER
270 #define DOWN BUTTON_DOWN
272 #elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
273 #define QUIT BUTTON_POWER
274 #define LEFT BUTTON_LEFT
275 #define RIGHT BUTTON_RIGHT
276 #define SELECT BUTTON_SELECT
278 #define DOWN BUTTON_DOWN
281 #error No keymap defined!
284 #ifdef HAVE_TOUCHSCREEN
286 #define ALTLEFT BUTTON_BOTTOMLEFT
288 #define LEFT BUTTON_BOTTOMLEFT
291 #define ALTRIGHT BUTTON_BOTTOMRIGHT
293 #define RIGHT BUTTON_BOTTOMRIGHT
296 #define ALTSELECT BUTTON_CENTER
298 #define SELECT BUTTON_CENTER
301 #define UP BUTTON_TOPMIDDLE
304 #define DOWN BUTTON_BOTTOMMIDDLE
308 /* Continue text is used as a string later when the game is paused. This allows
309 * targets to specify their own text if needed.
311 #if !defined(CONTINUE_TEXT)
312 #define CONTINUE_TEXT "Press SELECT To Continue"
315 #ifndef SCROLL_FWD /* targets without scroll wheel*/
316 #define SCROLL_FWD(x) (0)
317 #define SCROLL_BACK(x) (0)
321 #define NUM_BRICKS_ROWS 8
322 #define NUM_BRICKS_COLS 10
326 * Geometric dimensions
330 /* If there are three fractional bits, the smallest screen size that will scale
331 * properly is 28x22. If you have a smaller screen increase the fractional
332 * precision. If you have a precision of 4 the smallest screen size would be
333 * 14x11. Note though that this will decrease the maximum resolution due to
334 * the line intersection tests. These defines are used for all of the fixed
335 * point calculations/conversions.
337 #define FIXED3(x) ((x)<<3)
338 #define FIXED3_MUL(x, y) ((long long)((x)*(y))>>3)
339 #define FIXED3_DIV(x, y) (((x)<<3)/(y))
340 #define INT3(x) ((x)>>3)
342 #define GAMESCREEN_WIDTH FIXED3(LCD_WIDTH)
343 #define GAMESCREEN_HEIGHT FIXED3(LCD_HEIGHT)
345 #define PAD_WIDTH FIXED3(BMPWIDTH_brickmania_pads)
346 #define PAD_HEIGHT FIXED3(BMPHEIGHT_brickmania_pads/3)
347 #define SHORT_PAD_WIDTH FIXED3(BMPWIDTH_brickmania_short_pads)
348 #define LONG_PAD_WIDTH FIXED3(BMPWIDTH_brickmania_long_pads)
349 #define BRICK_HEIGHT FIXED3(BMPHEIGHT_brickmania_bricks/7)
350 #define BRICK_WIDTH FIXED3(BMPWIDTH_brickmania_bricks)
351 #define LEFTMARGIN ((GAMESCREEN_WIDTH-NUM_BRICKS_COLS*BRICK_WIDTH)/2)
352 #define POWERUP_WIDTH FIXED3(BMPWIDTH_brickmania_powerups)
353 #define BALL FIXED3(BMPHEIGHT_brickmania_ball)
354 #define HALFBALL (BALL / 2)
355 #define PAD_POS_Y (GAMESCREEN_HEIGHT - PAD_HEIGHT - 1)
356 #define ON_PAD_POS_Y (PAD_POS_Y - HALFBALL)
358 #define GAMEOVER_WIDTH FIXED3(BMPWIDTH_brickmania_gameover)
359 #define GAMEOVER_HEIGHT FIXED3(BMPHEIGHT_brickmania_gameover)
361 #define TOPMARGIN MAX(BRICK_HEIGHT, FIXED3(8))
363 #define STRINGPOS_FINISH (GAMESCREEN_HEIGHT - (GAMESCREEN_HEIGHT / 6))
364 #define STRINGPOS_NAVI (STRINGPOS_FINISH - 10)
365 #define STRINGPOS_FLIP (STRINGPOS_FINISH - 10)
374 /* Brickmania was originally designed for the H300, other targets should scale
375 * the speed up/down as needed based on the screen height.
377 #define SPEED_SCALE_H(y) FIXED3_DIV(GAMESCREEN_HEIGHT, FIXED3(176)/(y) )
378 #define SPEED_SCALE_W(x) FIXED3_DIV(GAMESCREEN_WIDTH, FIXED3(220)/(x) )
380 /* These are all used as ball speeds depending on where the ball hit the
383 * Note that all of these speeds (including pad, power, and fire)
384 * could be made variable and could be raised to be much higher to add
385 * additional difficulty to the game. The line intersection tests allow this
386 * to be drastically increased without the collision detection failing
389 #define SPEED_1Q_X SPEED_SCALE_W( 6)
390 #define SPEED_1Q_Y SPEED_SCALE_H(-2)
392 #define SPEED_2Q_X SPEED_SCALE_W( 4)
393 #define SPEED_2Q_Y SPEED_SCALE_H(-3)
395 #define SPEED_3Q_X SPEED_SCALE_W( 3)
396 #define SPEED_3Q_Y SPEED_SCALE_H(-4)
398 #define SPEED_4Q_X SPEED_SCALE_W( 2)
399 #define SPEED_4Q_Y SPEED_SCALE_H(-4)
401 /* This is used to determine the speed of the paddle */
402 #define SPEED_PAD SPEED_SCALE_W( 8)
404 /* This defines the speed that the powerups drop */
405 #define SPEED_POWER SPEED_SCALE_H( 2)
407 /* This defines the speed that the shot moves */
408 #define SPEED_FIRE SPEED_SCALE_H( 4)
409 #define FIRE_LENGTH SPEED_SCALE_H( 7)
418 /* The time ms for one iteration through the game loop - decrease this to speed
419 * up the game - note that current_tick is (currently) only accurate to 10ms.
421 #define CYCLETIME 30 /* ms */
423 #define FLIP_SIDES_DELAY 10 /* seconds */
432 #define SCORE_BALL_HIT_BRICK 2
433 #define SCORE_BALL_DEMOLISHED_BRICK 8
434 #define SCORE_FIRE_HIT_BRICK 13
435 #define SCORE_LEVEL_COMPLETED 100
436 #define SCORE_POWER_LIFE_GAIN 50
437 #define SCORE_POWER_PADDLE_STICKY 34
438 #define SCORE_POWER_PADDLE_SHOOTER 47
439 #define SCORE_POWER_PADDLE_NORMAL 23
440 #define SCORE_POWER_FLIP 23
441 #define SCORE_POWER_EXTRA_BALL 23
442 #define SCORE_POWER_LONG_PADDLE 23
453 #define MAX_POWERS 10
462 #define CONFIG_FILE_NAME "brickmania.cfg"
463 #define SAVE_FILE PLUGIN_GAMES_DATA_DIR "/brickmania.save"
464 #define SCORE_FILE PLUGIN_GAMES_DATA_DIR "/brickmania.score"
474 /* change to however many levels there are, i.e. how many arrays there are total */
475 #define NUM_LEVELS 40
477 /* change the first number in [ ] to however many levels there are */
478 static unsigned char levels
[NUM_LEVELS
][NUM_BRICKS_ROWS
][NUM_BRICKS_COLS
] =
479 /* You can set up new levels with the level editor
480 ( http://plugbox.rockbox-lounge.com/brickmania.htm ).
481 With 0x1, it refers to the first brick in the bitmap, 0x2 would refer to the
482 second, ect., 0x0 leaves a empty space. If you add a 2 before the 2nd number,
483 it will take two hits to break, and 3 hits if you add a 3. That is 0x24, will
484 result with the fourth brick being displayed and having take 2 hits to break.
485 You could do the same with the 3, just replace the 2 with a 3 for it to take
486 three hits to break it apart. */
489 {0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1},
490 {0x2,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x2},
491 {0x0,0x2,0x1,0x0,0x0,0x0,0x0,0x1,0x2,0x0},
492 {0x0,0x0,0x2,0x1,0x0,0x0,0x1,0x2,0x0,0x0},
493 {0x0,0x0,0x0,0x2,0x1,0x1,0x2,0x0,0x0,0x0},
494 {0x7,0x0,0x0,0x7,0x2,0x2,0x7,0x0,0x0,0x7},
495 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
496 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
499 {0x0,0x0,0x7,0x7,0x1,0x1,0x7,0x7,0x0,0x0},
500 {0x0,0x1,0x0,0x0,0x1,0x1,0x0,0x0,0x1,0x0},
501 {0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1},
502 {0x1,0x1,0x1,0x1,0x0,0x0,0x1,0x1,0x1,0x1},
503 {0x1,0x1,0x2,0x1,0x0,0x0,0x1,0x2,0x1,0x1},
504 {0x1,0x2,0x0,0x2,0x2,0x2,0x2,0x0,0x2,0x1},
505 {0x0,0x1,0x2,0x0,0x0,0x0,0x0,0x2,0x1,0x0},
506 {0x0,0x0,0x1,0x2,0x2,0x2,0x2,0x1,0x0,0x0}
509 {0x3,0x3,0x3,0x3,0x0,0x0,0x2,0x2,0x2,0x2},
510 {0x3,0x23,0x23,0x3,0x0,0x0,0x2,0x22,0x22,0x2},
511 {0x3,0x3,0x3,0x3,0x0,0x0,0x2,0x2,0x2,0x2},
512 {0x0,0x0,0x0,0x0,0x37,0x37,0x0,0x0,0x0,0x0},
513 {0x0,0x0,0x0,0x0,0x37,0x37,0x0,0x0,0x0,0x0},
514 {0x5,0x5,0x5,0x5,0x0,0x0,0x6,0x6,0x6,0x6},
515 {0x5,0x25,0x25,0x5,0x0,0x0,0x6,0x26,0x26,0x6},
516 {0x5,0x5,0x5,0x5,0x0,0x0,0x6,0x6,0x6,0x6}
519 {0x0,0x0,0x0,0x27,0x27,0x27,0x27,0x0,0x0,0x0},
520 {0x0,0x0,0x0,0x27,0x7,0x7,0x27,0x0,0x0,0x0},
521 {0x22,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x22},
522 {0x22,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x22},
523 {0x26,0x6,0x0,0x2,0x2,0x2,0x2,0x0,0x6,0x26},
524 {0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0},
525 {0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0},
526 {0x1,0x1,0x1,0x1,0x0,0x0,0x1,0x1,0x1,0x1}
529 {0x1,0x0,0x2,0x2,0x0,0x3,0x3,0x0,0x4,0x4},
530 {0x0,0x2,0x2,0x0,0x3,0x3,0x0,0x4,0x4,0x0},
531 {0x2,0x2,0x0,0x3,0x3,0x0,0x4,0x4,0x0,0x5},
532 {0x2,0x0,0x3,0x3,0x0,0x4,0x4,0x0,0x5,0x5},
533 {0x0,0x33,0x3,0x0,0x4,0x4,0x0,0x5,0x5,0x0},
534 {0x3,0x33,0x0,0x4,0x4,0x0,0x5,0x5,0x0,0x36},
535 {0x3,0x0,0x4,0x4,0x0,0x5,0x5,0x0,0x6,0x36},
536 {0x0,0x24,0x24,0x0,0x25,0x25,0x0,0x26,0x26,0x0}
539 {0x0,0x1,0x3,0x7,0x7,0x7,0x7,0x3,0x1,0x0},
540 {0x3,0x1,0x3,0x7,0x0,0x0,0x7,0x3,0x1,0x3},
541 {0x3,0x1,0x3,0x7,0x7,0x7,0x7,0x3,0x1,0x3},
542 {0x0,0x0,0x0,0x2,0x2,0x2,0x2,0x0,0x0,0x0},
543 {0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5},
544 {0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x5},
545 {0x0,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x0},
546 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
549 {0x0,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x0},
550 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
551 {0x6,0x0,0x0,0x2,0x2,0x2,0x2,0x0,0x0,0x6},
552 {0x6,0x0,0x0,0x2,0x2,0x2,0x2,0x0,0x0,0x6},
553 {0x6,0x6,0x6,0x0,0x0,0x0,0x0,0x6,0x6,0x6},
554 {0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0},
555 {0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0},
556 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
559 {0x0,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x0},
560 {0x0,0x0,0x0,0x4,0x0,0x0,0x4,0x0,0x0,0x0},
561 {0x6,0x6,0x0,0x2,0x32,0x32,0x2,0x0,0x6,0x6},
562 {0x0,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x0,0x0},
563 {0x0,0x6,0x6,0x0,0x0,0x0,0x0,0x6,0x6,0x0},
564 {0x0,0x0,0x0,0x5,0x25,0x25,0x5,0x0,0x0,0x0},
565 {0x0,0x5,0x5,0x25,0x5,0x5,0x25,0x5,0x5,0x0},
566 {0x5,0x5,0x25,0x5,0x5,0x5,0x5,0x25,0x5,0x5}
569 {0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2},
570 {0x2,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x2},
571 {0x2,0x0,0x3,0x0,0x1,0x1,0x0,0x3,0x0,0x2},
572 {0x2,0x0,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x2},
573 {0x2,0x0,0x1,0x0,0x3,0x3,0x0,0x1,0x0,0x2},
574 {0x2,0x0,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x2},
575 {0x2,0x2,0x0,0x0,0x1,0x1,0x0,0x0,0x2,0x2},
576 {0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2}
579 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
580 {0x0,0x5,0x0,0x5,0x0,0x5,0x0,0x5,0x0,0x5},
581 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
582 {0x0,0x0,0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0},
583 {0x0,0x0,0x0,0x4,0x1,0x1,0x4,0x0,0x0,0x0},
584 {0x0,0x0,0x3,0x4,0x1,0x1,0x4,0x3,0x0,0x0},
585 {0x0,0x2,0x3,0x4,0x1,0x1,0x4,0x3,0x2,0x0},
586 {0x1,0x2,0x3,0x4,0x1,0x1,0x4,0x3,0x2,0x1}
589 {0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3},
590 {0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x2},
591 {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2},
592 {0x2,0x0,0x0,0x0,0x7,0x7,0x0,0x0,0x0,0x2},
593 {0x2,0x0,0x0,0x7,0x7,0x7,0x7,0x0,0x0,0x2},
594 {0x0,0x0,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x0},
595 {0x0,0x2,0x0,0x1,0x0,0x0,0x1,0x0,0x2,0x0},
596 {0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5}
599 {0x2,0x1,0x3,0x1,0x0,0x0,0x1,0x3,0x1,0x2},
600 {0x1,0x1,0x1,0x1,0x0,0x0,0x1,0x1,0x1,0x1},
601 {0x1,0x1,0x1,0x0,0x1,0x1,0x0,0x1,0x1,0x1},
602 {0x0,0x1,0x0,0x1,0x6,0x6,0x1,0x0,0x1,0x0},
603 {0x0,0x0,0x1,0x1,0x6,0x6,0x1,0x1,0x0,0x0},
604 {0x1,0x1,0x1,0x7,0x0,0x0,0x7,0x1,0x1,0x1},
605 {0x1,0x1,0x7,0x1,0x0,0x0,0x1,0x7,0x1,0x1},
606 {0x2,0x2,0x0,0x2,0x2,0x2,0x2,0x0,0x2,0x2}
609 {0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2},
610 {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2},
611 {0x2,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x0,0x2},
612 {0x2,0x0,0x2,0x3,0x3,0x3,0x3,0x3,0x0,0x2},
613 {0x2,0x0,0x2,0x4,0x4,0x4,0x4,0x4,0x0,0x2},
614 {0x2,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2},
615 {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
616 {0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2}
619 {0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1},
620 {0x4,0x4,0x4,0x4,0x2,0x2,0x4,0x4,0x4,0x4},
621 {0x4,0x0,0x0,0x0,0x2,0x2,0x0,0x0,0x0,0x4},
622 {0x4,0x0,0x0,0x2,0x3,0x3,0x2,0x0,0x0,0x4},
623 {0x4,0x0,0x2,0x23,0x3,0x3,0x23,0x2,0x0,0x4},
624 {0x4,0x0,0x2,0x22,0x2,0x2,0x22,0x2,0x0,0x4},
625 {0x4,0x0,0x6,0x21,0x5,0x5,0x21,0x6,0x0,0x4},
626 {0x4,0x6,0x1,0x1,0x5,0x5,0x1,0x1,0x6,0x4}
629 {0x4,0x4,0x4,0x4,0x4,0x3,0x3,0x3,0x3,0x3},
630 {0x2,0x2,0x1,0x1,0x1,0x1,0x1,0x5,0x0,0x0},
631 {0x2,0x2,0x1,0x1,0x1,0x0,0x1,0x6,0x0,0x0},
632 {0x2,0x1,0x1,0x2,0x1,0x1,0x1,0x5,0x0,0x0},
633 {0x2,0x1,0x2,0x2,0x2,0x1,0x1,0x6,0x0,0x0},
634 {0x2,0x1,0x2,0x2,0x2,0x1,0x3,0x5,0x3,0x0},
635 {0x2,0x1,0x1,0x2,0x1,0x1,0x1,0x6,0x0,0x0},
636 {0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2}
638 {/* level 16 (Rockbox) by ts-x */
639 {0x2,0x2,0x3,0x3,0x3,0x4,0x4,0x5,0x0,0x5},
640 {0x2,0x0,0x3,0x0,0x3,0x4,0x0,0x5,0x5,0x0},
641 {0x2,0x0,0x3,0x3,0x3,0x4,0x4,0x5,0x0,0x5},
642 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
643 {0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
644 {0x7,0x7,0x7,0x1,0x1,0x1,0x2,0x0,0x2,0x0},
645 {0x7,0x0,0x7,0x1,0x0,0x1,0x0,0x2,0x0,0x0},
646 {0x7,0x7,0x7,0x1,0x1,0x1,0x2,0x0,0x2,0x0}
648 {/* level 17 (Alien) by ts-x */
649 {0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1},
650 {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2},
651 {0x1,0x0,0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x1},
652 {0x2,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x2},
653 {0x1,0x0,0x1,0x2,0x2,0x2,0x2,0x1,0x0,0x1},
654 {0x2,0x0,0x0,0x1,0x2,0x2,0x1,0x0,0x0,0x2},
655 {0x2,0x1,0x0,0x0,0x1,0x1,0x0,0x0,0x1,0x2},
656 {0x2,0x2,0x1,0x0,0x1,0x1,0x0,0x1,0x2,0x2}
658 {/* level 18 (Tetris) by ts-x */
659 {0x0,0x2,0x0,0x0,0x3,0x4,0x0,0x2,0x2,0x0},
660 {0x0,0x2,0x7,0x0,0x3,0x4,0x0,0x2,0x2,0x0},
661 {0x2,0x2,0x7,0x0,0x3,0x4,0x0,0x6,0x2,0x2},
662 {0x2,0x2,0x7,0x7,0x3,0x4,0x0,0x6,0x2,0x2},
663 {0x2,0x1,0x7,0x7,0x3,0x4,0x4,0x6,0x5,0x5},
664 {0x2,0x1,0x0,0x7,0x3,0x4,0x4,0x6,0x5,0x5},
665 {0x1,0x1,0x1,0x7,0x3,0x0,0x6,0x6,0x5,0x5},
666 {0x1,0x1,0x1,0x0,0x3,0x0,0x6,0x6,0x5,0x5}
668 { /* level 19 (Stalactites) by ts-x */
669 {0x5,0x2,0x6,0x3,0x4,0x7,0x5,0x3,0x1,0x2},
670 {0x5,0x2,0x6,0x3,0x4,0x7,0x5,0x3,0x1,0x2},
671 {0x5,0x0,0x6,0x3,0x4,0x7,0x5,0x0,0x1,0x2},
672 {0x5,0x2,0x6,0x3,0x4,0x0,0x5,0x3,0x1,0x2},
673 {0x5,0x0,0x6,0x0,0x4,0x7,0x5,0x0,0x1,0x0},
674 {0x5,0x0,0x0,0x3,0x4,0x0,0x0,0x0,0x1,0x2},
675 {0x0,0x0,0x6,0x0,0x0,0x0,0x5,0x0,0x0,0x0},
676 {0x5,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0}
678 { /* level 20 (Maze) by ts-x */
679 {0x1,0x1,0x21,0x1,0x1,0x1,0x1,0x1,0x1,0x21},
680 {0x1,0x0,0x0,0x3,0x0,0x0,0x3,0x1,0x31,0x1},
681 {0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x31,0x0,0x1},
682 {0x21,0x0,0x21,0x3,0x0,0x3,0x0,0x3,0x0,0x2},
683 {0x1,0x0,0x1,0x21,0x0,0x12,0x0,0x0,0x0,0x0},
684 {0x31,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x3,0x0},
685 {0x1,0x0,0x1,0x0,0x1,0x1,0x31,0x1,0x1,0x2},
686 {0x22,0x0,0x2,0x1,0x1,0x1,0x1,0x1,0x1,0x21}
688 { /* level 21 (Dentist) by ts-x */
689 {0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x0},
690 {0x2,0x2,0x0,0x6,0x0,0x6,0x0,0x6,0x2,0x2},
691 {0x2,0x6,0x0,0x6,0x0,0x6,0x0,0x6,0x0,0x2},
692 {0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x2},
693 {0x2,0x0,0x6,0x0,0x6,0x0,0x0,0x0,0x0,0x2},
694 {0x2,0x0,0x6,0x0,0x6,0x0,0x6,0x0,0x6,0x2},
695 {0x2,0x2,0x6,0x0,0x6,0x0,0x6,0x0,0x2,0x2},
696 {0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x0}
698 { /* level 22 (Spider) by ts-x */
699 {0x31,0x3,0x1,0x1,0x0,0x0,0x1,0x1,0x3,0x31},
700 {0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0},
701 {0x33,0x1,0x1,0x36,0x1,0x1,0x36,0x1,0x1,0x33},
702 {0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0},
703 {0x0,0x0,0x1,0x1,0x0,0x0,0x1,0x1,0x0,0x0},
704 {0x21,0x3,0x1,0x21,0x2,0x2,0x21,0x1,0x3,0x21},
705 {0x0,0x0,0x0,0x1,0x21,0x1,0x1,0x0,0x0,0x0},
706 {0x3,0x1,0x3,0x1,0x0,0x0,0x1,0x3,0x1,0x3}
708 { /* level 23 (Pool) by ts-x */
709 {0x0,0x7,0x7,0x7,0x0,0x7,0x7,0x7,0x7,0x0},
710 {0x0,0x0,0x5,0x0,0x2,0x0,0x0,0x0,0x2,0x0},
711 {0x7,0x3,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x7},
712 {0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x5,0x0,0x7},
713 {0x7,0x0,0x4,0x0,0x0,0x3,0x0,0x0,0x0,0x7},
714 {0x7,0x0,0x0,0x6,0x0,0x0,0x0,0x0,0x4,0x7},
715 {0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
716 {0x0,0x7,0x7,0x7,0x7,0x0,0x7,0x7,0x7,0x0}
718 { /* level 24 (Vorbis Fish) by ts-x */
719 {0x0,0x0,0x4,0x4,0x5,0x5,0x5,0x0,0x0,0x5},
720 {0x0,0x4,0x6,0x4,0x4,0x5,0x5,0x5,0x0,0x5},
721 {0x5,0x6,0x0,0x6,0x4,0x4,0x4,0x5,0x5,0x5},
722 {0x5,0x6,0x0,0x6,0x4,0x4,0x4,0x4,0x5,0x5},
723 {0x0,0x5,0x6,0x4,0x4,0x5,0x5,0x4,0x5,0x0},
724 {0x5,0x5,0x4,0x4,0x5,0x5,0x5,0x4,0x5,0x5},
725 {0x5,0x4,0x4,0x4,0x5,0x5,0x4,0x4,0x5,0x5},
726 {0x0,0x0,0x4,0x4,0x4,0x4,0x4,0x5,0x0,0x5}
728 {/* level 25 (Rainbow) by ts-x */
729 {0x0,0x4,0x1,0x0,0x0,0x0,0x0,0x1,0x4,0x0},
730 {0x24,0x1,0x3,0x1,0x0,0x0,0x21,0x3,0x1,0x24},
731 {0x1,0x23,0x5,0x3,0x1,0x21,0x3,0x5,0x3,0x21},
732 {0x3,0x5,0x6,0x5,0x3,0x3,0x5,0x6,0x5,0x3},
733 {0x5,0x6,0x7,0x6,0x5,0x5,0x6,0x7,0x6,0x5},
734 {0x6,0x7,0x2,0x27,0x6,0x6,0x27,0x2,0x7,0x6},
735 {0x7,0x2,0x0,0x2,0x27,0x27,0x2,0x0,0x2,0x7},
736 {0x32,0x0,0x0,0x0,0x2,0x2,0x0,0x0,0x0,0x32}
738 { /* level 26 (Bowtie) by ts-x */
739 {0x5,0x1,0x5,0x1,0x0,0x0,0x1,0x5,0x1,0x5},
740 {0x1,0x0,0x0,0x1,0x5,0x5,0x1,0x0,0x0,0x1},
741 {0x5,0x0,0x6,0x0,0x1,0x1,0x0,0x6,0x0,0x5},
742 {0x1,0x0,0x6,0x6,0x0,0x0,0x6,0x6,0x0,0x1},
743 {0x1,0x0,0x6,0x6,0x0,0x0,0x6,0x6,0x0,0x1},
744 {0x5,0x0,0x6,0x0,0x1,0x1,0x0,0x6,0x0,0x5},
745 {0x1,0x0,0x0,0x1,0x5,0x5,0x1,0x0,0x0,0x1},
746 {0x5,0x1,0x5,0x1,0x0,0x0,0x1,0x5,0x1,0x5}
748 { /* level 27 (Frog) by ts-x */
749 {0x0,0x5,0x25,0x0,0x0,0x0,0x0,0x25,0x5,0x0},
750 {0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5},
751 {0x25,0x0,0x0,0x5,0x6,0x6,0x5,0x0,0x0,0x25},
752 {0x5,0x0,0x3,0x0,0x6,0x6,0x0,0x3,0x0,0x5},
753 {0x5,0x0,0x31,0x0,0x6,0x6,0x0,0x31,0x0,0x5},
754 {0x5,0x0,0x0,0x5,0x6,0x6,0x5,0x0,0x0,0x5},
755 {0x5,0x5,0x5,0x35,0x0,0x0,0x35,0x5,0x5,0x5},
756 {0x0,0x25,0x5,0x0,0x4,0x4,0x0,0x5,0x25,0x0}
758 { /* level 28 (DigDug) by ts-x */
759 {0x35,0x5,0x5,0x25,0x0,0x25,0x25,0x5,0x5,0x35},
760 {0x6,0x0,0x0,0x6,0x0,0x6,0x6,0x0,0x0,0x6},
761 {0x7,0x0,0x37,0x37,0x0,0x37,0x37,0x7,0x0,0x7},
762 {0x7,0x0,0x7,0x0,0x0,0x0,0x7,0x7,0x7,0x7},
763 {0x4,0x4,0x4,0x24,0x0,0x24,0x4,0x0,0x0,0x4},
764 {0x4,0x4,0x0,0x0,0x0,0x4,0x4,0x0,0x4,0x4},
765 {0x24,0x24,0x4,0x4,0x4,0x4,0x0,0x0,0x24,0x4},
766 {0x1,0x1,0x1,0x1,0x1,0x1,0x21,0x21,0x1,0x1}
768 { /* level 29 UK Flag by Seth Opgenorth */
769 {0x32,0x0,0x3,0x3,0x2,0x2,0x3,0x3,0x0,0x32},
770 {0x0,0x2,0x0,0x3,0x32,0x22,0x33,0x0,0x32,0x0},
771 {0x33,0x0,0x22,0x0,0x2,0x2,0x0,0x2,0x0,0x33},
772 {0x22,0x32,0x2,0x2,0x2,0x2,0x2,0x2,0x22,0x2},
773 {0x3,0x0,0x0,0x32,0x22,0x2,0x2,0x0,0x0,0x3},
774 {0x23,0x0,0x32,0x0,0x32,0x2,0x0,0x2,0x0,0x3},
775 {0x0,0x2,0x0,0x3,0x2,0x2,0x3,0x0,0x22,0x0},
776 {0x32,0x0,0x3,0x23,0x2,0x2,0x23,0x33,0x0,0x32}
778 { /* level 30 Win-Logo by Seth Opgenorth */
779 {0x0,0x0,0x0,0x22,0x0,0x0,0x0,0x0,0x0,0x0},
780 {0x0,0x0,0x32,0x2,0x2,0x25,0x0,0x5,0x0,0x0},
781 {0x0,0x0,0x2,0x22,0x2,0x5,0x5,0x35,0x0,0x0},
782 {0x0,0x0,0x2,0x1,0x2,0x5,0x5,0x25,0x0,0x0},
783 {0x0,0x0,0x21,0x1,0x1,0x36,0x7,0x26,0x0,0x0},
784 {0x0,0x0,0x1,0x1,0x1,0x6,0x6,0x6,0x0,0x0},
785 {0x0,0x0,0x21,0x0,0x21,0x6,0x6,0x26,0x0,0x0},
786 {0x0,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x0,0x0}
788 { /* level 31 Color wave/V by Seth Opgenorth */
789 {0x25,0x34,0x2,0x31,0x33,0x23,0x1,0x2,0x34,0x5},
790 {0x3,0x5,0x24,0x2,0x1,0x1,0x2,0x4,0x5,0x3},
791 {0x1,0x3,0x5,0x4,0x2,0x2,0x4,0x5,0x3,0x1},
792 {0x2,0x1,0x33,0x35,0x4,0x4,0x5,0x33,0x1,0x22},
793 {0x31,0x22,0x1,0x3,0x5,0x25,0x3,0x1,0x2,0x31},
794 {0x3,0x1,0x2,0x1,0x3,0x3,0x1,0x2,0x21,0x3},
795 {0x5,0x23,0x1,0x32,0x1,0x1,0x2,0x1,0x3,0x5},
796 {0x4,0x35,0x3,0x1,0x2,0x22,0x31,0x3,0x5,0x4}
798 { /* level 32 Sweedish Flag by Seth Opgenorth */
799 {0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
800 {0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
801 {0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
802 {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36},
803 {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36},
804 {0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
805 {0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
806 {0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3}
808 { /* level 33 Color Pyramid by Seth Opgenorth */
809 {0x0,0x0,0x0,0x0,0x2,0x2,0x0,0x0,0x0,0x0},
810 {0x0,0x0,0x0,0x4,0x24,0x4,0x24,0x0,0x0,0x0},
811 {0x0,0x0,0x23,0x3,0x3,0x3,0x23,0x3,0x0,0x0},
812 {0x0,0x0,0x25,0x5,0x25,0x35,0x5,0x35,0x0,0x0},
813 {0x0,0x36,0x6,0x6,0x6,0x6,0x26,0x6,0x6,0x0},
814 {0x0,0x7,0x7,0x7,0x7,0x25,0x27,0x7,0x27,0x0},
815 {0x2,0x2,0x22,0x2,0x2,0x2,0x22,0x2,0x2,0x2},
816 {0x21,0x1,0x1,0x31,0x1,0x21,0x1,0x1,0x31,0x1}
818 { /* level 34 Rhombus by Seth Opgenorth */
819 {0x0,0x0,0x0,0x0,0x3,0x33,0x0,0x0,0x0,0x0},
820 {0x0,0x0,0x0,0x3,0x32,0x22,0x23,0x0,0x0,0x0},
821 {0x0,0x0,0x3,0x2,0x24,0x4,0x2,0x23,0x0,0x0},
822 {0x26,0x3,0x2,0x4,0x5,0x5,0x4,0x22,0x3,0x6},
823 {0x36,0x3,0x2,0x34,0x5,0x5,0x4,0x2,0x3,0x36},
824 {0x0,0x0,0x3,0x2,0x4,0x34,0x2,0x23,0x0,0x0},
825 {0x0,0x0,0x0,0x23,0x2,0x2,0x3,0x0,0x0,0x0},
826 {0x0,0x0,0x0,0x0,0x3,0x33,0x0,0x0,0x0,0x0}
828 { /* level 35 PacMan Ghost by Seth Opgenorth */
829 {0x0,0x0,0x0,0x0,0x2,0x32,0x2,0x0,0x0,0x0},
830 {0x0,0x0,0x0,0x2,0x2,0x2,0x2,0x2,0x0,0x0},
831 {0x0,0x0,0x2,0x24,0x4,0x2,0x4,0x4,0x32,0x0},
832 {0x0,0x0,0x2,0x24,0x0,0x22,0x24,0x0,0x22,0x0},
833 {0x0,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x0},
834 {0x0,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x0},
835 {0x0,0x0,0x2,0x32,0x2,0x2,0x22,0x2,0x32,0x0},
836 {0x0,0x0,0x0,0x22,0x0,0x32,0x0,0x22,0x0,0x0}
838 { /* level 36 Star by Seth Opgenorth */
839 {0x3,0x4,0x3,0x4,0x6,0x24,0x3,0x24,0x3,0x0},
840 {0x24,0x0,0x0,0x6,0x6,0x6,0x0,0x0,0x4,0x0},
841 {0x3,0x26,0x6,0x2,0x6,0x2,0x6,0x26,0x23,0x0},
842 {0x4,0x0,0x6,0x6,0x36,0x6,0x6,0x0,0x4,0x0},
843 {0x3,0x0,0x0,0x26,0x6,0x26,0x0,0x0,0x33,0x0},
844 {0x34,0x0,0x6,0x6,0x0,0x6,0x6,0x0,0x4,0x0},
845 {0x3,0x26,0x6,0x0,0x0,0x0,0x6,0x6,0x3,0x0},
846 {0x4,0x3,0x4,0x23,0x24,0x3,0x4,0x33,0x4,0x0}
848 { /* level 37 It's 8-Bit by Seth Opgenorth */
849 {0x26,0x26,0x6,0x6,0x5,0x6,0x26,0x6,0x26,0x6},
850 {0x2,0x2,0x22,0x3,0x3,0x0,0x0,0x0,0x4,0x0},
851 {0x2,0x0,0x2,0x33,0x3,0x3,0x5,0x0,0x24,0x0},
852 {0x32,0x2,0x2,0x33,0x0,0x23,0x0,0x4,0x4,0x4},
853 {0x2,0x22,0x2,0x3,0x3,0x0,0x5,0x4,0x4,0x24},
854 {0x2,0x0,0x2,0x23,0x0,0x3,0x25,0x0,0x4,0x0},
855 {0x22,0x2,0x2,0x3,0x23,0x0,0x5,0x0,0x4,0x0},
856 {0x6,0x26,0x6,0x36,0x6,0x36,0x6,0x6,0x6,0x6}
858 { /* level 38 Linux by Seth Opgenorth */
859 {0x27,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
860 {0x7,0x0,0x0,0x0,0x33,0x0,0x23,0x0,0x0,0x0},
861 {0x7,0x32,0x0,0x0,0x3,0x0,0x23,0x6,0x0,0x6},
862 {0x37,0x0,0x0,0x0,0x23,0x0,0x3,0x6,0x0,0x26},
863 {0x7,0x22,0x24,0x0,0x3,0x33,0x3,0x0,0x26,0x0},
864 {0x37,0x22,0x24,0x24,0x4,0x0,0x0,0x0,0x26,0x0},
865 {0x7,0x2,0x4,0x0,0x4,0x0,0x0,0x6,0x0,0x26},
866 {0x7,0x27,0x4,0x0,0x34,0x0,0x0,0x6,0x0,0x26}
868 { /* level 39 Colorful Squares by Seth Opgenorth*/
869 {0x0,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x0},
870 {0x0,0x4,0x5,0x5,0x5,0x5,0x5,0x5,0x4,0x0},
871 {0x0,0x4,0x5,0x3,0x3,0x3,0x3,0x5,0x4,0x0},
872 {0x0,0x4,0x5,0x3,0x4,0x4,0x3,0x5,0x4,0x0},
873 {0x0,0x4,0x5,0x3,0x4,0x4,0x3,0x5,0x4,0x0},
874 {0x0,0x4,0x5,0x3,0x3,0x3,0x3,0x5,0x4,0x0},
875 {0x0,0x4,0x5,0x5,0x5,0x5,0x5,0x5,0x4,0x0},
876 {0x0,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x0}
879 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
880 {0x32,0x32,0x36,0x0,0x0,0x36,0x34,0x34,0x0,0x0},
881 {0x32,0x0,0x36,0x36,0x0,0x36,0x34,0x0,0x34,0x0},
882 {0x32,0x32,0x36,0x36,0x0,0x36,0x34,0x0,0x34,0x0},
883 {0x32,0x32,0x36,0x0,0x36,0x36,0x34,0x0,0x34,0x0},
884 {0x32,0x0,0x36,0x0,0x36,0x36,0x34,0x0,0x34,0x0},
885 {0x32,0x32,0x36,0x0,0x0,0x36,0x34,0x34,0x0,0x0},
886 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
899 POWER_TYPE_LIFE_GAIN
= 0,
900 POWER_TYPE_LIFE_LOSS
,
901 POWER_TYPE_PADDLE_STICKY
,
902 POWER_TYPE_PADDLE_SHOOTER
,
903 POWER_TYPE_PADDLE_NORMAL
,
904 POWER_TYPE_PADDLE_FLIP
,
905 POWER_TYPE_EXTRA_BALL
,
906 POWER_TYPE_PADDLE_LONG
,
907 POWER_TYPE_PADDLE_SHORT
,
911 #define POWERUP_HEIGHT FIXED3(BMPHEIGHT_brickmania_powerups/NUMBER_OF_POWERUPS)
912 /* Increasing this value makes the game with less powerups */
913 #define POWER_RAND (NUMBER_OF_POWERUPS + 15)
915 enum difficulty_options
930 PADDLE_TYPE_NORMAL
= 0,
946 bool used
; /* Is the brick still in play? */
948 int hits
; /* How many hits can this brick take? */
954 /* pos_x and y store the current center position of the ball */
957 /* tempx and tempy store an absolute position the ball should be in. If
958 * they are equal to 0, they are not used when positioning the ball.
962 /* speedx and speedy store the current speed of the ball */
965 bool glue
; /* Is the ball stuck to the paddle? */
970 int top
; /* This stores the fire y position, it is a fixed point num */
971 int x_pos
; /* This stores the fire x position, it is a whole number */
976 int top
; /* This stores the powerup y position, it is a fixed point num */
977 int x_pos
; /* This stores the (middle of) powerup x position, it is a whole number */
978 enum power_types type
; /* This stores the powerup type */
995 struct point top_left
;
996 struct point bottom_right
;
1005 static enum game_state game_state
;
1006 static int pad_pos_x
;
1008 static int score
,vscore
;
1009 static bool flip_sides
;
1011 static int brick_on_board
;
1012 static int used_balls
;
1013 static int used_fires
;
1014 static int used_powers
;
1015 static int difficulty
= NORMAL
;
1016 static int pad_width
;
1017 static int flip_sides_delay
;
1018 static bool resume
= false;
1019 static bool resume_file
= false;
1020 static struct brick brick
[NUM_BRICKS_ROWS
][NUM_BRICKS_COLS
];
1021 static struct ball ball
[MAX_BALLS
];
1022 static struct fire fire
[MAX_FIRES
];
1023 static struct power power
[MAX_POWERS
];
1024 static enum paddle_type paddle_type
;
1026 static struct configdata config
[] =
1028 {TYPE_INT
, 0, 1, { .int_p
= &difficulty
}, "difficulty", NULL
},
1031 static struct highscore highscores
[NUM_SCORES
];
1042 * This is based off an explanation and expanded math presented by Paul Bourke:
1043 * http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
1045 * It takes two lines as inputs and returns 1 if they intersect, 0 if they do
1046 * not. hitp returns the point where the two lines intersected.
1048 * This function expects fixed point inputs with a precision of 3. When a
1049 * collision occurs hitp is updated with a fixed point location (precision 3)
1050 * where the collision happened. The internal calculations are fixed
1051 * point with a 7 bit fractional precision.
1053 * If you choose 10 bits of precision a screen size of about 640x480 is the
1054 * largest this can go. 7 bits allows for an accurate intersection calculation
1055 * with a line length of about 64 and a rougher line lenght of 128 which is
1056 * larger than any target currently needs (the pad is the longest line and it
1057 * only needs an accuracy of 2^4 at most to figure out which section of the pad
1058 * the ball hit). A precision of 7 gives breathing room for larger screens.
1059 * Longer line sizes that need accurate intersection points will need more
1060 * precision, but will decrease the maximum screen resolution.
1064 static int check_lines(struct line
*line1
, struct line
*line2
,
1068 * This code is based on the solution of these two input equations:
1069 * Pa = P1 + ua (P2-P1)
1070 * Pb = P3 + ub (P4-P3)
1072 * Where line one is composed of points P1 and P2 and line two is composed
1073 * of points P3 and P4.
1075 * ua/b is the fractional value you can multiply the x and y legs of the
1076 * triangle formed by each line to find a point on the line.
1078 * The two equations can be expanded to their x/y components:
1079 * Pa.x = p1.x + ua(p2.x - p1.x)
1080 * Pa.y = p1.y + ua(p2.y - p1.y)
1082 * Pb.x = p3.x + ub(p4.x - p3.x)
1083 * Pb.y = p3.y + ub(p4.y - p3.y)
1085 * When Pa.x == Pb.x and Pa.y == Pb.y the lines intersect so you can come
1086 * up with two equations (one for x and one for y):
1088 * p1.x + ua(p2.x - p1.x) = p3.x + ub(p4.x - p3.x)
1089 * p1.y + ua(p2.y - p1.y) = p3.y + ub(p4.y - p3.y)
1091 * ua and ub can then be individually solved for. This results in the
1092 * equations used in the following code.
1095 /* Denominator for ua and ub are the same so store this calculation */
1096 int d
= FIXED3_MUL((line2
->p2
.y
- line2
->p1
.y
),(line1
->p2
.x
-line1
->p1
.x
))
1097 -FIXED3_MUL((line2
->p2
.x
- line2
->p1
.x
),(line1
->p2
.y
-line1
->p1
.y
));
1099 /* n_a and n_b are calculated as seperate values for readability */
1100 int n_a
= FIXED3_MUL((line2
->p2
.x
- line2
->p1
.x
),(line1
->p1
.y
-line2
->p1
.y
))
1101 -FIXED3_MUL((line2
->p2
.y
- line2
->p1
.y
),(line1
->p1
.x
-line2
->p1
.x
));
1103 int n_b
= FIXED3_MUL((line1
->p2
.x
- line1
->p1
.x
),(line1
->p1
.y
-line2
->p1
.y
))
1104 -FIXED3_MUL((line1
->p2
.y
- line1
->p1
.y
),(line1
->p1
.x
-line2
->p1
.x
));
1106 /* Make sure there is not a division by zero - this also indicates that
1107 * the lines are parallel.
1109 * If n_a and n_b were both equal to zero the lines would be on top of each
1110 * other (coincidental). This check is not done because it is not
1111 * necessary for this implementation (the parallel check accounts for this).
1116 /* Calculate the intermediate fractional point that the lines potentially
1119 int ua
= (n_a
<< LINE_PREC
)/d
;
1120 int ub
= (n_b
<< LINE_PREC
)/d
;
1122 /* The fractional point will be between 0 and 1 inclusive if the lines
1123 * intersect. If the fractional calculation is larger than 1 or smaller
1124 * than 0 the lines would need to be longer to intersect.
1126 if(ua
>=0 && ua
<= (1<<LINE_PREC
) && ub
>= 0 && ub
<= (1<<LINE_PREC
))
1128 hitp
->x
= line1
->p1
.x
+ ((ua
* (line1
->p2
.x
- line1
->p1
.x
))>>LINE_PREC
);
1129 hitp
->y
= line1
->p1
.y
+ ((ua
* (line1
->p2
.y
- line1
->p1
.y
))>>LINE_PREC
);
1136 static int check_rect(struct line
*line
, struct rect
*rect
,
1137 enum intersection intersection
, struct point
*hitp
)
1141 switch (intersection
)
1143 case INTERSECTION_TOP
:
1145 edge
.p1
.x
= rect
->top_left
.x
;
1146 edge
.p1
.y
= rect
->top_left
.y
;
1148 edge
.p2
.x
= rect
->bottom_right
.x
;
1149 edge
.p2
.y
= rect
->top_left
.y
;
1153 case INTERSECTION_BOTTOM
:
1155 edge
.p1
.x
= rect
->top_left
.x
;
1156 edge
.p1
.y
= rect
->bottom_right
.y
;
1158 edge
.p2
.x
= rect
->bottom_right
.x
;
1159 edge
.p2
.y
= rect
->bottom_right
.y
;
1163 case INTERSECTION_LEFT
:
1165 edge
.p1
.x
= rect
->top_left
.x
;
1166 edge
.p1
.y
= rect
->top_left
.y
;
1168 edge
.p2
.x
= rect
->top_left
.x
;
1169 edge
.p2
.y
= rect
->bottom_right
.y
;
1173 case INTERSECTION_RIGHT
:
1175 edge
.p1
.x
= rect
->bottom_right
.x
;
1176 edge
.p1
.y
= rect
->top_left
.y
;
1178 edge
.p2
.x
= rect
->bottom_right
.x
;
1179 edge
.p2
.y
= rect
->bottom_right
.y
;
1183 case INTERSECTION_ALL
: /* Test hit on all edges */
1185 return (check_rect(line
, rect
, INTERSECTION_TOP
, hitp
) ||
1186 check_rect(line
, rect
, INTERSECTION_BOTTOM
, hitp
) ||
1187 check_rect(line
, rect
, INTERSECTION_LEFT
, hitp
) ||
1188 check_rect(line
, rect
, INTERSECTION_RIGHT
, hitp
));
1192 return check_lines(line
, &edge
, hitp
);
1195 static void brickmania_init_game(bool new_game
)
1199 pad_pos_x
= GAMESCREEN_WIDTH
/2 - PAD_WIDTH
/2;
1201 for(i
=0;i
<MAX_BALLS
;i
++)
1207 ball
[i
].pos_y
= ON_PAD_POS_Y
;
1208 ball
[i
].pos_x
= GAMESCREEN_WIDTH
/2;
1209 ball
[i
].glue
= false;
1215 game_state
= ST_READY
;
1216 paddle_type
= PADDLE_TYPE_NORMAL
;
1217 pad_width
= PAD_WIDTH
;
1219 flip_sides_delay
= FLIP_SIDES_DELAY
;
1223 /* add one life per achieved level */
1224 if (difficulty
==EASY
&& life
<2) {
1225 score
+=SCORE_LEVEL_COMPLETED
;
1230 for(i
=0;i
<NUM_BRICKS_ROWS
;i
++) {
1231 for(j
=0;j
<NUM_BRICKS_COLS
;j
++) {
1233 brick
[i
][j
].hits
=levels
[level
][i
][j
]>=10?
1234 levels
[level
][i
][j
]/16-1:0;
1235 brick
[i
][j
].hiteffect
=0;
1236 brick
[i
][j
].used
=!(levels
[level
][i
][j
]==0);
1237 brick
[i
][j
].color
=(levels
[level
][i
][j
]>=10?
1238 levels
[level
][i
][j
]%16:
1239 levels
[level
][i
][j
])-1;
1240 if (levels
[level
][i
][j
]!=0)
1247 static void brickmania_loadgame(void)
1253 /* open game file */
1254 fd
= rb
->open(SAVE_FILE
, O_RDONLY
);
1257 /* read in saved game */
1258 if((rb
->read(fd
, &pad_pos_x
, sizeof(pad_pos_x
)) <= 0) ||
1259 (rb
->read(fd
, &life
, sizeof(life
)) <= 0) ||
1260 (rb
->read(fd
, &game_state
, sizeof(game_state
)) <= 0) ||
1261 (rb
->read(fd
, &paddle_type
, sizeof(paddle_type
)) <= 0) ||
1262 (rb
->read(fd
, &score
, sizeof(score
)) <= 0) ||
1263 (rb
->read(fd
, &flip_sides
, sizeof(flip_sides
)) <= 0) ||
1264 (rb
->read(fd
, &level
, sizeof(level
)) <= 0) ||
1265 (rb
->read(fd
, &brick_on_board
, sizeof(brick_on_board
)) <= 0) ||
1266 (rb
->read(fd
, &used_balls
, sizeof(used_balls
)) <= 0) ||
1267 (rb
->read(fd
, &used_fires
, sizeof(used_fires
)) <= 0) ||
1268 (rb
->read(fd
, &used_powers
, sizeof(used_powers
)) <= 0) ||
1269 (rb
->read(fd
, &pad_width
, sizeof(pad_width
)) <= 0) ||
1270 (rb
->read(fd
, &flip_sides_delay
, sizeof(flip_sides_delay
)) <= 0) ||
1271 (rb
->read(fd
, &brick
, sizeof(brick
)) <= 0) ||
1272 (rb
->read(fd
, &ball
, sizeof(ball
)) <= 0) ||
1273 (rb
->read(fd
, &fire
, sizeof(fire
)) <= 0) ||
1274 (rb
->read(fd
, &power
, sizeof(power
)) <= 0))
1276 rb
->splash(HZ
/2, "Failed to load game");
1289 static void brickmania_savegame(void)
1293 /* write out the game state to the save file */
1294 fd
= rb
->open(SAVE_FILE
, O_WRONLY
|O_CREAT
, 0666);
1297 if ((rb
->write(fd
, &pad_pos_x
, sizeof(pad_pos_x
)) <= 0) ||
1298 (rb
->write(fd
, &life
, sizeof(life
)) <= 0) ||
1299 (rb
->write(fd
, &game_state
, sizeof(game_state
)) <= 0) ||
1300 (rb
->write(fd
, &paddle_type
, sizeof(paddle_type
)) <= 0) ||
1301 (rb
->write(fd
, &score
, sizeof(score
)) <= 0) ||
1302 (rb
->write(fd
, &flip_sides
, sizeof(flip_sides
)) <= 0) ||
1303 (rb
->write(fd
, &level
, sizeof(level
)) <= 0) ||
1304 (rb
->write(fd
, &brick_on_board
, sizeof(brick_on_board
)) <= 0) ||
1305 (rb
->write(fd
, &used_balls
, sizeof(used_balls
)) <= 0) ||
1306 (rb
->write(fd
, &used_fires
, sizeof(used_fires
)) <= 0) ||
1307 (rb
->write(fd
, &used_powers
, sizeof(used_powers
)) <= 0) ||
1308 (rb
->write(fd
, &pad_width
, sizeof(pad_width
)) <= 0) ||
1309 (rb
->write(fd
, &flip_sides_delay
, sizeof(flip_sides_delay
)) <= 0) ||
1310 (rb
->write(fd
, &brick
, sizeof(brick
)) <= 0) ||
1311 (rb
->write(fd
, &ball
, sizeof(ball
)) <= 0) ||
1312 (rb
->write(fd
, &fire
, sizeof(fire
)) <= 0) ||
1313 (rb
->write(fd
, &power
, sizeof(power
)) <= 0))
1316 rb
->remove(SAVE_FILE
);
1317 rb
->splash(HZ
/2, "Failed to save game");
1324 /* brickmania_sleep timer counting the score */
1325 static void brickmania_sleep(int secs
)
1335 count
= *rb
->current_tick
+ HZ
*secs
;
1336 if ( (TIME_AFTER(*rb
->current_tick
, count
)) && (vscore
== score
) )
1345 rb
->snprintf(s
, sizeof(s
), "%d", vscore
);
1346 rb
->lcd_getstringsize(s
, &sw
, &w
);
1347 rb
->lcd_putsxy(LCD_WIDTH
/2-sw
/2, 0, s
);
1348 rb
->lcd_update_rect(0,0,LCD_WIDTH
,w
+2);
1354 static int brickmania_help(void)
1356 static char *help_text
[] = {
1357 "Brickmania", "", "Aim", "",
1358 "Destroy", "all", "the", "bricks", "by", "bouncing",
1359 "the", "ball", "of", "them", "using", "the", "paddle.", "", "",
1361 #if CONFIG_KEYPAD == COWON_D2_PAD
1366 "Moves", "the", "paddle", "",
1367 #if CONFIG_KEYPAD == ONDIO_PAD
1369 #elif (CONFIG_KEYPAD == RECORDER_PAD) || (CONFIG_KEYPAD == IAUDIO_M3_PAD)
1371 #elif CONFIG_KEYPAD == IRIVER_H300_PAD
1373 #elif CONFIG_KEYPAD == COWON_D2_PAD
1378 "Releases", "the", "ball/Fire!", "",
1379 #if CONFIG_KEYPAD == IAUDIO_M3_PAD
1381 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \
1382 (CONFIG_KEYPAD == CREATIVEZVM_PAD)
1384 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
1385 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
1386 (CONFIG_KEYPAD == IPOD_1G2G_PAD) || \
1387 (CONFIG_KEYPAD == SANSA_FUZE_PAD)
1389 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
1390 (CONFIG_KEYPAD == IRIVER_H300_PAD) || \
1391 (CONFIG_KEYPAD == ONDIO_PAD) || \
1392 (CONFIG_KEYPAD == RECORDER_PAD) || \
1393 (CONFIG_KEYPAD == ARCHOS_AV300_PAD)
1398 "Returns", "to", "menu", "", "",
1400 "N", "Normal:", "returns", "paddle", "to", "normal", "",
1401 "D", "DIE!:", "loses", "a", "life", "",
1402 "L", "Life:", "gains", "a", "life/power", "up", "",
1403 "F", "Fire:", "allows", "you", "to", "shoot", "bricks", "",
1404 "G", "Glue:", "ball", "sticks", "to", "paddle", "",
1405 "B", "Ball:", "generates", "another", "ball", "",
1406 "FL", "Flip:", "flips", "left / right", "movement", "",
1407 "<->", "or", "<E>:", "enlarges", "the", "paddle", "",
1408 ">-<", "or", ">S<:", "shrinks", "the", "paddle", "",
1410 static struct style_text formation
[]={
1411 { 0, TEXT_CENTER
|TEXT_UNDERLINE
},
1425 rb
->lcd_setfont(FONT_UI
);
1426 #ifdef HAVE_LCD_COLOR
1427 rb
->lcd_set_background(LCD_BLACK
);
1428 rb
->lcd_set_foreground(LCD_WHITE
);
1430 if (display_text(ARRAYLEN(help_text
), help_text
, formation
, NULL
, true))
1432 rb
->lcd_setfont(FONT_SYSFIXED
);
1437 static int brickmania_menu_cb(int action
, const struct menu_item_ex
*this_item
)
1439 int i
= ((intptr_t)this_item
);
1440 if(action
== ACTION_REQUEST_MENUITEM
1441 && !resume
&& (i
==0 || i
==6))
1442 return ACTION_EXIT_MENUITEM
;
1446 static int brickmania_menu(void)
1450 static struct opt_items options
[] = {
1455 #ifdef HAVE_TOUCHSCREEN
1456 /* Entering Menu, set the touchscreen to the global setting */
1457 rb
->touchscreen_set_mode(rb
->global_settings
->touch_mode
);
1460 MENUITEM_STRINGLIST(main_menu
, "Brickmania Menu", brickmania_menu_cb
,
1461 "Resume Game", "Start New Game",
1462 "Difficulty", "Help", "High Scores",
1464 "Quit without Saving", "Quit");
1466 rb
->button_clear_queue();
1468 switch (rb
->do_menu(&main_menu
, &selected
, NULL
, false)) {
1470 if(game_state
!=ST_READY
)
1471 game_state
= ST_PAUSE
;
1473 rb
->remove(SAVE_FILE
);
1480 brickmania_init_game(true);
1483 rb
->set_option("Difficulty", &difficulty
, INT
,
1487 if (brickmania_help())
1491 highscore_show(-1, highscores
, NUM_SCORES
, true);
1494 if (playback_control(NULL
))
1501 rb
->splash(HZ
*1, "Saving game ...");
1502 brickmania_savegame();
1505 case MENU_ATTACHED_USB
:
1511 #ifdef HAVE_TOUCHSCREEN
1512 rb
->touchscreen_set_mode(TOUCHSCREEN_POINT
);
1516 static void brick_hit(int i
, int j
)
1518 if(!brick
[i
][j
].used
)
1521 /* if this is a crackable brick hits starts as
1524 if (brick
[i
][j
].hits
> 0) {
1526 brick
[i
][j
].hiteffect
++;
1527 score
+=SCORE_BALL_HIT_BRICK
;
1530 brick
[i
][j
].used
=false;
1531 if (used_powers
<MAX_POWERS
)
1533 int ran
= rb
->rand()%POWER_RAND
;
1535 if (ran
<NUMBER_OF_POWERUPS
)
1537 power
[used_powers
].top
= TOPMARGIN
+ i
*BRICK_HEIGHT
;
1538 power
[used_powers
].x_pos
= LEFTMARGIN
+ j
*BRICK_WIDTH
+
1540 power
[used_powers
].type
= ran
;
1545 score
+=SCORE_BALL_DEMOLISHED_BRICK
;
1549 static int brickmania_game_loop(void)
1557 /* pad_rect used for powerup/ball checks */
1558 struct rect pad_rect
;
1559 /* This is used for various lines that are checked (ball and powerup) */
1560 struct line misc_line
;
1562 /* This stores the point that the two lines intersected in a test */
1563 struct point pt_hit
;
1565 if (brickmania_menu()) {
1569 resume_file
= false;
1571 #ifdef HAVE_LCD_COLOR
1572 rb
->lcd_set_background(LCD_BLACK
);
1573 rb
->lcd_set_foreground(LCD_WHITE
);
1574 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1575 rb
->lcd_clear_display();
1579 /* Convert CYCLETIME (in ms) to HZ */
1580 end
= *rb
->current_tick
+ (CYCLETIME
* HZ
) / 1000;
1583 rb
->lcd_clear_display();
1587 if (TIME_AFTER(*rb
->current_tick
, sec_count
))
1589 sec_count
=*rb
->current_tick
+HZ
;
1590 if (flip_sides_delay
> 1)
1595 rb
->snprintf(s
, sizeof(s
), "%d", flip_sides_delay
);
1596 rb
->lcd_getstringsize(s
, &sw
, NULL
);
1597 rb
->lcd_putsxy(LCD_WIDTH
/2-2, INT3(STRINGPOS_FLIP
), s
);
1601 #if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
1602 rb
->snprintf(s
, sizeof(s
), "L%d", level
+1);
1604 rb
->snprintf(s
, sizeof(s
), "Level %d", level
+1);
1607 rb
->lcd_getstringsize(s
, &sw
, NULL
);
1608 rb
->lcd_putsxy(LCD_WIDTH
-sw
, 0, s
);
1610 if (vscore
<score
) vscore
++;
1611 rb
->snprintf(s
, sizeof(s
), "%d", vscore
);
1612 rb
->lcd_getstringsize(s
, &sw
, NULL
);
1613 rb
->lcd_putsxy(LCD_WIDTH
/2-sw
/2, 0, s
);
1615 /* write life num */
1616 rb
->snprintf(s
, sizeof(s
), "Life: %d", life
);
1618 /* hijack i - it's reset to 0 in 17 lines */
1620 rb
->lcd_getstringsize(s
, &sw
, NULL
);
1621 if (sw
>= (LCD_WIDTH
/2-i
/2))
1622 rb
->snprintf(s
, sizeof(s
), "L: %d", life
);
1623 rb
->lcd_putsxy(0, 0, s
);
1626 if (game_state
== ST_PAUSE
)
1628 rb
->snprintf(s
, sizeof(s
), CONTINUE_TEXT
);
1629 rb
->lcd_getstringsize(s
, &sw
, NULL
);
1630 rb
->lcd_putsxy(LCD_WIDTH
/2-sw
/2, INT3(STRINGPOS_NAVI
), s
);
1632 sec_count
=*rb
->current_tick
+HZ
;
1636 for(i
=0;i
<used_balls
;i
++)
1637 rb
->lcd_bitmap(brickmania_ball
,
1638 INT3(ball
[i
].pos_x
- HALFBALL
),
1639 INT3(ball
[i
].pos_y
- HALFBALL
),
1640 INT3(BALL
), INT3(BALL
));
1642 if (brick_on_board
==0)
1645 /* Setup the pad line-later used in intersection test */
1646 pad_rect
.top_left
.x
= pad_pos_x
;
1647 pad_rect
.top_left
.y
= PAD_POS_Y
;
1649 pad_rect
.bottom_right
.x
= pad_pos_x
+ pad_width
;
1650 pad_rect
.bottom_right
.y
= PAD_POS_Y
+ PAD_HEIGHT
;
1652 if (game_state
!=ST_PAUSE
)
1654 /* move the fires */
1655 for(k
=0;k
<used_fires
;k
++)
1657 fire
[k
].top
-= SPEED_FIRE
;
1658 if (fire
[k
].top
< 0)
1661 fire
[k
].top
= fire
[used_fires
].top
;
1662 fire
[k
].x_pos
= fire
[used_fires
].x_pos
;
1665 else if (fire
[k
].x_pos
>= LEFTMARGIN
&&
1666 fire
[k
].x_pos
< LEFTMARGIN
+ NUM_BRICKS_COLS
* BRICK_WIDTH
)
1668 j
= (fire
[k
].x_pos
- LEFTMARGIN
) / BRICK_WIDTH
;
1669 for (i
=NUM_BRICKS_ROWS
-1;i
>=0;i
--)
1671 if (TOPMARGIN
+ i
*BRICK_HEIGHT
<=fire
[k
].top
)
1673 if (brick
[i
][j
].used
)
1675 score
+= SCORE_FIRE_HIT_BRICK
;
1678 fire
[k
].top
= fire
[used_fires
].top
;
1679 fire
[k
].x_pos
= fire
[used_fires
].x_pos
;
1687 /* move and handle the powerups */
1688 for (k
=0;k
<used_powers
;k
++)
1690 int remove_power
= 0;
1692 power
[k
].top
+= SPEED_POWER
;
1694 if (power
[k
].top
> PAD_POS_Y
)
1696 /* power hit bottom */
1701 /* Use misc_line to check if the center of the powerup
1704 misc_line
.p1
.x
= power
[k
].x_pos
;
1705 misc_line
.p1
.y
= power
[k
].top
;
1707 misc_line
.p2
= misc_line
.p1
;
1708 misc_line
.p2
.y
+= SPEED_POWER
;
1710 /* Check if the powerup will hit the paddle */
1711 if (check_rect(&misc_line
, &pad_rect
, INTERSECTION_ALL
,
1715 /* power hit paddle */
1717 switch(power
[k
].type
)
1719 case POWER_TYPE_LIFE_GAIN
:
1721 score
+= SCORE_POWER_LIFE_GAIN
;
1723 case POWER_TYPE_LIFE_LOSS
:
1727 brickmania_init_game(false);
1728 brickmania_sleep(2);
1731 case POWER_TYPE_PADDLE_STICKY
:
1732 score
+= SCORE_POWER_PADDLE_STICKY
;
1733 paddle_type
= PADDLE_TYPE_STICKY
;
1735 case POWER_TYPE_PADDLE_SHOOTER
:
1736 score
+= SCORE_POWER_PADDLE_SHOOTER
;
1737 paddle_type
= PADDLE_TYPE_SHOOTER
;
1738 for(i
=0;i
<used_balls
;i
++)
1741 case POWER_TYPE_PADDLE_NORMAL
:
1742 score
+= SCORE_POWER_PADDLE_NORMAL
;
1743 paddle_type
= PADDLE_TYPE_NORMAL
;
1744 for(i
=0;i
<used_balls
;i
++)
1747 pad_pos_x
+= (pad_width
-PAD_WIDTH
)/2;
1748 pad_width
= PAD_WIDTH
;
1750 case POWER_TYPE_PADDLE_FLIP
:
1751 score
+= SCORE_POWER_FLIP
;
1752 sec_count
= *rb
->current_tick
+HZ
;
1753 flip_sides_delay
= FLIP_SIDES_DELAY
;
1756 case POWER_TYPE_EXTRA_BALL
:
1757 score
+= SCORE_POWER_EXTRA_BALL
;
1758 if(used_balls
<MAX_BALLS
)
1761 if(rb
->rand()%2 == 0)
1762 ball
[used_balls
].speedx
=-SPEED_4Q_X
;
1764 ball
[used_balls
].speedx
= SPEED_4Q_X
;
1765 ball
[used_balls
].speedy
= SPEED_4Q_Y
;
1766 /* Ball is not glued */
1767 ball
[used_balls
].glue
= false;
1771 case POWER_TYPE_PADDLE_LONG
:
1772 score
+=SCORE_POWER_LONG_PADDLE
;
1773 if (pad_width
==PAD_WIDTH
)
1775 pad_width
= LONG_PAD_WIDTH
;
1776 pad_pos_x
-= (LONG_PAD_WIDTH
-
1779 else if (pad_width
==SHORT_PAD_WIDTH
)
1781 pad_width
= PAD_WIDTH
;
1782 pad_pos_x
-=(PAD_WIDTH
-
1787 else if(pad_pos_x
+ pad_width
>
1789 pad_pos_x
= GAMESCREEN_WIDTH
-pad_width
;
1791 case POWER_TYPE_PADDLE_SHORT
:
1792 if (pad_width
==PAD_WIDTH
)
1794 pad_width
=SHORT_PAD_WIDTH
;
1795 pad_pos_x
+=(PAD_WIDTH
-
1798 else if (pad_width
==LONG_PAD_WIDTH
)
1800 pad_width
=PAD_WIDTH
;
1801 pad_pos_x
+=(LONG_PAD_WIDTH
-PAD_WIDTH
)/2;
1812 if (k
!= used_powers
)
1814 power
[k
].top
= power
[used_powers
].top
;
1815 power
[k
].x_pos
= power
[used_powers
].x_pos
;
1816 power
[k
].type
= power
[used_powers
].type
;
1824 /* draw the fires */
1825 for(k
=0;k
<used_fires
;k
++)
1827 rb
->lcd_vline(INT3(fire
[k
].x_pos
), INT3(fire
[k
].top
),
1828 INT3(fire
[k
].top
+ FIRE_LENGTH
));
1831 /* draw the powerups */
1832 for(k
=0;k
<used_powers
;k
++)
1834 rb
->lcd_bitmap_part(brickmania_powerups
,0,
1835 INT3(POWERUP_HEIGHT
)*power
[k
].type
,
1836 STRIDE(SCREEN_MAIN
, BMPWIDTH_brickmania_powerups
,
1837 BMPHEIGHT_brickmania_powerups
),
1838 INT3(power
[k
].x_pos
- (POWERUP_WIDTH
>> 1)),
1839 INT3(power
[k
].top
), INT3(POWERUP_WIDTH
),
1840 INT3(POWERUP_HEIGHT
));
1843 /* handle all of the bricks */
1844 for (i
=0; i
<NUM_BRICKS_ROWS
; i
++)
1846 for (j
=0; j
<NUM_BRICKS_COLS
;j
++)
1850 /* The brick is a brick, but it may or may not be in use */
1851 if(brick
[i
][j
].used
)
1853 struct rect brick_rect
;
1855 brickx
= LEFTMARGIN
+ j
*BRICK_WIDTH
;
1856 bricky
= TOPMARGIN
+ i
*BRICK_HEIGHT
;
1858 brick_rect
.top_left
.x
= brickx
;
1859 brick_rect
.top_left
.y
= bricky
;
1861 brick_rect
.bottom_right
.x
= brickx
+ BRICK_WIDTH
;
1862 brick_rect
.bottom_right
.y
= bricky
+ BRICK_HEIGHT
;
1864 /* Draw the brick */
1865 rb
->lcd_bitmap_part(brickmania_bricks
,0,
1866 INT3(BRICK_HEIGHT
)*brick
[i
][j
].color
,
1867 STRIDE( SCREEN_MAIN
,
1868 BMPWIDTH_brickmania_bricks
,
1869 BMPHEIGHT_brickmania_bricks
),
1872 INT3(BRICK_WIDTH
), INT3(BRICK_HEIGHT
) );
1874 #ifdef HAVE_LCD_COLOR /* No transparent effect for greyscale lcds for now */
1875 if (brick
[i
][j
].hiteffect
> 0)
1876 rb
->lcd_bitmap_transparent_part(brickmania_break
,0,
1877 INT3(BRICK_HEIGHT
)*brick
[i
][j
].hiteffect
,
1878 STRIDE( SCREEN_MAIN
,
1879 BMPWIDTH_brickmania_break
,
1880 BMPHEIGHT_brickmania_break
),
1883 INT3(BRICK_WIDTH
), INT3(BRICK_HEIGHT
) );
1886 /* Check if any balls collided with the brick */
1887 for(k
=0; k
<used_balls
; k
++)
1891 /* Setup the ball path to describe the current ball
1892 * position and the line it makes to its next
1895 misc_line
.p1
.x
= ball
[k
].pos_x
;
1896 misc_line
.p1
.y
= ball
[k
].pos_y
;
1898 misc_line
.p2
.x
= ball
[k
].pos_x
+ ball
[k
].speedx
;
1899 misc_line
.p2
.y
= ball
[k
].pos_y
+ ball
[k
].speedy
;
1901 /* Check to see if the ball and the bottom hit. If
1902 * the ball is moving down we don't want to
1903 * include the bottom line intersection.
1905 * The order that the sides are checked matters.
1907 * Note that tempx/tempy store the next position
1908 * that the ball should be drawn.
1910 if (ball
[k
].speedy
<= 0 && check_rect(&misc_line
,
1911 &brick_rect
, INTERSECTION_BOTTOM
, &pt_hit
))
1913 ball
[k
].speedy
= -ball
[k
].speedy
;
1916 /* Check the top, if the ball is moving up dont
1917 * count it as a hit.
1919 else if (ball
[k
].speedy
> 0 && check_rect(&misc_line
,
1920 &brick_rect
, INTERSECTION_TOP
, &pt_hit
))
1922 ball
[k
].speedy
= -ball
[k
].speedy
;
1925 /* Check the left side of the brick */
1926 else if (check_rect(&misc_line
, &brick_rect
,
1927 INTERSECTION_LEFT
, &pt_hit
))
1929 ball
[k
].speedx
= -ball
[k
].speedx
;
1932 /* Check the right side of the brick */
1933 else if (check_rect(&misc_line
, &brick_rect
,
1934 INTERSECTION_RIGHT
, &pt_hit
))
1936 ball
[k
].speedx
= -ball
[k
].speedx
;
1942 ball
[k
].tempy
= pt_hit
.y
;
1943 ball
[k
].tempx
= pt_hit
.x
;
1953 /* draw the paddle according to the PAD_WIDTH */
1954 if( pad_width
== PAD_WIDTH
) /* Normal width */
1956 rb
->lcd_bitmap_part(
1958 0, paddle_type
*INT3(PAD_HEIGHT
),
1959 STRIDE( SCREEN_MAIN
, BMPWIDTH_brickmania_pads
,
1960 BMPHEIGHT_brickmania_pads
),
1961 INT3(pad_pos_x
), INT3(PAD_POS_Y
),
1962 INT3(pad_width
), INT3(PAD_HEIGHT
) );
1964 else if( pad_width
== LONG_PAD_WIDTH
) /* Long Pad */
1966 rb
->lcd_bitmap_part(
1967 brickmania_long_pads
,
1968 0,paddle_type
*INT3(PAD_HEIGHT
),
1969 STRIDE( SCREEN_MAIN
, BMPWIDTH_brickmania_long_pads
,
1970 BMPHEIGHT_brickmania_long_pads
),
1971 INT3(pad_pos_x
), INT3(PAD_POS_Y
),
1972 INT3(pad_width
), INT3(PAD_HEIGHT
) );
1974 else /* Short pad */
1976 rb
->lcd_bitmap_part(
1977 brickmania_short_pads
,
1978 0,paddle_type
*INT3(PAD_HEIGHT
),
1979 STRIDE( SCREEN_MAIN
, BMPWIDTH_brickmania_short_pads
,
1980 BMPHEIGHT_brickmania_short_pads
),
1981 INT3(pad_pos_x
), INT3(PAD_POS_Y
),
1982 INT3(pad_width
), INT3(PAD_HEIGHT
) );
1985 /* If the game is not paused continue */
1986 if (game_state
!=ST_PAUSE
)
1988 /* Loop through all of the balls in play */
1989 for(k
=0;k
<used_balls
;k
++)
1991 struct line screen_edge
;
1993 /* Describe the ball movement for the edge collision detection */
1994 misc_line
.p1
.x
= ball
[k
].pos_x
;
1995 misc_line
.p1
.y
= ball
[k
].pos_y
;
1997 misc_line
.p2
.x
= ball
[k
].pos_x
+ ball
[k
].speedx
;
1998 misc_line
.p2
.y
= ball
[k
].pos_y
+ ball
[k
].speedy
;
2000 /* Did the Ball hit the top of the screen? */
2001 screen_edge
.p1
.x
= 0;
2002 screen_edge
.p1
.y
= 0;
2004 screen_edge
.p2
.x
= GAMESCREEN_WIDTH
;
2005 screen_edge
.p2
.y
= 0;
2006 /* the test for pos_y prevents the ball from bouncing back
2007 * from _over_ the top to infinity on some rare cases */
2008 if (ball
[k
].pos_y
> 0 &&
2009 check_lines(&misc_line
, &screen_edge
, &pt_hit
))
2011 ball
[k
].tempy
= pt_hit
.y
+ 1;
2012 ball
[k
].tempx
= pt_hit
.x
;
2013 /* Reverse the direction */
2014 ball
[k
].speedy
= -ball
[k
].speedy
;
2017 /* Player missed the ball and hit bottom of screen */
2018 if (ball
[k
].pos_y
>= GAMESCREEN_HEIGHT
)
2020 /* Player had balls to spare, so handle the removal */
2023 /* decrease number of balls in play */
2025 /* Replace removed ball with the last ball */
2026 ball
[k
].pos_x
= ball
[used_balls
].pos_x
;
2027 ball
[k
].pos_y
= ball
[used_balls
].pos_y
;
2028 ball
[k
].speedy
= ball
[used_balls
].speedy
;
2029 ball
[k
].tempy
= ball
[used_balls
].tempy
;
2030 ball
[k
].speedx
= ball
[used_balls
].speedx
;
2031 ball
[k
].tempx
= ball
[used_balls
].tempx
;
2032 ball
[k
].glue
= ball
[used_balls
].glue
;
2034 /* Reset the last ball that was removed */
2035 ball
[used_balls
].speedx
=0;
2036 ball
[used_balls
].speedy
=0;
2037 ball
[used_balls
].tempy
=0;
2038 ball
[used_balls
].tempx
=0;
2039 ball
[used_balls
].pos_y
=ON_PAD_POS_Y
;
2040 ball
[used_balls
].pos_x
=pad_pos_x
+(pad_width
/2)-HALFBALL
;
2047 /* Player lost a life */
2051 /* No lives left reset game */
2052 brickmania_init_game(false);
2053 brickmania_sleep(2);
2054 rb
->button_clear_queue();
2059 if (game_state
!= ST_READY
&& !ball
[k
].glue
)
2061 /* Check if the ball hit the left side */
2062 screen_edge
.p1
.x
= 0;
2063 screen_edge
.p1
.y
= 0;
2065 screen_edge
.p2
.x
= 0;
2066 screen_edge
.p2
.y
= GAMESCREEN_HEIGHT
;
2067 if (check_lines(&misc_line
, &screen_edge
, &pt_hit
))
2069 /* Reverse direction */
2070 ball
[k
].speedx
= abs(ball
[k
].speedx
);
2072 /* Re-position ball in gameboard */
2073 ball
[k
].tempy
= pt_hit
.y
;
2077 /* Check if the ball hit the right side */
2078 screen_edge
.p1
.x
= GAMESCREEN_WIDTH
;
2079 screen_edge
.p1
.y
= 0;
2081 screen_edge
.p2
.x
= GAMESCREEN_WIDTH
;
2082 screen_edge
.p2
.y
= GAMESCREEN_HEIGHT
;
2083 if (check_lines(&misc_line
, &screen_edge
, &pt_hit
))
2085 /* Reverse direction */
2086 ball
[k
].speedx
= -abs(ball
[k
].speedx
);
2088 /* Re-position ball in gameboard */
2089 ball
[k
].tempy
= pt_hit
.y
;
2090 ball
[k
].tempx
= GAMESCREEN_WIDTH
- FIXED3(1);
2093 /* Did the ball hit the paddle? Depending on where the ball
2094 * Hit set the x/y speed appropriately.
2096 if(check_rect(&misc_line
, &pad_rect
, INTERSECTION_TOP
,
2099 /* Re-position ball based on collision */
2100 ball
[k
].tempy
= ON_PAD_POS_Y
;
2101 ball
[k
].tempx
= pt_hit
.x
;
2103 /* Calculate the ball position relative to the paddle width */
2104 int ball_repos
= pt_hit
.x
- pad_pos_x
;
2105 /* If the ball hits the right half of paddle, x speed
2106 * should be positive, if it hits the left half it
2107 * should be negative.
2109 int x_direction
= -1;
2111 /* Comparisons are done with respect to 1/2 pad_width */
2112 if(ball_repos
> pad_width
/2)
2114 /* flip the relative position */
2115 ball_repos
-= ((ball_repos
- pad_width
/2) << 1);
2116 /* Ball hit the right half so X speed calculations
2117 * should be positive.
2122 /* Figure out where the ball hit relative to 1/2 pad
2123 * and in divisions of 4.
2125 ball_repos
= ball_repos
/ (pad_width
/2/4);
2129 /* Ball hit the outer edge of the paddle */
2131 ball
[k
].speedy
= SPEED_1Q_Y
;
2132 ball
[k
].speedx
= SPEED_1Q_X
* x_direction
;
2134 /* Ball hit the next fourth of the paddle */
2136 ball
[k
].speedy
= SPEED_2Q_Y
;
2137 ball
[k
].speedx
= SPEED_2Q_X
* x_direction
;
2139 /* Ball hit the third fourth of the paddle */
2141 ball
[k
].speedy
= SPEED_3Q_Y
;
2142 ball
[k
].speedx
= SPEED_3Q_X
* x_direction
;
2144 /* Ball hit the fourth fourth of the paddle or dead
2149 ball
[k
].speedy
= SPEED_4Q_Y
;
2150 /* Since this is the middle we don't want to
2151 * force the ball in a different direction.
2152 * Just keep it going in the same direction
2153 * with a specific speed.
2155 if(ball
[k
].speedx
> 0)
2157 ball
[k
].speedx
= SPEED_4Q_X
;
2161 ball
[k
].speedx
= -SPEED_4Q_X
;
2166 ball
[k
].speedy
= SPEED_4Q_Y
;
2170 if(paddle_type
== PADDLE_TYPE_STICKY
)
2172 ball
[k
].speedy
= -ball
[k
].speedy
;
2175 /* X location should not be forced since that is moved with the paddle. The Y
2176 * position should be forced to keep the ball at the paddle.
2179 ball
[k
].tempy
= ON_PAD_POS_Y
;
2184 /* Update the ball position */
2188 ball
[k
].pos_x
= ball
[k
].tempx
;
2190 ball
[k
].pos_x
+= ball
[k
].speedx
;
2193 ball
[k
].pos_y
= ball
[k
].tempy
;
2195 ball
[k
].pos_y
+= ball
[k
].speedy
;
2205 if (brick_on_board
< 0)
2207 if (level
+1<NUM_LEVELS
)
2210 if (difficulty
==NORMAL
)
2211 score
+=SCORE_LEVEL_COMPLETED
;
2212 brickmania_init_game(true);
2213 brickmania_sleep(2);
2214 rb
->button_clear_queue();
2218 rb
->lcd_getstringsize("Congratulations!", &sw
, &sh
);
2219 rb
->lcd_putsxy(LCD_WIDTH
/2-sw
/2, INT3(STRINGPOS_FINISH
) - 2 * sh
,
2220 "Congratulations!");
2221 #if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
2222 rb
->lcd_getstringsize("No more levels", &sw
, NULL
);
2223 rb
->lcd_putsxy(LCD_WIDTH
/2-sw
/2, INT3(STRINGPOS_FINISH
),
2226 rb
->lcd_getstringsize("You have finished the game!",
2228 rb
->lcd_putsxy(LCD_WIDTH
/2-sw
/2, INT3(STRINGPOS_FINISH
),
2229 "You have finished the game!");
2233 brickmania_sleep(2);
2238 int button
=rb
->button_get(false);
2239 int move_button
= rb
->button_status();
2241 #if defined(HAS_BUTTON_HOLD) && !defined(HAVE_REMOTE_LCD_AS_MAIN)
2242 /* FIXME: Should probably check remote hold here */
2243 if (rb
->button_hold())
2247 #ifdef HAVE_TOUCHSCREEN
2248 if( move_button
& BUTTON_TOUCHSCREEN
)
2252 rb
->button_status_wdata(&data
);
2253 touch_x
= FIXED3(data
>> 16);
2257 pad_pos_x
= GAMESCREEN_WIDTH
- (touch_x
+ pad_width
/2);
2261 pad_pos_x
= (touch_x
- pad_width
/2);
2266 else if(pad_pos_x
+ pad_width
> GAMESCREEN_WIDTH
)
2267 pad_pos_x
= GAMESCREEN_WIDTH
-pad_width
;
2268 for(k
=0; k
<used_balls
; k
++)
2269 if (game_state
==ST_READY
|| ball
[k
].glue
)
2270 ball
[k
].pos_x
= pad_pos_x
+ pad_width
/2;
2275 int button_right
, button_left
;
2277 button_right
= move_button
& (RIGHT
| ALTRIGHT
);
2278 button_left
= move_button
& (LEFT
| ALTLEFT
);
2280 button_right
=((move_button
& RIGHT
)|| SCROLL_FWD(button
));
2281 button_left
=((move_button
& LEFT
) ||SCROLL_BACK(button
));
2283 if ((game_state
==ST_PAUSE
) && (button_right
|| button_left
))
2286 if (button_left
|| button_right
)
2290 if ((button_right
&& !flip_sides
) ||
2291 (button_left
&& flip_sides
))
2293 if (pad_pos_x
+SPEED_PAD
+pad_width
> GAMESCREEN_WIDTH
)
2294 dx
= GAMESCREEN_WIDTH
- pad_pos_x
- pad_width
;
2298 else if ((button_left
&& !flip_sides
) ||
2299 (button_right
&& flip_sides
))
2301 if (pad_pos_x
-SPEED_PAD
< 0)
2308 for(k
=0;k
<used_balls
;k
++)
2310 if (game_state
==ST_READY
|| ball
[k
].glue
)
2314 if (ball
[k
].pos_x
< HALFBALL
)
2315 ball
[k
].pos_x
= HALFBALL
;
2316 else if (ball
[k
].pos_x
> GAMESCREEN_WIDTH
- HALFBALL
)
2317 ball
[k
].pos_x
= GAMESCREEN_WIDTH
- HALFBALL
;
2325 #if defined(HAVE_TOUCHSCREEN)
2326 case (BUTTON_REL
| BUTTON_TOUCHSCREEN
):
2333 if (game_state
==ST_READY
)
2335 /* Initialize used balls starting speed */
2336 for(k
=0 ; k
< used_balls
; k
++)
2338 ball
[k
].speedy
= SPEED_4Q_Y
;
2339 if(pad_pos_x
+ (pad_width
/2) >= GAMESCREEN_WIDTH
/2)
2341 ball
[k
].speedx
= SPEED_4Q_X
;
2345 ball
[k
].speedx
= -SPEED_4Q_X
;
2348 game_state
=ST_START
;
2350 else if (game_state
==ST_PAUSE
)
2352 game_state
=ST_START
;
2354 else if (paddle_type
== PADDLE_TYPE_STICKY
)
2356 for(k
=0;k
<used_balls
;k
++)
2361 ball
[k
].speedy
= -ball
[k
].speedy
;
2365 else if (paddle_type
== PADDLE_TYPE_SHOOTER
)
2367 if (used_fires
< MAX_FIRES
)
2369 fire
[used_fires
].top
= PAD_POS_Y
- FIRE_LENGTH
;
2370 fire
[used_fires
].x_pos
= pad_pos_x
+ 1; /* Add 1 for edge */
2373 if (used_fires
< MAX_FIRES
)
2375 fire
[used_fires
].top
= PAD_POS_Y
- FIRE_LENGTH
;
2376 fire
[used_fires
].x_pos
= pad_pos_x
+ pad_width
- 1; /* Sub1 edge*/
2390 if(rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
2397 #ifdef HAVE_LCD_COLOR
2398 rb
->lcd_bitmap_transparent(brickmania_gameover
,
2399 (LCD_WIDTH
- INT3(GAMEOVER_WIDTH
))/2,
2400 INT3(GAMESCREEN_HEIGHT
- GAMEOVER_HEIGHT
)/2,
2401 INT3(GAMEOVER_WIDTH
),INT3(GAMEOVER_HEIGHT
));
2402 #else /* greyscale and mono */
2403 rb
->lcd_bitmap(brickmania_gameover
,(LCD_WIDTH
-
2404 INT3(GAMEOVER_WIDTH
))/2,
2405 INT3(GAMESCREEN_HEIGHT
- GAMEOVER_HEIGHT
)/2,
2406 INT3(GAMEOVER_WIDTH
),INT3(GAMEOVER_HEIGHT
) );
2409 brickmania_sleep(2);
2413 /* Game always needs to yield for other threads */
2416 /* Sleep for a bit if there is time to spare */
2417 if (TIME_BEFORE(*rb
->current_tick
, end
))
2418 rb
->sleep(end
-*rb
->current_tick
);
2423 /* this is the plugin entry point */
2424 enum plugin_status
plugin_start(const void* parameter
)
2427 int last_difficulty
;
2429 highscore_load(SCORE_FILE
, highscores
, NUM_SCORES
);
2430 configfile_load(CONFIG_FILE_NAME
,config
,1,0);
2431 last_difficulty
= difficulty
;
2433 #ifdef HAVE_TOUCHSCREEN
2434 rb
->touchscreen_set_mode(TOUCHSCREEN_POINT
);
2437 rb
->lcd_setfont(FONT_SYSFIXED
);
2439 rb
->lcd_set_backdrop(NULL
);
2441 /* Turn off backlight timeout */
2442 backlight_ignore_timeout();
2444 /* now go ahead and have fun! */
2445 rb
->srand( *rb
->current_tick
);
2446 brickmania_loadgame();
2447 resume_file
= resume
;
2448 while(!brickmania_game_loop())
2452 int position
= highscore_update(score
, level
+1, "",
2453 highscores
, NUM_SCORES
);
2457 rb
->splash(HZ
*2, "New High Score");
2458 highscore_show(position
, highscores
, NUM_SCORES
, true);
2462 brickmania_sleep(3);
2467 highscore_save(SCORE_FILE
, highscores
, NUM_SCORES
);
2468 if(last_difficulty
!= difficulty
)
2469 configfile_save(CONFIG_FILE_NAME
,config
,1,0);
2470 /* Restore user's original backlight setting */
2471 rb
->lcd_setfont(FONT_UI
);
2472 /* Turn on backlight timeout (revert to settings) */
2473 backlight_use_settings();