161 lines
4.0 KiB
C
161 lines
4.0 KiB
C
#include "duet.h"
|
|
|
|
void player_position(float angle,
|
|
float *x1, float *y1, float *x2, float *y2)
|
|
{
|
|
int x=PLAYER_X, y=DHEIGHT/2;
|
|
|
|
float sin, cos;
|
|
sincosf(angle, &sin, &cos);
|
|
|
|
if(x1) *x1 = x + sin * PLAYER_R;
|
|
if(y1) *y1 = y + cos * PLAYER_R;
|
|
|
|
if(x2) *x2 = x - sin * PLAYER_R;
|
|
if(y2) *y2 = y - cos * PLAYER_R;
|
|
}
|
|
|
|
bool player_collision(game_t const *game)
|
|
{
|
|
float x1, y1, x2, y2;
|
|
player_position(game->player_rota, &x1, &y1, &x2, &y2);
|
|
|
|
for(int i = 0; i < game->rect_count; i++) {
|
|
if(rect_circle_collide(&game->rects[i], x1, y1, PLAYER_SIZE))
|
|
return true;
|
|
if(rect_circle_collide(&game->rects[i], x2, y2, PLAYER_SIZE))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool rect_circle_collide(rect_t const *r, int cx0, int cy0, int cr)
|
|
{
|
|
/* Translate so that rectangle center is (0,0) */
|
|
cx0 -= r->x;
|
|
cy0 -= r->y;
|
|
|
|
/* Rotate so that rectangle is flat */
|
|
float sin, cos;
|
|
sincosf(-r->r, &sin, &cos);
|
|
float cx = cx0 * cos + cy0 * sin;
|
|
float cy = -cx0 * sin + cy0 * cos;
|
|
|
|
/* Determine point of rectangle closest to center of circle */
|
|
float clx=cx, cly=cy;
|
|
if(clx < -r->w/2) clx = -r->w/2;
|
|
if(clx > r->w/2) clx = r->w/2;
|
|
if(cly < -r->h/2) cly = -r->h/2;
|
|
if(cly > r->h/2) cly = r->h/2;
|
|
|
|
/* Determine whether that point is in the circle */
|
|
|
|
return (clx - cx) * (clx - cx) + (cly - cy) * (cly - cy) <= cr * cr;
|
|
}
|
|
|
|
void rect_load(rect_t *r, rectmeta_t const *meta)
|
|
{
|
|
r->w = 0;
|
|
r->h = 0;
|
|
|
|
switch(meta->shape) {
|
|
case Shape_Square:
|
|
r->w = 0.4;
|
|
r->h = 0.5;
|
|
break;
|
|
case Shape_SmallBar:
|
|
r->w = 0.2;
|
|
r->h = 0.5;
|
|
break;
|
|
case Shape_MediumBar:
|
|
r->w = 0.2;
|
|
r->h = 0.62;
|
|
break;
|
|
case Shape_NormalBar:
|
|
r->w = 0.2;
|
|
r->h = 1.0;
|
|
break;
|
|
case Shape_LongBar:
|
|
r->w = 0.2;
|
|
r->h = 1.15;
|
|
break;
|
|
case Shape_HugeBar:
|
|
r->w = 0.2;
|
|
r->h = 1.5;
|
|
break;
|
|
case Shape_LongVertical:
|
|
r->w = 0.8;
|
|
r->h = 0.2;
|
|
break;
|
|
}
|
|
|
|
r->w *= 2 * PLAYER_R;
|
|
r->h *= 2 * PLAYER_R;
|
|
|
|
switch(meta->position) {
|
|
case Position_Left:
|
|
if(meta->shape == Shape_Square)
|
|
r->y = DHEIGHT/2 - 0.22*CORRIDOR_SIZE;
|
|
else if(meta->shape == Shape_HugeBar)
|
|
r->y = DHEIGHT/2 - 0.38*CORRIDOR_SIZE;
|
|
else
|
|
r->y = DHEIGHT/2 - CORRIDOR_SIZE/2 + r->h/2;
|
|
break;
|
|
case Position_Right:
|
|
if(meta->shape == Shape_Square)
|
|
r->y = DHEIGHT/2 + 0.22*CORRIDOR_SIZE;
|
|
else if(meta->shape == Shape_HugeBar)
|
|
r->y = DHEIGHT/2 + 0.38*CORRIDOR_SIZE;
|
|
else
|
|
r->y = DHEIGHT/2 + CORRIDOR_SIZE/2 - r->h/2;
|
|
break;
|
|
case Position_Middle:
|
|
r->y = DHEIGHT/2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void rect_physics(rect_t *r, rectmeta_t const *meta, float absolute_time)
|
|
{
|
|
float time = absolute_time - meta->time; /* <= 0 most of the time */
|
|
|
|
r->x = PLAYER_X - RECT_SPEED * time;
|
|
r->r = 0;
|
|
|
|
if(meta->action == Action_RotateLeft) {
|
|
float vr = 2.0; /* rad/tempo */
|
|
r->r = -0.3 + time * vr;
|
|
}
|
|
else if(meta->action == Action_RotateRight) {
|
|
float vr = 2.0; /* rad/tempo */
|
|
r->r = 0.3 - time * vr;
|
|
}
|
|
else if(meta->action == Action_Speed1) {
|
|
/* Double speed between -8 and -6 to skip 2 tempos */
|
|
float speeding_period = fminf(2.0, fmaxf(0.0, time + 6.0));
|
|
r->x -= RECT_SPEED * speeding_period;
|
|
}
|
|
else if(meta->action == Action_FadeOut) {
|
|
// TODO
|
|
}
|
|
else if(meta->action == Action_OuterRotateLeft) {
|
|
float vr = 0.7; /* rad/tempo */
|
|
r->r = time * vr;
|
|
}
|
|
else if(meta->action == Action_OuterRotateRight) {
|
|
float vr = 0.7; /* rad/tempo */
|
|
r->r = -time * vr;
|
|
}
|
|
else if(meta->action == Action_Slide) {
|
|
// TODO
|
|
}
|
|
else if(meta->action == Action_Speed2) {
|
|
/* Double speed permanently */
|
|
// TODO
|
|
}
|
|
else if(meta->action == Action_Speed3) {
|
|
// TODO
|
|
}
|
|
}
|