109 lines
3.4 KiB
C
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;
|
|
} |