## 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):

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.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_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):

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

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
return True
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.

## Moving the player object in Pygame

In the last chapter we have created the animation effect for the player object and in this chapter, we will move the player object in the x-axis. We will leave the wall and boundary collision detection mechanism to the next chapter. In the last chapter we have already linked up the keyboard events with the game manager class and in this chapter, we only need a slight modification to move the player across the scene when the left or the right arrow key has been pressed. One of the problems with the pygame event module is that we need to activate the repeated event detection process by our-self with this single line of code before the module can send the repeated keypress event (which means when someone is holding the same key on the keyboard) to us.

```pygame.key.set_repeat(100, 40)
```

By setting the delay and interval in the pygame.key.set_repeat method the program will continue to receive the information of the key which the player has pressed on at the moment, this is very important because if the key repeated event has been disabled then the program will only get the keypress’s feedback once after the user has pressed on any key on the keyboard and will not receive the key pressed event again even-though the user has held on to that same key after he has pressed on it. We need to continuously receive the feedback from the pygame key event module in order to move the player smoothly across the canvas. Below is the modified version of the main file.

```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 == 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()
```

Next, we will modify the game manager class by including the boy sprite update method in the update method of this class.

```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.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.GAME = 1
self.OVER = 2
self.NEXT = 3
self.WIN = 4
self.MANUAL = 6
self.PAUSE = 7
self.SCORE = 8
self.SCENE = 9

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.explosion_manager = ExplosionManager(self.scene)

def loop(self):

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
self.state = self.GAME
elif (self.rect_play.collidepoint(x, y) and self.state == self.PAUSE):
self.state = self.GAME
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):
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.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)):
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 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()
```

Finally we will slightly modify 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)

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.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.initialize()

# set the x and y direction for the player object

def setX(self, x):
self.up = False
self.x += x
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):
if(y == 0 or 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 = 0
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 update(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
```

Just in case you wonder why the boy’s sprite has such a wield frame number, I will leave two sprite sheets of the boy object below for you to figure it out.

If you run the above program and press the left or right key on your keyboard you will see the below outcome. As I have mentioned earlier the boy’s boundary detection part will be on the next chapter.

Hope you like this post, like, share or tweet!

## Create a player object in pygame

In this article, we will create a player sprite class which will render the player image on the game scene. First, we will create the player object class which serves as the container for the player’s location data.

```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.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

```

The next part is the player sprite class which will handle the image rendering process.

```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.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.enemy_image_sprite_right = 'Asset/bright.png'
self.boy_rect = Rect(3 * 64, 0, 64, 64)
self.sprite_boy = GameSprite(self.enemy_image_sprite_right, self.boy_rect)
self.boy_surface = self.sprite_boy.getImage()

def update(self):

pass

def draw(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
```

We will render the fourth standstill sprite on the player sprite sheet. Next, we will edit the game manager class to make it includes the player sprite class in it.

```from Player import 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

class GameManager(object):

def __init__(self, scene):

self.scene = scene

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.GAME = 1
self.OVER = 2
self.NEXT = 3
self.WIN = 4
self.MANUAL = 6
self.PAUSE = 7
self.SCORE = 8
self.SCENE = 9

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.player = Player(self.scene)
self.enemy_manager = EnemyManager(self.scene, game_level)
self.boy_sprite = BoySprite(self.scene, game_level)
self.explosion_manager = ExplosionManager(self.scene)

def loop(self):

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
self.state = self.GAME
elif (self.rect_play.collidepoint(x, y) and self.state == self.PAUSE):
self.state = self.GAME
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):
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.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)):
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 play_music(self):
pygame.mixer_music.play(-1) #play the music infinite time

def set_player_x(self, _x):
if (self.state == self.GAME):
self.player.setX(_x)

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

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

def set_missile_strike(self, strike):
if (self.state == self.GAME):
self.player.setStrike(strike)

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

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

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

There we have it, if we run the above program we will make the player sprite renders the standstill image of the boy on the bottom left of the game scene.

Like, share and comment on above tweet or follow me on twitter.

## Move the enemy object with pygame

Hi, here is another quick post on the latest pygame project which I have developed lately. In the previous article, we have created an animated enemy object which can switch direction using the timer control. The timer control is only for demonstration purpose only, during the game the enemy will only switch direction if it hits any obstacle in its path. In this chapter, we will take out the timer and create the moving enemy object which will only switch the direction once it hits an obstacle. The obstacle is consists of an imagination block located on both the right and the left side of the enemy’s path. Each enemy has its own obstacle attached to it. In order to achieve this result, we need to edit three classes. 1) The enemy class which will receive two parameters, the list which contains the left and the right obstacles and the original position of the enemy. The enemy will also move in the x-direction on every update.

```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.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) &gt; 0):
return self.sprite_frame_list_right
elif (self.right == True and len(self.sprite_frame_list_right) &lt;= 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) &gt; 0):
return self.sprite_frame_list_left
elif (self.right == False and len(self.sprite_frame_list_left) &lt;= 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.switch_position()
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 &gt; 26):
if (self.count &gt; 6 and self.forward == True):  # use this logic to control the counter and the image
self.count -= 1
self.forward = False
elif (self.count &lt; 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 &gt; 26):
if (self.count &gt; 5 and self.forward == True):  # use this logic to control the counter and the image
self.count -= 1
self.forward = False
elif (self.count &lt; 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 &lt;= 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 &gt; 0):
self.switch_timer -= 1
elif(self.right == False and self.switch_timer_left &gt; 0):
self.switch_timer_left -= 1
elif(self.switch_timer_left &lt;= 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 &lt; 1 and self.forward == False):
self.count += 1
self.forward = True
elif(self.count &gt; 6 and self.forward == True):
self.count -= 1
self.forward = False

return self.count
```

2) The enemy object class will now contain the original position list and the obstacle list for each level of the game.

```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]]

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
```

3) The next class we need to edit is the enemy sprite class which will then connect the above two classes up!

```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.enemy_object = EnemyObject()

self.create_enemy(level)

def create_enemy(self, level):

self.total_enemy_list = []
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)
```

Once those classes have been updated you will see the above outcome.

## Further modifying the enemy class

In the previous article, we have successfully created the animation effect for the enemy object, in this article, we will add in the switch direction method which will switch the direction of the enemy image from facing left to facing right after a certain time period and then continue to switch back and forth. In order to achieve the previous mentioned effect we only need to further edit the enemy class. We will move all the enemy object surface creation processes to the enemy class and only leave a small amount of image rendering codes on the enemy sprite class.

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

class Enemy(object):

def __init__(self):

self.count = 0
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 = []

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.switch_position()
self.change_graphic()

def change_graphic(self):
if (self.right == True):
if (self.timer > 30):
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 > 30):
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
```

As you can see we have included another sprite sheet for the right facing images. Now, all we need is to modify the enemy sprite class a little bit.

```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.create_enemy(level)

self.level = level # current game level

self.enemy_object = EnemyObject()

def create_enemy(self, level):
self.total_enemy_list = []
i = 0
if(level == 1):
while(i < 5):
self.total_enemy_list.append(Enemy())
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):

self.draw_pos = mt.Vector2(self.space * column, self.space * row) # the position of the image on game scene

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

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

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)
```

Basically, we will get the below outcome after we have changed the above classes.

## Modify the enemy sprite’s animation

After we have finished creating our first animated enemy sprite in the previous chapter we will need to further modify that animation class because I have found numerous shortages in the previous program. In the previous program 1) We only create a single counter to handle the sprite animation for all five enemy objects which is simply unrealistic because during the game not every enemy will move to the same frame on the sprite sheet due to the change of the direction of that enemy. 2) There is no adjustment on the image’s transition speed at all, we need to slow down the image transition process so the image will not change too fast.

With all that taking into the consideration we will create an enemy class which will handle each enemy movement differently.

```class Enemy(object):

def __init__(self):

self.count = 0
self.forward = False
self.timer = 0

def update(self):
if(self.timer &amp;gt; 30):
if (self.count &amp;gt; 6 and self.forward == True):  # use this logic to control the counter and the image
self.count -= 1
self.forward = False
elif (self.count &amp;lt; 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

def get_count(self):

if(self.count &amp;lt; 1 and self.forward == False):
self.count += 1
self.forward = True
elif(self.count &amp;gt; 6 and self.forward == True):
self.count -= 1
self.forward = False

return self.count
```

The above class consists of a image’s counter and a timer which controls the speed of the image transition process.

Now we just need to modify the enemy manager class and the enemy sprite manager class accordingly.

```from EnemySprite import EnemySprite

class EnemyManager(object):

def __init__(self, scene, game_level):

self.scene = scene
self.enemy_list = []
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 check_boundary(self):

pass

def draw(self):

self.enemy.draw()
```
```from EnemyObject import EnemyObject
from pygame.locals import *
from pygame import math as mt
from GameSprite import GameSprite
from Enemy import Enemy

class EnemySprite(object):

def __init__(self, level, scene):

self.row = 10
self.column = 10
self.enemy_image_sprite = 'Asset/right.png'
self.scene = scene # game scene instance
self.space = 64 # image width and height

self.sprite_frame_list = []

self.create_enemy(level)

# the first frame
self.frame_1_rect = Rect(0, 0, 64, 64)
self.sprite_frame_1 = GameSprite(self.enemy_image_sprite, self.frame_1_rect)
self.sprite_frame_1_surface = self.sprite_frame_1.getImage()
self.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(self.enemy_image_sprite, self.frame_2_rect)
self.sprite_frame_2_surface = self.sprite_frame_2.getImage()
self.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(self.enemy_image_sprite, self.frame_3_rect)
self.sprite_frame_3_surface = self.sprite_frame_3.getImage()
self.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(self.enemy_image_sprite, self.frame_4_rect)
self.sprite_frame_4_surface = self.sprite_frame_4.getImage()
self.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(self.enemy_image_sprite, self.frame_5_rect)
self.sprite_frame_5_surface = self.sprite_frame_5.getImage()
self.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(self.enemy_image_sprite, self.frame_6_rect)
self.sprite_frame_6_surface = self.sprite_frame_6.getImage()
self.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(self.enemy_image_sprite, self.frame_7_rect)
self.sprite_frame_7_surface = self.sprite_frame_7.getImage()
self.sprite_frame_list.append(self.sprite_frame_7_surface)

self.level = level # current game level

self.enemy_object = EnemyObject()

def create_enemy(self, level):
self.total_enemy_list = []
i = 0
if(level == 1):
while(i &amp;lt; 5):
self.total_enemy_list.append(Enemy())
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):

self.draw_pos = mt.Vector2(self.space * column, self.space * row) # the position of the image on game scene

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

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

self.scene.blit(self.sprite_frame_list[self.enemy.get_count()], self.draw_pos)  # draw enemy frame

self.counter += 1

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

Finally, we do a little bit of modification by activated the update method of the enemy manager instance on the game manager class.

```from Player import 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

class GameManager(object):

def __init__(self, scene):

self.scene = scene

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.GAME = 1
self.OVER = 2
self.NEXT = 3
self.WIN = 4
self.MANUAL = 6
self.PAUSE = 7
self.SCORE = 8
self.SCENE = 9

def setup(self, game_level):

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

def loop(self):

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
self.state = self.GAME
elif (self.rect_play.collidepoint(x, y) and self.state == self.PAUSE):
self.state = self.GAME
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):
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.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)):
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 play_music(self):
pygame.mixer_music.play(-1) #play the music infinite time

def set_player_x(self, _x):
if (self.state == self.GAME):
self.player.setX(_x)

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

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

def set_missile_strike(self, strike):
if (self.state == self.GAME):
self.player.setStrike(strike)

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

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

def draw(self):
if(self.state == self.GAME):
self.background.draw()
#self.player.draw()
#self.enemy_manager.update()
self.enemy_manager.draw()
#self.explosion_manager.draw()
#self.score_manager.draw()
pygame.display.flip()
```

With that, we have made the sprite animation a lot more efficient than the previous one. We will continue to work on the enemy sprite movement in the next chapter. If you want to support this site do consider to donate a few crypto coins to fund this project, the crypto addresses are on the sidebar of this website.

http://islandstropicalman.tumblr.com/post/182577491488/pygame

## Create the animation character on the maze

Today we are going to create the animated enemy for our new pygame project. We are going to edit the enemy manager class and the game manager class then we are going to create an enemy sprite class and an enemy object class which will serve as the original sprite container just like the previous background object class does.

Alright, let us get the thing going. First of all we are going to create the enemy object class which will hold the list which contains the initial enemy object’s position on the maze board for each level.

```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]
]

def get_object_list(self, level):

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

The above class is just like the background object class which you have seen previously.

Next we will create the enemy sprite class which will perform the same job as the background sprite class which is to render the enemy object on the game scene.

```from EnemyObject import EnemyObject
from pygame.locals import *
from pygame import math as mt
from GameSprite import GameSprite

class EnemySprite(object):

def __init__(self, level, scene):

self.row = 10
self.column = 10
self.enemy_image_sprite = 'Asset/right.png'
self.scene = scene # game scene instance
self.space = 64 # image width and height

self.sprite_frame_list = []
self.count = -1 # frame controller
self.forward = False # switch to move counter forward or backward

# the first frame
self.frame_1_rect = Rect(0, 0, 64, 64)
self.sprite_frame_1 = GameSprite(self.enemy_image_sprite, self.frame_1_rect)
self.sprite_frame_1_surface = self.sprite_frame_1.getImage()
self.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(self.enemy_image_sprite, self.frame_2_rect)
self.sprite_frame_2_surface = self.sprite_frame_2.getImage()
self.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(self.enemy_image_sprite, self.frame_3_rect)
self.sprite_frame_3_surface = self.sprite_frame_3.getImage()
self.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(self.enemy_image_sprite, self.frame_4_rect)
self.sprite_frame_4_surface = self.sprite_frame_4.getImage()
self.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(self.enemy_image_sprite, self.frame_5_rect)
self.sprite_frame_5_surface = self.sprite_frame_5.getImage()
self.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(self.enemy_image_sprite, self.frame_6_rect)
self.sprite_frame_6_surface = self.sprite_frame_6.getImage()
self.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(self.enemy_image_sprite, self.frame_7_rect)
self.sprite_frame_7_surface = self.sprite_frame_7.getImage()
self.sprite_frame_list.append(self.sprite_frame_7_surface)

self.level = level # current game level

self.enemy_object = EnemyObject()

def draw(self):

for row in range(self.row):

for column in range(self.column):

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 < 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.draw_pos = mt.Vector2(self.space * column, self.space * row) # the position of the image on game scene

if(self.enemy_list[row][column] == 1):
self.scene.blit(self.sprite_frame_list[self.count], self.draw_pos)  # draw enemy frame

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

The above class is more complicated than the background sprite class but the idea is the same, which is to render the game’s object on the scene. We will come back to further modify this class in the next chapter but for now this class will just initiate the enemy object on the game scene and then continuously animates the enemy object on each update.

Our next target is to modify the enemy manager class accordingly.

```from EnemySprite import EnemySprite

class EnemyManager(object):

def __init__(self, scene, game_level):

self.scene = scene
self.enemy_list = []
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):

pass

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

pass

def draw(self):

self.enemy.draw()
```

Then on the game manager class, we will call the enemy manager class to prepare and to draw the enemy object during each game loop.

```from Player import 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

class GameManager(object):

def __init__(self, scene):

self.scene = scene

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.GAME = 1
self.OVER = 2
self.NEXT = 3
self.WIN = 4
self.MANUAL = 6
self.PAUSE = 7
self.SCORE = 8
self.SCENE = 9

def setup(self, game_level):

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

def loop(self):

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
self.state = self.GAME
elif (self.rect_play.collidepoint(x, y) and self.state == self.PAUSE):
self.state = self.GAME
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):
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.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)):
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 play_music(self):
pygame.mixer_music.play(-1) #play the music infinite time

def set_player_x(self, _x):
if (self.state == self.GAME):
self.player.setX(_x)

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

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

def set_missile_strike(self, strike):
if (self.state == self.GAME):
self.player.setStrike(strike)

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

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

def draw(self):
if(self.state == self.GAME):
self.background.draw()
#self.player.draw()
self.enemy_manager.draw()
#self.explosion_manager.draw()
#self.score_manager.draw()
pygame.display.flip()
```

That is it, as we slowly develop our new pygame project we will further edit the above game manager class.

http://islandstropicalman.tumblr.com/post/182491960069/pygame-project

If you like this tutorial and you have excessive bitcoins or other cryptocurrencies then kindly do consider to support this site by donating any amount of them through the below donation box. I have created many sites like this one and I do need cryptocurrencies to pay for the web hosting package so those sites include this one will be able to continue producing free source code for those who need it. Every cent you pay will be used to fund this free source code’s website and the other free source code sites that I have created so please help me out if it is possible. A little amount such as a few dollars will do, thank you very much indeed.

• Bitcoin
• Ethereum
• Bitcoin cash
• Litecoin
• Stellar

## Donate Bitcoin to this address

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

## Donate Ethereum to this address

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

## Donate Bitcoin cash to this address

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

## Donate Litecoin to this address

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

## Donate Stellar to this address

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

## Change the direction of the enemy ship

Besides continue developing and posting the previous project, I will also start to write about the next pygame project which is a maze game project in this same website, so make sure you subscribed to this website by clicking on the bell button below this post.

Alright, so much for that, now let us continue with the previous pygame project which we will now change the direction of the enemy ship from which previously moves horizontally from left to right to move in both directions instead. In the previous program, a new enemy ship which moves from left to right will be created each time the player has destroyed the old one which makes the path of that enemy ship always look the same. In this new update, we will change the direction of the new enemy ship from right to left if the old one which gets destroyed is moving from left to right and vice-versa. In order to achieve this, we only need to edit the enemy manager class like before.

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

class EnemyManager(object):

def __init__(self, scene, player, game_level):

self.enemy_missile_manager = EnemyMissileManager()
self.scene = scene
self.player = player
self.enemy_count = 10
self.horizontal_enemy_count = 1
self.missile_count = 60
self.enemy_list = []
self.horizontal_enemy_list = []
self.image = 'Asset/enemy0.png'
self.image1 =  'Asset/enemy1.png'
self.image2 = 'Asset/enemy2.png'
self.width = 30
self.height = 30
self.width1 = 130
self.height1 = 130
self.rect = Rect(0, 0, self.width, self.height)
self.rect1 = Rect(0, 0, self.width1, self.height1)
self.more_enemy = 0
self.y = -50
self.boundary_width = 660
self.boundary_height = 660
self.object_pool = Objectpool(self.enemy_count)
self.horizontal_object_pool = Objectpool(self.horizontal_enemy_count)
self.next_enemy = 0
self.level = game_level

# initialize game sprite object
self.sprite = GameSprite(self.image, self.rect)
self.sprite1 = GameSprite(self.image1, self.rect)
self.sprite2 = GameSprite(self.image2, self.rect1)

def create_enemy(self, x, y):

if(self.enemy_count &gt; 0):

if(self.object_pool.getSize() &gt; 0): # get the ship from object pool if the pool is not empty
self.enemy_list.append(self.object_pool.obtain())
else: # objects setup based on the level of the game
if(self.level == 1):
self.enemy_surface = self.sprite.getImage()
elif(self.level == 2 or self.level == 3):
if(self.next_enemy == 0):
self.enemy_surface = self.sprite.getImage()
self.next_enemy += 1
elif(self.next_enemy == 1):
self.enemy_surface = self.sprite1.getImage()
self.next_enemy = 0
self.enemy_list.append(Enemy(self.enemy_surface, x, y))
self.enemy_count -= 1

def create_horizontal_enemy(self, x, y):

if (self.horizontal_enemy_count &gt; 0):

if (self.horizontal_object_pool.getSize() &gt; 0):  # get the ship from object pool if the pool is not empty
self.horizontal_enemy_list.append(self.horizontal_object_pool.obtain())
else:  # objects setup based on the level of the game
if (self.level == 3):
self.enemy_surface1 = self.sprite2.getImage()
self.horizontal_enemy_list.append(Enemy1(self.enemy_surface1, x, y))
self.horizontal_enemy_count -= 1

def update(self):

if (self.level == 1 or self.level == 2):

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

elif(self.level == 3):

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

if(self.horizontal_enemy_count &gt; 0):
self.create_horizontal_enemy(-130, 200)  # create new enemy

self.create_enemy_missile()
self.enemy_update()
self.check_boundary()

def create_enemy_missile(self):

for item in list(self.enemy_list):

if(self.player.pos.y - item.y  &lt; 200 and abs(self.player.pos.x - item.x) &lt; 160):

item.create_enemy_missile(self.enemy_missile_manager)

if(self.level == 3):

for item in list(self.horizontal_enemy_list):
item.create_enemy_missile(self.enemy_missile_manager)

def enemy_update(self):

for item in list(self.enemy_list):

if(item.on == False):
self.enemy_list.remove(item)
self.enemy_count += 1
item.y = self.y
item.on = True
self.object_pool.recycle(item)
else:
if ((self.player.pos.y - item.y &lt; 200 and self.player.pos.y - item.y &gt; -2) and abs(self.player.pos.x - item.x) &lt; 200):
item.update((self.player.pos.x - item.x) * 0.004, 0.1)
else:
item.update(0, 0.1)

if (self.level == 3):

for item in list(self.horizontal_enemy_list):

if (item.on == False):

self.horizontal_enemy_count += 1
item.y = 220

if(item.direction == True):
item.x = 800
item.direction = False
else:
item.x = -130
item.direction = True
self.horizontal_enemy_list.remove(item)
item.on = True
self.horizontal_object_pool.recycle(item)

else:
item.update()

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

for i in range(len(self.enemy_list)):
if (self.enemy_list[i].y &gt; self.boundary_height):
self.enemy_list[i].on = False

if (self.level == 3):
for i in range(len(self.horizontal_enemy_list)):
if (self.horizontal_enemy_list[i].x &gt; self.boundary_width):
self.horizontal_enemy_list[i].direction = False
elif(self.horizontal_enemy_list[i].x &lt;= -130):
self.horizontal_enemy_list[i].direction = True

def draw(self):

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

if(self.level == 3):
for i in range(len(self.horizontal_enemy_list)):
self.scene.blit(self.horizontal_enemy_list[i].enemy_surface, self.horizontal_enemy_list[i].enemy_pos)
self.horizontal_enemy_list[i].missile_draw(self.scene)
```

By changing the above program we will be able to achieve that change of path effect for the horizontally moving enemy ship.

I wish you all the best of luck in the year 2019 and stay tuned for more game development articles in this website.

## The beginning of Game AI

We have basically finished including all the game features in our pygame project and we are now ready to further tune up this pygame project. In this article, we will further tune up the path of the enemy ships. In the previous program, the enemy ship is moving downward in the vertical position and shooting missile at the player if the distance between the player and the enemy is close enough. In this article, we will make the enemy a lot smarter than previously by making it moves toward the direction of the player when it spots the player within a certain range.

We will need to modify the enemy class’s update method by including the x and the y parameter into it that will be used to adjust the path of the enemy ship to make it moves toward the player direction during the game.

```from pygame import math as mt
from Objectpool import Objectpool

class Enemy(object):

def __init__(self, enemy_surface, x, y):

self.on = True
self.enemy_surface = enemy_surface
self.x = x
self.y = y
self.hit = False
self.enemy_pos = mt.Vector2(self.x, self.y)
self.missile_count = 10
self.missile_timer = 0
self.missile_object_pool = Objectpool(self.missile_count)
self.missile_list = []

def update(self, x, y):
self.y += y
self.x += x
self.enemy_pos = mt.Vector2(self.x, self.y)
self.missile_update(self.missile_object_pool)

def missile_update(self, pool):

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

def missile_draw(self, scene): # draw enemy missiles on game scene
for item in list(self.missile_list):
scene.blit(item.missile_surface, item.missile_pos)

def create_enemy_missile(self, enemy_missile_manager):

if(self.missile_timer &gt; 300):

self.missile_timer = 0

if (self.missile_object_pool.getSize() &gt; 0):
enemy_missile_manager.create_missile(self.x + 5, self.y + 4, self.missile_object_pool, self.missile_list)
else:
enemy_missile_manager.create_missile(self.x + 5, self.y + 4, None, self.missile_list)

else:

self.missile_timer += 1
```

The next class we need to modify is the enemy manager class which we will adjust the range where the enemy will fire a missile at the player as well as creating the range where the enemy will start to move toward the player during the game.

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

class EnemyManager(object):

def __init__(self, scene, player, game_level):

self.enemy_missile_manager = EnemyMissileManager()
self.scene = scene
self.player = player
self.enemy_count = 10
self.horizontal_enemy_count = 1
self.missile_count = 60
self.enemy_list = []
self.horizontal_enemy_list = []
self.image = 'Asset/enemy0.png'
self.image1 =  'Asset/enemy1.png'
self.image2 = 'Asset/enemy2.png'
self.width = 30
self.height = 30
self.width1 = 130
self.height1 = 130
self.rect = Rect(0, 0, self.width, self.height)
self.rect1 = Rect(0, 0, self.width1, self.height1)
self.more_enemy = 0
self.y = -50
self.boundary_width = 660
self.boundary_height = 660
self.object_pool = Objectpool(self.enemy_count)
self.horizontal_object_pool = Objectpool(self.horizontal_enemy_count)
self.next_enemy = 0
self.level = game_level

# initialize game sprite object
self.sprite = GameSprite(self.image, self.rect)
self.sprite1 = GameSprite(self.image1, self.rect)
self.sprite2 = GameSprite(self.image2, self.rect1)

def create_enemy(self, x, y):

if(self.enemy_count &gt; 0):

if(self.object_pool.getSize() &gt; 0): # get the ship from object pool if the pool is not empty
self.enemy_list.append(self.object_pool.obtain())
else: # objects setup based on the level of the game
if(self.level == 1):
self.enemy_surface = self.sprite.getImage()
elif(self.level == 2 or self.level == 3):
if(self.next_enemy == 0):
self.enemy_surface = self.sprite.getImage()
self.next_enemy += 1
elif(self.next_enemy == 1):
self.enemy_surface = self.sprite1.getImage()
self.next_enemy = 0
self.enemy_list.append(Enemy(self.enemy_surface, x, y))
self.enemy_count -= 1

def create_horizontal_enemy(self, x, y):

if (self.horizontal_enemy_count &gt; 0):

if (self.horizontal_object_pool.getSize() &gt; 0):  # get the ship from object pool if the pool is not empty
self.horizontal_enemy_list.append(self.horizontal_object_pool.obtain())
else:  # objects setup based on the level of the game
if (self.level == 3):
self.enemy_surface1 = self.sprite2.getImage()
self.horizontal_enemy_list.append(Enemy1(self.enemy_surface1, x, y))
self.horizontal_enemy_count -= 1

def update(self):

if (self.level == 1 or self.level == 2):

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

elif(self.level == 3):

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

if(self.horizontal_enemy_count &gt; 0):
self.create_horizontal_enemy(-130, 200)  # create new enemy

self.create_enemy_missile()
self.enemy_update()
self.check_boundary()

def create_enemy_missile(self):

for item in list(self.enemy_list):

if(self.player.pos.y - item.y  &lt; 200 and abs(self.player.pos.x - item.x) &lt; 160):

item.create_enemy_missile(self.enemy_missile_manager)

if(self.level == 3):

for item in list(self.horizontal_enemy_list):
item.create_enemy_missile(self.enemy_missile_manager)

def enemy_update(self):

for item in list(self.enemy_list):

if(item.on == False):
self.enemy_list.remove(item)
self.enemy_count += 1
item.y = self.y
item.on = True
self.object_pool.recycle(item)
else:
if ((self.player.pos.y - item.y &lt; 200 and self.player.pos.y - item.y &gt; -2) and abs(self.player.pos.x - item.x) &lt; 200):
item.update((self.player.pos.x - item.x) * 0.005, 0.1)
else:
item.update(0, 0.1)

if (self.level == 3):

for item in list(self.horizontal_enemy_list):
if (item.on == False):
self.horizontal_enemy_list.remove(item)
self.horizontal_enemy_count += 1
item.y = 220
item.x = -130
item.on = True
self.horizontal_object_pool.recycle(item)
else:
item.update()

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

for i in range(len(self.enemy_list)):
if (self.enemy_list[i].y &gt; self.boundary_height):
self.enemy_list[i].on = False

if (self.level == 3):
for i in range(len(self.horizontal_enemy_list)):
if (self.horizontal_enemy_list[i].x &gt; self.boundary_width):
self.horizontal_enemy_list[i].direction = False
elif(self.horizontal_enemy_list[i].x &lt;= -130):
self.horizontal_enemy_list[i].direction = True

def draw(self):

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

if(self.level == 3):
for i in range(len(self.horizontal_enemy_list)):
self.scene.blit(self.horizontal_enemy_list[i].enemy_surface, self.horizontal_enemy_list[i].enemy_pos)
self.horizontal_enemy_list[i].missile_draw(self.scene)
```

Now, whenever the enemy spots the player within a certain range it will move toward that player.

## Lets put the game instruction online instead

In the previous article we have successfully created an about page which contains both game instruction as well as game credit, however it is better to put the game instruction into it’s own page to make our game looks more professional. In this article we are going to create an online game manual which will open up once the player has clicked on the manual button on the main game page.

Lets go ahead and create the game manual button on the start scene class just like we did previously for the about button. We will also create an offline manual page for this game just like how we create the about page but we are not going to use it at the moment, this page is for the future use just in case we want to bring the manual page offline. Here is the modify version of the start scene class with a new manual button.

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

class StartScene(object):

def __init__(self, scene):
self.scene = scene
self.play_button = 'Asset/play.png'
self.score_button = 'Asset/score.png'
self.home_button = 'Asset/back.png'
self.button_image = 'Asset/button_play.png'
self.manual_button = 'Asset/manual.png'
self.bg_image = 'Asset/start.png'
self.over_image = 'Asset/ove.png'
self.next_image = 'Asset/next.png'
self.win_image = 'Asset/winn.png'
self.general_image = 'Asset/general.png'
self.manual_page = 'Asset/manual_page.png'
self.soundon = 'Asset/sound.png'
self.soundoff = 'Asset/soundoff.png'
self.bg_rect = Rect(0, 0, 660, 660)
self.button_rect = Rect(0, 0,  306, 112)
self.home_button_rect = Rect(0, 0, 200, 53)
self.back_button_rect = Rect(0, 0, 40, 30)
self.sound_button_rect = Rect(0, 0, 29, 30)

self.sprite = BgSprite(self.bg_image, self.bg_rect)
self.sprite_manual = BgSprite(self.manual_page, self.bg_rect)
self.sprite_win = BgSprite(self.win_image, self.bg_rect)
self.sprite_over = BgSprite(self.over_image, self.bg_rect)
self.sprite_next = BgSprite(self.next_image, self.bg_rect)

self.soundon_button = GameSprite(self.soundon, self.sound_button_rect)
self.soundoff_button = GameSprite(self.soundoff, self.sound_button_rect)

self.soundoff_button_surface = self.soundoff_button.getImage()  # get the button sprite surface
self.soundon_button_surface = self.soundon_button.getImage()  # get the button sprite surface

self.sprite_button = GameSprite(self.button_image, self.button_rect)
self.sprite_manual_button = GameSprite(self.manual_button, self.home_button_rect)
self.sprite_play_button = GameSprite(self.play_button, self.home_button_rect)
self.sprite_score_button = GameSprite(self.score_button, self.home_button_rect)
self.sprite_home_button = GameSprite(self.home_button, self.back_button_rect)
self.manual_surface = self.sprite_manual.getImage()  # get the manual sprite surface
self.win_surface = self.sprite_win.getImage()  # get the win sprite surface
self.next_surface = self.sprite_next.getImage()  # get the next level sprite surface
self.over_surface = self.sprite_over.getImage()  # get the game over sprite surface
self.surface = self.sprite.getImage()  # get the start scene sprite surface
self.button_surface = self.sprite_button.getImage() # get the button sprite surface
self.play_button_surface = self.sprite_play_button.getImage()  # get the button sprite surface
self.score_button_surface = self.sprite_score_button.getImage()  # get the button sprite surface
self.manual_button_surface = self.sprite_manual_button.getImage()  # get the button sprite surface
self.home_button_surface = self.sprite_home_button.getImage()  # get the button sprite surface
self.draw_pos = mt.Vector2(0, 0)
self.draw_button_pos = mt.Vector2(177, 274)
self.draw_play_button_pos = mt.Vector2(229, 200)
self.draw_score_button_pos = mt.Vector2(229, 328)
self.draw_manual_button_pos = mt.Vector2(229, 393)
self.draw_back_button_pos = mt.Vector2(10, 620)

self.draw_sound_button_pos = mt.Vector2(10, 620)

self.soundon = True

def draw(self, state):

if(state == 0):
self.scene.blit(self.surface, self.draw_pos) # draw a start scene sprite
self.scene.blit(self.play_button_surface, self.draw_play_button_pos)  # draw a button sprite
self.scene.blit(self.score_button_surface, self.draw_score_button_pos)  # draw a button sprite
self.scene.blit(self.manual_button_surface, self.draw_manual_button_pos)  # draw a button sprite
if(self.soundon == True):
self.scene.blit(self.soundon_button_surface, self.draw_sound_button_pos)  # draw a button sprite
else:
self.scene.blit(self.soundoff_button_surface, self.draw_sound_button_pos)  # draw a button sprite
elif(state == 2):
self.scene.blit(self.over_surface, self.draw_pos)  # draw a game over sprite

elif (state == 3):
self.scene.blit(self.next_surface, self.draw_pos)  # draw a next level sprite

elif(state == 4):
self.scene.blit(self.win_surface, self.draw_pos)  # draw a win sprite

elif (state == 5):
self.scene.blit(self.home_button_surface, self.draw_back_button_pos)  # draw a button sprite

elif (state == 6):
self.scene.blit(self.manual_surface, self.draw_pos)  # draw a manual sprite
self.scene.blit(self.home_button_surface, self.draw_back_button_pos)  # draw a button sprite

if(state == 2 or state == 3 or state == 4):
self.scene.blit(self.button_surface, self.draw_button_pos)  # draw a button sprite

pygame.display.flip()
```

Next we will modify the game manager class, we will create a new game state for the game manual but we are not going to use it now because we will directly open up a web browser with the help of the python’s webbrowser module. Here is the modify version of the game manager class.

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

class GameManager(object):

def __init__(self, scene):

self.scene = scene
self.start_scene = StartScene(scene)
self.play_music()
self.overlap_manager = Overlap()
self.level_manager = LevelManager(self)

self.setup(self.level_manager.get_level())

#game state
self.GAME = 1
self.OVER = 2
self.NEXT = 3
self.WIN = 4
self.MANUAL = 6

def setup(self, game_level):

self.game_level = game_level
self.score_manager = Score(self.scene)
self.background = Background(self.scene)

self.player = Player(self.scene)
self.enemy_manager = EnemyManager(self.scene, self.player, game_level)
self.explosion_manager = ExplosionManager(self.scene)

def loop(self):

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.MANUAL):

self.start_scene.draw(self.state)

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

self.update()
self.draw()

def isAreaClick(self, pos):
if (self.state == self.LOAD or self.state == self.OVER or self.state == self.NEXT or self.state == self.WIN or self.state == self.ABOUT or self.state == self.MANUAL):
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_manual = Rect(229, 393, 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, 620, 29, 30) # the position of the sound button on the home scene
x, y = pos
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
self.state = self.GAME
elif (self.rect_manual.collidepoint(x, y) and self.state == self.LOAD):
#self.state = self.MANUAL
webbrowser.open_new('http://gamingdirectional.com/')
elif (self.rect_back.collidepoint(x, y) and (self.state == self.ABOUT or self.state == self.MANUAL)):
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 play_music(self):
pygame.mixer_music.play(-1) #play the music infinite time

def set_player_x(self, _x):
if (self.state == self.GAME):
self.player.setX(_x)

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

def set_missile_strike(self, strike):
if (self.state == self.GAME):
self.player.setStrike(strike)

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

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

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

That is it, when you have clicked on the manual button on the home scene the online manual page will open up!