pygame笔记(更新中

pygame Notebook

由于使用emacs-org进行编辑,为方便使用了英文

Table of Contents

  1. chimp (instance)
    1. importing modules
    2. loading resources
      1. image
      2. sound
    3. game object classes
      1. fist
      2. chimp
    4. init everything
    5. create the background
      1. create the surface
      2. put text on the background
      3. display the background (after the setup)
    6. prepare game obj
    7. main loop
    8. handle input events
    9. update all the sprites
    10. draw the entire scene
    11. no need to do anything cleaning up
  2. sprites
    1. use group
    2. group types
      1. Group
      2. GroupSingle
      3. RenderPlain
      4. RenderClear
      5. RenderUpdates
    3. collision detection
      1. spritecollide(sprite, group, dokill) -> list
      2. groupcollide(group1, group2, dokill1, dokill2) -> dictionary
    4. create my own group class
  3. numpy (Numeric Python) intro
    1. mathematical operations
    2. array slice
    3. 2d array slice
  4. surfarray
  5. making game

chimp (instance)

importing modules

import 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.

loading resources

image

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.

sound

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

game object classes

fist

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.

chimp

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.

init everything

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 the background

create a single surface to represent the background

create the surface

background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((250, 250, 250))

put text on the background

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

display the background (after the setup)

screen.blit(background, (0, 0))
pygame.display.flip()

flip: handles the entire window area
both single-buffered and double-buffered surfaces

  • Note taken on [2020-01-10 周五 00:45]

double-buffering:
在图形图像显示过程中,计算机从显示缓冲区取数据然后显示,
很多图形的操作都很复杂需要大量的计算,
很难访问一次显示缓冲区就能写入待显示的完整图形数据,
通常需要多次访问显示缓冲区,每次访问时写入最新计算的图形数据。
而这样造成的后果是一个需要复杂计算的图形,
你看到的效果可能是一部分一部分地显示出来的,造成很大的闪烁不连贯。
而使用双缓冲,可以使你先将计算的中间结果存放在另一个缓冲区中,
待全部的计算结束,该缓冲区已经存储了完整的图形之后,
再将该缓冲区的图形数据一次性复制到显示缓冲区。

prepare game obj

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

main loop

while 1:
    clock.tick(60)

no more than 60 frames per second

handle input events

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.

update all the sprites

allsprites.update()

sprite groups have an update() method,
which simply calls the update() for all the sprites
it contains.

draw the entire scene

screen.blit(background, (0, 0))
allsprites.draw(screen)
pygame.display.flip()

no need to do anything cleaning up

sprites

remember to Sprite.__init__(self), or respond:

AttributeError: 'mysprite' instance has no attribute '_Sprite__g'

use group

  • Note taken on [2020-01-11 周六 00:48]
    get some methods here

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.

group types

Group

GroupSingle

contain at most 1 sprites, when added to, forget the old one.

RenderPlain

every sprite has a image and a rect.

has a draw() method that draw all the sprites on a surface
or a screen.

RenderClear

derived from RenderPlain.
add a method clear(): clear sprites from the screen
with background.

RenderUpdates

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.

collision detection

spritecollide(sprite, group, dokill) -> list

check 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) -> dictionary

dokill1: 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

create my own group class

to get extra features.

numpy (Numeric Python) intro

deal with array, holds an array of fixed size,
and all elements inside an array are of the same type.

mathematical operations

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.

array slice

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.

2d array slice

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]])

surfarray

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"

making game

你可能感兴趣的:(Python)