//============================================================ // Event Handlers: //============================================================ private void Asteroid_AsteroidDestroyed(Asteroid asteroid, Vector2 asteroidDeathPosition) { // stop tracking the asteroid as it no-longer exists trackedAsteroids.Remove(asteroid); // if the last asteroid was destroyed, send an alert so the next wave can begin if (trackedAsteroids.Count == 0 && asteroid.AsteroidSize == AsteroidSizes.Small) { if (AllAsteroidsDestroyed != null) { AllAsteroidsDestroyed.Invoke(); } return; } // if the asteroid was small, we don't need to do anything atm if (asteroid.AsteroidSize == AsteroidSizes.Small) { return; } // get the new asteroid size based on the size of the one which died AsteroidSizes newAsteroidSize = asteroid.AsteroidSize + 1; // spawn the number of asteroids that the asteroid splits into on death for (int i = 0; i < asteroidSplitAmount; i++) { // here, we are slightly adjusting the angle of velocity so the asteroids direction changes // this is randomised so the new asteroids head in their own directions Quaternion velocityAdjustment = Quaternion.AngleAxis(Random.Range(-MAXIMUM_VELOCITY_ADJUSTMENT, MAXIMUM_VELOCITY_ADJUSTMENT), asteroid.transform.forward); Vector3 adjustedVelocity = velocityAdjustment * asteroid.AsteroidVelocity; SpawnNewAsteroid(newAsteroidSize, asteroidDeathPosition, adjustedVelocity * ASTEROID_VELOCITY_MODIFIER); } }
//============================================================ // Private Methods: //============================================================ private void SpawnNewAsteroid(AsteroidSizes newAsteroidSize, Vector2 newAsteroidSpawnPosition, Vector2 newAsteroidVelocity) { // find a random asteroid based on the size of asteroid we are to spawn Asteroid newAsteroid = null; switch (newAsteroidSize) { case AsteroidSizes.Large: newAsteroid = largeAsteroids[Random.Range(0, largeAsteroids.Count)]; break; case AsteroidSizes.Medium: newAsteroid = mediumAsteroids[Random.Range(0, mediumAsteroids.Count)]; break; case AsteroidSizes.Small: newAsteroid = smallAsteroids[Random.Range(0, smallAsteroids.Count)]; break; } // if we reach this point and the asteroid is still null, something has gone wrong and it must be corrected if (newAsteroid == null) { throw new Exception("The asteroid was not initialised correctly."); } // generate some random values for spawn offset and starting rotation for a bit of variety with the asteroids Vector2 asteroidSpawnOffset = Random.insideUnitCircle * ASTEROID_SPAWN_MODIFIER; Quaternion asteroidStartingRotation = Quaternion.Euler(new Vector3(0, 0, Random.Range(0, 360))); // instantiate the new asteroid, initialise it, then begin to track it newAsteroid = Instantiate(newAsteroid, newAsteroidSpawnPosition + asteroidSpawnOffset, asteroidStartingRotation, spawnedAsteroidsContainer); newAsteroid.Init(newAsteroidSize, newAsteroidVelocity); trackedAsteroids.Add(newAsteroid); }
//Returns a random asteroid prefab of the specified size private GameObject GetAsteroidPrefab(AsteroidSizes Size) { //Select one of the prefabs of the specified size at random int MaxSelection = Size == AsteroidSizes.Small ? 5 : 2; int Selection = Random.Range(0, MaxSelection); //Return it from the prefab list return(Size == AsteroidSizes.Small ? SmallPrefabs[Selection] : Size == AsteroidSizes.Medium ? MediumPrefabs[Selection] : LargePrefabs[Selection]); }
//Spawns an asteroid at a specified location public void SpawnAsteroid(AsteroidSizes Size, Vector3 Location) { //Ignore this function call if there is already the maximum number of asteroids active if (ActiveAsteroids.Count > MaxAsteroidCount) { return; } //Select one of the prefabs of the given size at random, and spawn it in at the given location GameObject RandomPrefab = GetAsteroidPrefab(Size); Quaternion RandomRotation = Quaternion.Euler(0f, 0f, Random.Range(-360f, 360f)); GameObject AsteroidSpawn = Instantiate(RandomPrefab, Location, RandomRotation); //Add it to the tracking list with all the others ActiveAsteroids.Add(AsteroidSpawn); }
public void playAsteroidCollision(AsteroidSizes size) { switch (size) { case AsteroidSizes.Small: playSmallAsteroid(); break; case AsteroidSizes.Medium: playMediumAsteroid(); break; case AsteroidSizes.Large: playLargeAsteroid(); break; } }
//Spawns 2 smaller sizes asteroids near the previous ones location private void SpawnFragments(AsteroidSizes Size, Vector3 SpawnPos) { //Ignore this function call if the maximum amount of asteroids already exist if (ActiveAsteroids.Count >= MaxAsteroidCount) { return; } //Get a random direction to offset the spawns from the destroyed asteroids previous location Vector3 SpawnDirection = new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1f), 0f).normalized; //Get two locations where each fragment will be spawned in at Vector3 FirstSpawnPos = SpawnPos + SpawnDirection * (Size == AsteroidSizes.Medium ? HalfMediumSpaceNeeded : HalfSmallSpaceNeeded); Vector3 SecondSpawnPos = SpawnPos - SpawnDirection * (Size == AsteroidSizes.Medium ? HalfMediumSpaceNeeded : HalfSmallSpaceNeeded); //When the fragments are spawned in, they should be pushed away from the point of the explosion Vector3 FirstSpawnExplosionDirection = Vector3.Normalize(FirstSpawnPos - SpawnPos); float FirstSpawnExplosionForce = Random.Range(FragmentExplosionForce.x, FragmentExplosionForce.y); Vector3 SecondSpawnExplosionDirection = Vector3.Normalize(SecondSpawnPos - SpawnPos); float SecondSpawnExplosionForce = Random.Range(FragmentExplosionForce.x, FragmentExplosionForce.y); //Get two random rotations to apply to the asteroids when spawning them in Quaternion FirstSpawnRotation = Quaternion.Euler(0f, 0f, Random.Range(-360f, 360f)); Quaternion SecondSpawnRotation = Quaternion.Euler(0f, 0f, Random.Range(-360f, 360f)); //Grab random prefabs to spawn in for each fragment GameObject FirstPrefab = GetAsteroidPrefab(Size); GameObject SecondPrefab = GetAsteroidPrefab(Size); //Spawn in the first prefab and add it to the tracking list with all the others GameObject FirstSpawn = Instantiate(FirstPrefab, FirstSpawnPos, FirstSpawnRotation); FirstSpawn.GetComponent <AsteroidDrift>().ApplyExplosionForce(FirstSpawnExplosionDirection * FirstSpawnExplosionForce); ActiveAsteroids.Add(FirstSpawn); //Spawn and track the 2nd prefab if adding the first one didnt cause us to reach the max asteroid count if (ActiveAsteroids.Count < MaxAsteroidCount) { GameObject SecondSpawn = Instantiate(SecondPrefab, SecondSpawnPos, SecondSpawnRotation); SecondSpawn.GetComponent <AsteroidDrift>().ApplyExplosionForce(SecondSpawnExplosionDirection * SecondSpawnExplosionForce); ActiveAsteroids.Add(SecondSpawn); } }
//Destroys an asteroid and removes it from the active list, continues to the next level if there are no asteroids left public void DestroyAsteroid(GameObject Asteroid) { //Remove the asteroid from the active tracking list if (ActiveAsteroids.Contains(Asteroid)) { ActiveAsteroids.Remove(Asteroid); } //Store the asteroids size and position, then destroy it AsteroidSizes AsteroidSize = Asteroid.GetComponent <AsteroidSize>().MySize; Vector3 AsteroidPos = Asteroid.transform.position; Destroy(Asteroid); //If the asteroid was large or medium, spawn a couple smaller asteroids nearby the destroyed asteroids location if (AsteroidSize == AsteroidSizes.Large) { SpawnFragments(AsteroidSizes.Medium, AsteroidPos); } else if (AsteroidSize == AsteroidSizes.Medium) { SpawnFragments(AsteroidSizes.Small, AsteroidPos); } //Play sound effect and award points for destroying the asteroid SoundEffectsPlayer.Instance.PlaySound("AsteroidDestroy"); GameState.Instance.IncreaseScore((int)(AsteroidSize == AsteroidSizes.Large ? ScoreValues.LargeAsteroid : AsteroidSize == AsteroidSizes.Medium ? ScoreValues.MediumAsteroid : ScoreValues.SmallAsteroid)); //Continue onto the next level if they are no more asteroids left if (ActiveAsteroids.Count <= 0) { GameState.Instance.NextLevel(); } }