$ virtualenv MYGAME $ source MYGAME/bin/activate (MYGAME) $ pip install --upgrade http://pyglet.googlecode.com/archive/tip.zip
Walk through basics of writing a game:
Along the way write a fun toy in 20-30 lines of Python code.
Gaming libraries:
Pyglet is slightly more modern, Pygame more widely used.
We’re using Pyglet
Working with pre-release version. Fixes some bugs that bit me on MacOS
$ virtualenv MYGAME $ source MYGAME/bin/activate (MYGAME) $ pip install --upgrade http://pyglet.googlecode.com/archive/tip.zip
Using the Pyglet API
import pyglet
window = pyglet.window.Window()
#pyglet.app.run()
You can read about the Window Class in the Pyglet docs.
Pyglet handles making a UI window, sizing it, handles OS events like "Close" button.
Try it out!
Frameworks always lead to "weird" code because you’re not exactly in charge. But pyglet does a pretty good job of helping you structure your code.
pyglet.window.Window() is a class. Instanciating it makes a window show up.
pyglet.app.run() starts a program that you didn’t write.
What happens if you comment out the pyglet.app.run() line?
Event loops are common in many kinds of programming - from network to UI - where what your program does is sit there, waiting for events happen.
import pyglet
window = pyglet.window.Window()
label = pyglet.text.Label('Hello, world', x=window.width//2, y=window.height//2,
anchor_x='center', anchor_y='center')
@window.event
def on_draw():
window.clear()
label.draw()
pyglet.app.run()
Pyglet generally has us handle events by providing an event handler.
Event handler is just a function that registers in some way that it wants to be called when something happens.
import pyglet
window = pyglet.window.Window()
label = pyglet.text.Label('Hello, world', x=window.width//2, y=window.height//2,
anchor_x='center', anchor_y='center')
@window.event
def on_draw():
window.clear()
label.draw()
pyglet.app.run()
Game frameworks all do more or less the same thing when used naively - every few milliseconds redraw the screen. This is the Application Loop or Game Loop.
Animation comes from moving things around.
The on_draw event is your simples access to Pyglet’s Application Loop. Let’s add some animation
import pyglet
window = pyglet.window.Window()
label = pyglet.text.Label('Hello, world', x=window.width//2, y=window.height//2,
anchor_x='center', anchor_y='center')
@window.event
def on_draw():
window.clear()
label.x += 1
label.y += 1
label.draw()
pyglet.app.run()
Does it work? (Hit the space bar)
the on_draw event is only called if there’s something to do.
And if no events have happened, then nothing has changed, and there’s nothing to do!
We need to cause an event on a regular basis.
import pyglet
window = pyglet.window.Window()
label = pyglet.text.Label('Hello, world', x=window.width//2, y=window.height//2,
anchor_x='center', anchor_y='center')
def update(dt):
print(dt) # time elapsed since last time we were called
label.x += 1
label.y += 1
@window.event
def on_draw():
window.clear()
label.draw()
pyglet.clock.schedule(update) # cause a timed event as fast as you can!
pyglet.app.run()
Use pyglet.clock.schedule(func) or pyglet.clock.schedule_interval(func, seconds) to schedule timed events.
We’re using x and y coordinates. What are the numbers and what do they mean?
x is the horizontal axix, y is the vertical axis.
The bottom left corner is (x=0, y=0). The unit is pixels.
Oh and by default most things are placed by their bottom left corner. Hence the configuration:
label = pyglet.text.Label('Hello, world', x=window.width//2, y=window.height//2,
anchor_x='center', anchor_y='center')
Pyglet lets us show images easily!
import pyglet
window = pyglet.window.Window()
image = pyglet.resource.image('simeon64x64.jpg')
image.anchor_x = image.width // 2
image.anchor_y = image.height // 2
@window.event
def on_draw():
window.clear()
image.blit(window.width//2, window.height//2)
pyglet.app.run()
Although if you have a lot of images see http://www.pyglet.org/doc/programming_guide/displaying_images.html <<<
Pyglet lets us play sounds
import pyglet
window = pyglet.window.Window()
explosion = pyglet.resource.media('explosion.wav', streaming=False)
def boom(dt):
explosion.play()
@window.event
def on_draw():
window.clear()
pyglet.clock.schedule_interval(boom, 1) # Explode every 1 seconds
pyglet.app.run()
See http://www.bfxr.net/ for your own 8bit game sounds.
We want to do more than draw the window and cause timed events. You can’t have a game without user input!
It’s easy in pyglet to handle discrete mouse and keyboard events. Try holding down on the arrow keys in this demo however…
import pyglet
from pyglet.window import key, mouse
window = pyglet.window.Window()
image = pyglet.resource.image('simeon64x64.jpg')
position = dict(x=0, y=0)
@window.event
def on_key_press(symbol, modifiers):
if symbol == key.RIGHT:
position['x'] += 1
elif symbol == key.UP:
position['y'] += 1
elif symbol == key.DOWN:
position['y'] -= 1
elif symbol == key.LEFT:
position['x'] -= 1
@window.event
def on_mouse_press(x, y, button, modifiers):
if button == mouse.LEFT:
position['x'] = x
position['y'] = y
@window.event
def on_draw():
window.clear()
image.blit(position['x'], position['y'])
pyglet.app.run()
Let’s see:
I’d like replicate a game from my childhood.
Funnels and Buckets taught me to type math facts fast on a 10key keypad.
It was released in 1984 (I know, I’m getting old).
The game at its simplest is
See http://youtu.be/mfnV47vLsmk?t=24s for gameplay
Identify all the game pieces that will be displayed (math fact, answer box, score box, etc)
Create objects to represent them and draw them on the screen. Use timed events to update the drawn objects.
Use globals to store state (what math fact?, what is the answer? What is the score?)
You may find that you have more code in your problem domain than in your game domain. How do you generate the math problems and calculate the correct answer?
I’m going to look at http://en.wikipedia.org/wiki/Spaced_repetition and see if I can optimize the math problems shown so that difficult problem re-occur but not too soon!
/
#