August'24: Kamaelia is in maintenance mode and will recieve periodic updates, about twice a year, primarily targeted around Python 3 and ecosystem compatibility. PRs are always welcome. Latest Release: 1.14.32 (2024/3/24)
Cookbook Example
How can I...?
Example 9 : Simple component based game using pygame. This demonstrates use of a collection of simple physics behaviours components, Graphline to bind these to a BasicSprite component, an EventHandler to show how to deal with keyboard handling, a fanout component to help co-ordinate shutdown, and a specialised scheduler - the SpriteScheduler component to run these. Components used:Graphline, BasicSprite, SpriteScheduler, EventHandler, fanout, bouncingFloat, cartesianPingPong, loopingCounter, continuousIdentity, continuousZero, continuousOne
Warnings: if you're less than 4 you'll love this game ;-) Also, This isn't quite integrated with the PyGameApp code, but shows a nice way of writing simple games.
#!/usr/bin/python
import pygame
import random
import os
from Kamaelia.Util.Graphline import Graphline
from Kamaelia.UI.Pygame.BasicSprite import BasicSprite
from Kamaelia.Physics.Behaviours import bouncingFloat, cartesianPingPong, loopingCounter, continuousIdentity, continuousZero, continuousOne
from Kamaelia.UI.Pygame.EventHandler import EventHandler
from Kamaelia.Util.Fanout import fanout
from Kamaelia.UI.Pygame.SpriteScheduler import SpriteScheduler
= "banner.gif"
banner_location = "cat.gif"
cat_location = "hold.wav"
cat_pop_wav_file = "KDE_Beep_Bottles.wav"
cat_appear_wav_file = (700,550)
screensize = (255,255,255)
back_colour = 40
border = pygame.DOUBLEBUF
flags
= pygame.mixer.Sound(cat_pop_wav_file)
cat_pop_wav = pygame.mixer.Sound(cat_appear_wav_file)
cat_appear_wav
pygame.init()# --------------------------------------------------------------------------
def makeAndInitialiseBackground(banner_location, screensize,
screen_surface, back_colour):#
# Load images for background
#
= pygame.image.load(banner_location)
banner_surface = banner_surface.convert()
banner = banner_surface
surface = banner_surface.get_width()
width = banner_surface.get_height()
height
#
# Calculate position for image, relative to screen size.
# This is calculated as a rectangle
#
= (screensize[0] - width)/2
horizonal_to_move = (screensize[1] - height)/2
vertical_to_move = banner_surface.get_rect()
rect = rect.move([horizonal_to_move,vertical_to_move])
rect
# Create the actual background, and then insert the image(s) into the
# background.
#
= pygame.Surface(screen_surface.get_size())
background = background.convert()
background
background.fill(back_colour)
background.blit(banner_surface, rect)
#
# Finally, return the completed background.
#
return background
def randomFromRangeExcludingZero(min,max):
= 0
result while result == 0:
= random.randint(min,max)
result return result
def make_cat(cat_location, screensize, border ):
# Get the cat again!
= list()
files for x in os.listdir("pictures"):
if x not in ("README","CVS"):
files.append(x)
= files[random.randint(0,len(files)-1)]
image_location
= pygame.image.load("pictures/"+image_location)
cat_surface = cat_surface.convert()
cat 255,255,255), pygame.RLEACCEL)
cat.set_colorkey((
= randomFromRangeExcludingZero(-2,2)
rotation_speed = float(randomFromRangeExcludingZero(-1,1))
scale_speed = list( (random.randint(border,screensize[0]-border),
position 1]-border)))
random.randint(border,screensize[
= BasicSprite(image=cat)
newCat
= Graphline(
X = newCat,
newCat = loopingCounter(rotation_speed),
rotator = cartesianPingPong(position,screensize[0],screensize[1],border),
translation = bouncingFloat(scale_speed),
scaler = continuousIdentity(cat),
imaging = fanout(["rotator","translation","scaler", "imaging","self_shutdown"]),
shutdown_fanout = {
linkages "rotator","outbox" ) : ("newCat", "rotator"),
("translation","outbox" ) : ("newCat", "translation"),
("scaler","outbox" ) : ("newCat", "scaler"),
("imaging","outbox" ) : ("newCat", "imaging"),
("newCat", "signal" ): ("shutdown_fanout", "inbox"),
("shutdown_fanout", "rotator") : ("rotator", "control"),
("shutdown_fanout", "translation") : ("translation", "control"),
("shutdown_fanout", "scaler") : ("scaler", "control"),
("shutdown_fanout", "imaging") : ("imaging", "control"),
("shutdown_fanout", "self_shutdown") : ("shutdown_fanout", "control"),
(
}
).activate()
return newCat
def make_cats(cat_location, screensize, border, numberCats=20):
= []
cat_sprites for i in range(numberCats):
# Need to load the image separately for each sprite...
= make_cat(cat_location, screensize, border)
newCat
cat_sprites.append(newCat)return cat_sprites
class MyGamesEvents(EventHandler):
def __init__(self, cat_args, trace=1, ):
self.trace = 0
self.cat_args = cat_args
def mousebuttondown(self, pos, button, where):
if button == 1:
= cat_appear_wav.play()
channel = make_cat(*self.cat_args)
newCat = newCat
cat_sprite
where.allsprites.add(cat_sprite)if button == 2:
= where.allsprites.sprites()
sprites for sprite in sprites:
if sprite.rect.collidepoint(*pos):
sprite.togglePause()if button == 3:
# Make a sprite disappear
= cat_pop_wav.play()
channel = where.allsprites.sprites()
sprites = 0
popped for sprite in sprites:
if sprite.rect.collidepoint(*pos):
= sprite
spriteToZap
spriteToZap.shutdown()
where.allsprites.remove(spriteToZap)return
try:
= sprites[len(sprites)-1]
spriteToZap except IndexError:
pass
else:
spriteToZap.shutdown()
where.allsprites.remove(spriteToZap)def keydown(self, unicode, key, mod, where):
if key == 112: # "P"
# PAUSE ALL MOVEMENT
for sprite in where.allsprites.sprites():
sprite.pause()if key == 113: # "Q"
raise "QUIT"
if key == 117: # "U"
# UNPAUSE ALL MOVEMENT
for sprite in where.allsprites.sprites():
sprite.unpause()if key == 116: # "T"
# Toggle PAUSE ALL MOVEMENT
for sprite in where.allsprites.sprites():
sprite.togglePause()
= pygame.display.set_mode(screensize, flags)
screen_surface = makeAndInitialiseBackground(banner_location, screensize, screen_surface,back_colour)
background = make_cats(cat_location, screensize, border,1)
cat_sprites = (cat_location, screensize, border)
cat_args
try:
SpriteScheduler(cat_args, cat_sprites, background, screen_surface, MyGamesEvents).run()except:
pass
Source: Examples/example9/Simplegame.py