platformer physics

This commit is contained in:
KikooDX 2021-12-17 00:20:39 +01:00
parent 689044f03b
commit 6f3eda4353
8 changed files with 127 additions and 13 deletions

View File

@ -11,6 +11,7 @@ include_directories(inc)
set(SOURCES
src/main.c
src/util.c
src/draw.c
src/input.c
src/level.c

View File

@ -1,4 +1,13 @@
#pragma once
#define TILE_SIZE 16
#define TILE_OOB 0
#define TILE_SIZE 16
#define PLAYER_WIDTH 12
#define PLAYER_HEIGHT 12
#define MAX_WALK_SPEED 2.0f
#define AIR_ACCELERATION 0.4f
#define GROUND_ACCELERATION 0.4f
#define AIR_FRICTION (AIR_ACCELERATION / MAX_WALK_SPEED)
#define GROUND_FRICTION (GROUND_ACCELERATION / MAX_WALK_SPEED)
#define AIR_RESISTANCE 0.02f
#define GRAVITY 0.2f
#define JUMP_SPEED -4.0f

View File

@ -9,3 +9,4 @@ struct Player {
void player_init(struct Player *);
void player_update(struct Player *);
void player_draw(struct Player *);
void player_move(struct Player *, struct Vec);

7
inc/tile.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
enum Tile {
TILE_AIR,
TILE_SOLID,
TILE_OOB,
};

3
inc/util.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
int sign(int);

View File

@ -1,5 +1,6 @@
#include "level.h"
#include "conf.h"
#include "tile.h"
#include "visual_data.h"
#include <gint/display.h>
#include <stdlib.h>

View File

@ -1,33 +1,118 @@
#include "player.h"
#include "conf.h"
#include "draw.h"
#include "input.h"
#include "level.h"
#include "tile.h"
#include "util.h"
static void player_reset_speed(struct Player *);
static void reset_speed(struct Player *, int x, int y);
static struct Vec update_rem(struct Player *);
static int collide_margin(int x, int y, int tile, int margin);
static int collide(int x, int y, int tile);
static int collide_solid(int x, int y);
void
player_init(struct Player *p)
{
p->pos.x = 0;
p->pos.y = 0;
player_reset_speed(p);
p->pos.x = TILE_SIZE;
p->pos.y = TILE_SIZE;
reset_speed(p, 1, 1);
}
void
player_update(struct Player *p)
{
p->pos.x++;
const int on_ground = collide_solid(p->pos.x, p->pos.y + 1);
const int k_left = input_down(K_LEFT);
const int k_right = input_down(K_RIGHT);
// const int k_up = input_down(K_UP);
// const int k_down = input_down(K_DOWN);
const int kp_jump = input_pressed(K_JUMP);
const int dir_x = k_right - k_left;
/* horizontal friction & acceleration */
p->spd.x *= on_ground ? (1 - GROUND_FRICTION) : (1 - AIR_FRICTION);
p->spd.x +=
dir_x * (on_ground ? GROUND_ACCELERATION : AIR_ACCELERATION);
/* air resistance & gravity */
p->spd.y *= (1 - AIR_RESISTANCE);
p->spd.y += GRAVITY;
/* jump */
if (on_ground && kp_jump) p->spd.y = JUMP_SPEED;
player_move(p, update_rem(p));
}
void
player_draw(struct Player *p)
{
draw_rectangle(C_WHITE, p->pos.x, p->pos.y, 16, 16);
draw_rectangle(C_WHITE, p->pos.x, p->pos.y, PLAYER_WIDTH,
PLAYER_HEIGHT);
}
void
player_move(struct Player *p, struct Vec spd)
{
float sign_x = sign(spd.x);
const float sign_y = sign(spd.y);
if (!sign_x && !sign_y) sign_x = 1.0f;
p->pos.x += spd.x;
if (collide_solid(p->pos.x, p->pos.y)) reset_speed(p, 1, 0);
while (collide_solid(p->pos.x, p->pos.y))
p->pos.x -= sign_x;
p->pos.y += spd.y;
if (collide_solid(p->pos.x, p->pos.y)) reset_speed(p, 0, 1);
while (collide_solid(p->pos.x, p->pos.y))
p->pos.y -= sign_y;
}
static void
player_reset_speed(struct Player *p)
reset_speed(struct Player *p, int x, int y)
{
p->spd.x = 0.0f;
p->spd.y = 0.0f;
p->rem.x = 0.0f;
p->rem.y = 0.0f;
if (x) {
p->spd.x = 0.0f;
p->rem.x = 0.0f;
}
if (y) {
p->spd.y = 0.0f;
p->rem.y = 0.0f;
}
}
static struct Vec
update_rem(struct Player *p)
{
struct VecF spd_n_rem = {p->spd.x + p->rem.x, p->spd.y + p->rem.y};
struct Vec spd_trunc = {spd_n_rem.x, spd_n_rem.y};
p->rem.x = spd_n_rem.x - (float)spd_trunc.x;
p->rem.y = spd_n_rem.y - (float)spd_trunc.y;
return spd_trunc;
}
static int
collide_margin(int x, int y, int tile, int margin)
{
const int x1 = x + margin;
const int x2 = x + PLAYER_WIDTH - 1 - margin;
const int y1 = y + margin;
const int y2 = y + PLAYER_HEIGHT - 1 - margin;
return level_get_px(x1, y1) == tile || level_get_px(x2, y1) == tile ||
level_get_px(x1, y2) == tile || level_get_px(x2, y2) == tile;
}
static int
collide(int x, int y, int tile)
{
return collide_margin(x, y, tile, 0);
}
static int
collide_solid(int x, int y)
{
return collide(x, y, TILE_SOLID);
}

7
src/util.c Normal file
View File

@ -0,0 +1,7 @@
#include "util.h"
int
sign(int x)
{
return (x > 0) - (x < 0);
}