From c9608ad7a7f0ca291a924fe92314c14879a34830 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Tue, 4 Nov 2025 08:41:18 -0600 Subject: [PATCH] Made input work on fixed timesteps primarily. --- CMakeLists.txt | 2 +- src/input/input.c | 26 ++++++++++++++++-- src/input/input.h | 18 ++++++++++++- src/input/inputaction.h | 2 ++ src/rpg/entity/entity.c | 15 +---------- src/rpg/entity/entity.h | 16 ++--------- src/rpg/entity/entitytype.h | 53 +++++++++++++++++++++++++++++++++++++ src/rpg/entity/npc.c | 11 +++++++- src/rpg/entity/npc.h | 10 ++++++- src/rpg/entity/player.c | 20 ++------------ src/rpg/entity/player.h | 16 ++++++++++- 11 files changed, 136 insertions(+), 53 deletions(-) create mode 100644 src/rpg/entity/entitytype.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e9d19b..d26057c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ # Setup cmake_minimum_required(VERSION 3.13) -set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) diff --git a/src/input/input.c b/src/input/input.c index 881a263..5c154e3 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -10,6 +10,7 @@ #include "util/memory.h" #include "util/string.h" #include "util/math.h" +#include "time/time.h" input_t INPUT; @@ -81,6 +82,11 @@ void inputUpdate(void) { do { action->lastValue = action->currentValue; action->currentValue = 0.0f; + if(TIME.fixedUpdate) { + action->lastFixedValue = action->currentFixedValue; + action->currentFixedValue = 0.0f; + } + action++; } while(action < &INPUT.actions[INPUT_ACTION_COUNT]); @@ -95,20 +101,36 @@ void inputUpdate(void) { continue; } + // Update current val. INPUT.actions[cur->action].currentValue = mathMax( cur->curVal, INPUT.actions[cur->action].currentValue ); + if(TIME.fixedUpdate) { + INPUT.actions[cur->action].currentFixedValue = mathMax( + cur->curVal, INPUT.actions[cur->action].currentFixedValue + ); + } cur++; } while(cur->name); } float_t inputGetCurrentValue(const inputaction_t action) { + assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds"); + return INPUT.actions[action].currentFixedValue; +} + +float_t inputGetCurrentValueNonFixed(const inputaction_t action) { assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds"); return INPUT.actions[action].currentValue; } -float_t inputGetLast(const inputaction_t action) { +float_t inputGetLastValue(const inputaction_t action) { + assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds"); + return INPUT.actions[action].lastFixedValue; +} + +float_t inputGetLastValueNonFixed(const inputaction_t action) { assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds"); return INPUT.actions[action].lastValue; } @@ -118,7 +140,7 @@ bool_t inputIsDown(const inputaction_t action) { } bool_t inputWasDown(const inputaction_t action) { - return inputGetLast(action) > 0.0f; + return inputGetLastValue(action) > 0.0f; } bool_t inputPressed(const inputaction_t action) { diff --git a/src/input/input.h b/src/input/input.h index 89b8be0..9aab7f3 100644 --- a/src/input/input.h +++ b/src/input/input.h @@ -47,13 +47,29 @@ void inputUpdate(void); */ float_t inputGetCurrentValue(const inputaction_t action); +/** + * Gets the current value of a specific input action (non-fixed timestep). + * + * @param action The input action to get the value for. + * @return The current value of the action (0.0f to 1.0f). + */ +float_t inputGetCurrentValueNonFixed(const inputaction_t action); + /** * Gets the last value of a specific input action. * * @param action The input action to get the value for. * @return The last value of the action (0.0f to 1.0f). */ -float_t inputGetLast(const inputaction_t action); +float_t inputGetLastValue(const inputaction_t action); + +/** + * Gets the last value of a specific input action (non-fixed timestep). + * + * @param action The input action to get the value for. + * @return The last value of the action (0.0f to 1.0f). + */ +float_t inputGetLastValueNonFixed(const inputaction_t action); /** * Checks if a specific input action is currently pressed. diff --git a/src/input/inputaction.h b/src/input/inputaction.h index 07bf400..1040e2c 100644 --- a/src/input/inputaction.h +++ b/src/input/inputaction.h @@ -25,6 +25,8 @@ typedef struct { inputaction_t action; float_t lastValue; float_t currentValue; + float_t lastFixedValue; + float_t currentFixedValue; } inputactiondata_t; extern const char_t* INPUT_ACTION_NAMES[INPUT_ACTION_COUNT]; diff --git a/src/rpg/entity/entity.c b/src/rpg/entity/entity.c index 2eca099..a904e75 100644 --- a/src/rpg/entity/entity.c +++ b/src/rpg/entity/entity.c @@ -26,19 +26,7 @@ void entityInit(entity_t *entity, const entitytype_t type) { entity->id = (uint8_t)(entity - ENTITIES); entity->type = type; - // Init. I did use a callback struct but it was not flexible enough. - switch(type) { - case ENTITY_TYPE_PLAYER: - playerInit(entity); - break; - - case ENTITY_TYPE_NPC: - npcInit(entity); - break; - - default: - break; - } + if(ENTITY_CALLBACKS[type].init != NULL) ENTITY_CALLBACKS[type].init(entity); } void entityUpdate(entity_t *entity) { @@ -66,7 +54,6 @@ void entityTurn(entity_t *entity, const entitydir_t direction) { entity->animFrame = ENTITY_ANIM_TURN_DURATION; } - void entityWalk(entity_t *entity, const entitydir_t direction) { // TODO: Animation, delay, etc. entity->direction = direction; diff --git a/src/rpg/entity/entity.h b/src/rpg/entity/entity.h index 4ef4b14..9a89860 100644 --- a/src/rpg/entity/entity.h +++ b/src/rpg/entity/entity.h @@ -8,24 +8,17 @@ #pragma once #include "entitydir.h" #include "entityanim.h" -#include "rpg/entity/player.h" +#include "entitytype.h" #include "npc.h" -#include "rpg/world/worldpos.h" #define ENTITY_COUNT 256 typedef struct map_s map_t; -typedef enum { - ENTITY_TYPE_NULL, - ENTITY_TYPE_PLAYER, - ENTITY_TYPE_NPC, - ENTITY_TYPE_COUNT -} entitytype_t; - typedef struct entity_s { uint8_t id; entitytype_t type; + entitytypedata_t; // Movement entitydir_t direction; @@ -33,11 +26,6 @@ typedef struct entity_s { entityanim_t animation; uint8_t animFrame; - - union { - player_t player; - npc_t npc; - }; } entity_t; extern entity_t ENTITIES[ENTITY_COUNT]; diff --git a/src/rpg/entity/entitytype.h b/src/rpg/entity/entitytype.h new file mode 100644 index 0000000..7369b75 --- /dev/null +++ b/src/rpg/entity/entitytype.h @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "rpg/entity/player.h" +#include "npc.h" + +typedef enum { + ENTITY_TYPE_NULL, + + ENTITY_TYPE_PLAYER, + ENTITY_TYPE_NPC, + + ENTITY_TYPE_COUNT +} entitytype_t; + +typedef union { + player_t player; + npc_t npc; +} entitytypedata_t; + +typedef struct { + /** + * Initialization callback for the entity type. + * @param entity Pointer to the entity to initialize. + */ + void (*init)(entity_t *entity); + + /** + * Interaction callback for the entity type. + * @param player Pointer to the player entity. + * @param entity Pointer to the entity to interact with. + * @return True if the entity handled the interaction, false otherwise. + */ + bool_t (*interact)(entity_t *player, entity_t *entity); +} entitycallback_t; + +static const entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = { + [ENTITY_TYPE_NULL] = { NULL }, + + [ENTITY_TYPE_PLAYER] = { + .init = playerInit + }, + + [ENTITY_TYPE_NPC] = { + .init = npcInit, + .interact = npcInteract + } +}; \ No newline at end of file diff --git a/src/rpg/entity/npc.c b/src/rpg/entity/npc.c index 79d21d6..1f97e0f 100644 --- a/src/rpg/entity/npc.c +++ b/src/rpg/entity/npc.c @@ -14,4 +14,13 @@ void npcInit(entity_t *entity) { void npcUpdate(entity_t *entity) { assertNotNull(entity, "Entity pointer cannot be NULL"); -} \ No newline at end of file +} + +bool_t npcInteract(entity_t *player, entity_t *npc) { + assertNotNull(player, "Player entity pointer cannot be NULL"); + assertNotNull(npc, "NPC entity pointer cannot be NULL"); + + printf("npc interact\n"); + + return false; +}; \ No newline at end of file diff --git a/src/rpg/entity/npc.h b/src/rpg/entity/npc.h index b22754f..a444da2 100644 --- a/src/rpg/entity/npc.h +++ b/src/rpg/entity/npc.h @@ -26,4 +26,12 @@ void npcInit(entity_t *entity); * * @param entity Pointer to the entity structure to update. */ -void npcUpdate(entity_t *entity); \ No newline at end of file +void npcUpdate(entity_t *entity); + +/** + * Handles interaction with an NPC entity. + * + * @param player Pointer to the player entity. + * @param npc Pointer to the NPC entity. + */ +bool_t npcInteract(entity_t *player, entity_t *npc); \ No newline at end of file diff --git a/src/rpg/entity/player.c b/src/rpg/entity/player.c index c1d84ba..cf33d56 100644 --- a/src/rpg/entity/player.c +++ b/src/rpg/entity/player.c @@ -7,25 +7,10 @@ #include "entity.h" #include "assert/assert.h" -#include "input/input.h" #include "rpg/rpgcamera.h" #include "util/memory.h" #include "time/time.h" -typedef struct { - inputaction_t action; - entitydir_t direction; -} playerinputdirmap_t; - -static const playerinputdirmap_t PLAYER_INPUT_DIR_MAP[] = { - { INPUT_ACTION_UP, ENTITY_DIR_NORTH }, - { INPUT_ACTION_DOWN, ENTITY_DIR_SOUTH }, - { INPUT_ACTION_LEFT, ENTITY_DIR_WEST }, - { INPUT_ACTION_RIGHT, ENTITY_DIR_EAST }, - - { 0xFF, 0xFF } -}; - void playerInit(entity_t *entity) { assertNotNull(entity, "Entity pointer cannot be NULL"); } @@ -61,9 +46,8 @@ void playerInput(entity_t *entity) { } entity_t *interact = entityGetAt((worldpos_t){ x, y, z }); - if(interact != NULL) { - printf("INTERACT\n"); - return; + if(interact != NULL && ENTITY_CALLBACKS[interact->type].interact != NULL) { + if(ENTITY_CALLBACKS[interact->type].interact(entity, interact)) return; } } diff --git a/src/rpg/entity/player.h b/src/rpg/entity/player.h index 97dfd31..8c10f31 100644 --- a/src/rpg/entity/player.h +++ b/src/rpg/entity/player.h @@ -6,7 +6,7 @@ */ #pragma once -#include "dusk.h" +#include "input/input.h" typedef struct entity_s entity_t; @@ -14,6 +14,20 @@ typedef struct { void *nothing; } player_t; +typedef struct { + inputaction_t action; + entitydir_t direction; +} playerinputdirmap_t; + +static const playerinputdirmap_t PLAYER_INPUT_DIR_MAP[] = { + { INPUT_ACTION_UP, ENTITY_DIR_NORTH }, + { INPUT_ACTION_DOWN, ENTITY_DIR_SOUTH }, + { INPUT_ACTION_LEFT, ENTITY_DIR_WEST }, + { INPUT_ACTION_RIGHT, ENTITY_DIR_EAST }, + + { 0xFF, 0xFF } +}; + /** * Initializes a player entity. *