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

153 lines
2.9 KiB
C

#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)
{
int8_t proj_x, proj_y, bounce;
/*
if (!b->strength)
return;
*/
/* 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);
if (bounce & BOUNCE_UNDEF)
bounce = (BOUNCE_X | bounce) & (BOUNCE_X | BOUNCE_Y);
bounce |= check_bounce (b->x / 256, proj_y);
if (bounce & BOUNCE_UNDEF)
bounce = (BOUNCE_Y | bounce) & (BOUNCE_X | BOUNCE_Y);
bounce |= check_bounce (proj_x, proj_y);
if (bounce & BOUNCE_UNDEF)
bounce = BOUNCE_X | BOUNCE_Y;
bounce_rand_vector (b, bounce);
/* bounce in x direction */
if (bounce & (BOUNCE_X | BOUNCE_BRICK))
{
b->dir_x *= -1; /* invert x vector */
#if BOUNCE_SLOWDOWN
if (b->dir_x < 0)
{
b->dir_x += BOUNCE_SLOWDOWN;
} else
{
b->dir_x -= BOUNCE_SLOWDOWN;
}
#endif
}
/* bounce in y direction */
if (bounce & (BOUNCE_Y | BOUNCE_BRICK))
{
b->dir_y *= -1; /* invert y vector */
#if BOUNCE_SLOWDOWN
if (b->dir_y < 0)
{
b->dir_y += BOUNCE_SLOWDOWN;
} else
{
b->dir_y -= BOUNCE_SLOWDOWN;
}
#endif
}
b->y += b->dir_y;
b->x += b->dir_x;
if (!b->dir_x || !b->dir_y)
{
printf("Ball stopped!\n");
}
}
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);
}