diff --git a/.gitignore b/.gitignore index caf783c..cc0eb7a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ -.cache/clangd/index +.vscode +.cache +compile_commands/ bin/ build/ intermediate/ diff --git a/Build.lua b/Build.lua index a2777cf..339cff8 100644 --- a/Build.lua +++ b/Build.lua @@ -5,7 +5,7 @@ workspace "Fencer-Template" startproject "Game" filter "system:windows" - defines { "SDL_MAIN_HANDLED" } + defines { "SDL_MAIN_HANDLED", "_CRT_SECURE_NO_WARNINGS" } buildoptions { "/EHsc", "/Zc:preprocessor" } OutputDir = "%{cfg.system}-%{cfg.architecture}/%{cfg.buildcfg}" diff --git a/assets/sprites/player/player_walk.png b/assets/sprites/player/player_walk.png deleted file mode 100644 index b90fd8e..0000000 Binary files a/assets/sprites/player/player_walk.png and /dev/null differ diff --git a/core/src/animation_sprite.c b/core/src/animation_sprite.c new file mode 100644 index 0000000..692721b --- /dev/null +++ b/core/src/animation_sprite.c @@ -0,0 +1,58 @@ +#include "animation_sprite.h" +#include "debug.h" +#include "program.h" + +struct AnimationSprite { + Spritesheet* sheet; + Sprite* sprite; + + AnimationSpriteLoopMode loop_mode; + + float frame_interval; + float start_time; +}; + +AnimationSprite* animation_sprite_new(Spritesheet* sheet, float framerate) { + AnimationSprite* self = malloc(sizeof(AnimationSprite)); + ASSERT_RETURN(self != NULL, NULL, "Failed to allocate memory for AnimationSprite"); + *self = (AnimationSprite){ + .sheet = sheet, + .frame_interval = 1.0f / framerate, + .loop_mode = LoopMode_Loop, + .start_time = game_time(), + .sprite = sprite_from_spritesheet(sheet, 0) + }; + + return self; +} + +void animation_sprite_destroy(AnimationSprite* self) { + sprite_destroy(self->sprite); + spritesheet_destroy(self->sheet); + free(self); +} + +void animation_sprite_play_from(AnimationSprite* self, float normalized_time) { + self->start_time = game_time() - normalized_time * animation_sprite_get_length(self); +} + +void animation_sprite_draw(AnimationSprite* self, Transform* transform) { + const float time = game_time() - self->start_time; + const size_t frame = time / self->frame_interval; + + sprite_set_spritesheet(self->sprite, self->sheet); + sprite_set_tile(self->sprite, frame); + sprite_draw(self->sprite, *transform); +} + +float animation_sprite_get_length(AnimationSprite* self) { + return (float)spritesheet_get_tile_count(self->sheet) * self->frame_interval; +} + +void animation_sprite_set_framerate(AnimationSprite* self, float framerate) { + self->frame_interval = 1.0f / framerate; +} + +float animation_sprite_get_framerate(const AnimationSprite* self) { + return 1.0f / self->frame_interval; +} diff --git a/core/src/animation_sprite.h b/core/src/animation_sprite.h new file mode 100644 index 0000000..135e440 --- /dev/null +++ b/core/src/animation_sprite.h @@ -0,0 +1,26 @@ +#ifndef _fencer_animation_sprite_h +#define _fencer_animation_sprite_h + +#include "sprite.h" +#include "spritesheet.h" + +typedef enum AnimationSpriteLoopMode { + LoopMode_Stop, + LoopMode_Hide, + LoopMode_Loop, + LoopMode_PingPong, +} AnimationSpriteLoopMode; + +typedef struct AnimationSprite AnimationSprite; + +extern AnimationSprite* animation_sprite_new(Spritesheet* sheet, float framerate); +extern void animation_sprite_destroy(AnimationSprite* self); + +extern void animation_sprite_play_from(AnimationSprite* self, float normalized_time); +extern void animation_sprite_draw(AnimationSprite* self, Transform* transform); + +extern float animation_sprite_get_length(AnimationSprite* self); +extern void animation_sprite_set_framerate(AnimationSprite* self, float framerate); +extern float animation_sprite_get_framerate(const AnimationSprite* self); + +#endif // !_fencer_animation_sprite_h \ No newline at end of file diff --git a/core/src/assets.c b/core/src/assets.c index 6473d2c..0f90a1d 100644 --- a/core/src/assets.c +++ b/core/src/assets.c @@ -10,16 +10,16 @@ static asset_id _next_id = 0; static size_t file_length(FILE* fp) { - size_t start = ftell(fp); + long start = ftell(fp); fseek(fp, 0, SEEK_END); - size_t r = ftell(fp); + long r = ftell(fp); fseek(fp, start, SEEK_SET); - return r; + return (size_t)r; } static void read_file(FILE* fp, char* out_buffer, size_t out_size) { - size_t start = ftell(fp); + long start = ftell(fp); fread(out_buffer, 1, out_size, fp); fseek(fp, start, SEEK_SET); } @@ -88,15 +88,13 @@ asset_id get_asset_id(void* asset) { } void free_asset(asset_id id) { - Asset* found; - size_t found_index; + Asset* found = NULL; + size_t found_index = _assets.len; for(size_t i = 0; i < _assets.len; ++i) { found = list_at_as(Asset, &_assets, i); if(found->tc->get_id(found->data) == id) { found_index = i; break; - } else { - found = NULL; } } ASSERT_RETURN(found != NULL,, "Attempt to free nonexistent asset."); diff --git a/core/src/assets.h b/core/src/assets.h index 8f6a11b..579254a 100644 --- a/core/src/assets.h +++ b/core/src/assets.h @@ -31,8 +31,8 @@ size_t json_array_len(cJSON* array); static inline Vector json_array_to_vector(cJSON* array) { return (Vector) { - cJSON_GetArrayItem(array, 0)->valuedouble, - cJSON_GetArrayItem(array, 1)->valuedouble, + (float)cJSON_GetArrayItem(array, 0)->valuedouble, + (float)cJSON_GetArrayItem(array, 1)->valuedouble, }; } static inline diff --git a/core/src/camera.c b/core/src/camera.c index 80b7946..c9c896b 100644 --- a/core/src/camera.c +++ b/core/src/camera.c @@ -21,7 +21,7 @@ SDL_FRect camera_world_to_pixel_rect(Camera* self, SDL_FRect* world_space) { t.scale = OneVector; t = transform_invert(t); - Vector tl = {world_space->x + (self->fov / 2.0), world_space->y + (_camera_height(self) / 2.0)}; + Vector tl = {world_space->x + (self->fov / 2.0f), world_space->y + (_camera_height(self) / 2.0f)}; Vector size = {world_space->w, world_space->h}; tl = vmulff(transform_point(&t, tl), g_render_resolution.x / self->fov); @@ -40,7 +40,7 @@ Vector camera_world_to_pixel_point(Camera* self, Vector point) { t.scale = OneVector; t = transform_invert(t); - point = (Vector){point.x + (self->fov / 2.0), point.y + (_camera_height(self) / 2.0)}; + point = (Vector){point.x + (self->fov / 2.0f), point.y + (_camera_height(self) / 2.0f)}; return vmulff(transform_point(&t, point), g_render_resolution.x / self->fov); } diff --git a/core/src/drop.c b/core/src/drop.c new file mode 100644 index 0000000..7bd372a --- /dev/null +++ b/core/src/drop.c @@ -0,0 +1,6 @@ +#include "drop.h" +#include "stdlib.h" + +void default_drop(void* data) { + free(data); +} diff --git a/core/src/drop.h b/core/src/drop.h index e5aaef4..c5a9936 100644 --- a/core/src/drop.h +++ b/core/src/drop.h @@ -19,8 +19,13 @@ static inline Drop T##_as_Drop(T* x) {\ return (Drop){.tc = &tc, .data = x};\ } -#define impl_default_Drop_for(T)\ - static void default_drop_##T(T* v) { free(v); }\ - impl_Drop_for(T, default_drop_##T) +extern void default_drop(void*); +#define impl_default_Drop_for(T)\ +static inline Drop T##_as_Drop(T* x) {\ + static IDrop const tc = {\ + .drop = default_drop,\ + };\ + return (Drop){.tc = &tc, .data = x};\ +} #endif // !_fencer_drop_h diff --git a/core/src/game_world.c b/core/src/game_world.c index 8dfa86f..b93a029 100644 --- a/core/src/game_world.c +++ b/core/src/game_world.c @@ -73,7 +73,7 @@ void game_world_update() { _internal_clear_removed(); } -void game_word_draw() { +void game_world_draw() { list_foreach(BehaviourEntity*, entity, &_game_entities) { entity->tc->draw(entity->data); } diff --git a/core/src/input_axis.c b/core/src/input_axis.c index 36ee80f..162a897 100644 --- a/core/src/input_axis.c +++ b/core/src/input_axis.c @@ -4,6 +4,7 @@ KeyBind* keybind_new(SDL_Scancode key) { KeyBind* self = malloc(sizeof(KeyBind)); + ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for KeyBind instance"); *self = (KeyBind) { .device = NULL, .scancode = key, @@ -31,6 +32,7 @@ void keybind_set_device(KeyBind* self, InputDevice* device) { ControllerAxis* controlleraxis_new(int axis) { ControllerAxis* self = malloc(sizeof(ControllerAxis)); + ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for ControllerAxis instance"); *self = (ControllerAxis){ .axis = axis, .device = NULL @@ -48,7 +50,6 @@ int controlleraxis_is_changed_by(ControllerAxis* self, SDL_Event event) { InputEvent controlleraxis_evaluate(ControllerAxis* self, SDL_Event event) { float result = (float)event.caxis.value / 32767.0; - LOG_INFO("axis %f", result); return (InputEvent) { .type = InputEvent_Float, .as_float = result @@ -61,6 +62,7 @@ void controlleraxis_set_device(ControllerAxis* self, InputDevice* device) { ControllerButton* controllerbutton_new(int button) { ControllerButton* self = malloc(sizeof(ControllerButton)); + ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for ControllerButton instance"); *self = (ControllerButton) { .button = button, .device = NULL @@ -88,6 +90,7 @@ void controllerbutton_set_device(ControllerButton* self, InputDevice* device) { CompositeAxis1D* compositeaxis1d_new(InputAxis left, InputAxis right, InputEventType type) { CompositeAxis1D* self = malloc(sizeof(CompositeAxis1D)); + ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for CompositeAxis1D instance"); *self = (CompositeAxis1D) { .left = left, .right = right, diff --git a/core/src/physics_entity.c b/core/src/physics_entity.c index 5b7b45d..4d2f5bb 100644 --- a/core/src/physics_entity.c +++ b/core/src/physics_entity.c @@ -18,11 +18,11 @@ void physics_entity_debug_draw(PhysicsEntity self) { lhs = camera_world_to_pixel_point(&g_camera, lhs); rhs = camera_world_to_pixel_point(&g_camera, rhs); SDL_SetRenderDrawColor(g_renderer, 0, 255, 0, 255); - SDL_RenderDrawLine(g_renderer, lhs.x, lhs.y, rhs.x, rhs.y); + SDL_RenderDrawLineF(g_renderer, lhs.x, lhs.y, rhs.x, rhs.y); rhs = camera_world_to_pixel_point(&g_camera, vaddf(transform->position, rigidbody_get_force(body))); SDL_SetRenderDrawColor(g_renderer, 0, 255, 255, 255); - SDL_RenderDrawLine(g_renderer, lhs.x, lhs.y, rhs.x, rhs.y); + SDL_RenderDrawLineF(g_renderer, lhs.x, lhs.y, rhs.x, rhs.y); } static inline Vector _internal_calculate_contact_force(RigidBody* self, Contact* contact) { diff --git a/core/src/player_input.c b/core/src/player_input.c index d8220f8..55d1efc 100644 --- a/core/src/player_input.c +++ b/core/src/player_input.c @@ -1,7 +1,9 @@ #include "player_input.h" +#include "debug.h" PlayerInput* playerinput_new(void* target, int device) { PlayerInput* self = malloc(sizeof(PlayerInput)); + ASSERT_RETURN(self != NULL, NULL, "Could not allocate memory for PlayerInput instance"); self->listeners = list_from_type(InputListener); self->device = input_get_device_by_id(device); self->target = target; diff --git a/core/src/program.c b/core/src/program.c index 62a7220..538c960 100644 --- a/core/src/program.c +++ b/core/src/program.c @@ -25,7 +25,7 @@ double tstos(struct timespec ts) { struct timespec get_time() { struct timespec ts; - timespec_get(&ts, TIME_UTC); + (void)timespec_get(&ts, TIME_UTC); return ts; } @@ -80,6 +80,7 @@ void program_run(const struct ProgramSettings* settings) { physics_world_tick(); } settings->on_draw(); + game_world_draw(); SDL_Delay(1); } @@ -132,10 +133,10 @@ void program_handle_windowevent(SDL_WindowEvent* event) { inline float delta_time() { - return _target_delta_time == 0 ? _delta_time : _target_delta_time; + return (float)(_target_delta_time == 0 ? _delta_time : _target_delta_time); } inline float game_time() { - return get_time_s() - _game_start_time; + return (float)(get_time_s() - _game_start_time); } diff --git a/core/src/sprite.c b/core/src/sprite.c index ac86bd8..3524502 100644 --- a/core/src/sprite.c +++ b/core/src/sprite.c @@ -42,10 +42,10 @@ void sprite_draw(Sprite* self, Transform transform) { Vector origin = self->origin; if(self->flip_state && SDL_FLIP_HORIZONTAL) { - origin.x = 1.0-origin.x; + origin.x = 1.0f-origin.x; } if((self->flip_state & SDL_FLIP_VERTICAL) != 0) { - origin.y = 1.0-origin.y; + origin.y = 1.0f-origin.y; } Vector left_top = transform_point(&transform, vinvf(origin)); @@ -75,8 +75,7 @@ size_t sprite_get_tile(const Sprite* self) { } void sprite_set_tile(Sprite* self, size_t frame) { - frame = frame % spritesheet_get_tile_count(self->spritesheet); - self->tile_index = frame; + self->tile_index = frame % spritesheet_get_tile_count(self->spritesheet); } Spritesheet* sprite_get_spritesheet(const Sprite* self) { diff --git a/core/src/spritesheet.c b/core/src/spritesheet.c index 777492a..554fa6f 100644 --- a/core/src/spritesheet.c +++ b/core/src/spritesheet.c @@ -43,8 +43,8 @@ Spritesheet* spritesheet_from_texture(SDL_Texture* texture, IVector tile_size) { SDL_QueryTexture(self->texture, NULL, NULL, &self->resolution.x, &self->resolution.y); self->tile_size = tile_size; - self->tile_shear = self->resolution.x / self->tile_size.x; - self->tile_count = self->resolution.x / self->tile_size.x * self->resolution.y / self->tile_size.y; + self->tile_shear = (size_t)self->resolution.x / self->tile_size.x; + self->tile_count = (size_t)self->resolution.x / self->tile_size.x * self->resolution.y / self->tile_size.y; return self; } @@ -57,7 +57,7 @@ SDL_Texture* spritesheet_get_texture(const Spritesheet* self) { } SDL_Rect spritesheet_get_tile_rect(const Spritesheet* self, size_t index) { - IVector tile_coord = {index % self->tile_shear, index / self->tile_shear}; + IVector tile_coord = {(int)(index % self->tile_shear), (int)(index / self->tile_shear)}; tile_coord = vmuli(tile_coord, self->tile_size); return (SDL_Rect) { diff --git a/core/src/state.h b/core/src/state.h new file mode 100644 index 0000000..ebaea05 --- /dev/null +++ b/core/src/state.h @@ -0,0 +1,27 @@ +#ifndef _fencer_state_h +#define _fencer_state_h + +#include "typeclass_helpers.h" + +typedef struct State State; + +struct State { + void (*const enter)(void* data); + void (*const exit)(void* data); + const State* (*const update)(void* data, float dt); +}; + +#define DefineState(_StateName, _DataType, enter_fn, exit_fn, update_fn)\ +static inline const State* _StateName() {\ + TC_FN_TYPECHECK(void, enter_fn, _DataType*);\ + TC_FN_TYPECHECK(void, exit_fn, _DataType*);\ + TC_FN_TYPECHECK(const State*, update_fn, _DataType*, float);\ + static const State instance = {\ + .enter = (void(*const)(void*)) enter_fn,\ + .exit = (void(*const)(void*)) exit_fn,\ + .update = (const State*(*const)(void*, float)) update_fn,\ + };\ + return &instance;\ +} + +#endif // !_fencer_state_h diff --git a/core/src/state_machine.c b/core/src/state_machine.c new file mode 100644 index 0000000..4e18ad8 --- /dev/null +++ b/core/src/state_machine.c @@ -0,0 +1,42 @@ +#include "state_machine.h" +#include "stdlib.h" +#include "debug.h" + +struct StateMachine { + const State* current_state; + void* data; +}; + +static inline +void internal_state_machine_set_state(StateMachine* self, const State* state) { + self->current_state->exit(self->data); + self->current_state = state; + self->current_state->enter(self->data); +} + +StateMachine* state_machine_init(void* data, const State* start_state) { + StateMachine* self = malloc(sizeof(StateMachine)); + ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for StateMachine instance"); + *self = (StateMachine){ + .current_state = start_state, + .data = data + }; + + self->current_state->enter(self->data); + return self; +} + +void state_machine_destroy(StateMachine* self) { + self->current_state->exit(self->data); + free(self); +} + +void state_machine_update(StateMachine* self, float dt) { + const State* next = self->current_state->update(self->data, dt); + if(next != self->current_state) + internal_state_machine_set_state(self, next); +} + +const State* state_machine_get_current_state(StateMachine* self) { + return self->current_state; +} diff --git a/core/src/state_machine.h b/core/src/state_machine.h new file mode 100644 index 0000000..0d5c2fb --- /dev/null +++ b/core/src/state_machine.h @@ -0,0 +1,15 @@ +#ifndef _fencer_state_machine_h +#define _fencer_state_machine_h + +#include "state.h" + +typedef struct StateMachine StateMachine; + +extern StateMachine* state_machine_init(void* data, const State* start_state); +extern void state_machine_destroy(StateMachine* self); + +extern void state_machine_update(StateMachine* self, float dt); + +extern const State* state_machine_get_current_state(StateMachine* self); + +#endif // !_fencer_state_machine_h diff --git a/core/src/vmath.h b/core/src/vmath.h index 4c92d6b..029463f 100644 --- a/core/src/vmath.h +++ b/core/src/vmath.h @@ -106,7 +106,7 @@ float vsqrmagnitudef(Vector a) { static inline Vector vnormalizedf(Vector a) { if(veqf(a, ZeroVector)) return ZeroVector; - return vmulff(a, 1.0/vmagnitudef(a)); + return vmulff(a, 1.0f/vmagnitudef(a)); } static inline float vdotf(Vector a, Vector b) { @@ -122,7 +122,7 @@ float vsqrdistf(Vector a, Vector b) { } static inline Vector vreciprocalf(Vector a) { - return (Vector){1.0/a.x, 1.0/a.y}; + return (Vector){1.0f/a.x, 1.0f/a.y}; } static inline Vector vrotatef(Vector a, float t) { @@ -157,7 +157,7 @@ Vector vaveragef(Vector* array, size_t count) { for(size_t i = 0; i < count; ++i) { acc = vaddf(acc, array[i]); } - return vmulff(acc, 1.0/(float)count); + return vmulff(acc, 1.0f/(float)count); } static inline diff --git a/game/Build-Game.lua b/game/Build-Game.lua index fd6bf22..8fb6e6a 100644 --- a/game/Build-Game.lua +++ b/game/Build-Game.lua @@ -3,17 +3,22 @@ project "Game" language "C" staticruntime "Off" targetdir "bin/%{cfg.buildcfg}" + debugdir "." defines { "VMATH_SDL" } files { "src/**.c", "src/**.h" } includedirs { "src/", - "../core/src" + "../core/src/" } links { "Engine-Core" } + + postbuildcommands { + "{COPYDIR} assets/ %{cfg.targetdir}/assets" + } targetdir ("../bin/" .. OutputDir .. "/%{prj.name}" ) objdir ("../intermediate/" .. OutputDir .. "/%{prj.name}" ) diff --git a/game/src/fencer.c b/game/src/fencer.c index 47ab192..050c644 100644 --- a/game/src/fencer.c +++ b/game/src/fencer.c @@ -1,10 +1,7 @@ -#include "camera.h" #include "program.h" static -void play() { - g_camera.fov = 40; -} +void play() {} static void tick() {}