Common Enemies and their special abilities (2D Space Shooter)

Alberto Garcia
3 min readApr 7, 2023

--

Common Enemies spawn more frequently and share the basic attack of two laser shots at a time. Enemy A moves straight, can avoid one shot. Enemy B moves swinging left and right and has two special attacks. Enemy B may spawn carrying a homing projectile or a shield. If Enemy B survives his first round, it gains a new shield when reentering the map.

  • Enemy Avoid Shot
  • Smart Enemy (Shoots behind the player)
  • Enemy Shields

First, let’s analyze how Enemy A can Avoid one Shot.

Enemy avoiding lasers by moving randomly left or right.
// This method is inside the enemy script 
public void AvoidShot()
{
int move = Random.Range(0, 2);
float t = 1;
Vector2 _currentPosition = transform.position;
Vector2 _movedPositionLeft = new Vector2(transform.position.x - 2, transform.position.y);
Vector2 _movedPositionRight = new Vector2(transform.position.x + 2, transform.position.y);

if (move == 0)
{
transform.position = Vector2.Lerp(_currentPosition, _movedPositionLeft, t);
}
else
{
transform.position = Vector2.Lerp(_currentPosition, _movedPositionRight, t);
}
}

Then an invisible box collider is carried in front of every enemy to detect a laser.

//inside the Shot Sensor script
[SerializeField]
private bool shotAvoided = false;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Laser" && !shotAvoided)
{
transform.GetComponentInParent<Enemy>().AvoidShot();
shotAvoided= true;
}
}

This way the sensor only works for one shot. If these enemies get close to each other, they become very tricky to shoot at.

Enemy B Smart shot is a homing projectile that burns power-ups and follow the player.

That laser triangle with the metal ball is the homing missile. When the enemy B enters the arena again, it gains a new shield! The homing projectiles can be shot at to avoid damage, but it requires skill and speed.

Enemy B starts with Special ability 1 and then gains a shield with specialID 0
//Enemy B Script
//inside the Start Mehtod, these are declared along the switch
//that determines if the Enemy B has the homing beam or shield
void Start()
{

_shootingOn = true;
_specialAbilityID = Random.Range(0, 2);
_shieldIsOn = false;

switch (_specialAbilityID)
{
case 0:
_offset = Random.Range(-2, 2);
ShieldOn();
break;
case 1:
_offset = Random.Range(-6, 6);
_homingBeam.gameObject.SetActive(true);
break;
}
}

// this code is called inside the movement when enemy leaves screen
if (transform.position.y < -6.5)
{
EnemyBSpecials();
float randomX = Random.Range(-9f, 9f);
transform.position = new Vector3(randomX, 8, 0);
}
private void ShootHomingLaser()
{
//This method is called right after
//the homing projectile is unparented
//and gets ID 0 to obtain shields
_homingBeamScript.ActivateSeeking();
_specialAbilityID = 0;
}

//Shielding
void EnemyBSpecials()
{
switch (_specialAbilityID)
{
case 0:
ShieldOn();
break;
case 1:
if (_homingBeam != null)
{
_homingBeam.transform.SetParent(null);
Debug.Log("Homing unparented");
}
ShootHomingLaser();
break;
}
}

private void ShieldOn()
{
_enemShieldRenderer.color = Color.red;
_enemyShield.gameObject.SetActive(true);
_shieldIsOn = true;
}
//With this Set up, inside the OnTriggerEnter2D()
else if (_shieldIsOn && other.tag == "Laser")
{
{
other.gameObject.SetActive(false);
_enemyShield.gameObject.SetActive(false);
_shieldIsOn = false;
}
}
else if (other.tag == "Laser" && !_shieldIsOn)
{
other.gameObject.SetActive(false);
if (_spawnManagerScript != null)
{
OnEnemyDeath();
}
}

If Enemy B starts with an ID 0, it never carries the homing beam. Making it less frequent for homing beams to appear. I’ll explain the homing beam script functionality on a separate article where I’ll also describe a homing projectile used by the player.

--

--

Alberto Garcia
Alberto Garcia

No responses yet