ICS4U – Applying OOP with Pygame

ICS4U Learning Goals

In this ICS4U Grade 12 Computer Science lesson you will be learning how to

  • Make a simple game using the Python Pygame Library
  • Create a program a program using multiple classes
  • Apply the principles of inheritance to a program

Install the Pygame Module

Some python installations already include the Pygame library Modules.  An easy way to check is to run a program with the line

				
					import pygame
				
			

If it runs without an error you are already setup and good to go.  If not, then we need to use PIP (a package management system) to install the libraries.  

These are what I have found works best for some different IDE’s

IDLE on Windows -> Open a command prompt and type 

  • py -m pip install pygame

IDLE on Mac -> Open a Terminal  and type 

  • pip install pygame

Ancaconda Installation -> Search for “Anaconda Prompt” and in the terminal window type

  • pip install pygame

VSCode on Windows -> Open a terminal inside VSCode and type

  • py -m pip install pygame

Pycharm -> Has a built in package manager you can access from the bottom left portion on the app.  You can search and install pygame from there.

Basics of Pygame

Pygame is event-driven.  That means it is not a linear flowing program that you have been used to creating.  The program waits for events to happen, and then responds accordingly.  Common events might be mouse clicks, keyboard presses, collisions.  To make this happen you will require and infinite game loop that never stops until the program is closed.  Basically your loop will accomplish the following tasks

  • Check for events
  • Update the gamestate (positions, velocities, other variables) based on what event occcured
  • Draw the background
  • Draw the images of everything in the game on the background

The details of how exactly to do this in pygame can get really complicated, very fast.  There are MANY different ways that you will find on the internet on how different coders will make all these things fit together. 

I have decided to come up with a way to do all this so it follows the curriculum for the course.  We are taking an Object Oriented Approach to creating these games.  That is, you must think of everything in the game as an object.  Everything you add to your games will be coded inside classes.  (It doesn’t have to but we have an obligation to meet the curriculum requirements, so that is what you are going to do)

To make this easier, and to take the focus off of actually having to learn the gritty details of pygame, we are going to use a custom Module that I created. You MUST use this module when doing your assignments to ensure that you are meeting the curriculum requirements on the course.

Course Pygame Module

Best way to handle the module is just to save it in the same directory as your python .py game file

Game Template

You have a main game window.  In the game you will add Rooms.  Rooms act like levels in your game.  Your first room might be a title screen, then you might have several levels in your game. Finally you might decide to have a game over screen with high scores. 

All the objects objects you create for your game will be added to their specific room  The game loop will keep track of what Room the game is currently in and only update and draw the objects in the correct room.  When an event happens that requires the game to proceed to a different room, it will do so and only update objects in that room.

 

ICS4U Interactive Learning Activity - Grade 12 Computer Science

Follow along with the video below and get the basic setup working on your machine

Explanation of Game and Room Classes

Here is a little bit more information on the functions that make up the Game and Room Classes from the course pygame module.

I encourage you to open that file and take a look at what is going on in there if you wanted to know a little bit more about pygame.  Please keep in mind I am not a pygame expert by any means.  I wrote this module to make it easier for you to make some simple games without having to worry about the gritty details of pygame. If you have a better way to do things and want to modify the Module, you are free to, but make sure I get your updated file when you submit your game.

Creating Objects in the Game

Remember that these games will consist of a collection of objects that will eventually interact with each other through events to form the gameplay

ICS4U Interactive Learning Activity - Grade 12 Computer Science

Follow along with the video below and learn how to create some simple objects to add to your game

Adding Mouse Click Events

A simple event in pygame is a mouse click. We have to be able to determine what object was clicked on, and then add an action to occur for that event.  

This type of event isn’t the easiest to implement in pygame.  There are many different ways that it could be done, but here is the general idea on how I accomplished the task

  • In the update event of any object we want to check if the mouse was pressed down and is overtop of its image

NOTE:  I have in the past have had “some”, but not all MAC users saying the mouse click code doesn’t work properly sometimes on their machine.  I honestly don’t have a clue why nor do I have a MAC to test some fixes.  One suggestion is to not use the drawn objects like rectangles and circles, but to download and import an actual image file (gif, jpg,etc) instead.  They had some success with that as clicking on those images seemed to work better.

ICS4U Interactive Learning Activity - Grade 12 Computer Science

Follow along with the video below and learn how to react to mouse clicks

Creating Text Boxes and Buttons

Drawing text on the screen in pygame isn’t as straightforward as it should be.  Part of the course pygame module has classes I developed to make it easy to draw text on the screen at any location and make what looks like a clickable button.  

ICS4U Interactive Learning Activity - Grade 12 Computer Science

Follow along with the video below and learn how to draw text and click on buttons

Multiple Rooms and Timers

Rooms

You can create multiple rooms using the course pygame module.  These rooms act as levels for your game or start screens or game over screens.  Rooms are stored in the module in a list in the order they are created in the game.  Basically the module just draws objects that exist in the current room.

You can add objects to any room you want at the start of the game or as the game is being played.

To go to different rooms there are two functions:

  • nextRoom( ) – This function sends control of the game to the next room in the list
  • goToRoom ( x ) – This function sends control of the game to a specific room.  The argument x is the index of the room you want to go to.  First Room created is index 0, second room is index 1, etc.  

Timers

Pygame didn’t really have an easy way to have things happen after a given time period, and that can be really useful in game.  The course module contains an Alarm Class to make that easier for you to code. 

Alarms count down from a starting time and trigger an alarm event. Alarms can be global objects or can be created as an attribute of an object.

Before using an alarm you need to create an alarm object using its constructor …. something like self.timer = Alarm( ) .  The contructor takes no parameters.

You can set the timer to start counting down at any point in the code with the setAlarm function.  The amount of time in milliseconds is passed as a parameter

  • self.timer.setAlarm(1000) will set an alarm event to go off after 1 second
  • self.timer.setAlarm(5000) will set an alarm event to go off after 5 second

In order to use this alarm event you need to check in your update function if that alarm is finished or not.  There is a function called finished( ) that returns true or false if that alarm has gone off or not. This would typically be used in an if statement to apply a piece of code when the alarm has gone off.

ICS4U Interactive Learning Activity - Grade 12 Computer Science

Enter the code below to see an example of how Multiple Rooms and Timers work

				
					import pygame
import random
from pygameRogers import Game
from pygameRogers import Room
from pygameRogers import TextRectangle
from pygameRogers import Alarm

#Create a new Game
g = Game(640,480)

#Graphic Resources
BLACK = (0,0,0)
WHITE = (255,255,255)
myFont = g.makeFont("Arial",38)
gameBackground = g.makeBackground(BLACK)

#Button for the first room -> Sends game to next room
class NextRoomButton(TextRectangle):

	def __init__(self, text, xPos, yPos, font, textColor, buttonWidth, buttonHeight, buttonColor):
		TextRectangle.__init__(self, text, xPos, yPos, font, textColor, buttonWidth, buttonHeight, buttonColor)

	def update(self):
		# Check for a mouse click
		self.checkMousePressedOnMe(event)

		# Update Game State when mousebutton released
		if self.mouseHasPressedOnMe and event.type == pygame.MOUSEBUTTONUP:

			# Goto next room
			g.nextRoom()


			# Prevent multiple mouse clicks
			self.mouseHasPressedOnMe = False

#Button for the second room -> Makes a random message appear every 1 second
class StartTimerButton(TextRectangle):

	def __init__(self, text, xPos, yPos, font, textColor, buttonWidth, buttonHeight, buttonColor):
		TextRectangle.__init__(self, text, xPos, yPos, font, textColor, buttonWidth, buttonHeight, buttonColor)
		self.thingsToSay = ["Hi", "Bye", "Welcome", "Greetings", "Go Away", "See You Later", "Come Here"]

		#Create an Alarm
		self.timer = Alarm()

	def update(self):
		# Check for a mouse click
		self.checkMousePressedOnMe(event)

		# Update Game State when mousebutton released
		if self.mouseHasPressedOnMe and event.type == pygame.MOUSEBUTTONUP:

			#Set Timer To go off 2 seconds after button being clicked
			self.timer.setAlarm(2000)

			# Prevent multiple mouse clicks
			self.mouseHasPressedOnMe = False

		#Check if the alarm is done
		if self.timer.finished():

			#Change the word
			self.word = random.choice(self.thingsToSay)
			self.setText(self.word)

			#Reset the alarm to go off again after 1 second (Creates a little alarm loop constantly going off after 1 second
			self.timer.setAlarm(1000)


#Create the Rooms and add them to the game
r1 = Room("Level 1",gameBackground )
g.addRoom(r1)
r2 = Room("Level 2",gameBackground)
g.addRoom(r2)


#Create the buttons objects and add them to the rooms
myButton = NextRoomButton("Next Room",g.windowWidth/2-150/2, g.windowHeight - 75, myFont, BLACK, 200,50, WHITE)
myTimerStart = StartTimerButton("Start Timer",g.windowWidth/2-150/2, g.windowHeight - 75, myFont, BLACK, 200,50, WHITE)
r1.addObject(myButton)
r2.addObject(myTimerStart)


#Start Game----------------------------------------------------------
#Game Loop
g.start()

while g.running:

	# How often the game loop executes each second
	dt = g.clock.tick(60)

	# Check Events
	for event in pygame.event.get():

		# Check for [x]
		if event.type == pygame.QUIT:
			g.stop()

	# Update All objects in Room
	g.currentRoom().updateObjects()

	# Render Background to the game surface
	g.currentRoom().renderBackground(g)

	# Render ALL Objects to the game surface
	g.currentRoom().renderObjects(g)

	# Draw everything on the screen
	pygame.display.flip()

pygame.quit()