add player rotation and collisions

This commit is contained in:
Lephenixnoir 2021-08-21 14:49:01 +02:00
parent 798ff9b409
commit df576a3048
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
5 changed files with 135 additions and 15 deletions

View File

@ -12,7 +12,7 @@ find_package(Gint 2.1 REQUIRED)
set(SOURCES
src/main.c
src/render.c
# ...
src/physics.c
)
set(ASSETS
assets-cg/example.png

View File

@ -55,6 +55,10 @@ typedef struct {
// Game
//---
#define PLAYER_X 55
#define PLAYER_R 35
#define PLAYER_SIZE 6
typedef struct {
float w, h; /* px */
float x, y; /* px */
@ -65,7 +69,7 @@ typedef struct {
#define RECT_TABLE_SIZE 20
struct game {
typedef struct game {
int dead;
float time;
level_t *level;
@ -73,7 +77,7 @@ struct game {
rect_t table[RECT_TABLE_SIZE];
int cursor;
float player_rota;
};
} game_t;
//---
// Rendering
@ -84,3 +88,15 @@ void dcircle(int x, int y, int r, int color, bool fill);
void dtriangle(int x1, int y1, int x2, int y2, int x3, int y3, int color);
void drectoid(rect_t const *r, int color);
void render_player(float angle);
//---
// Physics
//---
void player_position(float angle,
float *x1, float *y1, float *x2, float *y2);
bool player_collision(game_t const *game);
bool rect_circle_collide(rect_t const *r, int cx, int cy, int cr);

View File

@ -35,45 +35,83 @@ level_t level0 = {
int main(void)
{
volatile int need_frame;
struct game game;
volatile int need_frame = 1;
game_t game;
float dt = 0;
int timer;
__printf_enable_fp();
memset(&game, 0x00, sizeof(struct game));
memset(&game, 0x00, sizeof game);
game.level = &level0;
/* Temporary level */
game.table[0] = (rect_t){
.w=80, .h=20, .x=440, .y=50, .vx=-100, .vy=0, .r=0, .vr=0.5
};
game.cursor = 1;
timer = timer_configure(TIMER_ANY, 33000, GINT_CALL_SET(&need_frame));
timer_start(timer);
while (1) {
/* Time management */
while (need_frame == 0) sleep();
need_frame = 0;
dt = (1.0 / 30) * level0.tempo;
game.time += 1.0 / 30;
/* Input analysis */
bool rotate_left=false, rotate_right=false;
key_event_t e;
while ((e = pollevent()).type != KEYEV_NONE) {
if (e.type == KEYEV_DOWN && e.key == KEY_MENU)
gint_osmenu();
}
if (keydown(KEY_7)) {
game.player_rota += dt;
rotate_left = true;
}
if (keydown(KEY_0)) {
game.player_rota -= dt;
rotate_right = true;
}
//TODO: physix
/* Level generation */
/* TODO */
dclear(C_BLACK);
/* Physics */
// if(player_collision(&game))
// break;
for(int i = 0; i < game.cursor; i++) {
rect_t *r = &game.table[i];
r->x += r->vx * dt;
r->y += r->vy * dt;
r->r += r->vr * dt;
}
if(rotate_left)
game.player_rota += M_PI * dt;
if(rotate_right)
game.player_rota -= M_PI * dt;
/* Rendering */
dclear(player_collision(&game) ? C_RED : C_BLACK);
dprint(0, 0, C_WHITE, "game time: %.2fs", game.time);
dprint(0, 11, C_WHITE, "player rota: %.2f rad", game.player_rota);
dupdate();
while (need_frame == 0)
sleep();
need_frame = 0;
for(int i = 0; i < game.cursor; i++)
drectoid(&game.table[i], C_WHITE);
render_player(game.player_rota);
dupdate();
}
timer_stop(timer);
return (1);
}

54
src/physics.c Normal file
View File

@ -0,0 +1,54 @@
#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->cursor; i++) {
if(rect_circle_collide(&game->table[i], x1, y1, PLAYER_SIZE))
return true;
if(rect_circle_collide(&game->table[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;
}

View File

@ -97,3 +97,15 @@ void drectoid(rect_t const *r, int color)
dtriangle(x[0], y[0], x[1], y[1], x[2], y[2], color);
dtriangle(x[2], y[2], x[3], y[3], x[0], y[0], color);
}
void render_player(float angle)
{
int x=PLAYER_X, y=DHEIGHT/2;
dcircle(x, y, PLAYER_R, C_WHITE, false);
float x1, y1, x2, y2;
player_position(angle, &x1, &y1, &x2, &y2);
dcircle(x1, y1, PLAYER_SIZE, C_RGB(0, 16, 26), true);
dcircle(x2, y2, PLAYER_SIZE, C_RGB(31, 6, 0), true);
}