From 025bc2cff622a3c356f09a8fe855d8f37f48eb33 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Fri, 20 Jun 2025 12:01:00 -0500 Subject: [PATCH] Moved tile collision --- src/dusk/entity/entity.c | 66 ++++++-------------------------------- src/dusk/physics/physics.c | 66 ++++++++++++++++++++++++++++++++++++++ src/dusk/physics/physics.h | 17 ++++++++++ 3 files changed, 92 insertions(+), 57 deletions(-) diff --git a/src/dusk/entity/entity.c b/src/dusk/entity/entity.c index 075a6ce..2bff5c7 100644 --- a/src/dusk/entity/entity.c +++ b/src/dusk/entity/entity.c @@ -54,6 +54,11 @@ void entityUpdate(entity_t *entity) { fixed248_t newX = entity->x + entity->vx; fixed248_t newY = entity->y + entity->vy; fixed248_t halfTileWH = FIXED248(TILE_WIDTH_HEIGHT / 2, 0); + + // Because all hit detection is done assuming the entity is a circle, with + // its position centered, we need to precalc these; + fixed248_t selfCircX = fx248Addfx248(newX, halfTileWH); + fixed248_t selfCircY = fx248Addfx248(newY, halfTileWH); fixed248_t selfCircR = halfTileWH; // Check for collisions with tiles @@ -91,63 +96,9 @@ void entityUpdate(entity_t *entity) { uint8_t chunkTileY = tileY % CHUNK_HEIGHT; tile_t tile = chunk->tilesBase[chunkTileY * CHUNK_WIDTH + chunkTileX]; - fixed248_t lx = fx248Mulfx248(x, FIXED248(TILE_WIDTH_HEIGHT, 0)); - fixed248_t ty = fx248Mulfx248(y, FIXED248(TILE_WIDTH_HEIGHT, 0)); - fixed248_t rx = fx248Addfx248(lx, FIXED248(TILE_WIDTH_HEIGHT, 0)); - fixed248_t by = fx248Addfx248(ty, FIXED248(TILE_WIDTH_HEIGHT, 0)); - - // Determine tile collision type - collisionresult_t collision; - switch(TILE_META_DATA[tile].solidType) { - case TILE_SOLID_FULL: - collision = physicsCheckCircleAABB( - fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR, - lx, ty, - FIXED248(TILE_WIDTH_HEIGHT, 0), - FIXED248(TILE_WIDTH_HEIGHT, 0) - ); - break; - - case TILE_SOLID_TRIANGLE_TOP_RIGHT: - collision = physicsCheckCircleTriangle( - fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR, - rx, by, - rx, ty, - lx, ty - ); - break; - - case TILE_SOLID_TRIANGLE_TOP_LEFT: - collision = physicsCheckCircleTriangle( - fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR, - lx, by, - lx, ty, - rx, ty - ); - break; - - case TILE_SOLID_TRIANGLE_BOTTOM_RIGHT: - collision = physicsCheckCircleTriangle( - fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR, - rx, ty, - rx, by, - lx, by - ); - break; - case TILE_SOLID_TRIANGLE_BOTTOM_LEFT: - collision = physicsCheckCircleTriangle( - fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR, - lx, ty, - lx, by, - rx, by - ); - break; - - default: - continue; - } - - + collisionresult_t collision = physicsCheckCircleTile( + selfCircX, selfCircY, selfCircR, x, y, tile + ); if(collision.hit && collision.depth > FIXED248(0, 1)) { fixed248_t slideX = fx248Mulfx248( collision.normalX, collision.depth @@ -172,6 +123,7 @@ void entityUpdate(entity_t *entity) { fixed248_t otherCircR = halfTileWH; + // We DONT use selfCircX/Y here because the other entity is ALSO a circle. collisionresult_t collision = physicsCheckCircleCircle( newX, newY, selfCircR, otherEntity->x, otherEntity->y, otherCircR diff --git a/src/dusk/physics/physics.c b/src/dusk/physics/physics.c index 81ec5e1..1ac4f82 100644 --- a/src/dusk/physics/physics.c +++ b/src/dusk/physics/physics.c @@ -6,6 +6,7 @@ */ #include "physics.h" +#include "world/tiledata.h" collisionresult_t physicsCheckCircleCircle( fixed248_t circle0x, fixed248_t circle0y, fixed248_t circle0r, @@ -245,3 +246,68 @@ collisionresult_t physicsCheckCircleTriangle( return result; } + +collisionresult_t physicsCheckCircleTile( + fixed248_t circleX, fixed248_t circleY, fixed248_t circleR, + fixed248_t tileX, fixed248_t tileY, tile_t tile +) { + collisionresult_t result; + + #define tw FIXED248(TILE_WIDTH_HEIGHT, 0) + #define th FIXED248(TILE_WIDTH_HEIGHT, 0) + #define lx fx248Mulfx248(tileX, tw) + #define ty fx248Mulfx248(tileY, th) + #define rx fx248Addfx248(lx, tw) + #define by fx248Addfx248(ty, th) + + switch(TILE_META_DATA[tile].solidType) { + case TILE_SOLID_FULL: + result = physicsCheckCircleAABB( + circleX, circleY, circleR, + lx, ty, + tw, th + ); + break; + + case TILE_SOLID_TRIANGLE_TOP_RIGHT: + result = physicsCheckCircleTriangle( + circleX, circleY, circleR, + rx, by, + rx, ty, + lx, ty + ); + break; + + case TILE_SOLID_TRIANGLE_TOP_LEFT: + result = physicsCheckCircleTriangle( + circleX, circleY, circleR, + lx, by, + lx, ty, + rx, ty + ); + break; + + case TILE_SOLID_TRIANGLE_BOTTOM_RIGHT: + result = physicsCheckCircleTriangle( + circleX, circleY, circleR, + rx, ty, + rx, by, + lx, by + ); + break; + case TILE_SOLID_TRIANGLE_BOTTOM_LEFT: + result = physicsCheckCircleTriangle( + circleX, circleY, circleR, + lx, ty, + lx, by, + rx, by + ); + break; + + default: + result.hit = false; + break; + } + + return result; +} \ No newline at end of file diff --git a/src/dusk/physics/physics.h b/src/dusk/physics/physics.h index b8d2aec..a0c7625 100644 --- a/src/dusk/physics/physics.h +++ b/src/dusk/physics/physics.h @@ -7,6 +7,7 @@ #pragma once #include "util/fixed.h" +#include "world/tile.h" typedef struct { bool_t hit; @@ -106,4 +107,20 @@ collisionresult_t physicsCheckCircleTriangle( fixed248_t triX0, fixed248_t triY0, fixed248_t triX1, fixed248_t triY1, fixed248_t triX2, fixed248_t triY2 +); + +/** + * Check for collision between a circle and a tile. + * + * @param circleX X coordinate of the circle's center. + * @param circleY Y coordinate of the circle's center. + * @param circleR Radius of the circle. + * @param tileX X coordinate of the tile's top-left corner. + * @param tileY Y coordinate of the tile's top-left corner. + * @param tile The tile to check against. + * @return A collisionresult_t structure containing collision information. + */ +collisionresult_t physicsCheckCircleTile( + fixed248_t circleX, fixed248_t circleY, fixed248_t circleR, + fixed248_t tileX, fixed248_t tileY, tile_t tile ); \ No newline at end of file