0b5ad60c26
The port to for this two targets has been entirely developped by Ilia Sergachev (alias Il or xzcc). His source can be found at https://bitbucket.org/isergachev/rockbox . The few necesary modifications for the DX90 port was done by headwhacker form head-fi.org. Unfortunately i could not try out the final state of the DX90 port. The port is hosted on android (without java) as standalone app. The official Firmware is required to run this port. Ilia did modify the source files for the "android" target in the rockbox source to make the DX port work. The work I did was to separate the code for DX50 (&DX90) from the android target. On this Target Ilia used source from tinyalsa from AOSP. I did not touch that part of the code because I do not understand it. What else I changed from Ilias sources besides the separation from the target "android": * removed a dirty hack to keep backlight off * changed value battery meter to voltage battery meter * made all plugins compile (named target as "standalone") and added keymaps * i added the graphics for the manual but did not do anything else for the manual yet * minor optimizations known bugs: * timers are slowed donw when playback is active (tinyalsa related?) * some minor bugs Things to do: * The main prolem will be how to install the app correctly. A guy called DOC2008 added a CWM (by androtab.info) to the official firmware and Ilia made a CWM installation script and a dualboot selector (rbutils/ibassoboot, build with ndk-build). We will have to find a way to install rockbox in a proper way without breaking any copyrights. Maybe ADB is an option but it is not enable with OF by default. Patching the OF is probably the way to go. * All the wiki and manual to build: needed: android ndk installed, android sdk installed with additional build-tools 19.1.0 installed ./tools/configure select iBasso DX50 or iBasso DX90 make -j apk the content of rockbox.zip/.rockbox needs to be copied to /system/rockbox/app_rockbox/rockbox/ (rockbox app not needed) the content of libs/armeabi to /system/rockbox/lib/ (rockbox app needed) The boot selector is needed as /system/bin/MangoPlayer and the iBasso app as /system/bin/MangoPlayer_original. There is also the "vold" file. The one from OF does not work with DX50 rockbox (DX90 works!?), the one from Ilia is necessary. Until we have found a proper way to install it, it can only be installed following the instructions of Ilia on his bitbucket page, using the CWM-OF and his installation script package. Change-Id: Ic4faaf84824c162aabcc08e492cee6e0068719d0 Reviewed-on: http://gerrit.rockbox.org/941 Tested: Chiwen Chang <rock1104.tw@yahoo.com.tw> Reviewed-by: Michael Giacomelli <giac2000@hotmail.com>
2528 lines
89 KiB
C
2528 lines
89 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2005, 2006 Ben Basha (Paprica)
|
|
* Copyright (C) 2009 Karl Kurbjun
|
|
* check_lines is based off an explanation and expanded math presented by Paul
|
|
* Bourke: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "plugin.h"
|
|
#include "lib/configfile.h"
|
|
#include "lib/display_text.h"
|
|
#include "lib/helper.h"
|
|
#include "lib/highscore.h"
|
|
#include "lib/playback_control.h"
|
|
|
|
#include "pluginbitmaps/brickmania_pads.h"
|
|
#include "pluginbitmaps/brickmania_short_pads.h"
|
|
#include "pluginbitmaps/brickmania_long_pads.h"
|
|
#include "pluginbitmaps/brickmania_bricks.h"
|
|
#include "pluginbitmaps/brickmania_powerups.h"
|
|
#include "pluginbitmaps/brickmania_ball.h"
|
|
#include "pluginbitmaps/brickmania_gameover.h"
|
|
|
|
#ifdef HAVE_LCD_COLOR /* currently no transparency for non-colour */
|
|
#include "pluginbitmaps/brickmania_break.h"
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
*
|
|
* Keymaps
|
|
*
|
|
*/
|
|
|
|
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
|
|
(CONFIG_KEYPAD == IRIVER_H300_PAD)
|
|
#define CONTINUE_TEXT "Press NAVI To Continue"
|
|
#define QUIT BUTTON_OFF
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
#define RC_QUIT BUTTON_RC_STOP
|
|
|
|
#elif CONFIG_KEYPAD == ONDIO_PAD
|
|
#define CONTINUE_TEXT "MENU To Continue"
|
|
#define QUIT BUTTON_OFF
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_MENU
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == RECORDER_PAD
|
|
#define QUIT BUTTON_OFF
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_PLAY
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
|
|
#define QUIT BUTTON_OFF
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
|
|
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
|
|
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
|
|
#define QUIT BUTTON_MENU
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_SCROLL_BACK
|
|
#define DOWN BUTTON_SCROLL_FWD
|
|
#define SCROLL_FWD(x) ((x) & BUTTON_SCROLL_FWD)
|
|
#define SCROLL_BACK(x) ((x) & BUTTON_SCROLL_BACK)
|
|
|
|
#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_PLAY
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif (CONFIG_KEYPAD == SANSA_E200_PAD)
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
#define SCROLL_FWD(x) ((x) & BUTTON_SCROLL_FWD)
|
|
#define SCROLL_BACK(x) ((x) & BUTTON_SCROLL_BACK)
|
|
|
|
|
|
#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
|
|
#define QUIT (BUTTON_HOME|BUTTON_REPEAT)
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#define SCROLL_FWD(x) ((x) & BUTTON_SCROLL_FWD)
|
|
#define SCROLL_BACK(x) ((x) & BUTTON_SCROLL_BACK)
|
|
|
|
|
|
#elif CONFIG_KEYPAD == SANSA_C200_PAD || \
|
|
CONFIG_KEYPAD == SANSA_CLIP_PAD || \
|
|
CONFIG_KEYPAD == SANSA_M200_PAD || \
|
|
CONFIG_KEYPAD == SANSA_CONNECT_PAD
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define ALTLEFT BUTTON_VOL_DOWN
|
|
#define ALTRIGHT BUTTON_VOL_UP
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == IRIVER_H10_PAD
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_PLAY
|
|
#define UP BUTTON_SCROLL_UP
|
|
#define DOWN BUTTON_SCROLL_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == GIGABEAT_S_PAD \
|
|
|| CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
|
|
#define QUIT BUTTON_BACK
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif (CONFIG_KEYPAD == MROBE100_PAD)
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
|
|
#define CONTINUE_TEXT "PLAY To Continue"
|
|
#define QUIT BUTTON_RC_REC
|
|
#define LEFT BUTTON_RC_REW
|
|
#define RIGHT BUTTON_RC_FF
|
|
#define SELECT BUTTON_RC_PLAY
|
|
#define UP BUTTON_RC_VOL_UP
|
|
#define DOWN BUTTON_RC_VOL_DOWN
|
|
#define RC_QUIT BUTTON_REC
|
|
|
|
#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
|
|
#define QUIT BUTTON_BACK
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_BACK
|
|
#define RIGHT BUTTON_MENU
|
|
#define SELECT BUTTON_PLAY
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_PLAY
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_PREV
|
|
#define RIGHT BUTTON_NEXT
|
|
#define SELECT BUTTON_PLAY
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == COWON_D2_PAD
|
|
#define CONTINUE_TEXT "MENU To Continue"
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_MINUS
|
|
#define RIGHT BUTTON_PLUS
|
|
#define SELECT BUTTON_MENU
|
|
|
|
#elif CONFIG_KEYPAD == ONDAVX747_PAD
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_VOL_DOWN
|
|
#define RIGHT BUTTON_VOL_UP
|
|
#define SELECT BUTTON_MENU
|
|
#elif CONFIG_KEYPAD == ONDAVX777_PAD
|
|
#define QUIT BUTTON_POWER
|
|
|
|
#elif CONFIG_KEYPAD == MROBE500_PAD
|
|
#define QUIT BUTTON_POWER
|
|
|
|
#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \
|
|
(CONFIG_KEYPAD == SAMSUNG_YH920_PAD)
|
|
#define QUIT BUTTON_FFWD
|
|
#define SELECT BUTTON_PLAY
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
|
|
#define QUIT BUTTON_REC
|
|
#define LEFT BUTTON_PREV
|
|
#define RIGHT BUTTON_NEXT
|
|
#define ALTLEFT BUTTON_MENU
|
|
#define ALTRIGHT BUTTON_PLAY
|
|
#define SELECT BUTTON_OK
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == MPIO_HD200_PAD
|
|
#define QUIT (BUTTON_REC|BUTTON_PLAY)
|
|
#define LEFT BUTTON_VOL_DOWN
|
|
#define RIGHT BUTTON_VOL_UP
|
|
#define SELECT BUTTON_FUNC
|
|
#define UP BUTTON_REW
|
|
#define DOWN BUTTON_FF
|
|
|
|
#elif CONFIG_KEYPAD == MPIO_HD300_PAD
|
|
#define QUIT (BUTTON_MENU|BUTTON_REPEAT)
|
|
#define LEFT BUTTON_REW
|
|
#define RIGHT BUTTON_FF
|
|
#define SELECT BUTTON_ENTER
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif (CONFIG_KEYPAD == HM60X_PAD) || \
|
|
(CONFIG_KEYPAD == HM801_PAD)
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == SONY_NWZ_PAD
|
|
#define QUIT BUTTON_BACK
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_PLAY
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == CREATIVE_ZEN_PAD
|
|
#define QUIT BUTTON_BACK
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_SELECT
|
|
#define UP BUTTON_UP
|
|
#define DOWN BUTTON_DOWN
|
|
|
|
#elif CONFIG_KEYPAD == DX50_PAD
|
|
#define QUIT BUTTON_POWER
|
|
#define LEFT BUTTON_LEFT
|
|
#define RIGHT BUTTON_RIGHT
|
|
#define SELECT BUTTON_PLAY
|
|
#define UP BUTTON_VOL_UP
|
|
#define DOWN BUTTON_VOL_DOWN
|
|
|
|
#else
|
|
#error No keymap defined!
|
|
#endif
|
|
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
#ifdef LEFT
|
|
#define ALTLEFT BUTTON_BOTTOMLEFT
|
|
#else
|
|
#define LEFT BUTTON_BOTTOMLEFT
|
|
#endif
|
|
#ifdef RIGHT
|
|
#define ALTRIGHT BUTTON_BOTTOMRIGHT
|
|
#else
|
|
#define RIGHT BUTTON_BOTTOMRIGHT
|
|
#endif
|
|
#ifdef SELECT
|
|
#define ALTSELECT BUTTON_CENTER
|
|
#else
|
|
#define SELECT BUTTON_CENTER
|
|
#endif
|
|
#ifndef UP
|
|
#define UP BUTTON_TOPMIDDLE
|
|
#endif
|
|
#ifndef DOWN
|
|
#define DOWN BUTTON_BOTTOMMIDDLE
|
|
#endif
|
|
#endif
|
|
|
|
/* Continue text is used as a string later when the game is paused. This allows
|
|
* targets to specify their own text if needed.
|
|
*/
|
|
#if !defined(CONTINUE_TEXT)
|
|
#define CONTINUE_TEXT "Press SELECT To Continue"
|
|
#endif
|
|
|
|
#ifndef SCROLL_FWD /* targets without scroll wheel*/
|
|
#define SCROLL_FWD(x) (0)
|
|
#define SCROLL_BACK(x) (0)
|
|
#endif
|
|
|
|
|
|
#define NUM_BRICKS_ROWS 8
|
|
#define NUM_BRICKS_COLS 10
|
|
|
|
/*
|
|
*
|
|
* Geometric dimensions
|
|
*
|
|
*/
|
|
|
|
/* If there are three fractional bits, the smallest screen size that will scale
|
|
* properly is 28x22. If you have a smaller screen increase the fractional
|
|
* precision. If you have a precision of 4 the smallest screen size would be
|
|
* 14x11. Note though that this will decrease the maximum resolution due to
|
|
* the line intersection tests. These defines are used for all of the fixed
|
|
* point calculations/conversions.
|
|
*/
|
|
#define FIXED3(x) ((x)<<3)
|
|
#define FIXED3_MUL(x, y) ((long long)((x)*(y))>>3)
|
|
#define FIXED3_DIV(x, y) (((x)<<3)/(y))
|
|
#define INT3(x) ((x)>>3)
|
|
|
|
#define GAMESCREEN_WIDTH FIXED3(LCD_WIDTH)
|
|
#define GAMESCREEN_HEIGHT FIXED3(LCD_HEIGHT)
|
|
|
|
#define PAD_WIDTH FIXED3(BMPWIDTH_brickmania_pads)
|
|
#define PAD_HEIGHT FIXED3(BMPHEIGHT_brickmania_pads/3)
|
|
#define SHORT_PAD_WIDTH FIXED3(BMPWIDTH_brickmania_short_pads)
|
|
#define LONG_PAD_WIDTH FIXED3(BMPWIDTH_brickmania_long_pads)
|
|
#define BRICK_HEIGHT FIXED3(BMPHEIGHT_brickmania_bricks/7)
|
|
#define BRICK_WIDTH FIXED3(BMPWIDTH_brickmania_bricks)
|
|
#define LEFTMARGIN ((GAMESCREEN_WIDTH-NUM_BRICKS_COLS*BRICK_WIDTH)/2)
|
|
#define POWERUP_WIDTH FIXED3(BMPWIDTH_brickmania_powerups)
|
|
#define BALL FIXED3(BMPHEIGHT_brickmania_ball)
|
|
#define HALFBALL (BALL / 2)
|
|
#define PAD_POS_Y (GAMESCREEN_HEIGHT - PAD_HEIGHT - 1)
|
|
#define ON_PAD_POS_Y (PAD_POS_Y - HALFBALL)
|
|
|
|
#define GAMEOVER_WIDTH FIXED3(BMPWIDTH_brickmania_gameover)
|
|
#define GAMEOVER_HEIGHT FIXED3(BMPHEIGHT_brickmania_gameover)
|
|
|
|
#define TOPMARGIN MAX(BRICK_HEIGHT, FIXED3(8))
|
|
|
|
#define STRINGPOS_FINISH (GAMESCREEN_HEIGHT - (GAMESCREEN_HEIGHT / 6))
|
|
#define STRINGPOS_NAVI (STRINGPOS_FINISH - 10)
|
|
#define STRINGPOS_FLIP (STRINGPOS_FINISH - 10)
|
|
|
|
|
|
/*
|
|
*
|
|
* Speeds
|
|
*
|
|
*/
|
|
|
|
/* Brickmania was originally designed for the H300, other targets should scale
|
|
* the speed up/down as needed based on the screen height.
|
|
*/
|
|
#define SPEED_SCALE_H(y) FIXED3_DIV(GAMESCREEN_HEIGHT, FIXED3(176)/(y) )
|
|
#define SPEED_SCALE_W(x) FIXED3_DIV(GAMESCREEN_WIDTH, FIXED3(220)/(x) )
|
|
|
|
/* These are all used as ball speeds depending on where the ball hit the
|
|
* paddle.
|
|
*
|
|
* Note that all of these speeds (including pad, power, and fire)
|
|
* could be made variable and could be raised to be much higher to add
|
|
* additional difficulty to the game. The line intersection tests allow this
|
|
* to be drastically increased without the collision detection failing
|
|
* (ideally).
|
|
*/
|
|
#define SPEED_1Q_X SPEED_SCALE_W( 6)
|
|
#define SPEED_1Q_Y SPEED_SCALE_H(-2)
|
|
|
|
#define SPEED_2Q_X SPEED_SCALE_W( 4)
|
|
#define SPEED_2Q_Y SPEED_SCALE_H(-3)
|
|
|
|
#define SPEED_3Q_X SPEED_SCALE_W( 3)
|
|
#define SPEED_3Q_Y SPEED_SCALE_H(-4)
|
|
|
|
#define SPEED_4Q_X SPEED_SCALE_W( 2)
|
|
#define SPEED_4Q_Y SPEED_SCALE_H(-4)
|
|
|
|
/* This is used to determine the speed of the paddle */
|
|
#define SPEED_PAD SPEED_SCALE_W( 8)
|
|
|
|
/* This defines the speed that the powerups drop */
|
|
#define SPEED_POWER SPEED_SCALE_H( 2)
|
|
|
|
/* This defines the speed that the shot moves */
|
|
#define SPEED_FIRE SPEED_SCALE_H( 4)
|
|
#define FIRE_LENGTH SPEED_SCALE_H( 7)
|
|
|
|
|
|
/*
|
|
*
|
|
* Timings
|
|
*
|
|
*/
|
|
|
|
/* The time ms for one iteration through the game loop - decrease this to speed
|
|
* up the game - note that current_tick is (currently) only accurate to 10ms.
|
|
*/
|
|
#define CYCLETIME 30 /* ms */
|
|
|
|
#define FLIP_SIDES_DELAY 10 /* seconds */
|
|
|
|
|
|
/*
|
|
*
|
|
* Scores
|
|
*
|
|
*/
|
|
|
|
#define SCORE_BALL_HIT_BRICK 2
|
|
#define SCORE_BALL_DEMOLISHED_BRICK 8
|
|
#define SCORE_FIRE_HIT_BRICK 13
|
|
#define SCORE_LEVEL_COMPLETED 100
|
|
#define SCORE_POWER_LIFE_GAIN 50
|
|
#define SCORE_POWER_PADDLE_STICKY 34
|
|
#define SCORE_POWER_PADDLE_SHOOTER 47
|
|
#define SCORE_POWER_PADDLE_NORMAL 23
|
|
#define SCORE_POWER_FLIP 23
|
|
#define SCORE_POWER_EXTRA_BALL 23
|
|
#define SCORE_POWER_LONG_PADDLE 23
|
|
|
|
|
|
/*
|
|
*
|
|
* Limits
|
|
*
|
|
*/
|
|
|
|
#define MAX_BALLS 10
|
|
#define MAX_FIRES 30
|
|
#define MAX_POWERS 10
|
|
|
|
|
|
/*
|
|
*
|
|
* Files
|
|
*
|
|
*/
|
|
|
|
#define CONFIG_FILE_NAME "brickmania.cfg"
|
|
#define SAVE_FILE PLUGIN_GAMES_DATA_DIR "/brickmania.save"
|
|
#define SCORE_FILE PLUGIN_GAMES_DATA_DIR "/brickmania.score"
|
|
#define NUM_SCORES 5
|
|
|
|
|
|
/*
|
|
*
|
|
* Game levels
|
|
*
|
|
*/
|
|
|
|
/* change to however many levels there are, i.e. how many arrays there are total */
|
|
#define NUM_LEVELS 40
|
|
|
|
/* change the first number in [ ] to however many levels there are */
|
|
static unsigned char levels[NUM_LEVELS][NUM_BRICKS_ROWS][NUM_BRICKS_COLS] =
|
|
/* You can set up new levels with the level editor
|
|
( http://plugbox.rockbox-lounge.com/brickmania.htm ).
|
|
With 0x1, it refers to the first brick in the bitmap, 0x2 would refer to the
|
|
second, ect., 0x0 leaves a empty space. If you add a 2 before the 2nd number,
|
|
it will take two hits to break, and 3 hits if you add a 3. That is 0x24, will
|
|
result with the fourth brick being displayed and having take 2 hits to break.
|
|
You could do the same with the 3, just replace the 2 with a 3 for it to take
|
|
three hits to break it apart. */
|
|
{
|
|
{ /* level 1 */
|
|
{0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1},
|
|
{0x2,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x2},
|
|
{0x0,0x2,0x1,0x0,0x0,0x0,0x0,0x1,0x2,0x0},
|
|
{0x0,0x0,0x2,0x1,0x0,0x0,0x1,0x2,0x0,0x0},
|
|
{0x0,0x0,0x0,0x2,0x1,0x1,0x2,0x0,0x0,0x0},
|
|
{0x7,0x0,0x0,0x7,0x2,0x2,0x7,0x0,0x0,0x7},
|
|
{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
|
|
{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
|
|
},
|
|
{ /* level 2 */
|
|
{0x0,0x0,0x7,0x7,0x1,0x1,0x7,0x7,0x0,0x0},
|
|
{0x0,0x1,0x0,0x0,0x1,0x1,0x0,0x0,0x1,0x0},
|
|
{0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1},
|
|
{0x1,0x1,0x1,0x1,0x0,0x0,0x1,0x1,0x1,0x1},
|
|
{0x1,0x1,0x2,0x1,0x0,0x0,0x1,0x2,0x1,0x1},
|
|
{0x1,0x2,0x0,0x2,0x2,0x2,0x2,0x0,0x2,0x1},
|
|
{0x0,0x1,0x2,0x0,0x0,0x0,0x0,0x2,0x1,0x0},
|
|
{0x0,0x0,0x1,0x2,0x2,0x2,0x2,0x1,0x0,0x0}
|
|
},
|
|
{ /* level 3 */
|
|
{0x3,0x3,0x3,0x3,0x0,0x0,0x2,0x2,0x2,0x2},
|
|
{0x3,0x23,0x23,0x3,0x0,0x0,0x2,0x22,0x22,0x2},
|
|
{0x3,0x3,0x3,0x3,0x0,0x0,0x2,0x2,0x2,0x2},
|
|
{0x0,0x0,0x0,0x0,0x37,0x37,0x0,0x0,0x0,0x0},
|
|
{0x0,0x0,0x0,0x0,0x37,0x37,0x0,0x0,0x0,0x0},
|
|
{0x5,0x5,0x5,0x5,0x0,0x0,0x6,0x6,0x6,0x6},
|
|
{0x5,0x25,0x25,0x5,0x0,0x0,0x6,0x26,0x26,0x6},
|
|
{0x5,0x5,0x5,0x5,0x0,0x0,0x6,0x6,0x6,0x6}
|
|
},
|
|
{ /* level 4 */
|
|
{0x0,0x0,0x0,0x27,0x27,0x27,0x27,0x0,0x0,0x0},
|
|
{0x0,0x0,0x0,0x27,0x7,0x7,0x27,0x0,0x0,0x0},
|
|
{0x22,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x22},
|
|
{0x22,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x22},
|
|
{0x26,0x6,0x0,0x2,0x2,0x2,0x2,0x0,0x6,0x26},
|
|
{0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0},
|
|
{0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0},
|
|
{0x1,0x1,0x1,0x1,0x0,0x0,0x1,0x1,0x1,0x1}
|
|
},
|
|
{ /* level 5 */
|
|
{0x1,0x0,0x2,0x2,0x0,0x3,0x3,0x0,0x4,0x4},
|
|
{0x0,0x2,0x2,0x0,0x3,0x3,0x0,0x4,0x4,0x0},
|
|
{0x2,0x2,0x0,0x3,0x3,0x0,0x4,0x4,0x0,0x5},
|
|
{0x2,0x0,0x3,0x3,0x0,0x4,0x4,0x0,0x5,0x5},
|
|
{0x0,0x33,0x3,0x0,0x4,0x4,0x0,0x5,0x5,0x0},
|
|
{0x3,0x33,0x0,0x4,0x4,0x0,0x5,0x5,0x0,0x36},
|
|
{0x3,0x0,0x4,0x4,0x0,0x5,0x5,0x0,0x6,0x36},
|
|
{0x0,0x24,0x24,0x0,0x25,0x25,0x0,0x26,0x26,0x0}
|
|
},
|
|
{ /* level 6 */
|
|
{0x0,0x1,0x3,0x7,0x7,0x7,0x7,0x3,0x1,0x0},
|
|
{0x3,0x1,0x3,0x7,0x0,0x0,0x7,0x3,0x1,0x3},
|
|
{0x3,0x1,0x3,0x7,0x7,0x7,0x7,0x3,0x1,0x3},
|
|
{0x0,0x0,0x0,0x2,0x2,0x2,0x2,0x0,0x0,0x0},
|
|
{0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5},
|
|
{0x5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x5},
|
|
{0x0,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x0},
|
|
{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
|
|
},
|
|
{ /* level 7 */
|
|
{0x0,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x0},
|
|
{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
|
|
{0x6,0x0,0x0,0x2,0x2,0x2,0x2,0x0,0x0,0x6},
|
|
{0x6,0x0,0x0,0x2,0x2,0x2,0x2,0x0,0x0,0x6},
|
|
{0x6,0x6,0x6,0x0,0x0,0x0,0x0,0x6,0x6,0x6},
|
|
{0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x0,0x0,0x0},
|
|
{0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x0},
|
|
{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
|
|
},
|
|
{ /* level 8 */
|
|
{0x0,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x0},
|
|
{0x0,0x0,0x0,0x4,0x0,0x0,0x4,0x0,0x0,0x0},
|
|
{0x6,0x6,0x0,0x2,0x32,0x32,0x2,0x0,0x6,0x6},
|
|
{0x0,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x0,0x0},
|
|
{0x0,0x6,0x6,0x0,0x0,0x0,0x0,0x6,0x6,0x0},
|
|
{0x0,0x0,0x0,0x5,0x25,0x25,0x5,0x0,0x0,0x0},
|
|
{0x0,0x5,0x5,0x25,0x5,0x5,0x25,0x5,0x5,0x0},
|
|
{0x5,0x5,0x25,0x5,0x5,0x5,0x5,0x25,0x5,0x5}
|
|
},
|
|
{ /* level 9 */
|
|
{0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2},
|
|
{0x2,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x2},
|
|
{0x2,0x0,0x3,0x0,0x1,0x1,0x0,0x3,0x0,0x2},
|
|
{0x2,0x0,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x2},
|
|
{0x2,0x0,0x1,0x0,0x3,0x3,0x0,0x1,0x0,0x2},
|
|
{0x2,0x0,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x2},
|
|
{0x2,0x2,0x0,0x0,0x1,0x1,0x0,0x0,0x2,0x2},
|
|
{0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2}
|
|
},
|
|
{ /* level 10 */
|
|
{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
|
|
{0x0,0x5,0x0,0x5,0x0,0x5,0x0,0x5,0x0,0x5},
|
|
{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
|
|
{0x0,0x0,0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0},
|
|
{0x0,0x0,0x0,0x4,0x1,0x1,0x4,0x0,0x0,0x0},
|
|
{0x0,0x0,0x3,0x4,0x1,0x1,0x4,0x3,0x0,0x0},
|
|
{0x0,0x2,0x3,0x4,0x1,0x1,0x4,0x3,0x2,0x0},
|
|
{0x1,0x2,0x3,0x4,0x1,0x1,0x4,0x3,0x2,0x1}
|
|
},
|
|
{ /* level 11 */
|
|
{0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3},
|
|
{0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x2},
|
|
{0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2},
|
|
{0x2,0x0,0x0,0x0,0x7,0x7,0x0,0x0,0x0,0x2},
|
|
{0x2,0x0,0x0,0x7,0x7,0x7,0x7,0x0,0x0,0x2},
|
|
{0x0,0x0,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x0},
|
|
{0x0,0x2,0x0,0x1,0x0,0x0,0x1,0x0,0x2,0x0},
|
|
{0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5}
|
|
},
|
|
{ /* level 12 */
|
|
{0x2,0x1,0x3,0x1,0x0,0x0,0x1,0x3,0x1,0x2},
|
|
{0x1,0x1,0x1,0x1,0x0,0x0,0x1,0x1,0x1,0x1},
|
|
{0x1,0x1,0x1,0x0,0x1,0x1,0x0,0x1,0x1,0x1},
|
|
{0x0,0x1,0x0,0x1,0x6,0x6,0x1,0x0,0x1,0x0},
|
|
{0x0,0x0,0x1,0x1,0x6,0x6,0x1,0x1,0x0,0x0},
|
|
{0x1,0x1,0x1,0x7,0x0,0x0,0x7,0x1,0x1,0x1},
|
|
{0x1,0x1,0x7,0x1,0x0,0x0,0x1,0x7,0x1,0x1},
|
|
{0x2,0x2,0x0,0x2,0x2,0x2,0x2,0x0,0x2,0x2}
|
|
},
|
|
{/* levell13 */
|
|
{0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2},
|
|
{0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2},
|
|
{0x2,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x0,0x2},
|
|
{0x2,0x0,0x2,0x3,0x3,0x3,0x3,0x3,0x0,0x2},
|
|
{0x2,0x0,0x2,0x4,0x4,0x4,0x4,0x4,0x0,0x2},
|
|
{0x2,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2},
|
|
{0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
|
|
{0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2}
|
|
},
|
|
{/* level 14 */
|
|
{0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1},
|
|
{0x4,0x4,0x4,0x4,0x2,0x2,0x4,0x4,0x4,0x4},
|
|
{0x4,0x0,0x0,0x0,0x2,0x2,0x0,0x0,0x0,0x4},
|
|
{0x4,0x0,0x0,0x2,0x3,0x3,0x2,0x0,0x0,0x4},
|
|
{0x4,0x0,0x2,0x23,0x3,0x3,0x23,0x2,0x0,0x4},
|
|
{0x4,0x0,0x2,0x22,0x2,0x2,0x22,0x2,0x0,0x4},
|
|
{0x4,0x0,0x6,0x21,0x5,0x5,0x21,0x6,0x0,0x4},
|
|
{0x4,0x6,0x1,0x1,0x5,0x5,0x1,0x1,0x6,0x4}
|
|
},
|
|
{/* level 15 */
|
|
{0x4,0x4,0x4,0x4,0x4,0x3,0x3,0x3,0x3,0x3},
|
|
{0x2,0x2,0x1,0x1,0x1,0x1,0x1,0x5,0x0,0x0},
|
|
{0x2,0x2,0x1,0x1,0x1,0x0,0x1,0x6,0x0,0x0},
|
|
{0x2,0x1,0x1,0x2,0x1,0x1,0x1,0x5,0x0,0x0},
|
|
{0x2,0x1,0x2,0x2,0x2,0x1,0x1,0x6,0x0,0x0},
|
|
{0x2,0x1,0x2,0x2,0x2,0x1,0x3,0x5,0x3,0x0},
|
|
{0x2,0x1,0x1,0x2,0x1,0x1,0x1,0x6,0x0,0x0},
|
|
{0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2}
|
|
},
|
|
{/* level 16 (Rockbox) by ts-x */
|
|
{0x2,0x2,0x3,0x3,0x3,0x4,0x4,0x5,0x0,0x5},
|
|
{0x2,0x0,0x3,0x0,0x3,0x4,0x0,0x5,0x5,0x0},
|
|
{0x2,0x0,0x3,0x3,0x3,0x4,0x4,0x5,0x0,0x5},
|
|
{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
|
|
{0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
|
|
{0x7,0x7,0x7,0x1,0x1,0x1,0x2,0x0,0x2,0x0},
|
|
{0x7,0x0,0x7,0x1,0x0,0x1,0x0,0x2,0x0,0x0},
|
|
{0x7,0x7,0x7,0x1,0x1,0x1,0x2,0x0,0x2,0x0}
|
|
},
|
|
{/* level 17 (Alien) by ts-x */
|
|
{0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1},
|
|
{0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2},
|
|
{0x1,0x0,0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x1},
|
|
{0x2,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x2},
|
|
{0x1,0x0,0x1,0x2,0x2,0x2,0x2,0x1,0x0,0x1},
|
|
{0x2,0x0,0x0,0x1,0x2,0x2,0x1,0x0,0x0,0x2},
|
|
{0x2,0x1,0x0,0x0,0x1,0x1,0x0,0x0,0x1,0x2},
|
|
{0x2,0x2,0x1,0x0,0x1,0x1,0x0,0x1,0x2,0x2}
|
|
},
|
|
{/* level 18 (Tetris) by ts-x */
|
|
{0x0,0x2,0x0,0x0,0x3,0x4,0x0,0x2,0x2,0x0},
|
|
{0x0,0x2,0x7,0x0,0x3,0x4,0x0,0x2,0x2,0x0},
|
|
{0x2,0x2,0x7,0x0,0x3,0x4,0x0,0x6,0x2,0x2},
|
|
{0x2,0x2,0x7,0x7,0x3,0x4,0x0,0x6,0x2,0x2},
|
|
{0x2,0x1,0x7,0x7,0x3,0x4,0x4,0x6,0x5,0x5},
|
|
{0x2,0x1,0x0,0x7,0x3,0x4,0x4,0x6,0x5,0x5},
|
|
{0x1,0x1,0x1,0x7,0x3,0x0,0x6,0x6,0x5,0x5},
|
|
{0x1,0x1,0x1,0x0,0x3,0x0,0x6,0x6,0x5,0x5}
|
|
},
|
|
{ /* level 19 (Stalactites) by ts-x */
|
|
{0x5,0x2,0x6,0x3,0x4,0x7,0x5,0x3,0x1,0x2},
|
|
{0x5,0x2,0x6,0x3,0x4,0x7,0x5,0x3,0x1,0x2},
|
|
{0x5,0x0,0x6,0x3,0x4,0x7,0x5,0x0,0x1,0x2},
|
|
{0x5,0x2,0x6,0x3,0x4,0x0,0x5,0x3,0x1,0x2},
|
|
{0x5,0x0,0x6,0x0,0x4,0x7,0x5,0x0,0x1,0x0},
|
|
{0x5,0x0,0x0,0x3,0x4,0x0,0x0,0x0,0x1,0x2},
|
|
{0x0,0x0,0x6,0x0,0x0,0x0,0x5,0x0,0x0,0x0},
|
|
{0x5,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0}
|
|
},
|
|
{ /* level 20 (Maze) by ts-x */
|
|
{0x1,0x1,0x21,0x1,0x1,0x1,0x1,0x1,0x1,0x21},
|
|
{0x1,0x0,0x0,0x3,0x0,0x0,0x3,0x1,0x31,0x1},
|
|
{0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x31,0x0,0x1},
|
|
{0x21,0x0,0x21,0x3,0x0,0x3,0x0,0x3,0x0,0x2},
|
|
{0x1,0x0,0x1,0x21,0x0,0x12,0x0,0x0,0x0,0x0},
|
|
{0x31,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x3,0x0},
|
|
{0x1,0x0,0x1,0x0,0x1,0x1,0x31,0x1,0x1,0x2},
|
|
{0x22,0x0,0x2,0x1,0x1,0x1,0x1,0x1,0x1,0x21}
|
|
},
|
|
{ /* level 21 (Dentist) by ts-x */
|
|
{0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x0},
|
|
{0x2,0x2,0x0,0x6,0x0,0x6,0x0,0x6,0x2,0x2},
|
|
{0x2,0x6,0x0,0x6,0x0,0x6,0x0,0x6,0x0,0x2},
|
|
{0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x2},
|
|
{0x2,0x0,0x6,0x0,0x6,0x0,0x0,0x0,0x0,0x2},
|
|
{0x2,0x0,0x6,0x0,0x6,0x0,0x6,0x0,0x6,0x2},
|
|
{0x2,0x2,0x6,0x0,0x6,0x0,0x6,0x0,0x2,0x2},
|
|
{0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x0}
|
|
},
|
|
{ /* level 22 (Spider) by ts-x */
|
|
{0x31,0x3,0x1,0x1,0x0,0x0,0x1,0x1,0x3,0x31},
|
|
{0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0},
|
|
{0x33,0x1,0x1,0x36,0x1,0x1,0x36,0x1,0x1,0x33},
|
|
{0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x0,0x0},
|
|
{0x0,0x0,0x1,0x1,0x0,0x0,0x1,0x1,0x0,0x0},
|
|
{0x21,0x3,0x1,0x21,0x2,0x2,0x21,0x1,0x3,0x21},
|
|
{0x0,0x0,0x0,0x1,0x21,0x1,0x1,0x0,0x0,0x0},
|
|
{0x3,0x1,0x3,0x1,0x0,0x0,0x1,0x3,0x1,0x3}
|
|
},
|
|
{ /* level 23 (Pool) by ts-x */
|
|
{0x0,0x7,0x7,0x7,0x0,0x7,0x7,0x7,0x7,0x0},
|
|
{0x0,0x0,0x5,0x0,0x2,0x0,0x0,0x0,0x2,0x0},
|
|
{0x7,0x3,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x7},
|
|
{0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x5,0x0,0x7},
|
|
{0x7,0x0,0x4,0x0,0x0,0x3,0x0,0x0,0x0,0x7},
|
|
{0x7,0x0,0x0,0x6,0x0,0x0,0x0,0x0,0x4,0x7},
|
|
{0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
|
|
{0x0,0x7,0x7,0x7,0x7,0x0,0x7,0x7,0x7,0x0}
|
|
},
|
|
{ /* level 24 (Vorbis Fish) by ts-x */
|
|
{0x0,0x0,0x4,0x4,0x5,0x5,0x5,0x0,0x0,0x5},
|
|
{0x0,0x4,0x6,0x4,0x4,0x5,0x5,0x5,0x0,0x5},
|
|
{0x5,0x6,0x0,0x6,0x4,0x4,0x4,0x5,0x5,0x5},
|
|
{0x5,0x6,0x0,0x6,0x4,0x4,0x4,0x4,0x5,0x5},
|
|
{0x0,0x5,0x6,0x4,0x4,0x5,0x5,0x4,0x5,0x0},
|
|
{0x5,0x5,0x4,0x4,0x5,0x5,0x5,0x4,0x5,0x5},
|
|
{0x5,0x4,0x4,0x4,0x5,0x5,0x4,0x4,0x5,0x5},
|
|
{0x0,0x0,0x4,0x4,0x4,0x4,0x4,0x5,0x0,0x5}
|
|
},
|
|
{/* level 25 (Rainbow) by ts-x */
|
|
{0x0,0x4,0x1,0x0,0x0,0x0,0x0,0x1,0x4,0x0},
|
|
{0x24,0x1,0x3,0x1,0x0,0x0,0x21,0x3,0x1,0x24},
|
|
{0x1,0x23,0x5,0x3,0x1,0x21,0x3,0x5,0x3,0x21},
|
|
{0x3,0x5,0x6,0x5,0x3,0x3,0x5,0x6,0x5,0x3},
|
|
{0x5,0x6,0x7,0x6,0x5,0x5,0x6,0x7,0x6,0x5},
|
|
{0x6,0x7,0x2,0x27,0x6,0x6,0x27,0x2,0x7,0x6},
|
|
{0x7,0x2,0x0,0x2,0x27,0x27,0x2,0x0,0x2,0x7},
|
|
{0x32,0x0,0x0,0x0,0x2,0x2,0x0,0x0,0x0,0x32}
|
|
},
|
|
{ /* level 26 (Bowtie) by ts-x */
|
|
{0x5,0x1,0x5,0x1,0x0,0x0,0x1,0x5,0x1,0x5},
|
|
{0x1,0x0,0x0,0x1,0x5,0x5,0x1,0x0,0x0,0x1},
|
|
{0x5,0x0,0x6,0x0,0x1,0x1,0x0,0x6,0x0,0x5},
|
|
{0x1,0x0,0x6,0x6,0x0,0x0,0x6,0x6,0x0,0x1},
|
|
{0x1,0x0,0x6,0x6,0x0,0x0,0x6,0x6,0x0,0x1},
|
|
{0x5,0x0,0x6,0x0,0x1,0x1,0x0,0x6,0x0,0x5},
|
|
{0x1,0x0,0x0,0x1,0x5,0x5,0x1,0x0,0x0,0x1},
|
|
{0x5,0x1,0x5,0x1,0x0,0x0,0x1,0x5,0x1,0x5}
|
|
},
|
|
{ /* level 27 (Frog) by ts-x */
|
|
{0x0,0x5,0x25,0x0,0x0,0x0,0x0,0x25,0x5,0x0},
|
|
{0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5},
|
|
{0x25,0x0,0x0,0x5,0x6,0x6,0x5,0x0,0x0,0x25},
|
|
{0x5,0x0,0x3,0x0,0x6,0x6,0x0,0x3,0x0,0x5},
|
|
{0x5,0x0,0x31,0x0,0x6,0x6,0x0,0x31,0x0,0x5},
|
|
{0x5,0x0,0x0,0x5,0x6,0x6,0x5,0x0,0x0,0x5},
|
|
{0x5,0x5,0x5,0x35,0x0,0x0,0x35,0x5,0x5,0x5},
|
|
{0x0,0x25,0x5,0x0,0x4,0x4,0x0,0x5,0x25,0x0}
|
|
},
|
|
{ /* level 28 (DigDug) by ts-x */
|
|
{0x35,0x5,0x5,0x25,0x0,0x25,0x25,0x5,0x5,0x35},
|
|
{0x6,0x0,0x0,0x6,0x0,0x6,0x6,0x0,0x0,0x6},
|
|
{0x7,0x0,0x37,0x37,0x0,0x37,0x37,0x7,0x0,0x7},
|
|
{0x7,0x0,0x7,0x0,0x0,0x0,0x7,0x7,0x7,0x7},
|
|
{0x4,0x4,0x4,0x24,0x0,0x24,0x4,0x0,0x0,0x4},
|
|
{0x4,0x4,0x0,0x0,0x0,0x4,0x4,0x0,0x4,0x4},
|
|
{0x24,0x24,0x4,0x4,0x4,0x4,0x0,0x0,0x24,0x4},
|
|
{0x1,0x1,0x1,0x1,0x1,0x1,0x21,0x21,0x1,0x1}
|
|
},
|
|
{ /* level 29 UK Flag by Seth Opgenorth */
|
|
{0x32,0x0,0x3,0x3,0x2,0x2,0x3,0x3,0x0,0x32},
|
|
{0x0,0x2,0x0,0x3,0x32,0x22,0x33,0x0,0x32,0x0},
|
|
{0x33,0x0,0x22,0x0,0x2,0x2,0x0,0x2,0x0,0x33},
|
|
{0x22,0x32,0x2,0x2,0x2,0x2,0x2,0x2,0x22,0x2},
|
|
{0x3,0x0,0x0,0x32,0x22,0x2,0x2,0x0,0x0,0x3},
|
|
{0x23,0x0,0x32,0x0,0x32,0x2,0x0,0x2,0x0,0x3},
|
|
{0x0,0x2,0x0,0x3,0x2,0x2,0x3,0x0,0x22,0x0},
|
|
{0x32,0x0,0x3,0x23,0x2,0x2,0x23,0x33,0x0,0x32}
|
|
},
|
|
{ /* level 30 Win-Logo by Seth Opgenorth */
|
|
{0x0,0x0,0x0,0x22,0x0,0x0,0x0,0x0,0x0,0x0},
|
|
{0x0,0x0,0x32,0x2,0x2,0x25,0x0,0x5,0x0,0x0},
|
|
{0x0,0x0,0x2,0x22,0x2,0x5,0x5,0x35,0x0,0x0},
|
|
{0x0,0x0,0x2,0x1,0x2,0x5,0x5,0x25,0x0,0x0},
|
|
{0x0,0x0,0x21,0x1,0x1,0x36,0x7,0x26,0x0,0x0},
|
|
{0x0,0x0,0x1,0x1,0x1,0x6,0x6,0x6,0x0,0x0},
|
|
{0x0,0x0,0x21,0x0,0x21,0x6,0x6,0x26,0x0,0x0},
|
|
{0x0,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x0,0x0}
|
|
},
|
|
{ /* level 31 Color wave/V by Seth Opgenorth */
|
|
{0x25,0x34,0x2,0x31,0x33,0x23,0x1,0x2,0x34,0x5},
|
|
{0x3,0x5,0x24,0x2,0x1,0x1,0x2,0x4,0x5,0x3},
|
|
{0x1,0x3,0x5,0x4,0x2,0x2,0x4,0x5,0x3,0x1},
|
|
{0x2,0x1,0x33,0x35,0x4,0x4,0x5,0x33,0x1,0x22},
|
|
{0x31,0x22,0x1,0x3,0x5,0x25,0x3,0x1,0x2,0x31},
|
|
{0x3,0x1,0x2,0x1,0x3,0x3,0x1,0x2,0x21,0x3},
|
|
{0x5,0x23,0x1,0x32,0x1,0x1,0x2,0x1,0x3,0x5},
|
|
{0x4,0x35,0x3,0x1,0x2,0x22,0x31,0x3,0x5,0x4}
|
|
},
|
|
{ /* level 32 Sweedish Flag by Seth Opgenorth */
|
|
{0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
|
|
{0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
|
|
{0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
|
|
{0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36},
|
|
{0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36},
|
|
{0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
|
|
{0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3},
|
|
{0x3,0x3,0x3,0x36,0x3,0x3,0x3,0x3,0x3,0x3}
|
|
},
|
|
{ /* level 33 Color Pyramid by Seth Opgenorth */
|
|
{0x0,0x0,0x0,0x0,0x2,0x2,0x0,0x0,0x0,0x0},
|
|
{0x0,0x0,0x0,0x4,0x24,0x4,0x24,0x0,0x0,0x0},
|
|
{0x0,0x0,0x23,0x3,0x3,0x3,0x23,0x3,0x0,0x0},
|
|
{0x0,0x0,0x25,0x5,0x25,0x35,0x5,0x35,0x0,0x0},
|
|
{0x0,0x36,0x6,0x6,0x6,0x6,0x26,0x6,0x6,0x0},
|
|
{0x0,0x7,0x7,0x7,0x7,0x25,0x27,0x7,0x27,0x0},
|
|
{0x2,0x2,0x22,0x2,0x2,0x2,0x22,0x2,0x2,0x2},
|
|
{0x21,0x1,0x1,0x31,0x1,0x21,0x1,0x1,0x31,0x1}
|
|
},
|
|
{ /* level 34 Rhombus by Seth Opgenorth */
|
|
{0x0,0x0,0x0,0x0,0x3,0x33,0x0,0x0,0x0,0x0},
|
|
{0x0,0x0,0x0,0x3,0x32,0x22,0x23,0x0,0x0,0x0},
|
|
{0x0,0x0,0x3,0x2,0x24,0x4,0x2,0x23,0x0,0x0},
|
|
{0x26,0x3,0x2,0x4,0x5,0x5,0x4,0x22,0x3,0x6},
|
|
{0x36,0x3,0x2,0x34,0x5,0x5,0x4,0x2,0x3,0x36},
|
|
{0x0,0x0,0x3,0x2,0x4,0x34,0x2,0x23,0x0,0x0},
|
|
{0x0,0x0,0x0,0x23,0x2,0x2,0x3,0x0,0x0,0x0},
|
|
{0x0,0x0,0x0,0x0,0x3,0x33,0x0,0x0,0x0,0x0}
|
|
},
|
|
{ /* level 35 PacMan Ghost by Seth Opgenorth */
|
|
{0x0,0x0,0x0,0x0,0x2,0x32,0x2,0x0,0x0,0x0},
|
|
{0x0,0x0,0x0,0x2,0x2,0x2,0x2,0x2,0x0,0x0},
|
|
{0x0,0x0,0x2,0x24,0x4,0x2,0x4,0x4,0x32,0x0},
|
|
{0x0,0x0,0x2,0x24,0x0,0x22,0x24,0x0,0x22,0x0},
|
|
{0x0,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x0},
|
|
{0x0,0x0,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x0},
|
|
{0x0,0x0,0x2,0x32,0x2,0x2,0x22,0x2,0x32,0x0},
|
|
{0x0,0x0,0x0,0x22,0x0,0x32,0x0,0x22,0x0,0x0}
|
|
},
|
|
{ /* level 36 Star by Seth Opgenorth */
|
|
{0x3,0x4,0x3,0x4,0x6,0x24,0x3,0x24,0x3,0x0},
|
|
{0x24,0x0,0x0,0x6,0x6,0x6,0x0,0x0,0x4,0x0},
|
|
{0x3,0x26,0x6,0x2,0x6,0x2,0x6,0x26,0x23,0x0},
|
|
{0x4,0x0,0x6,0x6,0x36,0x6,0x6,0x0,0x4,0x0},
|
|
{0x3,0x0,0x0,0x26,0x6,0x26,0x0,0x0,0x33,0x0},
|
|
{0x34,0x0,0x6,0x6,0x0,0x6,0x6,0x0,0x4,0x0},
|
|
{0x3,0x26,0x6,0x0,0x0,0x0,0x6,0x6,0x3,0x0},
|
|
{0x4,0x3,0x4,0x23,0x24,0x3,0x4,0x33,0x4,0x0}
|
|
},
|
|
{ /* level 37 It's 8-Bit by Seth Opgenorth */
|
|
{0x26,0x26,0x6,0x6,0x5,0x6,0x26,0x6,0x26,0x6},
|
|
{0x2,0x2,0x22,0x3,0x3,0x0,0x0,0x0,0x4,0x0},
|
|
{0x2,0x0,0x2,0x33,0x3,0x3,0x5,0x0,0x24,0x0},
|
|
{0x32,0x2,0x2,0x33,0x0,0x23,0x0,0x4,0x4,0x4},
|
|
{0x2,0x22,0x2,0x3,0x3,0x0,0x5,0x4,0x4,0x24},
|
|
{0x2,0x0,0x2,0x23,0x0,0x3,0x25,0x0,0x4,0x0},
|
|
{0x22,0x2,0x2,0x3,0x23,0x0,0x5,0x0,0x4,0x0},
|
|
{0x6,0x26,0x6,0x36,0x6,0x36,0x6,0x6,0x6,0x6}
|
|
},
|
|
{ /* level 38 Linux by Seth Opgenorth */
|
|
{0x27,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
|
|
{0x7,0x0,0x0,0x0,0x33,0x0,0x23,0x0,0x0,0x0},
|
|
{0x7,0x32,0x0,0x0,0x3,0x0,0x23,0x6,0x0,0x6},
|
|
{0x37,0x0,0x0,0x0,0x23,0x0,0x3,0x6,0x0,0x26},
|
|
{0x7,0x22,0x24,0x0,0x3,0x33,0x3,0x0,0x26,0x0},
|
|
{0x37,0x22,0x24,0x24,0x4,0x0,0x0,0x0,0x26,0x0},
|
|
{0x7,0x2,0x4,0x0,0x4,0x0,0x0,0x6,0x0,0x26},
|
|
{0x7,0x27,0x4,0x0,0x34,0x0,0x0,0x6,0x0,0x26}
|
|
},
|
|
{ /* level 39 Colorful Squares by Seth Opgenorth*/
|
|
{0x0,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x0},
|
|
{0x0,0x4,0x5,0x5,0x5,0x5,0x5,0x5,0x4,0x0},
|
|
{0x0,0x4,0x5,0x3,0x3,0x3,0x3,0x5,0x4,0x0},
|
|
{0x0,0x4,0x5,0x3,0x4,0x4,0x3,0x5,0x4,0x0},
|
|
{0x0,0x4,0x5,0x3,0x4,0x4,0x3,0x5,0x4,0x0},
|
|
{0x0,0x4,0x5,0x3,0x3,0x3,0x3,0x5,0x4,0x0},
|
|
{0x0,0x4,0x5,0x5,0x5,0x5,0x5,0x5,0x4,0x0},
|
|
{0x0,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x0}
|
|
},
|
|
{ /* TheEnd */
|
|
{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},
|
|
{0x32,0x32,0x36,0x0,0x0,0x36,0x34,0x34,0x0,0x0},
|
|
{0x32,0x0,0x36,0x36,0x0,0x36,0x34,0x0,0x34,0x0},
|
|
{0x32,0x32,0x36,0x36,0x0,0x36,0x34,0x0,0x34,0x0},
|
|
{0x32,0x32,0x36,0x0,0x36,0x36,0x34,0x0,0x34,0x0},
|
|
{0x32,0x0,0x36,0x0,0x36,0x36,0x34,0x0,0x34,0x0},
|
|
{0x32,0x32,0x36,0x0,0x0,0x36,0x34,0x34,0x0,0x0},
|
|
{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
*
|
|
* Enums and structs
|
|
*
|
|
*/
|
|
|
|
enum power_types
|
|
{
|
|
POWER_TYPE_LIFE_GAIN = 0,
|
|
POWER_TYPE_LIFE_LOSS,
|
|
POWER_TYPE_PADDLE_STICKY,
|
|
POWER_TYPE_PADDLE_SHOOTER,
|
|
POWER_TYPE_PADDLE_NORMAL,
|
|
POWER_TYPE_PADDLE_FLIP,
|
|
POWER_TYPE_EXTRA_BALL,
|
|
POWER_TYPE_PADDLE_LONG,
|
|
POWER_TYPE_PADDLE_SHORT,
|
|
NUMBER_OF_POWERUPS,
|
|
};
|
|
|
|
#define POWERUP_HEIGHT FIXED3(BMPHEIGHT_brickmania_powerups/NUMBER_OF_POWERUPS)
|
|
/* Increasing this value makes the game with less powerups */
|
|
#define POWER_RAND (NUMBER_OF_POWERUPS + 15)
|
|
|
|
enum difficulty_options
|
|
{
|
|
EASY,
|
|
NORMAL
|
|
};
|
|
|
|
enum game_state
|
|
{
|
|
ST_READY,
|
|
ST_START,
|
|
ST_PAUSE
|
|
};
|
|
|
|
enum paddle_type
|
|
{
|
|
PADDLE_TYPE_NORMAL = 0,
|
|
PADDLE_TYPE_STICKY,
|
|
PADDLE_TYPE_SHOOTER,
|
|
};
|
|
|
|
enum intersection
|
|
{
|
|
INTERSECTION_TOP,
|
|
INTERSECTION_BOTTOM,
|
|
INTERSECTION_LEFT,
|
|
INTERSECTION_RIGHT,
|
|
INTERSECTION_ALL,
|
|
};
|
|
|
|
struct brick
|
|
{
|
|
bool used; /* Is the brick still in play? */
|
|
int color;
|
|
int hits; /* How many hits can this brick take? */
|
|
int hiteffect;
|
|
};
|
|
|
|
struct ball
|
|
{
|
|
/* pos_x and y store the current center position of the ball */
|
|
int pos_x;
|
|
int pos_y;
|
|
/* tempx and tempy store an absolute position the ball should be in. If
|
|
* they are equal to 0, they are not used when positioning the ball.
|
|
*/
|
|
int tempx;
|
|
int tempy;
|
|
/* speedx and speedy store the current speed of the ball */
|
|
int speedx;
|
|
int speedy;
|
|
bool glue; /* Is the ball stuck to the paddle? */
|
|
};
|
|
|
|
struct fire
|
|
{
|
|
int top; /* This stores the fire y position, it is a fixed point num */
|
|
int x_pos; /* This stores the fire x position, it is a whole number */
|
|
};
|
|
|
|
struct power
|
|
{
|
|
int top; /* This stores the powerup y position, it is a fixed point num */
|
|
int x_pos; /* This stores the (middle of) powerup x position, it is a whole number */
|
|
enum power_types type; /* This stores the powerup type */
|
|
};
|
|
|
|
struct point
|
|
{
|
|
int x;
|
|
int y;
|
|
};
|
|
|
|
struct line
|
|
{
|
|
struct point p1;
|
|
struct point p2;
|
|
};
|
|
|
|
struct rect
|
|
{
|
|
struct point top_left;
|
|
struct point bottom_right;
|
|
};
|
|
|
|
/*
|
|
*
|
|
* Globals
|
|
*
|
|
*/
|
|
|
|
static enum game_state game_state;
|
|
static int pad_pos_x;
|
|
static int life;
|
|
static int score,vscore;
|
|
static bool flip_sides;
|
|
static int level;
|
|
static int brick_on_board;
|
|
static int used_balls;
|
|
static int used_fires;
|
|
static int used_powers;
|
|
static int difficulty = NORMAL;
|
|
static int pad_width;
|
|
static int flip_sides_delay;
|
|
static bool resume = false;
|
|
static bool resume_file = false;
|
|
static struct brick brick[NUM_BRICKS_ROWS][NUM_BRICKS_COLS];
|
|
static struct ball ball[MAX_BALLS];
|
|
static struct fire fire[MAX_FIRES];
|
|
static struct power power[MAX_POWERS];
|
|
static enum paddle_type paddle_type;
|
|
|
|
static struct configdata config[] =
|
|
{
|
|
{TYPE_INT, 0, 1, { .int_p = &difficulty }, "difficulty", NULL},
|
|
};
|
|
|
|
static struct highscore highscores[NUM_SCORES];
|
|
|
|
|
|
/*
|
|
*
|
|
* Functions
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* check_lines:
|
|
* This is based off an explanation and expanded math presented by Paul Bourke:
|
|
* http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
|
|
*
|
|
* It takes two lines as inputs and returns 1 if they intersect, 0 if they do
|
|
* not. hitp returns the point where the two lines intersected.
|
|
*
|
|
* This function expects fixed point inputs with a precision of 3. When a
|
|
* collision occurs hitp is updated with a fixed point location (precision 3)
|
|
* where the collision happened. The internal calculations are fixed
|
|
* point with a 7 bit fractional precision.
|
|
*
|
|
* If you choose 10 bits of precision a screen size of about 640x480 is the
|
|
* largest this can go. 7 bits allows for an accurate intersection calculation
|
|
* with a line length of about 64 and a rougher line lenght of 128 which is
|
|
* larger than any target currently needs (the pad is the longest line and it
|
|
* only needs an accuracy of 2^4 at most to figure out which section of the pad
|
|
* the ball hit). A precision of 7 gives breathing room for larger screens.
|
|
* Longer line sizes that need accurate intersection points will need more
|
|
* precision, but will decrease the maximum screen resolution.
|
|
*/
|
|
|
|
#define LINE_PREC 7
|
|
static int check_lines(struct line *line1, struct line *line2,
|
|
struct point *hitp)
|
|
{
|
|
/* Introduction:
|
|
* This code is based on the solution of these two input equations:
|
|
* Pa = P1 + ua (P2-P1)
|
|
* Pb = P3 + ub (P4-P3)
|
|
*
|
|
* Where line one is composed of points P1 and P2 and line two is composed
|
|
* of points P3 and P4.
|
|
*
|
|
* ua/b is the fractional value you can multiply the x and y legs of the
|
|
* triangle formed by each line to find a point on the line.
|
|
*
|
|
* The two equations can be expanded to their x/y components:
|
|
* Pa.x = p1.x + ua(p2.x - p1.x)
|
|
* Pa.y = p1.y + ua(p2.y - p1.y)
|
|
*
|
|
* Pb.x = p3.x + ub(p4.x - p3.x)
|
|
* Pb.y = p3.y + ub(p4.y - p3.y)
|
|
*
|
|
* When Pa.x == Pb.x and Pa.y == Pb.y the lines intersect so you can come
|
|
* up with two equations (one for x and one for y):
|
|
*
|
|
* p1.x + ua(p2.x - p1.x) = p3.x + ub(p4.x - p3.x)
|
|
* p1.y + ua(p2.y - p1.y) = p3.y + ub(p4.y - p3.y)
|
|
*
|
|
* ua and ub can then be individually solved for. This results in the
|
|
* equations used in the following code.
|
|
*/
|
|
|
|
/* Denominator for ua and ub are the same so store this calculation */
|
|
int d = FIXED3_MUL((line2->p2.y - line2->p1.y),(line1->p2.x-line1->p1.x))
|
|
-FIXED3_MUL((line2->p2.x - line2->p1.x),(line1->p2.y-line1->p1.y));
|
|
|
|
/* n_a and n_b are calculated as seperate values for readability */
|
|
int n_a = FIXED3_MUL((line2->p2.x - line2->p1.x),(line1->p1.y-line2->p1.y))
|
|
-FIXED3_MUL((line2->p2.y - line2->p1.y),(line1->p1.x-line2->p1.x));
|
|
|
|
int n_b = FIXED3_MUL((line1->p2.x - line1->p1.x),(line1->p1.y-line2->p1.y))
|
|
-FIXED3_MUL((line1->p2.y - line1->p1.y),(line1->p1.x-line2->p1.x));
|
|
|
|
/* Make sure there is not a division by zero - this also indicates that
|
|
* the lines are parallel.
|
|
*
|
|
* If n_a and n_b were both equal to zero the lines would be on top of each
|
|
* other (coincidental). This check is not done because it is not
|
|
* necessary for this implementation (the parallel check accounts for this).
|
|
*/
|
|
if(d == 0)
|
|
return 0;
|
|
|
|
/* Calculate the intermediate fractional point that the lines potentially
|
|
* intersect.
|
|
*/
|
|
int ua = (n_a << LINE_PREC)/d;
|
|
int ub = (n_b << LINE_PREC)/d;
|
|
|
|
/* The fractional point will be between 0 and 1 inclusive if the lines
|
|
* intersect. If the fractional calculation is larger than 1 or smaller
|
|
* than 0 the lines would need to be longer to intersect.
|
|
*/
|
|
if(ua >=0 && ua <= (1<<LINE_PREC) && ub >= 0 && ub <= (1<<LINE_PREC))
|
|
{
|
|
hitp->x = line1->p1.x + ((ua * (line1->p2.x - line1->p1.x))>>LINE_PREC);
|
|
hitp->y = line1->p1.y + ((ua * (line1->p2.y - line1->p1.y))>>LINE_PREC);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int check_rect(struct line *line, struct rect *rect,
|
|
enum intersection intersection, struct point *hitp)
|
|
{
|
|
struct line edge;
|
|
|
|
switch (intersection)
|
|
{
|
|
case INTERSECTION_TOP:
|
|
{
|
|
edge.p1.x = rect->top_left.x;
|
|
edge.p1.y = rect->top_left.y;
|
|
|
|
edge.p2.x = rect->bottom_right.x;
|
|
edge.p2.y = rect->top_left.y;
|
|
|
|
break;
|
|
}
|
|
case INTERSECTION_BOTTOM:
|
|
{
|
|
edge.p1.x = rect->top_left.x;
|
|
edge.p1.y = rect->bottom_right.y;
|
|
|
|
edge.p2.x = rect->bottom_right.x;
|
|
edge.p2.y = rect->bottom_right.y;
|
|
|
|
break;
|
|
}
|
|
case INTERSECTION_LEFT:
|
|
{
|
|
edge.p1.x = rect->top_left.x;
|
|
edge.p1.y = rect->top_left.y;
|
|
|
|
edge.p2.x = rect->top_left.x;
|
|
edge.p2.y = rect->bottom_right.y;
|
|
|
|
break;
|
|
}
|
|
case INTERSECTION_RIGHT:
|
|
{
|
|
edge.p1.x = rect->bottom_right.x;
|
|
edge.p1.y = rect->top_left.y;
|
|
|
|
edge.p2.x = rect->bottom_right.x;
|
|
edge.p2.y = rect->bottom_right.y;
|
|
|
|
break;
|
|
}
|
|
case INTERSECTION_ALL: /* Test hit on all edges */
|
|
{
|
|
return (check_rect(line, rect, INTERSECTION_TOP, hitp) ||
|
|
check_rect(line, rect, INTERSECTION_BOTTOM, hitp) ||
|
|
check_rect(line, rect, INTERSECTION_LEFT, hitp) ||
|
|
check_rect(line, rect, INTERSECTION_RIGHT, hitp));
|
|
}
|
|
}
|
|
|
|
return check_lines(line, &edge, hitp);
|
|
}
|
|
|
|
static void brickmania_init_game(bool new_game)
|
|
{
|
|
int i,j;
|
|
|
|
pad_pos_x = GAMESCREEN_WIDTH/2 - PAD_WIDTH/2;
|
|
|
|
for(i=0;i<MAX_BALLS;i++)
|
|
{
|
|
ball[i].speedx = 0;
|
|
ball[i].speedy = 0;
|
|
ball[i].tempy = 0;
|
|
ball[i].tempx = 0;
|
|
ball[i].pos_y = ON_PAD_POS_Y;
|
|
ball[i].pos_x = GAMESCREEN_WIDTH/2;
|
|
ball[i].glue = false;
|
|
}
|
|
|
|
used_balls = 1;
|
|
used_fires = 0;
|
|
used_powers = 0;
|
|
game_state = ST_READY;
|
|
paddle_type = PADDLE_TYPE_NORMAL;
|
|
pad_width = PAD_WIDTH;
|
|
flip_sides = false;
|
|
flip_sides_delay = FLIP_SIDES_DELAY;
|
|
|
|
if (new_game) {
|
|
brick_on_board=0;
|
|
/* add one life per achieved level */
|
|
if (difficulty==EASY && life<2) {
|
|
score+=SCORE_LEVEL_COMPLETED;
|
|
life++;
|
|
}
|
|
}
|
|
|
|
for(i=0;i<NUM_BRICKS_ROWS;i++) {
|
|
for(j=0;j<NUM_BRICKS_COLS;j++) {
|
|
if (new_game) {
|
|
brick[i][j].hits=levels[level][i][j]>=10?
|
|
levels[level][i][j]/16-1:0;
|
|
brick[i][j].hiteffect=0;
|
|
brick[i][j].used=!(levels[level][i][j]==0);
|
|
brick[i][j].color=(levels[level][i][j]>=10?
|
|
levels[level][i][j]%16:
|
|
levels[level][i][j])-1;
|
|
if (levels[level][i][j]!=0)
|
|
brick_on_board++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void brickmania_loadgame(void)
|
|
{
|
|
int fd;
|
|
|
|
resume = false;
|
|
|
|
/* open game file */
|
|
fd = rb->open(SAVE_FILE, O_RDONLY);
|
|
if(fd < 0) return;
|
|
|
|
/* read in saved game */
|
|
if((rb->read(fd, &pad_pos_x, sizeof(pad_pos_x)) <= 0) ||
|
|
(rb->read(fd, &life, sizeof(life)) <= 0) ||
|
|
(rb->read(fd, &game_state, sizeof(game_state)) <= 0) ||
|
|
(rb->read(fd, &paddle_type, sizeof(paddle_type)) <= 0) ||
|
|
(rb->read(fd, &score, sizeof(score)) <= 0) ||
|
|
(rb->read(fd, &flip_sides, sizeof(flip_sides)) <= 0) ||
|
|
(rb->read(fd, &level, sizeof(level)) <= 0) ||
|
|
(rb->read(fd, &brick_on_board, sizeof(brick_on_board)) <= 0) ||
|
|
(rb->read(fd, &used_balls, sizeof(used_balls)) <= 0) ||
|
|
(rb->read(fd, &used_fires, sizeof(used_fires)) <= 0) ||
|
|
(rb->read(fd, &used_powers, sizeof(used_powers)) <= 0) ||
|
|
(rb->read(fd, &pad_width, sizeof(pad_width)) <= 0) ||
|
|
(rb->read(fd, &flip_sides_delay, sizeof(flip_sides_delay)) <= 0) ||
|
|
(rb->read(fd, &brick, sizeof(brick)) <= 0) ||
|
|
(rb->read(fd, &ball, sizeof(ball)) <= 0) ||
|
|
(rb->read(fd, &fire, sizeof(fire)) <= 0) ||
|
|
(rb->read(fd, &power, sizeof(power)) <= 0))
|
|
{
|
|
rb->splash(HZ/2, "Failed to load game");
|
|
}
|
|
else
|
|
{
|
|
vscore = score;
|
|
resume = true;
|
|
}
|
|
|
|
rb->close(fd);
|
|
|
|
return;
|
|
}
|
|
|
|
static void brickmania_savegame(void)
|
|
{
|
|
int fd;
|
|
|
|
/* write out the game state to the save file */
|
|
fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT, 0666);
|
|
if(fd < 0) return;
|
|
|
|
if ((rb->write(fd, &pad_pos_x, sizeof(pad_pos_x)) <= 0) ||
|
|
(rb->write(fd, &life, sizeof(life)) <= 0) ||
|
|
(rb->write(fd, &game_state, sizeof(game_state)) <= 0) ||
|
|
(rb->write(fd, &paddle_type, sizeof(paddle_type)) <= 0) ||
|
|
(rb->write(fd, &score, sizeof(score)) <= 0) ||
|
|
(rb->write(fd, &flip_sides, sizeof(flip_sides)) <= 0) ||
|
|
(rb->write(fd, &level, sizeof(level)) <= 0) ||
|
|
(rb->write(fd, &brick_on_board, sizeof(brick_on_board)) <= 0) ||
|
|
(rb->write(fd, &used_balls, sizeof(used_balls)) <= 0) ||
|
|
(rb->write(fd, &used_fires, sizeof(used_fires)) <= 0) ||
|
|
(rb->write(fd, &used_powers, sizeof(used_powers)) <= 0) ||
|
|
(rb->write(fd, &pad_width, sizeof(pad_width)) <= 0) ||
|
|
(rb->write(fd, &flip_sides_delay, sizeof(flip_sides_delay)) <= 0) ||
|
|
(rb->write(fd, &brick, sizeof(brick)) <= 0) ||
|
|
(rb->write(fd, &ball, sizeof(ball)) <= 0) ||
|
|
(rb->write(fd, &fire, sizeof(fire)) <= 0) ||
|
|
(rb->write(fd, &power, sizeof(power)) <= 0))
|
|
{
|
|
rb->close(fd);
|
|
rb->remove(SAVE_FILE);
|
|
rb->splash(HZ/2, "Failed to save game");
|
|
return;
|
|
}
|
|
|
|
rb->close(fd);
|
|
}
|
|
|
|
/* brickmania_sleep timer counting the score */
|
|
static void brickmania_sleep(int secs)
|
|
{
|
|
bool done=false;
|
|
char s[20];
|
|
int count=0;
|
|
int sw, w;
|
|
|
|
while (!done)
|
|
{
|
|
if (count == 0)
|
|
count = *rb->current_tick + HZ*secs;
|
|
if ( (TIME_AFTER(*rb->current_tick, count)) && (vscore == score) )
|
|
done = true;
|
|
|
|
if(vscore != score)
|
|
{
|
|
if (vscore<score)
|
|
vscore++;
|
|
if (vscore>score)
|
|
vscore--;
|
|
rb->snprintf(s, sizeof(s), "%d", vscore);
|
|
rb->lcd_getstringsize(s, &sw, &w);
|
|
rb->lcd_putsxy(LCD_WIDTH/2-sw/2, 0, s);
|
|
rb->lcd_update_rect(0,0,LCD_WIDTH,w+2);
|
|
}
|
|
rb->yield();
|
|
}
|
|
}
|
|
|
|
static int brickmania_help(void)
|
|
{
|
|
static char *help_text[] = {
|
|
"Brickmania", "", "Aim", "",
|
|
"Destroy", "all", "the", "bricks", "by", "bouncing",
|
|
"the", "ball", "of", "them", "using", "the", "paddle.", "", "",
|
|
"Controls", "",
|
|
#if CONFIG_KEYPAD == COWON_D2_PAD
|
|
"- & +:",
|
|
#else
|
|
"< & >:",
|
|
#endif
|
|
"Moves", "the", "paddle", "",
|
|
#if CONFIG_KEYPAD == ONDIO_PAD
|
|
"MENU:",
|
|
#elif (CONFIG_KEYPAD == RECORDER_PAD) || (CONFIG_KEYPAD == IAUDIO_M3_PAD)
|
|
"PLAY:",
|
|
#elif CONFIG_KEYPAD == IRIVER_H300_PAD
|
|
"NAVI:",
|
|
#elif CONFIG_KEYPAD == COWON_D2_PAD
|
|
"MENU:",
|
|
#else
|
|
"SELECT:",
|
|
#endif
|
|
"Releases", "the", "ball/Fire!", "",
|
|
#if CONFIG_KEYPAD == IAUDIO_M3_PAD
|
|
"REC:",
|
|
#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \
|
|
(CONFIG_KEYPAD == CREATIVEZVM_PAD)
|
|
"BACK:",
|
|
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
|
|
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
|
|
(CONFIG_KEYPAD == IPOD_1G2G_PAD) || \
|
|
(CONFIG_KEYPAD == SANSA_FUZE_PAD)
|
|
"MENU:",
|
|
#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
|
|
(CONFIG_KEYPAD == IRIVER_H300_PAD) || \
|
|
(CONFIG_KEYPAD == ONDIO_PAD) || \
|
|
(CONFIG_KEYPAD == RECORDER_PAD) || \
|
|
(CONFIG_KEYPAD == ARCHOS_AV300_PAD)
|
|
"STOP:",
|
|
#else
|
|
"POWER:",
|
|
#endif
|
|
"Returns", "to", "menu", "", "",
|
|
"Specials", "",
|
|
"N", "Normal:", "returns", "paddle", "to", "normal", "",
|
|
"D", "DIE!:", "loses", "a", "life", "",
|
|
"L", "Life:", "gains", "a", "life/power", "up", "",
|
|
"F", "Fire:", "allows", "you", "to", "shoot", "bricks", "",
|
|
"G", "Glue:", "ball", "sticks", "to", "paddle", "",
|
|
"B", "Ball:", "generates", "another", "ball", "",
|
|
"FL", "Flip:", "flips", "left / right", "movement", "",
|
|
"<->", "or", "<E>:", "enlarges", "the", "paddle", "",
|
|
">-<", "or", ">S<:", "shrinks", "the", "paddle", "",
|
|
};
|
|
static struct style_text formation[]={
|
|
{ 0, TEXT_CENTER|TEXT_UNDERLINE },
|
|
{ 2, C_RED },
|
|
{ 19, C_RED },
|
|
{ 37, C_RED },
|
|
{ 39, C_BLUE },
|
|
{ 46, C_RED },
|
|
{ 52, C_GREEN },
|
|
{ 59, C_ORANGE },
|
|
{ 67, C_GREEN },
|
|
{ 74, C_YELLOW },
|
|
{ 80, C_RED },
|
|
LAST_STYLE_ITEM
|
|
};
|
|
|
|
rb->lcd_setfont(FONT_UI);
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_set_background(LCD_BLACK);
|
|
rb->lcd_set_foreground(LCD_WHITE);
|
|
#endif
|
|
if (display_text(ARRAYLEN(help_text), help_text, formation, NULL, true))
|
|
return 1;
|
|
rb->lcd_setfont(FONT_SYSFIXED);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int brickmania_menu_cb(int action, const struct menu_item_ex *this_item)
|
|
{
|
|
int i = ((intptr_t)this_item);
|
|
if(action == ACTION_REQUEST_MENUITEM
|
|
&& !resume && (i==0 || i==6))
|
|
return ACTION_EXIT_MENUITEM;
|
|
return action;
|
|
}
|
|
|
|
static int brickmania_menu(void)
|
|
{
|
|
int selected = 0;
|
|
|
|
static struct opt_items options[] = {
|
|
{ "Easy", -1 },
|
|
{ "Normal", -1 },
|
|
};
|
|
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
/* Entering Menu, set the touchscreen to the global setting */
|
|
rb->touchscreen_set_mode(rb->global_settings->touch_mode);
|
|
#endif
|
|
|
|
MENUITEM_STRINGLIST(main_menu, "Brickmania Menu", brickmania_menu_cb,
|
|
"Resume Game", "Start New Game",
|
|
"Difficulty", "Help", "High Scores",
|
|
"Playback Control",
|
|
"Quit without Saving", "Quit");
|
|
|
|
rb->button_clear_queue();
|
|
while (true) {
|
|
switch (rb->do_menu(&main_menu, &selected, NULL, false)) {
|
|
case 0:
|
|
if(game_state!=ST_READY)
|
|
game_state = ST_PAUSE;
|
|
if(resume_file)
|
|
rb->remove(SAVE_FILE);
|
|
return 0;
|
|
case 1:
|
|
score=0;
|
|
vscore=0;
|
|
life=2;
|
|
level=0;
|
|
brickmania_init_game(true);
|
|
return 0;
|
|
case 2:
|
|
rb->set_option("Difficulty", &difficulty, INT,
|
|
options, 2, NULL);
|
|
break;
|
|
case 3:
|
|
if (brickmania_help())
|
|
return 1;
|
|
break;
|
|
case 4:
|
|
highscore_show(-1, highscores, NUM_SCORES, true);
|
|
break;
|
|
case 5:
|
|
if (playback_control(NULL))
|
|
return 1;
|
|
break;
|
|
case 6:
|
|
return 1;
|
|
case 7:
|
|
if (resume) {
|
|
rb->splash(HZ*1, "Saving game ...");
|
|
brickmania_savegame();
|
|
}
|
|
return 1;
|
|
case MENU_ATTACHED_USB:
|
|
return 1;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
rb->touchscreen_set_mode(TOUCHSCREEN_POINT);
|
|
#endif
|
|
}
|
|
|
|
static void brick_hit(int i, int j)
|
|
{
|
|
if(!brick[i][j].used)
|
|
return;
|
|
|
|
/* if this is a crackable brick hits starts as
|
|
* greater than 0.
|
|
*/
|
|
if (brick[i][j].hits > 0) {
|
|
brick[i][j].hits--;
|
|
brick[i][j].hiteffect++;
|
|
score+=SCORE_BALL_HIT_BRICK;
|
|
}
|
|
else {
|
|
brick[i][j].used=false;
|
|
if (used_powers<MAX_POWERS)
|
|
{
|
|
int ran = rb->rand()%POWER_RAND;
|
|
|
|
if (ran<NUMBER_OF_POWERUPS)
|
|
{
|
|
power[used_powers].top = TOPMARGIN + i*BRICK_HEIGHT;
|
|
power[used_powers].x_pos = LEFTMARGIN + j*BRICK_WIDTH +
|
|
(BRICK_WIDTH >> 1);
|
|
power[used_powers].type = ran;
|
|
used_powers++;
|
|
}
|
|
}
|
|
brick_on_board--;
|
|
score+=SCORE_BALL_DEMOLISHED_BRICK;
|
|
}
|
|
}
|
|
|
|
static int brickmania_game_loop(void)
|
|
{
|
|
int j,i,k;
|
|
int sw, sh;
|
|
char s[30];
|
|
int sec_count=0;
|
|
int end;
|
|
|
|
/* pad_rect used for powerup/ball checks */
|
|
struct rect pad_rect;
|
|
/* This is used for various lines that are checked (ball and powerup) */
|
|
struct line misc_line;
|
|
|
|
/* This stores the point that the two lines intersected in a test */
|
|
struct point pt_hit;
|
|
|
|
if (brickmania_menu()) {
|
|
return 1;
|
|
}
|
|
resume = false;
|
|
resume_file = false;
|
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_set_background(LCD_BLACK);
|
|
rb->lcd_set_foreground(LCD_WHITE);
|
|
rb->lcd_set_drawmode(DRMODE_SOLID);
|
|
rb->lcd_clear_display();
|
|
#endif
|
|
|
|
while(true) {
|
|
/* Convert CYCLETIME (in ms) to HZ */
|
|
end = *rb->current_tick + (CYCLETIME * HZ) / 1000;
|
|
|
|
if (life >= 0) {
|
|
rb->lcd_clear_display();
|
|
|
|
if (flip_sides)
|
|
{
|
|
if (TIME_AFTER(*rb->current_tick, sec_count))
|
|
{
|
|
sec_count=*rb->current_tick+HZ;
|
|
if (flip_sides_delay > 1)
|
|
flip_sides_delay--;
|
|
else
|
|
flip_sides=false;
|
|
}
|
|
rb->snprintf(s, sizeof(s), "%d", flip_sides_delay);
|
|
rb->lcd_getstringsize(s, &sw, NULL);
|
|
rb->lcd_putsxy(LCD_WIDTH/2-2, INT3(STRINGPOS_FLIP), s);
|
|
}
|
|
|
|
|
|
if (vscore<score) vscore++;
|
|
rb->snprintf(s, sizeof(s), "%d", vscore);
|
|
rb->lcd_getstringsize(s, &sw, NULL);
|
|
rb->lcd_putsxy(LCD_WIDTH/2-sw/2, 0, s);
|
|
|
|
/* write life num */
|
|
rb->snprintf(s, sizeof(s), "Life: %d", life);
|
|
|
|
/* hijack i */
|
|
i = sw;
|
|
rb->lcd_getstringsize(s, &sw, NULL);
|
|
if (sw >= (LCD_WIDTH/2-i/2))
|
|
rb->snprintf(s, sizeof(s), "L: %d", life);
|
|
rb->lcd_putsxy(0, 0, s);
|
|
|
|
/* write level */
|
|
rb->snprintf(s, sizeof(s), "Level %d", level+1);
|
|
rb->lcd_getstringsize(s, &sw, NULL);
|
|
|
|
if (LCD_WIDTH-sw <= (LCD_WIDTH/2+i/2)+1)
|
|
{
|
|
rb->snprintf(s, sizeof(s), "Lvl %d", level+1);
|
|
rb->lcd_getstringsize(s, &sw, NULL);
|
|
}
|
|
|
|
rb->lcd_putsxy(LCD_WIDTH-sw, 0, s);
|
|
i = 0;
|
|
|
|
/* continue game */
|
|
if (game_state == ST_PAUSE)
|
|
{
|
|
rb->snprintf(s, sizeof(s), CONTINUE_TEXT);
|
|
rb->lcd_getstringsize(s, &sw, NULL);
|
|
rb->lcd_putsxy(LCD_WIDTH/2-sw/2, INT3(STRINGPOS_NAVI), s);
|
|
|
|
sec_count=*rb->current_tick+HZ;
|
|
}
|
|
|
|
/* draw the ball */
|
|
for(i=0;i<used_balls;i++)
|
|
rb->lcd_bitmap(brickmania_ball,
|
|
INT3(ball[i].pos_x - HALFBALL),
|
|
INT3(ball[i].pos_y - HALFBALL),
|
|
INT3(BALL), INT3(BALL));
|
|
|
|
if (brick_on_board==0)
|
|
brick_on_board--;
|
|
|
|
/* Setup the pad line-later used in intersection test */
|
|
pad_rect.top_left.x = pad_pos_x;
|
|
pad_rect.top_left.y = PAD_POS_Y;
|
|
|
|
pad_rect.bottom_right.x = pad_pos_x + pad_width;
|
|
pad_rect.bottom_right.y = PAD_POS_Y + PAD_HEIGHT;
|
|
|
|
if (game_state!=ST_PAUSE)
|
|
{
|
|
/* move the fires */
|
|
for(k=0;k<used_fires;k++)
|
|
{
|
|
fire[k].top -= SPEED_FIRE;
|
|
if (fire[k].top < 0)
|
|
{
|
|
used_fires--;
|
|
fire[k].top = fire[used_fires].top;
|
|
fire[k].x_pos = fire[used_fires].x_pos;
|
|
k--;
|
|
}
|
|
else if (fire[k].x_pos >= LEFTMARGIN &&
|
|
fire[k].x_pos < LEFTMARGIN + NUM_BRICKS_COLS * BRICK_WIDTH)
|
|
{
|
|
j = (fire[k].x_pos - LEFTMARGIN) / BRICK_WIDTH;
|
|
for (i=NUM_BRICKS_ROWS-1;i>=0;i--)
|
|
{
|
|
if (TOPMARGIN + i*BRICK_HEIGHT<=fire[k].top)
|
|
break;
|
|
if (brick[i][j].used)
|
|
{
|
|
score += SCORE_FIRE_HIT_BRICK;
|
|
brick_hit(i, j);
|
|
used_fires--;
|
|
fire[k].top = fire[used_fires].top;
|
|
fire[k].x_pos = fire[used_fires].x_pos;
|
|
k--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* move and handle the powerups */
|
|
for (k=0;k<used_powers;k++)
|
|
{
|
|
int remove_power = 0;
|
|
|
|
power[k].top += SPEED_POWER;
|
|
|
|
if (power[k].top > PAD_POS_Y)
|
|
{
|
|
/* power hit bottom */
|
|
remove_power = 1;
|
|
}
|
|
else
|
|
{
|
|
/* Use misc_line to check if the center of the powerup
|
|
* hit the paddle.
|
|
*/
|
|
misc_line.p1.x = power[k].x_pos;
|
|
misc_line.p1.y = power[k].top;
|
|
|
|
misc_line.p2 = misc_line.p1;
|
|
misc_line.p2.y += SPEED_POWER;
|
|
|
|
/* Check if the powerup will hit the paddle */
|
|
if (check_rect(&misc_line, &pad_rect, INTERSECTION_ALL,
|
|
&pt_hit))
|
|
{
|
|
|
|
/* power hit paddle */
|
|
remove_power = 1;
|
|
switch(power[k].type)
|
|
{
|
|
case POWER_TYPE_LIFE_GAIN:
|
|
life++;
|
|
score += SCORE_POWER_LIFE_GAIN;
|
|
break;
|
|
case POWER_TYPE_LIFE_LOSS:
|
|
life--;
|
|
if (life>=0)
|
|
{
|
|
brickmania_init_game(false);
|
|
brickmania_sleep(2);
|
|
}
|
|
break;
|
|
case POWER_TYPE_PADDLE_STICKY:
|
|
score += SCORE_POWER_PADDLE_STICKY;
|
|
paddle_type = PADDLE_TYPE_STICKY;
|
|
break;
|
|
case POWER_TYPE_PADDLE_SHOOTER:
|
|
score += SCORE_POWER_PADDLE_SHOOTER;
|
|
paddle_type = PADDLE_TYPE_SHOOTER;
|
|
for(i=0;i<used_balls;i++)
|
|
ball[i].glue=false;
|
|
break;
|
|
case POWER_TYPE_PADDLE_NORMAL:
|
|
score += SCORE_POWER_PADDLE_NORMAL;
|
|
paddle_type = PADDLE_TYPE_NORMAL;
|
|
for(i=0;i<used_balls;i++)
|
|
ball[i].glue=false;
|
|
flip_sides=false;
|
|
pad_pos_x += (pad_width-PAD_WIDTH)/2;
|
|
pad_width = PAD_WIDTH;
|
|
break;
|
|
case POWER_TYPE_PADDLE_FLIP:
|
|
score += SCORE_POWER_FLIP;
|
|
sec_count = *rb->current_tick+HZ;
|
|
flip_sides_delay = FLIP_SIDES_DELAY;
|
|
flip_sides = true;
|
|
break;
|
|
case POWER_TYPE_EXTRA_BALL:
|
|
score += SCORE_POWER_EXTRA_BALL;
|
|
if(used_balls<MAX_BALLS)
|
|
{
|
|
/* Set the speed */
|
|
if(rb->rand()%2 == 0)
|
|
ball[used_balls].speedx=-SPEED_4Q_X;
|
|
else
|
|
ball[used_balls].speedx= SPEED_4Q_X;
|
|
ball[used_balls].speedy= SPEED_4Q_Y;
|
|
/* Ball is not glued */
|
|
ball[used_balls].glue= false;
|
|
used_balls++;
|
|
}
|
|
break;
|
|
case POWER_TYPE_PADDLE_LONG:
|
|
score+=SCORE_POWER_LONG_PADDLE;
|
|
if (pad_width==PAD_WIDTH)
|
|
{
|
|
pad_width = LONG_PAD_WIDTH;
|
|
pad_pos_x -= (LONG_PAD_WIDTH -
|
|
PAD_WIDTH)/2;
|
|
}
|
|
else if (pad_width==SHORT_PAD_WIDTH)
|
|
{
|
|
pad_width = PAD_WIDTH;
|
|
pad_pos_x-=(PAD_WIDTH-
|
|
SHORT_PAD_WIDTH)/2;
|
|
}
|
|
if (pad_pos_x < 0)
|
|
pad_pos_x = 0;
|
|
else if(pad_pos_x + pad_width >
|
|
GAMESCREEN_WIDTH)
|
|
pad_pos_x = GAMESCREEN_WIDTH-pad_width;
|
|
break;
|
|
case POWER_TYPE_PADDLE_SHORT:
|
|
if (pad_width==PAD_WIDTH)
|
|
{
|
|
pad_width=SHORT_PAD_WIDTH;
|
|
pad_pos_x+=(PAD_WIDTH-
|
|
SHORT_PAD_WIDTH)/2;
|
|
}
|
|
else if (pad_width==LONG_PAD_WIDTH)
|
|
{
|
|
pad_width=PAD_WIDTH;
|
|
pad_pos_x+=(LONG_PAD_WIDTH-PAD_WIDTH)/2;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (remove_power)
|
|
{
|
|
used_powers--;
|
|
if (k != used_powers)
|
|
{
|
|
power[k].top = power[used_powers].top;
|
|
power[k].x_pos = power[used_powers].x_pos;
|
|
power[k].type = power[used_powers].type;
|
|
}
|
|
k--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* draw the fires */
|
|
for(k=0;k<used_fires;k++)
|
|
{
|
|
rb->lcd_vline(INT3(fire[k].x_pos), INT3(fire[k].top),
|
|
INT3(fire[k].top + FIRE_LENGTH));
|
|
}
|
|
|
|
/* draw the powerups */
|
|
for(k=0;k<used_powers;k++)
|
|
{
|
|
rb->lcd_bitmap_part(brickmania_powerups,0,
|
|
INT3(POWERUP_HEIGHT)*power[k].type,
|
|
STRIDE(SCREEN_MAIN, BMPWIDTH_brickmania_powerups,
|
|
BMPHEIGHT_brickmania_powerups),
|
|
INT3(power[k].x_pos - (POWERUP_WIDTH >> 1)),
|
|
INT3(power[k].top), INT3(POWERUP_WIDTH),
|
|
INT3(POWERUP_HEIGHT));
|
|
}
|
|
|
|
/* handle all of the bricks */
|
|
for (i=0; i<NUM_BRICKS_ROWS; i++)
|
|
{
|
|
for (j=0; j<NUM_BRICKS_COLS ;j++)
|
|
{
|
|
int brickx,bricky;
|
|
|
|
/* The brick is a brick, but it may or may not be in use */
|
|
if(brick[i][j].used)
|
|
{
|
|
struct rect brick_rect;
|
|
|
|
brickx = LEFTMARGIN + j*BRICK_WIDTH;
|
|
bricky = TOPMARGIN + i*BRICK_HEIGHT;
|
|
|
|
brick_rect.top_left.x = brickx;
|
|
brick_rect.top_left.y = bricky;
|
|
|
|
brick_rect.bottom_right.x = brickx + BRICK_WIDTH;
|
|
brick_rect.bottom_right.y = bricky + BRICK_HEIGHT;
|
|
|
|
/* Draw the brick */
|
|
rb->lcd_bitmap_part(brickmania_bricks,0,
|
|
INT3(BRICK_HEIGHT)*brick[i][j].color,
|
|
STRIDE( SCREEN_MAIN,
|
|
BMPWIDTH_brickmania_bricks,
|
|
BMPHEIGHT_brickmania_bricks),
|
|
INT3(brickx),
|
|
INT3(bricky),
|
|
INT3(BRICK_WIDTH), INT3(BRICK_HEIGHT) );
|
|
|
|
#ifdef HAVE_LCD_COLOR /* No transparent effect for greyscale lcds for now */
|
|
if (brick[i][j].hiteffect > 0)
|
|
rb->lcd_bitmap_transparent_part(brickmania_break,0,
|
|
INT3(BRICK_HEIGHT)*brick[i][j].hiteffect,
|
|
STRIDE( SCREEN_MAIN,
|
|
BMPWIDTH_brickmania_break,
|
|
BMPHEIGHT_brickmania_break),
|
|
INT3(brickx),
|
|
INT3(bricky),
|
|
INT3(BRICK_WIDTH), INT3(BRICK_HEIGHT) );
|
|
#endif
|
|
|
|
/* Check if any balls collided with the brick */
|
|
for(k=0; k<used_balls; k++)
|
|
{
|
|
int hit = 0;
|
|
|
|
/* Setup the ball path to describe the current ball
|
|
* position and the line it makes to its next
|
|
* position.
|
|
*/
|
|
misc_line.p1.x = ball[k].pos_x;
|
|
misc_line.p1.y = ball[k].pos_y;
|
|
|
|
misc_line.p2.x = ball[k].pos_x + ball[k].speedx;
|
|
misc_line.p2.y = ball[k].pos_y + ball[k].speedy;
|
|
|
|
/* Check to see if the ball and the bottom hit. If
|
|
* the ball is moving down we don't want to
|
|
* include the bottom line intersection.
|
|
*
|
|
* The order that the sides are checked matters.
|
|
*
|
|
* Note that tempx/tempy store the next position
|
|
* that the ball should be drawn.
|
|
*/
|
|
if (ball[k].speedy <= 0 && check_rect(&misc_line,
|
|
&brick_rect, INTERSECTION_BOTTOM, &pt_hit))
|
|
{
|
|
ball[k].speedy = -ball[k].speedy;
|
|
hit = 1;
|
|
}
|
|
/* Check the top, if the ball is moving up dont
|
|
* count it as a hit.
|
|
*/
|
|
else if (ball[k].speedy > 0 && check_rect(&misc_line,
|
|
&brick_rect, INTERSECTION_TOP, &pt_hit))
|
|
{
|
|
ball[k].speedy = -ball[k].speedy;
|
|
hit = 1;
|
|
}
|
|
/* Check the left side of the brick */
|
|
else if (check_rect(&misc_line, &brick_rect,
|
|
INTERSECTION_LEFT, &pt_hit))
|
|
{
|
|
ball[k].speedx = -ball[k].speedx;
|
|
hit = 1;
|
|
}
|
|
/* Check the right side of the brick */
|
|
else if (check_rect(&misc_line, &brick_rect,
|
|
INTERSECTION_RIGHT, &pt_hit))
|
|
{
|
|
ball[k].speedx = -ball[k].speedx;
|
|
hit = 1;
|
|
}
|
|
|
|
if (hit)
|
|
{
|
|
ball[k].tempy = pt_hit.y;
|
|
ball[k].tempx = pt_hit.x;
|
|
brick_hit(i, j);
|
|
break;
|
|
}
|
|
} /* for k */
|
|
} /* if(used) */
|
|
|
|
} /* for j */
|
|
} /* for i */
|
|
|
|
/* draw the paddle according to the PAD_WIDTH */
|
|
if( pad_width == PAD_WIDTH ) /* Normal width */
|
|
{
|
|
rb->lcd_bitmap_part(
|
|
brickmania_pads,
|
|
0, paddle_type*INT3(PAD_HEIGHT),
|
|
STRIDE( SCREEN_MAIN, BMPWIDTH_brickmania_pads,
|
|
BMPHEIGHT_brickmania_pads),
|
|
INT3(pad_pos_x), INT3(PAD_POS_Y),
|
|
INT3(pad_width), INT3(PAD_HEIGHT) );
|
|
}
|
|
else if( pad_width == LONG_PAD_WIDTH ) /* Long Pad */
|
|
{
|
|
rb->lcd_bitmap_part(
|
|
brickmania_long_pads,
|
|
0,paddle_type*INT3(PAD_HEIGHT),
|
|
STRIDE( SCREEN_MAIN, BMPWIDTH_brickmania_long_pads,
|
|
BMPHEIGHT_brickmania_long_pads),
|
|
INT3(pad_pos_x), INT3(PAD_POS_Y),
|
|
INT3(pad_width), INT3(PAD_HEIGHT) );
|
|
}
|
|
else /* Short pad */
|
|
{
|
|
rb->lcd_bitmap_part(
|
|
brickmania_short_pads,
|
|
0,paddle_type*INT3(PAD_HEIGHT),
|
|
STRIDE( SCREEN_MAIN, BMPWIDTH_brickmania_short_pads,
|
|
BMPHEIGHT_brickmania_short_pads),
|
|
INT3(pad_pos_x), INT3(PAD_POS_Y),
|
|
INT3(pad_width), INT3(PAD_HEIGHT) );
|
|
}
|
|
|
|
/* If the game is not paused continue */
|
|
if (game_state!=ST_PAUSE)
|
|
{
|
|
/* Loop through all of the balls in play */
|
|
for(k=0;k<used_balls;k++)
|
|
{
|
|
struct line screen_edge;
|
|
|
|
/* Describe the ball movement for the edge collision detection */
|
|
misc_line.p1.x = ball[k].pos_x;
|
|
misc_line.p1.y = ball[k].pos_y;
|
|
|
|
misc_line.p2.x = ball[k].pos_x + ball[k].speedx;
|
|
misc_line.p2.y = ball[k].pos_y + ball[k].speedy;
|
|
|
|
/* Did the Ball hit the top of the screen? */
|
|
screen_edge.p1.x = 0;
|
|
screen_edge.p1.y = 0;
|
|
|
|
screen_edge.p2.x = GAMESCREEN_WIDTH;
|
|
screen_edge.p2.y = 0;
|
|
/* the test for pos_y prevents the ball from bouncing back
|
|
* from _over_ the top to infinity on some rare cases */
|
|
if (ball[k].pos_y > 0 &&
|
|
check_lines(&misc_line, &screen_edge, &pt_hit))
|
|
{
|
|
ball[k].tempy = pt_hit.y + 1;
|
|
ball[k].tempx = pt_hit.x;
|
|
/* Reverse the direction */
|
|
ball[k].speedy = -ball[k].speedy;
|
|
}
|
|
|
|
/* Player missed the ball and hit bottom of screen */
|
|
if (ball[k].pos_y >= GAMESCREEN_HEIGHT)
|
|
{
|
|
/* Player had balls to spare, so handle the removal */
|
|
if (used_balls>1)
|
|
{
|
|
/* decrease number of balls in play */
|
|
used_balls--;
|
|
/* Replace removed ball with the last ball */
|
|
ball[k].pos_x = ball[used_balls].pos_x;
|
|
ball[k].pos_y = ball[used_balls].pos_y;
|
|
ball[k].speedy = ball[used_balls].speedy;
|
|
ball[k].tempy = ball[used_balls].tempy;
|
|
ball[k].speedx = ball[used_balls].speedx;
|
|
ball[k].tempx = ball[used_balls].tempx;
|
|
ball[k].glue = ball[used_balls].glue;
|
|
|
|
/* Reset the last ball that was removed */
|
|
ball[used_balls].speedx=0;
|
|
ball[used_balls].speedy=0;
|
|
ball[used_balls].tempy=0;
|
|
ball[used_balls].tempx=0;
|
|
ball[used_balls].pos_y=ON_PAD_POS_Y;
|
|
ball[used_balls].pos_x=pad_pos_x+(pad_width/2)-HALFBALL;
|
|
|
|
k--;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
/* Player lost a life */
|
|
life--;
|
|
if (life>=0)
|
|
{
|
|
/* No lives left reset game */
|
|
brickmania_init_game(false);
|
|
brickmania_sleep(2);
|
|
rb->button_clear_queue();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (game_state != ST_READY && !ball[k].glue)
|
|
{
|
|
/* Check if the ball hit the left side */
|
|
screen_edge.p1.x = 0;
|
|
screen_edge.p1.y = 0;
|
|
|
|
screen_edge.p2.x = 0;
|
|
screen_edge.p2.y = GAMESCREEN_HEIGHT;
|
|
if (check_lines(&misc_line, &screen_edge, &pt_hit))
|
|
{
|
|
/* Reverse direction */
|
|
ball[k].speedx = abs(ball[k].speedx);
|
|
|
|
/* Re-position ball in gameboard */
|
|
ball[k].tempy = pt_hit.y;
|
|
ball[k].tempx = 0;
|
|
}
|
|
|
|
/* Check if the ball hit the right side */
|
|
screen_edge.p1.x = GAMESCREEN_WIDTH;
|
|
screen_edge.p1.y = 0;
|
|
|
|
screen_edge.p2.x = GAMESCREEN_WIDTH;
|
|
screen_edge.p2.y = GAMESCREEN_HEIGHT;
|
|
if (check_lines(&misc_line, &screen_edge, &pt_hit))
|
|
{
|
|
/* Reverse direction */
|
|
ball[k].speedx = -abs(ball[k].speedx);
|
|
|
|
/* Re-position ball in gameboard */
|
|
ball[k].tempy = pt_hit.y;
|
|
ball[k].tempx = GAMESCREEN_WIDTH - FIXED3(1);
|
|
}
|
|
|
|
/* Did the ball hit the paddle? Depending on where the ball
|
|
* Hit set the x/y speed appropriately.
|
|
*/
|
|
if(check_rect(&misc_line, &pad_rect, INTERSECTION_TOP,
|
|
&pt_hit) )
|
|
{
|
|
/* Re-position ball based on collision */
|
|
ball[k].tempy = ON_PAD_POS_Y;
|
|
ball[k].tempx = pt_hit.x;
|
|
|
|
/* Calculate the ball position relative to the paddle width */
|
|
int ball_repos = pt_hit.x - pad_pos_x;
|
|
/* If the ball hits the right half of paddle, x speed
|
|
* should be positive, if it hits the left half it
|
|
* should be negative.
|
|
*/
|
|
int x_direction = -1;
|
|
|
|
/* Comparisons are done with respect to 1/2 pad_width */
|
|
if(ball_repos > pad_width/2)
|
|
{
|
|
/* flip the relative position */
|
|
ball_repos -= ((ball_repos - pad_width/2) << 1);
|
|
/* Ball hit the right half so X speed calculations
|
|
* should be positive.
|
|
*/
|
|
x_direction = 1;
|
|
}
|
|
|
|
/* Figure out where the ball hit relative to 1/2 pad
|
|
* and in divisions of 4.
|
|
*/
|
|
ball_repos = ball_repos / (pad_width/2/4);
|
|
|
|
switch(ball_repos)
|
|
{
|
|
/* Ball hit the outer edge of the paddle */
|
|
case 0:
|
|
ball[k].speedy = SPEED_1Q_Y;
|
|
ball[k].speedx = SPEED_1Q_X * x_direction;
|
|
break;
|
|
/* Ball hit the next fourth of the paddle */
|
|
case 1:
|
|
ball[k].speedy = SPEED_2Q_Y;
|
|
ball[k].speedx = SPEED_2Q_X * x_direction;
|
|
break;
|
|
/* Ball hit the third fourth of the paddle */
|
|
case 2:
|
|
ball[k].speedy = SPEED_3Q_Y;
|
|
ball[k].speedx = SPEED_3Q_X * x_direction;
|
|
break;
|
|
/* Ball hit the fourth fourth of the paddle or dead
|
|
* center.
|
|
*/
|
|
case 3:
|
|
case 4:
|
|
ball[k].speedy = SPEED_4Q_Y;
|
|
/* Since this is the middle we don't want to
|
|
* force the ball in a different direction.
|
|
* Just keep it going in the same direction
|
|
* with a specific speed.
|
|
*/
|
|
if(ball[k].speedx > 0)
|
|
{
|
|
ball[k].speedx = SPEED_4Q_X;
|
|
}
|
|
else
|
|
{
|
|
ball[k].speedx = -SPEED_4Q_X;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ball[k].speedy = SPEED_4Q_Y;
|
|
break;
|
|
}
|
|
|
|
if(paddle_type == PADDLE_TYPE_STICKY)
|
|
{
|
|
ball[k].speedy = -ball[k].speedy;
|
|
ball[k].glue=true;
|
|
|
|
/* X location should not be forced since that is moved with the paddle. The Y
|
|
* position should be forced to keep the ball at the paddle.
|
|
*/
|
|
ball[k].tempx = 0;
|
|
ball[k].tempy = ON_PAD_POS_Y;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Update the ball position */
|
|
if (!ball[k].glue)
|
|
{
|
|
if(ball[k].tempx)
|
|
ball[k].pos_x = ball[k].tempx;
|
|
else
|
|
ball[k].pos_x += ball[k].speedx;
|
|
|
|
if(ball[k].tempy)
|
|
ball[k].pos_y = ball[k].tempy;
|
|
else
|
|
ball[k].pos_y += ball[k].speedy;
|
|
|
|
ball[k].tempy=0;
|
|
ball[k].tempx=0;
|
|
}
|
|
} /* for k */
|
|
}
|
|
|
|
rb->lcd_update();
|
|
|
|
if (brick_on_board < 0)
|
|
{
|
|
if (level+1<NUM_LEVELS)
|
|
{
|
|
level++;
|
|
if (difficulty==NORMAL)
|
|
score+=SCORE_LEVEL_COMPLETED;
|
|
brickmania_init_game(true);
|
|
brickmania_sleep(2);
|
|
rb->button_clear_queue();
|
|
}
|
|
else
|
|
{
|
|
rb->lcd_getstringsize("Congratulations!", &sw, &sh);
|
|
rb->lcd_putsxy(LCD_WIDTH/2-sw/2, INT3(STRINGPOS_FINISH) - 2 * sh,
|
|
"Congratulations!");
|
|
#if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
|
|
rb->lcd_getstringsize("No more levels", &sw, NULL);
|
|
rb->lcd_putsxy(LCD_WIDTH/2-sw/2, INT3(STRINGPOS_FINISH),
|
|
"No more levels");
|
|
#else
|
|
rb->lcd_getstringsize("You have finished the game!",
|
|
&sw, NULL);
|
|
rb->lcd_putsxy(LCD_WIDTH/2-sw/2, INT3(STRINGPOS_FINISH),
|
|
"You have finished the game!");
|
|
#endif
|
|
vscore=score;
|
|
rb->lcd_update();
|
|
brickmania_sleep(2);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int button=rb->button_get(false);
|
|
int move_button = rb->button_status();
|
|
|
|
#if defined(HAS_BUTTON_HOLD) && !defined(HAVE_REMOTE_LCD_AS_MAIN)
|
|
/* FIXME: Should probably check remote hold here */
|
|
if (rb->button_hold())
|
|
button = QUIT;
|
|
#endif
|
|
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
if( move_button & BUTTON_TOUCHSCREEN)
|
|
{
|
|
int data;
|
|
short touch_x;
|
|
rb->button_status_wdata(&data);
|
|
touch_x = FIXED3(data >> 16);
|
|
|
|
if(flip_sides)
|
|
{
|
|
pad_pos_x = GAMESCREEN_WIDTH - (touch_x + pad_width/2);
|
|
}
|
|
else
|
|
{
|
|
pad_pos_x = (touch_x - pad_width/2);
|
|
}
|
|
|
|
if(pad_pos_x < 0)
|
|
pad_pos_x = 0;
|
|
else if(pad_pos_x + pad_width > GAMESCREEN_WIDTH)
|
|
pad_pos_x = GAMESCREEN_WIDTH-pad_width;
|
|
for(k=0; k<used_balls; k++)
|
|
if (game_state==ST_READY || ball[k].glue)
|
|
ball[k].pos_x = pad_pos_x + pad_width/2;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
int button_right, button_left;
|
|
#ifdef ALTRIGHT
|
|
button_right = move_button & (RIGHT | ALTRIGHT);
|
|
button_left = move_button & (LEFT | ALTLEFT);
|
|
#else
|
|
button_right =((move_button & RIGHT)|| SCROLL_FWD(button));
|
|
button_left =((move_button & LEFT) ||SCROLL_BACK(button));
|
|
#endif
|
|
if ((game_state==ST_PAUSE) && (button_right || button_left))
|
|
continue;
|
|
|
|
if (button_left || button_right)
|
|
{
|
|
int dx = 0;
|
|
|
|
if ((button_right && !flip_sides) ||
|
|
(button_left && flip_sides))
|
|
{
|
|
if (pad_pos_x+SPEED_PAD+pad_width > GAMESCREEN_WIDTH)
|
|
dx = GAMESCREEN_WIDTH - pad_pos_x - pad_width;
|
|
else
|
|
dx = SPEED_PAD;
|
|
}
|
|
else if ((button_left && !flip_sides) ||
|
|
(button_right && flip_sides))
|
|
{
|
|
if (pad_pos_x-SPEED_PAD < 0)
|
|
dx = -pad_pos_x;
|
|
else
|
|
dx = -SPEED_PAD;
|
|
}
|
|
|
|
pad_pos_x+=dx;
|
|
for(k=0;k<used_balls;k++)
|
|
{
|
|
if (game_state==ST_READY || ball[k].glue)
|
|
{
|
|
ball[k].pos_x+=dx;
|
|
|
|
if (ball[k].pos_x < HALFBALL)
|
|
ball[k].pos_x = HALFBALL;
|
|
else if (ball[k].pos_x > GAMESCREEN_WIDTH - HALFBALL)
|
|
ball[k].pos_x = GAMESCREEN_WIDTH - HALFBALL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
switch(button)
|
|
{
|
|
#if defined(HAVE_TOUCHSCREEN)
|
|
case (BUTTON_REL | BUTTON_TOUCHSCREEN):
|
|
#endif
|
|
case UP:
|
|
case SELECT:
|
|
#ifdef ALTSELECT
|
|
case ALTSELECT:
|
|
#endif
|
|
if (game_state==ST_READY)
|
|
{
|
|
/* Initialize used balls starting speed */
|
|
for(k=0 ; k < used_balls ; k++)
|
|
{
|
|
ball[k].speedy = SPEED_4Q_Y;
|
|
if(pad_pos_x + (pad_width/2) >= GAMESCREEN_WIDTH/2)
|
|
{
|
|
ball[k].speedx = SPEED_4Q_X;
|
|
}
|
|
else
|
|
{
|
|
ball[k].speedx = -SPEED_4Q_X;
|
|
}
|
|
}
|
|
game_state=ST_START;
|
|
}
|
|
else if (game_state==ST_PAUSE)
|
|
{
|
|
game_state=ST_START;
|
|
}
|
|
else if (paddle_type == PADDLE_TYPE_STICKY)
|
|
{
|
|
for(k=0;k<used_balls;k++)
|
|
{
|
|
if (ball[k].glue)
|
|
{
|
|
ball[k].glue=false;
|
|
ball[k].speedy = -ball[k].speedy;
|
|
}
|
|
}
|
|
}
|
|
else if (paddle_type == PADDLE_TYPE_SHOOTER)
|
|
{
|
|
if (used_fires < MAX_FIRES)
|
|
{
|
|
fire[used_fires].top = PAD_POS_Y - FIRE_LENGTH;
|
|
fire[used_fires].x_pos = pad_pos_x + 1; /* Add 1 for edge */
|
|
used_fires++;
|
|
}
|
|
if (used_fires < MAX_FIRES)
|
|
{
|
|
fire[used_fires].top = PAD_POS_Y - FIRE_LENGTH;
|
|
fire[used_fires].x_pos = pad_pos_x + pad_width - 1; /* Sub1 edge*/
|
|
used_fires++;
|
|
}
|
|
}
|
|
break;
|
|
#ifdef RC_QUIT
|
|
case RC_QUIT:
|
|
#endif
|
|
case QUIT:
|
|
resume = true;
|
|
return 0;
|
|
break;
|
|
|
|
default:
|
|
if(rb->default_event_handler(button) == SYS_USB_CONNECTED)
|
|
return 1;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
resume = false;
|
|
if(resume_file)
|
|
{
|
|
rb->remove(SAVE_FILE);
|
|
resume_file = false;
|
|
}
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_bitmap_transparent(brickmania_gameover,
|
|
(LCD_WIDTH - INT3(GAMEOVER_WIDTH))/2,
|
|
INT3(GAMESCREEN_HEIGHT - GAMEOVER_HEIGHT)/2,
|
|
INT3(GAMEOVER_WIDTH),INT3(GAMEOVER_HEIGHT));
|
|
#else /* greyscale and mono */
|
|
rb->lcd_bitmap(brickmania_gameover,(LCD_WIDTH -
|
|
INT3(GAMEOVER_WIDTH))/2,
|
|
INT3(GAMESCREEN_HEIGHT - GAMEOVER_HEIGHT)/2,
|
|
INT3(GAMEOVER_WIDTH),INT3(GAMEOVER_HEIGHT) );
|
|
#endif
|
|
rb->lcd_update();
|
|
brickmania_sleep(2);
|
|
return 0;
|
|
}
|
|
|
|
/* Game always needs to yield for other threads */
|
|
rb->yield();
|
|
|
|
/* Sleep for a bit if there is time to spare */
|
|
if (TIME_BEFORE(*rb->current_tick, end))
|
|
rb->sleep(end-*rb->current_tick);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* this is the plugin entry point */
|
|
enum plugin_status plugin_start(const void* parameter)
|
|
{
|
|
(void)parameter;
|
|
int last_difficulty;
|
|
|
|
highscore_load(SCORE_FILE, highscores, NUM_SCORES);
|
|
configfile_load(CONFIG_FILE_NAME,config,1,0);
|
|
last_difficulty = difficulty;
|
|
|
|
#ifdef HAVE_TOUCHSCREEN
|
|
rb->touchscreen_set_mode(TOUCHSCREEN_POINT);
|
|
#endif
|
|
|
|
rb->lcd_setfont(FONT_SYSFIXED);
|
|
#if LCD_DEPTH > 1
|
|
rb->lcd_set_backdrop(NULL);
|
|
#endif
|
|
/* Turn off backlight timeout */
|
|
backlight_ignore_timeout();
|
|
|
|
/* now go ahead and have fun! */
|
|
rb->srand( *rb->current_tick );
|
|
brickmania_loadgame();
|
|
resume_file = resume;
|
|
while(!brickmania_game_loop())
|
|
{
|
|
if(!resume)
|
|
{
|
|
int position = highscore_update(score, level+1, "",
|
|
highscores, NUM_SCORES);
|
|
if (position != -1)
|
|
{
|
|
if (position == 0)
|
|
rb->splash(HZ*2, "New High Score");
|
|
highscore_show(position, highscores, NUM_SCORES, true);
|
|
}
|
|
else
|
|
{
|
|
brickmania_sleep(3);
|
|
}
|
|
}
|
|
}
|
|
|
|
highscore_save(SCORE_FILE, highscores, NUM_SCORES);
|
|
if(last_difficulty != difficulty)
|
|
configfile_save(CONFIG_FILE_NAME,config,1,0);
|
|
/* Restore user's original backlight setting */
|
|
rb->lcd_setfont(FONT_UI);
|
|
/* Turn on backlight timeout (revert to settings) */
|
|
backlight_use_settings();
|
|
|
|
return PLUGIN_OK;
|
|
}
|