Files
dusk/src/dusk/entity/entity.c
2025-06-19 16:48:04 -05:00

109 lines
3.4 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 "world/world.h"
#include "physics/physics.h"
entity_t ENTITIES[ENTITY_COUNT_MAX] = {0};
entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = {
{NULL}, // ENTITY_TYPE_NULL
{playerNPCInit, playerNPCUpdate}, // ENTITY_TYPE_PLAYER
{npcInit, npcUpdate} // ENTITY_TYPE_NPC
};
void entityInit(entity_t *entity, const entitytype_t type) {
assertNotNull(entity, "Entity pointer cannot be NULL");
assertTrue(type != ENTITY_TYPE_NULL, "Entity type NULL");
assertTrue(type < ENTITY_TYPE_COUNT, "Entity type out of bounds");
assertNotNull(
ENTITY_CALLBACKS[type].init,
"Entity type has no init callback"
);
memoryZero(entity, sizeof(entity_t));
entity->type = type;
ENTITY_CALLBACKS[type].init(entity);
}
void entityUpdate(entity_t *entity) {
assertNotNull(entity, "Entity pointer cannot be NULL");
assertTrue(entity->type != ENTITY_TYPE_NULL, "Entity type NULL");
assertTrue(entity->type < ENTITY_TYPE_COUNT, "Entity type out of bounds");
assertNotNull(
ENTITY_CALLBACKS[entity->type].update,
"Entity type has no update callback"
);
ENTITY_CALLBACKS[entity->type].update(entity);
if(
entity->vx == FIXED248(0, 0) &&
entity->vy == FIXED248(0, 0)
) return;
fixed248_t newX = entity->x + entity->vx;
fixed248_t newY = entity->y + entity->vy;
fixed248_t halfTileWH = FIXED248(TILE_WIDTH_HEIGHT / 2, 0);
fixed248_t selfCircR = halfTileWH;
// Check for collisions with the world boundaries
// Check for collisions with tile
fixed248_t tileStartX = fx248Floor(newX - halfTileWH);
fixed248_t tileStartY = fx248Floor(newY - halfTileWH);
fixed248_t tileEndX = fx248Ceil(newX + halfTileWH);
fixed248_t tileEndY = fx248Ceil(newY + halfTileWH);
for(fixed248_t y = tileStartY; y <= tileEndY; y+= FIXED248_ONE) {
for(fixed248_t x = tileStartX; x <= tileEndX; x+= FIXED248_ONE) {
//
}
}
// uint16_t tileStartX = fx248Tou16(fx248Floor(newX - halfTileWH));
// uint16_t tileStartY = fx248Tou16(fx248Floor(newY - halfTileWH));
// uint16_t tileEndX = fx248Tou16(fx248Ceil(newX + halfTileWH)) + 1;
// uint16_t tileEndY = fx248Tou16(fx248Ceil(newY + halfTileWH)) + 1;
// printf("Checking tiles between (%u, %u) and (%u, %u)\n",
// tileStartX, tileStartY, tileEndX, tileEndY
// );
// for(uint16_t tileY = tileStartY; tileY <= tileEndY; tileY++) {
// for(uint16_t tileX = tileStartX; tileX <= tileEndX; tileX++) {
// }
// }
// Check for collisions with other entities
entity_t *otherEntity = ENTITIES;
do {
// Skip self and null entities
if(otherEntity == entity || otherEntity->type == ENTITY_TYPE_NULL) continue;
fixed248_t otherCircR = halfTileWH;
collisionresult_t collision = physicsCheckCircleCircle(
newX, newY, selfCircR,
otherEntity->x, otherEntity->y, otherCircR
);
if(!collision.hit) continue;
// Collision with entity detected. Slide out of collision.
fixed248_t slideX = fx248Mulf32(collision.normalX, fx248Tof32(collision.depth));
fixed248_t slideY = fx248Mulf32(collision.normalY, fx248Tof32(collision.depth));
newX -= slideX;
newY -= slideY;
} while(++otherEntity < ENTITIES + ENTITY_COUNT_MAX);
entity->x = newX;
entity->y = newY;
}