119 lines
3.6 KiB
C
119 lines
3.6 KiB
C
#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 HIT_POINT_RANGES[10][4] = {
|
|
{ 1, 1, 1, 1 },
|
|
{ 1, 1, 1, 1 },
|
|
{ 1, 1, 1, 2 },
|
|
{ 1, 1, 1, 2 },
|
|
{ 1, 1, 2, 2 },
|
|
{ 1, 2, 2, 2 },
|
|
{ 1, 2, 2, 2 },
|
|
{ 1, 2, 2, 3 },
|
|
{ 1, 2, 2, 3 },
|
|
{ 1, 2, 3, 3 }
|
|
};
|
|
|
|
int determineEnemyHitPointCalculation(int difficulty, int roll) {
|
|
return HIT_POINT_RANGES[difficulty][roll];
|
|
}
|
|
|
|
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;
|
|
}
|