Python游戏:PyGame « 燕之庐网站建设

2010/02/01

Tags:

Pygame是脚本语言Python的一个扩展包就是SDL的封装包,是用Python C语言开发;开发人是Pete Shinners。专门用于开发各类游戏。SDL意思是Simple Directmedia Library即“简单媒体类库”,这是一个跨平台的控制多媒体的C语言类库,类似于 DirectX。这里说的媒体包括CDROM即光驱、键盘鼠标、音频视频、操纵杆等 输入输出设备,Pygame写了关于这些对象的类库可在官方网站上找到。因为是“面向对象”就是所谓Object-Oriented编程语言,所以我们可 以继承这些类的性质来编写我们自己的游戏。

Pygame的官方网站: PyGameLogoTiny.gif
可惜中文的Pygame文档还没有。因为Pygame是面向对象脚本编程语言 Python的一个扩展,所以在使用Pygame之前要求基本的Python的知识和技术。

不 管在什么平台上开发,所有游戏的代码通常会有的结构包含六个部分:

  1. (一)加载Pygame的或者其他工具软件的模块,在 Python是使用import语法完成;
  2. (二)资源处理类包括处理图象、声音、连接或断开网络等;
  3. (三)游戏本身 的对象类;
  4. (四)其他函数。包括不能归类的必要函数,它们可以归入游戏的逻辑代码块里但是这样处理会增加理解代 码的难度,所以把这类函数单独处理;
  5. (五)初始化。包括Pygame本身对象的初始化;游戏对象的初始化;背景、鼠标的初始化等;
  6. (六) 主循环就是def main()。处理用户输入、更新游戏对象和显示区等。

实 际上,游戏的结构是个风格问题,不同的人、从不同的侧重点出发会使用不同的方法组织自己的游戏代码。中国人学太极拳的时候有这样的一个讲究,刚刚开始学的 时候要有严格的“架式”就是动作规范,但是等到悟到用意不用力、用意念引导动作的阶段就可以随心所欲,不必太拘泥于一招一式细节了。

例如有从xx另外的角度的方法,把代码按照一下四个方面组织:(请查看的 资源作为参考)

  1. 模块和对象的初始化;
  2. 处理用户输入和事件循环;
  3. 动画和模拟;
  4. 提 交;

不管使用什么方式组织代码,上面例子中最主要的结构有两个:一个是主程 序即mail() loop;一个是游戏对象的类。主程序是游戏脚本开始时执行的,包括处理Pygame模块本身的初始化和游戏对象的初始化,还包括所谓事件循环就是处理游 戏玩家的输入如鼠标、键盘动作和其他事件的队列;而游戏类对象封装了游戏角色的数据和逻辑。对于初学者来说,先理解这两个结构可收提纲协领的效果。有些简 单的游戏只有一个游戏对象(没办法,我们总是要从最简单的例子开始),可能没有xx按照上面的格式写,但总是包含了这样的模式在里面。

这里有一个Pygame的代码库,各种游戏代码可供研究:

{dy}个简单的例程hello.py:

#Find place where Python interpretor located 让游戏脚本找到Python解释器安装的地方
#!/usr/bin/python

#Import using modules 输入要用到的模块
import pygame
from pygame.locals import *

def main():
#Initialise screen 初始化。初始化软件模块、初始化屏幕
pygame.init()
screen = pygame.display.set_mode((150, 50))
pygame.display.set_caption(’Basic Pygame program’)

#Fill background 添入背景
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((250, 250, 250))

#Display some text 显示区里显示文本
font = pygame.font.Font(None, 36)
text = font.render(”Hello There”, 1, (10, 10, 10))
textpos = text.get_rect()
textpos.centerx = background.get_rect().centerx
background.blit(text, textpos)

#Blit everything to the screen 把所有东西画到屏幕上
screen.blit(background, (0, 0))
pygame.display.flip()

#Event loop事件循环
while 1:
for event in pygame.event.get():
if event.type == QUIT:
return

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

#start main() 启动脚本时执行主循环
if __name__ == ‘__main__’: main()

把这段代码用自己的编辑器写入你 的一个名字叫py/的目录里,这个目录里只包含作为测试和学习用的代码样例(当然你也可以有其他的安排,你肯定有自己的打算 。注意你下载这个程序时不要使用中文注释,特别不要使用中文的#号,Python的解释器不能识别。请只下载代码。我这里加中文是为了解释代码的方便。注 意给这个脚本一个名字hello.py。

用这个简单的程序我们完成了一个框架,多数应用程序特别 是一个游戏就是写在这上面的,如下图:
图像  “http://www.pygame.org/docs/tut/tom/basic.png” 因其本身有错无法显示。

不算空格,加注释行,就是以#号开始的,以上总共31行代码。还有其他的语言能用同样的代码量来完成同样的工作 吗?也许你用可视化工具可以很容易地作出这了来,但那只是“依样画葫芦”!而你用Python写出这个简单的框架,你学会了一种功能强大的语言!也许你会 说Java的Applet能用更少的代码完成这些工作,实际上不是这样的,因为Java/Applet是在用户端的浏览器帮助下完成的,而这个是 stand alone。Python还是一种标准的黑客工具,世界上顶极黑客正在使用她!

是很 简单吗?但是你已经开始了!这个简单的程序里已经包含了游戏的主要结构。
首先你要在计算机监视器上创建一个游戏执行的框架区域,一般叫做 screen。

***********************************************
课 堂实验一
使用命令python进入命令行模式:

>>> import pygame
>>> from pygame.locals import *
>>> screen = pygame.display.set_mode((800,400))

这样 你创建了一块屏幕面积,宽800个像素,高400个像素,它的左上角的坐标为(0,0)这样你就完成了屏幕初始化的工作。

********************************************

学习一种语言{zh0}的办法就是实验,通过观察软件的行为,输入输出的变化来理解代码的功能。跟随我的路线图保证你 能在最短时间内顺利掌握语言和技术精髓,不必从基本教程开始。牛顿说过:“在科学发展上实例比理论更重要!”,我相信在学习技术上也是这样。我们先仔细地 研究这个程序样例,深入剖析,彻底理解,举一反三,触类旁通。

  1. (1)pygame.init( ) ——实现模块初始化,就是把你要输入的模块进行初始化,准备工作;
  2. (2)screen. = pygame.display.set_mode((150,50)) ——初始化游戏屏幕,宽150高50个像素。
  3. (3)pygame.display.set_caption( ‘Basic Pygame Program’) ——在屏幕的页眉上写字;
  4. (4)background = pygame.Surface(screen.get_size() ) ——开始填满背景,.get_size()表示跟屏幕一样大。引用Surface创建的实例相当于在前面创建的screen上敷上一张画布,所以后面的 blit( )方法实际上是在这张画布上画,而不是直接在screen上画;
  5. (5)background.fill((255,255,255)) —— 把RGB格式的颜色写入背景;
  6. (6)font = pygame.font.Font( );text = font.render(”Hello There”,1,(10,10,10))以及上面的screen是模块的对象,区别于游戏本身的对象。font创建字体对象,text创建文本对象就是 框架中间的Hello There,(10,10,10)是文本字体的颜色,而中间的数字1是对字体性质的限定,这里我们先忽略;
  7. (7)textpos = text.get_rect( ) —— 是为font.render( )提交变量的text准备一个矩形框,让提交的文本放在这里;
  8. (8)background.blit ( text,textpos ) —— 可能blit ( )是最值得注意的方法,这不是一个常用词,本copy和past是同义词,就是拷贝和粘貼的意思,把什么什么拷贝/粘貼在什么什么上面,这里就是把 text粘貼在textpos上的意思;
  9. (9)screen.blit(background,(0,0)) —— 接着又一次出现blit( )方法,这次是把上一步粘貼好文本的background再拷贝在screen上,(0,0)表示从坐标原点开始就是从左上角开始;
  10. (10)pygame.display.flip( ) —— flip英文意思是轻拍、快速翻转,这个方法xx各个元素,以后我们还会碰到方法update( ),这二者的作用有些相似,从字面上可以看出这个意思;
  11. (11)While 1 : —— 下面就开始事件循环,把可能的用户输入和其他输入的动作队列循环测试,给出应有的反应;
  12. (12){zh1}又出现了blit()、 flip()方法,在每次检测之后更新画面;
  13. (13)if —— 语句告诉游戏脚本执行定义的主循环程序即def main()。

第 二个有动画的例程ball.py:(可在下载/拷贝/测试)

import sys, pygame
pygame.init()
size = width, height = 320, 240
speed = [2, 2]
black = 0, 0, 0

screen = pygame.display.set_mode(size)

ball = pygame.image.load(”ball.bmp”)
ballrect = ball.get_rect()
while 1:
for event in pygame.event.get():

if event.type == pygame.QUIT: sys.exit()

ballrect = ballrect.move(speed)

if ballrect.left < 0 or ballrect.right > width:

speed[0] = -speed[0]
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = -speed[1]

screen.fill(black)

screen.blit(ball, ballrect)
pygame.display.flip()

在这个例 程中有了一个游戏对象就是一个运动的球,有了处理资源的语句就是ball = pygame.image.load(”ball.bmp”)。资源包括图像文件、声音文件、互联网接入等。Pygame能接受几乎所有图像音频视频文件 格式如bmp、jpeg、mp3等。

第三个例程是更完整的chimp.py:(可在下载/拷贝/测 试)

#/usr/bin/env python
"""
This simple example is used for the line-by-line tutorial
that comes with pygame. It is based on a 'popular' web banner.
Note there are comments here, but for the full explanation, 
follow along in the tutorial.
"""

#Import Modules
import os, pygame
from pygame.locals import *

if not pygame.font: print 'Warning, fonts disabled'
if not pygame.mixer: print 'Warning, sound disabled'

#functions to create our resources一下是处理资源的函数,如下载图像文件或者声音文件
def load_image(name, colorkey=None):
    fullname = os.path.join('data', name)
    try:
        image = pygame.image.load(fullname)
    except pygame.error, message:
        print 'Cannot load image:', fullname
        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()

def load_sound(name):
    class NoneSound:
        def play(self): pass
    if not pygame.mixer or not pygame.mixer.get_init():
        return NoneSound()
    fullname = os.path.join('data', name)
    try:
        sound = pygame.mixer.Sound(fullname)
    except pygame.error, message:
        print 'Cannot load sound:', fullname
        raise SystemExit, message
    return sound

#classes for our game objects以下是本游戏仅有的两个对象的类Fist和Chimp,这是游戏中涉及模拟和动画的部分
class Fist(pygame.sprite.Sprite):
    """moves a clenched fist on the screen, following the mouse"""
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) #call Sprite initializer
        self.image, self.rect = load_image('fist.bmp', -1)
        self.punching = 0

    def update(self):
        "move the fist based on the mouse position"
        pos = pygame.mouse.get_pos()
        self.rect.midtop = pos
        if self.punching:
            self.rect.move_ip(5, 10)

    def punch(self, target):
        "returns true if the fist collides with the target"
        if not self.punching:
            self.punching = 1
            hitbox = self.rect.inflate(-5, -5)
            return hitbox.colliderect(target.rect)

    def unpunch(self):
        "called to pull the fist back"
        self.punching = 0

class Chimp(pygame.sprite.Sprite):
    """moves a monkey critter across the screen. it can spin the
       monkey when it is punched."""
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) #call Sprite intializer
        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.di = 0

    def update(self):
        "walk or spin, depending on the monkeys state"
        if self.di:
            self._spin()
        else:
            self._walk()

    def _walk(self):
        "move the monkey across the screen, and turn at the ends"
        newpos = self.rect.move((self.move, 0))
        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):
        "spin the monkey image"
        center = self.rect.center
        self.di = self.di + 12
        if self.di >= 360:
            self.di = 0
            self.image = self.original
        else:
            rotate = pygame.transform.rotate
            self.image = rotate(self.original, self.di)
        self.rect = self.image.get_rect(center=center)

    def punched(self):
        "this will cause the monkey to start spinning"
        if not self.di:
            self.di = 1
            self.original = self.image

#主循环开始。当游戏脚本开始这个函数即被调用,并初始化模块和游戏对象,执行事件循环直到返回
def main():
    """this function is called when the program starts.
       it initializes everything it needs, then runs in
       a loop until the function returns."""
#Initialize Everything初始化
    pygame.init()
    screen = pygame.display.set_mode((468, 60))
    pygame.display.set_caption('Monkey Fever')
    pygame.mouse.set_visible(0)

#Create The Backgound创建背景
    background = pygame.Surface(screen.get_size())
    background = background.convert()
    background.fill((250, 250, 250))

#Put Text On The Background, Centered把文本贴在或者拷贝在背景上。{dy}次出现blit( )函数
    if pygame.font:
        font = pygame.font.Font(None, 36)
        text = font.render("Pummel The Chimp, And Win $$$", 1, (10, 10, 10))
        textpos = text.get_rect(centerx=background.get_width()/2)
        background.blit(text, textpos)

#Display The Background显示背景并更新。第二次出现blit( )函数
    screen.blit(background, (0, 0))
    pygame.display.flip()

#Prepare Game Objects准备好游戏对象包括时钟控制、模拟的对象、资源对象等
    clock = pygame.time.Clock()
    whiff_sound = load_sound('whiff.wav')
    punch_sound = load_sound('punch.wav')
    chimp = Chimp()
    fist = Fist()
    allsprites = pygame.sprite.RenderPlain((fist, chimp))

#Main Loop 事件循环,鼠标、键盘等的事件队列
    while 1:
        clock.tick(60)

    #Handle Input Events 处理用户输入事件
        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() #punch
                    chimp.punched()
                else:
                    whiff_sound.play() #miss
            elif event.type is MOUSEBUTTONUP:
                fist.unpunch()

        allsprites.update()

    #Draw Everything 第三次出现blit( )函数
        screen.blit(background, (0, 0))
        allsprites.draw(screen)
        pygame.display.flip()

#Game Over

#this calls the 'main' function when this script is executed 当本游戏脚本执行时调用main( )函数
if __name__ == '__main__': main()

首 先在代码开始的地方有三重的双括号”"” “”",括号内的叫docstring就是关于代码的文档说明,规范地说,每个程序代码都应该包含这部分内容,开发者自己或开发团队可以从这里获得关于代 码的功能、许可证等方面的信息。这是Python所特有的所谓“自省”功能,英语叫“Introspection”。这里有必要加以简单的介绍。在命令行 里使用dir(module/function),在实验中用 Python的模块、函数、方法os、sys、 pygame等等甚至是一个数字如2来代替括号里的斜体字,可以查看对象的性质。因为在Python里,一切都是对象,所以这些都可以使用dir()函数 查看对象的性质,这包括对象的结构、包含的函数和方法、类的继承关系、子类、可以接受的变量、返回的结果等详细信息。另外有同等功能的是在命令行的符 号>>>里使用help( )函数,用法与dir( )相同,但是得到的信息有所不同。这些都内嵌在Python的解释器里所以叫做内省的。非常形象。

***********************************************
课 堂实验二
>>> import pygame
>>> print dir(pygame)
>>> print dir(pygame.Rect)
>>> print help(pygame.Rect)

例 如:使用print dir(pygame.Rect)得到以下信息:
['__class__', '__cmp__', '__coerce__', '__copy__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__', '__len__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__safe_for_unpickling__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'bottom', 'bottomleft', 'bottomright', 'center', 'centerx', 'centery', 'clamp', 'clamp_ip', 'clip', 'collidedict', 'collidedictall', 'collidelist', 'collidelistall', 'collidepoint', 'colliderect', 'contains', 'fit', 'h', 'height', 'inflate', 'inflate_ip', 'left', 'midbottom', 'midleft', 'midright', 'midtop', 'move', 'move_ip', 'normalize', 'right', 'size', 'top', 'topleft', 'topright', 'union', 'union_ip', 'unionall', 'unionall_ip', 'w', 'width', 'x', 'y']

信息给出了Pygame的模块Rect包含的函数、需要 的变量和子类。这样你就知道怎样使用这个模块,例如由Rect创建的矩形面积有bottonleft、bottonright,就是左按钮、右按钮,那么 跟按钮绑定的动作就是可引用的。面向对象包含的封装就是把对象的性质和动作封装在一个类里面。

如果使用 help(pygame.Rect)得到信息如下:
Help on class Rect in module pygame:

class Rect(__builtin__.object)
| The rectangle object is a useful object
| representing a rectangle area. Rectangles are
| created from the pygame.Rect() function. This routine
| is also in the locals module, so importing the locals
| into your namespace allows you to just use Rect().
|
| Rect contains helpful methods, as well as a list of
| modifiable members:
| top, bottom, left, right, topleft, topright,
| bottomleft, bottomright, size, width, height,
| center, centerx, centery, midleft, midright, midtop,
| midbottom.
| When changing these members, the rectangle
| will be moved to the given assignment. (except when
| changing the size, width, or height member, which will
| resize the rectangle from the topleft corner)
|
| The rectstyle arguments used frequently with the
| Rect object (and elsewhere in pygame) is one of
| the following things.
… …
这 些信息告诉我们库类Rect能为我们作些什么工作,它创建一个矩形的面积把Sprite创建的对象就是图像放在里面等等。
********************************************

我 们在注释里强调了三次出现blit( )函数,所以这个函数对于理解游戏代码是个关键!{dy}个blit()的语法是background.blit(text,textpos),即把文本 text拷贝在text的位置textpos上,并把textpos拷贝在background上;第二个blit()的语法是 screen.blit(background,(0,0)),是把有了文本的background拷贝在screen上;第三个 screen.blit(background,(0,0))把上面刚创建、并拷贝在background上的游戏模拟对象fist和chimp再拷贝到 screen上;还有要注意的是,每个blit()后面都跟随一个flip(),上面在简单例子里我们已经介绍了英语flip的意义,这是要更新画面,动 画就是每一个循环给游戏对象一个新的位置,然后用flip()使得动画不断翻转,得到运动的感觉。而语句clock.tick(60)是由创建游戏对象的 部分里的clock = pagame.time.Clock()语句对象化得到的,这个对象告诉游戏脚本按照每秒60桢的速度更新屏幕。

PyGame的库类介绍

Pygame的类库:

|| || || || || || || || || || || || || || || || || || || || ||

这 些库类的功能可以望文生义,如Crom是处理光盘的类,Cursors是处理光标的类,Key是处理键盘的类,Joystick是处理游戏操纵杆的类, Mouse是处理鼠标的,而Music显然是处理音乐的。等大家有了一些基础之后就应该仔细地研究这些类库,熟练地掌握他们做起游戏来得心应手,左右逢 源。下面我们将就最常用的加以说明,在上面的样例涉及到的就是最重要的类库。

下面我们将以sprite、Display、Event、 Image等为例说明类库的使用。

郑重声明:资讯 【Python游戏:PyGame « 燕之庐网站建设】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——