Create a game over scene for pygame project

In this article we are going to create a game over scene for the pygame project, we will use back the start scene class which we have created previously to render our game over scene by slightly modify it for the multi-scenes uses. Here is the modify version of the start scene class, as you can see we have passed in a state variable to the start scene class’s draw method which will be used to determine which scene to be rendered on the screen.

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

class StartScene(object):

    def __init__(self, scene):
        self.scene = scene
        self.button_image = 'Asset/button_play.png'
        self.bg_image = 'Asset/start.png'
        self.over_image = 'Asset/ove.png'
        self.bg_rect = Rect(0, 0, 660, 660)
        self.button_rect = Rect(0, 0,  306, 112)
        self.sprite = BgSprite(self.bg_image, self.bg_rect)
        self.sprite_over = BgSprite(self.over_image, self.bg_rect)
        self.sprite_button = GameSprite(self.button_image, self.button_rect)
        self.over_surface = self.sprite_over.getImage()  # get the game over sprite surface
        self.surface = self.sprite.getImage()  # get the start scene sprite surface
        self.button_surface = self.sprite_button.getImage() # get the button sprite surface
        self.draw_pos = mt.Vector2(0, 0)
        self.draw_button_pos = mt.Vector2(177, 274)

    def draw(self, state):
        
        if(state == 0):
            self.scene.blit(self.surface, self.draw_pos) # draw a start scene sprite
        else:
            self.scene.blit(self.over_surface, self.draw_pos)  # draw a game over sprite
        self.scene.blit(self.button_surface, self.draw_button_pos)  # draw a button sprite
        pygame.display.flip()

Next we will need to modify the Game Manager class again by including an extra game over state variable and a new setup method into it.

from Player import Player
from Background import Background
from EnemyManager import EnemyManager
from Overlap import Overlap
from ExplosionManager import ExplosionManager
from Score import Score
from StartScene import StartScene
from pygame.locals import *
import pygame

class GameManager(object):

    def __init__(self, scene):

        self.scene = scene
        self.start_scene = StartScene(scene)
        self.load_music()
        self.play_music()
        self.overlap_manager = Overlap()

        self.setup()

        #game state
        self.LOAD = 0
        self.GAME = 1
        self.OVER = 2

        self.state = self.LOAD

    def setup(self):

        self.player = Player(self.scene)
        self.background = Background(self.scene)
        self.enemy_manager = EnemyManager(self.scene, self.player)
        self.explosion_manager = ExplosionManager(self.scene)
        self.score_manager = Score(self.scene)

    def loop(self):

        if(self.state == self.LOAD or self.state == self.OVER):

            self.start_scene.draw(self.state)

        elif(self.state == self.GAME):

            self.update()
            self.draw()

    def isAreaClick(self, pos):
        if (self.state == self.LOAD or self.state == self.OVER):
            self.rect = Rect(177, 274, 306, 112) # the position of the play button on the scene
            x, y = pos
            if(self.rect.collidepoint(x, y)):
                self.state = self.GAME


    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):
        if (self.state == self.GAME):
            self.player.setX(_x)

    def set_player_y(self, _y):
        if (self.state == self.GAME):
            self.player.setY(_y)

    def set_missile_strike(self, strike):
        if (self.state == self.GAME):
            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.isOverlap(self.player, self.enemy_manager, self.explosion_manager, self.score_manager, self)

    def draw(self):
        self.background.draw()
        self.player.draw()
        self.enemy_manager.draw()
        self.explosion_manager.draw()
        self.score_manager.draw()
        pygame.display.flip()

We will pass in this class as the reference into the isOverlap method of the overlap manager which then will be used to access the state variable as well as reset the game objects to their original state by calling the newly created setup method of this class.

The last thing we need to do is to modify the overlap class.

from pygame.locals import *

class Overlap(object):

    def __init__(self):
        pass # nothing here

    # is player and enemy, player missile, enemy missile overlap
    def isOverlap(self, player, em, ex, score, gm):

        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
                    gm.state = gm.OVER
                    gm.setup()

        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)
                score.set_score(-1)
                if(score.score < 0):
                    gm.state = gm.OVER
                    gm.setup()

        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
                        score.set_score(1)

The game over scene will be loaded and the game objects will be recreated whenever the player collides with the enemy ship or the player strength falls below zero.

With that done we are now ready to move on to the next stage of the project, which is to create a level manager class to manage all the game levels in this game. If you have not yet subscribed to this website then do make sure to click on the red bell button below this post so you will get a first hand notification whenever a new article has been posted. This pygame project is not yet complete and there are still more articles related to this topic will be posted soon so make sure you subscribe to this website by clicking on that red bell button below if you want to read more articles about the pygame subject!

If you are following this tutorial from the beginning then your pycharm file explorer area should now has all these files below.

The game graphic area
All the game graphics
All the game project files
All the game project files

It is time to move on to the next chapter, see you there!

Create a score manager class for pygame project

In this article we will create a score manager class to render the player score on the scene for our pygame project. At the moment we will only increase the score of the player each time the player’s missile hits the enemy ship and deduct the player score each time the player gets hit by the enemy missile, in the future we will introduce more features into the score manager class but for now lets just create a simple score manager class so we can edit it later on. Here is the score manager class.

import pygame.font as txt
from pygame.locals import *

class Score(object):

    def __init__(self, scene):

        self.score = 0
        self.scene = scene
        self.rect = Rect(20,20, 100, 30)
        self.font = txt.Font(None, 30)
        self.score_text = "Score : " + str(self.score)

    def set_score(self, score):

        self.score += score
        self.score_text = "Score : " + str(self.score)

    def draw(self):

        self.text = self.font.render(self.score_text, 1, (255, 255, 255))
        self.scene.blit(self.text, self.rect)

The set score method will be called in the overlap object’s iseOverlap method each time the player gets hit by the enemy missile or the enemy ship gets hit by the player missile. We will pass the score manager object into the iseOverlap method of the Overlap object in each game loop from the Game Manager class.

Lets edit the Game Manager class by creating a new score manager object and then pass the score manager object into the iseOverlap method of the Overlap object in each game loop. We will then call the score manager to draw the new score on the scene in the draw method of the Game Manager.

from Player import Player
from Background import Background
from EnemyManager import EnemyManager
from Overlap import Overlap
from ExplosionManager import ExplosionManager
from Score import Score
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.score_manager = Score(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, self.score_manager)

    def draw(self):
        self.background.draw()
        self.player.draw()
        self.enemy_manager.draw()
        self.explosion_manager.draw()
        self.score_manager.draw()
        pygame.display.flip()

The Overlap method just needs slightly modification.

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, score):

        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)
                score.set_score(-1)

        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
                        score.set_score(1)

Here is the result from the above program.

score manager in action
score manager in action

We will revisit the score manager again when we need it but for now it is time to move on to the next topic.

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.

Create the pool object for Enemy Missile class

In this article we will continue to create a new missile pool object which will be used to recycle the enemy missile object just like the pool object which will be used to recycle the enemy ship object in the previous article. Basically we will use back the previous object pool class which we have created earlier and then add in a new obtain missile method which takes in the x and y coordinate of the enemy ship at that moment that we can later use as the starting point for the missile object returns from the pool. Here is the class.

class Objectpool(object):

    def __init__(self, size):

        self.size = size
        self.count = 0
        self.elist = [None]*size

    def recycle(self, item):

        if (self.count  < self.size):
            self.elist[self.count] = item
            self.count += 1

    def obtain(self):

        if (self.count > 0):
            self.count -= 1
            self.item = self.elist[self.count]
            self.elist[self.count] = None
            self.item.missile_count = 1
            return self.item

    def obtain_missile(self, x, y): # get the missile object from the pool

        if (self.count > 0):
            self.count -= 1
            self.item = self.elist[self.count]
            self.elist[self.count] = None
            self.item.x = x
            self.item.y = y
            self.item.on = True
            return self.item

    def getSize(self):

        return self.count

That is it, now lets amend the Enemy Missile Manager class by adding in the create missile from pool method which will be used to obtain the old missile object from the object pool.

from GameSprite import GameSprite
from pygame.locals import *
from Enemymissile import Enemymissile

class EnemyMissileManager(object):

    def __init__(self, scene, player):

        self.scene = scene
        self.player = player
        self.missile_count = 60
        self.missile_list = []
        self.image = 'Asset/e_missile.png'
        self.width = 20
        self.height = 20
        self.rect = Rect(0, 0, self.width, self.height)

        # initialize game sprite object
        self.sprite = GameSprite(self.image, self.rect)

    def create_missile(self, x, y):

        if(self.missile_count >= 0):
            self.missile_surface = self.sprite.getImage()
            self.missile_list.append(Enemymissile(self.missile_surface, x, y))
            self.missile_count -= 1

    def create_missile_from_pool(self, x, y, pool):

        if (self.missile_count >= 0):
            self.missile_list.append(pool.obtain_missile(x, y))
            self.missile_count -= 1

    def update(self, pool):

        self.missile_update(pool)
        self.check_boundary()

    def missile_update(self, pool):

        for item in list(self.missile_list):
            if(item.on == False):
                self.missile_list.remove(item)
                self.missile_count += 1
                pool.recycle(item)
            else:
                item.update()

    def check_boundary(self):

        for i in range(len(self.missile_list)):
            if (self.missile_list[i].y + self.missile_list[i].height > 660):
                self.missile_list[i].on = False

    def draw(self):

        # blit the missile on  the scene
        for i in range(len(self.missile_list)):
            self.scene.blit(self.missile_list[i].missile_surface, self.missile_list[i].missile_pos)

We now need to do the last step which is to edit the Enemy Manager class.

from Enemy import Enemy
from GameSprite import GameSprite
from pygame.locals import *
from EnemyMissileManager import EnemyMissileManager
import random
from Objectpool import Objectpool

class EnemyManager(object):

    def __init__(self, scene, player):

        self.enemy_missile_manager = EnemyMissileManager(scene, player)
        self.scene = scene
        self.player = player
        self.enemy_count = 10
        self.missile_count = 60
        self.enemy_list = []
        self.image = 'Asset/enemy0.png'
        self.width = 30
        self.height = 30
        self.rect = Rect(0, 0, self.width, self.height)
        self.more_enemy = 0
        self.y = -50
        self.boundary_width = 660
        self.boundary_height = 660
        self.object_pool = Objectpool(self.enemy_count)
        self.missile_object_pool = Objectpool(self.missile_count)

        # initialize game sprite object
        self.sprite = GameSprite(self.image, self.rect)

    def create_enemy(self, x, y):
        if(self.enemy_count > 0):
            if(self.object_pool.getSize() > 0): # get the ship from object pool if the pool is not empty
                self.enemy_list.append(self.object_pool.obtain())
            else:
                self.enemy_surface = self.sprite.getImage()
                self.enemy_list.append(Enemy(self.enemy_surface, x, y))
            self.enemy_count -= 1


    def update(self):
        if (self.more_enemy > 600):
            self.more_enemy = 0
            x = random.randint(30, self.boundary_width - 50)
            self.create_enemy(x , self.y)  # create more enemy
        else:
            self.more_enemy += 1 # increase time

        self.enemy_update()
        self.check_boundary()
        self.create_enemy_missile()
        self.enemy_missile_manager.update(self.missile_object_pool)

    def create_enemy_missile(self):

        for item in list(self.enemy_list):

            if(self.player.pos.y - item.y  < 100 and abs(self.player.pos.x - item.x) < 60 ):

                if (item.missile_count > 0):

                    if (self.missile_object_pool.getSize() > 0):
                        self.enemy_missile_manager.create_missile_from_pool(item.x + 5, item.y + 4, self.missile_object_pool)

                    else:
                        self.enemy_missile_manager.create_missile(item.x + 5, item.y + 4)

                    item.missile_count -= 1

    def enemy_update(self):

        for item in list(self.enemy_list):
            if(item.on == False):
                self.enemy_list.remove(item)
                self.enemy_count += 1
                item.y = self.y
                item.on = True
                self.object_pool.recycle(item)
            else:
                item.update()

    def check_boundary(self):
        for i in range(len(self.enemy_list)):
            if (self.enemy_list[i].y > self.boundary_height):
                self.enemy_list[i].on = False

    def draw(self):

        # blit the enemy on  the scene
        for i in range(len(self.enemy_list)):
            self.scene.blit(self.enemy_list[i].enemy_surface, self.enemy_list[i].enemy_pos)
        # draw enemy missiles
        self.enemy_missile_manager.draw()

That is it! With that we will be able to reuse the old enemy missile object instead of creating a new one. The next article will still be dealing with the pool object and this time we will create an object pool for the player missile object!

Create the Overlap class for Pygame project

Hello there, sorry for a little bit late today because I am busy setting up my old website which is now ready for me to add in more articles into it, if you are interested in more programming articles then do visit this site because I am going to create a brand new laptop application project with python and if you are a python lover then go ahead and bookmark this site and visit it starting from tomorrow!. Gaming Directional, which is the site we both are in now will only concentrate on writing game code so if you want to read other programming articles besides the game one then do visit the above mentioned site instead. OK so much for that lets look at another of the new class I have created for the previous pygame project, which is the Overlap class.

We will call the Overlap class object on every game loop to determine the following:-

1) Does the player ship gets hit by the enemy missile? If so then we will remove that enemy missile.
2) Does the player ship hits one of the enemy ship? If so then we will remove that enemy ship.
3) Does the enemy ship gets hit by a player missile? If so then remove both of them.

We will not going to do anything on the player ship yet even if it gets hit by the enemy ship or missile because we will deal with this issue later on.

Here is the entire Overlap class.

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, pm):

        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

        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

        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(pm.missile_list)):

                self.pm_rect = Rect(pm.missile_list[j].x, pm.missile_list[j].y, pm.width, pm.height)

                if (self.em_rect.colliderect(self.pm_rect)):
                    em.enemy_list[i].on = False
                    pm.missile_list[j].on = False

We also need to edit the Game Manager class like this.

from Player import Player
from Background import Background
from MissileManager import MissileManager
from EnemyManager import EnemyManager
from Overlap import Overlap
import pygame

class GameManager(object):

    def __init__(self, scene):

        self.scene = scene
        self.player = Player(self.scene)
        self.background = Background(self.scene)
        self.missile_manager = MissileManager(self.scene, self.player)
        self.enemy_manager = EnemyManager(self.scene, self.player)
        self.overlap_manager = Overlap()
        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. missile_manager.setStrike(True)

    def update(self):
        self.player.update()
        self.missile_manager.update()
        self.enemy_manager.update()
        self.isOverlap()

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

    def draw(self):
        self.background.draw()
        self.player.draw()
        self.missile_manager.draw()
        self.enemy_manager.draw()
        pygame.display.flip()

And here is the outcome

Alright then, after this class we will continue to create the recycle class tomorrow which we will use to recycle and then reuse back the game object so we do not need to create a new one which will increase the burden of the computer’s processor.

The modify version of the Pygame Missile Manager Class

Before we go ahead and create the Game Manager class we will need to take out all the code which are related to the missile manager in the main python file as shown in the previous article and put them all under a single missile manager class. Here is the modify version of the missile manager class as compared with the previous version.. This class will take in both the scene as well as the player object to start with.

from Missile import Missile
from GameSprite import GameSprite
from pygame.locals import *

class MissileManager(object):

    def __init__(self, scene, player):
        self.scene = scene
        self.player = player
        self.missile_count = 10
        self.missile_list = []
        self.image = 'Asset/missile.png'
        self.width = 20
        self.height = 20
        self.rect = Rect(0, 0, self.width, self.height)
        self.strike = False
        self.strike_again = 0
        # initialize game sprite object
        self.sprite = GameSprite(self.image, self.rect)

    def setStrike(self, strike):

        # set the missile strike flag
        self.strike = strike
        self.strike_again += 1

    def create_missile(self, x, y):
        if(self.missile_count >= 0):
            self.missile_surface = self.sprite.getImage()
            self.missile_list.append(Missile(self.missile_surface, x, y))
            self.missile_count -= 1

    def update(self):
        if (self.strike == True and self.strike_again > 1):
            self.strike_again = 0
            x, y = self.player.get()
            self.create_missile(x + 5, y - 8)  # create more missile
        self.missile_update()
        self.check_boundary()

    def missile_update(self):

        for item in list(self.missile_list):
            if(item.on == False):
                self.missile_list.remove(item)
                self.missile_count += 1
            else:
                item.update()

    def check_boundary(self):
        for i in range(len(self.missile_list)):
            if (self.missile_list[i].y < 0):
                self.missile_list[i].on = False

    def draw(self):

        # blit the missile on  the scene
        for i in range(len(self.missile_list)):
            self.scene.blit(self.missile_list[i].missile_surface, self.missile_list[i].missile_pos)

As you can see we will use a single update method to control both the missile update and the check boundary method. We have also included a new draw method to draw the missiles on the game scene. The missile manager class does not need to return the missile list anymore to the main file so the previous method has been totally removed. Finally we have a set strike method to turn the strike flag on or off depends on whether the space key has been pressed or released.

That is it for this one, now lets us look at the Game Manager class in the next chapter.

Pygame loads image and background graphic on game scene

After a few days of rest, today I have continued my pygame project again and will keep on working on my new pygame projects without stopping anymore starting from today. Today I have created two game sprite classes to render the player and the background on the game scene.

The player sprite class is almost the same as the background sprite class, the only reason I have created two game sprite classes is because I want to create extra custom methods for the background sprite class.

The player class (GameSprite.py) will look like this.

import pygame

class GameSprite(object):

    def __init__(self, image, rect):
        self.image = image
        self.rect = rect
        self.sprite = pygame.image.load(image).convert_alpha() # return a pygame surface object

    def getImage(self):  # this method will return a subsurface which is the child of the self.sprite surface
        return self.sprite.subsurface(self.rect)

The background class (BgSprite.py) is almost the same for now.

import pygame

class BgSprite(object):

    def __init__(self, image, rect):
        self.image = image
        self.rect = rect
        self.sprite = pygame.image.load(image).convert() # return a pygame surface object

    def getImage(self):  # this method will return a subsurface which is the child of the self.sprite surface
        return self.sprite.subsurface(self.rect)

Here is the modify version of the main file, the background and the player image has been displayed.

import sys, pygame
from pygame import math as mt
from pygame.locals import *
from GameSprite import GameSprite
from BgSprite import BgSprite

pygame.init()
size = width, height = 660, 660
pygame.display.set_caption("Hello World") # set the title of the window
screen = pygame.display.set_mode(size)

pygame.mixer_music.load('Music/winternight.ogg')
pygame.mixer_music.play(-1)

player_sprite = 'Asset/player.png'
bg_sprite = 'Asset/bg.png'

player_pos = mt.Vector2(width/2, height/2) # initialize the position of the player sprite

rect = Rect(0, 0, 40, 40)  # the rectangle object uses to clip the sprite area
game_sprite = GameSprite(player_sprite, rect)
game_sprite_surface = game_sprite.getImage()  # get the player sprite surface

rect = Rect(0, 0, 660, 660)
game_bg_sprite = BgSprite(bg_sprite, rect)
game_bg_surface = game_bg_sprite.getImage()  # get the background sprite surface

player_draw_pos = mt.Vector2(player_pos.x , player_pos.y)
bg_draw_pos = mt.Vector2(0 , 0)

while True:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.mixer_music.stop()
            sys.exit()

    screen.blit(game_bg_surface, bg_draw_pos)
    screen.blit(game_sprite_surface, player_draw_pos)
    pygame.display.flip()

Run the above program will get this outcome.

Display the player and the background
Display the player and the background

The files under the project file explorer will now look like this.

PyCharm file explorer
PyCharm file explorer

In the next session we will deal with keyboard input so we can move the player around the game scene.

Journey into PyGame — The beginning

For those python fans, Pygame is indeed a great python’s game engine which you all should really consider if you want to write game using the python language. Although some of you might disagree with my thought but if we remove PyGame from the list of Python’s gaming engine then the only one left for us to consider will be pyglet which is not that well documented as compared to PyGame and thus makes our game development process even harder as compared to using the PyGame engine.

In this article I am going to show you how to install and run your first pygame program with a few lines of python script, ok, without wasting any time let get started.

I have installed python 3.5.2 in my computer and thus I will need to install the PyGame version which matches my python version. In order to install PyGame which matches Python 3.x you will need to visit this PyGame download page. Although my computer’s os belongs to windows 64bit but it seems like the 64bit PyGame version is not working due to some unknown reason (either one of the module is missing or the platform is not supported), due to that I have selected the 32bit version instead because it really doesn’t matter either we are installing the 32bit or the 64bit in our 64bit os as long as the os is 64bit then we can either select the 32bit or the 64bit version, however the reverse is not true because if we install the 64bit PyGame in our 32bit pc then we will not be able to use it at all.

I have downloaded this file pygame-1.9.2b1-cp35-cp35m-win32.whl from the above website. The cp35 in the filename means python 3.5 and win32 means it is for 32bit of windows os. After I have downloaded this file I will need to install it either with pip or pip3 or pip3.5. Browse to the folder where you have downloaded the whl file in the windows command prompt then type in this command : pip3 install pygame-1.9.2b1-cp35-cp35m-win32.whl to extract and then install the PyGame module into Python’s site package folder.

Next create a new project in NetBeans 8.1 IDE and then create a new python module with any name you like and enter below script into it. If you want to know how to use PyGame in your python program then you can visit the PyGame official homepage for further detail.

#!/usr/bin/env python

import pygame
from pygame.locals import *
from sys import exit

background_image = 'terain7.png'

pygame.init()
screen = pygame.display.set_mode((640, 480), 0, 32)
pygame.display.set_caption("Pygame Demo")
background = pygame.image.load(background_image).convert()

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
    screen.blit(background, (0,0))
    pygame.display.update()

You will also need to provide a background image (terain7.png) in the same folder as your gaming module in order for the display to show that image. Now run the script and you should see the below pop up with any background image which you have included together with your gaming module.

Pygame
Pygame

Pygame engine starts slowly which is a common problem for all the python programs but once it is ready then it will operate smoothly!