borgware-2d/games/breakout/ball.c

185 lines
3.9 KiB
C
Raw Normal View History

2010-01-21 14:45:16 +00:00
/*
* 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"
2010-01-21 13:40:40 +00:00
/* 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);
2010-01-21 18:32:17 +00:00
2010-01-21 13:40:40 +00:00
if (JOYISRIGHT || JOYISLEFT)
{
2010-01-21 18:32:17 +00:00
/* a moving rebond accelerates the ball 12,5% */
2010-01-21 13:40:40 +00:00
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;
}
2010-01-19 19:44:16 +00:00
void ball_think (ball_t *b)
{
2010-01-23 20:15:45 +00:00
int8_t proj_x, proj_y, bounce, tmp;
2010-01-19 09:55:28 +00:00
/* projection of the new coordinates */
proj_x = (b->x + (b->dir_x)) / 256;
proj_y = (b->y + (b->dir_y)) / 256;
2010-01-19 19:44:16 +00:00
2010-01-21 13:40:40 +00:00
/* falling out of the field */
2010-01-19 19:44:16 +00:00
if (proj_y >= NUM_ROWS)
ball_die (b);
2010-01-19 09:55:28 +00:00
bounce = check_bounce (proj_x, b->y / 256);
2010-01-21 21:26:30 +00:00
2010-01-23 20:15:45 +00:00
/* bouncing on bricks needs special handling */
if (bounce & (BOUNCE_BRICK))
bounce |= BOUNCE_X;
2010-01-19 09:55:28 +00:00
2010-01-23 20:15:45 +00:00
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;
2010-01-15 16:02:31 +00:00
2010-01-21 13:40:40 +00:00
bounce_rand_vector (b, bounce);
/* bounce in x direction */
2010-01-23 20:15:45 +00:00
if (bounce & BOUNCE_X)
{
b->dir_x *= -1; /* invert x vector */
}
/* bounce in y direction */
2010-01-23 20:15:45 +00:00
if (bounce & BOUNCE_Y)
{
b->dir_y *= -1; /* invert y vector */
2010-01-21 18:32:17 +00:00
}
#if BOUNCE_SLOWDOWN
2010-01-21 18:32:17 +00:00
if (bounce & BOUNCE_BRICK)
{
2010-01-21 21:26:30 +00:00
if (b->dir_y < - BALL_MINSPEED)
{
b->dir_y += BOUNCE_SLOWDOWN;
2010-01-21 18:32:17 +00:00
} else if (b->dir_y > BALL_MINSPEED)
{
b->dir_y -= BOUNCE_SLOWDOWN;
}
2010-01-21 18:32:17 +00:00
2010-01-21 21:26:30 +00:00
if (b->dir_x < - BALL_MINSPEED)
2010-01-21 18:32:17 +00:00
{
b->dir_x += BOUNCE_SLOWDOWN;
} else if (b->dir_y > BALL_MINSPEED)
{
b->dir_x -= BOUNCE_SLOWDOWN;
}
}
#endif
2010-01-21 18:32:17 +00:00
if (bounce & BOUNCE_REBOUND)
{
rebound_reflect(b, proj_x);
}
2010-01-15 16:02:31 +00:00
2010-01-21 18:32:17 +00:00
if (b->dir_x > BALL_MAXSPEED)
b->dir_x = BALL_MAXSPEED;
2010-01-21 21:26:30 +00:00
if (b->dir_x < -BALL_MAXSPEED)
b->dir_x = -BALL_MAXSPEED;
2010-01-21 18:32:17 +00:00
if (b->dir_y > BALL_MAXSPEED)
b->dir_y = BALL_MAXSPEED;
2010-01-21 21:26:30 +00:00
if (b->dir_y < -BALL_MAXSPEED)
b->dir_y = -BALL_MAXSPEED;
2010-01-21 18:32:17 +00:00
2010-01-19 09:55:28 +00:00
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)
2010-01-19 19:44:16 +00:00
{
print_ballsleft(in_b);
2010-01-21 13:40:40 +00:00
ball_spawn_default (in_b);
2010-01-19 19:44:16 +00:00
}
}
2010-01-15 16:02:31 +00:00
void ball_draw (ball_t *b)
{
pixel p;
2010-01-19 09:55:28 +00:00
p.x = (uint8_t) abs(b->x / 256);
p.y = (uint8_t) abs(b->y / 256);
2010-01-15 16:02:31 +00:00
setpixel (p, 3);
}
2010-01-21 13:40:40 +00:00
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)
2010-01-15 16:02:31 +00:00
{
in_ball->x = in_x;
in_ball->y = in_y;
in_ball->dir_x = in_dir_x;
in_ball->dir_y = in_dir_y;
}
2010-01-19 19:44:16 +00:00
void ball_spawn_default (ball_t *in_b)
{
2010-01-21 13:40:40 +00:00
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);
2010-01-19 19:44:16 +00:00
}