由于使用emacs-org进行编辑,为方便使用了英文
spritecollide(sprite, group, dokill)
-> listgroupcollide(group1, group2, dokill1, dokill2)
-> dictionaryimport os, sys
import pygame
from pygame.locals import *
if not pygame.font: print('Warning, fonts disabled')
if not pygame.mixer: print('Warning, sound disabled')
os
, sys
modules can get independent on platforms.
pygame.locals
: commonly used constants and functions,
not necessary to include, just include pygame
is enough.
def load_image(name, colorkey = None):
fullname = os.path.join("assets", name)
try:
image = pygame.image.load(fullname)
except pygame.error as message:
print("cannot load image:", name)
raise SystemExit(message)
image = image.convert()
if colorkey is not None:
if colorkey is -1:
colorkey = image.get_at((0, 0,))
image.set_colorkey(colorkey, RLEACCEL)
return image, image.get_rect()
create a fullname, tryna load the img,
raise exception if failed, convert the img to the format
of the screen
to make it faster to blit,
set a transparent colorkey,
default the (0, 0,) point’s color,
return the img and its rect.
REACCEL
can boost up blitting but slow down modifying.
def load_sound(name):
class NoneSound:
def play(self): pass
if not pygame.mixer:
return NoneSound()
fullname = os.path.join("assets", name)
try:
sound = pygame.mixer.Sound(fullname)
except pygame.error as message:
print("cannot load sound", wav)
raise SystemExit(message)
return sound
class Fist(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = load_image("fist.bmp", -1)
self.punching = 0
def update(self):
pos = pygame.mouse.get_pos()
self.rect.midtop = pos
if self.punching:
self.rect.move_ip(5, 10)
def punch(self, target):
if not self.punching:
self.punching = 1
hitbox = self.rect.inflate(-5, -5)
return hitbox.colliderect(target.rect)
def unpunch(self):
self.punching = 0
use one of the sprite drawing Group classes.
These classes can draw sprites that have image
and rect
attribute.
By simply changing these two attributes, the renderer will
draw the current image at the current position.
All sprites have an update() method, called once per frame.
should put in code that moves and updates the variables
for the sprite.
class Chimp(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = load_image("chimp.bmp", -1)
screen = pygame.display.get_surface()
self.area = screen.get_rect()
self.rect.topleft = 10, 10
self.move = 9
self.dizzy = 0
def update(self):
if self.dizzy():
self._spin()
else:
self._walk()
def _walk(self):
newpos = self.rect.move((self.move, 0))
if not self.area.contains(newpos):
if self.rect.left < self.area.left or \
self.rect.right > self.area.right:
self.move = -self.move
newpos = self.rect.move((self.move, 0))
self.image = pygame.transform.flip(self.image, 1, 0)
self.rect = newpos
def _spin(self):
center = self.rect.center
self.dizzy += 12
if self.dizzy >= 360:
self.dizzy = 0
self.image = self.original
else:
rotate = pygame.transform.rotate
self.image = rotate(self.original, self.dizzy)
self.rect = self.image.get_rect(center = center)
def punched(self):
if not self.dizzy:
self.dizzy = 1
self.original = self.image
rotate
was made as a local reference,
to make that line shorter.
ALWAYS ROTATE FROM THE ORIGINAL PICTURE!!!
'cause each rotation will cost a loss of quality and size.
– when to make a copy?
– when first punched.
pygame.init()
screen = pygame.display.set_mode((468, 60))
pygame.display.set_caption("Chimp Fever")
pygame.mouse.set_visible(0)
init()
: initialize all the pygame modules imported.
display
: if not set, pygame’ll choose the best
color depth.
mouse.set_visible(0)
: set invisible
create a single surface
to represent the background
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((250, 250, 250))
get text rendered onto the background surface
if pygame.font:
font = pygame.font.Font(None, 36)
text = font.render("Pummel The Chimp, And Win $$$", 1, (1, 10, 10))
textpos = text.get_rect(centerx = background.get_width() / 2)
background.blit(text, textpos)
None
can be replaced by a TrueType font.
render
: create a new surface with appropriate size
1
to tell the renderer to use antialiased text
screen.blit(background, (0, 0))
pygame.display.flip()
flip
: handles the entire window area
both single-buffered and double-buffered surfaces
double-buffering:
在图形图像显示过程中,计算机从显示缓冲区取数据然后显示,
很多图形的操作都很复杂需要大量的计算,
很难访问一次显示缓冲区就能写入待显示的完整图形数据,
通常需要多次访问显示缓冲区,每次访问时写入最新计算的图形数据。
而这样造成的后果是一个需要复杂计算的图形,
你看到的效果可能是一部分一部分地显示出来的,造成很大的闪烁不连贯。
而使用双缓冲,可以使你先将计算的中间结果存放在另一个缓冲区中,
待全部的计算结束,该缓冲区已经存储了完整的图形之后,
再将该缓冲区的图形数据一次性复制到显示缓冲区。
create all the objects
whiff_sound = load_sound("whiff.wav")
punch_sound = load_sound("punch.wav")
chimp = Chimp()
fist = Fist()
allsprites = pygame.sprite.RenderPlain((fist, chimp))
clock = pygame.time.Clock()
allsprites
: a sprite Group named RenderPlain.
RenderPlain
can draw all the sprites it contains
to the screen.
clock
: used in the mainloop to control the
framerate
while 1:
clock.tick(60)
no more than 60 frames per second
work with the event queue
for event in pygame.event.get():
if event.type == QUIT:
return
elif event.type == KEYDOWN and event.key == K_ESCAPE
return
elif event.type == MOUSEBUTTONDOWN:
if fist.punch(chimp):
punch_sound.play()
chimp.punched()
else:
whiff_sound.play()
elif event.type == MOUSEBUTTONUP:
fist.unpunch()
K_ESCAPE
: ESC
.
allsprites.update()
sprite groups have an update() method,
which simply calls the update() for all the sprites
it contains.
screen.blit(background, (0, 0))
allsprites.draw(screen)
pygame.display.flip()
remember to Sprite.__init__(self)
, or respond:
AttributeError: 'mysprite' instance has no attribute '_Sprite__g'
belong to a group -> alive.
not belong to any group -> cleared up.
kill()
: remove the sprite from all the groups it belonged to.
sprites()
: return a iteratable object shows all the sprites
a group has.
update()
: update all.
contain at most 1 sprites, when added to, forget the old one.
every sprite has a image
and a rect
.
has a draw()
method that draw all the sprites on a surface
or a screen.
derived from RenderPlain.
add a method clear()
: clear sprites from the screen
with background.
derived from RenderClear, Cadillac of rendering Groups
.
the draw()
method will return a list of rects of all sprites
showing all the area that is occupied.
spritecollide(sprite, group, dokill)
-> listcheck for collisions between a single sprite
and a sprite group.
require a rect
attribute for all the sprites used.
dokill
: (boolean)
whether to call kill()
on all crashed sprites.
return a list of all the sprites in the group that collides.
groupcollide(group1, group2, dokill1, dokill2)
-> dictionarydokill1
: if true, kill all the crashed sprites in group1.
dokill2
: if true, kill all the crashed sprites in group2.
dict
: key is sprites in group1 that crashed.
its value is sprites in group2 that the key crashed
to get extra features.
deal with array
, holds an array of fixed size,
and all elements inside an array are of the same type.
apply to all elements in an array. (element-wise operations)
but only when able to apply the operation.
ex.
>>> array((1, 2, 3)) + array((4, 5, 6))
array([5, 7, 9])
>>> array((1, 2, 3)) + array((3, 4))
Traceback (most recent call last):
File "" , line 1, in <module>
ValueError: operands could not be broadcast together with shapes (3,) (2,)
# different size arrays cannot be added up.
same to python list.
sliced-out array still refers to the original array.
so if when changing the sliced-out array,
the original one changes, too.
use ,
to separate different dimention’s indices,
and for each dimention’s index,
almost same to 1d scenario, but can use :
to show “all”.
ex.
>>> b = array(((1, 2, 3), (3, 4, 5)))
>>> b[0, 1]
2
>>> b[1, :]
array([3, 4, 5])
>>> b[1]
array([3, 4, 5])
>>> b[:, :2]
array([[1, 2],
[3, 4]])
be sure to import: use exception ImportError
try:
import numpy as np
import pygame.surfarray as surfarray
except ImportError:
raise ImportErrer, "NumPy and Surfarray are required"