bool EnemyZone::_SpawnEnemy(uint32 enemy_index) { // When spawning an enemy in a random zone location, sometimes it is occupied by another // object or that section is unwalkable. We try only a few different spawn locations before // giving up. Otherwise this function could potentially take a noticable amount of time to complete const int8 SPAWN_RETRIES = 40; if (enemy_index >= _enemies.size()) { IF_PRINT_WARNING(MAP_DEBUG) << "function called with an out-of-range index argument: " << enemy_index << endl; return false; } uint16 x, y; // Used to retain random position coordinates in the zone int8 retries = SPAWN_RETRIES; // Number of times to try finding a valid spawning location bool collision; // Holds the result of a collision detection check // Select a random position inside the zone to place the spawning enemy. To do this, we need to diable the no_collision // property of the enemy sprite. bool saved_no_collision = _enemies[enemy_index]->no_collision; _enemies[enemy_index]->no_collision = false; // This must be temporarily MapZone* spawning_zone = NULL; if (HasSeparateSpawnZone() == false) { spawning_zone = this; } else { spawning_zone = _spawn_zone; } // Try to find a suitable spawn location do { spawning_zone->_RandomPosition(x, y); _enemies[enemy_index]->SetXPosition(x, 0.0f); _enemies[enemy_index]->SetYPosition(y, 0.0f); collision = MapMode::CurrentInstance()->GetObjectSupervisor()->DetectCollision(_enemies[enemy_index], NULL); } while (collision && --retries > 0); // If we didn't find a suitable spawning location, reset the collision info // on the enemy sprite and we will retry on the next call to this function if (collision) { _enemies[enemy_index]->no_collision = saved_no_collision; return false; } // Otherwise, spawn the enemy and reset the spawn timer else { _spawn_timer.Reset(); _spawn_timer.Run(); _enemies[enemy_index]->ChangeStateSpawn(); _active_enemies++; return true; } }
void EnemyZone::Update() { // When spawning an enemy in a random zone location, sometimes it is occupied by another // object or that section is unwalkable. We try only a few different spawn locations before // giving up and waiting for the next call to Update(). Otherwise this function could // potentially take a noticable amount of time to complete const int8 SPAWN_RETRIES = 5; if (_enemies.empty() == true) return; // Spawn new enemies only if there is at least one enemy that is not active if (_active_enemies >= _enemies.size()) return; // Update the regeneration timer and return if the spawn time has not yet been reached _spawn_timer.Update(); if (_spawn_timer.IsFinished() == false) { return; } // Otherwise, select a DEAD enemy to spawn uint32 index = 0; for (uint32 i = 0; i < _enemies.size(); i++) { if (_enemies[i]->IsDead() == true) { index = i; break; } } float x, y; // Used to retain random position coordinates in the zone int8 retries = SPAWN_RETRIES; // Number of times to try finding a valid spawning location bool collision; // Holds the result of a collision detection check // Select a random position inside the zone to place the spawning enemy _enemies[index]->no_collision = false; MapZone* spawning_zone = NULL; if (HasSeparateSpawnZone() == false) { spawning_zone = this; } else { spawning_zone = _spawn_zone; } // If there is a collision, retry a different location do { spawning_zone->_RandomPosition(x, y); _enemies[index]->SetPosition(x, y); collision = MapMode::CurrentInstance()->GetObjectSupervisor()->DetectCollision(_enemies[index], _enemies[index]->GetXPosition(), _enemies[index]->GetYPosition(), NULL); } while (collision && --retries > 0); // If we didn't find a suitable spawning location, reset the collision info // on the enemy sprite and we will retry on the next call to this function if (collision) { _enemies[index]->no_collision = true; } // Otherwise, spawn the enemy and reset the spawn timer else { _spawn_timer.Reset(); _spawn_timer.Run(); _enemies[index]->ChangeStateSpawning(); _active_enemies++; } } // void EnemyZone::Update()