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

    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

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

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

Leave a Reply

Your email address will not be published. Required fields are marked *