Made input work on fixed timesteps primarily.
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
# Setup
|
# Setup
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "util/math.h"
|
#include "util/math.h"
|
||||||
|
#include "time/time.h"
|
||||||
|
|
||||||
input_t INPUT;
|
input_t INPUT;
|
||||||
|
|
||||||
@@ -81,6 +82,11 @@ void inputUpdate(void) {
|
|||||||
do {
|
do {
|
||||||
action->lastValue = action->currentValue;
|
action->lastValue = action->currentValue;
|
||||||
action->currentValue = 0.0f;
|
action->currentValue = 0.0f;
|
||||||
|
if(TIME.fixedUpdate) {
|
||||||
|
action->lastFixedValue = action->currentFixedValue;
|
||||||
|
action->currentFixedValue = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
action++;
|
action++;
|
||||||
} while(action < &INPUT.actions[INPUT_ACTION_COUNT]);
|
} while(action < &INPUT.actions[INPUT_ACTION_COUNT]);
|
||||||
|
|
||||||
@@ -95,20 +101,36 @@ void inputUpdate(void) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update current val.
|
||||||
INPUT.actions[cur->action].currentValue = mathMax(
|
INPUT.actions[cur->action].currentValue = mathMax(
|
||||||
cur->curVal, INPUT.actions[cur->action].currentValue
|
cur->curVal, INPUT.actions[cur->action].currentValue
|
||||||
);
|
);
|
||||||
|
if(TIME.fixedUpdate) {
|
||||||
|
INPUT.actions[cur->action].currentFixedValue = mathMax(
|
||||||
|
cur->curVal, INPUT.actions[cur->action].currentFixedValue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
cur++;
|
cur++;
|
||||||
} while(cur->name);
|
} while(cur->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
float_t inputGetCurrentValue(const inputaction_t action) {
|
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");
|
assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds");
|
||||||
return INPUT.actions[action].currentValue;
|
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");
|
assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds");
|
||||||
return INPUT.actions[action].lastValue;
|
return INPUT.actions[action].lastValue;
|
||||||
}
|
}
|
||||||
@@ -118,7 +140,7 @@ bool_t inputIsDown(const inputaction_t action) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool_t inputWasDown(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) {
|
bool_t inputPressed(const inputaction_t action) {
|
||||||
|
|||||||
@@ -47,13 +47,29 @@ void inputUpdate(void);
|
|||||||
*/
|
*/
|
||||||
float_t inputGetCurrentValue(const inputaction_t action);
|
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.
|
* Gets the last value of a specific input action.
|
||||||
*
|
*
|
||||||
* @param action The input action to get the value for.
|
* @param action The input action to get the value for.
|
||||||
* @return The last value of the action (0.0f to 1.0f).
|
* @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.
|
* Checks if a specific input action is currently pressed.
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ typedef struct {
|
|||||||
inputaction_t action;
|
inputaction_t action;
|
||||||
float_t lastValue;
|
float_t lastValue;
|
||||||
float_t currentValue;
|
float_t currentValue;
|
||||||
|
float_t lastFixedValue;
|
||||||
|
float_t currentFixedValue;
|
||||||
} inputactiondata_t;
|
} inputactiondata_t;
|
||||||
|
|
||||||
extern const char_t* INPUT_ACTION_NAMES[INPUT_ACTION_COUNT];
|
extern const char_t* INPUT_ACTION_NAMES[INPUT_ACTION_COUNT];
|
||||||
|
|||||||
@@ -26,19 +26,7 @@ void entityInit(entity_t *entity, const entitytype_t type) {
|
|||||||
entity->id = (uint8_t)(entity - ENTITIES);
|
entity->id = (uint8_t)(entity - ENTITIES);
|
||||||
entity->type = type;
|
entity->type = type;
|
||||||
|
|
||||||
// Init. I did use a callback struct but it was not flexible enough.
|
if(ENTITY_CALLBACKS[type].init != NULL) ENTITY_CALLBACKS[type].init(entity);
|
||||||
switch(type) {
|
|
||||||
case ENTITY_TYPE_PLAYER:
|
|
||||||
playerInit(entity);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ENTITY_TYPE_NPC:
|
|
||||||
npcInit(entity);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void entityUpdate(entity_t *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;
|
entity->animFrame = ENTITY_ANIM_TURN_DURATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void entityWalk(entity_t *entity, const entitydir_t direction) {
|
void entityWalk(entity_t *entity, const entitydir_t direction) {
|
||||||
// TODO: Animation, delay, etc.
|
// TODO: Animation, delay, etc.
|
||||||
entity->direction = direction;
|
entity->direction = direction;
|
||||||
|
|||||||
@@ -8,24 +8,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "entitydir.h"
|
#include "entitydir.h"
|
||||||
#include "entityanim.h"
|
#include "entityanim.h"
|
||||||
#include "rpg/entity/player.h"
|
#include "entitytype.h"
|
||||||
#include "npc.h"
|
#include "npc.h"
|
||||||
#include "rpg/world/worldpos.h"
|
|
||||||
|
|
||||||
#define ENTITY_COUNT 256
|
#define ENTITY_COUNT 256
|
||||||
|
|
||||||
typedef struct map_s map_t;
|
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 {
|
typedef struct entity_s {
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
entitytype_t type;
|
entitytype_t type;
|
||||||
|
entitytypedata_t;
|
||||||
|
|
||||||
// Movement
|
// Movement
|
||||||
entitydir_t direction;
|
entitydir_t direction;
|
||||||
@@ -33,11 +26,6 @@ typedef struct entity_s {
|
|||||||
|
|
||||||
entityanim_t animation;
|
entityanim_t animation;
|
||||||
uint8_t animFrame;
|
uint8_t animFrame;
|
||||||
|
|
||||||
union {
|
|
||||||
player_t player;
|
|
||||||
npc_t npc;
|
|
||||||
};
|
|
||||||
} entity_t;
|
} entity_t;
|
||||||
|
|
||||||
extern entity_t ENTITIES[ENTITY_COUNT];
|
extern entity_t ENTITIES[ENTITY_COUNT];
|
||||||
|
|||||||
53
src/rpg/entity/entitytype.h
Normal file
53
src/rpg/entity/entitytype.h
Normal 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
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -14,4 +14,13 @@ void npcInit(entity_t *entity) {
|
|||||||
|
|
||||||
void npcUpdate(entity_t *entity) {
|
void npcUpdate(entity_t *entity) {
|
||||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
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;
|
||||||
|
};
|
||||||
@@ -26,4 +26,12 @@ void npcInit(entity_t *entity);
|
|||||||
*
|
*
|
||||||
* @param entity Pointer to the entity structure to update.
|
* @param entity Pointer to the entity structure to update.
|
||||||
*/
|
*/
|
||||||
void npcUpdate(entity_t *entity);
|
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);
|
||||||
@@ -7,25 +7,10 @@
|
|||||||
|
|
||||||
#include "entity.h"
|
#include "entity.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "input/input.h"
|
|
||||||
#include "rpg/rpgcamera.h"
|
#include "rpg/rpgcamera.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "time/time.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) {
|
void playerInit(entity_t *entity) {
|
||||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
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 });
|
entity_t *interact = entityGetAt((worldpos_t){ x, y, z });
|
||||||
if(interact != NULL) {
|
if(interact != NULL && ENTITY_CALLBACKS[interact->type].interact != NULL) {
|
||||||
printf("INTERACT\n");
|
if(ENTITY_CALLBACKS[interact->type].interact(entity, interact)) return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "dusk.h"
|
#include "input/input.h"
|
||||||
|
|
||||||
typedef struct entity_s entity_t;
|
typedef struct entity_s entity_t;
|
||||||
|
|
||||||
@@ -14,6 +14,20 @@ typedef struct {
|
|||||||
void *nothing;
|
void *nothing;
|
||||||
} player_t;
|
} 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.
|
* Initializes a player entity.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user