polyadvent

A game engine from scratch in C
git clone git://jb55.com/polyadvent
Log | Files | Refs | README

commit 81a52fbdaabd1fc1e321d6dce6cbf55677f46e1f
parent 6bb1b1f05bcf2d7900cef18fc6ba1134769418c8
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 28 Jul 2019 16:04:32 -0700

initial physics and jumping

Diffstat:
Msrc/entity.c | 2+-
Msrc/entity.h | 7++++---
Msrc/game.c | 2+-
Msrc/node.c | 2+-
Msrc/render.c | 2+-
Msrc/terrain.c | 2+-
Msrc/terrain_collision.c | 18++++++++++++++----
Msrc/terrain_collision.h | 2+-
Msrc/update.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/vec3.h | 7++++---
10 files changed, 79 insertions(+), 24 deletions(-)

diff --git a/src/entity.c b/src/entity.c @@ -31,7 +31,7 @@ struct entity *init_entity(struct entity *ent, node_id *id) { else { ent->node_id = *id; } - ent->casts_shadows = 0; + ent->flags &= ~ENT_CASTS_SHADOWS; return ent; } diff --git a/src/entity.h b/src/entity.h @@ -11,8 +11,10 @@ #define MAX_ENTITIES 2048 enum entity_flags { - ENT_IS_PLAYER = 1 << 0, - ENT_INVISIBLE = 1 << 1, + ENT_IS_PLAYER = 1 << 0, + ENT_INVISIBLE = 1 << 1, + ENT_CASTS_SHADOWS = 1 << 2, + ENT_AT_REST = 1 << 3, }; struct entity { @@ -21,7 +23,6 @@ struct entity { u32 flags; float velocity[3]; float accel[3]; - int casts_shadows; }; typedef struct resource_id entity_id; diff --git a/src/game.c b/src/game.c @@ -178,7 +178,7 @@ void game_init(struct game *game, int width, int height) { // player entity init_id(&res->player_id); player = &static_entities()[entity_player]; - player->casts_shadows = 1; + player->flags |= ENT_CASTS_SHADOWS; struct node *pnode = &static_nodes()[node_player]; assert(pnode); res->player_id = make_static_id(entity_player); diff --git a/src/node.c b/src/node.c @@ -83,7 +83,7 @@ void node_scale(struct node *node, float val) { void node_translate(struct node *node, vec3 *p) { if (vec3_isall(p, 0)) - return; + return; /* printf("translating %f %f %f\n", p[0], p[1], p[2]); */ vec3_add(node->pos, p, node->pos); diff --git a/src/render.c b/src/render.c @@ -306,7 +306,7 @@ void render (struct game *game, struct render_config *config) { if (entity->flags & ENT_INVISIBLE) continue; - if (config->is_depth_pass && !entity->casts_shadows) + if (config->is_depth_pass && !(entity->flags & ENT_CASTS_SHADOWS)) continue; // TODO this is a bit wonky, refactor this diff --git a/src/terrain.c b/src/terrain.c @@ -66,7 +66,7 @@ void init_terrain(struct terrain *terrain, float size) { model->shading = SHADING_TERRAIN; node_set_label(node, "terrain"); - ent->casts_shadows = 0; + ent->flags &= ~ENT_CASTS_SHADOWS; // this is scale for some reason!? /* node->pos[2] = 20.0; */ diff --git a/src/terrain_collision.c b/src/terrain_collision.c @@ -82,7 +82,7 @@ static void terrain_tri_debug(float *verts, struct tri *tri) if (is_null_id(&tri->debug_id)) { - float tmp[3]; + float tmp[3], tmp2[3], normal[3]; float *v1 = &verts[tri->vert_indices[0]]; float *v2 = &verts[tri->vert_indices[1]]; @@ -94,7 +94,9 @@ static void terrain_tri_debug(float *verts, struct tri *tri) /* v3[0], v3[1]); */ vec3_subtract(v1, v2, tmp); + vec3_subtract(v2, v3, tmp2); + vec3_cross(tmp, tmp2, normal); /* debug("tmp %f %f\n", tmp[0], tmp[1]); */ vec3_scale(tmp, 0.5, tmp); @@ -105,7 +107,13 @@ static void terrain_tri_debug(float *verts, struct tri *tri) /* debug("creating new grid_debug entity at %f %f %f\n", tmp[0], tmp[1], tmp[2]); */ - new_debug_entity(&tri->debug_id, tmp); + struct entity *ent = new_debug_entity(&tri->debug_id, tmp); + struct node *node = get_node(&ent->node_id); + + vec3_normalize(normal, normal); + /* vec3_scale(normal, 180/PI, normal); */ + node_rotate(node, normal); + node_recalc(node); } } @@ -151,7 +159,7 @@ static void get_terrain_penetration(float *verts, struct tri *tri, float *pos, f } -void collide_terrain(struct terrain *terrain, float *pos, struct model *model, vec3 *move) +struct tri *collide_terrain(struct terrain *terrain, float *pos, struct model *model, vec3 *move) { struct terrain_cell *cells[9] = {0}; struct grid_query queries[3]; @@ -175,7 +183,9 @@ void collide_terrain(struct terrain *terrain, float *pos, struct model *model, v if ((tri = point_in_vert_tris(terrain->verts, vtris, pos))) { terrain_tri_debug(terrain->verts, tri); get_terrain_penetration(terrain->verts, tri, pos, move); - return; + return tri; } } + + return NULL; } diff --git a/src/terrain_collision.h b/src/terrain_collision.h @@ -6,6 +6,6 @@ #include "node.h" #include "model.h" -void collide_terrain(struct terrain *terrain, float *pos, struct model *model, float *move); +struct tri *collide_terrain(struct terrain *terrain, float *pos, struct model *model, float *move); #endif /* TERRAIN_COLLISION_H */ diff --git a/src/update.c b/src/update.c @@ -23,7 +23,7 @@ static void movement(struct game *game, struct node *node, float speed_mult) { amt *= speed_mult; if (game->input.modifiers & KMOD_SHIFT) - amt *= 50; + amt *= 20; if (game->input.keystates[SDL_SCANCODE_A]) node_forward(node, V3(-amt,0,0)); @@ -240,12 +240,15 @@ static void day_night_cycle(float time, struct resources *res) { static void gravity(struct game *game) { struct entity *player = get_player(&game->test_resources); + + if (player->flags & ENT_AT_REST) + return; + struct node *pnode = get_node(&player->node_id); assert(pnode); static const float g = -1.0; - - node_translate(pnode, V3(0.0, 0.0, g)); + vec3_add(player->velocity, V3(0.0, 0.0, g * game->dt), player->velocity); } void orbit_update_from_mouse(struct orbit *camera, struct input *input, @@ -315,6 +318,15 @@ static void camera_keep_above_ground(struct terrain *terrain, } } +static void entity_jump(struct entity *ent) +{ + if (ent->flags & ENT_AT_REST) { + struct node *node = get_node(&ent->node_id); + debug("jumping\n"); + vec3_forward(ent->velocity, node->orientation, V3(0.0, 0.0, 1.0), ent->velocity); + } +} + static void player_update(struct game *game, struct entity *player) { @@ -341,11 +353,41 @@ static void player_update(struct game *game, struct entity *player) /* player_terrain_collision(terrain, node); */ float move[3]; - collide_terrain(terrain, node_world(node), NULL, move); - node_translate(node, move); - /* vec3_add(player->velocity, move, player->velocity); */ + float scaled[3]; + struct tri *tri = collide_terrain(terrain, node_world(node), NULL, move); + /* node_translate(node, move); */ + + if (tri) { + if (move[2] >= 0) { + node_translate(node, move); + player->flags |= ENT_AT_REST; + vec3_all(player->velocity, 0); + } + else { + player->flags &= ~ENT_AT_REST; + } + } + + if (was_key_pressed_this_frame(game, SDL_SCANCODE_SPACE)) { + entity_jump(player); + } + + if (!vec3_approxeq(player->velocity, V3(0,0,0))) + player->flags &= ~ENT_AT_REST; + /* debug("player velocity %f %f %f\n", */ + /* player->velocity[0], */ + /* player->velocity[1], */ + /* player->velocity[2]); */ + /* if (player->flags & ENT_AT_REST) */ + /* vec3_scale(player->velocity, 0.00001, player->velocity); */ + + if (!(player->flags & ENT_AT_REST)) { + debug("player not a rest\n"); + node_translate(node, player->velocity); + node_recalc(node); + } } @@ -366,7 +408,7 @@ void update (struct game *game) { float *time = &res->time; float *light = res->light_dir; - /* gravity(game); */ + gravity(game); if (needs_terrain_update) { /* update_terrain(terrain); */ @@ -401,8 +443,9 @@ void update (struct game *game) { game->wireframe ^= 1; } - if (was_key_pressed_this_frame(game, SDL_SCANCODE_C)) + if (was_key_pressed_this_frame(game, SDL_SCANCODE_C)) { printf("light_dir %f %f %f\n", light[0], light[1], light[2]); + } if (was_key_pressed_this_frame(game, SDL_SCANCODE_F)) toggle_fog = 1; diff --git a/src/vec3.h b/src/vec3.h @@ -7,6 +7,9 @@ typedef float vec3; +#define approxeq(a, b) (fabs(a-b) < EPSILON) +#define EPSILON 0.0001 +#define vec3_approxeq(a, b) vec3_eq(a, b, EPSILON) #define V3(x,y,z) ((vec3[3]){x,y,z}) static inline vec3 *vec3_create(vec3 *vec) { @@ -221,7 +224,7 @@ static inline vec3 *vec3_all(vec3 *vec, float n) { static inline int vec3_isall(vec3 *vec, float n) { for (int i = 0; i < 3; ++i) { - if (vec[i] != n) + if (!approxeq(vec[i], n)) return 0; } @@ -274,8 +277,6 @@ static inline vec3 *vec3_from_yaw_pitch(float yaw, float pitch, float *dest) { return dest; } -#define EPSILON 0.0001 -#define vec3_approxeq(a, b) vec3_eq(a, b, EPSILON) #endif /* VEC3_H */