From d4119775d4df2add2d35ff47500088570ee35c40 Mon Sep 17 00:00:00 2001 From: kju Date: Fri, 29 Jan 2010 01:34:24 +0000 Subject: [PATCH] re-include breakout. i want it, deknos want it, ... want it. --- games/breakout/Makefile | 10 ++ games/breakout/ball.c | 184 +++++++++++++++++++++++++++++++++++++ games/breakout/ball.h | 45 +++++++++ games/breakout/breakout.c | 67 ++++++++++++++ games/breakout/common.h | 41 +++++++++ games/breakout/config.h | 34 +++++++ games/breakout/level.c | 105 +++++++++++++++++++++ games/breakout/level.h | 24 +++++ games/breakout/messages.c | 37 ++++++++ games/breakout/messages.h | 27 ++++++ games/breakout/playfield.c | 125 +++++++++++++++++++++++++ games/breakout/playfield.h | 53 +++++++++++ games/breakout/rebound.c | 71 ++++++++++++++ games/breakout/rebound.h | 27 ++++++ games/breakout/score.c | 28 ++++++ games/breakout/score.h | 26 ++++++ 16 files changed, 904 insertions(+) create mode 100644 games/breakout/Makefile create mode 100644 games/breakout/ball.c create mode 100644 games/breakout/ball.h create mode 100644 games/breakout/breakout.c create mode 100644 games/breakout/common.h create mode 100644 games/breakout/config.h create mode 100644 games/breakout/level.c create mode 100644 games/breakout/level.h create mode 100644 games/breakout/messages.c create mode 100644 games/breakout/messages.h create mode 100644 games/breakout/playfield.c create mode 100644 games/breakout/playfield.h create mode 100644 games/breakout/rebound.c create mode 100644 games/breakout/rebound.h create mode 100644 games/breakout/score.c create mode 100644 games/breakout/score.h diff --git a/games/breakout/Makefile b/games/breakout/Makefile new file mode 100644 index 0000000..c5dae36 --- /dev/null +++ b/games/breakout/Makefile @@ -0,0 +1,10 @@ +TARGET = +TOPDIR = ../.. + +include $(TOPDIR)/defaults.mk + +ifeq ($(GAME_BREAKOUT),y) + SRC = breakout.c playfield.c rebound.c score.c level.c ball.c messages.c +endif + +include $(TOPDIR)/rules.mk diff --git a/games/breakout/ball.c b/games/breakout/ball.c new file mode 100644 index 0000000..692d196 --- /dev/null +++ b/games/breakout/ball.c @@ -0,0 +1,184 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Author & Copyright (C) 2010: Soeren Heisrath (forename@surename.org) + * + */ + +#include "ball.h" + +/* modify a vecotor according to given type of bouncing */ +void bounce_rand_vector (ball_t *in_b, uint8_t in_bouncetype); +void bounce_rand_vector (ball_t *in_b, uint8_t in_bouncetype) +{ + uint8_t rval = random8(); + + switch (in_bouncetype) + { + case BOUNCE_NONE: /* don't touch the vector since nothing changed */ + return; + + case BOUNCE_BRICK: + in_b->dir_x ^= (rval & 0x07); + in_b->dir_y ^= (rval & 0x07); + break; + + case BOUNCE_REBOUND: /* the rebound is rather percise */ + in_b->dir_x ^= (rval & 0x03); + in_b->dir_y ^= (rval & 0x03); + + if (JOYISRIGHT || JOYISLEFT) + { + /* a moving rebond accelerates the ball 12,5% */ + in_b->dir_y += (in_b->dir_y / 8); + in_b->dir_x += (in_b->dir_x / 8); + } + break; + + default: /* walls */ + in_b->dir_x ^= (rval & 0x01); + in_b->dir_y ^= (rval & 0x01); + } + if (!in_b->dir_x) + in_b->dir_x = 213; + + if (!in_b->dir_y) + in_b->dir_y = 217; +} + +void ball_think (ball_t *b) +{ + int8_t proj_x, proj_y, bounce, tmp; + + /* projection of the new coordinates */ + proj_x = (b->x + (b->dir_x)) / 256; + proj_y = (b->y + (b->dir_y)) / 256; + + /* falling out of the field */ + if (proj_y >= NUM_ROWS) + ball_die (b); + + bounce = check_bounce (proj_x, b->y / 256); + + /* bouncing on bricks needs special handling */ + if (bounce & (BOUNCE_BRICK)) + bounce |= BOUNCE_X; + + tmp = check_bounce (b->x / 256, proj_y); + if (tmp & (BOUNCE_BRICK)) + bounce |= BOUNCE_Y; + bounce |= tmp; + + tmp = check_bounce (proj_x, proj_y); + if (tmp & (BOUNCE_BRICK)) + bounce |= BOUNCE_X | BOUNCE_Y; + bounce |= tmp; + + bounce_rand_vector (b, bounce); + + /* bounce in x direction */ + if (bounce & BOUNCE_X) + { + b->dir_x *= -1; /* invert x vector */ + } + + /* bounce in y direction */ + if (bounce & BOUNCE_Y) + { + b->dir_y *= -1; /* invert y vector */ + } + +#if BOUNCE_SLOWDOWN + if (bounce & BOUNCE_BRICK) + { + if (b->dir_y < - BALL_MINSPEED) + { + b->dir_y += BOUNCE_SLOWDOWN; + } else if (b->dir_y > BALL_MINSPEED) + { + b->dir_y -= BOUNCE_SLOWDOWN; + } + + if (b->dir_x < - BALL_MINSPEED) + { + b->dir_x += BOUNCE_SLOWDOWN; + } else if (b->dir_y > BALL_MINSPEED) + { + b->dir_x -= BOUNCE_SLOWDOWN; + } + } +#endif + + if (bounce & BOUNCE_REBOUND) + { + rebound_reflect(b, proj_x); + } + + if (b->dir_x > BALL_MAXSPEED) + b->dir_x = BALL_MAXSPEED; + + if (b->dir_x < -BALL_MAXSPEED) + b->dir_x = -BALL_MAXSPEED; + + if (b->dir_y > BALL_MAXSPEED) + b->dir_y = BALL_MAXSPEED; + + if (b->dir_y < -BALL_MAXSPEED) + b->dir_y = -BALL_MAXSPEED; + + + b->y += b->dir_y; + b->x += b->dir_x; +} + +void ball_die (ball_t *in_b) +{ + in_b->strength--; + + /* respawn ball with random direction */ + if (in_b->strength) + { + print_ballsleft(in_b); + ball_spawn_default (in_b); + } +} + +void ball_draw (ball_t *b) +{ + pixel p; + p.x = (uint8_t) abs(b->x / 256); + p.y = (uint8_t) abs(b->y / 256); + + setpixel (p, 3); +} + +void ball_spawn (ball_t *in_ball, uint16_t in_x, uint16_t in_y, int16_t in_dir_x, int16_t in_dir_y) +{ + in_ball->x = in_x; + in_ball->y = in_y; + in_ball->dir_x = in_dir_x; + in_ball->dir_y = in_dir_y; +} + +void ball_spawn_default (ball_t *in_b) +{ + int16_t xdir; + + xdir = 128 + (random8() & 0x3F); + if (random8() & 0x01) + xdir *= -1; + + ball_spawn (in_b, (uint16_t) rebound_getpos() * 256, (NUM_ROWS -2) * 256, + xdir, -131); +} diff --git a/games/breakout/ball.h b/games/breakout/ball.h new file mode 100644 index 0000000..31727fd --- /dev/null +++ b/games/breakout/ball.h @@ -0,0 +1,45 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Author & Copyright (C) 2010: Soeren Heisrath (forename@surename.org) + * + */ +#include "common.h" + +#ifndef BALL_H +#define BALL_H + + +typedef struct +{ + int16_t x; + int16_t y; + int16_t dir_x; /* direction vector */ + int16_t dir_y; + uint8_t strength; +} ball_t; + +void ball_spawn (ball_t *in_ball, uint16_t in_x, uint16_t in_y, int16_t in_dir_x, int16_t in_dir_y); + +/* @description Called once per game tick. Move the ball further along it's vector. + */ +void ball_think (ball_t *in_ball); + + +void ball_die (ball_t *in_b); + +void ball_draw (ball_t *); + +void ball_spawn_default (ball_t *in_b); +#endif /* BALL_H */ diff --git a/games/breakout/breakout.c b/games/breakout/breakout.c new file mode 100644 index 0000000..13f18dc --- /dev/null +++ b/games/breakout/breakout.c @@ -0,0 +1,67 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Author & Copyright (C) 2010: Soeren Heisrath (forename@surename.org) + * + */ + +#include "common.h" +static void borg_breakout(); + +#ifdef MENU_SUPPORT +//static uint8_t breakout_icon[8] PROGMEM = {0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00}; /* our Icon */ +static uint8_t breakout_icon[8] PROGMEM = {0x00, 0x18, 0x18, 0x00, 0x00, 0xff, 0xff, 0x00}; /* our Icon */ + +game_descriptor_t breakout_game_descriptor __attribute__((section(".game_descriptors"))) = +{ + &borg_breakout, + breakout_icon +}; +#endif + +void borg_breakout() +{ + uint8_t level = 0; + ball_t balls[1]; + + /* spawn a ball in the middle bottom of the field, let it move upwards with random speed & direction */ + ball_spawn_default(&(balls[0])); + balls[0].strength = START_LIFES; + level_init(level); + rebound_init(); + + while (23) + { + wait(50); + rebound_tick(); + ball_think(&(balls[0])); + playfield_draw(); + ball_draw(&(balls[0])); + if (!balls[0].strength) + { + print_score(); + break; + } + + if (!level_getscorediff()) + { + level++; + /* respawn ball at rebound position */ + ball_spawn_default (&(balls[0])); + balls[0].strength++; + level_init(level); + rebound_init(); + } + } +} diff --git a/games/breakout/common.h b/games/breakout/common.h new file mode 100644 index 0000000..e4297e0 --- /dev/null +++ b/games/breakout/common.h @@ -0,0 +1,41 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Author & Copyright (C) 2010: Soeren Heisrath (forename@surename.org) + * + */ + +#ifndef COMMON_H +#define COMMON_H +#include +#include +#include +#include "../../joystick/joystick.h" +#include "../../config.h" +#include "../../autoconf.h" +#include "../../compat/eeprom.h" +#include "../../random/prng.h" +#include "../../compat/pgmspace.h" +#include "../../util.h" +#include "../../menu/menu.h" +#include "../../pixel.h" +#include "../../scrolltext/scrolltext.h" +#include "config.h" +#include "ball.h" +#include "playfield.h" +#include "score.h" +#include "level.h" +#include "rebound.h" +#include "messages.h" +#endif /* COMMON_H */ diff --git a/games/breakout/config.h b/games/breakout/config.h new file mode 100644 index 0000000..d375a6f --- /dev/null +++ b/games/breakout/config.h @@ -0,0 +1,34 @@ +#ifndef CONFIG_H +#define CONFIG_H +/* amount of speed to slow down on bounce */ +#define BOUNCE_SLOWDOWN 4 + +/* minimum speed of the ball */ +#define BALL_MINSPEED 64 +#define BALL_MAXSPEED 224 + +/* initial amount of lifes */ +#define START_LIFES 3 + +/* rebound size */ +#define REBOUND_SIZE 4 + + +/* "color" of the rebound */ +#define REBOUND_COLOR 2 + +/* rebound reflection: values to add to the vector at rebound field n + * the size of this array must be REBOUND_SIZE +2 + */ +static const int8_t rebound_reflection[6][2] = +{ + {-72, -20}, /* offside left */ + {-40, -12}, /* left */ + {-16, -8}, /* center left */ + { 16, -8}, /* center right */ + { 40, -12}, /* right */ + { 72, -20} /* offside right */ +}; + +#endif /* CONFIG_H */ + diff --git a/games/breakout/level.c b/games/breakout/level.c new file mode 100644 index 0000000..80c9457 --- /dev/null +++ b/games/breakout/level.c @@ -0,0 +1,105 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Author & Copyright (C) 2010: Soeren Heisrath (forename@surename.org) + * + */ + +#include "level.h" + +static uint16_t maxscore; + +/* real level definition */ +enum game_field_t level_field (uint8_t in_x, uint8_t in_y, uint8_t in_lvl); +enum game_field_t level_field (uint8_t in_x, uint8_t in_y, uint8_t in_lvl) +{ + switch (in_lvl) + { + case 0: + /* space for the lower half of the level */ + if (in_y > (NUM_ROWS / 3)) + return sp; + + return b1; /* b1-blocks for the rest */ + case 1: + /* space for the lower half of the level */ + if (in_y > (NUM_ROWS / 2)) + return sp; + + /* type 2 bricks for 1/4th of the field */ + if (in_y <= (NUM_ROWS / 4)) + return b2; + + /* fill the rest with type 1 */ + return b1; + break; + + case 3: + /* add a row of solid bricks right in the middle of the field */ + if (in_y == (NUM_ROWS / 2) && + (in_x > (NUM_COLS / 4)) && (in_x < (NUM_COLS - (NUM_COLS / 4)))) + return bs; + + /* intentional fallthrough: the rest of level 3 is like level 2 */ + + case 2: + /* space for the lower third of the level */ + if (in_y > (NUM_ROWS / 3)) + return sp; + + /* type 3 bricks for 1/8th of the field */ + if (in_y <= (NUM_ROWS / 8)) + return b3; + + /* type 2 bricks for 1/4th of the field */ + if (in_y <= (NUM_ROWS / 4)) + return b2; + + /* fill the rest with type 1 */ + return b1; + + default: /* random level generation */ + /* space for the lower half of the level */ + if (in_y > (NUM_ROWS / 2)) + return sp; + + return random8() & 0x03; /* fill field with random bricks (and spaces) */ + break; + } +} + +void level_init (uint8_t in_levelnum) +{ + uint8_t x,y; + enum game_field_t tmp; + maxscore = 0; + + for (x=0;xstrength); + scrolltext(txt); +#endif +} + +void print_score () +{ +#ifdef SCROLLTEXT_SUPPORT + char txt[32]; + snprintf (txt, sizeof(txt), "= NUM_ROWS || in_y >= NUM_COLS) + { + return; + } + playfield[in_x][in_y] = in_field; +} + +void brick_damage (uint8_t in_x, uint8_t in_y) +{ + if (playfield[in_x][in_y] >= bs || playfield[in_x][in_y] == 0) + return; + + playfield[in_x][in_y] -= 1; + score_add (1); +} + +uint8_t check_bounce (int8_t in_x, int8_t in_y) +{ + uint8_t ov = 0; + /* overflow check */ + if (in_x >= NUM_ROWS || in_x < 0) + ov |= BOUNCE_X; + + if (in_y >= NUM_COLS || in_y < 0) + ov |= BOUNCE_Y; + + if (ov) + { + return ov; + } + + /* collisions with real objects */ + switch (playfield[abs(in_x)][abs(in_y)]) + { + case b2: + case b3: + case b1: + brick_damage (in_x, in_y); + /* intentional fallthrough */ + case bs: + ov |= BOUNCE_BRICK; + break; + + /* bouncing on the rebound needs special care */ + case rb: + ov |= BOUNCE_Y | BOUNCE_REBOUND; + break; + + case sp: + case bl: + default: + break; + + } + return ov; +} + +/* this is the actual draw function for a single field + */ +static inline void draw_single_field (uint8_t in_x, uint8_t in_y, enum game_field_t in_f) +{ + pixel tmp; + uint8_t b; + switch (in_f) + { + case b1: + b = 1; + break; + + case rb: + case b2: + b = 2; + break; + + case b3: + case bl: + case bs: + b = 3; + break; + + default: /* this includes freespace */ + b = 0; + break; + + } + tmp.x = in_x; + tmp.y = in_y; + setpixel (tmp, b); +} + +void playfield_draw () +{ + uint8_t x,y; + + for (x=0;xdir_x += rebound_reflection[tmpidx][0]; + b->dir_y += rebound_reflection[tmpidx][1]; +} + +uint8_t rebound_getpos () +{ + return (rbpos + (REBOUND_SIZE / 2)); +} + +void rebound_init() +{ + rbpos = (NUM_ROWS / 2) - (REBOUND_SIZE / 2); + rebound_draw(); +} + +void rebound_draw () +{ + uint8_t i; + + for (i=0;i= rbpos && i < rbpos + REBOUND_SIZE) + playfield_set (i, NUM_ROWS-1, rb); /* set rebound pixel */ + else + playfield_set (i, NUM_ROWS-1, sp); /* space */ + } + printf("rpos: %i\n", rbpos); +} + +void rebound_tick() +{ + /* directions are inverted (JOYISLEFT means RIGHT) */ + if (JOYISRIGHT && rbpos) + { + rbpos--; + rebound_draw(); + } + + if (JOYISLEFT && rbpos < (NUM_COLS - (REBOUND_SIZE))) + { + rbpos++; + rebound_draw(); + } +} diff --git a/games/breakout/rebound.h b/games/breakout/rebound.h new file mode 100644 index 0000000..cd8f45c --- /dev/null +++ b/games/breakout/rebound.h @@ -0,0 +1,27 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Author & Copyright (C) 2010: Soeren Heisrath (forename@surename.org) + * + */ +#include "common.h" + +#ifndef REBOUND_H +#define REBOUND_H +void rebound_init(); +void rebound_tick(); +void rebound_draw(); +uint8_t rebound_getpos(); +void rebound_reflect(ball_t *b, int8_t in_x); +#endif /* REBOUND_H */ diff --git a/games/breakout/score.c b/games/breakout/score.c new file mode 100644 index 0000000..01033f9 --- /dev/null +++ b/games/breakout/score.c @@ -0,0 +1,28 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Author & Copyright (C) 2010: Soeren Heisrath (forename@surename.org) + * + */ +#include "score.h" +static uint16_t score = 0; +void score_add (uint8_t in_score) +{ + score += in_score; +} + +uint16_t score_get() +{ + return score; +} diff --git a/games/breakout/score.h b/games/breakout/score.h new file mode 100644 index 0000000..79bd767 --- /dev/null +++ b/games/breakout/score.h @@ -0,0 +1,26 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Author & Copyright (C) 2010: Soeren Heisrath (forename@surename.org) + * + */ +#include "common.h" + +#ifndef SCORE_H +#define SCORE_H + + +void score_add(uint8_t); +uint16_t score_get(); +#endif