Pygame RPG Tutorial – Enemy Generation

This is tutorial number 11 in our Pygame RPG series.

In this tutorial we’ll be continuing where we left off in the previous one. We’ve created a bunch of different dungeons, and now it’s time to actually populate them with the appropriate amount of enemies.

Creating Stages

The last tutorial, Stage generation was supposed to cover all stage generation concepts, and it did. It laid the framework for us to enable enemy generation. Remember, complete stage generation requires level generation + enemy generation. The last tutorial was more like level generation, instead of the complete stage generation.

class EventHandler():
      def __init__(self):
            self.stage_enemies = []
            for x in range(1, 21):
                  self.stage_enemies.append(int((x ** 2 / 2) + 1))

We’ve devised a “formula” to calculate the number of enemies to be generated per level. We could have manually defined it too, but this way allows us to create more dynamic code (unlimited number of levels). All we have to do is increase the upper limit on the for loop.

[1, 3, 5, 9, 13, 19, 25, 33, 41, 51, 61, 73, 85, 99, 113, 129, 145, 163, 181, 201]

This is what the list, stage_enemies looks like when printed out. We tweaked the formula till we got a list which starts out small, but begins getting larger with increasing gaps.

Advancing Stages

This code is in charge of moving the dungeon to the next stage. It increments the current stage counter by one, and sets the timer for enemy generation.

The interesting thing to note is the formula we created to calculate the intervals between each enemy generation. The higher the stage number, the lower the time gap between enemy spawns, meaning harder levels.

      def next_stage(self):  # Code for when the next stage is clicked            
            self.stage += 1
            self.enemy_count = 0
            print("Stage: "  + str(self.stage))
            pygame.time.set_timer(self.enemy_generation, 1500 - (50 * self.stage)) 

It’s important to set the enemy_count back to zero for every stage cleared, otherwise the number of enemies generated will be much fewer.

Modifying the Game loop

All the code below is going to be added into the game loop. Although we’ve just written the code itself, you should know where it’s meant to be placed by now based on their purpose.

The below code will keep generating enemies every time the timer for enemy generation is triggered (every 2 seconds). However, it will not generate more enemies than what our handler’s stage_enemies variable has defined as the max limit for that stage.

        if event.type == handler.enemy_generation:
            if handler.enemy_count < handler.stage_enemies[player.stage - 1]:
                  enemy = Enemy()
                  handler.enemy_count += 1     

This is the code that is going detect our keypress and activate the next_stage() function. We’ve assigned it the key press “n” which activates only when you are in a dungeon and there are no more enemies currently existing.

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_n:
                  if handler.battle == True and len(Enemies) == 0:

The below code is a really handy way of executing all the move() and render() methods of every enemy object using Sprite groups. It iterates over every single enemy object within it, and calls the three methods update(), move() and render().

    for entity in Enemies:

Our Game Progress

As as now we have successfully implemented both stage and enemy generation. We’ve uploaded an almost 1-min long video down below for you to properly view all the progress we have made uptil now.

The quality of the game actually drops a bit in the recording, so don’t make your final judgement until you’ve actually run the program on your own system.


As of this point, the core part of our game has been complete. From now on we’ll be dealing with much smaller (but important) concepts such as:

Click the button to move on to the next tutorial in this series, or use one of the above links to learn a specific concept. Remember, this is all done as part of a continuous series, so you may have trouble understanding if you pick from these tutorials randomly.

This marks the end of the Pygame RPG Tutorial – Enemy generation. Any suggestions or contributions for CodersLegacy are more than welcome. Questions regarding the article content can be asked in the comments section below.

Notify of
Newest Most Voted
Inline Feedbacks
View all comments