Made input work on fixed timesteps primarily.

This commit is contained in:
2025-11-04 08:41:18 -06:00
parent 6ea4132ff9
commit c9608ad7a7
11 changed files with 136 additions and 53 deletions

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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];

View File

@@ -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;

View File

@@ -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];

View File

@@ -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
}
};

View File

@@ -15,3 +15,12 @@ void npcInit(entity_t *entity) {
void npcUpdate(entity_t *entity) {
assertNotNull(entity, "Entity pointer cannot be NULL");
}
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;
};

View File

@@ -27,3 +27,11 @@ void npcInit(entity_t *entity);
* @param entity Pointer to the entity structure to update.
*/
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);

View File

@@ -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;
}
}

View File

@@ -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.
*