Add entity turn lockout
This commit is contained in:
@@ -113,6 +113,12 @@ errorret_t assetMeshLoaderSync(assetloading_t *loading) {
|
||||
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;
|
||||
errorOk();
|
||||
}
|
||||
@@ -125,7 +131,7 @@ errorret_t assetMeshDispose(assetentry_t *entry) {
|
||||
assetmeshoutput_t *out = &entry->data.mesh;
|
||||
if(out->vertices != NULL) {
|
||||
errorChain(meshDispose(&out->mesh));
|
||||
// memoryFree(out->vertices);
|
||||
memoryFree(out->vertices);
|
||||
out->vertices = NULL;
|
||||
}
|
||||
errorOk();
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "rpg/overworld/map.h"
|
||||
#include "rpg/overworld/tile.h"
|
||||
#include "time/time.h"
|
||||
#include "entityanimwalk.h"
|
||||
|
||||
const entityanimcallback_t ENTITY_ANIM_CALLBACKS[ENTITY_ANIM_COUNT] = {
|
||||
[ENTITY_ANIM_IDLE] = { entityAnimIdleUpdate },
|
||||
@@ -25,9 +26,19 @@ void entityAnimUpdate(entity_t *entity) {
|
||||
if(entity->animation != ENTITY_ANIM_IDLE) {
|
||||
entity->animTime -= TIME.delta;
|
||||
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->animTime = 0;
|
||||
}
|
||||
}
|
||||
if(entity->walkEndCooldown > 0) {
|
||||
entity->walkEndCooldown -= TIME.delta;
|
||||
if(entity->walkEndCooldown < 0) entity->walkEndCooldown = 0;
|
||||
}
|
||||
ENTITY_ANIM_CALLBACKS[entity->animation].update(entity);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
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.
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
|
||||
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.
|
||||
|
||||
@@ -52,7 +52,8 @@ void entityUpdate(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) {
|
||||
|
||||
@@ -27,6 +27,7 @@ typedef struct entity_s {
|
||||
|
||||
entityanim_t animation;
|
||||
float_t animTime;
|
||||
float_t walkEndCooldown;
|
||||
|
||||
entityinteract_t interact;
|
||||
|
||||
|
||||
@@ -17,6 +17,10 @@ void playerInit(entity_t *entity) {
|
||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
||||
}
|
||||
|
||||
bool_t playerCanInteract(entity_t *entity) {
|
||||
return entity->animation == ENTITY_ANIM_IDLE;
|
||||
}
|
||||
|
||||
void playerInput(entity_t *entity) {
|
||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
||||
|
||||
@@ -33,37 +37,51 @@ void playerInput(entity_t *entity) {
|
||||
// Can player act?
|
||||
if(UI_FOCUS.count > 0) return;
|
||||
|
||||
// Turn - only if not already holding the direction we face
|
||||
const playerinputdirmap_t *dirMap = PLAYER_INPUT_DIR_MAP;
|
||||
bool_t holdingFaced = false;
|
||||
// Determine direction player may be trying to face/go.
|
||||
const playerinputdirmap_t *dirMap;
|
||||
|
||||
// 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 {
|
||||
if(!inputIsDown(dirMap->action)) continue;
|
||||
if(entity->direction != dirMap->direction) continue;
|
||||
holdingFaced = true;
|
||||
if(dirMap->direction != entity->direction) continue;
|
||||
break;
|
||||
} 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;
|
||||
do {
|
||||
if(!inputIsDown(dirMap->action)) continue;
|
||||
if(entity->direction == dirMap->direction) continue;
|
||||
return entityTurn(entity, dirMap->direction);
|
||||
break;
|
||||
} while((++dirMap)->action != 0xFF);
|
||||
}
|
||||
|
||||
// Walk / Run
|
||||
bool_t running = inputIsDown(INPUT_ACTION_CANCEL);
|
||||
dirMap = PLAYER_INPUT_DIR_MAP;
|
||||
do {
|
||||
if(!inputIsDown(dirMap->action)) continue;
|
||||
if(entity->direction != dirMap->direction) continue;
|
||||
if(running) return entityRun(entity, dirMap->direction);
|
||||
return entityWalk(entity, dirMap->direction);
|
||||
} while((++dirMap)->action != 0xFF);
|
||||
// Trying to direct?
|
||||
if(dirMap->action != 0xFF) {
|
||||
// Is the player attempting to turn? That is, is the player idle and has the
|
||||
// turn lockout passed?
|
||||
if(entityCanTurn(entity)) {
|
||||
if(entity->direction != dirMap->direction) {
|
||||
entityTurn(entity, dirMap->direction);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool_t running = inputIsDown(INPUT_ACTION_CANCEL);
|
||||
if(running && entityCanRun(entity)) {
|
||||
entityRun(entity, dirMap->direction);
|
||||
} else if(entityCanWalk(entity)) {
|
||||
entityWalk(entity, dirMap->direction);
|
||||
}
|
||||
}
|
||||
|
||||
// Interaction
|
||||
if(inputPressed(INPUT_ACTION_ACCEPT)) {
|
||||
if(inputPressed(INPUT_ACTION_ACCEPT) && playerCanInteract(entity)) {
|
||||
worldunit_t x, y, z;
|
||||
{
|
||||
worldunits_t relX, relY;
|
||||
@@ -77,5 +95,4 @@ void playerInput(entity_t *entity) {
|
||||
if(target == NULL) return;
|
||||
entityInteractWith(entity, target);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,6 +35,14 @@ static const playerinputdirmap_t PLAYER_INPUT_DIR_MAP[] = {
|
||||
*/
|
||||
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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user