2D Games Core Programming: Aggressive Enemy Type

Manny Cabacungan
2 min readOct 15, 2023

--

Objectives:

  • Create the functionality to support enemy aggression
  • If an enemy is close to a player, the enemy will try and “ram” it.

I decided to make the new Laser Beam enemy aggressive at later levels to balance out the game play as the player progresses.

In the Enemy.cs script, I added the following new variables:

public int afterLevelXLaserBeamEnemyRamPlayerMove = 1; // Default = 7
[SerializeField] private bool _aggressiveEnemy = false;
public float _rammingDistance = 5.0f;

In the Update() method, inside the switch statement, in the case for the Laser Beam enemy, I added a new conditional if statement for the _aggressiveEnemy boolean around the movement conditionals. If _aggressiveEnemy is true the enemy will move to ram the player in the method RamPlayer() that we will define later.

After the switch cases, I made a call to another method for the enemy aggression, DetermineEnemyAggression(), that sets the _aggressiveEnemy boolean.

void Update()
{
switch (_enemyID)
{
case _enemyIDs.LaserBeam:
if (!_aggressiveEnemy)
{
if (_gameManager.waveID > afterLevelXLaserBeamEnemyWavyMove) // afterLevelXLaserBeamEnemyWavyMove = 7 (Default)
{
CalculateMovementWavy();
}
else
{
CalculateMovementStandard();
}
} else if (_aggressiveEnemy) // Enemy is close enough to player to Ram and advanced Wave Level
{
RamPlayer();
}

FireLaserBeam();
break;
case _enemyIDs.Standard:
default:
CalculateMovementStandard();
FireLaserNormal();
break;
}

DetermineEnemyAggression(); // sets _aggressiveEnemy according to wave level, distance to player, chance random assignment
}

Next, I defined the DetermineEnemyAggression() method, using a conditional to compare the current wave level with the wave number set in the variable afterLevelXLaserBeamEnemyRamPlayerMove and making sure the player is not dead, and another nested conditional comparing the distance of the enemy to the player using the Distance() function. If all these conditions are true, then I can set _aggressiveEnemy to true. Otherwise, it’s false.

Distance() reference

private void DetermineEnemyAggression() //sets _aggressiveEnemy according to wave level, distance to player
{
if ((_gameManager.waveID > afterLevelXLaserBeamEnemyRamPlayerMove) && _player != null)
{
float _distanceToPlayer = Vector3.Distance(this.transform.position, _player.transform.position);

if (_distanceToPlayer < _rammingDistance)
{
_aggressiveEnemy = true;
}
} else
{
_aggressiveEnemy = false;
}
}

The method RamPlayer() was defined using the MoveTowards() function which accepts the parameters for the current game object’s position, the target’s position, and the maximum distance to move in a frame which we temper with Time.deltaTime.

MoveTowards() reference

private void RamPlayer()
{
if (_player != null)
{
transform.position = Vector2.MoveTowards(transform.position, _player.transform.position, _speed * 1.5f * Time.deltaTime);
}
}

When we test the game, after Wave 3, the new Laser Beam enemies, will ram the player if the player is close enough.

--

--