-
Notifications
You must be signed in to change notification settings - Fork 21
Advanced Graphics with Classes
For this tutorial, return to your ggame-tutorials repository that you forked earlier.
Create a new file called tutorial4.py and paste the following code into it to get
started:
from ggame import App, RectangleAsset, ImageAsset, Sprite, LineStyle, Color, Frame
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
# Background
black = Color(0, 1)
noline = LineStyle(0, black)
bg_asset = RectangleAsset(SCREEN_WIDTH, SCREEN_HEIGHT, noline, black)
bg = Sprite(bg_asset, (0,0))
myapp = App(SCREEN_WIDTH, SCREEN_HEIGHT)
myapp.run()This snippet should look familiar, as it is a "cut down" version of the
last tutorial that you worked on (tutorial3.py). Notice that we have
removed the step function entirely. In this tutorial, we will add the step
function back, but in an entirely different way!
For the first part of this tutorial, we would like to customize the behavior
of the standard App class by creating an entirely new application class
called MyApp that inherits its basic behavior from the standard App class.
Paste the following snippet in just before the myapp = ... line:
class SpaceGame(App):
"""
Tutorial4 space game example.
"""
def __init__(self, width, height):
super().__init__(width, height)Then cut the four lines that create the background and paste them in below
the super()... line and indent them to match. Now your code should look like this:
class SpaceGame(App):
"""
Tutorial4 space game example.
"""
def __init__(self, width, height):
super().__init__(width, height)
black = Color(0, 1)
noline = LineStyle(0, black)
bg_asset = RectangleAsset(width, height, noline, black)
bg = Sprite(bg_asset, (0,0))Yes, you could have pasted this in from the get-go, but I want you to be very clear about where this code is coming from.
Things to notice about the change:
-
class SpaceGame(App):defines a new class, calledSpaceGame, that inherits all of the functionality of the standardAppclass. - The next line defines the
__init__method for the class. In this case it exactly matches the arguments of theAppclass' version of__init__. - The
super().__init__(...line forces the new SpaceGame class to call the standard App class'__init__function before beginning its own initialization. Always do this if you want your new class to fully inherit the behavior of the parent class. - Finally, since this code initializes the game, it makes sense to place
the code for creating a black background in the
__init__method of the game class.
As it stands, your program is broken. To make the new SpaceGame class take effect, we have to instantiate it instead of instantiating the App class. Change the next to last line of the program to read:
myapp = SpaceGame(SCREEN_WIDTH, SCREEN_HEIGHT)Try running the program. You should see a black background that is 640x480 pixels.
Just above your SpaceGame class definition, paste this new code:
class SpaceShip(Sprite):
"""
Animated space ship
"""
asset = ImageAsset("images/four_spaceship_by_albertov_with_thrust.png",
Frame(227,0,292-227,125), 4, 'vertical')
def __init__(self, position):
super().__init__(SpaceShip.asset, position)Run your program. It should not do anything different from before. Creating a new Sprite class does not actually create any sprites. All it does is create a blueprint for making sprites.
Add a single SpaceShip sprite by adding the following line to the end of
the SpaceGame __init__ method:
SpaceShip((100,100))Now run your code. Cool. Try adding a few more SpaceShip instances:
SpaceShip((150,150))
SpaceShip((200,50))It looks like you are building a fleet!
The code we added is very simple, but there is one line that needs some explanation:
asset = ImageAsset("images/four_spaceship_by_albertov_with_thrust.png",
Frame(227,0,292-227,125), 4, 'vertical')The asset variable is created within the class, but outside of any methods.
This makes it a class attribute that will be available to all instances of
the class. We used this to call the parent Sprite class __init__ method using
the syntax: SpaceShip.asset. This approach allows us to create as many
instances of the SpaceShip as we want, but without creating multiple
assets. There is one object representing the spaceship image, but multiple
objects representing the sprites.
This call to create an ImageAsset has more arguments than we used in the
previous tutorial. Here's what they are about:
- The
Frame(227,0,292-227,125)argument specifies a rectangular section within the image file. If you look at the image file in Github you will notice that it actually consists of sixteen different spacecraft images, some with rocket thrust and some without. The frame arguments refer to the horizontal and vertical location of the upper left hand corner of the sub-image we want, followed by the width and height of it. - The
4argument means that the asset will actually include four sub-images of the same size as the first, and... - The
'vertical'argument means that those four images are arranged vertically in the image file.
All of this additional information means that this asset is ready to animate! It consists of a single spaceship without thrust, and three spaceship images that include a blast of thrust. By selecting which of these frames we want to show at any given time, we can give the appearance of motion within the sprite itself.