hs

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | LICENSE

commit 0ee369e1bb7805ef2016beda31cff725ed3b611f
parent 9b6dc6f0f086c48131e4b90347cbfe02ccfebd6e
Author: Samdal <samdal@protonmail.com>
Date:   Mon, 11 Oct 2021 17:06:38 +0200

better collision, mouse buttons, room collision

Diffstat:
Mhs_graphics.h | 176+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Mhs_math.h | 6++----
2 files changed, 138 insertions(+), 44 deletions(-)

diff --git a/hs_graphics.h b/hs_graphics.h @@ -54,7 +54,7 @@ typedef struct { } hs_camera2_smooth; typedef struct { - float pos[2], tex[2]; + vec2 pos, tex; } hs_tex_corner; typedef hs_tex_corner hs_tex_square[6]; @@ -94,6 +94,10 @@ typedef struct { typedef struct { vec2 pos, half_size; +} hs_rect2; + +typedef struct { + hs_rect2 r; uint32_t flags; hs_tex tex; hs_shader_program sp; @@ -139,6 +143,8 @@ extern void hs_close(const hs_game_data gd); extern int32_t hs_window_up(const hs_game_data gd); extern enum hs_key_state hs_get_key_toggle(const hs_game_data gd, hs_key* key); extern enum hs_key_state hs_get_key_held(const hs_game_data gd, const int key); +extern enum hs_key_state hs_get_mouse_toggle(const hs_game_data gd, hs_key* key); +extern enum hs_key_state hs_get_mouse_held(const hs_game_data gd, const int key); extern void hs_clear(const float r, const float g, const float b, const float a, const GLbitfield mask); extern void hs_vattrib_enable(const uint32_t index, const uint32_t size, const GLenum type, const uint32_t stride, const size_t pointer); @@ -193,14 +199,15 @@ extern vec2 hs_aabb2_half_size(const hs_aabb2 rect); extern vec2i hs_aabb2i_center(const hs_aabb2i rect); extern vec2i hs_aabb2i_size(const hs_aabb2i rect); extern vec2i hs_aabb2i_half_size(const hs_aabb2i rect); -extern hs_aabb2 hs_aabb2_from_entity(const hs_entity2_hot e); +extern hs_aabb2 hs_aabb2_from_rect2(const hs_rect2 r); /* Anders Tale Dungeon generation v3 (BSP) */ extern uint32_t hs_bsp_recti_split_in_place_append(hs_aabb2i* rects, const uint32_t new_rect_index, const vec2i min_rect_size); /* Physics */ -extern uint32_t hs_aabb2_check_collide(const hs_aabb2 r1, const hs_aabb2 r2); -extern void hs_entity2_collide(hs_entity2_hot* e1, hs_entity2_hot* e2); +extern uint32_t hs_rect2_is_inside(const hs_rect2 r1, const hs_rect2 r2, float* lenabs); +extern void hs_entity2_force_inside_rects(hs_rect2* e, hs_rect2* rects, const uint32_t rectc); +extern void hs_entity2_collide(hs_rect2* r1, const hs_rect2* r2); /* Camera stuff */ extern hs_camera hs_init_fps_camera(); @@ -217,13 +224,13 @@ extern void hs_camera_update_front(hs_camera* camera); #define HS_CAMERA2_SMOOTH_DEFAULT {.zoom = 1.0f} extern void hs_camera2_smooth_view(mat4 view, const hs_camera2_smooth cam); extern void hs_camera2_smooth_move_to_goal(hs_camera2_smooth* cam, const float scale); +extern vec2 hs_px_coord_to_global(const vec2 cam_offset, const vec2 scale, const hs_aabb2 res, const vec2 px); /* Tilemap stuff */ extern void hs_tilemap_set(hs_tilemap* tilemap, const uint32_t vertex, uint32_t tile); extern void hs_tilemap_setall(hs_tilemap* tilemap, const uint32_t tile); extern void hs_tilemap_set_xy(hs_tilemap* tilemap, const uint32_t x, const uint32_t y, uint32_t tile); extern uint32_t hs_tilemap_sizeof(const hs_tilemap tilemap); -// expects width, height, sub_tex and half_tile to be filled out extern void hs_tilemap_init(hs_tilemap* tilemap, const uint32_t default_tex); extern void hs_tilemap_update_vbo(const hs_tilemap tilemap); extern void hs_tilemap_draw(const hs_tilemap tilemap); @@ -233,6 +240,7 @@ extern void hs_aroom_to_tilemap(const hs_aroom aroom, hs_tilemap* tilemap, c extern uint8_t hs_aroom_get_xy(const hs_aroom aroom, const uint16_t x, const uint16_t y); extern void hs_aroom_set_tilemap(const hs_aroom aroom, hs_tilemap* tilemap, const uint16_t layer); extern void hs_aroom_set_tilemap_offsetv(const hs_aroom aroom, hs_tilemap* tilemap, const uint16_t layer, const vec2i offset); +extern vec2 hs_tilemap_pos_to_global(const hs_tilemap tilemap, vec2i pos); /* Sprite stuff */ extern hs_shader_program hs_sp_sprite_create(const float width, const float height, const float screen_size); @@ -345,6 +353,30 @@ hs_get_key_held(const hs_game_data gd, const int key) return HS_KEY_UP; } +inline enum hs_key_state +hs_get_mouse_toggle(const hs_game_data gd, hs_key* key) +{ + const int state = glfwGetMouseButton(gd.window, key->key); + const int previous_state = key->previous_state; + key->previous_state = state; + + if (previous_state != state) { + if (state == GLFW_PRESS) return HS_KEY_PRESSED; + else return HS_KEY_RELEASED; + } + + return HS_KEY_UP; +} + +inline enum hs_key_state +hs_get_mouse_held(const hs_game_data gd, const int key) +{ + const int state = glfwGetMouseButton(gd.window, key); + if (state == GLFW_PRESS) + return HS_KEY_DOWN; + return HS_KEY_UP; +} + inline int hs_window_up(const hs_game_data gd) { @@ -770,11 +802,11 @@ hs_aabb2i_half_size(const hs_aabb2i rect) } inline hs_aabb2 -hs_aabb2_from_entity(const hs_entity2_hot e) +hs_aabb2_from_rect2(const hs_rect2 r) { return(hs_aabb2){ - .bl = vec2_sub(e.pos, e.half_size), - .tr = vec2_add(e.pos, e.half_size), + .bl = vec2_sub(r.pos, r.half_size), + .tr = vec2_add(r.pos, r.half_size), }; } @@ -827,31 +859,74 @@ hs_bsp_recti_split_in_place_append(hs_aabb2i* rects, const uint32_t new_rect_ind } inline uint32_t -hs_aabb2_check_collide(const hs_aabb2 r1, const hs_aabb2 r2) +hs_rect2_is_inside(const hs_rect2 r1, const hs_rect2 r2, float* lenabs) { - if (r1.tr.y <= r2.bl.y || r2.tr.y <= r1.bl.y || - r1.tr.x <= r2.bl.x || r2.tr.x <= r1.bl.x) + const vec2 distance = vec2_add(r1.half_size, r2.half_size); + const vec2 diff = vec2_sub(r1.pos, r2.pos); + const vec2 diffabs = {fabs(diff.x), fabs(diff.y)}; + *lenabs = vec2_len(diffabs); + + if (diffabs.x >= distance.x || diffabs.y >= distance.y) return false; return true; } +void +hs_entity2_force_inside_rects(hs_rect2* e, hs_rect2* rects, const uint32_t rectc) +{ + float len_to_closest_rect = INFINITY; + uint32_t closest_rect = 0; + for (uint32_t i = 0; i < rectc; i++) { + float len; + hs_rect2 r = rects[i]; + r.half_size = vec2_sub(r.half_size, vec2_scale(e->half_size, 2.0f)); + if (hs_rect2_is_inside(*e, r, &len)) return; + + if (len < len_to_closest_rect) { + closest_rect = i; + len_to_closest_rect = len; + } + } + + /* move player inside closest room */ + + const vec2 distance = vec2_sub(rects[closest_rect].half_size, e->half_size); + vec2 diff = vec2_sub(e->pos, rects[closest_rect].pos); + const vec2 diffabs = {fabs(diff.x), fabs(diff.y)}; + const float extra = 1.0f - 0.001f; + + if (diffabs.x > diffabs.y) { + const float mul = (diff.x / diffabs.x) * extra; + CLAMP(diff.x, distance.x, -distance.x); + e->pos = vec2_add(rects[closest_rect].pos, (vec2){distance.x * mul, diff.y}); + } else { + const float mul = (diff.y / diffabs.y) * extra; + CLAMP(diff.y, distance.y, -distance.y); + e->pos = vec2_add(rects[closest_rect].pos, (vec2){diff.x, distance.y * mul}); + } +} + inline void -hs_entity2_collide(hs_entity2_hot* e1, hs_entity2_hot* e2) +hs_entity2_collide(hs_rect2* r1, const hs_rect2* r2) { - const vec2 distance = vec2_add(e1->half_size, e2->half_size); - const vec2 diff = vec2_sub(e1->pos, e2->pos); + const vec2 distance = vec2_add(r1->half_size, r2->half_size); + vec2 diff = vec2_sub(r1->pos, r2->pos); + if (diff.x == 0) diff.x = random_float_negative() * 0.00000001; + if (diff.y == 0) diff.y = random_float_negative() * 0.00000001; + const vec2 diffabs = {fabs(diff.x), fabs(diff.y)}; if (diffabs.x >= distance.x || diffabs.y >= distance.y) return; + const float extra = 1.0001; if (diffabs.x > diffabs.y) { const float mul = (diff.x / diffabs.x) * extra; - e1->pos = vec2_add(e2->pos, (vec2){distance.x * mul, diff.y}); + r1->pos = vec2_add(r2->pos, (vec2){distance.x * mul, diff.y}); } else { const float mul = (diff.y / diffabs.y) * extra; - e1->pos = vec2_add(e2->pos, (vec2){diff.x, distance.y * mul}); + r1->pos = vec2_add(r2->pos, (vec2){diff.x, distance.y * mul}); } //static uint32_t col = 0; //printf("collisions %d\n", col++); @@ -940,6 +1015,19 @@ hs_camera2_smooth_move_to_goal(hs_camera2_smooth* cam, const float scale) cam->curr = vec2_add(cam->curr, vec2_scale(vec2_sub(cam->goal, cam->curr), scale)); } +vec2 +hs_px_coord_to_global(const vec2 cam_offset, const vec2 scale, const hs_aabb2 res, const vec2 px) +{ + if (px.x < res.bl.x || px.y < res.bl.y) return (vec2){NAN, NAN}; + if (px.x > res.tr.x || px.y > res.tr.y) return (vec2){NAN, NAN}; + + vec2 global; + global.x = MAP(px.x, res.bl.x, res.tr.x, -1/scale.x, 1/scale.x); + global.y = MAP(px.y, res.bl.y, res.tr.y, -1/scale.y, 1/scale.y); + + return vec2_add(global, cam_offset); +} + inline void hs_camera2_smooth_view(mat4 view, const hs_camera2_smooth cam) { @@ -965,28 +1053,28 @@ hs_tilemap_set(hs_tilemap* tilemap, const uint32_t vertex, uint32_t tile) height -= 0.001f; // bottom left - tilemap->vertices[vertex][0].tex[0] = xpos - width; - tilemap->vertices[vertex][0].tex[1] = ypos - height; + tilemap->vertices[vertex][0].tex.x = xpos - width; + tilemap->vertices[vertex][0].tex.y = ypos - height; // bottom right - tilemap->vertices[vertex][1].tex[0] = xpos; - tilemap->vertices[vertex][1].tex[1] = ypos - height; + tilemap->vertices[vertex][1].tex.x = xpos; + tilemap->vertices[vertex][1].tex.y = ypos - height; // top right - tilemap->vertices[vertex][2].tex[0] = xpos; - tilemap->vertices[vertex][2].tex[1] = ypos; + tilemap->vertices[vertex][2].tex.x = xpos; + tilemap->vertices[vertex][2].tex.y = ypos; // top right - tilemap->vertices[vertex][3].tex[0] = xpos; - tilemap->vertices[vertex][3].tex[1] = ypos; + tilemap->vertices[vertex][3].tex.x = xpos; + tilemap->vertices[vertex][3].tex.y = ypos; // top left - tilemap->vertices[vertex][4].tex[0] = xpos - width; - tilemap->vertices[vertex][4].tex[1] = ypos; + tilemap->vertices[vertex][4].tex.x = xpos - width; + tilemap->vertices[vertex][4].tex.y = ypos; // bottom left - tilemap->vertices[vertex][5].tex[0] = xpos - width; - tilemap->vertices[vertex][5].tex[1] = ypos - height; + tilemap->vertices[vertex][5].tex.x = xpos - width; + tilemap->vertices[vertex][5].tex.y = ypos - height; } @@ -1042,24 +1130,24 @@ hs_tilemap_init(hs_tilemap* tilemap, const uint32_t default_tex) const float left = offset.x - tilemap->tile_width; // triangle one - tilemap->vertices[vertex][0].pos[0] = left; - tilemap->vertices[vertex][0].pos[1] = bottom; + tilemap->vertices[vertex][0].pos.x = left; + tilemap->vertices[vertex][0].pos.y = bottom; - tilemap->vertices[vertex][1].pos[0] = right; - tilemap->vertices[vertex][1].pos[1] = bottom; + tilemap->vertices[vertex][1].pos.x = right; + tilemap->vertices[vertex][1].pos.y = bottom; - tilemap->vertices[vertex][2].pos[0] = right; - tilemap->vertices[vertex][2].pos[1] = top; + tilemap->vertices[vertex][2].pos.x = right; + tilemap->vertices[vertex][2].pos.y = top; // triangle two - tilemap->vertices[vertex][3].pos[0] = right; - tilemap->vertices[vertex][3].pos[1] = top; + tilemap->vertices[vertex][3].pos.x = right; + tilemap->vertices[vertex][3].pos.y = top; - tilemap->vertices[vertex][4].pos[0] = left; - tilemap->vertices[vertex][4].pos[1] = top; + tilemap->vertices[vertex][4].pos.x = left; + tilemap->vertices[vertex][4].pos.y = top; - tilemap->vertices[vertex][5].pos[0] = left; - tilemap->vertices[vertex][5].pos[1] = bottom; + tilemap->vertices[vertex][5].pos.x = left; + tilemap->vertices[vertex][5].pos.y = bottom; // set texture data hs_tilemap_set(tilemap, vertex, default_tex); @@ -1170,6 +1258,14 @@ hs_aroom_set_tilemap_offsetv(const hs_aroom aroom, hs_tilemap* tilemap, const ui } } +vec2 +hs_tilemap_pos_to_global(const hs_tilemap tilemap, vec2i pos) +{ + assert(tilemap.vertices); + const uint32_t v = pos.y * tilemap.width + pos.x; + return vec2_add(tilemap.vertices[v][0].pos, vec2_sub(tilemap.vertices[v][4].pos, tilemap.vertices[v][0].pos)); +} + inline hs_shader_program hs_sp_sprite_create(const float width, const float height, const float screen_size) { diff --git a/hs_math.h b/hs_math.h @@ -30,10 +30,8 @@ #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) - -// a is min, b is max -#define constrain(x, a, b) ({x = x < a ? a : x; x = x > b ? b : x;}) - +#define CLAMP(x, a, b) ({x = x < a ? a : x; x = x > b ? b : x;}) +#define MAP(x, fL, fH, tL, tH) ((x - fL) * (tH - tL) / (fH - fL) + tL) typedef union { struct {