From 7b85f11143f50e9b26a83f4fbcc3da40a70b759c Mon Sep 17 00:00:00 2001 From: John Bintz Date: Sun, 25 Feb 2024 15:48:19 -0500 Subject: [PATCH] streamline collision detection --- combat.c | 154 +++++++++++++++++++++++++++++++++++-------------------- combat.h | 6 +++ const.h | 1 + game.c | 8 ++- 4 files changed, 113 insertions(+), 56 deletions(-) diff --git a/combat.c b/combat.c index 4ed516e..d6032bd 100644 --- a/combat.c +++ b/combat.c @@ -109,84 +109,94 @@ void populateTargetCollision(struct CompiledSpriteRender *sprite) { collisionDetection.targetEY = bounds.bottom; } -void handleRabbitToEnemyCollisions( +// We are hardcoding a 2x2 grid on the screen as our collision partitioning +// scheme. +int rabbitBulletGrid[4][RABBIT_BULLET_LIMIT]; +int enemyGrid[4][ENEMY_MAX_COUNT]; +int rabbitGrid[4]; +int rabbitBulletGridIndex[4], enemyGridIndex[4]; + +int gridPosition[4]; + +#define CALCULATE_GRID_POS(x,y) ((x / COLLISION_GRID_SIZE) + (y / COLLISION_GRID_SIZE) * 2) + +void determineGridPositionsForSprite(struct CompiledSpriteRender *sprite) { + int i; + + getSpriteBounds(sprite, &bounds); + + for (i = 0; i < 4; ++i) { + gridPosition[i] = 0; + } + + gridPosition[CALCULATE_GRID_POS(bounds.left, bounds.top)] = 1; + gridPosition[CALCULATE_GRID_POS(bounds.right, bounds.top)] = 1; + gridPosition[CALCULATE_GRID_POS(bounds.left, bounds.bottom)] = 1; + gridPosition[CALCULATE_GRID_POS(bounds.right, bounds.bottom)] = 1; +} + +void buildCollisionGrids( + struct BulletPosition rabbitBulletPosition[], struct RabbitPosition *rabbitPosition, struct EnemyPosition enemyPosition[] ) { - int enemyIdx; + int grid, i; + + for (grid = 0; grid < 4; ++grid) { + rabbitBulletGridIndex[grid] = 0; + enemyGridIndex[grid] = 0; + } - // to start: brute force items - // possible performance improvements: - // * grid partitioning rabbit.x = rabbitPosition->rabbitPosition[0]; rabbit.y = rabbitPosition->rabbitPosition[1]; - populateSourceCollision(&rabbit); + determineGridPositionsForSprite(&rabbit); - for (enemyIdx = 0; enemyIdx < ENEMY_MAX_COUNT; ++enemyIdx) { - if (!enemyPosition[enemyIdx].isActive) continue; - if (enemyPosition[enemyIdx].willBeInactive) continue; + for (grid = 0; grid < 4; ++grid) { + rabbitGrid[grid] = gridPosition[grid]; + } - enemy.x = enemyPosition[enemyIdx].enemyPosition[0]; - enemy.y = enemyPosition[enemyIdx].enemyPosition[1]; - populateTargetCollision(&enemy); + for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) { + if (!rabbitBulletPosition[i].isActive) continue; + if (rabbitBulletPosition[i].willBeInactive) continue; - if (isCollision()) { - enemyPosition[enemyIdx].willBeInactive = 1; + bullet.x = rabbitBulletPosition[i].x; + bullet.y = rabbitBulletPosition[i].y; + determineGridPositionsForSprite(&bullet); + + for (grid = 0; grid < 4; ++grid) { + if (gridPosition[grid]) { + rabbitBulletGrid[grid][rabbitBulletGridIndex[grid]++] = i; + } + } + } + + for (i = 0; i < ENEMY_MAX_COUNT; ++i) { + if (!enemyPosition[i].isActive) continue; + if (enemyPosition[i].willBeInactive) continue; + + enemy.x = enemyPosition[i].enemyPosition[0]; + enemy.y = enemyPosition[i].enemyPosition[1]; + determineGridPositionsForSprite(&enemy); + + for (grid = 0; grid < 4; ++grid) { + if (gridPosition[grid]) { + enemyGrid[grid][enemyGridIndex[grid]++] = i; + } } } } -int rabbitBulletGrid[4][RABBIT_BULLET_LIMIT]; -int enemyGrid[4][ENEMY_MAX_COUNT]; - void handleRabbitBulletToEnemyCollisions( struct BulletPosition rabbitBulletPosition[], struct EnemyPosition enemyPosition[] ) { int bulletIdx, enemyIdx, grid; int resolvedBulletIdx, resolvedEnemyIdx; - int rabbitGridIndex[4], enemyGridIndex[4]; - - char buffer[30]; - - for (grid = 0; grid < 4; ++grid) { - rabbitGridIndex[grid] = 0; - } - - for (bulletIdx = 0; bulletIdx < RABBIT_BULLET_LIMIT; ++bulletIdx) { - if (!rabbitBulletPosition[bulletIdx].isActive) continue; - if (rabbitBulletPosition[bulletIdx].willBeInactive) continue; - - grid = ( - rabbitBulletPosition[bulletIdx].x / (TILE_SIZE * 5) - ) + ( - (rabbitBulletPosition[bulletIdx].y / (TILE_SIZE * 5)) * 2 - ); - - rabbitBulletGrid[grid][rabbitGridIndex[grid]++] = bulletIdx; - } - - for (grid = 0; grid < 4; ++grid) { - enemyGridIndex[grid] = 0; - } - - for (enemyIdx = 0; enemyIdx < ENEMY_MAX_COUNT; ++enemyIdx) { - if (!enemyPosition[enemyIdx].isActive) continue; - if (enemyPosition[enemyIdx].willBeInactive) continue; - - grid = ( - enemyPosition[enemyIdx].enemyPosition[0] / (TILE_SIZE * 5) - ) + ( - (enemyPosition[enemyIdx].enemyPosition[1] / (TILE_SIZE * 5)) * 2 - ); - - enemyGrid[grid][enemyGridIndex[grid]++] = enemyIdx; - } for (grid = 0; grid < 4; ++grid) { if (enemyGridIndex[grid] == 0) continue; - for (bulletIdx = 0; bulletIdx < rabbitGridIndex[grid]; ++bulletIdx) { + for (bulletIdx = 0; bulletIdx < rabbitBulletGridIndex[grid]; ++bulletIdx) { resolvedBulletIdx = rabbitBulletGrid[grid][bulletIdx]; if (!rabbitBulletPosition[resolvedBulletIdx].isActive) continue; @@ -216,3 +226,37 @@ void handleRabbitBulletToEnemyCollisions( } } +void handleRabbitToEnemyCollisions( + struct RabbitPosition *rabbitPosition, + struct EnemyPosition enemyPosition[] +) { + int enemyIdx, grid, resolvedEnemyIdx; + + // to start: brute force items + // possible performance improvements: + // * grid partitioning + rabbit.x = rabbitPosition->rabbitPosition[0]; + rabbit.y = rabbitPosition->rabbitPosition[1]; + populateSourceCollision(&rabbit); + + for (grid = 0; grid < 4; ++grid) { + if (!rabbitGrid[grid]) continue; + if (enemyGridIndex[grid] == 0) continue; + + for (enemyIdx = 0; enemyIdx < enemyGridIndex[grid]; ++enemyIdx) { + resolvedEnemyIdx = enemyGrid[grid][enemyIdx]; + + if (!enemyPosition[resolvedEnemyIdx].isActive) continue; + if (enemyPosition[resolvedEnemyIdx].willBeInactive) continue; + + enemy.x = enemyPosition[resolvedEnemyIdx].enemyPosition[0]; + enemy.y = enemyPosition[resolvedEnemyIdx].enemyPosition[1]; + populateTargetCollision(&enemy); + + if (isCollision()) { + enemyPosition[resolvedEnemyIdx].willBeInactive = 1; + } + } + } +} + diff --git a/combat.h b/combat.h index c1131a0..978fb60 100644 --- a/combat.h +++ b/combat.h @@ -18,3 +18,9 @@ void handleRabbitToEnemyCollisions( struct RabbitPosition*, struct EnemyPosition[] ); + +void buildCollisionGrids( + struct BulletPosition rabbitBulletPosition[], + struct RabbitPosition *rabbitPosition, + struct EnemyPosition enemyPosition[] +); diff --git a/const.h b/const.h index e477c3a..2edc2e4 100644 --- a/const.h +++ b/const.h @@ -1,6 +1,7 @@ #define TILE_SIZE (20) #define ARENA_WIDTH_TILES (10) #define ARENA_HEIGHT_TILES (10) +#define COLLISION_GRID_SIZE (ARENA_WIDTH_TILES / 2 * TILE_SIZE) #define MOUSE_DISTANCE (32) diff --git a/game.c b/game.c index 144466f..1a52b79 100644 --- a/game.c +++ b/game.c @@ -286,6 +286,12 @@ void handleCombat() { &rabbitWeaponry ); + buildCollisionGrids( + rabbitBulletPosition, + &rabbitPosition, + enemyPosition + ); + handleRabbitToEnemyCollisions( &rabbitPosition, enemyPosition @@ -337,10 +343,10 @@ int main(void) { handleMovement(); handleRedraw(); + handleCombat(); waitStartVbl(); copyDrawBufferToDisplay(); - handleCombat(); waitEndVbl(); if (keyboardKeydownState.KEY_ESC) { keepRunning = 0; }