Final Boss (2D Space Shooter)

Alberto Garcia
3 min readApr 10, 2023

--

The final boss is an enhanced soldier consisting of three systems and a couple of child game objects to increase it’s complexity as enemy. It has a strong defense mechanism that requires player’s accuracy for the boss to enter into a vulnerable state.

  • Movement System
  • Set of attacks
  • Damage Loop
Scene view of Final boss and player.

The movement translation of this enemy is unique as it stays on screen in a similar way to the player, dominating the screen by moving left and right, as up and down. To understand how the three systems of the boss are altered through out this fight, the boss has an attack position depending on its current health. When starting, the boss rampages through the middle of the screen and teleports to its first attack position. Every time the boss is damaged, it rampages through the middle of the screen. It’s first attack is simple as it only shoots while only moving left and right. During it’s second attack and third attack, the boss starts to glide up and down to reach for the player with it’s long-sweeping lasers.

void Glide()
{
if (_glidingLeft)
{
transform.Translate(Vector3.left * (Mathf.SmoothStep(_glidingSpeed, _glidingSpeed * 2, _t) * Time.deltaTime), Space.World);

if (transform.position.x <= -7.5f)
{
_glidingLeft = false;
}
}
else
{
transform.Translate(Vector3.right * (Mathf.SmoothStep(_glidingSpeed, _glidingSpeed * 2, _t) * Time.deltaTime), Space.World);

if (transform.position.x >= 7.5f)
{
_glidingLeft = true;
}
}
if (_attackID == 2 || _attackID == 3)
{

if (_glidingUp)
{
transform.Translate(Vector3.up * (Mathf.SmoothStep(_glidingSpeed, _glidingSpeed * 2, _t) * Time.deltaTime), Space.World);
if (transform.position.y >= 6.5f)
{
_glidingUp = false;
}
}
else
{
transform.Translate(Vector3.down * (Mathf.SmoothStep(_glidingSpeed, _glidingSpeed * 2, _t) * Time.deltaTime), Space.World);
if (transform.position.y <= 2.5f)
{
_glidingUp = true;
}
}

}
}

A set of boolean variables determine the direction of the boss; it always starts going left, and when it can go up and down, it always starts going up. This let’s the player react much safely to the boss new movement.

This is the first attack, this same functionality is replicated through each state but at different fire rates and during the third attack, the bullet slows as well as damaging the player. The boss may only shoot if the central Shield Ball is active, giving the player an opportunity to prioritize and damage the boss through each attack state differently.

This is a quick preview of the boss fight done very quickly.

Through this set of bools and checks, the boss damage system is set to only be available after the player has shot the three “death circles” (metallic circles around the ship

public void TakeDamage()
{
if (_ballsDown == false)
{
Debug.Log("JAJA");
return;
}
else if (_ballsDown)
{
_ballsDown = false;
ResetBallsBools();
Debug.Log("ouch");
_health--;
_canMove = false;
StartCoroutine(Rampage());

}
}
#region Death Circles

void CheckBalls()
{
if (_ballsDown)
{
return;
}
if (_ballsDown == false)
{
if (!_allBalls[0].activeInHierarchy && !_allBalls[1].activeInHierarchy && !_allBalls[2].activeInHierarchy)
{
Debug.Log("balls & shield down");
_ballsDown = true;
_bossShield.gameObject.SetActive(false);
}
}
}

The take damage function may only occur while the shield is down and once per shield take down. This makes the boss fight to require at least sixteen bullets to crack the shield and actually damage the boss.

The boss’s difficulty will change as the art and sound changes occur, to match the movement and theme related to the different artwork. This damage and attacks systems will remain, but the speed, fire rate, laser length and rotational speed will vary in the future.

--

--

Alberto Garcia
Alberto Garcia

No responses yet