Edit the level 2 game map

It has been a day since the last post, I am really busy recently working on the offline business so I really need to divide the time equally for both the online and the offline business. In this chapter, we will finish up the previous unfinished business which is to come out with a new game map for level 2. We need to edit those level 2 data for the player, the enemy, the background and the mana object as follows.

class BoyObject(object):

    def __init__(self):

        self.list_1 = [

            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.ladder_boundary_1 = [[9 * 64, 8 * 64],
                                  [9 * 64, 7 * 64],
                                  [5 * 64, 6 * 64],
                                  [5 * 64, 5 * 64],
                                  [2 * 64, 3 * 64],
                                  [2 * 64, 4 * 64],
                                  [0 * 64, 1 * 64],
                                  [0 * 64, 2 * 64],
                                  ] # the boundary of the ladder

        self.boundary_bottom_1 = [[9 * 64, 9 * 64],
                                  [5 * 64, 7 * 64],
                                  [2 * 64, 5 * 64],
                                  [0 * 64, 3 * 64]]  # the bottom boundary of the ladder

        self.boundary_side_1 = [[4 * 64, 6 * 64],
                                [1 * 64, 4 * 64],
                                [6 * 64, 2 * 64], ]  # the side boundary of the player

        self.boundary_door_1 = [[9 * 64, 0]]

        self.initial_1 = [0, 8 * 64]

        self.list_2 = [

            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.ladder_boundary_2 = [[9 * 64, 8 * 64],
                                  [9 * 64, 7 * 64],
                                  [2 * 64, 6 * 64],
                                  [2 * 64, 5 * 64],
                                  [2 * 64, 4 * 64],
                                  [2 * 64, 3 * 64],
                                  [8 * 64, 1 * 64],
                                  [8 * 64, 2 * 64],
                                  ]  # the boundary of the ladder

        self.boundary_bottom_2 = [[9 * 64, 9 * 64],
                                  [2 * 64, 7 * 64],
                                  [8 * 64, 3 * 64]]  # the bottom boundary of the ladder

        self.boundary_side_2 = [[1 * 64, 6 * 64],
                                [0 * 64, 2 * 64],]  # the side boundary of the player

        self.boundary_door_2 = [[0, 0]]

        self.initial_2 = [0, 8 * 64]

    def get_original_position(self, level):

        if (level == 1):
            return self.initial_1
        elif (level == 2):
            return self.initial_2

    def get_object_list(self, level):

        if(level == 1):
            return self.list_1
        elif (level == 2):
            return self.list_2

    def get_object_boundary(self, level):

        if (level == 1):
            return self.ladder_boundary_1
        elif (level == 2):
            return self.ladder_boundary_2

    def get_object_bottom_boundary(self, level):

        if (level == 1):
            return self.boundary_bottom_1
        elif (level == 2):
            return self.boundary_bottom_2

    def get_object_side_boundary(self, level):

        if (level == 1):
            return self.boundary_side_1
        elif (level == 2):
            return self.boundary_side_2

    def get_object_door_boundary(self, level):

        if(level == 1):
            return self.boundary_door_1
        elif (level == 2):
            return self.boundary_door_2
class EnemyObject(object):

    def __init__(self):

        self.list_1 = [

            [0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 1, 0, 0, 0, 1, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.boundary_1 = [
            [[0, 0], [8 * 64, 0]],
            [[0, 0], [8 * 64, 0]],
            [[2 * 64, 4 * 64], [8 * 64, 4 * 64]],
            [[2 * 64, 4 * 64], [8 * 64, 4 * 64]],
            [[5 * 64, 6 * 64], [8 * 64, 6 * 64]]
        ]

        self.initial_1 = [[64, 0], [5 * 64, 0],[4 * 64, 4 * 64], [8 * 64, 4 * 64],[6 * 64, 6 * 64]]

        self.list_2 = [

            [0, 0, 0, 0, 0, 1, 0, 1, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.boundary_2 = [
            [[0, 0], [9 * 64, 0]],
            [[0, 0], [9 * 64, 0]],
            [[0, 2 * 64], [9 * 64, 2 * 64]],
            [[0, 2 * 64], [9 * 64, 2 * 64]],
            [[2 * 64, 6 * 64], [9 * 64, 6 * 64]],
            [[2 * 64, 6 * 64], [9 * 64, 6 * 64]],
            [[0, 8 * 64], [9 * 64, 8 * 64]],
        ]

        self.initial_2 = [[64, 0], [5 * 64, 0], [3 * 64, 2 * 64], [5 * 64, 2 * 64], [3 * 64, 6 * 64], [5 * 64, 6 * 64],[4 * 64, 8 * 64] ]

    def get_original_position(self, level):

        if (level == 1):
            return self.initial_1
        elif (level == 2):
            return self.initial_2

    def get_object_list(self, level):

        if(level == 1):
            return self.list_1
        elif (level == 2):
            return self.list_2

    def get_object_boundary(self, level):

        if (level == 1):
            return self.boundary_1
        elif (level == 2):
            return self.boundary_2
class ManaObject(object):

    def __init__(self):

        self.list_1 = [

            [1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.initial_1 = [[3 * 64, 8 * 64], [6 * 64, 6 * 64],[0 * 64, 0 * 64], [1 * 64, 0 * 64]]

        self.list_2 = [

            [0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 1, 1, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.initial_2 = [[1 * 64, 8 * 64], [6 * 64, 6 * 64], [7 * 64, 6 * 64], [3 * 64, 2 * 64],[4 * 64, 2 * 64],[5 * 64, 0 * 64], [6 * 64, 0 * 64]]

    def get_original_position(self, level):

        if (level == 1):
            return self.initial_1
        elif (level == 2):
            return self.initial_2

    def get_object_list(self, level):

        if(level == 1):
            return self.list_1
        elif (level == 2):
            return self.list_2
class BgObject(object):

    def __init__(self):

        self.list_1 = [
            [3, 3, 3, 3, 3, 3, 3, 3, 3, 2],
            [4, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [4, 3, 3, 3, 3, 3, 3, 3, 3, 3],
            [0, 0, 4, 0, 0, 0, 3, 3, 3, 3],
            [3, 3, 4, 3, 3, 3, 3, 3, 3, 3],
            [0, 0, 0, 0, 1, 4, 1, 0, 0, 1],
            [3, 3, 3, 3, 3, 4, 3, 3, 3, 3],
            [3, 3, 3, 3, 3, 1, 1, 0, 0, 4],
            [3, 3, 3, 3, 3, 3, 3, 3, 3, 4],
            [0, 1, 0, 0, 1, 1, 0, 1, 1, 0]
        ]

        self.list_2 = [
            [2, 3, 3, 3, 3, 3, 3, 3, 3, 3],
            [1, 0, 0, 0, 0, 0, 0, 0, 4, 0],
            [3, 3, 3, 3, 3, 3, 3, 3, 4, 3],
            [3, 0, 4, 0, 0, 0, 0, 0, 0, 0],
            [3, 3, 4, 3, 3, 3, 3, 3, 3, 3],
            [3, 3, 4, 3, 3, 3, 3, 3, 3, 3],
            [3, 3, 4, 3, 3, 3, 3, 3, 3, 3],
            [3, 3, 0, 0, 0, 1, 1, 0, 0, 4],
            [3, 3, 3, 3, 3, 3, 3, 3, 3, 4],
            [0, 1, 0, 0, 1, 1, 0, 1, 1, 0]
        ]

    def get_object_list(self, level):

        if(level == 1):
            return self.list_1
        elif(level == 2):
            return self.list_2

Besides the above, we also need to make sure to change the number under the create enemy method of the enemy sprite class for level 2.

    def create_enemy(self, level):

        self.enemy_boundary_list = self.enemy_object.get_object_boundary(level)
        self.enemy_original_position = self.enemy_object.get_original_position(level)

        i = 0
        if(level == 1):
            while(i < 5):
                self.total_enemy_list.append(Enemy(self.enemy_boundary_list[i], self.enemy_original_position[i]))
                i += 1
        elif (level == 2):
            while (i < 7):
                self.total_enemy_list.append(Enemy(self.enemy_boundary_list[i], self.enemy_original_position[i]))
                i += 1

The same goes to the create mana method of the mana sprite class.

    def create_mana(self, level):

        self.mana_original_position = self.mana_object.get_original_position(level)

        i = 0
        if(level == 1):
            while(i < 4):
                self.total_mana_list.append(Mana(self.mana_original_position[i]))
                i += 1
        elif (level == 2):
            while (i < 7):
                self.total_mana_list.append(Mana(self.mana_original_position[i]))
                i += 1

If you run the above program again you will see this result.

Basically this project is almost completed, just a few touch up need to be done so stay tune for the next chapter.

Our greatest glory is not in never falling, but in rising every time we fall

Welcome back to this new pygame project. In this chapter we will win and get to the next level of the game, if we lose then we will return to the beginning of that level. In the previous chapter, we have passed the game manager object to the boy sprite object so that boy sprite object can use that game manager to reset the game when it is game over or to increase the game level when that player had won the game. In this chapter, we will use the level manager object to replace the game manager object so the boy sprite object will directly call the level manager to reset the game or to increase the level of the game accordingly. In order to use this system, we will need to edit a few files. The first one is the game manager class where we will pass in the level manager to the boy sprite object.

from EnemyManager import EnemyManager
from Overlap import Overlap
from ExplosionManager import ExplosionManager
from Score import Score
from StartScene import StartScene
from pygame.locals import *
from LevelManager import LevelManager
import pygame
import webbrowser
from Scene import Scene
from BackGroundSprite import BackGroundSprite
from BoySprite import BoySprite
from ManaManager import ManaManager

class GameManager(object):

    def __init__(self, scene):

        self.scene = scene
        self.load_music()
        self.play_music()
        self.overlap_manager = Overlap()
        self.level_manager = LevelManager(self)
        self.level_manager.set_level()
        self.setup(self.level_manager.get_level())
        self.start_scene = StartScene(scene, self.level_manager)
        self.pause = False # flag to pause the game
        self.game_scene = Scene(self.scene)

        #game state
        self.LOAD = 0
        self.GAME = 1
        self.OVER = 2
        self.NEXT = 3
        self.WIN = 4
        self.ABOUT = 5
        self.MANUAL = 6
        self.PAUSE = 7
        self.SCORE = 8
        self.SCENE = 9

        self.state = self.LOAD

    def setup(self, game_level):

        self.game_level = game_level
        self.score_manager = Score(self.scene, self.level_manager)
        self.background = BackGroundSprite(game_level, self.scene)
        self.enemy_manager = EnemyManager(self.scene, game_level)
        self.mana_manager = ManaManager(self.scene, game_level)
        self.boy_sprite = BoySprite(self.scene, game_level, self.enemy_manager, self.mana_manager, self.level_manager)
        self.explosion_manager = ExplosionManager(self.scene)

    def loop(self):

        if(self.state == self.LOAD):
            self.start_scene.draw(self.state)
        elif(self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN or self.state == self.ABOUT or self.state == self.MANUAL or self.state == self.SCORE):
            self.start_scene.draw(self.state)
        elif(self.state == self.SCENE):
            self.game_scene.draw()
        elif(self.state == self.GAME):

            self.update()
            self.draw()

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

            self.start_scene.draw(self.state)

    def isAreaClick(self, x, y):
        if (self.state == self.LOAD or self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN or self.state == self.ABOUT or self.state == self.SCORE or self.state == self.SCENE or self.state == self.MANUAL or self.state == self.PAUSE):
            self.rect = Rect(177, 274, 306, 112) # the position of the play button on the scene
            self.rect_play = Rect(229, 200, 200, 53)  # the position of the play button on the home scene
            self.rect_about = Rect(229, 263, 200, 53)  # the position of the about button on the home scene
            #self.rect_exit = Rect(229, 456, 200, 53)  # the position of the exit button on the home scene
            self.rect_pause_home = Rect(229, 263, 200, 53)  # the position of the home button on pause scene
            self.rect_score = Rect(229, 328, 200, 53)  # the position of the score button on the home scene
            self.rect_manual = Rect(229, 393, 200, 53)  # the position of the manual button on the home scene
            self.rect_scene = Rect(229, 519, 200, 53)  # the position of the manual button on the home scene
            self.rect_back = Rect(10, 620, 40, 30)  # the position of the back button on the home scene
            self.rect_sound = Rect(10, 600, 30, 30) # the position of the sound button on the home scene
            self.rect_scene_next = Rect(610, 330, 30, 30)  # the position of the next scene button on scene
            self.rect_scene_previous = Rect(50, 330, 30, 30)  # the position of the previous scene button on scene

            if(self.rect.collidepoint(x, y) and (self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN)):
                self.state = self.GAME
            elif(self.rect_play.collidepoint(x,y) and self.state == self.LOAD):
                self.state = self.GAME
            elif (self.rect_play.collidepoint(x, y) and self.state == self.PAUSE):
                self.state = self.GAME
            elif (self.rect_about.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.ABOUT
            elif (self.rect_score.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.SCORE
            elif (self.rect_scene.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.SCENE
            elif (self.rect_back.collidepoint(x, y) and self.state == self.SCENE):
                self.state = self.LOAD
            elif (self.rect_scene_next.collidepoint(x, y) and self.state == self.SCENE):
                self.game_scene.set_next_image()
            elif (self.rect_scene_previous.collidepoint(x, y) and self.state == self.SCENE):
                self.game_scene.set_previous_image()
            elif (self.rect_pause_home.collidepoint(x, y) and self.state == self.PAUSE):

                self.state = self.LOAD
                self.setup(self.level_manager.get_level())
                self.save_level()

            elif (self.rect_manual.collidepoint(x, y) and self.state == self.LOAD):
                webbrowser.open_new('http://gamingdirectional.com/blog/2018/12/25/air-strike//')
            elif (self.rect_back.collidepoint(x, y) and (self.state == self.ABOUT or self.state == self.MANUAL or self.state == self.SCORE)):
                self.state = self.LOAD
            elif (self.rect_sound.collidepoint(x, y) and self.state == self.LOAD):

                if(self.start_scene.soundon == True):
                    self.start_scene.soundon = False
                    pygame.mixer_music.pause()
                else:
                    self.start_scene.soundon = True
                    pygame.mixer_music.unpause()

    def save_level(self):
        self.level_manager.save_level()

    def set_pause(self, pause):

        self.pause = pause
        if(self.pause == True):

            self.state = self.PAUSE

    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.boy_sprite.setX(_x)

    def save_scene(self):
        self.game_scene.take_screen()

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

    def update(self):
        self.enemy_manager.update()
        self.mana_manager.update()
        self.boy_sprite.update()

    def draw(self):
        if(self.state == self.GAME):
            self.background.draw()
            #self.score_manager.draw()
            self.boy_sprite.draw()
            self.enemy_manager.draw()
            self.mana_manager.draw()
            pygame.display.flip()

The next few files we are going to edit are the boy object, mana object, background object and the enemy object class where we will include the level 2 location data and the items data to each of them. In this example, we will use back the level 1 data just to demonstrate the level up process!

class BoyObject(object):

    def __init__(self):

        self.list_1 = [

            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.ladder_boundary_1 = [[9 * 64, 8 * 64],
                                  [9 * 64, 7 * 64],
                                  [5 * 64, 6 * 64],
                                  [5 * 64, 5 * 64],
                                  [2 * 64, 3 * 64],
                                  [2 * 64, 4 * 64],
                                  [0 * 64, 1 * 64],
                                  [0 * 64, 2 * 64],
                                  ] # the boundary of the ladder

        self.boundary_bottom_1 = [[9 * 64, 9 * 64],
                                  [5 * 64, 7 * 64],
                                  [2 * 64, 5 * 64],
                                  [0 * 64, 3 * 64]]  # the bottom boundary of the ladder

        self.boundary_side_1 = [[4 * 64, 6 * 64],
                                [1 * 64, 4 * 64],
                                [6 * 64, 2 * 64], ]  # the side boundary of the player

        self.boundary_door_1 = [[9 * 64, 0]]

        self.initial_1 = [0, 8 * 64]

        self.list_2 = [

            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.ladder_boundary_2 = [[9 * 64, 8 * 64],
                                  [9 * 64, 7 * 64],
                                  [5 * 64, 6 * 64],
                                  [5 * 64, 5 * 64],
                                  [2 * 64, 3 * 64],
                                  [2 * 64, 4 * 64],
                                  [0 * 64, 1 * 64],
                                  [0 * 64, 2 * 64],
                                  ]  # the boundary of the ladder

        self.boundary_bottom_2 = [[9 * 64, 9 * 64],
                                  [5 * 64, 7 * 64],
                                  [2 * 64, 5 * 64],
                                  [0 * 64, 3 * 64]]  # the bottom boundary of the ladder

        self.boundary_side_2 = [[4 * 64, 6 * 64],
                                [1 * 64, 4 * 64],
                                [6 * 64, 2 * 64], ]  # the side boundary of the player

        self.boundary_door_2 = [[9 * 64, 0]]

        self.initial_2 = [0, 8 * 64]

    def get_original_position(self, level):

        if (level == 1):
            return self.initial_1
        elif (level == 2):
            return self.initial_2

    def get_object_list(self, level):

        if(level == 1):
            return self.list_1
        elif (level == 2):
            return self.list_2

    def get_object_boundary(self, level):

        if (level == 1):
            return self.ladder_boundary_1
        elif (level == 2):
            return self.ladder_boundary_2

    def get_object_bottom_boundary(self, level):

        if (level == 1):
            return self.boundary_bottom_1
        elif (level == 2):
            return self.boundary_bottom_2

    def get_object_side_boundary(self, level):

        if (level == 1):
            return self.boundary_side_1
        elif (level == 2):
            return self.boundary_side_2

    def get_object_door_boundary(self, level):

        if(level == 1):
            return self.boundary_door_1
        elif (level == 2):
            return self.boundary_door_2
class BgObject(object):

    def __init__(self):

        self.list_1 = [
            [3, 3, 3, 3, 3, 3, 3, 3, 3, 2],
            [4, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [4, 3, 3, 3, 3, 3, 3, 3, 3, 3],
            [0, 0, 4, 0, 0, 0, 3, 3, 3, 3],
            [3, 3, 4, 3, 3, 3, 3, 3, 3, 3],
            [0, 0, 0, 0, 1, 4, 1, 0, 0, 1],
            [3, 3, 3, 3, 3, 4, 3, 3, 3, 3],
            [3, 3, 3, 3, 3, 1, 1, 0, 0, 4],
            [3, 3, 3, 3, 3, 3, 3, 3, 3, 4],
            [0, 1, 0, 0, 1, 1, 0, 1, 1, 0]
        ]

        self.list_2 = [
            [3, 3, 3, 3, 3, 3, 3, 3, 3, 2],
            [4, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [4, 3, 3, 3, 3, 3, 3, 3, 3, 3],
            [0, 0, 4, 0, 0, 0, 3, 3, 3, 3],
            [3, 3, 4, 3, 3, 3, 3, 3, 3, 3],
            [0, 0, 0, 0, 1, 4, 1, 0, 0, 1],
            [3, 3, 3, 3, 3, 4, 3, 3, 3, 3],
            [3, 3, 3, 3, 3, 1, 1, 0, 0, 4],
            [3, 3, 3, 3, 3, 3, 3, 3, 3, 4],
            [0, 1, 0, 0, 1, 1, 0, 1, 1, 0]
        ]

    def get_object_list(self, level):

        if(level == 1):
            return self.list_1
        elif(level == 2):
            return self.list_2
class EnemyObject(object):

    def __init__(self):

        self.list_1 = [

            [0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 1, 0, 0, 0, 1, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.boundary_1 = [
            [[0, 0], [8 * 64, 0]],
            [[0, 0], [8 * 64, 0]],
            [[2 * 64, 4 * 64], [8 * 64, 4 * 64]],
            [[2 * 64, 4 * 64], [8 * 64, 4 * 64]],
            [[5 * 64, 6 * 64], [8 * 64, 6 * 64]]
        ]

        self.initial_1 = [[64, 0], [5 * 64, 0],[4 * 64, 4 * 64], [8 * 64, 4 * 64],[6 * 64, 6 * 64]]

        self.list_2 = [

            [0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 1, 0, 0, 0, 1, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.boundary_2 = [
            [[0, 0], [8 * 64, 0]],
            [[0, 0], [8 * 64, 0]],
            [[2 * 64, 4 * 64], [8 * 64, 4 * 64]],
            [[2 * 64, 4 * 64], [8 * 64, 4 * 64]],
            [[5 * 64, 6 * 64], [8 * 64, 6 * 64]]
        ]

        self.initial_2 = [[64, 0], [5 * 64, 0], [4 * 64, 4 * 64], [8 * 64, 4 * 64], [6 * 64, 6 * 64]]

    def get_original_position(self, level):

        if (level == 1):
            return self.initial_1
        elif (level == 2):
            return self.initial_2

    def get_object_list(self, level):

        if(level == 1):
            return self.list_1
        elif (level == 2):
            return self.list_2

    def get_object_boundary(self, level):

        if (level == 1):
            return self.boundary_1
        elif (level == 2):
            return self.boundary_2
class ManaObject(object):

    def __init__(self):

        self.list_1 = [

            [1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.initial_1 = [[3 * 64, 8 * 64], [6 * 64, 6 * 64],[0 * 64, 0 * 64], [1 * 64, 0 * 64]]

        self.list_2 = [

            [1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.initial_2 = [[3 * 64, 8 * 64], [6 * 64, 6 * 64], [0 * 64, 0 * 64], [1 * 64, 0 * 64]]

    def get_original_position(self, level):

        if (level == 1):
            return self.initial_1
        elif (level == 2):
            return self.initial_2

    def get_object_list(self, level):

        if(level == 1):
            return self.list_1
        elif (level == 2):
            return self.list_2

Anther three files we need to edit are the boy sprite class, enemy sprite class and the mana sprite class. In the boy sprite class, we will either reset the game if it is game over or increase the level if the player had won the game. In both the mana and the enemy sprite class we will create the object list for the level 2 stage.

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

class BoySprite(object):

    def __init__(self, scene, level, enemy_manager, mana_manager, level_manager):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height
        self.level = level # current game level
        self.enemy_manager = enemy_manager # the reference of enemy manager
        self.mana_manager = mana_manager # the reference of mana manager
        self.WIDTH = 640
        self.level_manager = level_manager
        self.prepare_boy(self.level)

    def prepare_boy(self, level):
        self.boy_object = BoyObject()
        self.boy_object_list = self.boy_object.get_object_list(level)
        self.boy_original_position = self.boy_object.get_original_position(level)
        self.x = self.boy_original_position[0]
        self.y = self.boy_original_position[1]
        self.speed = 2
        self.boy_image_sprite_right = 'Asset/bright.png'
        self.boy_image_sprite_left = 'Asset/bleft.png'
        self.boy_sprite = self.boy_image_sprite_right
        self.frame = 3
        self.up = False
        self.ladder = False
        self.left = False
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()
        self.boy_ladder_list = self.boy_object.get_object_boundary(level)
        self.boy_bottom_boundary_list = self.boy_object.get_object_bottom_boundary(level)
        self.boy_side_boundary_list = self.boy_object.get_object_side_boundary(level)
        self.boy_door_boundary_list = self.boy_object.get_object_door_boundary(level)
        self.enemy_list = self.enemy_manager.get_enemy_list()
        self.mana_list = self.mana_manager.get_mana_list()
        self.life = 1
        self.initialize()

    # set the x and the y direction for the player object

    def setX(self, x):

        if(self.ladder == True):
            return
        self.x += x
        if (self.up == True and x < 0):
            self.frame = 1
            self.up = False
        elif(self.up == True and x > 0):
            self.frame = 0
            self.up = False
        if(x < 0):
            self.left = True
            self.frame += 1
            if (self.frame > 5):
                self.frame = 1
            self.boy_sprite = self.boy_image_sprite_left
        elif(x > 0):
            self.frame += 1
            self.left = False
            if (self.frame > 4):
                self.frame = 0
            self.boy_sprite = self.boy_image_sprite_right
        elif(x == 0):
            if(self.left == True):
                self.frame = 2
                self.boy_sprite = self.boy_image_sprite_left
            elif(self.left == False):
                self.frame = 3
                self.boy_sprite = self.boy_image_sprite_right
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def setY(self, y):

        self.boy_rect = Rect(self.x, self.y+y, 64, 64)
        if(self.isUpDown(self.boy_rect, y) == True):
            self.y += y
        if(y == 0):
            self.frame = 9
        elif(self.up == False):
            self.frame = 6
            self.up = True
        else:
            if(y < 0):
                self.frame -= 1
            elif(y > 0):
                self.frame += 1
            if(self.frame > 10):
                self.frame = 6
            elif(self.frame < 6):
                self.frame += 2
        self.boy_sprite = self.boy_image_sprite_right
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def checkboundary(self):

        if(self.x < 0):
            self.x = 0
        elif(self.x > self.WIDTH - self.space):
            self.x = self.WIDTH - self.space
        else:
            self.isLeftRight()

    def isUpDown(self, rect, y):

        for boundary in self.boy_ladder_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            if ((boundary_rect.collidepoint(self.x, self.y+y) == True or boundary_rect.collidepoint(self.x, self.y+self.space+y) == True) and (self.x % self.space == 0)):
                for boundary_bottom in self.boy_bottom_boundary_list:
                    boundary_rect = Rect(boundary_bottom[0], boundary_bottom[1], 64, 64)
                    if (boundary_rect.colliderect(rect) == True):
                        self.ladder = False
                        return False
                self.ladder = True
                return True
        self.ladder = False
        return False

    def isLeftRight(self):

        for boundary in self.boy_side_boundary_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            boy_rect = Rect(self.x, self.y, 64, 64)
            if (boundary_rect.colliderect(boy_rect) == True):
                if(self.left == True):
                    self.x += self.speed
                else:
                    self.x -= self.speed

    def update(self):

        self.checkboundary()
        self.check_mana_collide()
        self.check_collide()
        self.check_win()
        self.move_boy()

    def check_win(self):
        for door in self.boy_door_boundary_list:
            if(door[0] == self.x and door[1] == self.y):
                self.level_manager.increase_level()

    def check_collide(self):
        for enemy in self.enemy_list:
            enemy_rect = Rect(enemy.x, enemy.y, 64, 64)
            boy_rect = Rect(self.x, self.y, 64, 64)
            if (enemy_rect.colliderect(boy_rect) == True and enemy.alive == True):
                if(self.life <= 0):
                    self.level_manager.reset_level()
                    return
                else:
                    self.life -= 1
                    enemy.alive = False

    def check_mana_collide(self):
        for mana in self.mana_list:
            mana_rect = Rect(mana.x, mana.y, 64, 64)
            if (mana_rect.collidepoint(self.x, self.y) == True):
                self.life += 1
                mana.alive = False
                return

    def move_boy(self):
        self.draw_pos = mt.Vector2(self.x, self.y)  # the position of the image on game scene

    def initialize(self):
        for row in range(self.row):
            for column in range(self.column):

                if(self.boy_object_list[row][column] == 1):

                    self.draw_pos = mt.Vector2(self.x, self.y)  # the vector position of the image on game scene
                    self.scene.blit(self.boy_surface, self.draw_pos)  # draw enemy frame

    def draw(self):

        self.scene.blit(self.boy_surface, self.draw_pos)  # draw boy frame
from EnemyObject import EnemyObject
from pygame import math as mt
from Enemy import Enemy

class EnemySprite(object):

    def __init__(self, level, scene):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height

        self.level = level # current game level

        self.total_enemy_list = []

        self.enemy_object = EnemyObject()

        self.create_enemy(level)

    def create_enemy(self, level):

        self.enemy_boundary_list = self.enemy_object.get_object_boundary(level)
        self.enemy_original_position = self.enemy_object.get_original_position(level)

        i = 0
        if(level == 1):
            while(i < 5):
                self.total_enemy_list.append(Enemy(self.enemy_boundary_list[i], self.enemy_original_position[i]))
                i += 1
        elif (level == 2):
            while (i < 5):
                self.total_enemy_list.append(Enemy(self.enemy_boundary_list[i], self.enemy_original_position[i]))
                i += 1

    def update(self):
        for enemy in self.total_enemy_list:
            if (enemy.alive == True):
                enemy.update()

    def draw(self):
        self.counter = 0
        for row in range(self.row):

            for column in range(self.column):

                if(self.enemy_list[row][column] == 1):

                    self.enemy = self.total_enemy_list[self.counter]

                    if(self.enemy.alive == True):

                        self.draw_pos = mt.Vector2(self.enemy.x, self.enemy.y)  # the position of the image on game scene
                        self.scene.blit(self.enemy.get_enemy_surface(), self.draw_pos)  # draw enemy frame

                    self.counter += 1

    def get_level(self, level):
        self.enemy_list = self.enemy_object.get_object_list(level)

    def get_enemy_list(self):
        return self.total_enemy_list
from pygame import math as mt
from Mana import Mana
from ManaObject import ManaObject

class ManaSprite(object):

    def __init__(self, level, scene):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height

        self.level = level # current game level

        self.total_mana_list = []

        self.mana_object = ManaObject()

        self.create_mana(level)

    def create_mana(self, level):

        self.mana_original_position = self.mana_object.get_original_position(level)

        i = 0
        if(level == 1):
            while(i < 4):
                self.total_mana_list.append(Mana(self.mana_original_position[i]))
                i += 1
        elif (level == 2):
            while (i < 4):
                self.total_mana_list.append(Mana(self.mana_original_position[i]))
                i += 1

    def update(self):

        for mana in self.total_mana_list:
            mana.update()

    def draw(self):
        self.counter = 0
        for row in range(self.row):

            for column in range(self.column):

                if(self.mana_list[row][column] == 1):

                    self.mana = self.total_mana_list[self.counter]
                    if(self.mana.alive == True):
                        self.draw_pos = mt.Vector2(self.mana.x - self.mana.get_width()/7, self.mana.y - self.mana.get_height()/7)  # the position of the image on game scene
                        self.scene.blit(self.mana.get_mana_surface(), self.draw_pos)  # draw mana object
                    self.counter += 1

    def get_level(self, level):
        self.mana_list = self.mana_object.get_object_list(level)

    def get_mana_list(self):
        return self.total_mana_list

The last file we need to edit is the level manager class which is also the engine to move this entire game.

import pickle

class LevelManager(object):

    def __init__(self, gm):

        self.game_manager = gm
        self.delete_line = False
        self.MAX_LEVEL = 2
        self.level = 1
        self.level_list = []

    def set_level(self):

        try:

            f = open("level.pickle", "rb")
            self.level_list = pickle.load(f)
            self.level = self.level_list[len(self.level_list) - 1]
            if (len(self.level_list) > 5):
                self.level_list.pop(0)

        except EOFError:
            self.level = 1
            self.level_list.append(self.level)

    def save_level(self):
        try:
            self.level_list.append(self.level)
            if(len(self.level_list) > 5):
                self.level_list.pop(0)
            f = open("level.pickle", "wb")
            pickle.dump(self.level_list, f)
            f.close()
        except IOError:
            print('cannot open a file')

    def increase_level(self):

        self.level += 1
        if(self.level >  self.MAX_LEVEL):
            #self.game_manager.state = self.game_manager.WIN
            self.level = 1
            self.game_manager.setup(self.level)
        else:
            #self.game_manager.state = self.game_manager.NEXT
            self.game_manager.setup(self.level)

    def get_level(self):

        return self.level

    def reset_level(self):

        self.game_manager.setup(self.level)

    def get_list(self):

        return self.level_list

I am not sure yet whether if we create a new level in such a manner will it leads to more CPU consumption or not, so do leave your comment below this post if you have a better idea.

Like, share or follow me on twitter. If you would like to support the continued development of this project do consider to donate to this website through the donation form located on the sidebar of this website.

I have been a little bit lazy lately but hopefully in the future I will work harder and write more articles per week just to please you all.

Rotate the mana object

In this chapter, we will continue to develop the mana object. We will rotate the mana object on each update. If you still remember that we have created an update method under the mana class then in this chapter we will update the rotation angle position of that mana object accordingly on each update under this method. We will also create the get height and get width method so that mana object will return both the width and the height of that mana object that will be used by the mana sprite class to calculate the new position of the mana object on the game scene before drawing it. We also used the clock object from the pygame.time module to control the speed of rotation.

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

class Mana(object):

    def __init__(self, original_position_list):

        self.count = 0

        #original location for mana object

        self.x = original_position_list[0]
        self.y = original_position_list[1]

        self.alive = True

        # the width and height of mana
        self.w = 64
        self.h = 64

        self.clock = pygame.time.Clock()
        self.rotation = 0. # the rotation angle of the mana
        self.rotation_speed = 360.  # 360 degrees per second
        self.rotation_direction = 1.0

        self.mana_image_sprite_right = 'Asset/right.png'

        self.create_surface(self.mana_image_sprite_right)

    def create_surface(self, mana_image_sprite):

        self.mana_rect = Rect(7 * 64, 0, 64, 64)
        self.sprite = GameSprite(mana_image_sprite, self.mana_rect)
        self.sprite_surface = self.sprite.getImage()
        self.rotated_surface = self.sprite_surface # the mana rotate surface which will be returned by the mana object

    def update(self):

        self.rotated_surface = pygame.transform.rotate(self.sprite_surface, self.rotation ) # Return the rotated mana surface object
        self.w, self.h = self.rotated_surface.get_size()

        self.time_passed_seconds = (self.clock.tick())/ 2600.0

        self.rotation += self.rotation_direction * self.rotation_speed * self.time_passed_seconds

    def get_mana_surface(self):

        return self.rotated_surface

    def get_width(self):

        return self.w

    def get_height(self):

        return self.h

Finally, we will edit the mana sprite file accordingly to draw the rotating mana object on the game scene.

from pygame import math as mt
from Mana import Mana
from ManaObject import ManaObject

class ManaSprite(object):

    def __init__(self, level, scene):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height

        self.level = level # current game level

        self.total_mana_list = []

        self.mana_object = ManaObject()

        self.create_mana(level)

    def create_mana(self, level):

        self.mana_original_position = self.mana_object.get_original_position(level)

        i = 0
        if(level == 1):
            while(i < 4):
                self.total_mana_list.append(Mana(self.mana_original_position[i]))
                i += 1

    def update(self):

        for mana in self.total_mana_list:
            mana.update()

    def draw(self):
        self.counter = 0
        for row in range(self.row):

            for column in range(self.column):

                if(self.mana_list[row][column] == 1):

                    self.mana = self.total_mana_list[self.counter]
                    if(self.mana.alive == True):
                        self.draw_pos = mt.Vector2(self.mana.x - self.mana.get_width()/7, self.mana.y - self.mana.get_height()/7)  # the position of the image on game scene
                        self.scene.blit(self.mana.get_mana_surface(), self.draw_pos)  # draw mana object
                    self.counter += 1

    def get_level(self, level):
        self.mana_list = self.mana_object.get_object_list(level)

    def get_mana_list(self):
        return self.total_mana_list

Here is the product of the above program.

The mana detection mechanism

Finally, in this chapter, we will look at the mana detection mechanism where when the player has overlapped mana he will gain 1 unit of life so when he hits the enemy he can continue to move onward after he has used that 1 unit of life to heal himself. We will also remove the enemy from the scene after it has collided with the player. In order to create such a system, we need to edit a few files. The first file we need to edit is the enemy file where we will just add in the alive flag to indicate whether that enemy is alive or not, if that enemy did not collide with the boy then it is alive.

from pygame.locals import *
from GameSprite import GameSprite

class Enemy(object):

    def __init__(self, boundary_list, original_position_list):

        self.count = -1
        self.forward = False
        self.timer = 0
        self.right = True
        self.switch_timer = 900
        self.switch_timer_left = 900
        self.sprite_frame_list_right = []
        self.sprite_frame_list_left = []

        #boundary for enemy object
        self.left_boundary = Rect(boundary_list[0][0], boundary_list[0][1], 64, 64)
        self.right_boundary = Rect(boundary_list[1][0], boundary_list[1][1], 64, 64)

        self.x = original_position_list[0]
        self.y = original_position_list[1]
        self.alive = True

        self.enemy_image_sprite_right = 'Asset/right.png'
        self.enemy_image_sprite_left = 'Asset/left.png'

        self.sprite_frame_list = self.create_surface(self.enemy_image_sprite_right)

    def create_surface(self, enemy_image_sprite):

        if(self.right == True and len(self.sprite_frame_list_right) > 0):
            return self.sprite_frame_list_right
        elif (self.right == True and len(self.sprite_frame_list_right) <= 0):
            self.sprite_frame_list_right = self.create_sub_surface(enemy_image_sprite, self.sprite_frame_list_right)
            return self.sprite_frame_list_right
        elif(self.right == False and len(self.sprite_frame_list_left) > 0):
            return self.sprite_frame_list_left
        elif (self.right == False and len(self.sprite_frame_list_left) <= 0):
            self.sprite_frame_list_left = self.create_sub_surface(enemy_image_sprite, self.sprite_frame_list_left)
            return self.sprite_frame_list_left

    def create_sub_surface(self, enemy_image_sprite, sprite_frame_list):
        # the first frame
        self.frame_1_rect = Rect(0, 0, 64, 64)
        self.sprite_frame_1 = GameSprite(enemy_image_sprite, self.frame_1_rect)
        self.sprite_frame_1_surface = self.sprite_frame_1.getImage()
        sprite_frame_list.append(self.sprite_frame_1_surface)
        # the second frame
        self.frame_2_rect = Rect(64, 0, 64, 64)
        self.sprite_frame_2 = GameSprite(enemy_image_sprite, self.frame_2_rect)
        self.sprite_frame_2_surface = self.sprite_frame_2.getImage()
        sprite_frame_list.append(self.sprite_frame_2_surface)
        # the third frame
        self.frame_3_rect = Rect(64 * 2, 0, 64, 64)
        self.sprite_frame_3 = GameSprite(enemy_image_sprite, self.frame_3_rect)
        self.sprite_frame_3_surface = self.sprite_frame_3.getImage()
        sprite_frame_list.append(self.sprite_frame_3_surface)
        # the fourth frame
        self.frame_4_rect = Rect(64 * 3, 0, 64, 64)
        self.sprite_frame_4 = GameSprite(enemy_image_sprite, self.frame_4_rect)
        self.sprite_frame_4_surface = self.sprite_frame_4.getImage()
        sprite_frame_list.append(self.sprite_frame_4_surface)
        # the fifth frame
        self.frame_5_rect = Rect(64 * 4, 0, 64, 64)
        self.sprite_frame_5 = GameSprite(enemy_image_sprite, self.frame_5_rect)
        self.sprite_frame_5_surface = self.sprite_frame_5.getImage()
        sprite_frame_list.append(self.sprite_frame_5_surface)
        # the sixth frame
        self.frame_6_rect = Rect(64 * 5, 0, 64, 64)
        self.sprite_frame_6 = GameSprite(enemy_image_sprite, self.frame_6_rect)
        self.sprite_frame_6_surface = self.sprite_frame_6.getImage()
        sprite_frame_list.append(self.sprite_frame_6_surface)
        # the seventh frame
        self.frame_7_rect = Rect(64 * 6, 0, 64, 64)
        self.sprite_frame_7 = GameSprite(enemy_image_sprite, self.frame_7_rect)
        self.sprite_frame_7_surface = self.sprite_frame_7.getImage()
        sprite_frame_list.append(self.sprite_frame_7_surface)

        return sprite_frame_list

    def update(self):
        self.checkboundary()
        self.change_graphic()
        self.move_x()

    def checkboundary(self):
        if(self.left_boundary.collidepoint(self.x, self.y)):
            self.right = False
            self.x += 0.2
            self.sprite_frame_list = self.create_surface(self.enemy_image_sprite_left)
        elif(self.right_boundary.collidepoint(self.x, self.y)):
            self.right = True
            self.x -= 0.2
            self.sprite_frame_list = self.create_surface(self.enemy_image_sprite_right)

    def move_x(self):
        if(self.right == True):
            self.x -= 0.2
        else:
            self.x += 0.2

    def change_graphic(self):
        if (self.right == True):
            if (self.timer > 26):
                if (self.count > 6 and self.forward == True):  # use this logic to control the counter and the image
                    self.count -= 1
                    self.forward = False
                elif (self.count < 1 and self.forward == False):
                    self.count += 1
                    self.forward = True
                elif (self.forward == False):
                    self.count -= 1
                elif (self.forward == True):
                    self.count += 1
                self.timer = 0
            else:
                self.timer += 1
        else:
            if (self.timer > 26):
                if (self.count > 5 and self.forward == True):  # use this logic to control the counter and the image
                    self.count -= 1
                    self.forward = False
                elif (self.count < 0 and self.forward == False):
                    self.count += 1
                    self.forward = True
                elif (self.forward == False):
                    self.count -= 1
                elif (self.forward == True):
                    self.count += 1
                self.timer = 0
            else:
                self.timer += 1

    def switch_position(self):

        if(self.switch_timer <= 0):
            self.right = False
            self.timer = 0
            self.count = 0
            self.switch_timer = 900
            self.sprite_frame_list=self.create_surface(self.enemy_image_sprite_left)
        elif (self.right == True and self.switch_timer > 0):
            self.switch_timer -= 1
        elif(self.right == False and self.switch_timer_left > 0):
            self.switch_timer_left -= 1
        elif(self.switch_timer_left <= 0):
            self.right = True
            self.timer = 0
            self.count = 0
            self.switch_timer_left = 900
            self.sprite_frame_list=self.create_surface(self.enemy_image_sprite_right)

    def get_enemy_surface(self):

        return self.sprite_frame_list[self.get_count()]

    def get_count(self):

        if(self.count < 1 and self.forward == False):
            self.count += 1
            self.forward = True
        elif(self.count > 6 and self.forward == True):
            self.count -= 1
            self.forward = False

        return self.count

Then the enemy sprite class will only update and draw that enemy if it is alive.

from EnemyObject import EnemyObject
from pygame import math as mt
from Enemy import Enemy

class EnemySprite(object):

    def __init__(self, level, scene):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height

        self.level = level # current game level

        self.total_enemy_list = []

        self.enemy_object = EnemyObject()

        self.create_enemy(level)

    def create_enemy(self, level):

        self.enemy_boundary_list = self.enemy_object.get_object_boundary(level)
        self.enemy_original_position = self.enemy_object.get_original_position(level)

        i = 0
        if(level == 1):
            while(i < 5):
                self.total_enemy_list.append(Enemy(self.enemy_boundary_list[i], self.enemy_original_position[i]))
                i += 1

    def update(self):
        for enemy in self.total_enemy_list:
            if (enemy.alive == True):
                enemy.update()

    def draw(self):
        self.counter = 0
        for row in range(self.row):

            for column in range(self.column):

                if(self.enemy_list[row][column] == 1):

                    self.enemy = self.total_enemy_list[self.counter]

                    if(self.enemy.alive == True):

                        self.draw_pos = mt.Vector2(self.enemy.x, self.enemy.y)  # the position of the image on game scene
                        self.scene.blit(self.enemy.get_enemy_surface(), self.draw_pos)  # draw enemy frame

                    self.counter += 1

    def get_level(self, level):
        self.enemy_list = self.enemy_object.get_object_list(level)

    def get_enemy_list(self):
        return self.total_enemy_list

The next file we need to edit is the mana file where we will again include the alive flag for mana as well.

from pygame.locals import *
from GameSprite import GameSprite

class Mana(object):

    def __init__(self, original_position_list):

        self.count = 0

        #original location for mana object

        self.x = original_position_list[0]
        self.y = original_position_list[1]

        self.alive = True

        self.mana_image_sprite_right = 'Asset/right.png'

        self.create_surface(self.mana_image_sprite_right)

    def create_surface(self, mana_image_sprite):

        self.mana_rect = Rect(7 * 64, 0, 64, 64)
        self.sprite = GameSprite(mana_image_sprite, self.mana_rect)
        self.sprite_surface = self.sprite.getImage()

    def update(self):
        pass

    def get_mana_surface(self):

        return self.sprite_surface

The next file we need to edit is the mana sprite file where that class will only draw the mana if it is alive. We have also added in the get mana list method which will be called by the mana manager class later on.

from pygame import math as mt
from Mana import Mana
from ManaObject import ManaObject

class ManaSprite(object):

    def __init__(self, level, scene):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height

        self.level = level # current game level

        self.total_mana_list = []

        self.mana_object = ManaObject()

        self.create_mana(level)

    def create_mana(self, level):

        self.mana_original_position = self.mana_object.get_original_position(level)

        i = 0
        if(level == 1):
            while(i < 4):
                self.total_mana_list.append(Mana(self.mana_original_position[i]))
                i += 1

    def update(self):

        for mana in self.total_mana_list:
            mana.update()

    def draw(self):
        self.counter = 0
        for row in range(self.row):

            for column in range(self.column):

                if(self.mana_list[row][column] == 1):

                    self.mana = self.total_mana_list[self.counter]
                    if(self.mana.alive == True):
                        self.draw_pos = mt.Vector2(self.mana.x, self.mana.y)  # the position of the image on game scene
                        self.scene.blit(self.mana.get_mana_surface(), self.draw_pos)  # draw mana object
                    self.counter += 1

    def get_level(self, level):
        self.mana_list = self.mana_object.get_object_list(level)

    def get_mana_list(self):
        return self.total_mana_list

Next is the mana manager class where we will include a new method call get mana list to return the list of mana objects from the mana sprite class where that mana list will later be used in the boy sprite class.

from ManaSprite import ManaSprite

class ManaManager(object):

    def __init__(self, scene, game_level):

        self.scene = scene
        self.level = game_level
        self.mana = ManaSprite(self.level, self.scene)
        self.create_mana()

    # get the mana location list for this level
    def create_mana(self):

        self.mana.get_level(self.level)

    def update(self):

        self.mana.update()

    def draw(self):

        self.mana.draw()

    def get_mana_list(self):

        return self.mana.get_mana_list()

The next file we need to edit is the boy sprite class where we will detect the mana-boy overlapping and detect the boy-enemy collision event accordingly.

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

class BoySprite(object):

    def __init__(self, scene, level, enemy_manager, mana_manager, game_manager):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height
        self.level = level # current game level
        self.enemy_manager = enemy_manager # the reference of enemy manager
        self.mana_manager = mana_manager # the reference of mana manager
        self.WIDTH = 640
        self.game_manager = game_manager
        self.prepare_boy(self.level)

    def prepare_boy(self, level):
        self.boy_object = BoyObject()
        self.boy_object_list = self.boy_object.get_object_list(level)
        self.boy_original_position = self.boy_object.get_original_position(level)
        self.x = self.boy_original_position[0]
        self.y = self.boy_original_position[1]
        self.speed = 2
        self.boy_image_sprite_right = 'Asset/bright.png'
        self.boy_image_sprite_left = 'Asset/bleft.png'
        self.boy_sprite = self.boy_image_sprite_right
        self.frame = 3
        self.up = False
        self.ladder = False
        self.left = False
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()
        self.boy_ladder_list = self.boy_object.get_object_boundary(level)
        self.boy_bottom_boundary_list = self.boy_object.get_object_bottom_boundary(level)
        self.boy_side_boundary_list = self.boy_object.get_object_side_boundary(level)
        self.boy_door_boundary_list = self.boy_object.get_object_door_boundary(level)
        self.enemy_list = self.enemy_manager.get_enemy_list()
        self.mana_list = self.mana_manager.get_mana_list()
        self.life = 1
        self.initialize()

    # set the x and the y direction for the player object

    def setX(self, x):

        if(self.ladder == True):
            return
        self.x += x
        if (self.up == True and x < 0):
            self.frame = 1
            self.up = False
        elif(self.up == True and x > 0):
            self.frame = 0
            self.up = False
        if(x < 0):
            self.left = True
            self.frame += 1
            if (self.frame > 5):
                self.frame = 1
            self.boy_sprite = self.boy_image_sprite_left
        elif(x > 0):
            self.frame += 1
            self.left = False
            if (self.frame > 4):
                self.frame = 0
            self.boy_sprite = self.boy_image_sprite_right
        elif(x == 0):
            if(self.left == True):
                self.frame = 2
                self.boy_sprite = self.boy_image_sprite_left
            elif(self.left == False):
                self.frame = 3
                self.boy_sprite = self.boy_image_sprite_right
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def setY(self, y):

        self.boy_rect = Rect(self.x, self.y+y, 64, 64)
        if(self.isUpDown(self.boy_rect, y) == True):
            self.y += y
        if(y == 0):
            self.frame = 9
        elif(self.up == False):
            self.frame = 6
            self.up = True
        else:
            if(y < 0):
                self.frame -= 1
            elif(y > 0):
                self.frame += 1
            if(self.frame > 10):
                self.frame = 6
            elif(self.frame < 6):
                self.frame += 2
        self.boy_sprite = self.boy_image_sprite_right
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def checkboundary(self):

        if(self.x < 0):
            self.x = 0
        elif(self.x > self.WIDTH - self.space):
            self.x = self.WIDTH - self.space
        else:
            self.isLeftRight()

    def isUpDown(self, rect, y):

        for boundary in self.boy_ladder_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            if ((boundary_rect.collidepoint(self.x, self.y+y) == True or boundary_rect.collidepoint(self.x, self.y+self.space+y) == True) and (self.x % self.space == 0)):
                for boundary_bottom in self.boy_bottom_boundary_list:
                    boundary_rect = Rect(boundary_bottom[0], boundary_bottom[1], 64, 64)
                    if (boundary_rect.colliderect(rect) == True):
                        self.ladder = False
                        return False
                self.ladder = True
                return True
        self.ladder = False
        return False

    def isLeftRight(self):

        for boundary in self.boy_side_boundary_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            boy_rect = Rect(self.x, self.y, 64, 64)
            if (boundary_rect.colliderect(boy_rect) == True):
                if(self.left == True):
                    self.x += self.speed
                else:
                    self.x -= self.speed

    def update(self):
        self.checkboundary()
        self.check_mana_collide()
        self.check_collide()
        self.check_win()
        self.move_boy()

    def check_win(self):
        for door in self.boy_door_boundary_list:
            if(door[0] == self.x and door[1] == self.y):
                self.game_manager.setup(self.level)

    def check_collide(self):
        for enemy in self.enemy_list:
            enemy_rect = Rect(enemy.x, enemy.y, 64, 64)
            boy_rect = Rect(self.x, self.y, 64, 64)
            if (enemy_rect.colliderect(boy_rect) == True and enemy.alive == True):
                if(self.life <= 0):
                    self.game_manager.setup(self.level)
                    return
                else:
                    self.life -= 1
                    enemy.alive = False

    def check_mana_collide(self):
        for mana in self.mana_list:
            mana_rect = Rect(mana.x, mana.y, 64, 64)
            if (mana_rect.collidepoint(self.x, self.y) == True):
                self.life += 1
                mana.alive = False
                return

    def move_boy(self):
        self.draw_pos = mt.Vector2(self.x, self.y)  # the position of the image on game scene

    def initialize(self):
        for row in range(self.row):
            for column in range(self.column):

                if(self.boy_object_list[row][column] == 1):

                    self.draw_pos = mt.Vector2(self.x, self.y)  # the vector position of the image on game scene
                    self.scene.blit(self.boy_surface, self.draw_pos)  # draw enemy frame

    def draw(self):

        self.scene.blit(self.boy_surface, self.draw_pos)  # draw boy frame

The final file we need to edit is the game manager class where it will pass itself into the boy sprite so the boy sprite class can call the game manager setup method to reset the game after the boy has reached the door or the boy get hit by the enemy and it is game over.

from EnemyManager import EnemyManager
from Overlap import Overlap
from ExplosionManager import ExplosionManager
from Score import Score
from StartScene import StartScene
from pygame.locals import *
from LevelManager import LevelManager
import pygame
import webbrowser
from Scene import Scene
from BackGroundSprite import BackGroundSprite
from BoySprite import BoySprite
from ManaManager import ManaManager

class GameManager(object):

    def __init__(self, scene):

        self.scene = scene

        self.load_music()
        self.play_music()
        self.overlap_manager = Overlap()
        self.level_manager = LevelManager(self)
        self.level_manager.set_level()
        self.setup(self.level_manager.get_level())
        self.start_scene = StartScene(scene, self.level_manager)

        self.pause = False # flag to pause the game

        self.game_scene = Scene(self.scene)

        #game state
        self.LOAD = 0
        self.GAME = 1
        self.OVER = 2
        self.NEXT = 3
        self.WIN = 4
        self.ABOUT = 5
        self.MANUAL = 6
        self.PAUSE = 7
        self.SCORE = 8
        self.SCENE = 9

        self.state = self.LOAD

    def setup(self, game_level):

        self.game_level = game_level
        self.score_manager = Score(self.scene, self.level_manager)
        self.background = BackGroundSprite(game_level, self.scene)
        self.enemy_manager = EnemyManager(self.scene, game_level)
        self.mana_manager = ManaManager(self.scene, game_level)
        self.boy_sprite = BoySprite(self.scene, game_level, self.enemy_manager, self.mana_manager, self)
        self.explosion_manager = ExplosionManager(self.scene)

    def loop(self):

        if(self.state == self.LOAD):
            self.start_scene.draw(self.state)
        elif(self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN or self.state == self.ABOUT or self.state == self.MANUAL or self.state == self.SCORE):
            self.start_scene.draw(self.state)
        elif(self.state == self.SCENE):
            self.game_scene.draw()
        elif(self.state == self.GAME):

            self.update()
            self.draw()

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

            self.start_scene.draw(self.state)

    def isAreaClick(self, x, y):
        if (self.state == self.LOAD or self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN or self.state == self.ABOUT or self.state == self.SCORE or self.state == self.SCENE or self.state == self.MANUAL or self.state == self.PAUSE):
            self.rect = Rect(177, 274, 306, 112) # the position of the play button on the scene
            self.rect_play = Rect(229, 200, 200, 53)  # the position of the play button on the home scene
            self.rect_about = Rect(229, 263, 200, 53)  # the position of the about button on the home scene
            #self.rect_exit = Rect(229, 456, 200, 53)  # the position of the exit button on the home scene
            self.rect_pause_home = Rect(229, 263, 200, 53)  # the position of the home button on pause scene
            self.rect_score = Rect(229, 328, 200, 53)  # the position of the score button on the home scene
            self.rect_manual = Rect(229, 393, 200, 53)  # the position of the manual button on the home scene
            self.rect_scene = Rect(229, 519, 200, 53)  # the position of the manual button on the home scene
            self.rect_back = Rect(10, 620, 40, 30)  # the position of the back button on the home scene
            self.rect_sound = Rect(10, 600, 30, 30) # the position of the sound button on the home scene
            self.rect_scene_next = Rect(610, 330, 30, 30)  # the position of the next scene button on scene
            self.rect_scene_previous = Rect(50, 330, 30, 30)  # the position of the previous scene button on scene

            if(self.rect.collidepoint(x, y) and (self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN)):
                self.state = self.GAME
            elif(self.rect_play.collidepoint(x,y) and self.state == self.LOAD):
                self.state = self.GAME
            elif (self.rect_play.collidepoint(x, y) and self.state == self.PAUSE):
                self.state = self.GAME
            elif (self.rect_about.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.ABOUT
            elif (self.rect_score.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.SCORE
            elif (self.rect_scene.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.SCENE
            elif (self.rect_back.collidepoint(x, y) and self.state == self.SCENE):
                self.state = self.LOAD
            elif (self.rect_scene_next.collidepoint(x, y) and self.state == self.SCENE):
                self.game_scene.set_next_image()
            elif (self.rect_scene_previous.collidepoint(x, y) and self.state == self.SCENE):
                self.game_scene.set_previous_image()
            elif (self.rect_pause_home.collidepoint(x, y) and self.state == self.PAUSE):

                self.state = self.LOAD
                self.setup(self.level_manager.get_level())
                self.save_level()

            elif (self.rect_manual.collidepoint(x, y) and self.state == self.LOAD):
                webbrowser.open_new('http://gamingdirectional.com/blog/2018/12/25/air-strike//')
            elif (self.rect_back.collidepoint(x, y) and (self.state == self.ABOUT or self.state == self.MANUAL or self.state == self.SCORE)):
                self.state = self.LOAD
            elif (self.rect_sound.collidepoint(x, y) and self.state == self.LOAD):

                if(self.start_scene.soundon == True):
                    self.start_scene.soundon = False
                    pygame.mixer_music.pause()
                else:
                    self.start_scene.soundon = True
                    pygame.mixer_music.unpause()

    def save_level(self):
        self.level_manager.save_level()

    def set_pause(self, pause):

        self.pause = pause

        if(self.pause == True):

            self.state = self.PAUSE

    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.boy_sprite.setX(_x)

    def save_scene(self):
        self.game_scene.take_screen()

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

    def update(self):
        self.enemy_manager.update()
        self.mana_manager.update()
        self.boy_sprite.update()


    def draw(self):
        if(self.state == self.GAME):
            self.background.draw()
            #self.score_manager.draw()
            self.boy_sprite.draw()
            self.enemy_manager.draw()
            self.mana_manager.draw()
            pygame.display.flip()

If you run the above program then this is the outcome you will expect.

The above overlapping system will get further tune-up in the coming chapter. Like, share or following me on twitter. If you like this tutorial do consider to donate some bitcoin to this website to help me to ease the burden of hosting cost, thank you very much.

  • Bitcoin
  • Ethereum
  • Bitcoin cash
  • Litecoin
  • Stellar
Scan to Donate Bitcoin to 38han7NG6KHtxZsS4ppTwAtSw7UfLSY5Vd

Donate Bitcoin to this address

Scan the QR code or copy the address below into your wallet to send some Bitcoin

Scan to Donate Ethereum to 0x9Dfd0786c5fE998deebf6C86326bD036Ee2518c1

Donate Ethereum to this address

Scan the QR code or copy the address below into your wallet to send some Ethereum

Scan to Donate Bitcoin cash to qqegrlxc93q5ah0s2s6w9zxwf685vr26nu0kxlkvpc

Donate Bitcoin cash to this address

Scan the QR code or copy the address below into your wallet to send some Bitcoin cash

Scan to Donate Litecoin to MJJ2T1XyD4NtSjTA3NpcqTuaTaCKfT3fdA

Donate Litecoin to this address

Scan the QR code or copy the address below into your wallet to send some Litecoin

Scan to Donate Stellar to GAJRUOEMPNSHHR2ZB4KOOQ3MIR2BN54BBXGHTYA6QWMGST7AGI46WIHU

Donate Stellar to this address

Scan the QR code or copy the address below into your wallet to send some Stellar

Create the mana object with Pygame

Welcome back to our new pygame project. In this chapter, I will create the mana object to heal the player so he can continue to move forward after he has been hit by an enemy object. In this chapter, we will place the mana objects on the game scene and in the next chapter, we will deal with the player-mana overlapping mechanism. In order to place the mana object on the game scene, all we need is to create four new files. The first one is the mana object class which will contain the original position of all those mana objects on the game scene.

class ManaObject(object):

    def __init__(self):

        self.list_1 = [

            [1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.initial_1 = [[3 * 64, 8 * 64], [6 * 64, 6 * 64],[0 * 64, 0 * 64], [1 * 64, 0 * 64]]

    def get_original_position(self, level):

        if (level == 1):
            return self.initial_1

    def get_object_list(self, level):

        if(level == 1):
            return self.list_1

The second file which we will create is the mana class which holds the information for each individual mana.

from pygame.locals import *
from GameSprite import GameSprite

class Mana(object):

    def __init__(self, original_position_list):

        self.count = 0

        #original location for mana object

        self.x = original_position_list[0]
        self.y = original_position_list[1]

        self.mana_image_sprite_right = 'Asset/right.png'

        self.create_surface(self.mana_image_sprite_right)

    def create_surface(self, mana_image_sprite):

        self.mana_rect = Rect(7 * 64, 0, 64, 64)
        self.sprite = GameSprite(mana_image_sprite, self.mana_rect)
        self.sprite_surface = self.sprite.getImage()

    def update(self):
        pass

    def get_mana_surface(self):

        return self.sprite_surface

The next file is the mana sprite file which will control the individual mana object.

from pygame import math as mt
from Mana import Mana
from ManaObject import ManaObject

class ManaSprite(object):

    def __init__(self, level, scene):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height

        self.level = level # current game level

        self.total_mana_list = []

        self.mana_object = ManaObject()

        self.create_mana(level)

    def create_mana(self, level):

        self.mana_original_position = self.mana_object.get_original_position(level)

        i = 0
        if(level == 1):
            while(i < 4):
                self.total_mana_list.append(Mana(self.mana_original_position[i]))
                i += 1

    def update(self):

        for mana in self.total_mana_list:
            mana.update()

    def draw(self):
        self.counter = 0
        for row in range(self.row):

            for column in range(self.column):

                if(self.mana_list[row][column] == 1):

                    self.mana = self.total_mana_list[self.counter]

                    self.draw_pos = mt.Vector2(self.mana.x, self.mana.y)  # the position of the image on game scene

                    self.scene.blit(self.mana.get_mana_surface(), self.draw_pos)  # draw the mana object

                    self.counter += 1

    def get_level(self, level):
        self.mana_list = self.mana_object.get_object_list(level)

    def get_mana_list(self):
        return self.total_mana_list

The final file we need to create is the mana manager file where this class will call the mana sprite class to perform various jobs.

from ManaSprite import ManaSprite

class ManaManager(object):

    def __init__(self, scene, game_level):

        self.scene = scene
        self.level = game_level
        self.mana = ManaSprite(self.level, self.scene)
        self.create_mana()
        
    # get the mana location list for this level
    def create_mana(self):

        self.mana.get_level(self.level)

    def update(self):

        self.mana.update()

    def draw(self):

        self.mana.draw()

Then we will include the mana manager in the game manager file so we can call its update and draw method. At the moment we do not need to update anything yet but in the next chapter, we will once we are dealing with the overlapping detection mechanism between the mana and the player.

from EnemyManager import EnemyManager
from Overlap import Overlap
from ExplosionManager import ExplosionManager
from Score import Score
from StartScene import StartScene
from pygame.locals import *
from LevelManager import LevelManager
import pygame
import webbrowser
from Scene import Scene
from BackGroundSprite import BackGroundSprite
from BoySprite import BoySprite
from ManaManager import ManaManager

class GameManager(object):

    def __init__(self, scene):

        self.scene = scene

        self.load_music()
        self.play_music()
        self.overlap_manager = Overlap()
        self.level_manager = LevelManager(self)
        self.level_manager.set_level()
        self.setup(self.level_manager.get_level())
        self.start_scene = StartScene(scene, self.level_manager)

        self.pause = False # flag to pause the game

        self.game_scene = Scene(self.scene)

        #game state
        self.LOAD = 0
        self.GAME = 1
        self.OVER = 2
        self.NEXT = 3
        self.WIN = 4
        self.ABOUT = 5
        self.MANUAL = 6
        self.PAUSE = 7
        self.SCORE = 8
        self.SCENE = 9

        self.state = self.LOAD

    def setup(self, game_level):

        self.game_level = game_level
        self.score_manager = Score(self.scene, self.level_manager)
        self.background = BackGroundSprite(game_level, self.scene)
        self.enemy_manager = EnemyManager(self.scene, game_level)
        self.mana_manager = ManaManager(self.scene, game_level)
        self.boy_sprite = BoySprite(self.scene, game_level, self.enemy_manager)
        self.explosion_manager = ExplosionManager(self.scene)

    def loop(self):

        if(self.state == self.LOAD):
            self.start_scene.draw(self.state)
        elif(self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN or self.state == self.ABOUT or self.state == self.MANUAL or self.state == self.SCORE):
            self.start_scene.draw(self.state)
        elif(self.state == self.SCENE):
            self.game_scene.draw()
        elif(self.state == self.GAME):

            self.update()
            self.draw()

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

            self.start_scene.draw(self.state)

    def isAreaClick(self, x, y):
        if (self.state == self.LOAD or self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN or self.state == self.ABOUT or self.state == self.SCORE or self.state == self.SCENE or self.state == self.MANUAL or self.state == self.PAUSE):
            self.rect = Rect(177, 274, 306, 112) # the position of the play button on the scene
            self.rect_play = Rect(229, 200, 200, 53)  # the position of the play button on the home scene
            self.rect_about = Rect(229, 263, 200, 53)  # the position of the about button on the home scene
            #self.rect_exit = Rect(229, 456, 200, 53)  # the position of the exit button on the home scene
            self.rect_pause_home = Rect(229, 263, 200, 53)  # the position of the home button on pause scene
            self.rect_score = Rect(229, 328, 200, 53)  # the position of the score button on the home scene
            self.rect_manual = Rect(229, 393, 200, 53)  # the position of the manual button on the home scene
            self.rect_scene = Rect(229, 519, 200, 53)  # the position of the manual button on the home scene
            self.rect_back = Rect(10, 620, 40, 30)  # the position of the back button on the home scene
            self.rect_sound = Rect(10, 600, 30, 30) # the position of the sound button on the home scene
            self.rect_scene_next = Rect(610, 330, 30, 30)  # the position of the next scene button on scene
            self.rect_scene_previous = Rect(50, 330, 30, 30)  # the position of the previous scene button on scene

            if(self.rect.collidepoint(x, y) and (self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN)):
                self.state = self.GAME
            elif(self.rect_play.collidepoint(x,y) and self.state == self.LOAD):
                self.state = self.GAME
            elif (self.rect_play.collidepoint(x, y) and self.state == self.PAUSE):
                self.state = self.GAME
            elif (self.rect_about.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.ABOUT
            elif (self.rect_score.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.SCORE
            elif (self.rect_scene.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.SCENE
            elif (self.rect_back.collidepoint(x, y) and self.state == self.SCENE):
                self.state = self.LOAD
            elif (self.rect_scene_next.collidepoint(x, y) and self.state == self.SCENE):
                self.game_scene.set_next_image()
            elif (self.rect_scene_previous.collidepoint(x, y) and self.state == self.SCENE):
                self.game_scene.set_previous_image()
            elif (self.rect_pause_home.collidepoint(x, y) and self.state == self.PAUSE):

                self.state = self.LOAD
                self.setup(self.level_manager.get_level())
                self.save_level()

            elif (self.rect_manual.collidepoint(x, y) and self.state == self.LOAD):
                webbrowser.open_new('http://gamingdirectional.com/blog/2018/12/25/air-strike//')
            elif (self.rect_back.collidepoint(x, y) and (self.state == self.ABOUT or self.state == self.MANUAL or self.state == self.SCORE)):
                self.state = self.LOAD
            elif (self.rect_sound.collidepoint(x, y) and self.state == self.LOAD):

                if(self.start_scene.soundon == True):
                    self.start_scene.soundon = False
                    pygame.mixer_music.pause()
                else:
                    self.start_scene.soundon = True
                    pygame.mixer_music.unpause()

    def save_level(self):
        self.level_manager.save_level()

    def set_pause(self, pause):

        self.pause = pause

        if(self.pause == True):

            self.state = self.PAUSE

    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.boy_sprite.setX(_x)

    def save_scene(self):
        self.game_scene.take_screen()

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

    def update(self):
        self.enemy_manager.update()
        self.mana_manager.update()
        self.boy_sprite.update()


    def draw(self):
        if(self.state == self.GAME):
            self.background.draw()
            #self.score_manager.draw()
            self.boy_sprite.draw()
            self.enemy_manager.draw()
            self.mana_manager.draw()
            pygame.display.flip()

If you run the above program then you will see those manas nicely placed on the game scene at the moment.

Like, share or follow me on twitter.

Detect the next game level

Hello and welcome back to the current pygame project. In this article, we will create a new method to determine whether the boy has reached the door or not and if he did then the player will reach the next level. We will not create a new level yet so in this case, the game will restart again after the boy has reached the door. We will also temporary mute the player-enemy collision detection method because without the mana the boy will collide with the enemy and it will be a game over before the boy reaches the door, we will create the mana class in the next chapter. There are two files we need to edit in this chapter, first we will add in the door position list in the boy object class.

class BoyObject(object):

    def __init__(self):

        self.list_1 = [

            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.ladder_boundary_1 = [[9 * 64, 8 * 64],
                                  [9 * 64, 7 * 64],
                                  [5 * 64, 6 * 64],
                                  [5 * 64, 5 * 64],
                                  [2 * 64, 3 * 64],
                                  [2 * 64, 4 * 64],
                                  [0 * 64, 1 * 64],
                                  [0 * 64, 2 * 64],
                                  ] # the boundary of the ladder

        self.boundary_bottom_1 = [[9 * 64, 9 * 64],
                                  [5 * 64, 7 * 64],
                                  [2 * 64, 5 * 64],
                                  [0 * 64, 3 * 64]]  # the bottom boundary of the ladder

        self.boundary_side_1 = [[4 * 64, 6 * 64],
                                [1 * 64, 4 * 64],
                                [6 * 64, 2 * 64], ]  # the side boundary of the player

        self.boundary_door_1 = [[9 * 64, 0]]

        self.initial_1 = [0, 8 * 64]

    def get_original_position(self, level):

        if (level == 1):
            return self.initial_1

    def get_object_list(self, level):

        if(level == 1):
            return self.list_1

    def get_object_boundary(self, level):

        if (level == 1):
            return self.ladder_boundary_1

    def get_object_bottom_boundary(self, level):

        if (level == 1):
            return self.boundary_bottom_1

    def get_object_side_boundary(self, level):

        if (level == 1):
            return self.boundary_side_1

    def get_object_door_boundary(self, level):

        if(level == 1):
            return self.boundary_door_1

Next, we will create the check win method in the boy sprite class to determine whether the boy has reached the door or not, we will temporary mute the check collide method as mentioned above.

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

class BoySprite(object):

    def __init__(self, scene, level, enemy_manager):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height
        self.level = level # current game level
        self.enemy_manager = enemy_manager # the reference of enemy manager
        self.WIDTH = 640
        self.prepare_boy(self.level)

    def prepare_boy(self, level):
        self.boy_object = BoyObject()
        self.boy_object_list = self.boy_object.get_object_list(level)
        self.boy_original_position = self.boy_object.get_original_position(level)
        self.x = self.boy_original_position[0]
        self.y = self.boy_original_position[1]
        self.speed = 2
        self.boy_image_sprite_right = 'Asset/bright.png'
        self.boy_image_sprite_left = 'Asset/bleft.png'
        self.boy_sprite = self.boy_image_sprite_right
        self.frame = 3
        self.up = False
        self.ladder = False
        self.left = False
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()
        self.boy_ladder_list = self.boy_object.get_object_boundary(level)
        self.boy_bottom_boundary_list = self.boy_object.get_object_bottom_boundary(level)
        self.boy_side_boundary_list = self.boy_object.get_object_side_boundary(level)
        self.boy_door_boundary_list = self.boy_object.get_object_door_boundary(level)
        self.enemy_list = self.enemy_manager.get_enemy_list()
        self.initialize()

    # set the x and the y direction for the player object

    def setX(self, x):

        if(self.ladder == True):
            return
        self.x += x
        if (self.up == True and x < 0):
            self.frame = 1
            self.up = False
        elif(self.up == True and x > 0):
            self.frame = 0
            self.up = False
        if(x < 0):
            self.left = True
            self.frame += 1
            if (self.frame > 5):
                self.frame = 1
            self.boy_sprite = self.boy_image_sprite_left
        elif(x > 0):
            self.frame += 1
            self.left = False
            if (self.frame > 4):
                self.frame = 0
            self.boy_sprite = self.boy_image_sprite_right
        elif(x == 0):
            if(self.left == True):
                self.frame = 2
                self.boy_sprite = self.boy_image_sprite_left
            elif(self.left == False):
                self.frame = 3
                self.boy_sprite = self.boy_image_sprite_right
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def setY(self, y):

        self.boy_rect = Rect(self.x, self.y+y, 64, 64)
        if(self.isUpDown(self.boy_rect, y) == True):
            self.y += y
        if(y == 0):
            self.frame = 9
        elif(self.up == False):
            self.frame = 6
            self.up = True
        else:
            if(y < 0):
                self.frame -= 1
            elif(y > 0):
                self.frame += 1
            if(self.frame > 10):
                self.frame = 6
            elif(self.frame < 6):
                self.frame += 2
        self.boy_sprite = self.boy_image_sprite_right
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def checkboundary(self):

        if(self.x < 0):
            self.x = 0
        elif(self.x > self.WIDTH - self.space):
            self.x = self.WIDTH - self.space
        else:
            self.isLeftRight()

    def isUpDown(self, rect, y):

        for boundary in self.boy_ladder_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            if ((boundary_rect.collidepoint(self.x, self.y+y) == True or boundary_rect.collidepoint(self.x, self.y+self.space+y) == True) and (self.x % self.space == 0)):
                for boundary_bottom in self.boy_bottom_boundary_list:
                    boundary_rect = Rect(boundary_bottom[0], boundary_bottom[1], 64, 64)
                    if (boundary_rect.colliderect(rect) == True):
                        self.ladder = False
                        return False
                self.ladder = True
                return True
        self.ladder = False
        return False

    def isLeftRight(self):

        for boundary in self.boy_side_boundary_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            boy_rect = Rect(self.x, self.y, 64, 64)
            if (boundary_rect.colliderect(boy_rect) == True):
                if(self.left == True):
                    self.x += self.speed
                else:
                    self.x -= self.speed

    def update(self):
        self.checkboundary()
        #self.check_collide()
        self.check_win()
        self.move_boy()

    def check_win(self):
        for door in self.boy_door_boundary_list:
            if(door[0] == self.x and door[1] == self.y):
                self.prepare_boy(self.level)

    def check_collide(self):
        for enemy in self.enemy_list:
            enemy_rect = Rect(enemy.x, enemy.y, 64, 64)
            boy_rect = Rect(self.x, self.y, 64, 64)
            if (enemy_rect.colliderect(boy_rect) == True):
                self.prepare_boy(self.level)
                return

    def move_boy(self):
        self.draw_pos = mt.Vector2(self.x, self.y)  # the position of the image on game scene

    def initialize(self):
        for row in range(self.row):
            for column in range(self.column):

                if(self.boy_object_list[row][column] == 1):

                    self.draw_pos = mt.Vector2(self.x, self.y)  # the vector position of the image on game scene
                    self.scene.blit(self.boy_surface, self.draw_pos)  # draw enemy frame

    def draw(self):

        self.scene.blit(self.boy_surface, self.draw_pos)  # draw boy frame

With that, when the boy has finally reached the door position the game will restart again.

Like, share or subscribe the above tweet or follow me on twitter.

Create the enemy-player overlapping detection mechanism

In the previous article we have finished creating the player boundary detection mechanism and in this article, we will create a simple enemy player overlapping detection mechanism which we will then further modify it in the next article. Before we start, below are the game plans.

  1. We will create a player enemy overlapping detection mechanism which will reset the player object at its original position if the player has overlapped any enemy object during the game.
  2. This system is used to create the game over’s scenario in the real game where if the player hits the enemy and that player is not eating any mana then it will be game over.
  3. The program will loop through each enemy in an enemy list to check whether has that enemy hit that player or not.
  4. The enemy manager object will be passed into the boy sprite object when the program is creating the boy sprite object in the game manager class.

In order to achieve the above results we will need to edit four files, first is the game manager file.

from EnemyManager import EnemyManager
from Overlap import Overlap
from ExplosionManager import ExplosionManager
from Score import Score
from StartScene import StartScene
from pygame.locals import *
from LevelManager import LevelManager
import pygame
import webbrowser
from Scene import Scene
from BackGroundSprite import BackGroundSprite
from BoySprite import BoySprite

class GameManager(object):

    def __init__(self, scene):

        self.scene = scene
        self.load_music()
        self.play_music()
        self.overlap_manager = Overlap()
        self.level_manager = LevelManager(self)
        self.level_manager.set_level()
        self.setup(self.level_manager.get_level())
        self.start_scene = StartScene(scene, self.level_manager)

        self.pause = False # flag to pause the game

        self.game_scene = Scene(self.scene)

        #game state
        self.LOAD = 0
        self.GAME = 1
        self.OVER = 2
        self.NEXT = 3
        self.WIN = 4
        self.ABOUT = 5
        self.MANUAL = 6
        self.PAUSE = 7
        self.SCORE = 8
        self.SCENE = 9

        self.state = self.LOAD

    def setup(self, game_level):

        self.game_level = game_level
        self.score_manager = Score(self.scene, self.level_manager)
        self.background = BackGroundSprite(game_level, self.scene)
        self.enemy_manager = EnemyManager(self.scene, game_level)
        self.boy_sprite = BoySprite(self.scene, game_level, self.enemy_manager)
        self.explosion_manager = ExplosionManager(self.scene)

    def loop(self):

        if(self.state == self.LOAD):
            self.start_scene.draw(self.state)
        elif(self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN or self.state == self.ABOUT or self.state == self.MANUAL or self.state == self.SCORE):
            self.start_scene.draw(self.state)
        elif(self.state == self.SCENE):
            self.game_scene.draw()
        elif(self.state == self.GAME):

            self.update()
            self.draw()

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

            self.start_scene.draw(self.state)

    def isAreaClick(self, x, y):
        if (self.state == self.LOAD or self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN or self.state == self.ABOUT or self.state == self.SCORE or self.state == self.SCENE or self.state == self.MANUAL or self.state == self.PAUSE):
            self.rect = Rect(177, 274, 306, 112) # the position of the play button on the scene
            self.rect_play = Rect(229, 200, 200, 53)  # the position of the play button on the home scene
            self.rect_about = Rect(229, 263, 200, 53)  # the position of the about button on the home scene
            #self.rect_exit = Rect(229, 456, 200, 53)  # the position of the exit button on the home scene
            self.rect_pause_home = Rect(229, 263, 200, 53)  # the position of the home button on pause scene
            self.rect_score = Rect(229, 328, 200, 53)  # the position of the score button on the home scene
            self.rect_manual = Rect(229, 393, 200, 53)  # the position of the manual button on the home scene
            self.rect_scene = Rect(229, 519, 200, 53)  # the position of the manual button on the home scene
            self.rect_back = Rect(10, 620, 40, 30)  # the position of the back button on the home scene
            self.rect_sound = Rect(10, 600, 30, 30) # the position of the sound button on the home scene
            self.rect_scene_next = Rect(610, 330, 30, 30)  # the position of the next scene button on scene
            self.rect_scene_previous = Rect(50, 330, 30, 30)  # the position of the previous scene button on scene

            if(self.rect.collidepoint(x, y) and (self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN)):
                self.state = self.GAME
            elif(self.rect_play.collidepoint(x,y) and self.state == self.LOAD):
                self.state = self.GAME
            elif (self.rect_play.collidepoint(x, y) and self.state == self.PAUSE):
                self.state = self.GAME
            elif (self.rect_about.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.ABOUT
            elif (self.rect_score.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.SCORE
            elif (self.rect_scene.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.SCENE
            elif (self.rect_back.collidepoint(x, y) and self.state == self.SCENE):
                self.state = self.LOAD
            elif (self.rect_scene_next.collidepoint(x, y) and self.state == self.SCENE):
                self.game_scene.set_next_image()
            elif (self.rect_scene_previous.collidepoint(x, y) and self.state == self.SCENE):
                self.game_scene.set_previous_image()
            elif (self.rect_pause_home.collidepoint(x, y) and self.state == self.PAUSE):

                self.state = self.LOAD
                self.setup(self.level_manager.get_level())
                self.save_level()

            elif (self.rect_manual.collidepoint(x, y) and self.state == self.LOAD):
                webbrowser.open_new('http://gamingdirectional.com/blog/2018/12/25/air-strike//')
            elif (self.rect_back.collidepoint(x, y) and (self.state == self.ABOUT or self.state == self.MANUAL or self.state == self.SCORE)):
                self.state = self.LOAD
            elif (self.rect_sound.collidepoint(x, y) and self.state == self.LOAD):

                if(self.start_scene.soundon == True):
                    self.start_scene.soundon = False
                    pygame.mixer_music.pause()
                else:
                    self.start_scene.soundon = True
                    pygame.mixer_music.unpause()

    def save_level(self):
        self.level_manager.save_level()

    def set_pause(self, pause):

        self.pause = pause

        if(self.pause == True):

            self.state = self.PAUSE

    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.boy_sprite.setX(_x)

    def save_scene(self):
        self.game_scene.take_screen()

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

    def update(self):
        self.enemy_manager.update()
        self.boy_sprite.update()
        #self.isOverlap()
        #self.explosion_manager.explosion_update()

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

    def draw(self):
        if(self.state == self.GAME):
            self.background.draw()

            #self.enemy_manager.update()
            #self.explosion_manager.draw()
            #self.score_manager.draw()
            self.boy_sprite.draw()
            self.enemy_manager.draw()
            pygame.display.flip()

As you can see we have passed in the enemy manager instance to the boy sprite object during the setup stage of the game. Next we will edit the enemy manager file.

from EnemySprite import EnemySprite

class EnemyManager(object):

    def __init__(self, scene, game_level):

        self.scene = scene
        self.level = game_level
        self.enemy = EnemySprite(self.level, self.scene)
        self.create_enemy()

    def create_enemy(self):

        self.enemy.get_level(self.level)

    def update(self):

        self.enemy.update()

    # check the boundary of the enemy with the game scene area
    def get_enemy_list(self):

        return self.enemy.get_enemy_list()

    def draw(self):

        self.enemy.draw()

The get enemy list method will call the enemy sprite instance to return the complete enemy list which will then be returned to the original caller which is the boy sprite class. Next file we need to edit is the enemy sprite file.

from EnemyObject import EnemyObject
from pygame import math as mt
from Enemy import Enemy

class EnemySprite(object):

    def __init__(self, level, scene):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height

        self.level = level # current game level

        self.total_enemy_list = []

        self.enemy_object = EnemyObject()

        self.create_enemy(level)

    def create_enemy(self, level):

        self.enemy_boundary_list = self.enemy_object.get_object_boundary(level)
        self.enemy_original_position = self.enemy_object.get_original_position(level)

        i = 0
        if(level == 1):
            while(i < 5):
                self.total_enemy_list.append(Enemy(self.enemy_boundary_list[i], self.enemy_original_position[i]))
                i += 1

    def update(self):

        for enemy in self.total_enemy_list:
            enemy.update()

    def draw(self):
        self.counter = 0
        for row in range(self.row):

            for column in range(self.column):

                if(self.enemy_list[row][column] == 1):

                    self.enemy = self.total_enemy_list[self.counter]

                    self.draw_pos = mt.Vector2(self.enemy.x, self.enemy.y)  # the position of the image on game scene

                    self.scene.blit(self.enemy.get_enemy_surface(), self.draw_pos)  # draw enemy frame

                    self.counter += 1

    def get_level(self, level):
        self.enemy_list = self.enemy_object.get_object_list(level)

    def get_enemy_list(self):
        return self.total_enemy_list

Basically we have just included the get enemy list method which will return the entire enemy list to the caller. Finally we will edit the boy sprite class.

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

class BoySprite(object):

    def __init__(self, scene, level, enemy_manager):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height
        self.level = level # current game level
        self.enemy_manager = enemy_manager # the reference of enemy manager
        self.WIDTH = 640
        self.prepare_boy(self.level)

    def prepare_boy(self, level):
        self.boy_object = BoyObject()
        self.boy_object_list = self.boy_object.get_object_list(level)
        self.boy_original_position = self.boy_object.get_original_position(level)
        self.x = self.boy_original_position[0]
        self.y = self.boy_original_position[1]
        self.speed = 2
        self.boy_image_sprite_right = 'Asset/bright.png'
        self.boy_image_sprite_left = 'Asset/bleft.png'
        self.boy_sprite = self.boy_image_sprite_right
        self.frame = 3
        self.up = False
        self.ladder = False
        self.left = False
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()
        self.boy_ladder_list = self.boy_object.get_object_boundary(level)
        self.boy_bottom_boundary_list = self.boy_object.get_object_bottom_boundary(level)
        self.boy_side_boundary_list = self.boy_object.get_object_side_boundary(level)
        self.enemy_list = self.enemy_manager.get_enemy_list()
        self.initialize()

    # set the x and y direction for the player object

    def setX(self, x):

        if(self.ladder == True):
            return
        self.x += x
        if (self.up == True and x < 0):
            self.frame = 1
            self.up = False
        elif(self.up == True and x > 0):
            self.frame = 0
            self.up = False
        if(x < 0):
            self.left = True
            self.frame += 1
            if (self.frame > 5):
                self.frame = 1
            self.boy_sprite = self.boy_image_sprite_left
        elif(x > 0):
            self.frame += 1
            self.left = False
            if (self.frame > 4):
                self.frame = 0
            self.boy_sprite = self.boy_image_sprite_right
        elif(x == 0):
            if(self.left == True):
                self.frame = 2
                self.boy_sprite = self.boy_image_sprite_left
            elif(self.left == False):
                self.frame = 3
                self.boy_sprite = self.boy_image_sprite_right
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def setY(self, y):

        self.boy_rect = Rect(self.x, self.y+y, 64, 64)
        if(self.isUpDown(self.boy_rect, y) == True):
            self.y += y
        if(y == 0):
            self.frame = 9
        elif(self.up == False):
            self.frame = 6
            self.up = True
        else:
            if(y < 0):
                self.frame -= 1
            elif(y > 0):
                self.frame += 1
            if(self.frame > 10):
                self.frame = 6
            elif(self.frame < 6):
                self.frame += 2
        self.boy_sprite = self.boy_image_sprite_right
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def checkboundary(self):

        if(self.x < 0):
            self.x = 0
        elif(self.x > self.WIDTH - self.space):
            self.x = self.WIDTH - self.space
        else:
            self.isLeftRight()


    def isUpDown(self, rect, y):

        for boundary in self.boy_ladder_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            if ((boundary_rect.collidepoint(self.x, self.y+y) == True or boundary_rect.collidepoint(self.x, self.y+self.space+y) == True) and (self.x % self.space == 0)):
                for boundary_bottom in self.boy_bottom_boundary_list:
                    boundary_rect = Rect(boundary_bottom[0], boundary_bottom[1], 64, 64)
                    if (boundary_rect.colliderect(rect) == True):
                        self.ladder = False
                        return False
                self.ladder = True
                return True
        self.ladder = False
        return False

    def isLeftRight(self):

        for boundary in self.boy_side_boundary_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            boy_rect = Rect(self.x, self.y, 64, 64)
            if (boundary_rect.colliderect(boy_rect) == True):
                if(self.left == True):
                    self.x += self.speed
                else:
                    self.x -= self.speed

    def update(self):
        self.checkboundary()
        self.check_collide()
        self.move_boy()

    def check_collide(self):
        for enemy in self.enemy_list:
            enemy_rect = Rect(enemy.x, enemy.y, 64, 64)
            boy_rect = Rect(self.x, self.y, 64, 64)
            if (enemy_rect.colliderect(boy_rect) == True):
                self.prepare_boy(self.level)
                return

    def move_boy(self):
        self.draw_pos = mt.Vector2(self.x, self.y)  # the position of the image on game scene

    def initialize(self):
        for row in range(self.row):
            for column in range(self.column):

                if(self.boy_object_list[row][column] == 1):

                    self.draw_pos = mt.Vector2(self.x, self.y)  # the vector position of the image on game scene
                    self.scene.blit(self.boy_surface, self.draw_pos)  # draw enemy frame

    def draw(self):

        self.scene.blit(self.boy_surface, self.draw_pos)  # draw boy frame

The check collide method will reset the player to his original position if he has collided with the enemy object. In the real game situation it will be game over.

Hello man, have you visited my new website before? Come and read this new article: Create content and earn income!

Do you like this post, maybe you would like to support this website through the below donation button.

Alright, our next mission is to create a detection mechanism for the boy and the door object which will then bring the player to the next level.

Adjust the boy sprite animation

Hello, and welcome back, we are almost done coding the player animation mechanism after we have finished the player boundary detection mechanism in the last article but before we can go to the next stage we need to tidy up the player animation mechanism first by introducing the standstill image of the boy when the boy is not moving and that image will either face left or right or up or down based on the direction of the boy at the time he stops moving. In order to achieve this we only need to edit two files.

The first file we need to edit is the main file where we will include the keyup event so we can set the x different or y different to zero when the boy who is moving in either x or y-direction suddenly stop moving.

import pygame
from pygame.locals import *
from GameManager import GameManager

pygame.init()

size = width, height = 640, 640
pygame.display.set_caption("Amaze Boy")  # set the title of the window
screen = pygame.display.set_mode(size)
game_manager = GameManager(screen)
rect_exit = Rect(229, 456, 200, 53)  # the position of the exit button on the home scene
running = True
pygame.key.set_repeat(100, 40)

while running:

    for event in pygame.event.get():
        # when the user clicks on the 'x'
        if event.type == pygame.QUIT:
            game_manager.save_level()
            running = False

        # detect key press event
        if event.type == KEYDOWN:

            if (game_manager.state == 1):

                if event.key == K_LEFT:
                    game_manager.set_player_x(-2)
                elif event.key == K_RIGHT:
                    game_manager.set_player_x(2)
                elif event.key == K_UP:
                    game_manager.set_player_y(-2)
                elif event.key == K_DOWN:
                    game_manager.set_player_y(2)

        elif event.type == KEYUP:

            if (game_manager.state == 1):

                if event.key == K_LEFT:
                    game_manager.set_player_x(0)
                elif event.key == K_RIGHT:
                    game_manager.set_player_x(0)
                elif event.key == K_UP:
                    game_manager.set_player_y(0)
                elif event.key == K_DOWN:
                    game_manager.set_player_y(0)

        elif event.type == pygame.MOUSEBUTTONDOWN:
            x, y = event.pos
            if (rect_exit.collidepoint(x, y) and game_manager.state == game_manager.LOAD):
                game_manager.save_level()
                running = False
            # 1 is the left mouse button
            elif event.button == 1:
                game_manager.isAreaClick(x, y)

    game_manager.loop()

The next file we need to edit is the boy sprite class file where we will set the frame of the image to that of a standstill image of the boy depends on whether the boy is moving side-way or up-down before stopping.

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

class BoySprite(object):

    def __init__(self, scene, level):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height
        self.level = level # current game level
        self.frame = 3
        self.prepare_boy(self.level)
        self.WIDTH = 640

    def prepare_boy(self, level):
        self.boy_object = BoyObject()
        self.boy_object_list = self.boy_object.get_object_list(level)
        self.boy_original_position = self.boy_object.get_original_position(level)
        self.x = self.boy_original_position[0]
        self.y = self.boy_original_position[1]
        self.speed = 2
        self.boy_image_sprite_right = 'Asset/bright.png'
        self.boy_image_sprite_left = 'Asset/bleft.png'
        self.boy_sprite = self.boy_image_sprite_right
        self.left = False
        self.up = False
        self.ladder = False
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()
        self.boy_ladder_list = self.boy_object.get_object_boundary(level)
        self.boy_bottom_boundary_list = self.boy_object.get_object_bottom_boundary(level)
        self.boy_side_boundary_list = self.boy_object.get_object_side_boundary(level)
        self.initialize()

    # set the x and y direction for the player object

    def setX(self, x):

        if(self.ladder == True):
            return
        self.x += x
        if (self.up == True and x < 0):
            self.frame = 1
            self.up = False
        elif(self.up == True and x > 0):
            self.frame = 0
            self.up = False
        if(x < 0):
            self.left = True
            self.frame += 1
            if (self.frame > 5):
                self.frame = 1
            self.boy_sprite = self.boy_image_sprite_left
        elif(x > 0):
            self.frame += 1
            self.left = False
            if (self.frame > 4):
                self.frame = 0
            self.boy_sprite = self.boy_image_sprite_right
        elif(x == 0):
            if(self.left == True):
                self.frame = 2
                self.boy_sprite = self.boy_image_sprite_left
            elif(self.left == False):
                self.frame = 3
                self.boy_sprite = self.boy_image_sprite_right
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def setY(self, y):

        self.boy_rect = Rect(self.x, self.y+y, 64, 64)
        if(self.isUpDown(self.boy_rect, y) == True):
            self.y += y
        if(y == 0):
            self.frame = 9
        elif(self.up == False):
            self.frame = 6
            self.up = True
        else:
            if(y < 0):
                self.frame -= 1
            elif(y > 0):
                self.frame += 1
            if(self.frame > 10):
                self.frame = 6
            elif(self.frame < 6):
                self.frame += 2
        self.boy_sprite = self.boy_image_sprite_right
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def checkboundary(self):

        if(self.x < 0):
            self.x = 0
        elif(self.x > self.WIDTH - self.space):
            self.x = self.WIDTH - self.space
        else:
            self.isLeftRight()


    def isUpDown(self, rect, y):

        for boundary in self.boy_ladder_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            if ((boundary_rect.collidepoint(self.x, self.y+y) == True or boundary_rect.collidepoint(self.x, self.y+self.space+y) == True) and (self.x % self.space == 0)):
                for boundary_bottom in self.boy_bottom_boundary_list:
                    boundary_rect = Rect(boundary_bottom[0], boundary_bottom[1], 64, 64)
                    if (boundary_rect.colliderect(rect) == True):
                        self.ladder = False
                        return False
                self.ladder = True
                return True
        self.ladder = False
        return False

    def isLeftRight(self):

        for boundary in self.boy_side_boundary_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            boy_rect = Rect(self.x, self.y, 64, 64)
            if (boundary_rect.colliderect(boy_rect) == True):
                if(self.left == True):
                    self.x += self.speed
                else:
                    self.x -= self.speed

    def update(self):
        self.checkboundary()
        self.move_boy()

    def move_boy(self):
        self.draw_pos = mt.Vector2(self.x, self.y)  # the position of the image on game scene

    def initialize(self):
        for row in range(self.row):
            for column in range(self.column):

                if(self.boy_object_list[row][column] == 1):

                    self.draw_pos = mt.Vector2(self.x, self.y)  # the vector position of the image on game scene
                    self.scene.blit(self.boy_surface, self.draw_pos)  # draw enemy frame

    def draw(self):

        self.scene.blit(self.boy_surface, self.draw_pos)  # draw boy frame

With that, we will see a standstill image of the boy after the boy has stopped moving.

In the next chapter, we will explore the boy and the enemy overlapping detection mechanism. If you want to help this site please consider to donate through the below button, all your support will go to upgrading this site which will then provide you with a lot of new free code in the future, thank you in advance.

Final touch up for the boy boundary detection mechanism

Sorry for not posting yesterday as I am terribly sick, although I am still sick today mine condition is a lot more better now. After the previous article we have basically developed a boundary detection mechanism for the player object and in this article, we will do the final touch up for that mechanism. Here are the final rules that we need to apply in order to complete the boundary detection mechanism for the boy.

  1. If the boy is halfway up or down when he is insides a ladder then he can either move up or down but not side-way.
  2. If the boy has touched the bottom of the ladder then he can move both side or go up the ladder again but not go downward.
  3. The boy will not be able to move even further if there is an empty space below his feet to avoid him from falling down.

With the above three rules in place, we will slightly modify the boy object class by introducing a new side boundary list which will prevent the boy from going even further if the bottom of his feet is an empty space.

class BoyObject(object):

    def __init__(self):

        self.list_1 = [

            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.ladder_boundary_1 = [[9 * 64, 8 * 64],
                                  [9 * 64, 7 * 64],
                                  [5 * 64, 6 * 64],
                                  [5 * 64, 5 * 64],
                                  [2 * 64, 3 * 64],
                                  [2 * 64, 4 * 64],
                                  [0 * 64, 1 * 64],
                                  [0 * 64, 2 * 64],
                                  ] # the boundary of the ladder

        self.boundary_bottom_1 = [[9 * 64, 9 * 64],
                                  [5 * 64, 7 * 64],
                                  [2 * 64, 5 * 64],
                                  [0 * 64, 3 * 64]]  # the bottom boundary of the ladder

        self.boundary_side_1 = [[4 * 64, 6 * 64],
                                [1 * 64, 4 * 64],
                                [6 * 64, 2 * 64], ]  # the side boundary of the player

        self.initial_1 = [0, 8 * 64]

    def get_original_position(self, level):

        if (level == 1):
            return self.initial_1

    def get_object_list(self, level):

        if(level == 1):
            return self.list_1

    def get_object_boundary(self, level):

        if (level == 1):
            return self.ladder_boundary_1

    def get_object_bottom_boundary(self, level):

        if (level == 1):
            return self.boundary_bottom_1

    def get_object_side_boundary(self, level):

        if (level == 1):
            return self.boundary_side_1

Next, we will need to check the side boundary of the boy to make sure he will not fall down beside checking the ladder boundary and the bottom boundary of the ladder.

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

class BoySprite(object):

    def __init__(self, scene, level):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height
        self.level = level # current game level
        self.frame = 3
        self.prepare_boy(self.level)
        self.WIDTH = 640

    def prepare_boy(self, level):
        self.boy_object = BoyObject()
        self.boy_object_list = self.boy_object.get_object_list(level)
        self.boy_original_position = self.boy_object.get_original_position(level)
        self.x = self.boy_original_position[0]
        self.y = self.boy_original_position[1]
        self.speed = 2
        self.boy_image_sprite_right = 'Asset/bright.png'
        self.boy_image_sprite_left = 'Asset/bleft.png'
        self.boy_sprite = self.boy_image_sprite_right
        self.left = False
        self.up = False
        self.ladder = False
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()
        self.boy_ladder_list = self.boy_object.get_object_boundary(level)
        self.boy_bottom_boundary_list = self.boy_object.get_object_bottom_boundary(level)
        self.boy_side_boundary_list = self.boy_object.get_object_side_boundary(level)
        self.initialize()

    # set the x and y direction for the player object

    def setX(self, x):

        if(self.ladder == True):
            return
        self.x += x
        if (self.up == True and x < 0):
            self.frame = 1
            self.up = False
        elif(self.up == True and x > 0):
            self.frame = 0
            self.up = False
        if(x < 0):
            self.left = True
            self.frame += 1
            if (self.frame > 5):
                self.frame = 1
            self.boy_sprite = self.boy_image_sprite_left
        elif(x > 0):
            self.frame += 1
            self.left = False
            if (self.frame > 4):
                self.frame = 0
            self.boy_sprite = self.boy_image_sprite_right
        elif(x == 0):
            if(self.left == True):
                self.frame = 2
                self.boy_sprite = self.boy_image_sprite_left
            elif(self.left == False):
                self.frame = 3
                self.boy_sprite = self.boy_image_sprite_right

        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def setY(self, y):

        self.boy_rect = Rect(self.x, self.y+y, 64, 64)
        if(self.isUpDown(self.boy_rect, y) == True):
            self.y += y
        if(y == 0):
            self.frame = 6
        elif(self.up == False):
            self.frame = 6
            self.up = True
        else:
            if(y < 0):
                self.frame -= 1
            elif(y > 0):
                self.frame += 1
            if(self.frame > 10):
                self.frame = 6
            elif(self.frame < 6):
                self.frame += 2
        self.boy_sprite = self.boy_image_sprite_right
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def checkboundary(self):

        if(self.x < 0):
            self.x = 0
        elif(self.x > self.WIDTH - self.space):
            self.x = self.WIDTH - self.space
        else:
            self.isLeftRight()


    def isUpDown(self, rect, y):

        for boundary in self.boy_ladder_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            if ((boundary_rect.collidepoint(self.x, self.y+y) == True or boundary_rect.collidepoint(self.x, self.y+self.space+y) == True) and (self.x % self.space == 0)):
                for boundary_bottom in self.boy_bottom_boundary_list:
                    boundary_rect = Rect(boundary_bottom[0], boundary_bottom[1], 64, 64)
                    if (boundary_rect.colliderect(rect) == True):
                        self.ladder = False
                        return False
                self.ladder = True
                return True
        self.ladder = False
        return False

    def isLeftRight(self):

        for boundary in self.boy_side_boundary_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            boy_rect = Rect(self.x, self.y, 64, 64)
            if (boundary_rect.colliderect(boy_rect) == True):
                if(self.left == True):
                    self.x += self.speed
                else:
                    self.x -= self.speed

    def update(self):
        self.checkboundary()
        self.move_boy()

    def move_boy(self):
        self.draw_pos = mt.Vector2(self.x, self.y)  # the position of the image on game scene

    def initialize(self):
        for row in range(self.row):
            for column in range(self.column):

                if(self.boy_object_list[row][column] == 1):

                    self.draw_pos = mt.Vector2(self.x, self.y)  # the position of the image on game scene
                    self.scene.blit(self.boy_surface, self.draw_pos)  # draw enemy frame

    def draw(self):

        self.scene.blit(self.boy_surface, self.draw_pos)  # draw enemy frame

Before the boy can move even further the pygame program needs to make sure he can go up, down, left or right.

Like, share or follow me on twitter.

Continue with the boy boundary detection mechanism

In the previous article, we have successfully made the boy climbing up the ladder but the boy will continue climbing even though there is no more ladder for him to climb. In this article, we will solve the previous problem by introducing the following rules.

  1. When the boy is climbing the ladder he can only move in either the upward or the downward direction but not side-way.
  2. There will be no return for the boy which means he can only move upward or downward but not going back again from where he comes from once he is insides the ladder.
  3. We have introduced the bottom boundary of the ladder which means if the boy steps on the bottom boundary of that ladder he cannot move further downward.
  4. We will also make sure that the x position of the boy is lining nicely with the top left corner of the ladder which is always situated on the left of the ladder block.

With all that being said we will include the bottom boundary list for the first ladder in the game scene in the boy object class.

class BoyObject(object):

    def __init__(self):

        self.list_1 = [

            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        ]

        self.boundary_1 = [[9 * 64, 8 * 64],
                           [9 * 64, 7 * 64]] # the boundary of the ladder

        self.boundary_bottom = [[9 * 64, 9 * 64]]  # the bottom boundary of the ladder

        self.initial_1 = [0, 8 * 64]

    def get_original_position(self, level):

        if (level == 1):
            return self.initial_1

    def get_object_list(self, level):

        if(level == 1):
            return self.list_1

    def get_object_boundary(self, level):

        if (level == 1):
            return self.boundary_1

    def get_object_bottom_boundary(self, level):

        if (level == 1):
            return self.boundary_bottom

Next we will link up the above lists with the boy sprite class.

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

class BoySprite(object):

    def __init__(self, scene, level):

        self.row = 10
        self.column = 10
        self.scene = scene # game scene instance
        self.space = 64 # image width and height
        self.level = level # current game level
        self.frame = 3
        self.prepare_boy(self.level)
        self.WIDTH = 640

    def prepare_boy(self, level):
        self.boy_object = BoyObject()
        self.boy_object_list = self.boy_object.get_object_list(level)
        self.boy_original_position = self.boy_object.get_original_position(level)
        self.x = self.boy_original_position[0]
        self.y = self.boy_original_position[1]
        self.boy_image_sprite_right = 'Asset/bright.png'
        self.boy_image_sprite_left = 'Asset/bleft.png'
        self.boy_sprite = self.boy_image_sprite_right
        self.left = False
        self.up = False
        self.ladder = False
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()
        self.boy_boundary_list = self.boy_object.get_object_boundary(level)
        self.boy_bottom_boundary_list = self.boy_object.get_object_bottom_boundary(level)
        self.initialize()

    # set the x and y direction for the player object

    def setX(self, x):

        if(self.ladder == True):
            return
        self.x += x
        if (self.up == True and x < 0):
            self.frame = 1
            self.up = False
        elif(self.up == True and x > 0):
            self.frame = 0
            self.up = False
        if(x < 0):
            self.left = True
            self.frame += 1
            if (self.frame > 5):
                self.frame = 1
            self.boy_sprite = self.boy_image_sprite_left
        elif(x > 0):
            self.frame += 1
            self.left = False
            if (self.frame > 4):
                self.frame = 0
            self.boy_sprite = self.boy_image_sprite_right
        elif(x == 0):
            if(self.left == True):
                self.frame = 2
                self.boy_sprite = self.boy_image_sprite_left
            elif(self.left == False):
                self.frame = 3
                self.boy_sprite = self.boy_image_sprite_right

        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def setY(self, y):

        self.boy_rect = Rect(self.x, self.y+y, 64, 64)
        if(self.isUpDown(self.boy_rect, y) == True):
            self.y += y
        if(y == 0):
            self.frame = 6
        elif(self.up == False):
            self.frame = 6
            self.up = True
        else:
            if(y < 0):
                self.frame -= 1
            elif(y > 0):
                self.frame += 1
            if(self.frame > 10):
                self.frame = 6
            elif(self.frame < 6):
                self.frame += 2
        self.boy_sprite = self.boy_image_sprite_right
        self.boy_rect = Rect(self.frame * 64, 0, 64, 64)
        self.sprite_boy = GameSprite(self.boy_sprite, self.boy_rect)
        self.boy_surface = self.sprite_boy.getImage()

    def checkboundary(self):
        if(self.x < 0):
            self.x = 0
        elif(self.x > self.WIDTH - self.space):
            self.x = self.WIDTH - self.space

    def isUpDown(self, rect, y):

        for boundary in self.boy_boundary_list:
            boundary_rect = Rect(boundary[0], boundary[1], 64, 64)
            if ((boundary_rect.collidepoint(self.x, self.y+y) == True or boundary_rect.collidepoint(self.x, self.y+self.space+y) == True) and (self.x % self.space == 0)):
                for boundary_bottom in self.boy_bottom_boundary_list:
                    boundary_rect = Rect(boundary_bottom[0], boundary_bottom[1], 64, 64)
                    if (boundary_rect.colliderect(rect) == True):
                        return False
                self.ladder = True
                return True
        self.ladder = False
        return False

    def update(self):
        self.move_boy()
        self.checkboundary()

    def move_boy(self):
        self.draw_pos = mt.Vector2(self.x, self.y)  # the position of the image on game scene

    def initialize(self):
        for row in range(self.row):
            for column in range(self.column):

                if(self.boy_object_list[row][column] == 1):

                    self.draw_pos = mt.Vector2(self.x, self.y)  # the position of the image on game scene
                    self.scene.blit(self.boy_surface, self.draw_pos)  # draw enemy frame

    def draw(self):

        self.scene.blit(self.boy_surface, self.draw_pos)  # draw enemy frame

By applying the above-mentioned rules to the boy sprite class we have now completed the boy’s boundary detection mechanism and the rest is just like homework where we will fill in the blank by completing the entire boy boundary’s list inside the boy object class in the next chapter. Actually, it is possible to allow the boy to move in the left or right direction once he is insides the ladder but there is no reason to do that because once he is insides the ladder his only target is to move to the next floor and then win the game!

Hope you like this article and don’t forget to share the above tweet.