diff --git a/game/Makefile b/game/Makefile index 1bf32dc..bda6205 100644 --- a/game/Makefile +++ b/game/Makefile @@ -1,4 +1,4 @@ -SRC=src/main.c src/program.c src/resources.c src/camera.c src/chunk/chunk.c \ +SRC=src/main.c src/program.c src/res.c src/camera.c src/chunk/chunk.c \ src/chunk/mesh.c src/flags.c src/texture.c src/chunk/manager.c \ src/event/manager.c src/event/handlers.c src/state.c src/graphics.c \ src/entity/meshes.c src/entity/manager.c src/entity/templates.c diff --git a/game/src/camera.c b/game/src/camera.c index 1ca932f..e3c7e42 100644 --- a/game/src/camera.c +++ b/game/src/camera.c @@ -1,54 +1,37 @@ #include "camera.h" -Camera -Camera_default () -{ - Camera cam = { - .position = { 0.0f, 0.0f, 0.0f }, - .rotation = { 0.0f, 0.0f, 0.0f }, - .fov = 80, - .near = 0.1, - .far = 1000.0 - }; - - return cam; -} +vec3 camera_position; +vec3 camera_rotation; void -Camera_get_direction (Camera *camera, vec3 dest) +camera_get_direction (vec3 dest) { - dest[0] = sinf (camera->rotation[0]) * cosf (camera->rotation[1]); - dest[1] = sinf (camera->rotation[1]); - dest[2] = cosf (camera->rotation[0]) * cosf (camera->rotation[1]); + dest[0] = sinf (camera_rotation[0]) * cosf (camera_rotation[1]); + dest[1] = sinf (camera_rotation[1]); + dest[2] = cosf (camera_rotation[0]) * cosf (camera_rotation[1]); glm_vec3_normalize (dest); } void -Camera_get_right (Camera *camera, vec3 dest) +camera_get_right (vec3 dest) { vec3 dir; - Camera_get_direction (camera, dir); + camera_get_direction (dir); glm_vec3_cross (dir, GLM_YUP, dest); glm_vec3_normalize (dest); } void -Camera_get_view (Camera *camera, mat4 dest) +camera_get_view (mat4 dest) { vec3 dir, center; - Camera_get_direction (camera, dir); - glm_vec3_add (camera->position, dir, center); - glm_lookat (camera->position, center, GLM_YUP, dest); + camera_get_direction (dir); + glm_vec3_add (camera_position, dir, center); + glm_lookat (camera_position, center, GLM_YUP, dest); } void -Camera_get_projection (Camera *camera, float aspect, mat4 dest) +camera_get_projection (float aspect, mat4 dest) { - glm_perspective (DEGTORAD (camera->fov), aspect, camera->near, camera->far, dest); -} - -void -Camera_print (Camera *camera) -{ - INFO ("Camera position: (%6.1f, %6.1f, %6.1f)", camera->position[0], camera->position[1], camera->position[2]); + glm_perspective (glm_rad (90), aspect, 0.1, 1000.0, dest); } diff --git a/game/src/camera.h b/game/src/camera.h index 6d235ec..e20f163 100644 --- a/game/src/camera.h +++ b/game/src/camera.h @@ -4,19 +4,7 @@ #include "util.h" -typedef struct Camera -{ - vec3 position; - vec3 rotation; - int fov; - float near; - float far; -} Camera; - -Camera Camera_default (); - -void Camera_get_direction (Camera *camera, vec3 dest); -void Camera_get_right (Camera *camera, vec3 dest); -void Camera_get_view (Camera *camera, mat4 dest); -void Camera_get_projection (Camera *camera, float aspect, mat4 dest); -void Camera_print (Camera *camera); +void camera_get_direction (vec3 dest); +void camera_get_right (vec3 dest); +void camera_get_view (mat4 dest); +void camera_get_projection (float aspect, mat4 dest); diff --git a/game/src/chunk/chunk.c b/game/src/chunk/chunk.c index d8d1de2..fac3056 100644 --- a/game/src/chunk/chunk.c +++ b/game/src/chunk/chunk.c @@ -2,9 +2,6 @@ #include -extern GHashTable *entity_templates; -extern GSequence *entity_manager; - Chunk * Chunk_new () { @@ -31,22 +28,22 @@ Chunk_random (Chunk *chunk, int xoffset, int zoffset) if (rand() % 100 < 2) { Entity *tree = malloc (sizeof (Entity)); - *tree = ET_ENTGET ("tree"); + *tree = ETEMPLGET ("tree"); tree->position[0] = x + xoffset; tree->position[1] = chunk->heightmap [INDEX (x, z)]; tree->position[2] = z + zoffset; tree->rotation = rand () % 180; - EM_ENTADD (tree); + em_add_entity (tree); } if (rand() % 100 < 10) { Entity *grass = malloc (sizeof (Entity)); - *grass = ET_ENTGET ("grass"); + *grass = ETEMPLGET ("grass"); grass->position[0] = x + xoffset; grass->position[1] = chunk->heightmap [INDEX (x, z)]; grass->position[2] = z + zoffset; - EM_ENTADD (grass); + em_add_entity (grass); } } } diff --git a/game/src/chunk/manager.c b/game/src/chunk/manager.c index 756bc61..d5c21a9 100644 --- a/game/src/chunk/manager.c +++ b/game/src/chunk/manager.c @@ -3,7 +3,8 @@ /* TODO: perhaps render the chunks in a circle, not a square, around the player? */ -ChunkManager chunk_manager; +static GHashTable *chunks; +static GHashTable *chunk_meshes; guint cm_ivec2_hash (gconstpointer key) @@ -37,17 +38,17 @@ cm_world_to_chunk (float x, float z, int *ox, int *oz) } void -ChunkManager_init () +cm_init () { - chunk_manager.chunks = g_hash_table_new_full (cm_ivec2_hash, cm_ivec2_equal, free, (GDestroyNotify) Chunk_free); - chunk_manager.chunk_meshes = g_hash_table_new_full (cm_ivec2_hash, cm_ivec2_equal, free, (GDestroyNotify) Chunk_free); + chunks = g_hash_table_new_full (cm_ivec2_hash, cm_ivec2_equal, free, (GDestroyNotify) Chunk_free); + chunk_meshes = g_hash_table_new_full (cm_ivec2_hash, cm_ivec2_equal, free, (GDestroyNotify) Chunk_free); } /* TODO: Update the chunks only if the player has moved into another chunk, to save frame time. */ void -ChunkManager_update (vec3 camera_position) +cm_update (vec3 camera_position) { int cx, cz; cm_world_to_chunk (camera_position[0], camera_position[2], &cx, &cz); @@ -56,9 +57,9 @@ ChunkManager_update (vec3 camera_position) { for (int x = cx - RENDER_DISTANCE - 1; x <= cx + RENDER_DISTANCE + 1; ++x) { - if (ChunkManager_get_Chunk_at (x, z) == NULL) + if (cm_get_Chunk_at (x, z) == NULL) { - ChunkManager_generate_Chunk_at (x, z); + cm_generate_Chunk_at (x, z); } } } @@ -67,16 +68,16 @@ ChunkManager_update (vec3 camera_position) { for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x) { - if (ChunkManager_get_ChunkMesh_at (x, z) == NULL) + if (cm_get_ChunkMesh_at (x, z) == NULL) { - ChunkManager_generate_ChunkMesh_at (x, z); + cm_generate_ChunkMesh_at (x, z); } } } } void -ChunkManager_render (vec3 camera_position, int program) +cm_render (vec3 camera_position, int program) { int cx = 0, cz = 0; cm_world_to_chunk (camera_position[0], camera_position[2], &cx, &cz); @@ -85,7 +86,7 @@ ChunkManager_render (vec3 camera_position, int program) { for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x) { - ChunkMesh *mesh = ChunkManager_get_ChunkMesh_at (x, z); + ChunkMesh *mesh = cm_get_ChunkMesh_at (x, z); if (mesh != NULL) { program_set_vec3 (program, "chunk_position", x * CHUNK_DIM, 0.0, z * CHUNK_DIM); @@ -96,50 +97,50 @@ ChunkManager_render (vec3 camera_position, int program) } Chunk * -ChunkManager_get_Chunk_at (int x, int z) +cm_get_Chunk_at (int x, int z) { - return (Chunk *) g_hash_table_lookup (chunk_manager.chunks, (ivec2) { x, z }); + return (Chunk *) g_hash_table_lookup (chunks, (ivec2) { x, z }); } void -ChunkManager_set_Chunk_at (int x, int z, Chunk *chunk) +cm_set_Chunk_at (int x, int z, Chunk *chunk) { - g_hash_table_insert (chunk_manager.chunks, cm_make_key (x, z), chunk); + g_hash_table_insert (chunks, cm_make_key (x, z), chunk); } void -ChunkManager_generate_Chunk_at (int x, int z) +cm_generate_Chunk_at (int x, int z) { Chunk *chunk = Chunk_new (); Chunk_random (chunk, x * CHUNK_DIM, z * CHUNK_DIM); - ChunkManager_set_Chunk_at (x, z, chunk); + cm_set_Chunk_at (x, z, chunk); } void -ChunkManager_get_Chunk_neighbors_at (int x, int z, Chunk **nr, Chunk **nd, Chunk **nc) +cm_get_Chunk_neighbors_at (int x, int z, Chunk **nr, Chunk **nd, Chunk **nc) { - *nr = ChunkManager_get_Chunk_at (x + 1, z); - *nd = ChunkManager_get_Chunk_at (x, z + 1); - *nc = ChunkManager_get_Chunk_at (x + 1, z + 1); + *nr = cm_get_Chunk_at (x + 1, z); + *nd = cm_get_Chunk_at (x, z + 1); + *nc = cm_get_Chunk_at (x + 1, z + 1); } ChunkMesh * -ChunkManager_get_ChunkMesh_at (int x, int z) +cm_get_ChunkMesh_at (int x, int z) { - return (ChunkMesh *) g_hash_table_lookup (chunk_manager.chunk_meshes, (ivec2) { x, z }); + return (ChunkMesh *) g_hash_table_lookup (chunk_meshes, (ivec2) { x, z }); } void -ChunkManager_set_ChunkMesh_at (int x, int z, ChunkMesh *mesh) +cm_set_ChunkMesh_at (int x, int z, ChunkMesh *mesh) { - g_hash_table_insert (chunk_manager.chunk_meshes, cm_make_key (x, z), mesh); + g_hash_table_insert (chunk_meshes, cm_make_key (x, z), mesh); } void -ChunkManager_generate_ChunkMesh_at (int x, int z) +cm_generate_ChunkMesh_at (int x, int z) { Chunk *nr, *nd, *nc; - ChunkManager_get_Chunk_neighbors_at (x, z, &nr, &nd, &nc); - ChunkManager_set_ChunkMesh_at - (x, z, ChunkMesh_build (ChunkManager_get_Chunk_at (x, z), nr, nd, nc)); + cm_get_Chunk_neighbors_at (x, z, &nr, &nd, &nc); + cm_set_ChunkMesh_at + (x, z, ChunkMesh_build (cm_get_Chunk_at (x, z), nr, nd, nc)); } diff --git a/game/src/chunk/manager.h b/game/src/chunk/manager.h index aa585cf..636b91d 100644 --- a/game/src/chunk/manager.h +++ b/game/src/chunk/manager.h @@ -9,25 +9,16 @@ #define RENDER_DISTANCE 3 -typedef struct ChunkManager -{ - GHashTable *chunks; - GHashTable *chunk_meshes; +void cm_init (); +void cm_update (vec3 camera_position); +void cm_render (vec3 camera_position, int program); - GAsyncQueue *chunk_queue; - GAsyncQueue *chunk_mesh_queue; -} ChunkManager; +Chunk *cm_get_Chunk_at (int x, int z); +void cm_get_Chunk_neighbors_at (int x, int z, Chunk **nr, Chunk **nd, Chunk **nc); +void cm_set_Chunk_at (int x, int z, Chunk *chunk); -void ChunkManager_init (); -void ChunkManager_update (vec3 camera_position); -void ChunkManager_render (vec3 camera_position, int program); +ChunkMesh *cm_get_ChunkMesh_at (int x, int z); +void cm_set_ChunkMesh_at (int x, int z, ChunkMesh *mesh); -Chunk *ChunkManager_get_Chunk_at (int x, int z); -void ChunkManager_get_Chunk_neighbors_at (int x, int z, Chunk **nr, Chunk **nd, Chunk **nc); -void ChunkManager_set_Chunk_at (int x, int z, Chunk *chunk); - -ChunkMesh *ChunkManager_get_ChunkMesh_at (int x, int z); -void ChunkManager_set_ChunkMesh_at (int x, int z, ChunkMesh *mesh); - -void ChunkManager_generate_Chunk_at (int x, int z); -void ChunkManager_generate_ChunkMesh_at (int x, int z); +void cm_generate_Chunk_at (int x, int z); +void cm_generate_ChunkMesh_at (int x, int z); diff --git a/game/src/chunk/mesh.c b/game/src/chunk/mesh.c index d7d51f9..0827834 100644 --- a/game/src/chunk/mesh.c +++ b/game/src/chunk/mesh.c @@ -3,8 +3,6 @@ /* No need to bind the elements buffer all the time; it's the same for every single ChunkMesh. */ -extern GameFlags game_flags; - ChunkMesh * ChunkMesh_build (Chunk *chunk, Chunk *nr, Chunk *nd, Chunk *nc) /* nd --- down neighbor; nr --- right neighbor; nc --- corner neighbor */ @@ -110,7 +108,7 @@ ChunkMesh_render (ChunkMesh *mesh) glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh->ebo); - if (game_flags.wireframe_enabled) + if (flags_get ("wireframe_enabled")) { glDrawElements (GL_LINES, CHUNK_SIZE * 6, GL_UNSIGNED_INT, 0); } diff --git a/game/src/entity/manager.c b/game/src/entity/manager.c index a6d8e8a..c7d2475 100644 --- a/game/src/entity/manager.c +++ b/game/src/entity/manager.c @@ -1,21 +1,15 @@ #include "manager.h" -/* TODO: Sort entities by mesh type AS WELL AS distance. Binding - buffers is very performance-sensitive, thus to conserve speed one - type should be rendered in one go, then the other type, etc. */ +extern vec3 camera_position; -GSequence *entity_manager; -EntityMesh mesh_quad2, mesh_quad_x; - -extern GameState game_state; -extern Resources resources; - -unsigned int last_type = -1; +static GSequence *entities; +static EntityMesh mesh_quad2, mesh_quad_x; +static unsigned int last_type = -1; void -EntityManager_init () +em_init () { - entity_manager = g_sequence_new (NULL); + entities = g_sequence_new (NULL); mesh_quad2 = EntityMesh_make_quad2 (); mesh_quad_x = EntityMesh_make_quad_x (); } @@ -33,9 +27,9 @@ em_tick_internal (gpointer data, gpointer userdata) } void -EntityManager_tick () +em_tick () { - g_sequence_foreach (entity_manager, em_tick_internal, NULL); + g_sequence_foreach (entities, em_tick_internal, NULL); } void @@ -44,7 +38,7 @@ em_render_internal (gpointer data, gpointer userdata) Entity *entity = data; mat4 *view = userdata; - if (glm_vec3_distance (game_state.camera.position, entity->position) > EM_RENDER_DISTANCE) + if (glm_vec3_distance (camera_position, entity->position) > EM_RENDER_DISTANCE) { return; } @@ -55,7 +49,7 @@ em_render_internal (gpointer data, gpointer userdata) vec4 planes[6]; mat4 proj, view_proj; - Camera_get_projection (&game_state.camera, 640.0 / 480.0, proj); + camera_get_projection (640.0 / 480.0, proj); glm_mat4_mul (proj, *view, view_proj); glm_frustum_planes (view_proj, planes); @@ -113,7 +107,7 @@ em_render_internal (gpointer data, gpointer userdata) /* It's not quite a "real" billboard, but the effect is much better on the eye. */ vec3 delta; - glm_vec3_sub (game_state.camera.position, entity->position, delta); + glm_vec3_sub (camera_position, entity->position, delta); delta[1] = 0.0; glm_normalize (delta); glm_rotate_at(model, entity->position, atan2f (delta[0], delta[2]), (vec3) { 0.0, 1.0, 0.0 }); @@ -132,11 +126,10 @@ em_render_internal (gpointer data, gpointer userdata) glm_scale (model, entity->scale); - program_use (R_PRGGET ("default")); - program_set_mat4 (R_PRGGET ("default"), "model", model); + program_set_mat4 (RESPRG ("default"), "model", model); glActiveTexture (GL_TEXTURE0); - glBindTexture (GL_TEXTURE_2D, R_TEXGET (entity->texture)); + glBindTexture (GL_TEXTURE_2D, RESTEX (entity->texture)); if (entity->mesh_type != last_type) { @@ -148,7 +141,40 @@ em_render_internal (gpointer data, gpointer userdata) } void -EntityManager_render (mat4 view) +em_render (mat4 view) { - g_sequence_foreach (entity_manager, em_render_internal, view); + g_sequence_foreach (entities, em_render_internal, view); +} + +static inline int +em_compare (gconstpointer a, gconstpointer b, gpointer userdata) +/* This function is used to sort Entities by their mesh type, so that + diferrent buffers aren't bound every single frame. */ +{ + UNUSED (userdata); + const Entity *entity1 = a; + const Entity *entity2 = b; + + if (entity1->mesh_type == entity2->mesh_type) + { + return 0; + } + + if (entity1->mesh_type == MESH_QUAD_X && entity2->mesh_type == MESH_QUAD2) + { + return -1; + } + + if (entity1->mesh_type == MESH_QUAD2 && entity2->mesh_type == MESH_QUAD_X) + { + return 1; + } + + return (int) entity1->mesh_type - (int) entity2->mesh_type; +} + +void +em_add_entity (Entity *entity) +{ + g_sequence_insert_sorted (entities, entity, em_compare, NULL); } diff --git a/game/src/entity/manager.h b/game/src/entity/manager.h index eef0acc..81aacd1 100644 --- a/game/src/entity/manager.h +++ b/game/src/entity/manager.h @@ -6,41 +6,13 @@ #include "entity.h" #include "meshes.h" #include "../util.h" -#include "../resources.h" +#include "../res.h" #include "../state.h" #include "../chunk/chunk.h" #define EM_RENDER_DISTANCE (3*CHUNK_DIM/2) -#define EM_ENTADD(entity) (g_sequence_insert_sorted (entity_manager, entity, em_compare, NULL)); - -static inline int -em_compare (gconstpointer a, gconstpointer b, gpointer userdata) -/* This function is used to sort Entities by their mesh type, so that - diferrent buffers aren't bound every single frame. */ -{ - UNUSED (userdata); - const Entity *entity1 = a; - const Entity *entity2 = b; - - if (entity1->mesh_type == entity2->mesh_type) - { - return 0; - } - - if (entity1->mesh_type == MESH_QUAD_X && entity2->mesh_type == MESH_QUAD2) - { - return -1; - } - - if (entity1->mesh_type == MESH_QUAD2 && entity2->mesh_type == MESH_QUAD_X) - { - return 1; - } - - return (int) entity1->mesh_type - (int) entity2->mesh_type; -} - -void EntityManager_init (); -void EntityManager_tick (); -void EntityManager_render (); +void em_init (); +void em_tick (); +void em_render (); +void em_add_entity (Entity *entity); diff --git a/game/src/entity/meshes.c b/game/src/entity/meshes.c index 8a127a4..63c6527 100644 --- a/game/src/entity/meshes.c +++ b/game/src/entity/meshes.c @@ -2,8 +2,6 @@ /* TODO: Split binding/rendering */ -extern GameFlags game_flags; - void EntityMesh_bind (EntityMesh *mesh) { @@ -21,7 +19,7 @@ EntityMesh_bind (EntityMesh *mesh) void EntityMesh_render (EntityMesh *mesh) { - if (game_flags.wireframe_enabled) + if (flags_get ("wireframe_enabled")) { glDrawElements (GL_LINES, mesh->indices_len, GL_UNSIGNED_INT, 0); } diff --git a/game/src/entity/templates.c b/game/src/entity/templates.c index f98d73a..22e1fde 100644 --- a/game/src/entity/templates.c +++ b/game/src/entity/templates.c @@ -1,11 +1,23 @@ #include "templates.h" -GHashTable *entity_templates; +static GHashTable *templates; + +static inline void +ent_templates_add (char *key, Entity *entity) +{ + g_hash_table_insert (templates, key, entity); +} + +Entity +ent_templates_get (char *key) +{ + return *(Entity *) g_hash_table_lookup (templates, key); +} void -EntityTemplates_init () +ent_templates_init () { - entity_templates = g_hash_table_new (g_str_hash, g_str_equal); + templates = g_hash_table_new (g_str_hash, g_str_equal); Entity *tree = malloc (sizeof (Entity)); *tree = (Entity) { @@ -17,7 +29,7 @@ EntityTemplates_init () .texture = "tree0" }; - ET_ENTADD ("tree", tree); + ent_templates_add ("tree", tree); Entity *grass = malloc (sizeof (Entity)); *grass = (Entity) { @@ -30,8 +42,5 @@ EntityTemplates_init () .texture = "grass0" }; - ET_ENTADD ("grass", grass); + ent_templates_add ("grass", grass); } - -/* To avoid confusion with EM_ENTADD. */ -#undef ET_ENTADD diff --git a/game/src/entity/templates.h b/game/src/entity/templates.h index b467f9f..d30e2f3 100644 --- a/game/src/entity/templates.h +++ b/game/src/entity/templates.h @@ -1,8 +1,5 @@ #pragma once -/* TODO: Maybe make a function that allocates an Entity for you and - adds it's data from the template? */ - #include #include @@ -10,7 +7,7 @@ #include "entity.h" -#define ET_ENTGET(key) (*(Entity *) g_hash_table_lookup (entity_templates, key)) -#define ET_ENTADD(key, entity) (g_hash_table_insert (entity_templates, key, entity)) +#define ETEMPLGET(key) (ent_templates_get (key)) -void EntityTemplates_init (); +void ent_templates_init (); +Entity ent_templates_get (char *key); diff --git a/game/src/event/handlers.c b/game/src/event/handlers.c index 56dc16c..9b80cd5 100644 --- a/game/src/event/handlers.c +++ b/game/src/event/handlers.c @@ -1,7 +1,7 @@ #include "handlers.h" -extern GameState game_state; -extern GameFlags game_flags; +extern vec3 camera_position; +extern vec3 camera_rotation; void handlers_init () @@ -13,12 +13,12 @@ handlers_init () void handler_lookaround (SDL_Event *event) { - if (event->type == SDL_EVENT_MOUSE_MOTION && game_flags.can_free_look) + if (event->type == SDL_EVENT_MOUSE_MOTION) { - game_state.camera.rotation[0] -= event->motion.xrel / 100.f; - game_state.camera.rotation[1] -= event->motion.yrel / 100.f; - game_state.camera.rotation[1] = - CLAMP (game_state.camera.rotation[1], -M_PI / 2 + 0.025, M_PI / 2 - 0.025); + camera_rotation[0] -= event->motion.xrel / 100.f; + camera_rotation[1] -= event->motion.yrel / 100.f; + camera_rotation[1] = + CLAMP (camera_rotation[1], -M_PI / 2 + 0.025, M_PI / 2 - 0.025); } } @@ -30,19 +30,19 @@ handler_movement (SDL_Event *event) switch (event->key.key) { case SDLK_W: - game_flags.moving_forward = 1; + flags_set ("moving_forward", true); break; case SDLK_A: - game_flags.moving_left = 1; + flags_set ("moving_left", true); break; case SDLK_S: - game_flags.moving_backward = 1; + flags_set ("moving_backward", true); break; case SDLK_D: - game_flags.moving_right = 1; + flags_set ("moving_right", true); break; case SDLK_F1: - game_flags.wireframe_enabled = !game_flags.wireframe_enabled; + flags_set ("wireframe_enabled", !flags_get ("wireframe_enabled")); break; } } @@ -52,16 +52,16 @@ handler_movement (SDL_Event *event) switch (event->key.key) { case SDLK_W: - game_flags.moving_forward = 0; + flags_set ("moving_forward", false); break; case SDLK_A: - game_flags.moving_left = 0; + flags_set ("moving_left", false); break; case SDLK_S: - game_flags.moving_backward = 0; + flags_set ("moving_backward", false); break; case SDLK_D: - game_flags.moving_right = 0; + flags_set ("moving_right", false); break; } } diff --git a/game/src/flags.c b/game/src/flags.c index 65ac461..5e453cb 100644 --- a/game/src/flags.c +++ b/game/src/flags.c @@ -1,3 +1,22 @@ #include "flags.h" -GameFlags game_flags = { 0 }; +static GHashTable *flags; + +void +flags_init () +{ + flags = g_hash_table_new (g_str_hash, g_str_equal); + flags_set ("wireframe_enabled", false); +} + +void +flags_set (char *flag, bool value) +{ + g_hash_table_replace (flags, flag, GINT_TO_POINTER (value)); +} + +bool +flags_get (char *flag) +{ + return GPOINTER_TO_INT (g_hash_table_lookup (flags, flag)); +} diff --git a/game/src/flags.h b/game/src/flags.h index 91ef453..f23136e 100644 --- a/game/src/flags.h +++ b/game/src/flags.h @@ -1,18 +1,9 @@ #pragma once -typedef struct GameFlags -{ - /* Volatile state flags, zeroed at start. */ - int in_main_menu: 1; - int in_pause_menu: 1; - int in_game: 1; +#include - int can_free_look: 1; - int moving_forward: 1; - int moving_backward: 1; - int moving_left: 1; - int moving_right: 1; +#include - int wireframe_enabled: 1; - /* Saved state flags, loaded from game save/map. */ -} GameFlags; +void flags_init (); +void flags_set (char *flag, bool value); +bool flags_get (char *flag); diff --git a/game/src/graphics.c b/game/src/graphics.c index 3173ec6..c8e4038 100644 --- a/game/src/graphics.c +++ b/game/src/graphics.c @@ -1,22 +1,21 @@ #include "graphics.h" -GraphicsContext gfx; +extern vec3 camera_position; -extern ChunkManager chunk_manager; -extern GameState game_state; -extern Resources resources; +static SDL_Window *sdl_window; +static SDL_GLContext gl_context; void -GraphicsContext_init () +graphics_init () { if (!SDL_Init (SDL_INIT_VIDEO)) { FATAL ("Couldn't initialize SDL: %s", SDL_GetError ()); } - gfx.window = SDL_CreateWindow (GAME_NAME, 640, 480, SDL_WINDOW_OPENGL); + sdl_window = SDL_CreateWindow (GAME_NAME, 640, 480, SDL_WINDOW_OPENGL); - if (!gfx.window) + if (!sdl_window) { FATAL ("Couldn't create window: %s", SDL_GetError ()); } @@ -27,66 +26,66 @@ GraphicsContext_init () SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0); - gfx.gl_context = SDL_GL_CreateContext (gfx.window); + gl_context = SDL_GL_CreateContext (sdl_window); - if (!gfx.gl_context) + if (!gl_context) { FATAL ("Couldn't create OpenGL context: %s", SDL_GetError ()); } - SDL_GL_MakeCurrent (gfx.window, gfx.gl_context); - SDL_SetWindowRelativeMouseMode (gfx.window, true); + SDL_GL_MakeCurrent (sdl_window, gl_context); + SDL_SetWindowRelativeMouseMode (sdl_window, true); INFO ("Renderer: %s", glGetString (GL_RENDERER)); INFO ("OpenGL version: %s", glGetString (GL_VERSION)); INFO ("GLSL version: %s", glGetString (GL_SHADING_LANGUAGE_VERSION)); INFO ("Max vertex attributes: %d", GL_MAX_VERTEX_ATTRIBS); - glViewport(0, 0, 640, 480); + glViewport (0, 0, 640, 480); glClearColor (0, 0.3, 0.8, 1); glEnable (GL_CULL_FACE); - glEnable (GL_DEPTH_TEST); + glEnable (GL_DEPTH_TEST); } void -GraphicsContext_render () +graphics_render () { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); mat4 projection, view; - Camera_get_projection (&game_state.camera, 640.0 / 480.0, projection); - Camera_get_view (&game_state.camera, view); + camera_get_projection (640.0 / 480.0, projection); + camera_get_view (view); - /* Set views and projections in all programs. TODO: make this dynamic*/ - program_use (R_PRGGET ("default")); - program_set_mat4 (R_PRGGET ("default"), "projection", projection); - program_set_mat4 (R_PRGGET ("default"), "view", view); - - program_use (R_PRGGET ("chunk")); - program_set_mat4 (R_PRGGET ("chunk"), "projection", projection); - program_set_mat4 (R_PRGGET ("chunk"), "view", view); + program_use (RESPRG ("chunk")); + program_set_mat4 (RESPRG ("chunk"), "projection", projection); + program_set_mat4 (RESPRG ("chunk"), "view", view); glActiveTexture (GL_TEXTURE0); - glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain0")); + glBindTexture (GL_TEXTURE_2D, RESTEX ("terrain0")); glActiveTexture (GL_TEXTURE1); - glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain1")); + glBindTexture (GL_TEXTURE_2D, RESTEX ("terrain1")); glActiveTexture (GL_TEXTURE2); - glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain2")); + glBindTexture (GL_TEXTURE_2D, RESTEX ("terrain2")); glActiveTexture (GL_TEXTURE3); - glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain3")); + glBindTexture (GL_TEXTURE_2D, RESTEX ("terrain3")); glActiveTexture (GL_TEXTURE4); - glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain4")); + glBindTexture (GL_TEXTURE_2D, RESTEX ("terrain4")); - ChunkManager_render (game_state.camera.position, R_PRGGET ("chunk")); - EntityManager_render (view); + cm_render (camera_position, RESPRG ("chunk")); - SDL_GL_SwapWindow (gfx.window); + /* Set views and projections in all programs. TODO: make this dynamic*/ + program_use (RESPRG ("default")); + program_set_mat4 (RESPRG ("default"), "projection", projection); + program_set_mat4 (RESPRG ("default"), "view", view); + em_render (view); + + SDL_GL_SwapWindow (sdl_window); } void -GraphicsContext_free () +graphics_free () { - SDL_GL_DestroyContext (gfx.gl_context); - SDL_DestroyWindow (gfx.window); + SDL_GL_DestroyContext (gl_context); + SDL_DestroyWindow (sdl_window); } diff --git a/game/src/graphics.h b/game/src/graphics.h index 70ec949..7e46a21 100644 --- a/game/src/graphics.h +++ b/game/src/graphics.h @@ -7,14 +7,8 @@ #include "chunk/manager.h" #include "entity/manager.h" #include "state.h" -#include "resources.h" +#include "res.h" -typedef struct GraphicsContext -{ - SDL_Window *window; - SDL_GLContext gl_context; -} GraphicsContext; - -void GraphicsContext_init (); -void GraphicsContext_render (); -void GraphicsContext_free (); +void graphics_init (); +void graphics_render (); +void graphics_free (); diff --git a/game/src/main.c b/game/src/main.c index ef5f7ea..56deee2 100644 --- a/game/src/main.c +++ b/game/src/main.c @@ -8,11 +8,10 @@ #include "chunk/manager.h" #include "entity/templates.h" #include "state.h" -#include "resources.h" +#include "res.h" #include "graphics.h" -extern GameState game_state; -extern GameFlags game_flags; +extern vec3 camera_position; SDL_AppResult SDL_AppInit (void **appstate, int argc, char **argv) @@ -20,16 +19,14 @@ SDL_AppInit (void **appstate, int argc, char **argv) UNUSED (appstate, argc, argv); SDL_SetAppMetadata (GAME_NAME, GAME_VERSION, "eur.chopininteractive.wschod-game"); - GraphicsContext_init (); + graphics_init (); handlers_init (); - Resources_init (); - ChunkManager_init (); - EntityManager_init (); - EntityTemplates_init (); - GameState_init (SDL_GetTicks ()); - /* Set some basic game flags for testing. */ - game_flags.can_free_look = 1; - game_flags.wireframe_enabled = 0; + res_init (); + cm_init (); + em_init (); + ent_templates_init (); + flags_init (); + game_state_init (SDL_GetTicks ()); return SDL_APP_CONTINUE; } @@ -53,10 +50,10 @@ SDL_AppIterate (void *appstate) { UNUSED (appstate); - GameState_tick (SDL_GetTicks ()); - EntityManager_tick (); - ChunkManager_update (game_state.camera.position); - GraphicsContext_render (); + game_state_tick (SDL_GetTicks ()); + em_tick (); + cm_update (camera_position); + graphics_render (); return SDL_APP_CONTINUE; } @@ -65,5 +62,5 @@ void SDL_AppQuit (void *appstate, SDL_AppResult result) { UNUSED (appstate, result); - GraphicsContext_free (); + graphics_free (); } diff --git a/game/src/res.c b/game/src/res.c new file mode 100644 index 0000000..1fa6d11 --- /dev/null +++ b/game/src/res.c @@ -0,0 +1,99 @@ +#include "res.h" + +static GHashTable *programs; +static GHashTable *textures; + +unsigned int +res_load_program (const char *v_path, const char *f_path) +{ + FILE *v_file = fopen (v_path, "r"); + + if (v_file == NULL) + { + WARN ("File `%s' does not exist.", v_path); + } + + fseek (v_file, 0L, SEEK_END); + size_t v_len = ftell (v_file) + 1; + char *v_src = calloc (v_len, sizeof (char)); + rewind (v_file); + INFO ("Read %zu bytes from vertex source.", fread (v_src, sizeof (char), v_len, v_file)); + + FILE *f_file = fopen (f_path, "r"); + + if (f_file == NULL) + { + WARN ("File `%s' does not exist.", f_path); + } + + fseek (f_file, 0L, SEEK_END); + size_t f_len = ftell (f_file) + 1; + char *f_src = calloc (f_len, sizeof (char)); + rewind (f_file); + INFO ("Read %zu bytes from fragment source.", fread (f_src, sizeof (char), f_len, f_file)); + + unsigned int program = program_create (v_src, f_src); + free (v_src); + free (f_src); + return program; +} + +unsigned int +res_load_texture (const char *path) +{ + SDL_Surface *surface = IMG_Load (path); + + if (surface == NULL) + { + WARN ("Failed to load texture from path %s: %s", path, SDL_GetError ()); + } + + unsigned int texture = texture_create (surface->w, surface->h, surface->pixels); + return texture; +} + +static inline void +res_add_program (char *key, unsigned int program) +{ + g_hash_table_insert (programs, key, GINT_TO_POINTER (program)); +} + +static inline void +res_add_texture (char *key, unsigned int texture) +{ + g_hash_table_insert (textures, key, GINT_TO_POINTER (texture)); +} + +unsigned int +res_get_program (char *key) +{ + return GPOINTER_TO_INT (g_hash_table_lookup (programs, key)); +} + +unsigned int +res_get_texture (char *key) +{ + return GPOINTER_TO_INT (g_hash_table_lookup (textures, key)); +} + +void +res_init () +{ + programs = g_hash_table_new (g_str_hash, g_str_equal); + textures = g_hash_table_new (g_str_hash, g_str_equal); + + res_add_program ("default", res_load_program ("res/shaders/default.vert", "res/shaders/default.frag")); + res_add_program ("chunk", res_load_program ("res/shaders/chunk.vert", "res/shaders/chunk.frag")); + + program_use (res_get_program ("chunk")); + program_set_int_array (res_get_program ("chunk"), "materials", 5, (int[5]) { 0, 1, 2, 3, 4 }); + + res_add_texture ("terrain0", res_load_texture ("res/textures/dirt.png")); + res_add_texture ("terrain1", res_load_texture ("res/textures/drygrass.png")); + res_add_texture ("terrain2", res_load_texture ("res/textures/grass.png")); + res_add_texture ("terrain3", res_load_texture ("res/textures/rock_cement.png")); + res_add_texture ("terrain4", res_load_texture ("res/textures/asphalt_gravel.png")); + + res_add_texture ("tree0", res_load_texture ("res/textures/tree.png")); + res_add_texture ("grass0", res_load_texture ("res/textures/grass0.png")); +} diff --git a/game/src/res.h b/game/src/res.h new file mode 100644 index 0000000..0e3b01c --- /dev/null +++ b/game/src/res.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include "program.h" +#include "texture.h" + +#define RESPRG(key) (res_get_program (key)) +#define RESTEX(key) (res_get_texture (key)) + +unsigned int res_get_program (char *key); +unsigned int res_get_texture (char *key); +void res_init (); diff --git a/game/src/resources.c b/game/src/resources.c deleted file mode 100644 index a29967f..0000000 --- a/game/src/resources.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "resources.h" - -Resources resources; - -void -Resources_init () -{ - resources.programs = g_hash_table_new (g_str_hash, g_str_equal); - resources.textures = g_hash_table_new (g_str_hash, g_str_equal); - - R_PRGADD ("default", R_PRGLOAD ("res/shaders/default.vert", "res/shaders/default.frag")); - R_PRGADD ("chunk", R_PRGLOAD ("res/shaders/chunk.vert", "res/shaders/chunk.frag")); - - program_use (R_PRGGET ("chunk")); - program_set_int_array (R_PRGGET ("chunk"), "materials", 5, (int[5]) { 0, 1, 2, 3, 4 }); - - R_TEXADD ("terrain0", R_TEXLOAD ("res/textures/dirt.png")); - R_TEXADD ("terrain1", R_TEXLOAD ("res/textures/drygrass.png")); - R_TEXADD ("terrain2", R_TEXLOAD ("res/textures/grass.png")); - R_TEXADD ("terrain3", R_TEXLOAD ("res/textures/rock_cement.png")); - R_TEXADD ("terrain4", R_TEXLOAD ("res/textures/asphalt_gravel.png")); - - R_TEXADD ("tree0", R_TEXLOAD ("res/textures/tree.png")); - R_TEXADD ("grass0", R_TEXLOAD ("res/textures/grass0.png")); -} - -unsigned int -Resources_load_program (const char *v_path, const char *f_path) -{ - FILE *v_file = fopen (v_path, "r"); - - if (v_file == NULL) - { - WARN ("File `%s' does not exist.", v_path); - } - - fseek (v_file, 0L, SEEK_END); - size_t v_len = ftell (v_file) + 1; - char *v_src = calloc (v_len, sizeof (char)); - rewind (v_file); - INFO ("Read %zu bytes from vertex source.", fread (v_src, sizeof (char), v_len, v_file)); - - FILE *f_file = fopen (f_path, "r"); - - if (f_file == NULL) - { - WARN ("File `%s' does not exist.", f_path); - } - - fseek (f_file, 0L, SEEK_END); - size_t f_len = ftell (f_file) + 1; - char *f_src = calloc (f_len, sizeof (char)); - rewind (f_file); - INFO ("Read %zu bytes from fragment source.", fread (f_src, sizeof (char), f_len, f_file)); - - unsigned int program = program_create (v_src, f_src); - free (v_src); - free (f_src); - return program; -} - -unsigned int -Resources_load_texture (const char *path) -{ - SDL_Surface *surface = IMG_Load (path); - - if (surface == NULL) - { - WARN ("Failed to load texture from path %s: %s", path, SDL_GetError ()); - } - - unsigned int texture = texture_create (surface->w, surface->h, surface->pixels); - return texture; -} diff --git a/game/src/resources.h b/game/src/resources.h deleted file mode 100644 index 3ef6d6c..0000000 --- a/game/src/resources.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include - -#include "program.h" -#include "texture.h" - -#define R_PRGADD(key, program) (g_hash_table_insert (resources.programs, key, GINT_TO_POINTER (program))) -#define R_TEXADD(key, texture) (g_hash_table_insert (resources.textures, key, GINT_TO_POINTER (texture))) -#define R_PRGLOAD(v_path, f_path) (Resources_load_program (v_path, f_path)) -#define R_TEXLOAD(path) (Resources_load_texture (path)) -#define R_PRGGET(key) (GPOINTER_TO_INT (g_hash_table_lookup (resources.programs, key))) -#define R_TEXGET(key) (GPOINTER_TO_INT (g_hash_table_lookup (resources.textures, key))) - -typedef struct Resources { - GHashTable *programs; - GHashTable *textures; -} Resources; - -unsigned int Resources_load_program (const char *v_path, const char *f_path); -unsigned int Resources_load_texture (const char *path); - -void Resources_init (); diff --git a/game/src/state.c b/game/src/state.c index 28ea819..9f69883 100644 --- a/game/src/state.c +++ b/game/src/state.c @@ -1,57 +1,56 @@ #include "state.h" -GameState game_state; +extern vec3 camera_position; -extern GameFlags game_flags; +float delta_time; +static int last_time; void -GameState_init (int ticks) +game_state_init (int ticks) { - game_state.last_time = ticks; - game_state.camera = Camera_default (); - game_state.camera.position[2] = -1.0; + last_time = ticks; } void -GameState_tick (int ticks) +game_state_tick (int ticks) { /* Caluclate stuff per frame. */ - game_state.delta_time = (ticks - game_state.last_time) / 1000.0; - game_state.last_time = ticks; + delta_time = (ticks - last_time) / 1000.0; + last_time = ticks; - if (game_flags.moving_forward) + if (flags_get ("moving_forward")) { vec3 dir, change, new_pos; - Camera_get_direction (&game_state.camera, dir); - glm_vec3_scale (dir, game_state.delta_time * 5, change); - glm_vec3_add (game_state.camera.position, change, new_pos); - glm_vec3_copy (new_pos, game_state.camera.position); + camera_get_direction (dir); + glm_vec3_scale (dir, delta_time * 5, change); + glm_vec3_add (camera_position, change, new_pos); + glm_vec3_copy (new_pos, camera_position); } - if (game_flags.moving_backward) + if (flags_get ("moving_backward")) { vec3 dir, change, new_pos; - Camera_get_direction (&game_state.camera, dir); - glm_vec3_scale (dir, game_state.delta_time * 5, change); - glm_vec3_sub (game_state.camera.position, change, new_pos); - glm_vec3_copy (new_pos, game_state.camera.position); + camera_get_direction (dir); + glm_vec3_scale (dir, delta_time * 5, change); + glm_vec3_sub (camera_position, change, new_pos); + glm_vec3_copy (new_pos, camera_position); } - if (game_flags.moving_right) + if (flags_get ("moving_right")) { vec3 right, change, new_pos; - Camera_get_right (&game_state.camera, right); - glm_vec3_scale (right, game_state.delta_time * 5, change); - glm_vec3_add (game_state.camera.position, change, new_pos); - glm_vec3_copy (new_pos, game_state.camera.position); + camera_get_right (right); + glm_vec3_scale (right, delta_time * 5, change); + glm_vec3_add (camera_position, change, new_pos); + glm_vec3_copy (new_pos, camera_position); } - if (game_flags.moving_left) + if (flags_get ("moving_left")) { vec3 right, change, new_pos; - Camera_get_right (&game_state.camera, right); - glm_vec3_scale (right, game_state.delta_time * 5, change); - glm_vec3_sub (game_state.camera.position, change, new_pos); - glm_vec3_copy (new_pos, game_state.camera.position); + camera_get_right (right); + glm_vec3_scale (right, delta_time * 5, change); + glm_vec3_sub (camera_position, change, new_pos); + glm_vec3_copy (new_pos, camera_position); } } diff --git a/game/src/state.h b/game/src/state.h index d201868..4e079d8 100644 --- a/game/src/state.h +++ b/game/src/state.h @@ -3,13 +3,5 @@ #include "camera.h" #include "flags.h" -typedef struct GameState -{ - int last_time; - float delta_time; - - Camera camera; -} GameState; - -void GameState_init (); -void GameState_tick (); +void game_state_init (int ticks); +void game_state_tick (int ticks);