a-game

2D platformer written from scratch.
git clone git://git.amin.space/a-game.git
Log | Files | Refs | README | LICENSE

commit c4db8d188ef28e4f6a8c817a82e19dbc0556af38
parent 423b40abf8007d7354083b09765768169fd869fe
Author: amin <dev@aminmesbah.com>
Date:   Tue, 16 Apr 2019 21:39:55 +0000

Move platform game interfaces to new header file

This preparation for making certain platform functions available to the
game as function pointers.

FossilOrigin-Name: d5e9f425178ef6829b505b7d56eec146087841da3688519016f84e39ff9faa61
Diffstat:
Msrc/game.c | 22+++++++++++++---------
Msrc/game.h | 32+++-----------------------------
Msrc/glmth.h | 92-------------------------------------------------------------------------------
Asrc/platform.h | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/platform_linux.c | 36+++++++++++++++++++++---------------
Msrc/platform_linux.h | 10+---------
Msrc/types.h | 100++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
7 files changed, 188 insertions(+), 157 deletions(-)

diff --git a/src/game.c b/src/game.c @@ -9,8 +9,10 @@ void game_load_opengl_symbols(void) } #endif -internal void game_init(struct GameState *game_state, v2u framebuffer) +internal void game_init(struct GameMemory *game_memory, v2u framebuffer) { + struct GameState *game_state = game_memory->game_state; + // init player game_state->player.pos = (v2) { 1.0f, 1.0f }; @@ -65,8 +67,10 @@ internal void game_init(struct GameState *game_state, v2u framebuffer) // NOTE(amin): For now updating and rendering are interleaved. We simulate the // world at the same rate we render it. Our timestep is not fixed. We may want // to change this in the future. -void game_update_and_render(struct GameState *game_state, f32 dt, v2u framebuffer) +void game_update_and_render(struct GameMemory *game_memory, struct GameInput *game_input, v2u framebuffer) { + struct GameState *game_state = game_memory->game_state; + rect viewport = {0}; f32 ppm = 0.0f; { @@ -160,23 +164,22 @@ void game_update_and_render(struct GameState *game_state, f32 dt, v2u framebuffe // update player { f32 max_meters_per_second = 5.0f; - f32 movement_speed = max_meters_per_second * dt; - struct GameInput input = game_state->input; + f32 movement_speed = max_meters_per_second * game_input->dt; - if (input.key_up) + if (game_input->key_up) { game_state->player.pos.y += movement_speed; } - else if (input.key_down) + else if (game_input->key_down) { game_state->player.pos.y -= movement_speed; } - if (input.key_left) + if (game_input->key_left) { game_state->player.pos.x -= movement_speed; } - else if (input.key_right) + else if (game_input->key_right) { game_state->player.pos.x += movement_speed; } @@ -211,8 +214,9 @@ void game_update_and_render(struct GameState *game_state, f32 dt, v2u framebuffe } } -internal void game_cleanup(struct GameState *game_state) +internal void game_cleanup(struct GameMemory *game_memory) { + struct GameState *game_state = game_memory->game_state; glDeleteVertexArrays(1, &game_state->tiles.vao); glDeleteBuffers(1, &game_state->tiles.vbo); } diff --git a/src/game.h b/src/game.h @@ -10,6 +10,7 @@ #include "types.h" #include "glmth.h" #include "shader.h" +#include "platform.h" #define ROOM_TILE_DIM_X 25 #define ROOM_TILE_DIM_Y 10 @@ -24,21 +25,6 @@ struct Tiles struct Shader shader; }; -enum InputKeyAction -{ - KEY_RELEASE, - KEY_PRESS, - KEY_REPEAT, -}; - -struct GameInput -{ - enum InputKeyAction key_left; - enum InputKeyAction key_right; - enum InputKeyAction key_up; - enum InputKeyAction key_down; -}; - struct Entity { v2 pos; @@ -48,20 +34,8 @@ struct Entity struct GameState { struct Tiles tiles; - struct GameInput input; struct Entity player; }; -#ifdef PLATFORM_HOTLOAD_GAME_CODE -// We need to call this from the platform layer in order for the game, when -// built as a shared object library to have access to the OpenGL symbols. -// https://github.com/Dav1dde/glad/issues/151 -typedef void (game_load_opengl_symbols_func)(void); -void game_load_opengl_symbols(void); -#endif // PLATFORM_HOTLOAD_GAME_CODE - -typedef void (game_update_and_render_func)(struct GameState *game_state, f32 dt, v2u framebuffer); -void game_update_and_render(struct GameState *game_state, f32 dt, v2u framebuffer); - -internal void game_init(struct GameState *game_state, v2u framebuffer); -internal void game_cleanup(struct GameState *game_state); +internal void game_init(struct GameMemory *game_memory, v2u framebuffer); +internal void game_cleanup(struct GameMemory *game_memory); diff --git a/src/glmth.h b/src/glmth.h @@ -2,98 +2,6 @@ #define M_PI 3.14159265359f #endif -typedef union -{ - struct - { - f32 x, y; - }; - struct - { - f32 width, height; - }; - f32 E[2]; -} v2; - -typedef union -{ - struct - { - u32 x, y; - }; - struct - { - u32 width, height; - }; - u32 E[2]; -} v2u; - -typedef union -{ - struct - { - f32 x, y, z; - }; - struct - { - v2 xy; - f32 ignored_z; - }; - struct - { - f32 ignored_x; - v2 yz; - }; - f32 E[3]; -} v3; - -typedef union -{ - struct - { - union - { - v3 xyz; - struct - { - f32 x, y, z; - }; - }; - f32 w; - }; - struct - { - v2 xy; - f32 ignored_z_xy; - f32 ignored_w_xy; - }; - struct - { - f32 ignored_x_yz; - v2 yz; - f32 ignored_w_yz; - }; - struct - { - f32 ignored_x_zw; - f32 ignored_y_zw; - v2 zw; - }; - f32 E[4]; -} v4; - -typedef struct -{ - v2 min, max; -} rect; - -typedef struct -{ - // row-major, so you probably want to transpose before passing to opengl, - // which uses column-major matrices - f32 E[4][4]; // E[row][column] -} m4; - // TODO: make sure these functions are inlineable and that the compiler does // indeed inline them. diff --git a/src/platform.h b/src/platform.h @@ -0,0 +1,53 @@ +#pragma once + +#include <time.h> + +#include "types.h" + +enum InputKeyAction +{ + KEY_RELEASE, + KEY_PRESS, + KEY_REPEAT, +}; + +struct GameInput +{ + f32 dt; + enum InputKeyAction key_left; + enum InputKeyAction key_right; + enum InputKeyAction key_up; + enum InputKeyAction key_down; +}; + +#define PLATFORM_READ_ENTIRE_FILE(name) char *(name)(char *file_path) +typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file_func); + +struct PlatformApi +{ + platform_read_entire_file_func* platform_read_entire_file; +}; + +struct GameMemory +{ + struct GameState *game_state; + struct PlatformApi platform; +}; + +#ifdef PLATFORM_HOTLOAD_GAME_CODE +// We need to call this from the platform layer in order for the game, when +// built as a shared object library to have access to the OpenGL symbols. +// https://github.com/Dav1dde/glad/issues/151 +typedef void (game_load_opengl_symbols_func)(void); + +typedef void (game_update_and_render_func)(struct GameMemory *game_memory, struct GameInput *game_input, v2u framebuffer); + +struct GameCode +{ + bool is_valid; + void *game_code_library; + time_t last_write_time; + game_load_opengl_symbols_func *game_load_opengl_symbols; + game_update_and_render_func *game_update_and_render; +}; +#endif // PLATFORM_HOTLOAD_GAME_CODE diff --git a/src/platform_linux.c b/src/platform_linux.c @@ -7,6 +7,7 @@ #include <GLFW/glfw3.h> #include "game.c" +#include "platform.h" #include "platform_linux.h" internal void error_callback(int error, const char* description); @@ -68,8 +69,12 @@ int main(void) #endif struct GameState game_state = {0}; - glfwSetWindowUserPointer(window, &game_state); - game_init(&game_state, (v2u) {PLATFORM_SCR_WIDTH, PLATFORM_SCR_HEIGHT}); + struct GameMemory game_memory = {0}; + game_memory.game_state = &game_state; + + struct GameInput game_input = {0}; + glfwSetWindowUserPointer(window, &game_input); + game_init(&game_memory, (v2u) {PLATFORM_SCR_WIDTH, PLATFORM_SCR_HEIGHT}); #ifdef PLATFORM_HOTLOAD_GAME_CODE struct GameCode game_code = load_game_code(PLATFORM_GAME_LIB_PATH); @@ -80,7 +85,6 @@ int main(void) // to store it. We will not run out of precision. uint64_t previous_wall_clock_time = glfwGetTimerValue(); uint64_t timer_frequency = glfwGetTimerFrequency(); - float dt = 0.0f; while (!glfwWindowShouldClose(window)) { @@ -89,14 +93,18 @@ int main(void) { uint64_t previous_frame_duration = current_wall_clock_time - previous_wall_clock_time; previous_wall_clock_time = current_wall_clock_time; - dt = (float)previous_frame_duration / (float)timer_frequency; + f32 dt = (float)previous_frame_duration / (float)timer_frequency; // TODO: Debug periodic dropped frame on linux when fullscreen - printf("ms per frame: %f\n", dt * 1000.0f); + //printf("ms per frame: %f\n", dt * 1000.0f); + game_input.dt = dt; } int32_t framebuffer_width = PLATFORM_SCR_WIDTH; int32_t framebuffer_height = PLATFORM_SCR_HEIGHT; glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height); + assert(framebuffer_width >= 0); + assert(framebuffer_height >= 0); + v2u framebuffer = {framebuffer_width, framebuffer_height}; #ifdef PLATFORM_HOTLOAD_GAME_CODE time_t last_write_time = file_get_modified_time(PLATFORM_GAME_LIB_PATH); @@ -111,11 +119,9 @@ int main(void) // TODO: fall back to backup? } } - // TODO: Don't make a v2u out of two i32s - game_code.game_update_and_render(&game_state, dt, (v2u) {framebuffer_width, framebuffer_height}); + game_code.game_update_and_render(&game_memory, &game_input, framebuffer); #else - // TODO: Don't make a v2u out of two i32s - game_update_and_render(&game_state, dt, (v2u) {framebuffer_width, framebuffer_height}); + game_update_and_render(&game_memory, &game_input, framebuffer); #endif // PLATFORM_HOTLOAD_GAME_CODE // TODO: Do something sane when vsync is disabled @@ -123,7 +129,7 @@ int main(void) glfwPollEvents(); } - game_cleanup(&game_state); + game_cleanup(&game_memory); glfwDestroyWindow(window); glfwTerminate(); @@ -145,7 +151,7 @@ internal void framebuffer_size_callback(GLFWwindow* window, int width, int heigh internal void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { - struct GameState* game_state = (struct GameState *)glfwGetWindowUserPointer(window); + struct GameInput *game_input = (struct GameInput*)glfwGetWindowUserPointer(window); enum InputKeyAction game_input_key_action = 0; switch (action) @@ -168,16 +174,16 @@ internal void key_callback(GLFWwindow* window, int key, int scancode, int action switch (key) { case GLFW_KEY_LEFT: - game_key = &(game_state->input.key_left); + game_key = &(game_input->key_left); break; case GLFW_KEY_RIGHT: - game_key = &(game_state->input.key_right); + game_key = &(game_input->key_right); break; case GLFW_KEY_UP: - game_key = &(game_state->input.key_up); + game_key = &(game_input->key_up); break; case GLFW_KEY_DOWN: - game_key = &(game_state->input.key_down); + game_key = &(game_input->key_down); break; default: break; diff --git a/src/platform_linux.h b/src/platform_linux.h @@ -3,12 +3,4 @@ #ifdef PLATFORM_HOTLOAD_GAME_CODE #define PLATFORM_GAME_LIB_PATH "./out/release/game.so" -struct GameCode -{ - bool is_valid; - void *game_code_library; - time_t last_write_time; - game_load_opengl_symbols_func *game_load_opengl_symbols; - game_update_and_render_func *game_update_and_render; -}; -#endif // PLATFORM_HOTLOAD_GAME_CODE +#endif diff --git a/src/types.h b/src/types.h @@ -1,3 +1,9 @@ +#pragma once + +#define global_variable static +#define internal static +#define local_persist static + typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; @@ -9,6 +15,94 @@ typedef int64_t i64; typedef float f32; typedef double f64; -#define global_variable static -#define internal static -#define local_persist static +typedef union +{ + struct + { + f32 x, y; + }; + struct + { + f32 width, height; + }; + f32 E[2]; +} v2; + +typedef union +{ + struct + { + u32 x, y; + }; + struct + { + u32 width, height; + }; + u32 E[2]; +} v2u; + +typedef union +{ + struct + { + f32 x, y, z; + }; + struct + { + v2 xy; + f32 ignored_z; + }; + struct + { + f32 ignored_x; + v2 yz; + }; + f32 E[3]; +} v3; + +typedef union +{ + struct + { + union + { + v3 xyz; + struct + { + f32 x, y, z; + }; + }; + f32 w; + }; + struct + { + v2 xy; + f32 ignored_z_xy; + f32 ignored_w_xy; + }; + struct + { + f32 ignored_x_yz; + v2 yz; + f32 ignored_w_yz; + }; + struct + { + f32 ignored_x_zw; + f32 ignored_y_zw; + v2 zw; + }; + f32 E[4]; +} v4; + +typedef struct +{ + v2 min, max; +} rect; + +typedef struct +{ + // row-major, so you probably want to transpose before passing to opengl, + // which uses column-major matrices + f32 E[4][4]; // E[row][column] +} m4;