mirror of https://git.sr.ht/~kikoodx/crystal-tower
player collision code
This commit is contained in:
parent
6e8041a926
commit
c0c4630095
|
@ -16,6 +16,7 @@ set(SOURCES
|
|||
src/input.c
|
||||
src/level.c
|
||||
src/player.c
|
||||
src/util.c
|
||||
)
|
||||
|
||||
set(LEVELS
|
||||
|
|
12
inc/level.h
12
inc/level.h
|
@ -17,7 +17,11 @@ struct Level {
|
|||
char *data;
|
||||
};
|
||||
|
||||
struct Level level_load(struct LevelBin *restrict);
|
||||
void level_free(struct Level *restrict);
|
||||
void level_draw(struct Level *restrict);
|
||||
struct Vec level_find(struct Level *restrict, enum Tile);
|
||||
void level_load(struct LevelBin *);
|
||||
void level_free(void);
|
||||
void level_draw(void);
|
||||
struct Vec level_find(enum Tile);
|
||||
enum Tile level_get(int x, int y);
|
||||
enum Tile level_get_px(int x, int y);
|
||||
void level_set(int x, int y, enum Tile v);
|
||||
void level_set_px(int x, int y, enum Tile v);
|
||||
|
|
|
@ -7,6 +7,9 @@ struct Player {
|
|||
struct VecF rem;
|
||||
};
|
||||
|
||||
struct Player player_new(struct Vec pos);
|
||||
void player_update(struct Player *restrict);
|
||||
void player_draw(struct Player *restrict);
|
||||
void player_init(struct Vec pos);
|
||||
void player_update(void);
|
||||
void player_draw(void);
|
||||
/* return truncated speed */
|
||||
struct Vec player_update_rem(void);
|
||||
void player_move(struct Vec spd);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
enum Tile { TILE_VOID, TILE_SOLID };
|
||||
enum Tile { TILE_VOID, TILE_SOLID, TILE_OOB = TILE_SOLID };
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
int sign(int);
|
||||
float signf(float);
|
|
@ -16,4 +16,4 @@ struct VecF {
|
|||
|
||||
#define VECF(x, y) \
|
||||
(struct VecF) { x, y }
|
||||
#define VECFZ VECF(0.0, 0.0)
|
||||
#define VECFZ VECF(0.0f, 0.0f)
|
||||
|
|
68
src/level.c
68
src/level.c
|
@ -5,29 +5,29 @@
|
|||
#include <gint/display.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct Level
|
||||
level_load(struct LevelBin *restrict s)
|
||||
static struct Level self;
|
||||
|
||||
void
|
||||
level_load(struct LevelBin *s)
|
||||
{
|
||||
struct Level level;
|
||||
int i = s->width * s->height;
|
||||
level.width = s->width;
|
||||
level.height = s->height;
|
||||
level.size = i;
|
||||
level.data = malloc(i);
|
||||
self.width = s->width;
|
||||
self.height = s->height;
|
||||
self.size = i;
|
||||
self.data = malloc(i);
|
||||
while (i-- > 0) {
|
||||
level.data[i] = s->data[i];
|
||||
self.data[i] = s->data[i];
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
void
|
||||
level_free(struct Level *restrict s)
|
||||
level_free(void)
|
||||
{
|
||||
free(s->data);
|
||||
free(self.data);
|
||||
}
|
||||
|
||||
void
|
||||
level_draw(struct Level *restrict s)
|
||||
level_draw(void)
|
||||
{
|
||||
extern bopti_image_t bimg_tileset;
|
||||
const int tileset_width = bimg_tileset.width / TILE_SIZE;
|
||||
|
@ -35,17 +35,17 @@ level_draw(struct Level *restrict s)
|
|||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
for (i = 0; i < s->size; i++) {
|
||||
for (i = 0; i < self.size; i++) {
|
||||
const int sx = x * TILE_SIZE;
|
||||
const int sy = y * TILE_SIZE;
|
||||
const int tile = s->data[i];
|
||||
const int tile = self.data[i];
|
||||
const int rx = tile % tileset_width * TILE_SIZE;
|
||||
const int ry = tile / tileset_width * TILE_SIZE;
|
||||
|
||||
dsubimage(sx, sy, &bimg_tileset, rx, ry, TILE_SIZE, TILE_SIZE,
|
||||
DIMAGE_NONE);
|
||||
|
||||
if (++x >= s->width) {
|
||||
if (++x >= self.width) {
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
|
@ -53,15 +53,43 @@ level_draw(struct Level *restrict s)
|
|||
}
|
||||
|
||||
struct Vec
|
||||
level_find(struct Level *restrict s, enum Tile seek)
|
||||
level_find(enum Tile seek)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < s->size; i++) {
|
||||
const enum Tile tile = s->data[i];
|
||||
for (i = 0; i < self.size; i++) {
|
||||
const enum Tile tile = self.data[i];
|
||||
if (tile == seek) {
|
||||
return VEC(i % s->width * TILE_SIZE,
|
||||
(int)(i / s->height) * TILE_SIZE);
|
||||
return VEC(i % self.width * TILE_SIZE,
|
||||
(int)(i / self.height) * TILE_SIZE);
|
||||
}
|
||||
}
|
||||
return VEC(0, 0);
|
||||
}
|
||||
|
||||
enum Tile
|
||||
level_get(int x, int y)
|
||||
{
|
||||
if (x < 0 || y < 0 || x >= self.width || y >= self.height)
|
||||
return TILE_OOB;
|
||||
return self.data[x + y * self.width];
|
||||
}
|
||||
|
||||
enum Tile
|
||||
level_get_px(int x, int y)
|
||||
{
|
||||
return level_get(x / TILE_SIZE, y / TILE_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
level_set(int x, int y, enum Tile v)
|
||||
{
|
||||
if (x < 0 || y < 0 || x >= self.width || y >= self.height)
|
||||
return;
|
||||
self.data[x + y * self.size] = v;
|
||||
}
|
||||
|
||||
void
|
||||
level_set_px(int x, int y, enum Tile v)
|
||||
{
|
||||
level_set(x / TILE_SIZE, y / TILE_SIZE, v);
|
||||
}
|
||||
|
|
13
src/main.c
13
src/main.c
|
@ -8,7 +8,6 @@
|
|||
#include <gint/timer.h>
|
||||
|
||||
extern struct LevelBin lvl_test;
|
||||
struct Level level;
|
||||
struct Player player;
|
||||
|
||||
static void update(void);
|
||||
|
@ -26,8 +25,8 @@ main(void)
|
|||
GINT_CALL(callback, &has_ticked));
|
||||
timer_start(timer);
|
||||
input_init();
|
||||
level = level_load(&lvl_test);
|
||||
player = player_new(VECZ);
|
||||
level_load(&lvl_test);
|
||||
player_init(level_find(TILE_VOID));
|
||||
|
||||
while (!input_pressed(K_EXIT)) {
|
||||
int i;
|
||||
|
@ -45,7 +44,7 @@ main(void)
|
|||
}
|
||||
|
||||
timer_stop(timer);
|
||||
level_free(&level);
|
||||
level_free();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -53,15 +52,15 @@ static void
|
|||
update(void)
|
||||
{
|
||||
input_update();
|
||||
player_update(&player);
|
||||
player_update();
|
||||
}
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
dclear(C_BLACK);
|
||||
level_draw(&level);
|
||||
player_draw(&player);
|
||||
level_draw();
|
||||
player_draw();
|
||||
dupdate();
|
||||
}
|
||||
|
||||
|
|
80
src/player.c
80
src/player.c
|
@ -1,28 +1,82 @@
|
|||
#include "player.h"
|
||||
#include "conf.h"
|
||||
#include "level.h"
|
||||
#include "util.h"
|
||||
#include "vec.h"
|
||||
#include <gint/display.h>
|
||||
|
||||
struct Player
|
||||
player_new(struct Vec pos)
|
||||
static struct Player self;
|
||||
|
||||
static int collide_solid(int x, int y);
|
||||
|
||||
void
|
||||
player_init(struct Vec pos)
|
||||
{
|
||||
struct Player p;
|
||||
p.pos = pos;
|
||||
p.spd = VECFZ;
|
||||
p.rem = VECFZ;
|
||||
return p;
|
||||
self.pos = pos;
|
||||
self.spd = VECFZ;
|
||||
self.rem = VECFZ;
|
||||
}
|
||||
|
||||
void
|
||||
player_update(struct Player *restrict p)
|
||||
player_update(void)
|
||||
{
|
||||
p->pos.x++;
|
||||
self.spd.x = 0.9f;
|
||||
player_move(player_update_rem());
|
||||
}
|
||||
|
||||
void
|
||||
player_draw(struct Player *restrict p)
|
||||
player_draw(void)
|
||||
{
|
||||
const int x2 = p->pos.x + PLAYER_WIDTH - 1;
|
||||
const int y2 = p->pos.y + PLAYER_HEIGHT - 1;
|
||||
drect(p->pos.x, p->pos.y, x2, y2, C_BLUE);
|
||||
const int x2 = self.pos.x + PLAYER_WIDTH - 1;
|
||||
const int y2 = self.pos.y + PLAYER_HEIGHT - 1;
|
||||
drect(self.pos.x, self.pos.y, x2, y2, C_BLUE);
|
||||
}
|
||||
|
||||
struct Vec
|
||||
player_update_rem(void)
|
||||
{
|
||||
struct VecF spd_n_rem = {self.spd.x + self.rem.x,
|
||||
self.spd.y + self.rem.y};
|
||||
struct Vec spd_trunc = {spd_n_rem.x, spd_n_rem.y};
|
||||
self.rem.x = spd_n_rem.x - (float)spd_trunc.x;
|
||||
self.rem.y = spd_n_rem.y - (float)spd_trunc.y;
|
||||
return spd_trunc;
|
||||
}
|
||||
|
||||
void
|
||||
player_move(struct Vec spd)
|
||||
{
|
||||
float sign_x = signf(spd.x);
|
||||
const float sign_y = signf(spd.y);
|
||||
if (!sign_x && !sign_y)
|
||||
sign_x = 1.0f;
|
||||
|
||||
self.pos.x += spd.x;
|
||||
if (collide_solid(self.pos.x, self.pos.y)) {
|
||||
self.spd.x = 0.0f;
|
||||
self.rem.x = 0.0f;
|
||||
}
|
||||
while (collide_solid(self.pos.x, self.pos.y)) {
|
||||
self.pos.x -= sign_x;
|
||||
}
|
||||
|
||||
self.pos.y += spd.y;
|
||||
if (collide_solid(self.pos.x, self.pos.y)) {
|
||||
self.spd.y = 0.0f;
|
||||
self.rem.y = 0.0f;
|
||||
}
|
||||
while (collide_solid(self.pos.x, self.pos.y)) {
|
||||
self.pos.y -= sign_y;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
collide_solid(int x, int y)
|
||||
{
|
||||
const int x2 = x + PLAYER_WIDTH - 1;
|
||||
const int y2 = y + PLAYER_HEIGHT - 1;
|
||||
return level_get_px(x, y) == TILE_SOLID ||
|
||||
level_get_px(x, y2) == TILE_SOLID ||
|
||||
level_get_px(x2, y) == TILE_SOLID ||
|
||||
level_get_px(x2, y2) == TILE_SOLID;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#include "util.h"
|
||||
|
||||
int
|
||||
sign(int n)
|
||||
{
|
||||
return (n > 0) - (n < 0);
|
||||
}
|
||||
|
||||
float
|
||||
signf(float n)
|
||||
{
|
||||
return (n > 0.0) - (n < 0.0);
|
||||
}
|
Loading…
Reference in New Issue