#include #include #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; }