2D Space Shooter Game: Secondary Fire Powerup (Wide Shot)

Manny Cabacungan
4 min readJul 31, 2023

--

Objectives:

  • Create a new form of projectile. You should already have a triple shot. Include something new from multi direction shot, to a radius clearing bomb, etc.
  • Replaces the standard fire for 5 seconds.
  • Should be a rare spawn

For the secondary fire powerup, I decided to make a wide shot powerup that spreads five lasers out of the ship spreading out radially 180 degrees ahead of the ship.

Here is the image I created for the wide shot powerup.

  • I imported the image into the Project pane’s Sprite folder as I’ve done for the previous powerups and set it as a sprite.
  • Following the same process as before for the previous powerups, from the Project pane’s Prefabs folder, drag one of the powerups to the Hierarchy pane and rename it to “Powerup_Wide_Shot”.
  • In the Hierarchy pane, make sure the “Powerup_Wide_Shot” is selected. Change the sprite to the new wideshot sprite you created.
  • Open the Powerup.cs script.
  • To the enum _powerupIDs, add “, WideShot” after the last item.
  • Go back to the Powerup_Wide_Shot game object in the Heirarcy. In the Powerup (Script), Inspector panel properties, change the Powerup ID to “WideShot”
  • Make the “Powerup_Wide_Shot” game object into a new original prefab.
  • Now that we made the prefab for the wide shot powerup, we do not need the game object in the Hierarchy panel any more. Delete the “Powerup_Wide_Shot” in the Hierarchy pane.
  • Open the SpawnManager.cs script.
  • Because we want this new powerup to spawn at a different rate from the other powerups, the coroutine SpawnPowerupRoutine() needs to be more generic and accept parameters so that the array of powerup game objects and the wait times can be different. At the top of the script, I declared the following variables which includes a new array of GameObjects for the rarely spawned powerups:
    [SerializeField] private GameObject[] _powerupPrefabRare;
[SerializeField] private float _waitTimePowerupsNormalMin = 2.0f;
[SerializeField] private float _waitTimePowerupsNormalMax = 5.0f;
[SerializeField] private float _waitTimePowerupsRareMin = 10.0f;
[SerializeField] private float _waitTimePowerupsRareMax = 20.0f;
  • I adjusted the coroutine SpawnPowerupRoutine() to be more generic:
IEnumerator SpawnPowerupRoutine(GameObject[] _spawnList, float _waitTimeMin, float _waitTimeMax)
{
int _randomPowerUpIndex = 0;

while (_stopSpawning == false)
{
_waitTimePowerups = Random.Range(_waitTimeMin, _waitTimeMax);

yield return new WaitForSeconds(_waitTimePowerups);

// Instantiate prowerup prefab
_randomX = Random.Range(-_xPositionLimit, _xPositionLimit);
Vector3 spawnPosition = new Vector3(_randomX, _yPositionLimit, 0);
_randomPowerUpIndex = Random.Range(0, _spawnList.Length);
GameObject newPowerup = Instantiate(_spawnList[_randomPowerUpIndex], spawnPosition, Quaternion.identity);
}
}
  • I adjusted the StartSpawning() method to call the coroutine SpawnPowerupRoutine() with different parameters for the arrays _powerupPrefab and _powerupPrefabRare.
public void StartSpawning()
{
StartCoroutine(SpawnEnemyRoutine());
StartCoroutine(SpawnPowerupRoutine(_powerupPrefab, _waitTimePowerupsNormalMin, _waitTimePowerupsNormalMax));
StartCoroutine(SpawnPowerupRoutine(_powerupPrefabRare, _waitTimePowerupsRareMin, _waitTimePowerupsRareMax));
}
  • Add the Powerup_Wide_Shot prefab to the array _powerupPrefabRare.
  • Open the Player.cs script.
  • Add a boolean variable for the wideshot powerup active state:
[SerializeField] private bool _wideShotActive = false;
  • In the method FireLaser(), adjust the nested “if” conditional statements for _tripleShotActive to include _wideShotActive so that if _wideShotActive is true, instantiate five lasers so that they radiate out from the player’s ship from five different angles using the Quaternion,Euler() function for the angles. I’m using these angles: 0° (identity), 45°, 90°,-45°, -90°. I separated the instantiation of the wide shot lasers into its own method FireWideShot().
void FireLaser()
{
_canFire = Time.time + _firerate;

if (_ammoCount > 0)
{
Vector3 _laserPosition = transform.position + _laserOffset;

if (_tripleShotActive == true && _wideShotActive == false)
{
Instantiate(_tripleShotlaserPrefab, transform.position, Quaternion.identity);
}
else if (_tripleShotActive == false && _wideShotActive == true)
{
FireWideShot();
}
else
{
Instantiate(_laserPrefab, _laserPosition, Quaternion.identity);
}

_ammoCount--;
_UIManager.UpdateAmmo(_ammoCount);

_sfxAudioSource.clip = _laserShotAudioClip;
_sfxAudioSource.Play();
}
}

void FireWideShot()
{
Instantiate(_laserPrefab, transform.position + new Vector3(0, 1.05f, 0), Quaternion.identity);
Instantiate(_laserPrefab, transform.position + new Vector3(0, 1.05f, 0), Quaternion.Euler(0, 0, 45f));
Instantiate(_laserPrefab, transform.position + new Vector3(0, 1.05f, 0), Quaternion.Euler(0, 0, 90f));
Instantiate(_laserPrefab, transform.position + new Vector3(0, 1.05f, 0), Quaternion.Euler(0, 0, -45f));
Instantiate(_laserPrefab, transform.position + new Vector3(0, 1.05f, 0), Quaternion.Euler(0, 0, -90f));
}
  • Open the Powerup.cs script again.
  • In the switch statement block, after _powerupIDs.Health, add a conditional for _powerupIDs.WideShot and call player.WideshotActive() that we just made and pass (5.0f) as a parameter:
switch (_powerupID)
{
case _powerupIDs.TripleShot:
player.TripleShotActive(_powerupDuration);
Debug.Log("Powerup::OnTriggerEnter2D:switch TripleShot");
break;
case _powerupIDs.SpeedBoost:
player.SpeedBoostActive(_powerupDuration);
Debug.Log("Powerup::OnTriggerEnter2D:switch SpeedBoost");
break;
case _powerupIDs.Shields:
player.ShieldsActive();
Debug.Log("Powerup::OnTriggerEnter2D:switch Shields");
break;
case _powerupIDs.Ammo:
player.AmmoRefill();
Debug.Log("Powerup::OnTriggerEnter2D:switch Ammo");
break;
case _powerupIDs.Health:
player.AddShip();
Debug.Log("Powerup::OnTriggerEnter2D:switch AddLife");
break;
case _powerupIDs.WideShot:
player.WideShotActive(5.0f);
Debug.Log("Powerup::OnTriggerEnter2D:switch WideShot");
break;
default:
Debug.Log("Powerup::OnTriggerEnter2D:switch default");
break;
}
  • Now when you test the game, the wideshot powerup will spawn sparingly and give the player a special secondary fire weapon for a short time.

--

--