Air Strike

Air Strike is a single player shooting game for windows os laptop user. In this game, you will need to shoot down as many enemy ships as possible to advance to the next level. Make sure you are not getting hit by the enemy ship or else it will be game over. Also, do avoid as many enemy missiles as possible. The game will have 10 levels in total and currently it is at level 3, I will continue to create one game level per week after the beta stage of this game has been released on major game sites until this game has finally reached level 10. After that, I will continue to include more features into the game which means although you are playing the same level again and again but each time you will find out that a new game character has been added into that same level after each game’s updates.

Game Instruction: Use the right, left, up and down arrow key on your keyboard to move the ship around. Use the space bar to shoot a missile at the enemy. Press ‘p’ during the game will bring out the pause screen where you can then continue to play the game or go back to the home page. Press ‘s’ on the keyboard will save a copy of the screenshot during the game.

Game Scene

You can download this game through below game sites.

Download Air Strike

This game is still in it’s beta stage which means it is more like a demo game for python program rather than a real game but no worry because more features will be included from now onward! If you find any bug in this game do let me know through the comment box below this main post.

Hope you will enjoy this game and let you friend knows about it!

The game is ready for upload

Welcome to the final chapter of this pygame project where we have finally concluded the pygame project which has been ongoing for some time already. In this chapter I have just made a slight modification on the overlap class by reducing the points the player can get when the player missile hits the larger enemy ship.

from pygame.locals import *

class Overlap(object):

    def __init__(self):
        pass # nothing here

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

        self.checkOverlap(em.enemy_list, player, ex, gm, score, em.width, em.height, em.enemy_missile_manager.width, em.enemy_missile_manager.height, None)

        if(gm.level_manager.get_level() == 3):
            self.checkOverlap(em.horizontal_enemy_list, player, ex, gm, score, em.width1, em.height1, em.enemy_missile_manager.width, em.enemy_missile_manager.height, gm.level_manager.get_level())

    def checkOverlap(self, e_list, player, ex, gm, score, width, height, m_width, m_height, level):

        self.player_rect = Rect(player.pos.x, player.pos.y, player.width, player.height)

        for i in range(len(e_list)):  # is player collides with enemy

            self.em_rect = Rect(e_list[i].x, e_list[i].y, width, height)
            if (self.player_rect.colliderect(self.em_rect)):
                e_list[i].on = False
                if (e_list[i].hit == False):
                    ex.create_explosion(player.pos.x + 2, player.pos.y + 2)
                    e_list[i].hit = True
                    gm.state = gm.OVER
                    gm.setup(gm.level_manager.get_level())

        for i in range(len(e_list)):  # is enemy missile hits player

            for j in range(len(e_list[i].missile_list)):
                self.em_rect = Rect(e_list[i].missile_list[j].x, e_list[i].missile_list[j].y,
                                    m_width, m_height)
                if (self.player_rect.colliderect(self.em_rect)):
                    e_list[i].missile_list[j].on = False
                    ex.create_explosion(player.pos.x + 2, player.pos.y + 2)
                    score.set_score(-1)
                    if (score.power_y > 100):
                        gm.state = gm.OVER
                        gm.setup(gm.level_manager.get_level())

        for i in range(len(e_list)):  # is player missile hits enemy

            self.em_rect = Rect(e_list[i].x, e_list[i].y, width, height)

            for j in range(len(player.getMissileManager().missile_list)):

                self.mm_rect = Rect(player.getMissileManager().missile_list[j].x,
                                    player.getMissileManager().missile_list[j].y, player.getMissileManager().width,
                                    player.getMissileManager().height)

                if (self.em_rect.colliderect(self.mm_rect)):
                    e_list[i].on = False
                    player.getMissileManager().missile_list[j].on = False
                    if (e_list[i].hit == False):
                        ex.create_explosion(e_list[i].x, e_list[i].y + 2)
                        e_list[i].hit = True

                        if(level == 3):
                            score.set_score(2)
                        else:
                            score.set_score(1)
                        if (score.score >= gm.level_manager.get_level() * 30):
                            gm.level_manager.increase_level()

With that we have concluded this final chapter of our pygame project development tutorial and are now ready to start a brand new one a few days from now. This project which we have finished will be uploaded to the online gaming site where you will be able to download the game setup file for your windows os, at the moment this game is built only for the windows os user but if you have followed my previous tutorials on this project then you will be able to easily recreate this game for Linux and osx as well. I will tidy up the game code and recreate the game graphics before uploading this game to any online gaming site, this will be the last chapter regarding this project but need not worry because while I continue developing this game which only has three levels at the moment I will also start a brand new pygame project starting from the next chapter. I will let you guys know where am I uploading this latest project to in the coming article so you can download it to your windows os’s laptop and then play it.

Before we close this final chapter I would like to talk about my incoming development plan for a while. At the beginning I am planning to create a few games using python and the pygame framework, a few JavaFx games and a few android games using Java. But if you are also a Java developer then you should know that Java has gone through some changes lately, myself is a very careful person and I always think before I make any move which might bring me into trouble, thus I have decided to call off the plan to build desktop game based on JavaFx framework because the Java developer may need to pay the Java 11 license fee starting from the year 2019 and I am really not sure will that includes the JavaFx  as well as Java 8 or not. Although I will not use Java 11 but I am still afraid that even Java 8 will be included into the license fees category in the future so I will just stop all the JavaFx game development projects and then see what will come next. As for the android game, the Android Java version is based on Java 6 if I am not mistaken so it should have no impact at all to the Java developer. Thus here is the revised plan: 1) Create 5 python games 2) Create 5 android games (either using Java 6 or unity/c#). 3) Canceled the JavaFx game projects altogether. You might want to say that it is alright for the Java developer to use the open Java sdk to build the application but I don’t want to take any risk because of nobody knows what will happen to the open Java sdk as well in the future.

Alright, so much for that, it is time to get ready for our next pygame project!

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

            self.missile_timer = 0

            if (self.missile_object_pool.getSize() > 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 > 0):

            if(self.object_pool.getSize() > 0): # get the ship from object pool if the pool is not empty
                self.enemy_list.append(self.object_pool.obtain())
            else: # 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 > 0):

            if (self.horizontal_object_pool.getSize() > 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 > 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 > 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 > 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  < 200 and abs(self.player.pos.x - item.x) < 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 < 200 and self.player.pos.y - item.y > -2) and abs(self.player.pos.x - item.x) < 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 > 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 > self.boundary_width):
                    self.horizontal_enemy_list[i].direction = False
                elif(self.horizontal_enemy_list[i].x <= -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.

The enemy will move toward the player

Lets take a screen shot

Hello, welcome back to the new chapter of this pygame project. Today we are going to create the final feature of the game which is to allow the user to take a screenshot during the game then displays the game scenes just likes a slide show on a new game scene page. Here are what we are going to do:

  1. When the user presses the s key on the keyboard during the game, a screenshot will be taken.
  2. When the user has pressed the scene button on the main page he will be taken to the game’s scene page where he can then view all the screenshots he has taken during the game by navigating with the left and right button on both sides of the page.
  3. If he presses on the back button on the bottom left corner of the page he will be taken back to the main game page.
  4. Each time the screenshot has been taken the latest count value which will be used to increase the filename number will be saved to the count.txt file.
  5. We will need to create the count.txt file by hand first and then enter a 0 value into it which will be used to display the default image file if no screenshot has been taken yet!
  6. The first step we need to do is to create a Screen folder in our project folder which will then be used to keep the left and right navigating images, the count.txt file and all the screenshots that the program has taken.
We need to create the count.txt file by hand

Next, we will create a new Scene class which will be used to display screenshot as well as to take the screenshot.

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

class Scene(object):

    def __init__(self, scene):

        self.scene = scene
        self.screen_folder = 'Screen/'
        self.next_button = 'Screen/right_arrow.png'
        self.previous_button = 'Screen/left_arrow.png'
        self.home_button = 'Asset/back.png'

        self.bg_rect = Rect(0, 0, 660, 660)
        self.next_button_rect = Rect(0, 0,  30, 30)
        self.previous_button_rect = Rect(0, 0, 30, 30)
        self.home_button_rect = Rect(0, 0, 40, 30)
        self.count = 0
        self.next = 1
        self.open_file()
        self.setup()

        self.previous_button_sprite = GameSprite(self.previous_button, self.previous_button_rect)
        self.next_button_sprite = GameSprite(self.next_button, self.next_button_rect)
        self.sprite_home_button = GameSprite(self.home_button, self.home_button_rect)


        self.previous_button_surface = self.previous_button_sprite.getImage() # get the button sprite surface
        self.next_button_surface = self.next_button_sprite.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_next_button_pos = mt.Vector2(610, 330)
        self.draw_previous_button_pos = mt.Vector2(50, 330)
        self.draw_home_button_pos = mt.Vector2(10, 620)

    def open_file(self):

        try:
            f = open("Screen/count.txt", "r")

            try:
                if f.mode == 'r':
                    self.f1 = f.readlines()
                    for x in self.f1:
                        self.count = int(x)
            finally:
                f.close()


        except IOError:
            print('Error')

    def setup(self):

        if(self.count > 0):
            self.general_image = 'Screen/' + str(self.next) + 'game.png'
        else:
            self.general_image = 'Asset/general.png'

        self.screen_sprite = BgSprite(self.general_image, self.bg_rect)
        self.screen_surface = self.screen_sprite.getImage()  # get the screen sprite surface


    def take_screen(self): # take screenshot
        self.count += 1
        self.file_path = 'Screen/' + str(self.count) + 'game.png'
        pygame.image.save(self.scene, self.file_path)
        self.save_file()

    def save_file(self):
        try:
            f = open("Screen/count.txt", "w+")
            try:
                f.write(str(self.count))
            finally:
                f.close()
        except IOError:
            print('cannot save a file')

    def set_next_image(self):

        self.next += 1
        if(self.next > self.count):
            self.next = self.count

        self.setup()

    def set_previous_image(self):

        self.next -= 1

        if(self.next <= 0):
            self.next = 1

        self.setup()

    def draw(self):

        self.scene.blit(self.screen_surface, self.draw_pos)  # draw a game scene sprite
        self.scene.blit(self.previous_button_surface, self.draw_previous_button_pos)  # draw a button sprite
        self.scene.blit(self.next_button_surface, self.draw_next_button_pos)  # draw a button sprite
        self.scene.blit(self.home_button_surface, self.draw_home_button_pos)  # draw a button sprite

        pygame.display.flip()

The next file we need to edit is the start scene class where we will include the scene button into it which will launch the game’s screenshot page when the user has clicked on it.

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

class StartScene(object):

    def __init__(self, scene):

        self.scene = scene
        self.play_button = 'Asset/play.png'
        self.about_button  = 'Asset/about.png'
        self.exit_button = 'Asset/exit.png'
        self.scene_button = 'Asset/scene.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.about_page = 'Asset/about_page.png'
        self.manual_page = 'Asset/manual_page.png'
        self.soundon = 'Asset/sound.png'
        self.soundoff = 'Asset/soundoff.png'
        self.home_button_image = 'Asset/home.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_about = BgSprite(self.about_page, 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.sprite_pause = BgSprite(self.general_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_home_pause_button = GameSprite(self.home_button_image, self.home_button_rect)
        self.sprite_scene_button = GameSprite(self.scene_button, self.home_button_rect)
        self.sprite_manual_button = GameSprite(self.manual_button, self.home_button_rect)
        self.sprite_exit_button = GameSprite(self.exit_button, self.home_button_rect)
        self.sprite_play_button = GameSprite(self.play_button, self.home_button_rect)
        self.sprite_about_button = GameSprite(self.about_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.about_surface = self.sprite_about.getImage()  # get the about sprite surface
        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.pause_surface = self.sprite_pause.getImage()  # get the pause 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.home_pause_button_surface = self.sprite_home_pause_button.getImage() # get the button sprite surface
        self.play_button_surface = self.sprite_play_button.getImage()  # get the button sprite surface
        self.about_button_surface = self.sprite_about_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.scene_button_surface = self.sprite_scene_button.getImage()  # get the button sprite surface
        self.home_button_surface = self.sprite_home_button.getImage()  # get the button sprite surface
        self.exit_button_surface = self.sprite_exit_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_about_button_pos = mt.Vector2(229, 263)
        self.draw_home_button_pos = mt.Vector2(229, 263)
        self.draw_score_button_pos = mt.Vector2(229, 328)
        self.draw_manual_button_pos = mt.Vector2(229, 393)
        self.draw_exit_button_pos = mt.Vector2(229, 456)
        self.draw_scene_button_pos = mt.Vector2(229, 519)
        self.draw_back_button_pos = mt.Vector2(10, 620)

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

        self.soundon = True

        self.font = txt.Font(None, 90)
        self.score_text = "Top Achievements"
        self.text_width, self.text_height = self.font.size(self.score_text)
        self.x_title = 330 - self.text_width/2
        self.y_title = 20
        self.title_rect = Rect(self.x_title, self.y_title, self.text_width, self.text_height)
        self.title_score_text = self.font.render(self.score_text, 1, (255, 255, 255))

        self.score_value_text = ''
        self.f1 = None
        self.font1 = txt.Font(None, 100)
        self.score_rect = Rect(100, self.y_title+self.text_height, 100, 100)

    def recal_level(self): # get the top 5 levels
        self.count = 0
        self.origin = 0
        try:
            f = open("level.txt", "r")

            try:
                if f.mode == 'r':
                    self.f1 = f.readlines()
                    for x in self.f1:
                        self.count += 1
            finally:
                f.close()

        except IOError:
            print('Error')

    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.about_button_surface, self.draw_about_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
            self.scene.blit(self.exit_button_surface, self.draw_exit_button_pos)  # draw a button sprite
            self.scene.blit(self.scene_button_surface, self.draw_scene_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.about_surface, self.draw_pos)  # draw a about sprite
            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

        elif (state == 7):
            self.scene.blit(self.pause_surface, self.draw_pos)  # draw a pause sprite
            self.scene.blit(self.play_button_surface, self.draw_play_button_pos)  # draw a button sprite
            self.scene.blit(self.home_pause_button_surface, self.draw_home_button_pos)  # draw a button sprite

        elif (state == 8):
            self.scene.blit(self.pause_surface,  self.draw_pos)  # draw a score sprite
            self.scene.blit(self.title_score_text, self.title_rect) # the score title first

            while(self.count > 0):
                self.count -= 1
                self.origin += 1
                self.score_rect = Rect(130, self.y_title + self.text_height + self.origin * 80, 100, 100)
                self.score_value_text = str(self.count) + ".) Level " + self.f1[self.count][0:1]
                self.value_score_text = self.font1.render(self.score_value_text, 1, (255, 255, 255))
                self.scene.blit(self.value_score_text, self.score_rect)  # the top 5 levels of the game

            if(self.count <= 0):
                self.count = self.origin
                self.origin = 0

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

Then we will need to edit the game manager class which we will add in the mechanism to take the screenshot and to display the screenshot page. We will also include a new scene state variable into this 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
from Scene import Scene

class GameManager(object):

    def __init__(self, scene):

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

        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.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):
            self.start_scene.recal_level()
            self.level_manager.set_level()
            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, 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.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, 620, 29, 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
            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
            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_exit.collidepoint(x, y) and self.state == self.LOAD):
                exit()
            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())

                try:
                    f = open("level.txt", "a+")
                    try:
                        f.write('\n' + str(self.level_manager.get_level()))
                    finally:
                        f.close()
                except IOError:
                    print ('cannot open a file')

            elif (self.rect_manual.collidepoint(x, y) and self.state == self.LOAD):
                webbrowser.open_new('http://gamingdirectional.com/')
            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 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.draw()
            self.explosion_manager.draw()
            self.score_manager.draw()
            pygame.display.flip()

The final file we need to edit is the main file where we will add in the s key pressed event handler which will be used to trigger the game manager to take the screenshot during the game.

With that we have finally concluded the last piece of feature for this pygame project, our next mission is to tune up the game engine, tidy up the code and create better game graphic.

Pygame screenshot slideshow

Create a power bar for pygame project

In this chapter, we are going to create the last piece of game feature which is the player’s power bar, after this, I will do all the touches up to this game project which certainly includes to tidy up the game code before uploading the game to the pygame portal. Alright, let’s get to work.

The first file which we will need to edit is the score manager file where we will create a power bar object on the lower right corner of the game scene. What we will do here is to deduct the height of the original power bar whenever an enemy missile hits the player ship.

The next file which we need to edit is the overlap file where it will be game over if the value of the power_y variable of the score manager has get passed 100 which is equal to the total height of the power bar.

import pygame.font as txt
from pygame.locals import *
from BgSprite import BgSprite
from pygame import math as mt

class Score(object):

    def __init__(self, scene):

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

        #power bar setup

        self.power = 'Asset/power.png'
        self.power_rect = Rect(0, 0, 40, 100)
        self.power_sprite = BgSprite(self.power, self.power_rect)
        self.power_surface = self.power_sprite.getImage()
        self.draw_power_pos = mt.Vector2(600, 540)
        self.power_y = 0
        self.o_p = 100

    def set_score(self, score):

        self.score += score

        if(score < 0):
            self.power_y += 1
            self.draw_power_pos = mt.Vector2(600, 540 - self.power_y)
            self.power_rect = Rect(0, self.power_y, 40, self.o_p - self.power_y)
            self.power_sprite = BgSprite(self.power, self.power_rect)
            self.power_surface = self.power_sprite.getImage()

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

    def draw(self):

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

        self.scene.blit(self.power_surface, self.draw_power_pos)
from pygame.locals import *

class Overlap(object):

    def __init__(self):
        pass # nothing here

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

        self.checkOverlap(em.enemy_list, player, ex, gm, score, em.width, em.height, em.enemy_missile_manager.width, em.enemy_missile_manager.height, None)

        if(gm.level_manager.get_level() == 3):
            self.checkOverlap(em.horizontal_enemy_list, player, ex, gm, score, em.width1, em.height1, em.enemy_missile_manager.width, em.enemy_missile_manager.height, gm.level_manager.get_level())

    def checkOverlap(self, e_list, player, ex, gm, score, width, height, m_width, m_height, level):

        self.player_rect = Rect(player.pos.x, player.pos.y, player.width, player.height)

        for i in range(len(e_list)):  # is player collides with enemy

            self.em_rect = Rect(e_list[i].x, e_list[i].y, width, height)
            if (self.player_rect.colliderect(self.em_rect)):
                e_list[i].on = False
                if (e_list[i].hit == False):
                    ex.create_explosion(player.pos.x + 2, player.pos.y + 2)
                    e_list[i].hit = True
                    gm.state = gm.OVER
                    gm.setup(gm.level_manager.get_level())

        for i in range(len(e_list)):  # is enemy missile hits player

            for j in range(len(e_list[i].missile_list)):
                self.em_rect = Rect(e_list[i].missile_list[j].x, e_list[i].missile_list[j].y,
                                    m_width, m_height)
                if (self.player_rect.colliderect(self.em_rect)):
                    e_list[i].missile_list[j].on = False
                    ex.create_explosion(player.pos.x + 2, player.pos.y + 2)
                    score.set_score(-1)
                    if (score.power_y > 100):
                        gm.state = gm.OVER
                        gm.setup(gm.level_manager.get_level())

        for i in range(len(e_list)):  # is player missile hits enemy

            self.em_rect = Rect(e_list[i].x, e_list[i].y, width, height)

            for j in range(len(player.getMissileManager().missile_list)):

                self.mm_rect = Rect(player.getMissileManager().missile_list[j].x,
                                    player.getMissileManager().missile_list[j].y, player.getMissileManager().width,
                                    player.getMissileManager().height)

                if (self.em_rect.colliderect(self.mm_rect)):
                    e_list[i].on = False
                    player.getMissileManager().missile_list[j].on = False
                    if (e_list[i].hit == False):
                        ex.create_explosion(e_list[i].x, e_list[i].y + 2)
                        e_list[i].hit = True

                        if(level == 3):
                            score.set_score(10)
                        else:
                            score.set_score(1)
                        if (score.score >= gm.level_manager.get_level() * 30):
                            gm.level_manager.increase_level()

Power Bar

That is it, our next mission is to create a more exciting moment for the game which you will see in the next chapter.

What is your top achievements?

After the previous article, we have finally been able to create a score scene as I had promised you before in the last article. What this scene does is to list out the latest 5 levels that the player has achieved, if the level count has reached it’s maximum value then the earliest level from the list will be removed and get replaced by the latest level at the end of the list. This program will also remember the latest level a player has reached and when he starts the game again that level will be loaded. We will edit three files to achieve the above outcome. The first file which we will edit is the level manager file where the program will load the latest level when the game has started and then removed an excessive level if the levels have reached their maximun count which is 5 within the set level method. The program will call the set level method each time the player has loaded the game or the player has came back to the main menu scene.

import os

class LevelManager(object):

    def __init__(self, gm):

        self.game_manager = gm
        self.delete_line = False

        self.MAX_LEVEL = 3

    def set_level(self):
        try:
            f = open("level.txt", "r")
            try:
                if f.mode == 'r':
                    self.f1 = f.readlines()
                    if (self.f1.__len__() > 5):
                        self.delete_line = True
                    for x in self.f1:
                        self.level = int(x)

            finally:
                f.close()
        except IOError:
            print('Error')
        if (self.delete_line == True):
            self.delete_line = False
            try:
                f = open("level.txt", "w+")
                try:
                    f.write(''.join(self.f1[1:]))
                finally:
                    f.close()
            except IOError:
                print('cannot open a file')

    def increase_level(self):

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

    def get_level(self):

        return self.level

The next is to set up the score scene which will show the latest levels that the player has reached if he has clicked on the score button on the main menu scene, the maximun levels to show is 5. The recal_level method will be called each time a game has been loaded and whenever the player has loaded the main menu page so the new level can be updated if the player has pressed the home button on the pause scene page.

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

class StartScene(object):

    def __init__(self, scene):

        self.scene = scene
        self.play_button = 'Asset/play.png'
        self.about_button  = 'Asset/about.png'
        self.exit_button = 'Asset/exit.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.about_page = 'Asset/about_page.png'
        self.manual_page = 'Asset/manual_page.png'
        self.soundon = 'Asset/sound.png'
        self.soundoff = 'Asset/soundoff.png'
        self.home_button_image = 'Asset/home.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_about = BgSprite(self.about_page, 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.sprite_pause = BgSprite(self.general_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_home_pause_button = GameSprite(self.home_button_image, self.home_button_rect)
        self.sprite_manual_button = GameSprite(self.manual_button, self.home_button_rect)
        self.sprite_exit_button = GameSprite(self.exit_button, self.home_button_rect)
        self.sprite_play_button = GameSprite(self.play_button, self.home_button_rect)
        self.sprite_about_button = GameSprite(self.about_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.about_surface = self.sprite_about.getImage()  # get the about sprite surface
        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.pause_surface = self.sprite_pause.getImage()  # get the pause 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.home_pause_button_surface = self.sprite_home_pause_button.getImage() # get the button sprite surface
        self.play_button_surface = self.sprite_play_button.getImage()  # get the button sprite surface
        self.about_button_surface = self.sprite_about_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.exit_button_surface = self.sprite_exit_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_about_button_pos = mt.Vector2(229, 263)
        self.draw_home_button_pos = mt.Vector2(229, 263)
        self.draw_score_button_pos = mt.Vector2(229, 328)
        self.draw_manual_button_pos = mt.Vector2(229, 393)
        self.draw_exit_button_pos = mt.Vector2(229, 456)
        self.draw_back_button_pos = mt.Vector2(10, 620)

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

        self.soundon = True

        self.font = txt.Font(None, 90)
        self.score_text = "Top Achievements"
        self.text_width, self.text_height = self.font.size(self.score_text)
        self.x_title = 330 - self.text_width/2
        self.y_title = 20
        self.title_rect = Rect(self.x_title, self.y_title, self.text_width, self.text_height)
        self.title_score_text = self.font.render(self.score_text, 1, (255, 255, 255))

        self.score_value_text = ''
        self.f1 = None
        self.font1 = txt.Font(None, 100)
        self.score_rect = Rect(100, self.y_title+self.text_height, 100, 100)

    def recal_level(self): # get the top 5 levels
        self.count = 0
        self.origin = 0
        try:
            f = open("level.txt", "r")

            try:
                if f.mode == 'r':
                    self.f1 = f.readlines()
                    for x in self.f1:
                        self.count += 1
            finally:
                f.close()

        except IOError:
            print('Error')

    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.about_button_surface, self.draw_about_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
            self.scene.blit(self.exit_button_surface, self.draw_exit_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.about_surface, self.draw_pos)  # draw a about sprite
            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

        elif (state == 7):
            self.scene.blit(self.pause_surface, self.draw_pos)  # draw a pause sprite
            self.scene.blit(self.play_button_surface, self.draw_play_button_pos)  # draw a button sprite
            self.scene.blit(self.home_pause_button_surface, self.draw_home_button_pos)  # draw a button sprite

        elif (state == 8):
            self.scene.blit(self.pause_surface,  self.draw_pos)  # draw a score sprite
            self.scene.blit(self.title_score_text, self.title_rect) # the score title first

            while(self.count > 0):
                self.count -= 1
                self.origin += 1
                self.score_rect = Rect(130, self.y_title + self.text_height + self.origin * 80, 100, 100)
                self.score_value_text = str(self.count) + ".) Level " + self.f1[self.count][0:1]
                self.value_score_text = self.font1.render(self.score_value_text, 1, (255, 255, 255))
                self.scene.blit(self.value_score_text, self.score_rect)  # the top 5 levels of the game

            if(self.count <= 0):
                self.count = self.origin
                self.origin = 0

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

That is basically it, the last file we need to edit is the game manager file where we will add in an extra score state which will be used later on to display the score scene. Besides that, we also added in the machanism to handle this state as we have done before for the other state.

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

class GameManager(object):

    def __init__(self, scene):

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

        self.pause = False # flag to pause the game

        #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.state = self.LOAD

    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):
            self.start_scene.recal_level()
            self.level_manager.set_level()
            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.GAME):

            self.update()
            self.draw()

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

            self.start_scene.draw(self.state)

    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.SCORE 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_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
            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_exit.collidepoint(x, y) and self.state == self.LOAD):
                exit()
            elif (self.rect_pause_home.collidepoint(x, y) and self.state == self.PAUSE):

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

                try:
                    f = open("level.txt", "a+")
                    try:
                        f.write('\n' + str(self.level_manager.get_level()))
                    finally:
                        f.close()
                except IOError:
                    print ('cannot open a file')

            elif (self.rect_manual.collidepoint(x, y) and self.state == self.LOAD):
                webbrowser.open_new('http://gamingdirectional.com/')
            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 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 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.draw()
            self.explosion_manager.draw()
            self.score_manager.draw()
            pygame.display.flip()

As you can see the code has became hard to read when the game progress but we will leave the tidy up process to the last stage of the game development, as for now we will continue to add in more features to the game in the next chapter.

top 5 latest levels
top 5 latest levels

Create an exit button on the main game menu scene

In this article we will continue with our previous pygame project by creating an exit button on the main game menu scene which when the user clicks on it the program will close the game. We will create the score scene in the next chapter as I have promised in the previous article but in this article we will create the exit button which is also very important for this project. This button will only appear on the main scene. First we will need to edit the start scene class by including this button in it.

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.about_button  = 'Asset/about.png'
        self.exit_button = 'Asset/exit.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.about_page = 'Asset/about_page.png'
        self.manual_page = 'Asset/manual_page.png'
        self.soundon = 'Asset/sound.png'
        self.soundoff = 'Asset/soundoff.png'
        self.home_button_image = 'Asset/home.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_about = BgSprite(self.about_page, 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.sprite_pause = BgSprite(self.general_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_home_pause_button = GameSprite(self.home_button_image, self.home_button_rect)
        self.sprite_manual_button = GameSprite(self.manual_button, self.home_button_rect)
        self.sprite_exit_button = GameSprite(self.exit_button, self.home_button_rect)
        self.sprite_play_button = GameSprite(self.play_button, self.home_button_rect)
        self.sprite_about_button = GameSprite(self.about_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.about_surface = self.sprite_about.getImage()  # get the about sprite surface
        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.pause_surface = self.sprite_pause.getImage()  # get the pause 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.home_pause_button_surface = self.sprite_home_pause_button.getImage() # get the button sprite surface
        self.play_button_surface = self.sprite_play_button.getImage()  # get the button sprite surface
        self.about_button_surface = self.sprite_about_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.exit_button_surface = self.sprite_exit_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_about_button_pos = mt.Vector2(229, 263)
        self.draw_home_button_pos = mt.Vector2(229, 263)
        self.draw_score_button_pos = mt.Vector2(229, 328)
        self.draw_manual_button_pos = mt.Vector2(229, 393)
        self.draw_exit_button_pos = mt.Vector2(229, 456)
        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.about_button_surface, self.draw_about_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
            self.scene.blit(self.exit_button_surface, self.draw_exit_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.about_surface, self.draw_pos)  # draw a about sprite
            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

        elif (state == 7):
            self.scene.blit(self.pause_surface, self.draw_pos)  # draw a pause sprite
            self.scene.blit(self.play_button_surface, self.draw_play_button_pos)  # draw a button sprite
            self.scene.blit(self.home_pause_button_surface, self.draw_home_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()

The next step is to edit the game manager class which will terminate the game after the user has clicked on this button.

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

class GameManager(object):

    def __init__(self, scene):

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

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

        self.pause = False # flag to pause the game

        #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.state = self.LOAD

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

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

            self.start_scene.draw(self.state)

    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 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 about 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_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
            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_exit.collidepoint(x, y) and self.state == self.LOAD):
                exit()
            elif (self.rect_pause_home.collidepoint(x, y) and self.state == self.PAUSE):

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

                try:
                    f = open("level.txt", "w+")
                    try:
                        f.write(str(self.level_manager.get_level()))
                    finally:
                        f.close()
                except IOError:
                    print ('cannot open a file')

            elif (self.rect_manual.collidepoint(x, y) and self.state == self.LOAD):
                webbrowser.open_new('http://gamingdirectional.com/')
            elif (self.rect_back.collidepoint(x, y) and (self.state == self.ABOUT or self.state == self.MANUAL)):
                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 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 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.draw()
            self.explosion_manager.draw()
            self.score_manager.draw()
            pygame.display.flip()

That is it, the game manager class will take care of the button click events and will terminate the game if the exit button has been clicked. The development of this game will continue on the next chapter, if you have missed out the previous tutorials then don’t forget to read them all.

Open a text file then write the game level onto it with python

Welcome back, let us continue with our previous pygame project. In this article we will first create a text file which will be used to store the game level. This text file will be called level.txt which will be stored within the project folder. We need to create this text file by hand and type in 1 which is the first level of the game onto it, this level number will be rewritten each and every time the user has pressed the home button on the pause scene to go back to the homepage of the game. The reason why we are not letting the program to create the level.txt file for us is because when we have installed the game on our pc later on our computer’s os might not let the game program to create that text file on it’s won folder due to the security reason, therefore it is always the best practice for the game developer to create our own text file even if it is an empty file so the program will be able to edit that file later on. OK so much for that, lets create the text file first and write the starting level onto it.

pycharm's interface
pycharm’s interface

The next thing we need to do is to edit the level manager class. Now the level variable will directly get the level number from the text file.

import os

class LevelManager(object):

    def __init__(self, gm):

        self.game_manager = gm

        try:
            f = open("level.txt", "r")
            try:
                if f.mode == 'r':
                    f1 = f.readlines()
                    for x in f1:
                        self.level = int(x)
            finally:
                f.close()
        except IOError:
            print('Error')

        self.MAX_LEVEL = 3

    def increase_level(self):

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

    def get_level(self):

        return self.level

One thing you might have noticed from the top program is that we actually do not need to create loop when reading the content of the text file because it only consists of one line, the reason why we have created a loop is because we will have more than one line of game level in the future so we do need this loop and we will further modify this loop content in the future.

The last part is to edit the game manager class which will rewrite the game level to the text file each time the user has clicked on the home button on the pause scene to get back to the main game page.

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

class GameManager(object):

    def __init__(self, scene):

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

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

        self.pause = False # flag to pause the game

        #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.state = self.LOAD

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

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

            self.start_scene.draw(self.state)

    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 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_pause_home = Rect(229, 263, 200, 53)  # the position of the home button on pause 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
            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_pause_home.collidepoint(x, y) and self.state == self.PAUSE):

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

                try:
                    f = open("level.txt", "w+")
                    try:
                        f.write(str(self.level_manager.get_level()))
                    finally:
                        f.close()
                except IOError:
                    print ('cannot open the file')

            elif (self.rect_manual.collidepoint(x, y) and self.state == self.LOAD):
                webbrowser.open_new('http://gamingdirectional.com/')
            elif (self.rect_back.collidepoint(x, y) and (self.state == self.ABOUT or self.state == self.MANUAL)):
                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 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 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.draw()
            self.explosion_manager.draw()
            self.score_manager.draw()
            pygame.display.flip()

That is basically it, in the next chapter we will work on the score scene where the program will list out 5 highest levels that the player has achieved with the help of the level.text file which we have just created earlier in this chapter.

Create a home button on the pause scene

In the last chapter we have created a pause scene as well as created a play button which will resume the game after a user has pressed on it and in this chapter we will continue to modify the pause scene by adding in one more button which will return the player to the main page if that player has pressed on it. First we will need to modify the start scene class by adding an extra button into it.

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.about_button  = 'Asset/about.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.about_page = 'Asset/about_page.png'
        self.manual_page = 'Asset/manual_page.png'
        self.soundon = 'Asset/sound.png'
        self.soundoff = 'Asset/soundoff.png'
        self.home_button_image = 'Asset/home.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_about = BgSprite(self.about_page, 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.sprite_pause = BgSprite(self.general_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_home_pause_button = GameSprite(self.home_button_image, self.home_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_about_button = GameSprite(self.about_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.about_surface = self.sprite_about.getImage()  # get the about sprite surface
        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.pause_surface = self.sprite_pause.getImage()  # get the pause 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.home_pause_button_surface = self.sprite_home_pause_button.getImage() # get the button sprite surface
        self.play_button_surface = self.sprite_play_button.getImage()  # get the button sprite surface
        self.about_button_surface = self.sprite_about_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_about_button_pos = mt.Vector2(229, 263)
        self.draw_home_button_pos = mt.Vector2(229, 263)
        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.about_button_surface, self.draw_about_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.about_surface, self.draw_pos)  # draw a about sprite
            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

        elif (state == 7):
            self.scene.blit(self.pause_surface, self.draw_pos)  # draw a pause sprite
            self.scene.blit(self.play_button_surface, self.draw_play_button_pos)  # draw a button sprite
            self.scene.blit(self.home_pause_button_surface, self.draw_home_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()

The next file we will need to edit is the game manager file which we will set the game state to load as well as reset the game objects when the user has pressed on the home button on that pause scene.

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.load_music()
        self.play_music()
        self.overlap_manager = Overlap()
        self.level_manager = LevelManager(self)

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

        self.pause = False # flag to pause the game

        #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.state = self.LOAD

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

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

            self.start_scene.draw(self.state)

    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 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_pause_home = Rect(229, 263, 200, 53)  # the position of the home button on pause 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
            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_pause_home.collidepoint(x, y) and self.state == self.PAUSE):
                self.state = self.LOAD
                self.setup(self.level_manager.get_level())
            elif (self.rect_manual.collidepoint(x, y) and self.state == self.LOAD):
                webbrowser.open_new('http://gamingdirectional.com/')
            elif (self.rect_back.collidepoint(x, y) and (self.state == self.ABOUT or self.state == self.MANUAL)):
                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 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 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.draw()
            self.explosion_manager.draw()
            self.score_manager.draw()
            pygame.display.flip()

With that set we are ready to move on and in the next chapter we will save the current game level to a local txt file whenever the user has left the game!

Create the pause scene for the game

In this article we will create a pause scene for our ongoing pygame project. When a user presses the p key on his keyboard during the game, the game will pause and the pause scene will appear. When he presses the play button on the pause scene the game will resume. We need to modify three files in order to include this scene into the game. The first file to edit is the main project file which we will include in an extra mechanism to detect the p key pressed event.

import sys, pygame
from pygame.locals import *
from GameManager import GameManager

pygame.init()

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

game_manager = GameManager(screen)

while True:

    for event in pygame.event.get():

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

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

            if(game_manager.state == 1):
                if event.key == K_LEFT:
                    game_manager.set_player_x(-0.1)
                elif event.key == K_RIGHT:
                    game_manager.set_player_x(0.1)

                if event.key == K_UP:
                    game_manager.set_player_y(-0.1)
                elif event.key == K_DOWN:
                    game_manager.set_player_y(0.1)

                if event.key == K_SPACE:
                    game_manager.set_missile_strike(True)

                if event.key == K_p :
                    game_manager.set_pause(True) # set the pause state to true

        elif event.type == KEYUP:

            if (game_manager.state == 1):
                if event.key == K_LEFT:
                    game_manager.set_player_x(0)
                elif event.key == K_RIGHT:
                    game_manager.set_player_x(0)

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

                if event.key == K_SPACE:
                    game_manager.set_missile_strike(False)

        elif event.type == pygame.MOUSEBUTTONDOWN:
            # 1 is the left mouse button
            if event.button == 1:
                game_manager.isAreaClick(event.pos)

    game_manager.loop()

The next file needs to edit is the start scene file where we will include in the pause scene to the start scene class.

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.about_button  = 'Asset/about.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.about_page = 'Asset/about_page.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_about = BgSprite(self.about_page, 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.sprite_pause = BgSprite(self.general_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_about_button = GameSprite(self.about_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.about_surface = self.sprite_about.getImage()  # get the about sprite surface
        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.pause_surface = self.sprite_pause.getImage()  # get the pause 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.about_button_surface = self.sprite_about_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_about_button_pos = mt.Vector2(229, 263)
        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.about_button_surface, self.draw_about_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.about_surface, self.draw_pos)  # draw a about sprite
            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

        elif (state == 7):
            self.scene.blit(self.pause_surface, self.draw_pos)  # draw a game over sprite

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

        pygame.display.flip()

The final class which we need to edit is the game manager class where we need to include in the pause game state as well as to adjust the related methods to match this new state, for example shows the pause scene when the game is in the pause state.

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.load_music()
        self.play_music()
        self.overlap_manager = Overlap()
        self.level_manager = LevelManager(self)

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

        self.pause = False # flag to pause the game

        #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.state = self.LOAD

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

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

            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 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_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 or self.state == self.PAUSE)):
                self.state = self.GAME
            elif(self.rect_play.collidepoint(x,y) and self.state == self.LOAD):
                self.state = self.GAME
            elif (self.rect_about.collidepoint(x, y) and self.state == self.LOAD):
                self.state = self.ABOUT
            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)):
                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 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 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.draw()
            self.explosion_manager.draw()
            self.score_manager.draw()
        elif(self.state == self.PAUSE):
            self.start_scene.draw(self.state)
        pygame.display.flip()

That is it, now we are ready for the next lesson which will further deal with the game scenes.