Enemy Attack Cycles in Game Dev
I’m just about to get into programming in the combat system for my and my father’s card-based dungeon game, so I’ve had a good deal of time to think about and look into how I want the combat to feel and play out. One of the most important parts of a game is its combat, and how it implements it. Enemy design is the ultimate deciding factor on whether a game is fun, too difficult, or mind-numbingly easy. Below, I’ll explain the concept of an attack cycle, the rhythmic steps a player takes in response to an enemy’s behaviors and mechanics. Attack cycles are an important thing to take into account when developing your combat system, so let’s get into it.
The Attack Cycle
First things first: an often overlooked, yet important part of enemy design is the rhythm that the player creates as they fight an enemy. The complexity of an enemy shouldn’t be determined by how diverse and riveting their design, programming, or behaviors are, but by how many unique steps the player has to take in each attack cycle while in combat with it.
Below, I’ve written out a few different enemy types and the rhythm the player constructs as a way to defeat that enemy, aka the attack cycle.
Swordsman - Attacks when the player is close, every 1-2 seconds, with a second break between attacks.
[Block -> Attack -> Block -> Attack]
[Dodge -> Attack -> Dodge -> Attack]
The swordsman has two unique attack steps per attack cycle, making a rather simple yet enjoyable enemy type. Other enemy types similar to this are skeletons from Minecraft, which shoot in 1-2 second intervals, opening a chance to attack between shots, or the stone soldier from Moonlighter, which attacks in a single direction towards the player, giving them time to dodge out of the way and counter-attack while they are stuck in their thrust position.
Sniper - Keeps its distance from the player, shooting a projectile every 1-2 seconds, with a second break between attacks.
[Approach -> Block -> Approach -> Block -> Approach -> Attack]
[Approach -> Hide -> Approach -> Hide -> Approach -> Attack]
[Approach -> Dodge -> Approach -> Dodge -> Approach -> Attack]
The sniper is very similar to the swordsman in terms of mechanics, but it becomes a little more complex since it has three unique steps per attack cycle instead of the swordsman’s two.
Healer - Keeps its distance from the player, but pauses to heal nearby allies every 3-4 seconds. While it heals, it cannot move.
[Approach -> Attack -> Approach -> Attack]
Similar to the Swordsman, the healer has only two unique steps per attack cycle.
Opposite to enemy mechanics, which are usually reserved for one enemy type each to prevent clogging the roster, attack cycles very often overlap without any serious issue. You can program in many enemies with a [Block -> Attack] cycle, as long as some mechanics and statistics about each enemy change. A popular example of overlapping attack cycles is The Binding of Isaac, which re-purposes enemies multiple times, not changing their attack cycle but adding in extra mechanics to each one.
Chaotic Enemies
You may think an easy way to introduce difficulty into a game is to break down the attack cycle. While this does make enemies more difficult, it is very easy to cross into the domain of “unfair.”
Take an example:
Grunt - Fast moving, small, and relentless. Attacks quickly and doesn’t give the player time to attack.
[Run -> Attack -> Block -> Run -> Attack]
By not giving the player a window for attack, they have to improvise their own windows. Have you ever played a game where an enemy was so unrelenting that the only way to get attacks in was to run away and turn around? That’s how your player will feel with any overly-chaotic enemy. Prime example, yet another Minecraft reference, baby zombies. Small, fast, annoying, and never stop attacking. Bane of every player’s existence.
Simple Enemies
Simple enemies have little to no overall brain. I typically measure that through how many inputs they are given. Smart enemies may take into account player location, blocking status, attacking status, while simpler ones may only take in player location. Simple enemies, as I define them, have zero inputs. They roam the world aimlessly like a balloon in the wind.
Simple enemy - Chooses a direction to go, and then goes that direction until it hits a wall, then restarts.
[Attack -> Attack -> Attack -> Attack]
Simple enemies may require a dodge now and then, possibly a block if you're feeling fancy, but overall the player can just hack and slash away until the health bar drops. On their own, they can be incredibly boring. However, swarm the player with tens of them, or pair them up with more complex enemies, and you now have an exciting challenge. Below is a ranking of how many inputs makes different levels of simple enemies.
I - Simple - zero inputs, best for populating screens or backing up complex enemies.
II - Rat-brained - 1-2 inputs, has one or two unique steps in their attack cycles, but largely used for population or backing up.
III - Smart - 2-4 inputs, has 1-3 unique steps in their attack cycles, really the star of the show.
III - Intelligent - 4-6 inputs, processor heavy and really reserved for bosses.
It’s important to note that this isn’t a definitive list. Any enemy can have any number of inputs and any number of attack cycle steps. It’s largely up to the game designer how they want to implement their enemy AI.
Enemy Spawning
The best ratio to spawn enemies at is around 3-5 simple enemies and 1-2 complex at a time. The player should have to take into consideration simple enemies, but not worry about them enough to distract from the main threat of the room / encounter. Having too many rhythmic complex enemies at one time breaks the rhythm entirely and devolves the attack cycle into chaos.
Enemies are most engaging at a 1-2-1-2 rhythm, while bosses would benefit from a few more steps depending on how difficult they are expected to be.
Bosses
Bosses / tougher enemies can either be constructed by increasing the number of steps per cycle or being contradictory to the attack cycles the player has already encountered. Let’s bring back the Swordsman enemy from earlier to explain this better.
Swordsman - Attacks when the player is close, every 1-2 seconds, with a second break between attacks.
[Block -> Attack -> Block -> Attack]
[Dodge -> Attack -> Dodge -> Attack]
Let’s add a few more steps to this cycle. Say, now our enemy will also run and shoot a bullet every minute or so.
Firing swordsman - Attacks when the player is close, every 1-2 seconds, with a second break between attacks, then runs away and shoots a bullet.
[Block -> Attack -> Approach -> Hide -> Attack]
The enemy now has more steps, and is overall more complex. The player now needs to learn each of these steps to be able to defeat it in combat.
Now let’s add a contradiction to our attack cycle. Up to this point, the player has been fighting primarily Swordsmen and gotten used to the [Block -> Attack] formula. Let’s throw a wrench in their expectations by giving the enemy a shield-breaking attack that the player has to run away from. Let’s also say that this attack opens up a new attack window where the Swordsman’s weapon gets stuck for a few seconds.
Ultra swordsman - Attacks when the player is close, every 1-2 seconds, with a shield-breaking attack that it uses when the player uses their shield for too long.
[Block -> Retreat -> Attack -> Block -> Retreat -> Attack]
The player enters the boss fight, sees a larger version of the enemies they’ve already faced, and expects to use the same strategy. As they pull out their shield to block a sword swing, the enemy changes up last minute and breaks the player’s shield. The player is taken by surprise and now has to learn a new attack cycle.
For more variety in your boss fight, you can also chain together different attack cycles in different “phases.” This is an idea used since the very beginning of the gaming industry. If you’ve played a game with bosses, or even just heard of them, you’ve definitely run across the concept of “second phases.” This is another way to throw a wrench into the player’s plans, forcing them to adapt to the situation instead of getting used to the attack cycle and cruising through the whole fight. Be warned, though, adding a second phase to an already difficult or long boss fight might hurt players’ experiences.
A few final important notes:
A good boss is not just a larger version of your common enemies. They need to have new behaviors and mechanics. Upping the size and strength of your enemy and doing nothing else is boring for the player.
Bosses typically have more attack cycle steps than a normal enemy. Giving them the same number of steps as a common enemy ruins the tension and difficulty.
You can hose in a few simple enemies, giving the player more to think about when fighting the boss, but don’t overdo it if difficulty isn’t what you're going for. Remember, as a game designer, you will be better at your own game than most people will be. Adjust for a little bit of grace and have play testers playtest your boss.
Having a boss that spawns complex enemies into the arena looks good on paper, but make sure your player is given enough time to properly defeat them before the main boss comes back for an attack. Overloading the player’s senses does make it more difficult, but also more annoying. The last thing you want to do is have players give up your game because they spend hours on a single fight and can’t beat it.
I hope you enjoyed this deep dive into attack cycles, how the player interacts with enemies, and how attack cycle steps affect your player’s view of your game.