dos-vga-arena-shooter-game/combat.c

219 lines
7.2 KiB
C

#include <math.h>
#include <stdio.h>
#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;
}
}
}
}
}