diff --git a/game/res/scripts/u_main_menu.scm b/game/res/scripts/u_main_menu.scm index 7e08680..7d35722 100644 --- a/game/res/scripts/u_main_menu.scm +++ b/game/res/scripts/u_main_menu.scm @@ -5,7 +5,7 @@ #:layout-spacing 8 #:horizontal #t (widget-new 'label #:style style-button #:layout-weight 1 #:h 20 #:text-alignment 'center #:text "New game" - #:on-click (lambda (w e) (stateman-switch-state "game"))) + #:on-click (lambda (w e) (switch-stage "game"))) (widget-new 'label #:style style-button #:layout-weight 1 #:h 20 #:text-alignment 'center #:text "Options") (widget-new 'label #:style style-button #:layout-weight 1 #:h 20 #:text-alignment 'center #:text "Quit game")) diff --git a/game/src/camera.c b/game/src/camera.c index bc2f371..4243065 100644 --- a/game/src/camera.c +++ b/game/src/camera.c @@ -4,34 +4,36 @@ vec3 camera_position; vec3 camera_rotation; void -camera_get_direction (vec3 dest) +Camera_get_direction (Camera *camera, 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]); - glm_vec3_normalize (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]); + glm_vec3_normalize (dest); } void -camera_get_right (vec3 dest) +Camera_get_right (Camera *camera, vec3 dest) { vec3 dir; - camera_get_direction (dir); + Camera_get_direction (camera, dir); glm_vec3_cross (dir, GLM_YUP, dest); - glm_vec3_normalize (dest); + glm_vec3_normalize (dest); } void -camera_get_view (mat4 dest) +Camera_get_view (Camera *camera, mat4 dest) { vec3 dir, center; - camera_get_direction (dir); - glm_vec3_add (camera_position, dir, center); - glm_lookat (camera_position, center, GLM_YUP, dest); + Camera_get_direction (camera, dir); + glm_vec3_add (camera->position, dir, center); + glm_lookat (camera->position, center, GLM_YUP, dest); } void -camera_get_projection (float aspect, mat4 dest) +Camera_get_projection (Camera *camera, float aspect, mat4 dest) { - glm_perspective (glm_rad (70), aspect, 0.01, 7000.0, dest); + (void) camera; + glm_perspective (glm_rad (70), aspect, 0.01, 7000.0, dest); } + diff --git a/game/src/camera.h b/game/src/camera.h index 74de122..91b6366 100644 --- a/game/src/camera.h +++ b/game/src/camera.h @@ -2,6 +2,16 @@ #include +typedef struct Camera +{ + vec3 position, rotation; +} Camera; + +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_get_direction (vec3 dest); void camera_get_right (vec3 dest); void camera_get_view (mat4 dest); diff --git a/game/src/entity/entman.c b/game/src/entity/entman.c index b8e115a..35443bb 100644 --- a/game/src/entity/entman.c +++ b/game/src/entity/entman.c @@ -6,8 +6,6 @@ /* TODO: Instead of having a huge far plane, render the clouds seperately somehow. */ -extern vec3 camera_position; - Entity *player_entity, *sky_entity; /* The GArray is the fastest of all sequence types. Should work fine @@ -20,6 +18,11 @@ static unsigned int last_program = 0; static unsigned int last_type = 0; static unsigned int last_texture = 0; +/* These are defined as statics so we don't get those values from gvar + every frame.. */ +static int render_distance = 2; +static gboolean wireframe_enabled = FALSE; + void character_on_tick (Entity *entity) { @@ -107,21 +110,13 @@ entman_tick () } gboolean -entman_render_entity (Entity *entity, void *userdata) +entman_render_entity (Entity *entity, vec3 camera_position, mat4 view, vec4 frustum_planes[6]) { - struct { - mat4 *view; -#ifdef FRUSTUM_CULL - vec4 *frustum_planes[6]; -#endif - } *vp = userdata; - if (!entity->visible) { return FALSE; } - int render_distance = gvar_get ("render_distance"); /* Why an int, why int division? It's simply much faster than floating point operations. No need to have super accurate cull distance anyway, and might as well save a lot when rendering entities. */ @@ -142,7 +137,7 @@ entman_render_entity (Entity *entity, void *userdata) vec3 aabb[2]; entity_compute_aabb (entity, aabb[0], aabb[1]); - if (!glm_aabb_frustum (aabb, *vp->frustum_planes)) + if (!glm_aabb_frustum (aabb, frustum_planes)) { return FALSE; } @@ -170,7 +165,7 @@ entman_render_entity (Entity *entity, void *userdata) { case RENDER_BILLBOARD: mat4 inv_view; - glm_mat4_copy (*vp->view, inv_view); + glm_mat4_copy (view, inv_view); glm_mat4_inv (inv_view, inv_view); vec3 right = { inv_view[0][0], inv_view[1][0], inv_view[2][0] }; @@ -232,39 +227,22 @@ entman_render_entity (Entity *entity, void *userdata) last_type = entity->mesh_type; } - SimpleMesh_render (&to_render, FLAG_GET ("wireframe_enabled")); + SimpleMesh_render (&to_render, wireframe_enabled); return TRUE; } void -entman_render (mat4 *view, vec4 planes[6]) +entman_render (vec3 camera_position, mat4 view, vec4 planes[6]) { -#if !FRUSTUM_CULL - UNUSED (planes); -#endif - - last_program = -1; - last_texture = -1; - last_type = -1; - - struct { - mat4 *view; -#if FRUSTUM_CULL - vec4 *frustum_planes; -#endif - } data = { - view -#if FRUSTUM_CULL - ,planes -#endif - }; - int frame_entities = 0; + render_distance = gvar_get ("render_distance"); + wireframe_enabled = gvar_get ("wireframe_enabled"); + for (guint i = 0; i < entities->len; ++i) { Entity *e = g_array_index (entities, Entity*, i); - frame_entities += entman_render_entity (e, &data) ? 1 : 0; + frame_entities += entman_render_entity (e, camera_position, view, planes) ? 1 : 0; } gvar_set ("frame_entities", frame_entities); diff --git a/game/src/entity/entman.h b/game/src/entity/entman.h index d5efe54..e3a53ae 100644 --- a/game/src/entity/entman.h +++ b/game/src/entity/entman.h @@ -27,6 +27,6 @@ typedef struct SpawnRequest void entman_init (); void entman_tick (); -void entman_render (); +void entman_render (vec3 camera_position, mat4 view, vec4 planes[6]); void entman_add_entity (Entity *entity); void entman_add_spawn_request (char *template_name, vec3 position, vec3 rotation, vec3 scale); diff --git a/game/src/graphics.c b/game/src/graphics.c index 2a97226..48b6061 100644 --- a/game/src/graphics.c +++ b/game/src/graphics.c @@ -81,5 +81,5 @@ graphics_cb_window_resize (SDL_Event *event, void *data) gvar_set ("window_width", sdl_window_w); gvar_set ("window_height", sdl_window_h); /* Since other subsystems might want to use the event. */ - return FALSE; + return TRUE; } diff --git a/game/src/main.c b/game/src/main.c index 30aa04d..61b0038 100644 --- a/game/src/main.c +++ b/game/src/main.c @@ -9,7 +9,7 @@ #include "graphics.h" #include "gvar.h" #include "pakman.h" -#include "states/stateman.h" +#include "stage/stageman.h" SDL_AppResult SDL_AppInit (void **appstate, int argc, char **argv) @@ -21,12 +21,12 @@ SDL_AppInit (void **appstate, int argc, char **argv) things. */ scm_init_guile (); gvar_guile_register (); - stateman_guile_register (); + stageman_guile_register (); widget_guile_register (); entity_guile_register (); pakman_guile_register (); - /* The basics; game variables, graphics, the state manager, and the + /* The basics; game variables, graphics, the stage manager, and the pak manager. */ gvar_init (); graphics_init (); @@ -34,7 +34,7 @@ SDL_AppInit (void **appstate, int argc, char **argv) /* The base pack is always required, as it contains all the data needed for the functioning of the UI and graphics. */ pakman_load_pak ("res/"); - stateman_init (); + stageman_init (); /* I don't know. This probably needs to be moved somewhere. */ @@ -45,7 +45,7 @@ SDL_AppInit (void **appstate, int argc, char **argv) entman_init (); chunkman_init (); - stateman_switch_state ("main_menu"); + stageman_switch_stage ("main_menu"); return SDL_APP_CONTINUE; } @@ -60,7 +60,7 @@ SDL_AppEvent (void *appstate, SDL_Event *event) return SDL_APP_SUCCESS; } - stateman_on_SDL_Event (event); + stageman_on_SDL_Event (event); return SDL_APP_CONTINUE; } @@ -70,10 +70,10 @@ SDL_AppIterate (void *appstate) { UNUSED (appstate); - stateman_update (); + stageman_update (); graphics_prerender (); - stateman_render (); + stageman_render (); graphics_postrender (); return SDL_APP_CONTINUE; @@ -84,5 +84,5 @@ SDL_AppQuit (void *appstate, SDL_AppResult result) { UNUSED (appstate, result); graphics_free (); - stateman_free (); + stageman_free (); } diff --git a/game/src/states/state_common.c b/game/src/stage/stage_common.c similarity index 89% rename from game/src/states/state_common.c rename to game/src/stage/stage_common.c index 1553d0e..01959cd 100644 --- a/game/src/states/state_common.c +++ b/game/src/stage/stage_common.c @@ -1,21 +1,22 @@ -#include "state_common.h" +#include "stage_common.h" -GameState * -GameState_new () +GameStage * +GameStage_new () { - GameState *g = g_new0 (GameState, 1); + GameStage *g = g_new0 (GameStage, 1); g->ui_context = UIContext_new (); g->ui_context->tooltip = PMUID ("tooltip"); + g->camera = g_new0 (Camera, 1); return g; } void -GameState_register_UIContext_handlers (GameState *self) +GameStage_register_UIContext_handlers (GameStage *self) { /* UGH... I fucking hate this whole structure of the game I did here. It should be really extensible and whatnot, but jesus christ, it's so complex... */ -#define GAEH GameState_add_event_handler +#define GAEH GameStage_add_event_handler GAEH (self, 1, SDL_EVENT_WINDOW_RESIZED, NULL, NULL, UIContext_window_resize,self->ui_context); GAEH (self, 1, SDL_EVENT_KEY_DOWN, evt_pred_flag, "ui_has_focus", UIContext_key_down, self->ui_context); @@ -30,7 +31,7 @@ GameState_register_UIContext_handlers (GameState *self) } void -GameState_add_event_handler (GameState *self, int priority, unsigned int on_event, +GameStage_add_event_handler (GameStage *self, int priority, unsigned int on_event, gboolean (*predicate) (SDL_Event *sdl_event, void *userdata), void *predicate_data, gboolean (*callback) (SDL_Event *sdl_event, void *userdata), @@ -54,7 +55,7 @@ GameState_add_event_handler (GameState *self, int priority, unsigned int on_even } void -GameState_handle_SDL_Event (GameState *self, SDL_Event *event) +GameStage_handle_SDL_Event (GameStage *self, SDL_Event *event) { for (GList *l = self->event_handlers; l != NULL; l = l->next) { diff --git a/game/src/states/state_common.h b/game/src/stage/stage_common.h similarity index 63% rename from game/src/states/state_common.h rename to game/src/stage/stage_common.h index a3a90c7..e278dad 100644 --- a/game/src/states/state_common.h +++ b/game/src/stage/stage_common.h @@ -7,6 +7,7 @@ #include "../util.h" #include "../gvar.h" +#include "../camera.h" typedef struct { unsigned int on_event; @@ -16,28 +17,31 @@ typedef struct { gboolean (*callback) (SDL_Event *sdl_event, void *userdata); } EventHandler; -typedef struct GameState +typedef struct GameStage { - UIContext *ui_context; + UIContext *ui_context; /* Could be NULL... */ + Camera *camera; /* Doesn't have to be defined. */ + GList *event_handlers; + void *userdata; + + void (*on_enter) (struct GameStage *); + void (*on_exit) (struct GameStage *); + void (*on_update) (struct GameStage *); + void (*on_render) (struct GameStage *); +} GameStage; - void (*on_enter) (struct GameState *); - void (*on_exit) (struct GameState *); - void (*on_update) (struct GameState *); - void (*on_render) (struct GameState *); -} GameState; +GameStage *GameStage_new (); -GameState *GameState_new (); +void GameStage_register_UIContext_handlers (GameStage *self); -void GameState_register_UIContext_handlers (GameState *self); - -void GameState_add_event_handler (GameState *self, int priority, unsigned int on_event, +void GameStage_add_event_handler (GameStage *self, int priority, unsigned int on_event, gboolean (*predicate) (SDL_Event *sdl_event, void *userdata), void *predicate_data, gboolean (*callback) (SDL_Event *sdl_event, void *userdata), void *callback_data); -void GameState_handle_SDL_Event (GameState *self, SDL_Event *event); +void GameStage_handle_SDL_Event (GameStage *self, SDL_Event *event); gboolean evt_pred_key (SDL_Event *event, void *data); gboolean evt_pred_flag (SDL_Event *event, void *data); diff --git a/game/src/states/state_game.c b/game/src/stage/stage_game.c similarity index 77% rename from game/src/states/state_game.c rename to game/src/stage/stage_game.c index 7adad9b..56e4230 100644 --- a/game/src/states/state_game.c +++ b/game/src/stage/stage_game.c @@ -1,6 +1,5 @@ -#include "state_game.h" +#include "stage_game.h" -extern vec3 camera_position, camera_rotation; extern SDL_Window *sdl_window; extern Entity *player_entity, *sky_entity; @@ -12,21 +11,21 @@ _on_enter () } static void -_on_update () +_on_update (GameStage *self) { - chunkman_tick (camera_position); + chunkman_tick (self->camera->position); entman_tick (); /* We pin the camera to the player position, with eye level 20 centimeters below the height. */ - glm_vec3_copy (player_entity->position, camera_position); - camera_position[1] += player_entity->scale[1] - 0.2; - player_entity->rotation[1] = camera_rotation[1]; + glm_vec3_copy (player_entity->position, self->camera->position); + self->camera->position[1] += player_entity->scale[1] - 0.2; + player_entity->rotation[1] = self->camera->rotation[1]; /* The sky needs to be in the center of the world all the time, otherwise, as we explore the world, we might reach the end of the sky. */ - sky_entity->position[0] = camera_position[0]; - sky_entity->position[2] = camera_position[2]; + sky_entity->position[0] = self->camera->position[0]; + sky_entity->position[2] = self->camera->position[2]; int speed = 5; float delta_time = gvar_get ("delta_time"); @@ -39,7 +38,7 @@ _on_update () if (FLAG_GET ("moving_forward")) { vec3 dir, change, new_pos; - camera_get_direction (dir); + Camera_get_direction (self->camera, dir); glm_vec3_scale (dir, delta_time * speed, change); glm_vec3_add (player_entity->position, change, new_pos); glm_vec3_copy (new_pos, player_entity->position); @@ -48,7 +47,7 @@ _on_update () if (FLAG_GET ("moving_backward")) { vec3 dir, change, new_pos; - camera_get_direction (dir); + Camera_get_direction (self->camera, dir); glm_vec3_scale (dir, delta_time * speed, change); glm_vec3_sub (player_entity->position, change, new_pos); glm_vec3_copy (new_pos, player_entity->position); @@ -57,7 +56,7 @@ _on_update () if (FLAG_GET ("moving_right")) { vec3 right, change, new_pos; - camera_get_right (right); + Camera_get_right (self->camera, right); glm_vec3_scale (right, delta_time * speed, change); glm_vec3_add (player_entity->position, change, new_pos); glm_vec3_copy (new_pos, player_entity->position); @@ -66,7 +65,7 @@ _on_update () if (FLAG_GET ("moving_left")) { vec3 right, change, new_pos; - camera_get_right (right); + Camera_get_right (self->camera, right); glm_vec3_scale (right, delta_time * speed, change); glm_vec3_sub (player_entity->position, change, new_pos); glm_vec3_copy (new_pos, player_entity->position); @@ -91,11 +90,11 @@ _on_update () } static void -_on_render () +_on_render (GameStage *self) { mat4 projection, view; - camera_get_projection (gvar_get ("window_width") / gvar_get ("window_height"), projection); - camera_get_view (view); + Camera_get_projection (self->camera, gvar_get ("window_width") / gvar_get ("window_height"), projection); + Camera_get_view (self->camera, view); pakman_all_paks_set_mat4 ("projection", projection); pakman_all_paks_set_mat4 ("view", view); @@ -108,11 +107,11 @@ _on_render () glm_frustum_planes (view_proj, planes); #endif - chunkman_render (camera_position, planes); - entman_render (view, planes); + chunkman_render (self->camera->position, planes); + entman_render (self->camera->position, view, planes); } -/* Some helper callbacks for the game gamestate. */ +/* Some helper callbacks for the game gamestage. */ gboolean _switch_ui_focus (SDL_Event *event, void *data) @@ -132,29 +131,30 @@ _switch_ui_focus (SDL_Event *event, void *data) gboolean _freelook_camera (SDL_Event *event, void *userdata) { - UNUSED (userdata); - camera_rotation[0] -= event->motion.xrel / 100.f; - camera_rotation[1] -= event->motion.yrel / 100.f; - camera_rotation[1] = - glm_clamp (camera_rotation[1], -M_PI / 2 + 0.025, M_PI / 2 - 0.025); + Camera *cam = userdata; + + cam->rotation[0] -= event->motion.xrel / 100.f; + cam->rotation[1] -= event->motion.yrel / 100.f; + cam->rotation[1] = + glm_clamp (cam->rotation[1], -M_PI / 2 + 0.025, M_PI / 2 - 0.025); return TRUE; } -GameState * -state_game_new () +GameStage * +stage_game_new () { - GameState *self = GameState_new (); + GameStage *self = GameStage_new (); self->on_enter = _on_enter; self->on_update = _on_update; self->on_render = _on_render; #define KEY(k) GINT_TO_POINTER(k) -#define GAEH GameState_add_event_handler +#define GAEH GameStage_add_event_handler - GAEH (self, 0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_TAB), _switch_ui_focus, self->ui_context); + GAEH (self, 0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_TAB), _switch_ui_focus, self->ui_context); - GAEH (self, 0, SDL_EVENT_MOUSE_MOTION, NULL, NULL, _freelook_camera, NULL); + GAEH (self, 0, SDL_EVENT_MOUSE_MOTION, NULL, NULL, _freelook_camera, self->camera); GAEH (self, 0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_W), evt_cb_flag_on, "moving_forward"); GAEH (self, 0, SDL_EVENT_KEY_UP, evt_pred_key, KEY (SDLK_W), evt_cb_flag_off, "moving_forward"); @@ -171,12 +171,11 @@ state_game_new () GAEH (self, 0, SDL_EVENT_KEY_DOWN, evt_pred_key, KEY (SDLK_LSHIFT), evt_cb_flag_on, "flying_fast"); GAEH (self, 0, SDL_EVENT_KEY_UP, evt_pred_key, KEY (SDLK_LSHIFT), evt_cb_flag_off, "flying_fast"); - #undef GAEH #undef KEY - /* If your GameState uses the UI, always call this. */ - GameState_register_UIContext_handlers (self); + /* If your GameStage uses the UI, always call this. */ + GameStage_register_UIContext_handlers (self); self->ui_context->root = PMUID ("debug_window"); return self; diff --git a/game/src/states/state_game.h b/game/src/stage/stage_game.h similarity index 60% rename from game/src/states/state_game.h rename to game/src/stage/stage_game.h index 8e6b6f0..c500582 100644 --- a/game/src/states/state_game.h +++ b/game/src/stage/stage_game.h @@ -1,9 +1,9 @@ #pragma once -#include "state_common.h" +#include "stage_common.h" #include "../graphics.h" #include "../gvar.h" #include "../camera.h" -GameState *state_game_new (); +GameStage *stage_game_new (); diff --git a/game/src/states/state_global.c b/game/src/stage/stage_global.c similarity index 74% rename from game/src/states/state_global.c rename to game/src/stage/stage_global.c index 794b328..92bce6c 100644 --- a/game/src/states/state_global.c +++ b/game/src/stage/stage_global.c @@ -1,4 +1,4 @@ -#include "state_global.h" +#include "stage_global.h" /* The required callbacks. */ @@ -6,7 +6,7 @@ static void _on_enter () { gvar_set ("last_time", SDL_GetTicks ()); - g_print ("Successfuly initialized global state\n"); + g_print ("Successfuly initialized global stage\n"); } static void _on_exit () { return; } @@ -19,12 +19,12 @@ _on_update () gvar_set ("last_time", now); } -GameState * -state_global_new () +GameStage * +stage_global_new () { - GameState *self = GameState_new (); + GameStage *self = GameStage_new (); -#define GAEH GameState_add_event_handler +#define GAEH GameStage_add_event_handler GAEH (self, 0, SDL_EVENT_WINDOW_RESIZED, NULL, NULL, graphics_cb_window_resize, NULL); diff --git a/game/src/states/state_global.h b/game/src/stage/stage_global.h similarity index 51% rename from game/src/states/state_global.h rename to game/src/stage/stage_global.h index 71ce682..4b13433 100644 --- a/game/src/states/state_global.h +++ b/game/src/stage/stage_global.h @@ -1,8 +1,8 @@ #pragma once -#include "state_common.h" +#include "stage_common.h" #include "../graphics.h" #include "../gvar.h" -GameState *state_global_new (); +GameStage *stage_global_new (); diff --git a/game/src/stage/stage_main_menu.c b/game/src/stage/stage_main_menu.c new file mode 100644 index 0000000..fce1bbf --- /dev/null +++ b/game/src/stage/stage_main_menu.c @@ -0,0 +1,21 @@ +#include "stage_main_menu.h" + +static void +_on_enter () +{ + gvar_set ("ui_has_focus", TRUE); +} + +GameStage * +stage_main_menu_new () +{ + GameStage *g = GameStage_new (); + + g->on_enter = _on_enter; + + /* If your GameStage uses the UI, always call this. */ + GameStage_register_UIContext_handlers (g); + g->ui_context->root = PMUID ("main_menu"); + + return g; +} diff --git a/game/src/states/state_main_menu.h b/game/src/stage/stage_main_menu.h similarity index 50% rename from game/src/states/state_main_menu.h rename to game/src/stage/stage_main_menu.h index a59d8fe..553cfd5 100644 --- a/game/src/states/state_main_menu.h +++ b/game/src/stage/stage_main_menu.h @@ -1,8 +1,8 @@ #pragma once -#include "state_common.h" +#include "stage_common.h" #include "../graphics.h" #include "../gvar.h" -GameState *state_main_menu_new (); +GameStage *stage_main_menu_new (); diff --git a/game/src/stage/stageman.c b/game/src/stage/stageman.c new file mode 100644 index 0000000..d6dbffc --- /dev/null +++ b/game/src/stage/stageman.c @@ -0,0 +1,102 @@ +#include "stageman.h" + +static GHashTable *game_stages; + +static GameStage *current_stage; +static GameStage *global_stage; + +void +stageman_init () +{ + game_stages = g_hash_table_new (g_str_hash, g_str_equal); + + stageman_add_stage ("main_menu", stage_main_menu_new ()); + stageman_add_stage ("game", stage_game_new ()); + + global_stage = stage_global_new (); + global_stage->on_enter (global_stage); +} + +static SCM +_scm_switch_stage (SCM stage_val) +{ + char *stage = scm_to_utf8_string (stage_val); + stageman_switch_stage (stage); + return SCM_UNSPECIFIED; +} + +void +stageman_guile_register () +{ + scm_c_define_gsubr ("switch-stage", 1, 0, 0, _scm_switch_stage); +} + +void +stageman_add_stage (const char *name, GameStage *stage) +{ + g_hash_table_replace (game_stages, g_strdup (name), stage); +} + +void +stageman_switch_stage (const char *name) +{ + GameStage *next_stage = g_hash_table_lookup (game_stages, name); + + if (current_stage && current_stage->on_exit) + { + current_stage->on_exit (current_stage); + } + + if (next_stage && next_stage->on_enter) + { + /* When we enter, we also set the UI root to be the current + window size. After that, if callbacks for a given stage are + set up correctly (using + GameStage_register_UIContext_handlers), then it will update + the root size automatically.*/ + next_stage->ui_context->root->size[0] = gvar_get ("window_width"); + next_stage->ui_context->root->size[1] = gvar_get ("window_height"); + next_stage->on_enter (next_stage); + current_stage = next_stage; + } +} + +void stageman_update () +{ + global_stage->on_update (global_stage); + + if (current_stage && current_stage->on_update) + { + current_stage->on_update (current_stage); + } + + if (current_stage && current_stage->ui_context) + { + UIContext_update (current_stage->ui_context); + } +} + +void +stageman_on_SDL_Event (SDL_Event *event) +{ + GameStage_handle_SDL_Event (global_stage, event); + + if (current_stage && current_stage->event_handlers) + { + GameStage_handle_SDL_Event (current_stage, event); + } +} + +void +stageman_render () +{ + if (current_stage && current_stage->on_render) + { + current_stage->on_render (current_stage); + } + + if (current_stage && current_stage->ui_context) + { + UIContext_render (current_stage->ui_context); + } +} diff --git a/game/src/stage/stageman.h b/game/src/stage/stageman.h new file mode 100644 index 0000000..5906b24 --- /dev/null +++ b/game/src/stage/stageman.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include "stage_common.h" +#include "stage_global.h" + +#include "stage_main_menu.h" +#include "stage_game.h" + +void stageman_init (); +void stageman_guile_register (); +static inline void stageman_free () { } /* TODO: implement */ +void stageman_add_stage (const char *name, GameStage *stage); +void stageman_switch_stage (const char *name); + +void stageman_update (); +void stageman_on_SDL_Event (SDL_Event *event); +void stageman_render (); diff --git a/game/src/states/state_main_menu.c b/game/src/states/state_main_menu.c deleted file mode 100644 index d5da027..0000000 --- a/game/src/states/state_main_menu.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "state_main_menu.h" - -static void -_on_enter () -{ - gvar_set ("ui_has_focus", TRUE); -} - -GameState * -state_main_menu_new () -{ - GameState *g = GameState_new (); - - g->on_enter = _on_enter; - - /* If your GameState uses the UI, always call this. */ - GameState_register_UIContext_handlers (g); - g->ui_context->root = PMUID ("main_menu"); - - return g; -} diff --git a/game/src/states/stateman.c b/game/src/states/stateman.c deleted file mode 100644 index ef85370..0000000 --- a/game/src/states/stateman.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "stateman.h" - -static GHashTable *game_states; - -static GameState *current_state; -static GameState *global_state; - -void -stateman_init () -{ - game_states = g_hash_table_new (g_str_hash, g_str_equal); - - stateman_add_state ("main_menu", state_main_menu_new ()); - stateman_add_state ("game", state_game_new ()); - - global_state = state_global_new (); - global_state->on_enter (global_state); -} - -static SCM -_scm_switch_state (SCM state_val) -{ - char *state = scm_to_utf8_string (state_val); - stateman_switch_state (state); - return SCM_UNSPECIFIED; -} - -void -stateman_guile_register () -{ - scm_c_define_gsubr ("stateman-switch-state", 1, 0, 0, _scm_switch_state); -} - -void -stateman_add_state (const char *name, GameState *state) -{ - g_hash_table_replace (game_states, g_strdup (name), state); -} - -void -stateman_switch_state (const char *name) -{ - GameState *next_state = g_hash_table_lookup (game_states, name); - - if (current_state && current_state->on_exit) - { - current_state->on_exit (current_state); - } - - if (next_state && next_state->on_enter) - { - /* When we enter, we also set the UI root to be the current - window size. After that, if callbacks for a given state are - set up correctly (using - GameState_register_UIContext_handlers), then it will update - the root size automatically.*/ - next_state->ui_context->root->size[0] = gvar_get ("window_width"); - next_state->ui_context->root->size[1] = gvar_get ("window_height"); - next_state->on_enter (next_state); - current_state = next_state; - } -} - -void stateman_update () -{ - global_state->on_update (global_state); - - if (current_state && current_state->on_update) - { - current_state->on_update (current_state); - } - - if (current_state && current_state->ui_context) - { - UIContext_update (current_state->ui_context); - } -} - -void -stateman_on_SDL_Event (SDL_Event *event) -{ - GameState_handle_SDL_Event (global_state, event); - - if (current_state && current_state->event_handlers) - { - GameState_handle_SDL_Event (current_state, event); - } -} - -void -stateman_render () -{ - if (current_state && current_state->on_render) - { - current_state->on_render (current_state); - } - - if (current_state && current_state->ui_context) - { - UIContext_render (current_state->ui_context); - } -} diff --git a/game/src/states/stateman.h b/game/src/states/stateman.h deleted file mode 100644 index ff3f082..0000000 --- a/game/src/states/stateman.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include - -#include "state_common.h" -#include "state_global.h" - -#include "state_main_menu.h" -#include "state_game.h" - -void stateman_init (); -void stateman_guile_register (); -static inline void stateman_free () { } /* TODO: implement */ -void stateman_add_state (const char *name, GameState *state); -void stateman_switch_state (const char *name); - -void stateman_update (); -void stateman_on_SDL_Event (SDL_Event *event); -void stateman_render ();