Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 5 additions & 13 deletions example/game/main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
// 0 null, 1-127 texture_id, 128-255 color_id
static uint8_t map[ROWS][COLS] = {0};

void test_sprite_script(GameState *state, Sprite *self) {
void test_sprite_script(GameState *state, Entity *self) {
(void)state;
float incX = sinf(get_time());
float incY = cosf(get_time());
Expand All @@ -38,16 +38,6 @@ void test_sprite_script(GameState *state, Sprite *self) {
else self->texture_id = tx_greenlight;
}

Sprite sprites[] = {
{.pos = {6.5, 4.5}, .texture_id = tx_pillar, .vmove=-0.7, .collision_threshold = 0.25, .collision_mask = 1},
{.pos = {5.5, 5.5}, .texture_id = tx_greenlight, .update = test_sprite_script, .collision_threshold = 0.25, .collision_mask = 1},
{.pos = {2.5, 3.5}, .texture_id = tx_barrel, .collision_threshold = 0.25, .collision_mask = 1},
{.pos = {3.5, 3.5}, .texture_id = tx_barrel, .vmove=0.25, .collision_threshold = 0.25, .collision_mask = 1},
};
#define NUM_SPRITES ARRAY_LEN(sprites)



void init_map() {
for (int i = 0; i < ROWS; i++) {
map[i][0] = tx_bricks;
Expand Down Expand Up @@ -78,8 +68,10 @@ void init_game(GameState *state) {
state->map = (uint8_t *)map;
state->map_cols = COLS;
state->map_rows = ROWS;
state->sprites = sprites;
state->num_sprites = NUM_SPRITES;
da_append(&state->entities, ((Entity){.pos = {6.5, 4.5}, .texture_id = tx_pillar, .vmove=-0.7, .collision_threshold = 0.25, .collision_mask = 1}));
da_append(&state->entities, ((Entity){.pos = {5.5, 5.5}, .texture_id = tx_greenlight, .update = test_sprite_script, .collision_threshold = 0.25, .collision_mask = 1}));
da_append(&state->entities, ((Entity){.pos = {2.5, 3.5}, .texture_id = tx_barrel, .collision_threshold = 0.25, .collision_mask = 1}));
da_append(&state->entities, ((Entity){.pos = {3.5, 3.5}, .texture_id = tx_barrel, .vmove=0.25, .collision_threshold = 0.25, .collision_mask = 1}));
state->player = (Player){.pos = {10.5, 5.5}, .dir = {0, 1}, .collision_threshold = 0.15};
state->assets_map = assets_map;
state->floor_texture = tx_greystone;
Expand Down
82 changes: 82 additions & 0 deletions src/raycast/da.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#ifndef DA_H
#define DA_H

#ifndef DA_REALLOC
#include <stdlib.h>
#define DA_REALLOC realloc
#endif

#ifndef DA_FREE
#include <stdlib.h>
#define DA_FREE free
#endif

#ifndef DA_ASSERT
#include <assert.h>
#define DA_ASSERT assert
#endif

/**
* Dynamic array implementation
* The dynamic array struct should be defined by the user as follows:
* typedef struct {
* Type *data;
* size_t length;
* size_t capacity;
* ... // any additional fields
* } DynamicArray;
*/

#define DA_INIT_CAPACITY 16

#define da_reserve(da, expected_capacity) \
do { \
if ((size_t)(expected_capacity) > (da)->capacity) { \
if ((da)->capacity == 0) { \
if ((size_t)(expected_capacity) > DA_INIT_CAPACITY) \
(da)->capacity = (size_t)(expected_capacity); \
else \
(da)->capacity = DA_INIT_CAPACITY; \
} else { \
if ((size_t)(expected_capacity) > (da)->capacity * 2) \
(da)->capacity = (size_t)(expected_capacity); \
else \
(da)->capacity *= 2; \
} \
(da)->data = DA_REALLOC((da)->data, (da)->capacity * sizeof(*(da)->data)); \
DA_ASSERT((da)->data != NULL); \
} \
} while (0)

#define da_append(da, item) \
do { \
da_reserve((da), (da)->length + 1); \
(da)->data[(da)->length++] = (item); \
} while (0)

#define da_remove_unordered(da, idx) \
do { \
(da)->data[(idx)] = (da)->data[(da)->length - 1]; \
(da)->length--; \
} while (0)

#define da_shrink(da, capacity) \
do { \
if ((da)->capacity > (capacity)) { \
(da)->capacity = (capacity); \
(da)->data = DA_REALLOC((da)->data, (da)->capacity * sizeof(*(da)->data)); \
DA_ASSERT((da)->data != NULL); \
} \
} while (0)

#define da_shrink_to_fit(da) da_shrink((da), (da)->length)

#define da_free(da) \
do { \
DA_FREE((da)->data); \
(da)->data = NULL; \
(da)->length = 0; \
(da)->capacity = 0; \
} while (0)

#endif // DA_H
5 changes: 3 additions & 2 deletions src/raycast/physics.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ bool check_player_collision(GameState *state, Vector2 next_pos) {
if(state->map[cell_y * state->map_cols + cell_x]) {
return true;
}
for(size_t i=0; i<state->num_sprites; i++) {
Sprite *sprite = &state->sprites[i];
for(size_t i=0; i<state->entities.length; i++) {
if(state->entities.data[i].disabled) continue;
Entity *sprite = &state->entities.data[i];
if(!sprite->collision_mask) continue;
if(Vector2Distance(next_pos, sprite->pos) < sprite->collision_threshold + state->player.collision_threshold) {
return true;
Expand Down
8 changes: 8 additions & 0 deletions src/raycast/platform/wasm/wasm_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ void *malloc(size_t size) {
return p;
}

void *realloc(void *ptr, size_t size) {
(void)ptr; // bump allocator doesn't free, so realloc is just malloc
return malloc(size);
}

void free(void *ptr) {
(void)ptr; // bump allocator doesn't free
}
Expand Down Expand Up @@ -96,3 +101,6 @@ void qsort(void *base, size_t nmemb, size_t size,
// =================== abs ===================

int abs(int x) { return x < 0 ? -x : x; }

// =================== assert ===================
void assert(int condition) {}
7 changes: 7 additions & 0 deletions src/raycast/platform/wasm/wasm_sysroot/assert.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Stub stdlib.h for WASM freestanding build
#ifndef _WASM_ASSERT_H
#define _WASM_ASSERT_H

void assert(int);

#endif
1 change: 1 addition & 0 deletions src/raycast/platform/wasm/wasm_sysroot/stdlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <stddef.h>

void *malloc(size_t);
void *realloc(void *, size_t);
void free(void *);
int abs(int);
void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
Expand Down
24 changes: 13 additions & 11 deletions src/raycast/raycast.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#define THRESHOLD 0.0001

static int compare_sprite_dist(const void *a, const void *b) {
const Sprite *sa = (const Sprite *)a;
const Sprite *sb = (const Sprite *)b;
const Entity *sa = (const Entity *)a;
const Entity *sb = (const Entity *)b;
if (sa->dist < sb->dist) return 1;
if (sa->dist > sb->dist) return -1;
return 0;
Expand Down Expand Up @@ -142,24 +142,26 @@ void draw_background(GameState *state) {
}
}

void draw_sprites(GameState *state) {
void draw_entities(GameState *state) {
Player *p = &state->player;
for (size_t i = 0; i < state->num_sprites; i++) {
if (state->sprites[i].update) {
state->sprites[i].update(state, &state->sprites[i]);
for (size_t i = 0; i < state->entities.length; i++) {
if (state->entities.data[i].disabled) continue;
if (state->entities.data[i].update) {
state->entities.data[i].update(state, &state->entities.data[i]);
}
state->sprites[i].dist = Vector2LengthSqr(Vector2Subtract(state->sprites[i].pos, p->pos));
state->entities.data[i].dist = Vector2LengthSqr(Vector2Subtract(state->entities.data[i].pos, p->pos));
}

qsort(state->sprites, state->num_sprites, sizeof(Sprite), compare_sprite_dist);
qsort(state->entities.data, state->entities.length, sizeof(Entity), compare_sprite_dist);

Vector2 plane = {
-p->dir.y * tanf(FOV_ANGLE / 2.0f),
p->dir.x * tanf(FOV_ANGLE / 2.0f)
};

for (size_t i = 0; i < state->num_sprites; i++) {
Sprite sprite = state->sprites[i];
for (size_t i = 0; i < state->entities.length; i++) {
if (state->entities.data[i].disabled) continue;
Entity sprite = state->entities.data[i];

Vector2 rel = Vector2Subtract(sprite.pos, p->pos);
float invDet = 1.0f / (plane.x * p->dir.y - p->dir.x * plane.y);
Expand Down Expand Up @@ -231,7 +233,7 @@ void _init_game() {
void draw_game() {
draw_background(&state);
draw_walls(&state);
draw_sprites(&state);
draw_entities(&state);
}


Expand Down
20 changes: 14 additions & 6 deletions src/raycast/raycast.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "renderer.h"
#include "inputs.h"
#include "colors.h"
#include "da.h"

typedef struct {
Vector2 pos;
Expand All @@ -16,17 +17,25 @@ typedef struct {

typedef struct GameState GameState;

typedef struct Sprite {
typedef struct Entity {
Vector2 pos;
int texture_id;
float dist;
float vdiv;
float hdiv;
float vmove;
bool disabled;
void *data;
uint32_t collision_mask;
float collision_threshold;
void (*update)(GameState *state, struct Sprite *self);
} Sprite;
void (*update)(GameState *state, struct Entity *self);
} Entity;

typedef struct {
Entity *data;
size_t length;
size_t capacity;
} Entities;

typedef struct GameState {
Player player;
Expand All @@ -37,8 +46,7 @@ typedef struct GameState {
uint8_t *map;
uint8_t map_cols;
uint8_t map_rows;
Sprite *sprites;
size_t num_sprites;
Entities entities;
unsigned int ray_res;
float *zbuffer;
const pixel_t **assets_map;
Expand All @@ -54,7 +62,7 @@ void draw_walls(GameState *state);

void draw_background(GameState *state);

void draw_sprites(GameState *state);
void draw_entities(GameState *state);

void draw_game();

Expand Down