improved the wurstwasser-kompensator!
This commit is contained in:
parent
884badbc2f
commit
3488109d65
|
@ -1,21 +1,60 @@
|
||||||
#include "common.h"
|
#include "common.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 by 1/8th */
|
||||||
|
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)
|
void ball_think (ball_t *b)
|
||||||
{
|
{
|
||||||
int8_t proj_x, proj_y, bounce;
|
int8_t proj_x, proj_y, bounce;
|
||||||
|
|
||||||
|
/*
|
||||||
if (!b->strength)
|
if (!b->strength)
|
||||||
return;
|
return;
|
||||||
|
*/
|
||||||
|
|
||||||
/* projection of the new coordinates */
|
/* projection of the new coordinates */
|
||||||
proj_x = (b->x + (b->dir_x)) / 256;
|
proj_x = (b->x + (b->dir_x)) / 256;
|
||||||
proj_y = (b->y + (b->dir_y)) / 256;
|
proj_y = (b->y + (b->dir_y)) / 256;
|
||||||
|
|
||||||
/* ball fell out of the field */
|
/* falling out of the field */
|
||||||
if (proj_y >= NUM_ROWS)
|
if (proj_y >= NUM_ROWS)
|
||||||
ball_die (b);
|
ball_die (b);
|
||||||
|
|
||||||
|
|
||||||
bounce = check_bounce (proj_x, b->y / 256);
|
bounce = check_bounce (proj_x, b->y / 256);
|
||||||
if (bounce & BOUNCE_UNDEF)
|
if (bounce & BOUNCE_UNDEF)
|
||||||
bounce = (BOUNCE_X | bounce) & (BOUNCE_X | BOUNCE_Y);
|
bounce = (BOUNCE_X | bounce) & (BOUNCE_X | BOUNCE_Y);
|
||||||
|
@ -28,14 +67,12 @@ void ball_think (ball_t *b)
|
||||||
if (bounce & BOUNCE_UNDEF)
|
if (bounce & BOUNCE_UNDEF)
|
||||||
bounce = BOUNCE_X | BOUNCE_Y;
|
bounce = BOUNCE_X | BOUNCE_Y;
|
||||||
|
|
||||||
|
bounce_rand_vector (b, bounce);
|
||||||
|
|
||||||
/* bounce in x direction */
|
/* bounce in x direction */
|
||||||
if (bounce & 0x01)
|
if (bounce & (BOUNCE_X | BOUNCE_BRICK))
|
||||||
{
|
{
|
||||||
b->dir_x *= -1; /* invert x vector */
|
b->dir_x *= -1; /* invert x vector */
|
||||||
b->dir_x ^= random8() & 0x0F; /* randomize bouncing */
|
|
||||||
|
|
||||||
|
|
||||||
#if BOUNCE_SLOWDOWN
|
#if BOUNCE_SLOWDOWN
|
||||||
if (b->dir_x < 0)
|
if (b->dir_x < 0)
|
||||||
|
@ -49,10 +86,10 @@ void ball_think (ball_t *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bounce in y direction */
|
/* bounce in y direction */
|
||||||
if (bounce & 0x02)
|
if (bounce & (BOUNCE_Y | BOUNCE_BRICK))
|
||||||
{
|
{
|
||||||
b->dir_y *= -1; /* invert y vector */
|
b->dir_y *= -1; /* invert y vector */
|
||||||
b->dir_y ^= random8() & 0x0F;
|
|
||||||
#if BOUNCE_SLOWDOWN
|
#if BOUNCE_SLOWDOWN
|
||||||
if (b->dir_y < 0)
|
if (b->dir_y < 0)
|
||||||
{
|
{
|
||||||
|
@ -66,6 +103,11 @@ void ball_think (ball_t *b)
|
||||||
|
|
||||||
b->y += b->dir_y;
|
b->y += b->dir_y;
|
||||||
b->x += b->dir_x;
|
b->x += b->dir_x;
|
||||||
|
|
||||||
|
if (!b->dir_x || !b->dir_y)
|
||||||
|
{
|
||||||
|
printf("Ball stopped!\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ball_die (ball_t *in_b)
|
void ball_die (ball_t *in_b)
|
||||||
|
@ -76,7 +118,7 @@ void ball_die (ball_t *in_b)
|
||||||
if (in_b->strength)
|
if (in_b->strength)
|
||||||
{
|
{
|
||||||
print_ballsleft(in_b);
|
print_ballsleft(in_b);
|
||||||
ball_spawn (in_b, (uint16_t) (rebound_getpos() * 256), (uint16_t) (NUM_ROWS-2) * 256, -120, 150, in_b->strength);
|
ball_spawn_default (in_b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,16 +131,22 @@ void ball_draw (ball_t *b)
|
||||||
setpixel (p, 3);
|
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, uint8_t in_strength)
|
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->x = in_x;
|
||||||
in_ball->y = in_y;
|
in_ball->y = in_y;
|
||||||
in_ball->dir_x = in_dir_x;
|
in_ball->dir_x = in_dir_x;
|
||||||
in_ball->dir_y = in_dir_y;
|
in_ball->dir_y = in_dir_y;
|
||||||
in_ball->strength = in_strength;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ball_spawn_default (ball_t *in_b)
|
void ball_spawn_default (ball_t *in_b)
|
||||||
{
|
{
|
||||||
ball_spawn (in_b, (uint16_t) (NUM_COLS / 2) * 256, (uint16_t) (NUM_ROWS-2) * 256, -120, 150, START_LIFES);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ typedef struct
|
||||||
uint8_t strength;
|
uint8_t strength;
|
||||||
} ball_t;
|
} 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, uint8_t in_strength);
|
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.
|
/* @description Called once per game tick. Move the ball further along it's vector.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,7 +4,7 @@ void borg_breakout();
|
||||||
|
|
||||||
#ifdef MENU_SUPPORT
|
#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 = {0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00}; /* our Icon */
|
||||||
static uint8_t breakout_icon[8] PROGMEM = {0x18, 0x18, 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"))) =
|
game_descriptor_t breakout_game_descriptor __attribute__((section(".game_descriptors"))) =
|
||||||
{
|
{
|
||||||
|
@ -15,12 +15,13 @@ game_descriptor_t breakout_game_descriptor __attribute__((section(".game_descrip
|
||||||
|
|
||||||
void borg_breakout()
|
void borg_breakout()
|
||||||
{
|
{
|
||||||
uint8_t rungame = 1, num_balls = 1;
|
uint8_t rungame = 1, num_balls = 1, level = 0;
|
||||||
ball_t balls[1];
|
ball_t balls[1];
|
||||||
|
|
||||||
/* spawn a ball in the middle bottom of the field, let it move upwards with random speed & direction */
|
/* spawn a ball in the middle bottom of the field, let it move upwards with random speed & direction */
|
||||||
ball_spawn (&balls[0], (uint16_t) (NUM_COLS / 2) * 256, (uint16_t) (NUM_ROWS-2) * 256, -120, 150, START_LIFES);
|
ball_spawn_default(&(balls[0]));
|
||||||
level_init(0);
|
balls[0].strength = START_LIFES;
|
||||||
|
level_init(level);
|
||||||
rebound_init();
|
rebound_init();
|
||||||
|
|
||||||
while (23)
|
while (23)
|
||||||
|
@ -35,5 +36,15 @@ void borg_breakout()
|
||||||
print_score();
|
print_score();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!level_getscorediff())
|
||||||
|
{
|
||||||
|
printf("lvl done\n");
|
||||||
|
level++;
|
||||||
|
/* respawn ball at rebound position */
|
||||||
|
ball_spawn_default (&(balls[0]));
|
||||||
|
balls[0].strength++;
|
||||||
|
level_init(level);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,4 +19,6 @@
|
||||||
#include "level.h"
|
#include "level.h"
|
||||||
#include "rebound.h"
|
#include "rebound.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
|
|
||||||
|
#define MAX(a,b) (a > b) ? a : b
|
||||||
#endif /* COMMON_H */
|
#endif /* COMMON_H */
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
#include "level.h"
|
#include "level.h"
|
||||||
|
|
||||||
|
static uint16_t maxscore;
|
||||||
|
|
||||||
/* real level definition */
|
/* 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);
|
||||||
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)
|
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:
|
case 1:
|
||||||
/* space for the lower half of the level */
|
/* space for the lower half of the level */
|
||||||
if (in_y > (NUM_ROWS / 2))
|
if (in_y > (NUM_ROWS / 2))
|
||||||
|
@ -56,13 +64,24 @@ enum game_field_t level_field (uint8_t in_x, uint8_t in_y, uint8_t in_lvl)
|
||||||
void level_init (uint8_t in_levelnum)
|
void level_init (uint8_t in_levelnum)
|
||||||
{
|
{
|
||||||
uint8_t x,y;
|
uint8_t x,y;
|
||||||
|
enum game_field_t tmp;
|
||||||
|
maxscore = 0;
|
||||||
|
|
||||||
for (x=0;x<NUM_COLS;x++)
|
for (x=0;x<NUM_COLS;x++)
|
||||||
{
|
{
|
||||||
for (y=0;y<NUM_ROWS;y++)
|
for (y=0;y<NUM_ROWS;y++)
|
||||||
{
|
{
|
||||||
playfield_set (x,y, level_field (x, y, in_levelnum));
|
tmp = level_field (x, y, in_levelnum);
|
||||||
|
playfield_set (x,y, tmp);
|
||||||
|
if (tmp <= b3)
|
||||||
|
maxscore += tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxscore += score_get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t level_getscorediff ()
|
||||||
|
{
|
||||||
|
return maxscore - score_get();
|
||||||
|
}
|
||||||
|
|
|
@ -2,4 +2,5 @@
|
||||||
#define LEVEL_H
|
#define LEVEL_H
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
void level_init (uint8_t in_levelnum);
|
void level_init (uint8_t in_levelnum);
|
||||||
|
uint16_t level_getscorediff ();
|
||||||
#endif /* LEVEL_H */
|
#endif /* LEVEL_H */
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include "messages.h"
|
||||||
|
|
||||||
|
void print_ballsleft (ball_t *in_b)
|
||||||
|
{
|
||||||
|
#ifdef SCROLLTEXT_SUPPORT
|
||||||
|
uint8_t txt[20];
|
||||||
|
snprintf (txt, sizeof(txt), "</#%u balls left", in_b->strength);
|
||||||
|
scrolltext(txt);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_score ()
|
||||||
|
{
|
||||||
|
#ifdef SCROLLTEXT_SUPPORT
|
||||||
|
uint8_t txt[32];
|
||||||
|
snprintf (txt, sizeof(txt), "</#GAME OVER. Your score: %u", score_get());
|
||||||
|
scrolltext(txt);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "common.h"
|
||||||
|
#ifndef MESSAGES_H
|
||||||
|
#define MESSAGES_H
|
||||||
|
|
||||||
|
void print_ballsleft (ball_t *in_b);
|
||||||
|
void print_score ();
|
||||||
|
|
||||||
|
#endif
|
|
@ -3,6 +3,10 @@ static enum game_field_t playfield[NUM_COLS][NUM_ROWS];
|
||||||
|
|
||||||
void playfield_set (uint8_t in_x, uint8_t in_y, enum game_field_t in_field)
|
void playfield_set (uint8_t in_x, uint8_t in_y, enum game_field_t in_field)
|
||||||
{
|
{
|
||||||
|
if (in_x >= NUM_ROWS || in_y >= NUM_COLS)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
playfield[in_x][in_y] = in_field;
|
playfield[in_x][in_y] = in_field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,8 +14,9 @@ void brick_damage (uint8_t in_x, uint8_t in_y)
|
||||||
{
|
{
|
||||||
enum game_field_t newtype;
|
enum game_field_t newtype;
|
||||||
|
|
||||||
if (playfield[in_x][in_y] > bs || playfield[in_x][in_y] == 0)
|
if (playfield[in_x][in_y] >= bs || playfield[in_x][in_y] == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
playfield[in_x][in_y] -= 1;
|
playfield[in_x][in_y] -= 1;
|
||||||
score_add (1);
|
score_add (1);
|
||||||
}
|
}
|
||||||
|
@ -26,7 +31,11 @@ uint8_t check_bounce (int8_t in_x, int8_t in_y)
|
||||||
if (in_y >= NUM_COLS || in_y < 0)
|
if (in_y >= NUM_COLS || in_y < 0)
|
||||||
ov |= BOUNCE_Y;
|
ov |= BOUNCE_Y;
|
||||||
|
|
||||||
if (ov) return ov;
|
if (ov)
|
||||||
|
{
|
||||||
|
return ov;
|
||||||
|
}
|
||||||
|
|
||||||
/* collisions with real objects */
|
/* collisions with real objects */
|
||||||
switch (playfield[abs(in_x)][abs(in_y)])
|
switch (playfield[abs(in_x)][abs(in_y)])
|
||||||
{
|
{
|
||||||
|
@ -35,20 +44,22 @@ uint8_t check_bounce (int8_t in_x, int8_t in_y)
|
||||||
case b1:
|
case b1:
|
||||||
brick_damage (in_x, in_y);
|
brick_damage (in_x, in_y);
|
||||||
/* intentional fallthrough */
|
/* intentional fallthrough */
|
||||||
|
|
||||||
case bs:
|
case bs:
|
||||||
return BOUNCE_UNDEF | ov;
|
ov |= BOUNCE_BRICK;
|
||||||
|
break;
|
||||||
|
|
||||||
/* bouncing on the rebound needs special care */
|
/* bouncing on the rebound needs special care */
|
||||||
case rb:
|
case rb:
|
||||||
return BOUNCE_Y;
|
ov |= BOUNCE_Y | BOUNCE_REBOUND;
|
||||||
|
break;
|
||||||
|
|
||||||
case sp:
|
case sp:
|
||||||
case bl:
|
case bl:
|
||||||
default:
|
default:
|
||||||
return ov;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return ov;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this is the actual draw function for a single field
|
/* this is the actual draw function for a single field
|
||||||
|
|
|
@ -2,9 +2,12 @@
|
||||||
#define PLAYFIELD_H
|
#define PLAYFIELD_H
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#define BOUNCE_X 0x01
|
#define BOUNCE_NONE 0x00
|
||||||
#define BOUNCE_Y 0x02
|
#define BOUNCE_X 0x01
|
||||||
#define BOUNCE_UNDEF 0x04
|
#define BOUNCE_Y 0x02
|
||||||
|
#define BOUNCE_UNDEF 0x04
|
||||||
|
#define BOUNCE_BRICK 0x08
|
||||||
|
#define BOUNCE_REBOUND 0x10
|
||||||
|
|
||||||
/* entries for the playing field */
|
/* entries for the playing field */
|
||||||
enum game_field_t
|
enum game_field_t
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "rebound.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
static uint8_t rbpos;
|
||||||
|
|
||||||
|
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=rbpos;i<rbpos + REBOUND_SIZE;i++)
|
||||||
|
{
|
||||||
|
playfield_set (i, NUM_ROWS-1, rb); /* set rebound pixel */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rebound_tick()
|
||||||
|
{
|
||||||
|
/* directions are inverted (JOYISLEFT means RIGHT) */
|
||||||
|
if (JOYISRIGHT && rbpos)
|
||||||
|
{
|
||||||
|
playfield_set (rbpos + REBOUND_SIZE, NUM_ROWS-1, sp); /* clear rebound pixel */
|
||||||
|
rbpos--;
|
||||||
|
playfield_set (rbpos, NUM_ROWS-1, rb); /* set rebound pixel */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JOYISLEFT && rbpos < (NUM_COLS - (REBOUND_SIZE+1)))
|
||||||
|
{
|
||||||
|
playfield_set (rbpos, NUM_ROWS-1, sp); /* clear rebound pixel */
|
||||||
|
rbpos++;
|
||||||
|
playfield_set (rbpos + REBOUND_SIZE, NUM_ROWS-1, rb); /* set rebound pixel */
|
||||||
|
}
|
||||||
|
rebound_draw();
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef REBOUND_H
|
||||||
|
#define REBOUND_H
|
||||||
|
#include "common.h"
|
||||||
|
void rebound_init();
|
||||||
|
void rebound_tick();
|
||||||
|
uint8_t rebound_getpos ();
|
||||||
|
#endif
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include "score.h"
|
||||||
|
static uint16_t score = 0;
|
||||||
|
void score_add (uint8_t in_score)
|
||||||
|
{
|
||||||
|
score += in_score;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t score_get()
|
||||||
|
{
|
||||||
|
return score;
|
||||||
|
}
|
Loading…
Reference in New Issue