Pygame Music player demo

In this article we are going to play the background music with the help of the pygame.mixer_music module. We will first load the soundtrack then play it repeatedly. We can also play the background music with the help of pygame.mixer module which you can read the entire solution in this article but now we will use the pygame.mixer_music module to load and play the background soundtrack instead.

Inside the main python file enter below lines of code.

pygame.mixer_music.load('Music/winternight.ogg') # load winternight.ogg music file inside the Music folder
pygame.mixer_music.play(-1) # play the music again and again

Then make sure to stop the background music when the game has been terminated.

pygame.mixer_music.stop()

The entire program looks like this.

import sys, pygame
from AirStrikeColor import AirStrikeColor #from AirStrikeColor.py import AirStrikeColor class

pygame.init()
size = width, height = 600, 600
pygame.display.set_caption("Hello World") # set the title of the window
screen = pygame.display.set_mode(size)

pygame.mixer_music.load('Music/winternight.ogg')
pygame.mixer_music.play(-1)

while True:

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

    screen.fill(AirStrikeColor(120, 150, 130, 255).correct_gamma(0.5))
    pygame.display.flip()

You can refer to the previous article on the other part of the program which you have missed out entirely!

Here is the new file explorer structure.

All the files under file explorer
All the files under file explorer

There are two things I cannot get it going when using the pygame.mixer_music module.

1) The wav file format is not supported by this module.
2) pygame.mixer_music.queue(file) method which uses to play another song after the first one is not working.

With that we will end this tutorial and get ready for the next one.

Pygame’s Color class demo

Today I have paid a visit to the Pygame document page to revise all the pygame classes one by one because I have already forgotten all of them. In order to create a game with Pygame I will need to get familiar with these classes again. In this article I will write a simple python class which extends the pygame.Color class to demonstrate the use of the pygame Color class. Since most of the time our game will deal with graphic instead of color we do not actually need this class that much but it is good to go through it so we will get familiar with it if we really need to use it later on.

As usual, I open up the PyCharm which is the official ide for my pygame development project to continue with the previously created game project. I am not going to repeat the PyCharm feature which I have already mentioned in my previous article so if you do miss out my previous article then you can read the first chapter of this pygame development project here (Setting up PyCharm for Pygame development in Windows 10 OS). I also assume you are familiar with python because before you can create a game with pygame you will need to have a very strong python programming background.

Now lets create the extension of the Color class, we will create a new python file, make sure you are clicking on the project folder then goto File->New->Python File and give it any name you wish to.

This will be the class which will extend the Pygame Color class, the good thing we create an extension of the Color class is that we can now add in more custom made functions into this class later on if we need it.

Here is our new AirStrikeColor class.

from pygame import Color

class AirStrikeColor(Color):

    def __init__(self, r=255, g= 255, b= 255, a=255):
        Color.__init__(self, r, g, b ,a)

As you can see we have created a default value for all four elements (red, green, blue and alpha) so if the programmer does not enter any value when creating the AirStrikeColor class then this new object will use the default values instead.

Alright, that is about it, we will visit this class again to add in more functions if we need it but for now we can use all the functions of the pygame.Color class in our project as usual.

Next step is to import this new class into the main python file I have created previously. We will now go back to the main python file and import the new class.

from AirStrikeColor import AirStrikeColor #from AirStrikeColor.py import AirStrikeColor class

Also we need to take out the

from pygame import Color

statement because we do not need the main Color class anymore.

Now as usual we will replace the Color class statement with AirStrikeColor class statement like this.

screen.fill(AirStrikeColor())

Run the program again and it works!

Pygame window
Pygame window

Now replace the statement above with own values.

screen.fill(AirStrikeColor(120, 150, 130, 255).correct_gamma(0.5))
New window
New window

If you don’t know where is the main python file please refer back to my previous article.

With that we have concluded this second chapter of our pygame development journal and will now getting ready for the third one.

Setting up PyCharm for Pygame development in Windows 10 OS

It has been for a while since I have stopped writing about Pygame related topic on this website and today I will start to write about it again because there are 5 ongoing gaming projects that I have developed recently using Pygame and I would really like to show you one of them in this website from start to finish. If you want to know all about this project make sure you visit this website every week to see the latest post about my latest Pygame project.

I have selected PyCharm as the Python IDE for my next Pygame development which is not surprise at all because it is the only real deal in the market when it comes to the best IDE for Python application development. I have considered using Eclipse before because Eclipse is indeed the best IDE when it comes to writing and developing application but unfortunately Eclipse does not have the stand alone version just for the software development in Python, we will need to install PyDev plugin in Eclipse before we can develop application written with Python. So PyCharm is the one to go for. Basically PyCharm consists of the Community and Professional version. If you need Full-featured IDE for Python & Web development then go for the paid Professional version, I will use the free Community version for my Pygame development because the free version is more than enough if you just need a Lightweight IDE for Python & Scientific development. Go ahead to www.jetbrains.com then decide which version of PyCharm you would like to install.

After you have downloaded PyCharm then follow the step by step installation instructions to install this IDE on windows 10 os.

Next is to install Pygame, open up the windows command prompt and type in

pip install Pygame==1.9.4

to download and install Pygame from pypi.org and that is it!

Now it is time to see whether Pygame has been installed successfully or not, Launch PyCharm then go to the File menu and select New Project.

Provide the Project folder name together with the folder location and click on the create button.

Provide the folder name
Provide the folder name

One last thing you will need to do before you can start coding and that is to set the location of the project interpreter, so go ahead and select File->Settings then type ‘interpreter’ into the search box on the left pane and select the location on your disk where you have installed the Python program on the right pane then click the Apply and OK button.

Select Python Program
Select Python Program

Now lets create a python file, write some code and run pygame. Right click on the project folder under file explorer then select New->Python File from the pop up. Type a name for your python file with .py extension into the Name field then click on the ok button.

Create new python file
Create new python file

That is it, now click on the empty python file you have just created on the left pane and enter below code into the code editor.

select the empty python file
Select the empty python file
import sys, pygame
from pygame import Color

pygame.init()
size = width, height = 600, 600
screen = pygame.display.set_mode(size)

while True:
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    screen.fill(Color(25, 100, 200, 255))
    pygame.display.flip()

Next goto the Run menu then select Run ‘file name’, PyCharm will first debug the python program and if there is no error then it will run the program and this is what we will see. The code will be automatically saved each time you have debugged the program.

The outcome of the program
This Pygame code will create a game window which will terminate the program when you click on the ‘x’ button on top of the window

OK so much for today, just to remind you all that I will write a new Pygame development series story on this website from start to finish so do come back again to read more Pygame development stories on this website under the Pygame category. If you like this post then don’t forget to share it!

The cloud object has been introduced into Rock Sweeper

There is a new update coming soon with the introduction of the cloud object into the game, what this object does is to continuously moving downward and if it gets passed the screen boundary then it will reappear again from the other end.

from game_sprite import GameSprite
from pygame.locals import *
from vector2d import Vector2D

class CloudSprite(GameSprite):
    
    # Constructor. Pass in the image file
    # and it's width and height and it's position on the spritesheet
    def __init__(self, image, width, height, pos):
        
        # Call the parent class __init__ method
        GameSprite.__init__(self, image, width, height, pos)
        
        self.pos = Vector2D(0,0) #initialize the original position of the sprite on the screen
        
    def updatePosition(self): 
        self.pos += Vector2D(0.0, 0.1) #the new vector position of the cloud object on the screen
        #if the cloud gets passed the boundary then reset it to old position
        if(self.pos.y > (560+self.height/2)):
            self.pos.y = -300
        else:
            #else create the new rectangle object of the cloud
            self.rect = Rect(self.pos.x - self.width/2, self.pos.y - self.height/2, self.width, self.height) #self.rect will be called by the rock group

The new installer will also be used in this game for better user experience.

How to distribute the pygame program for windows os

If you have read my previous post regarding the PyInstaller then this one will further shows you how to create a installer for your pygame program for windows os so the windows users can download and install your program on their windows os’s pc.

Before we go further lets us revisit the part on how to create a distribution folder which includes a clickable application file that our application user can click on it to start the pygame application on windows os. In our previous tutorial regarding the PyInstaller we have only created a distribution folder for one file but in this one we will create the distribution folder for many files include the image files.

Make sure you have copied the freesansbold.ttf file to the main file folder if you are using it in your game before you create the spec file because PyInstaller is unable to locate it in the pygame package. We do not need to specify the pygame’s library because PyInstaller is smart enough to import all the pygame modules that the game requires for us.

As usual in the windows command prompt we will browse to the directory which contains all the files that we wish to turn into a single pygame application.

Create distribution folder :

1) Type in below command in the windows command prompt then press enter.

pyinstaller --noconsole main.py 

where main.py is the main file of the pygame application (the one which starts the application) and the ‘—noconsole’ option is used to hide the console window which will open in the background of python application program.

You will see errors such as the PyInstaller is unable to find the api-ms-win-crt-runtime-l1-1-0.dll file during the compilation stage but that is not a big issue as these files are in the windows os itself so we do not need to include it in our game package anymore. Also for the users to play the game they must have Python installed in their machine.

2) After PyInstaller has generated a spec file for your application open it up with any code editor which you prefer. Below is the spec file for my python game.

pyinstaller spec
pyinstaller spec

Besides the spec file you will also find a dist folder which contains of your application file in it but at the moment you cannot start the application because the application’s helper files are not there yet. There are also two other folders the pyinstaller has created for you : build and __pycache__ folder but we do not need to worry about those two as our main focus is on the dist folder.

3) Now I will edit or add in the following lines of code in that spec file.

# -*- mode: python -*-

block_cipher = None


a = Analysis(['rocksweeper.py'],
             pathex=['E:\\Pygame\\project0\\src'],
             binaries=None,
             datas=None,
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
			 
game_files =  [('world.py', 'E:\\Pygame\\project0\\src\\world.py', 'DATA')]		
game_files +=  [('win.png', 'E:\\Pygame\\project0\\src\\win.png', 'DATA')]	
game_files +=  [('vector2d.py', 'E:\\Pygame\\project0\\src\\vector2d.py', 'DATA')]
game_files +=  [('title.png', 'E:\\Pygame\\project0\\src\\title.png', 'DATA')]		
game_files +=  [('thick.png', 'E:\\Pygame\\project0\\src\\thick.png', 'DATA')] 
game_files +=  [('state_winning.py', 'E:\\Pygame\\project0\\src\\state_winning.py', 'DATA')]
game_files +=  [('state_playing.py', 'E:\\Pygame\\project0\\src\\state_playing.py', 'DATA')]
game_files +=  [('state_over.py', 'E:\\Pygame\\project0\\src\\state_over.py', 'DATA')]
game_files +=  [('state_losing.py', 'E:\\Pygame\\project0\\src\\state_losing.py', 'DATA')]
game_files +=  [('state_loading.py', 'E:\\Pygame\\project0\\src\\state_loading.py', 'DATA')]
game_files +=  [('state_engine.py', 'E:\\Pygame\\project0\\src\\state_engine.py', 'DATA')]
game_files +=  [('state.py', 'E:\\Pygame\\project0\\src\\state.py', 'DATA')]
game_files +=  [('ship_sprite.py', 'E:\\Pygame\\project0\\src\\ship_sprite.py', 'DATA')]
game_files +=  [('screen_win.py', 'E:\\Pygame\\project0\\src\\screen_win.py', 'DATA')]
game_files +=  [('screen_over.py', 'E:\\Pygame\\project0\\src\\screen_over.py', 'DATA')]
game_files +=  [('screen_lose.py', 'E:\\Pygame\\project0\\src\\screen_lose.py', 'DATA')]
game_files +=  [('screen_load.py', 'E:\\Pygame\\project0\\src\\screen_load.py', 'DATA')]
game_files +=  [('screen.py', 'E:\\Pygame\\project0\\src\\screen.py', 'DATA')]
game_files +=  [('rock_sprite.py', 'E:\\Pygame\\project0\\src\\rock_sprite.py', 'DATA')]
game_files +=  [('play_on.png', 'E:\\Pygame\\project0\\src\\play_on.png', 'DATA')]
game_files +=  [('next.png', 'E:\\Pygame\\project0\\src\\next.png', 'DATA')]
game_files +=  [('menu.png', 'E:\\Pygame\\project0\\src\\menu.png', 'DATA')]
game_files +=  [('maintile.png', 'E:\\Pygame\\project0\\src\\maintile.png', 'DATA')]
game_files +=  [('icon.png', 'E:\\Pygame\\project0\\src\\icon.png', 'DATA')]
game_files +=  [('game_state_engine.py', 'E:\\Pygame\\project0\\src\\game_state_engine.py', 'DATA')]
game_files +=  [('game_sprite.py', 'E:\\Pygame\\project0\\src\\game_sprite.py', 'DATA')]
game_files +=  [('gameover.png', 'E:\\Pygame\\project0\\src\\gameover.png', 'DATA')]
game_files +=  [('freesansbold.ttf', 'E:\\Pygame\\project0\\src\\freesansbold.ttf', 'DATA')]
			 
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          exclude_binaries=True,
          name='Rocksweeper',
          debug=False,
          strip=False,
          upx=True,
          console=False , icon='iconfile.ico' )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas + game_files,
               strip=False,
               upx=True,
               name='Rocksweeper')

Basically I have added in all those files that the game needs under the game_files list and then added that list to the a.datas list

a.datas + game_files

The game_files list takes in three element 1) The name of the file 2) The full path to the file (remember to use double backslash in your file path) 3) The string ‘DATA’ which is required by the spec file.

[('freesansbold.ttf', 'E:\\Pygame\\project0\\src\\freesansbold.ttf', 'DATA')]

Besides that if we do not want a console to appear on the background when we start the game (although we have already used the ‘—noconsole’ option when we create the spec but the console will still start for a short time) then we will simply set the console value to false


console=False

We can also include an icon for our application by specifying the path to the icon file.


icon=’iconfile.ico’

After we have added and changed a few lines in the spec file we are now ready to recreate it with below command in the command prompt.

pyinstaller rocksweeper.spec

After we have ran the above command the contents of the dist folder will be rewritten and now you are ready to distribute the entire folder for the user to download. Although we can stop here if we want to because the dist folder has already contained everything we need to start the application (the main application file and it’s helper files such as image and the module files) but it will be very hard for the users to start the program if they are not familiar with the files inside the folder therefore we need to create an installer for our program which will lead us to the second part of this tutorial.

Create installer :

There are so many softwares for python developers to choose from when it comes to create an installer for their application but in this post I will only show you how to use Inno Setup to create the application’s installer for windows os.

Inno Setup is a free installer for Windows programs. First introduced in 1997, Inno Setup today rivals and even surpasses many commercial installers in feature set and stability.

As compared to other installers Inno Setup is easy to use thus you can create a workable windows’ installer with just a few clicks.

1) Download Inno Setup and install it.
2) Start Inno Setup, select ‘Create a new script file using the Script Wizard’ then press OK.

inno setup
start inno setup

3)

click the next button
click the Next button

4)

fill in the detail about your application
fill in the detail about your application

5)

click next button
click Next button

6)

Select the path to application file then select the folder where the helper files are located, make sure all the files inside the subfolders are selected as well
Select the path to the application file then select the folder where the helper files are located, make sure all the files inside the subfolders are selected as well

7)

click next
click next

8)

select license file
select license file

9)

next
next

10)

select the location to create the installer, named the setup file and provide the path to the icon file
select the location to create the installer, named the setup file then provide the path to the icon file

11)

Next
Next

12)

finish
Finish

13) If you like you can save the new script for future use before compile it, that is it, once you have compiled the script Inno Setup will create the installer for you which you can then upload to your website for user to download and install your program.

Creating application with python and then pack it up is a long and painful process which takes lots of your time to do so, so make sure you stay cool and always look for help on forum or blog!

The game state engine is ready!

After one and the half day of working on and off on the game state engine, this mega structure has finally ready for the real production! Basically this game engine will become the brain which will control the state object which will then control the screen and the world object. Now our main game module has became so simple because of the introduction of the game state engine above.

#!/usr/bin/env python

import pygame
from pygame.locals import *
from sys import exit
from vector2d import Vector2D
from game_state_engine import GameStateEngine

SCREEN_SIZE = (550, 550) #game screen size

pygame.init()

screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
screen.fill((0, 0, 0))

pygame.display.set_caption("Rock Sweeper")

state_engine = GameStateEngine(screen)


while True:
   
    for event in pygame.event.get():
        
        if event.type == QUIT:
            exit()  
            
        elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            pos = pygame.mouse.get_pos()
            if(state_engine.get_state_name() == 'load'):
                state_engine.pos = pos
    
    pressed_keys = pygame.key.get_pressed() # get all the keys from key-press events 
        
    if pressed_keys[K_LEFT]: 
        if(state_engine.get_state_name() == 'play'):
            state_engine.v = Vector2D(-1., 0.) # move the top ship one unit to the left
            state_engine.v1 = Vector2D(1., 0.) # move the bottom ship one unit to the right
        
        
    elif pressed_keys[K_RIGHT]:
        if(state_engine.get_state_name() == 'play'):
            state_engine.v = Vector2D(1., 0.) # move the top ship one unit to the right
            state_engine.v1 = Vector2D(-1., 0.) # move the bottom ship one unit to the left
            
    else:
        #reset the speed to zero for both sjips
        state_engine.v = Vector2D(0.0, 0.0)
        state_engine.v1 = Vector2D(0.0, 0.0)
        
    state_engine.do_action() #do action
    state_engine.check_conditions() #what is the state now?
    
    pygame.display.flip()

Now with the building of this game state engine thing will become easier and simple because all we need to do now is to change the state within the game state engine!

Game progress — creating game state engine

Game state engine will be the one which uses by this game to control the world object which will control the game entities such as rock and ship. Another usage of the game state engine is uses to control the game screen (loading screen, winning screen, game over screen and etc). These few days I will need to figure it out how to connect the game state engine with various states that ask the world object as well as the screen object to perform various jobs.

So far here is how the game state engine looks like.

from state_engine import StateEngine 
from state_loading import GameStateLoading
from state_playing import GameStatePlaying
from state_winning import GameStateWinning
from state_losing import GameStateLosing
from state_over import GameStateOver

class GameStateEngine(StateEngine):
    
    def __init__(self, surface):
        
        StateEngine.__init__(self)
        
        self.surface = surface #the game surface
        
        loading_state = GameStateLoading('load', self.surface) 
        self.add_state(loading_state)
        
        playing_state = GameStatePlaying('play', self.surface)
        self.add_state(playing_state)
        
        winning_state = GameStateWinning('win', self.surface)
        self.add_state(winning_state)
        
        losing_state = GameStateLosing('lose', self.surface)
        self.add_state(losing_state)
        
        game_over_state = GameStateOver('over', self.surface)
        self.add_state(game_over_state)
        
        self.active_state = loading_state #set the active state as loading state when the game first started

The GameStateEngine above is derived from the StateEngine main class.

Here is one of the state which will load the welcome screen.

from state import State
from screen_load import ScreenLoad 

class GameStateLoading(State):
    
    def __init__(self, name, surface):
        State.__init__(self, name)
        self.surface = surface #the surface of the screen
        self.screen = ScreenLoad(surface) #initialize the ScreenLoad module
        
    def do_actions(self):
        screen.render() #render the welcome screen
        
    def check_conditions(self, pos):
        if(screen.isButtonClick(pos)): #if the play button has been clicked then return 'play' as a new state
            return 'play'

GameStateLoading which derives from the State class will responsible for the loading of the welcome screen.

Here is how the ScreenLoad object looks like.

from screen import Screen

class ScreenLoad(Screen):
    
    def __init__(self, surface):
        Screen.__init__(self)
        self.surface = surface #surface of the main screen
        self.main = 'title.png'
        self.play = 'play_on.png'
        self.screen = pygame.image.load(self.main).convert_alpha()
        self.play_button = pygame.image.load(self.play).convert_alpha()
        
    def render(self):
        self.surface.blit(self.screen, (0,0))
        self.button = self.surface.blit(self.play, (w/2, h/2))
        
    def isButtonClick(self, pos):
        return self.button.collidepoint(pos) #if the click area is within the button boundary then return true

Besides loading the title screen the ScreenLoad module will also responsible for the loading of the winning screen and etc therefore there will be further changes for this module.

As you can see the GameStateEngine class needs a lot of modules to function properly therefore it will take a few days for me to figure it out the entire game plan so stay tuned for the further progress of this game!

Creating rock on the screen with Pygame

Starting from this chapter I will no longer posting script on the article but just to let you know what is the progress I have made in this game. This is an open source game so at the end of this project I will upload the game as well as all the source code online for you to download, so don’t worry about it!

Basically what I have accomplished today is to create a RockSprite module and then use this module to create as many as 30 rocks on the screen which will move toward the ships. The player can now use the ship to intercept the rock as mentioned earlier in my previous article.

from game_sprite import GameSprite
from pygame.locals import *
from vector2d import Vector2D

class RockSprite(GameSprite):
    
    # Constructor. Pass in the image file
    # and it's width and height and the position on the spritesheet
    def __init__(self, image, width, height, pos, world):
        # Call the parent class constructor
        GameSprite.__init__(self, image, width, height, pos)
        
        self.world = world
        self.rock_health = 100
        
    def updatePosition(self): 
        self.pos += Vector2D(0.0, 0.1)
        #if the rock get passed the boundary then remove it
        if(self.pos.y > 560):
            self.world.removeRockEntity(self)
        else:
            #else create the new rectangle object of that rock
            self.rect = Rect(self.pos.x - self.width/2, self.pos.y - self.height/2, self.width, self.height) #self.rect will be called by the rock group

After the first ship has intercepted the rock the second ship will intercept it again to destroy it, the next thing I will need to do is to create a state engine for this game, see you tomorrow!

Create the spaceship in Rock Sweeper

In this chapter we are going to create two spaceships, one in front and one at the back. The first thing we need to do here is to create a spritesheet as shown below.

spritesheet
spritesheet

The spritesheet above consists of a spaceship with the width and height of 32px at spritesheet’s coordinate (0,0) as well as a rock (16px x 16px) at coordinate (32,0) and background image at the spritesheet’s coordinate of (0, 32). Import the above spritesheet into the project folder.

The next thing we need to do is to import the previous Vector2D module into our game project folder so we can use it later.

Then we will import the previous GameSprite module into our project as well then change a few lines of script.

import pygame
from pygame.locals import *
from vector2d import Vector2D

class GameSprite(pygame.sprite.Sprite):

    # Constructor. Pass in the image file
    # and it's width and height and position on the spritesheet
    def __init__(self, image, width, height, pos):
        # Call the parent class (Sprite) constructor
        pygame.sprite.Sprite.__init__(self)
        
        #register the width and height of the sprite
        self.width = width
        self.height = height
        #use the radius to detect overlap
        self.radius = self.width/4

        # Create the spritesheet surface from the image file
        self.sprite = pygame.image.load(image).convert_alpha()
        
        #the rectangle object uses in clipping
        self.clip_rect = Rect((pos.x, pos.y), (self.width, self.height))
        
        self.sprite.set_clip(self.clip_rect) # clip a portion of the spritesheet with the rectangle object
        self.image = self.sprite.subsurface(self.sprite.get_clip()) #create sprite surface
        
        self.pos = Vector2D(0,0) #initialize the original position of the sprite 
        
        #initialize the id of sprite
        self.entity_id = 0
        
    def updatePosition(self, pos): 
        pass

Next we will create a subclass for the ship based on the GameSprite module above.

from game_sprite import GameSprite
from pygame.locals import *

class ShipSprite(GameSprite):
    
    # Constructor. Pass in the image file
    # and it's width and height and the position on the spritesheet
    def __init__(self, image, width, height, pos):
        # Call the parent class constructor
        GameSprite.__init__(self, image, width, height, pos)
        
    def updatePosition(self, pos): 
        
        #make sure the ship stays within the boundry of the screen
        if(pos.x - self.width/2 < 0):
            pos.x = self.width/2
        elif(pos.x + self.width/2 >= 550):
            pos.x = 550 - self.width/2
        
        self.rect = Rect(pos.x - self.width/2, pos.y - self.height/2, self.width, self.height) #self.rect will be called by group

Next add a few lines of script into the World module which we have created previously.

from pygame.locals import *
from pygame.sprite import Group

class World(object):
    
    def __init__(self, maintile, background_coordinate, screen_size):
        
        #main spritesheet surface
        self.spritesheet = maintile
        
        #game entities dict to store all the game entities
        self.entities = {}
        
        #create a ship group
        self.ship_group = Group()
        
        #initialize the id of the first entity
        self.entity_id = 0
        
        #the rectangle object uses in clipping the background area
        self.clip_rect = Rect(background_coordinate, screen_size)
        self.spritesheet.set_clip(self.clip_rect) # clip a portion of the spritesheet with that rectangle object
        self.background = self.spritesheet.subsurface(self.spritesheet.get_clip()) #create the background surface 
       
    def render(self, surface):
         
        surface.blit(self.background, (0,0)) #blit the background to the pygame screen
        self.ship_group.draw(surface) #blit the ships to the pygame screen
        
    def addEntity(self, entity):
        self.entities[self.entity_id] = entity
        entity.entity_id = self.entity_id
        self.ship_group.add(entity)
        self.entity_id += 1
        
    def updateShipPosition(self, ship_one_pos, ship_two_pos):
        self.entities[0].updatePosition(ship_one_pos)
        self.entities[1].updatePosition(ship_two_pos)

Finally run the main module…

#!/usr/bin/env python

import pygame
from pygame.locals import *
from sys import exit
from world import World
from vector2d import Vector2D
from ship_sprite import ShipSprite

maintile = 'maintile.png' #spritesheet file

SCREEN_SIZE = (550, 550) 
BACKGROUND_COORDINATE = (0, 32)

screen_w, screen_h = SCREEN_SIZE

pygame.init()

screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
pygame.display.set_caption("Rock Sweeper")

spritesheet = pygame.image.load(maintile).convert_alpha() #spritesheet surface object

pygame.display.set_icon(spritesheet) #use the entire spritesheet surface as the window icon

world = World(spritesheet, BACKGROUND_COORDINATE, SCREEN_SIZE) #initialize the World object

clock = pygame.time.Clock() # initialize the clock object
game_speed = 70. # game speed per second

#width and height of the ship
w, h = 32, 32

#ship sprite left top position within maintile
pos = Vector2D(0, 0)

#create the first ship and add to group
ship_one = ShipSprite(maintile, w, h, pos)
ship_one.pos = Vector2D(screen_w/2-w, screen_h-h-h-h-h) 
world.addEntity(ship_one)

#create the second ship and add to group
ship_two = ShipSprite(maintile, w, h, pos)
ship_two.pos = Vector2D(screen_w/2-w-w, screen_h-h-h-h)
world.addEntity(ship_two)

while True:
   
    for event in pygame.event.get():
        
        if event.type == QUIT:
            exit()  
    
    #reset the speed to zero for both sjips
    v = Vector2D(0.0, 0.0)
    v1 = Vector2D(0.0, 0.0)
            
    pressed_keys = pygame.key.get_pressed() # get all the keys from key-press events 
        
    if pressed_keys[K_LEFT]: 
        v = Vector2D(-1., 0.) # move the top ship one unit to the left
        v1 = Vector2D(1., 0.) # move the bottom ship one unit to the right
        
    elif pressed_keys[K_RIGHT]:
        v = Vector2D(1., 0.) # move the top ship one unit to the right
        v1 = Vector2D(-1., 0.) # move the bottom ship one unit to the left
    
    world.updateShipPosition(ship_one.pos, ship_two.pos)
    world.render(screen) #render the game background and all the game entities 
    
    time_passed = clock.tick() #delta time for each frame
    time_passed_seconds = time_passed / 1000.0
    
    #re-adjust the position for both ships
    ship_one.pos+= v * game_speed * time_passed_seconds  
    ship_two.pos+= v1 * game_speed * time_passed_seconds
    
    pygame.display.flip()

One thing to take note here is that the world object will be used to control all the game entities as well as the background from here onward.

Create the World module for Rock Sweeper

Welcome to the second chapter of the Rock Sweeper project, a game which creates with Pygame. In this article we will create a World module which will later be used to manage game entities such as spaceship and rock as well as render the background image of the game.

We will use NetBeans IDE 8.1 to create this game, first open up your NetBeans IDE if you already have one or else you can refer to my previous article on how to install the NetBeans IDE on your computer. Start a new project and call it Rock Sweeper.

pygame's project
pygame’s project

Create an empty module under the same folder as the existing module and named it World. Below is the script for the World module which includes those use to blit the background.

from pygame.locals import *

class World(object):
    
    def __init__(self, maintile, background_coordinate, screen_size):
        
        #spritesheet
        self.spritesheet = maintile
        
        #the rectangle object uses in clipping the background area
        self.clip_rect = Rect(background_coordinate, screen_size)
        self.spritesheet.set_clip(self.clip_rect) # clip a portion of the spritesheet with that rectangle object
        self.background = self.spritesheet.subsurface(self.spritesheet.get_clip()) #create the background surface 
       
    def render(self, surface):
        surface.blit(self.background, (0,0))

In the main module we will call the World module to render the background within the while loop.

#!/usr/bin/env python

import pygame
from pygame.locals import *
from sys import exit
from world import World

maintile = 'maintile.png' #spritesheet file

SCREEN_SIZE = (550, 550) 
BACKGROUND_COORDINATE = (0, 32)

pygame.init()

screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
pygame.display.set_caption("Rock Sweeper")

spritesheet = pygame.image.load(maintile).convert_alpha() #spritesheet surface object

pygame.display.set_icon(spritesheet) #use the entire spritesheet surface as the window icon

world = World(spritesheet, BACKGROUND_COORDINATE, SCREEN_SIZE)

while True:
   
    for event in pygame.event.get():
        
        if event.type == QUIT:
            exit()
            
    world.render(screen) #render the background
    
    pygame.display.update()

If you run the main module above then you will see the below outcome.

blit background
blit background

The next chapter we will create game entities such as spaceship and rock so make sure you continue reading the tutorial!