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

106 lines
3.4 KiB
C
Raw Normal View History

2024-02-28 17:50:57 +00:00
#include <math.h>
#include <stdio.h>
#include "game.h"
#include "movement.h"
#include "const.h"
#include "spawn.h"
struct SpawnPointRange spawnPointRanges[4] = {
// top
{ .left = TILE_SIZE * 4, .width = TILE_SIZE * 2, .top = TILE_SIZE - 8, .height = TILE_SIZE },
// right
{ .left = (ARENA_WIDTH_TILES - 1) * TILE_SIZE - 8, .width = TILE_SIZE, .top = TILE_SIZE * 4, .height = TILE_SIZE * 2 },
// bottom
{ .left = TILE_SIZE * 4, .width = TILE_SIZE * 2, .top = (ARENA_HEIGHT_TILES - 1) * TILE_SIZE - 8, .height = TILE_SIZE },
// left
{ .left = TILE_SIZE - 8, .width = TILE_SIZE, .top = TILE_SIZE * 4, .height = TILE_SIZE * 2 },
};
int determineEnemyHitPointCalculation(int difficulty, int roll) {
2024-03-01 12:55:01 +00:00
return hitPointRanges[difficulty][roll];
2024-02-28 17:50:57 +00:00
}
void selectEnemySpawnLocation(
struct EnemySpawningDetails *spawnDetails,
struct RabbitPosition *rabbitPosition
) {
int spawnTry, gate, i;
int gatePlayerIsFacing = rabbitPosition->mouseAngle / 90;
// determine which gate the player is at and reduce the likelihood of
// spawning from that gate
// * 8 chances to spawn [0, 1] for each gate
// * if the gate the player is looking at gets [0], reroll
// * try three times max to limit cost of calculating
for (spawnTry = 0; spawnTry < 3; ++spawnTry) {
i = rand() % 12;
gate = i / 3;
if (gatePlayerIsFacing == gate && i % 3 != 0) continue;
}
spawnDetails->gate = gate;
spawnDetails->spawnX = spawnPointRanges[gate].left + rand() % spawnPointRanges[gate].width;
spawnDetails->spawnY = spawnPointRanges[gate].top + rand() % spawnPointRanges[gate].height;
}
void spawnEnemy(
struct EnemySpawningDetails *spawnDetails,
struct GlobalGameState *globalGameState
) {
spawnDetails->enemyPosition->isActive = 1;
spawnDetails->enemyPosition->willBeInactive = 0;
spawnDetails->enemyPosition->wasKilled = 0;
spawnDetails->enemyPosition->hitPoints = determineEnemyHitPointCalculation(
globalGameState->difficulty,
rand() % 4
);
spawnDetails->enemyPosition->hasLeftGate = 0;
spawnDetails->enemyPosition->gateExitedFrom = spawnDetails->gate;
spawnDetails->enemyPosition->enemyMoveDelayStep = 0;
spawnDetails->enemyPosition->enemyFireDelayStep = ENEMY_FIRE_MIN_DELAY + rand() % ENEMY_FIRE_VARIABLE_DELAY;
spawnDetails->enemyPosition->enemyPosition[0] = spawnDetails->spawnX;
spawnDetails->enemyPosition->enemyPosition[1] = spawnDetails->spawnY;
spawnDetails->enemyPosition->oldEnemyPosition[0] = spawnDetails->spawnX;
spawnDetails->enemyPosition->oldEnemyPosition[1] = spawnDetails->spawnY;
}
void maybeSpawnEnemy(
struct GlobalGameState *globalGameState,
struct EnemyPosition enemyPosition[],
struct RabbitPosition *rabbitPosition
) {
char canSpawn;
int i, availableEnemy;
struct EnemySpawningDetails spawnDetails;
if (globalGameState->spawnCooldown-- > 0) return;
for (i = 0; i < ENEMY_MAX_COUNT; ++i) {
if (!enemyPosition[i].isActive) {
availableEnemy = i;
canSpawn = 1;
break;
}
}
if (!canSpawn) return;
spawnDetails.enemyPosition = &enemyPosition[availableEnemy];
spawnDetails.difficulty = globalGameState->difficulty;
selectEnemySpawnLocation(
&spawnDetails,
rabbitPosition
);
spawnEnemy(
&spawnDetails,
globalGameState
);
globalGameState->spawnCooldown = (
BASE_ENEMY_SPAWN_COOLDOWN - (globalGameState->difficulty * DIFFICULTY_SPAWN_COOLDOWN_REDUCTION)) +
MINIMUM_ENEMY_SPAWN_COOLDOWN + rand() % VARIABLE_ENEMY_SPAWN_COOLDOWN;
}