streamline collision detection

This commit is contained in:
John Bintz 2024-02-25 15:48:19 -05:00
parent 83c35f68c4
commit 7b85f11143
4 changed files with 113 additions and 56 deletions

154
combat.c
View File

@ -109,84 +109,94 @@ void populateTargetCollision(struct CompiledSpriteRender *sprite) {
collisionDetection.targetEY = bounds.bottom; 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 RabbitPosition *rabbitPosition,
struct EnemyPosition enemyPosition[] 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.x = rabbitPosition->rabbitPosition[0];
rabbit.y = rabbitPosition->rabbitPosition[1]; rabbit.y = rabbitPosition->rabbitPosition[1];
populateSourceCollision(&rabbit); determineGridPositionsForSprite(&rabbit);
for (enemyIdx = 0; enemyIdx < ENEMY_MAX_COUNT; ++enemyIdx) { for (grid = 0; grid < 4; ++grid) {
if (!enemyPosition[enemyIdx].isActive) continue; rabbitGrid[grid] = gridPosition[grid];
if (enemyPosition[enemyIdx].willBeInactive) continue; }
enemy.x = enemyPosition[enemyIdx].enemyPosition[0]; for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) {
enemy.y = enemyPosition[enemyIdx].enemyPosition[1]; if (!rabbitBulletPosition[i].isActive) continue;
populateTargetCollision(&enemy); if (rabbitBulletPosition[i].willBeInactive) continue;
if (isCollision()) { bullet.x = rabbitBulletPosition[i].x;
enemyPosition[enemyIdx].willBeInactive = 1; 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( void handleRabbitBulletToEnemyCollisions(
struct BulletPosition rabbitBulletPosition[], struct BulletPosition rabbitBulletPosition[],
struct EnemyPosition enemyPosition[] struct EnemyPosition enemyPosition[]
) { ) {
int bulletIdx, enemyIdx, grid; int bulletIdx, enemyIdx, grid;
int resolvedBulletIdx, resolvedEnemyIdx; 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) { for (grid = 0; grid < 4; ++grid) {
if (enemyGridIndex[grid] == 0) continue; if (enemyGridIndex[grid] == 0) continue;
for (bulletIdx = 0; bulletIdx < rabbitGridIndex[grid]; ++bulletIdx) { for (bulletIdx = 0; bulletIdx < rabbitBulletGridIndex[grid]; ++bulletIdx) {
resolvedBulletIdx = rabbitBulletGrid[grid][bulletIdx]; resolvedBulletIdx = rabbitBulletGrid[grid][bulletIdx];
if (!rabbitBulletPosition[resolvedBulletIdx].isActive) continue; 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;
}
}
}
}

View File

@ -18,3 +18,9 @@ void handleRabbitToEnemyCollisions(
struct RabbitPosition*, struct RabbitPosition*,
struct EnemyPosition[] struct EnemyPosition[]
); );
void buildCollisionGrids(
struct BulletPosition rabbitBulletPosition[],
struct RabbitPosition *rabbitPosition,
struct EnemyPosition enemyPosition[]
);

View File

@ -1,6 +1,7 @@
#define TILE_SIZE (20) #define TILE_SIZE (20)
#define ARENA_WIDTH_TILES (10) #define ARENA_WIDTH_TILES (10)
#define ARENA_HEIGHT_TILES (10) #define ARENA_HEIGHT_TILES (10)
#define COLLISION_GRID_SIZE (ARENA_WIDTH_TILES / 2 * TILE_SIZE)
#define MOUSE_DISTANCE (32) #define MOUSE_DISTANCE (32)

8
game.c
View File

@ -286,6 +286,12 @@ void handleCombat() {
&rabbitWeaponry &rabbitWeaponry
); );
buildCollisionGrids(
rabbitBulletPosition,
&rabbitPosition,
enemyPosition
);
handleRabbitToEnemyCollisions( handleRabbitToEnemyCollisions(
&rabbitPosition, &rabbitPosition,
enemyPosition enemyPosition
@ -337,10 +343,10 @@ int main(void) {
handleMovement(); handleMovement();
handleRedraw(); handleRedraw();
handleCombat();
waitStartVbl(); waitStartVbl();
copyDrawBufferToDisplay(); copyDrawBufferToDisplay();
handleCombat();
waitEndVbl(); waitEndVbl();
if (keyboardKeydownState.KEY_ESC) { keepRunning = 0; } if (keyboardKeydownState.KEY_ESC) { keepRunning = 0; }