Add entity turn lockout
This commit is contained in:
@@ -113,6 +113,12 @@ errorret_t assetMeshLoaderSync(assetloading_t *loading) {
|
|||||||
errorChain(ret);
|
errorChain(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DUSK_OPENGL_LEGACY
|
||||||
|
// VBO owns the data now; CPU copy is no longer needed.
|
||||||
|
memoryFree(out->vertices);
|
||||||
|
out->vertices = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
loading->entry->state = ASSET_ENTRY_STATE_LOADED;
|
loading->entry->state = ASSET_ENTRY_STATE_LOADED;
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
@@ -125,7 +131,7 @@ errorret_t assetMeshDispose(assetentry_t *entry) {
|
|||||||
assetmeshoutput_t *out = &entry->data.mesh;
|
assetmeshoutput_t *out = &entry->data.mesh;
|
||||||
if(out->vertices != NULL) {
|
if(out->vertices != NULL) {
|
||||||
errorChain(meshDispose(&out->mesh));
|
errorChain(meshDispose(&out->mesh));
|
||||||
// memoryFree(out->vertices);
|
memoryFree(out->vertices);
|
||||||
out->vertices = NULL;
|
out->vertices = NULL;
|
||||||
}
|
}
|
||||||
errorOk();
|
errorOk();
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "rpg/overworld/map.h"
|
#include "rpg/overworld/map.h"
|
||||||
#include "rpg/overworld/tile.h"
|
#include "rpg/overworld/tile.h"
|
||||||
#include "time/time.h"
|
#include "time/time.h"
|
||||||
|
#include "entityanimwalk.h"
|
||||||
|
|
||||||
const entityanimcallback_t ENTITY_ANIM_CALLBACKS[ENTITY_ANIM_COUNT] = {
|
const entityanimcallback_t ENTITY_ANIM_CALLBACKS[ENTITY_ANIM_COUNT] = {
|
||||||
[ENTITY_ANIM_IDLE] = { entityAnimIdleUpdate },
|
[ENTITY_ANIM_IDLE] = { entityAnimIdleUpdate },
|
||||||
@@ -25,9 +26,19 @@ void entityAnimUpdate(entity_t *entity) {
|
|||||||
if(entity->animation != ENTITY_ANIM_IDLE) {
|
if(entity->animation != ENTITY_ANIM_IDLE) {
|
||||||
entity->animTime -= TIME.delta;
|
entity->animTime -= TIME.delta;
|
||||||
if(entity->animTime <= 0) {
|
if(entity->animTime <= 0) {
|
||||||
|
if(
|
||||||
|
entity->animation == ENTITY_ANIM_WALK ||
|
||||||
|
entity->animation == ENTITY_ANIM_RUN
|
||||||
|
) {
|
||||||
|
entity->walkEndCooldown = ENTITY_ANIM_WALK_TURN_COOLDOWN;
|
||||||
|
}
|
||||||
entity->animation = ENTITY_ANIM_IDLE;
|
entity->animation = ENTITY_ANIM_IDLE;
|
||||||
entity->animTime = 0;
|
entity->animTime = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(entity->walkEndCooldown > 0) {
|
||||||
|
entity->walkEndCooldown -= TIME.delta;
|
||||||
|
if(entity->walkEndCooldown < 0) entity->walkEndCooldown = 0;
|
||||||
|
}
|
||||||
ENTITY_ANIM_CALLBACKS[entity->animation].update(entity);
|
ENTITY_ANIM_CALLBACKS[entity->animation].update(entity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
typedef struct entity_s entity_t;
|
typedef struct entity_s entity_t;
|
||||||
|
|
||||||
#define ENTITY_ANIM_TURN_DURATION TIME_TICKS_TO_TIME(2)
|
#define ENTITY_ANIM_TURN_DURATION TIME_TICKS_TO_TIME(4)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates render position for the turn animation state.
|
* Updates render position for the turn animation state.
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
|
|
||||||
typedef struct entity_s entity_t;
|
typedef struct entity_s entity_t;
|
||||||
|
|
||||||
#define ENTITY_ANIM_WALK_DURATION TIME_TICKS_TO_TIME(10)
|
#define ENTITY_ANIM_WALK_DURATION TIME_TICKS_TO_TIME(12)
|
||||||
|
#define ENTITY_ANIM_WALK_TURN_COOLDOWN TIME_TICKS_TO_TIME(4)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates render position for the walk animation state.
|
* Updates render position for the walk animation state.
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ void entityUpdate(entity_t *entity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool_t entityCanTurn(entity_t *entity) {
|
bool_t entityCanTurn(entity_t *entity) {
|
||||||
return entity->animation == ENTITY_ANIM_IDLE;
|
return entity->animation == ENTITY_ANIM_IDLE &&
|
||||||
|
entity->walkEndCooldown <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t entityCanWalk(entity_t *entity) {
|
bool_t entityCanWalk(entity_t *entity) {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ typedef struct entity_s {
|
|||||||
|
|
||||||
entityanim_t animation;
|
entityanim_t animation;
|
||||||
float_t animTime;
|
float_t animTime;
|
||||||
|
float_t walkEndCooldown;
|
||||||
|
|
||||||
entityinteract_t interact;
|
entityinteract_t interact;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ void playerInit(entity_t *entity) {
|
|||||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
assertNotNull(entity, "Entity pointer cannot be NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool_t playerCanInteract(entity_t *entity) {
|
||||||
|
return entity->animation == ENTITY_ANIM_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
void playerInput(entity_t *entity) {
|
void playerInput(entity_t *entity) {
|
||||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
assertNotNull(entity, "Entity pointer cannot be NULL");
|
||||||
|
|
||||||
@@ -33,37 +37,51 @@ void playerInput(entity_t *entity) {
|
|||||||
// Can player act?
|
// Can player act?
|
||||||
if(UI_FOCUS.count > 0) return;
|
if(UI_FOCUS.count > 0) return;
|
||||||
|
|
||||||
// Turn - only if not already holding the direction we face
|
// Determine direction player may be trying to face/go.
|
||||||
const playerinputdirmap_t *dirMap = PLAYER_INPUT_DIR_MAP;
|
const playerinputdirmap_t *dirMap;
|
||||||
bool_t holdingFaced = false;
|
|
||||||
|
// First pass, we want to prefer a button relative to what the player is
|
||||||
|
// already facing, e.g. if they hold DOWN and start moving down, then tap
|
||||||
|
// right we want to prefer down over right.
|
||||||
|
|
||||||
|
// Determine current dirmap based on facing direction.
|
||||||
|
dirMap = PLAYER_INPUT_DIR_MAP;
|
||||||
do {
|
do {
|
||||||
if(!inputIsDown(dirMap->action)) continue;
|
if(dirMap->direction != entity->direction) continue;
|
||||||
if(entity->direction != dirMap->direction) continue;
|
|
||||||
holdingFaced = true;
|
|
||||||
break;
|
break;
|
||||||
} while((++dirMap)->action != 0xFF);
|
} while((++dirMap)->action != 0xFF);
|
||||||
|
|
||||||
if(!holdingFaced) {
|
// Are we holding that button?
|
||||||
|
if(!inputIsDown(dirMap->action)) {
|
||||||
|
// No, so we need to check all directions.
|
||||||
dirMap = PLAYER_INPUT_DIR_MAP;
|
dirMap = PLAYER_INPUT_DIR_MAP;
|
||||||
do {
|
do {
|
||||||
if(!inputIsDown(dirMap->action)) continue;
|
if(!inputIsDown(dirMap->action)) continue;
|
||||||
if(entity->direction == dirMap->direction) continue;
|
break;
|
||||||
return entityTurn(entity, dirMap->direction);
|
|
||||||
} while((++dirMap)->action != 0xFF);
|
} while((++dirMap)->action != 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk / Run
|
// Trying to direct?
|
||||||
bool_t running = inputIsDown(INPUT_ACTION_CANCEL);
|
if(dirMap->action != 0xFF) {
|
||||||
dirMap = PLAYER_INPUT_DIR_MAP;
|
// Is the player attempting to turn? That is, is the player idle and has the
|
||||||
do {
|
// turn lockout passed?
|
||||||
if(!inputIsDown(dirMap->action)) continue;
|
if(entityCanTurn(entity)) {
|
||||||
if(entity->direction != dirMap->direction) continue;
|
if(entity->direction != dirMap->direction) {
|
||||||
if(running) return entityRun(entity, dirMap->direction);
|
entityTurn(entity, dirMap->direction);
|
||||||
return entityWalk(entity, dirMap->direction);
|
return;
|
||||||
} while((++dirMap)->action != 0xFF);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t running = inputIsDown(INPUT_ACTION_CANCEL);
|
||||||
|
if(running && entityCanRun(entity)) {
|
||||||
|
entityRun(entity, dirMap->direction);
|
||||||
|
} else if(entityCanWalk(entity)) {
|
||||||
|
entityWalk(entity, dirMap->direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Interaction
|
// Interaction
|
||||||
if(inputPressed(INPUT_ACTION_ACCEPT)) {
|
if(inputPressed(INPUT_ACTION_ACCEPT) && playerCanInteract(entity)) {
|
||||||
worldunit_t x, y, z;
|
worldunit_t x, y, z;
|
||||||
{
|
{
|
||||||
worldunits_t relX, relY;
|
worldunits_t relX, relY;
|
||||||
@@ -77,5 +95,4 @@ void playerInput(entity_t *entity) {
|
|||||||
if(target == NULL) return;
|
if(target == NULL) return;
|
||||||
entityInteractWith(entity, target);
|
entityInteractWith(entity, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -35,9 +35,17 @@ static const playerinputdirmap_t PLAYER_INPUT_DIR_MAP[] = {
|
|||||||
*/
|
*/
|
||||||
void playerInit(entity_t *entity);
|
void playerInit(entity_t *entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the player entity is in a state where it can interact.
|
||||||
|
*
|
||||||
|
* @param entity Pointer to the player entity to check.
|
||||||
|
* @returns True if the entity can interact.
|
||||||
|
*/
|
||||||
|
bool_t playerCanInteract(entity_t *entity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles movement logic for the player entity.
|
* Handles movement logic for the player entity.
|
||||||
*
|
*
|
||||||
* @param entity Pointer to the player entity structure.
|
* @param entity Pointer to the player entity structure.
|
||||||
*/
|
*/
|
||||||
void playerInput(entity_t *entity);
|
void playerInput(entity_t *entity);
|
||||||
Reference in New Issue
Block a user