Create an explosion manager and explosion class for pygame project

In this article we will create an explosion manager as well as an explosion class to manage the on scene explosions but first of all lets watch the raw video below which shows the explosions on the game scene.

Before we create the above classes, we will create one single explosion sprite sheet which contains many explosion stages. We will then render each part of the sprite sheet with the help of the timer variable inside the explosion class.

Here is the explosion sprite sheet which we are using in this game.

Explosion
Explosion Sprite Sheet

Here is the explosion class.

from pygame import math as mt
from pygame.locals import *

class Explosion(object):

    def __init__(self, ex_surface, x, y):
        self.on = True
        self.ex_surface = ex_surface
        self.x = x
        self.y = y
        self.ex_pos = mt.Vector2(self.x, self.y)
        self.count = 0
        self.width = 64
        self.height = 64
        self.rect = Rect(self.count * self.width, 0, self.width, self.height)
        self.timer = 0

    def update(self):

        if(self.count <= 9):
            
            if(self.timer > 16):
                self.count += 1
                self.rect = Rect(self.count * self.width, 0, self.width, self.height)
                self.ex_pos = mt.Vector2(self.x, self.y)
                self.timer = 0
            else:
                self.timer += 1
        else:
            self.count = 0
            self.on = False
            self.timer = 0
            self.rect = Rect(self.count * self.width, 0, self.width, self.height)

As you can see we will constantly update the rect variable which will be used by the scene object to draw only a portion of the sprite explosion’s stage from the sprite sheet until all the explosion’s stages have been drawn on the scene which we will then remove the explosion object from the explosion main list. The timer variable is uses to control the creation speed of the new rectangle object so we will see a smooth stage transformation process on the game scene.

And here is the explosion manager class.

from pygame.locals import *
from GameSprite import GameSprite
from Objectpool import Objectpool
from Explosion import Explosion

class ExplosionManager(object):

    def __init__(self, scene):

        self.image = 'Asset/explosion.png'
        self.scene = scene
        self.width = 640
        self.height = 64
        self.explosion_count = 10
        self.count = 0
        self.rect = Rect(0, 0, self.width, self.height)
        self.sprite = GameSprite(self.image, self.rect)
        self.sprite_surface = self.sprite.getImage()  # get the player sprite surface
        self.explosion_object_pool = Objectpool(self.explosion_count)
        self.explosion_list = []

    def create_explosion(self, x, y):

        if (self.explosion_object_pool.getSize() > 0):
            self.explosion_list.append(self.explosion_object_pool.obtain_missile(x, y))
        else:
            self.explosion_list.append(Explosion(self.sprite_surface, x, y))

    def explosion_update(self):

        for item in list(self.explosion_list):
            if(item.on == False):
                self.explosion_list.remove(item)
                self.explosion_object_pool.recycle(item)
            else:
                item.update()

    def draw(self):

        # blit the explosion on  the scene
        for i in range(len(self.explosion_list)):
            self.scene.blit(self.explosion_list[i].ex_surface, self.explosion_list[i].ex_pos, self.explosion_list[i].rect)

The methods within the above class are almost the same as the methods use by the other manager classes, as you can see we have created an explosion pool object to recycle the explosion object just like what we did before in the other manager classes.

Finally we need to modify the Game Manager class and the Overlap class.

from Player import Player
from Background import Background
from EnemyManager import EnemyManager
from Overlap import Overlap
from ExplosionManager import ExplosionManager
import pygame

class GameManager(object):

    def __init__(self, scene):

        self.scene = scene
        self.player = Player(self.scene)
        self.background = Background(self.scene)
        self.enemy_manager = EnemyManager(self.scene, self.player)
        self.overlap_manager = Overlap()
        self.explosion_manager = ExplosionManager(self.scene)
        self.load_music()
        self.play_music()

    def load_music(self):
        pygame.mixer_music.load('Music/winternight.ogg')

    def play_music(self):
        pygame.mixer_music.play(-1) #play the music infinite time

    def set_player_x(self, _x):
        self.player.setX(_x)

    def set_player_y(self, _y):
        self.player.setY(_y)

    def set_missile_strike(self, strike):
        self.player.setStrike(strike)

    def update(self):
        self.player.update()
        self.enemy_manager.update()
        self.isOverlap()
        self.explosion_manager.explosion_update()

    # check for player, enemy, missiles overlap
    def isOverlap(self):
        self.overlap_manager.iseOverlap(self.player, self.enemy_manager, self.explosion_manager)

    def draw(self):
        self.background.draw()
        self.player.draw()
        self.enemy_manager.draw()
        self.explosion_manager.draw()
        pygame.display.flip()
from pygame.locals import *

class Overlap(object):

    def __init__(self):
        pass # nothing here

    # is player and enemy, player missile, enemy missile overlap
    def iseOverlap(self, player, em, ex):

        self.player_rect = Rect(player.pos.x, player.pos.y, player.width, player.height)

        for i in range(len(em.enemy_list)): # is player collides with enemy

            self.em_rect = Rect(em.enemy_list[i].x, em.enemy_list[i].y, em.width, em.height)
            if (self.player_rect.colliderect(self.em_rect)):
                em.enemy_list[i].on = False
                if(em.enemy_list[i].hit == False):
                    ex.create_explosion(player.pos.x + 2, player.pos.y + 2)
                    em.enemy_list[i].hit = True

        for i in range(len(em.enemy_missile_manager.missile_list)): # is enemy missile hits player

            self.em_rect = Rect(em.enemy_missile_manager.missile_list[i].x, em.enemy_missile_manager.missile_list[i].y, em.enemy_missile_manager.width, em.enemy_missile_manager.height)
            if (self.player_rect.colliderect(self.em_rect)):
                em.enemy_missile_manager.missile_list[i].on = False
                ex.create_explosion(player.pos.x + 2, player.pos.y + 2)

        for i in range(len(em.enemy_list)): # is player missile hits enemy

            self.em_rect = Rect(em.enemy_list[i].x, em.enemy_list[i].y, em.width, em.height)

            for j in range(len(player.getMissileManager().missile_list)):

                self.mm_rect = Rect(player.getMissileManager().missile_list[j].x, player.getMissileManager().missile_list[j].y, player.getMissileManager().width, player.getMissileManager().height)

                if (self.em_rect.colliderect(self.mm_rect)):
                    em.enemy_list[i].on = False
                    player.getMissileManager().missile_list[j].on = False
                    if (em.enemy_list[i].hit == False):
                        ex.create_explosion(em.enemy_list[i].x, em.enemy_list[i].y + 2)
                        em.enemy_list[i].hit = True

Besides the above, we also need to include a hit variable in the enemy class and set it to false so the explosion will not happen twice due to many time of contact between the enemy ship and the same missile as well as the enemy ship and the player ship during the game. Also don’t forget to set the hit variable of the enemy to false again within the obtain method of the object pool class.

That is it, after passing the explosion manager into the Overlap class we can now create an explosion object whenever there is any contact happens between the game objects on the scene.