111 lines
2.9 KiB
C
111 lines
2.9 KiB
C
/**
|
|
* Copyright (c) 2025 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "entity.h"
|
|
#include "assert/assert.h"
|
|
#include "util/memory.h"
|
|
#include "time/time.h"
|
|
#include "util/math.h"
|
|
|
|
entity_t ENTITIES[ENTITY_COUNT];
|
|
|
|
void entityInit(entity_t *entity, const entitytype_t type) {
|
|
assertNotNull(entity, "Entity pointer cannot be NULL");
|
|
assertTrue(type < ENTITY_TYPE_COUNT, "Invalid entity type");
|
|
assertTrue(type != ENTITY_TYPE_NULL, "Cannot have NULL entity type");
|
|
assertTrue(
|
|
entity >= ENTITIES && entity < ENTITIES + ENTITY_COUNT,
|
|
"Entity pointer is out of bounds"
|
|
);
|
|
|
|
memoryZero(entity, sizeof(entity_t));
|
|
entity->id = (uint8_t)(entity - ENTITIES);
|
|
entity->type = type;
|
|
|
|
if(ENTITY_CALLBACKS[type].init != NULL) ENTITY_CALLBACKS[type].init(entity);
|
|
}
|
|
|
|
void entityUpdate(entity_t *entity) {
|
|
assertNotNull(entity, "Entity pointer cannot be NULL");
|
|
assertTrue(entity->type < ENTITY_TYPE_COUNT, "Invalid entity type");
|
|
assertTrue(entity->type != ENTITY_TYPE_NULL, "Cannot have NULL entity type");
|
|
|
|
// What state is the entity in?
|
|
if(entity->animation != ENTITY_ANIM_IDLE) {
|
|
// Entity is mid animation, tick it (down).
|
|
entity->animFrame--;
|
|
if(entity->animFrame == 0) entity->animation = ENTITY_ANIM_IDLE;
|
|
return;
|
|
}
|
|
|
|
// Movement code.
|
|
if(ENTITY_CALLBACKS[entity->type].movement != NULL) {
|
|
ENTITY_CALLBACKS[entity->type].movement(entity);
|
|
}
|
|
}
|
|
|
|
void entityTurn(entity_t *entity, const entitydir_t direction) {
|
|
entity->direction = direction;
|
|
entity->animation = ENTITY_ANIM_TURN;
|
|
entity->animFrame = ENTITY_ANIM_TURN_DURATION;
|
|
}
|
|
|
|
void entityWalk(entity_t *entity, const entitydir_t direction) {
|
|
// TODO: Animation, delay, etc.
|
|
entity->direction = direction;
|
|
|
|
// Where are we moving?
|
|
uint8_t newX, newY;
|
|
newX = entity->position.x;
|
|
newY = entity->position.y;
|
|
{
|
|
int8_t relX, relY;
|
|
entityDirGetRelative(direction, &relX, &relY);
|
|
newX += relX;
|
|
newY += relY;
|
|
}
|
|
|
|
// TODO: Tile in way?
|
|
// TODO: Map bounds in way?
|
|
|
|
// Entity in way?
|
|
entity_t *start = ENTITIES;
|
|
do {
|
|
if(
|
|
start == entity ||
|
|
entity->type == ENTITY_TYPE_NULL ||
|
|
start->position.x != newX ||
|
|
start->position.y != newY ||
|
|
start->position.z != entity->position.z
|
|
) {
|
|
start++;
|
|
continue;
|
|
}
|
|
|
|
return;// Blocked
|
|
} while(start < &ENTITIES[ENTITY_COUNT]);
|
|
|
|
// Move.
|
|
entity->position.x = newX;
|
|
entity->position.y = newY;
|
|
|
|
entity->animation = ENTITY_ANIM_WALK;
|
|
entity->animFrame = ENTITY_ANIM_WALK_DURATION;// TODO: Running vs walking
|
|
}
|
|
|
|
entity_t * entityGetAt(const worldpos_t position) {
|
|
entity_t *ent = ENTITIES;
|
|
do {
|
|
if(ent->type == ENTITY_TYPE_NULL) continue;
|
|
if(ent->position.x != position.x) continue;
|
|
if(ent->position.y != position.y) continue;
|
|
if(ent->position.z != position.z) continue;
|
|
return ent;
|
|
} while(++ent, ent < &ENTITIES[ENTITY_COUNT]);
|
|
|
|
return NULL;
|
|
} |