#include #include #include "game.h" #include "movement.h" #include "const.h" #include "system/vga.h" void attemptToFireRabbitBullet( struct RabbitPosition *rabbitPosition, struct RabbitWeaponry *rabbitWeaponry, struct BulletPosition rabbitBulletPosition[] ) { int okToFire = 0, availableBullet, i; signed int doubleVelocityX, doubleVelocityY; char buffer[20]; if (rabbitWeaponry->cooldown > 0) return; for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) { if (rabbitBulletPosition[i].isActive == 0) { okToFire = 1; availableBullet = i; break; } } if (!okToFire) return; rabbitWeaponry->cooldown = RABBIT_BULLET_COOLDOWN; doubleVelocityX = sin(rabbitPosition->mouseAngle * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2); doubleVelocityY = -cos(rabbitPosition->mouseAngle * DEG2RAD) * (RABBIT_BULLET_VELOCITY * 2); rabbitBulletPosition[availableBullet].isActive = 1; rabbitBulletPosition[availableBullet].willBeInactive = 0; rabbitBulletPosition[availableBullet].x = rabbitPosition->rabbitPosition[0]; rabbitBulletPosition[availableBullet].y = rabbitPosition->rabbitPosition[1]; rabbitBulletPosition[availableBullet].oldX = rabbitBulletPosition[availableBullet].x; rabbitBulletPosition[availableBullet].oldY = rabbitBulletPosition[availableBullet].y; rabbitBulletPosition[availableBullet].velocityXSteps[0] = doubleVelocityX / RABBIT_BULLET_VELOCITY; rabbitBulletPosition[availableBullet].velocityXSteps[1] = doubleVelocityX - rabbitBulletPosition[availableBullet].velocityXSteps[0]; rabbitBulletPosition[availableBullet].velocityYSteps[0] = doubleVelocityY / RABBIT_BULLET_VELOCITY; rabbitBulletPosition[availableBullet].velocityYSteps[1] = doubleVelocityY - rabbitBulletPosition[availableBullet].velocityYSteps[0]; rabbitBulletPosition[availableBullet].velocityStep = 0; } void advanceRabbitBullets( struct BulletPosition rabbitBulletPosition[], struct RabbitWeaponry *rabbitWeaponry ) { int i; for (i = 0; i < RABBIT_BULLET_LIMIT; ++i) { if (!rabbitBulletPosition[i].isActive) continue; rabbitBulletPosition[i].oldX = rabbitBulletPosition[i].x; rabbitBulletPosition[i].oldY = rabbitBulletPosition[i].y; rabbitBulletPosition[i].x += rabbitBulletPosition[i].velocityXSteps[rabbitBulletPosition[i].velocityStep]; rabbitBulletPosition[i].y += rabbitBulletPosition[i].velocityYSteps[rabbitBulletPosition[i].velocityStep]; if (rabbitBulletPosition[i].x < MOUSE_LIMIT_LEFT) rabbitBulletPosition[i].willBeInactive = 1; if (rabbitBulletPosition[i].x >= MOUSE_LIMIT_RIGHT) rabbitBulletPosition[i].willBeInactive = 1; if (rabbitBulletPosition[i].y < MOUSE_LIMIT_TOP) rabbitBulletPosition[i].willBeInactive = 1; if (rabbitBulletPosition[i].y >= MOUSE_LIMIT_BOTTOM) rabbitBulletPosition[i].willBeInactive = 1; rabbitBulletPosition[i].velocityStep = 1 - rabbitBulletPosition[i].velocityStep; } if (rabbitWeaponry->cooldown > 0) rabbitWeaponry->cooldown--; } struct CollisionDetection { short int sourceSX, sourceSY, sourceEX, sourceEY; short int targetSX, targetSY, targetEX, targetEY; }; struct CollisionDetection collisionDetection; int isCollision() { if (collisionDetection.sourceEY < collisionDetection.targetSY) return 0; if (collisionDetection.sourceEX < collisionDetection.targetSX) return 0; if (collisionDetection.targetEY < collisionDetection.sourceSY) return 0; if (collisionDetection.targetEX < collisionDetection.sourceSX) return 0; return 1; } void populateSourceCollision(struct CompiledSpriteRender *sprite) { getSpriteBounds(sprite, &bounds); collisionDetection.sourceSX = bounds.left; collisionDetection.sourceSY = bounds.top; collisionDetection.sourceEX = bounds.right; collisionDetection.sourceEY = bounds.bottom; } void populateTargetCollision(struct CompiledSpriteRender *sprite) { getSpriteBounds(sprite, &bounds); collisionDetection.targetSX = bounds.left; collisionDetection.targetSY = bounds.top; collisionDetection.targetEX = bounds.right; collisionDetection.targetEY = bounds.bottom; } void handleRabbitToEnemyCollisions( struct RabbitPosition *rabbitPosition, struct EnemyPosition enemyPosition[] ) { int enemyIdx; // to start: brute force items // possible performance improvements: // * grid partitioning rabbit.x = rabbitPosition->rabbitPosition[0]; rabbit.y = rabbitPosition->rabbitPosition[1]; populateSourceCollision(&rabbit); for (enemyIdx = 0; enemyIdx < ENEMY_MAX_COUNT; ++enemyIdx) { if (!enemyPosition[enemyIdx].isActive) continue; if (enemyPosition[enemyIdx].willBeInactive) continue; enemy.x = enemyPosition[enemyIdx].enemyPosition[0]; enemy.y = enemyPosition[enemyIdx].enemyPosition[1]; populateTargetCollision(&enemy); if (isCollision()) { enemyPosition[enemyIdx].willBeInactive = 1; } } } 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) { resolvedBulletIdx = rabbitBulletGrid[grid][bulletIdx]; if (!rabbitBulletPosition[resolvedBulletIdx].isActive) continue; if (rabbitBulletPosition[resolvedBulletIdx].willBeInactive) continue; bullet.x = rabbitBulletPosition[resolvedBulletIdx].x; bullet.y = rabbitBulletPosition[resolvedBulletIdx].y; populateSourceCollision(&bullet); 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; rabbitBulletPosition[resolvedBulletIdx].willBeInactive = 1; break; } } } } }