Create Enemy Missile and Enemy Missile Manager

In this article we will create two new classes, enemy missile class and the enemy missile manager class. The enemy missile manager class will be called during each game loop by the enemy manager class to create new enemy missile as well as to update the position of those missiles and draw them on the game scene.

First of all, we will create the enemy missile class which will be used by the enemy missile manager class to create the enemy missile object.

This enemy missile class looks simple and it indeed is simple.

from pygame import math as mt

class Enemymissile(object):

    def __init__(self, missile_surface, x, y):
        self.on = True
        self.missile_surface = missile_surface
        self.x = x
        self.y = y
        self.height = 20
        self.width = 20
        self.missile_pos = mt.Vector2(self.x, self.y)

    def update(self):
        self.y += 1
        self.missile_pos = mt.Vector2(self.x, self.y)

The only method which is matter in the above class is the update method which will be used to update the position of that enemy missile in every game loop.

The next class is the enemy missile manager class which will be used to create and to control the enemy missiles.

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

class EnemyMissileManager(object):
    
    def __init__(self, scene, player):

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

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

    def create_missile(self, x, y):

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

    def update(self):

        self.missile_update()
        self.check_boundary()

    def missile_update(self):

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

    def check_boundary(self):

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

    def draw(self):

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

The enemy missile manager class above has below methods:

1) create missile method will create more enemy missile and will be called by the enemy manager class.
2) the update method will call the missile update and the check missile boundary method that will update the position of those missiles and remove those missiles after they have crossed the game scene boundary.
3) the draw method will draw those missiles on the game scene.

Now after we have created those two new classes, we will need to modify the enemy manager class which we have created previously.

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

class EnemyManager(object):

    def __init__(self, scene, player):

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

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

    def create_enemy(self, x, y):
        if(self.enemy_count > 0):
            self.enemy_surface = self.sprite.getImage()
            self.enemy_list.append(Enemy(self.enemy_surface, x, y))
            self.enemy_count -= 1

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

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

    def create_enemy_missile(self):
        for item in list(self.enemy_list):
            if(item.missile_count > 0):
                if(self.player.pos.y - item.y  < 100 and abs(self.player.pos.x - item.x) < 60 ):
                    self.enemy_missile_manager.create_missile(item.x + 5, item.y + 4)
                    item.missile_count -= 1

    def enemy_update(self):

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

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

    def draw(self):

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

The create enemy missile method under the update method will create new enemy missiles during the each game loop update and the missile will only get created when the enemy ship is getting close enough to the player ship because there is no point to fire the missile if the distance between the player ship and the enemy ship is so far apart. We also will need to check for the total missiles an enemy ship can launch before this method can create a new missile from that particular enemy ship. We might want to assign each enemy with it’s own enemy missile manager object so we can better control the missile launching time later on but for now we will create only one enemy missile manager object which will be used by the enemy manager object to create new enemy missiles. The update method of the enemy manager also will call the update method of the enemy missile manager which we have already gone through previously.

Finally the enemy manager draw method will call the enemy missile manager’s draw method to draw those missiles on the game scene during each game loop.

As you can see no contact has been detected yet in this game, we will create the contact manager in our up and coming articles to find out whether the player has hit the enemy ship, the enemy ship has been hit by the player missile and the player has been hit by the enemy missile or not!