Pygame是脚本语言Python的一个扩展包就是SDL的封装包,是用Python 和C语言开发;开发人是Pete Shinners。专门用于开发各类游戏。SDL意思是Simple Directmedia Library即“简单媒体类库”,这是一个跨平台的控制多媒体的C语言类库,类似于 DirectX。这里说的媒体包括CDROM即光驱、键盘鼠标、音频视频、操纵杆等输入输出设备,Pygame写了关于这些对象的类库可在官方网站上找到。因为是“面向对象”就是所谓Object-Oriented编程语言,所以我们可以继承这些类的性质来编写我们自己的游戏。
Pygame的官方网站: Pygame.org
可惜中文的Pygame文档还没有。因为Pygame是面向对象脚本编程语言Python的一个扩展,所以在使用Pygame之前要求基本的Python的知识和技术。
不管在什么平台上开发,所有游戏的代码通常会有的结构包含六个部分:
(一)加载Pygame的或者其他工具软件的模块,在Python是使用import语法完成;
(二)资源处理类包括处理图象、声音、连接或断开网络等;
(三)游戏本身的对象类;
(四)其他函数。包括不能归类的必要函数,它们可以归入游戏的逻辑代码块里但是这样处理会增加理解代 码的难度,所以把这类函数单独处理;
(五)初始化。包括Pygame本身对象的初始化;游戏对象的初始化;背景、鼠标的初始化等;
(六)主循环就是def main()。处理用户输入、更新游戏对象和显示区等。
实际上,游戏的结构是个风格问题,不同的人、从不同的侧重点出发会使用不同的方法组织自己的游戏代码。中国人学太极拳的时候有这样的一个讲究,刚刚开始学的时候要有严格的“架式”就是动作规范,但是等到悟到用意不用力、用意念引导动作的阶段就可以随心所欲,不必太拘泥于一招一式细节了。
例如有从完全另外的角度的方法,把代码按照一下四个方面组织:(请查看这里的资源作为参考)
模块和对象的初始化;
处理用户输入和事件循环;
动画和模拟;
提交;
不管使用什么方式组织代码,上面例子中最主要的结构有两个:一个是主程序即mail() loop;一个是游戏对象的类。主程序是游戏脚本开始时执行的,包括处理Pygame模块本身的初始化和游戏对象的初始化,还包括所谓事件循环就是处理游戏玩家的输入如鼠标、键盘动作和其他事件的队列;而游戏类对象封装了游戏角色的数据和逻辑。对于初学者来说,先理解这两个结构可收提纲协领的效果。有些简单的游戏只有一个游戏对象(没办法,我们总是要从最简单的例子开始),可能没有完全按照上面的格式写,但总是包含了这样的模式在里面。
这里有一个Pygame的代码库,各种游戏代码可供研究:Pygame代码库第一个简单的例程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。
用这个简单的程序我们完成了一个框架,多数应用程序特别是一个游戏就是写在这上面的,如下图:
不算空格,加注释行,就是以#号开始的,以上总共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)这样你就完成了屏幕初始化的工作。
学习一种语言最好的办法就是实验,通过观察软件的行为,输入输出的变化来理解代码的功能。跟随我的路线图保证你能在最短时间内顺利掌握语言和技术精髓,不必从基本教程开始。牛顿说过:“在科学发展上实例比理论更重要!”,我相信在学习技术上也是这样。我们先仔细地研究这个程序样例,深入剖析,彻底理解,举一反三,触类旁通。
(1)pygame.init( ) ——实现模块初始化,就是把你要输入的模块进行初始化,准备工作;
(2)screen. = pygame.display.set_mode((150,50)) ——初始化游戏屏幕,宽150高50个像素。
(3)pygame.display.set_caption( 'Basic Pygame Program') ——在屏幕的页眉上写字;
(4)background = pygame.Surface(screen.get_size() ) ——开始填满背景,.get_size()表示跟屏幕一样大。引用Surface创建的实例相当于在前面创建的screen上敷上一张画布,所以后面的 blit( )方法实际上是在这张画布上画,而不是直接在screen上画;
(5)background.fill((255,255,255)) —— 把RGB格式的颜色写入背景;
(6)font = pygame.font.Font( );text = font.render("Hello There",1,(10,10,10))以及上面的screen是模块的对象,区别于游戏本身的对象。font创建字体对象,text创建文本对象就是框架中间的Hello There,(10,10,10)是文本字体的颜色,而中间的数字1是对字体性质的限定,这里我们先忽略;
(7)textpos = text.get_rect( ) —— 是为font.render( )提交变量的text准备一个矩形框,让提交的文本放在这里;
(8)background.blit ( text,textpos ) —— 可能blit ( )是最值得注意的方法,这不是一个常用词,本copy和past是同义词,就是拷贝和粘貼的意思,把什么什么拷贝/粘貼在什么什么上面,这里就是把 text粘貼在textpos上的意思;
(9)screen.blit(background,(0,0)) —— 接着又一次出现blit( )方法,这次是把上一步粘貼好文本的background再拷贝在screen上,(0,0)表示从坐标原点开始就是从左上角开始;
(10)pygame.display.flip( ) —— flip英文意思是轻拍、快速翻转,这个方法激活各个元素,以后我们还会碰到方法update( ),这二者的作用有些相似,从字面上可以看出这个意思;
(11)While 1 : —— 下面就开始事件循环,把可能的用户输入和其他输入的动作队列循环测试,给出应有的反应;
(12)最后又出现了blit()、flip()方法,在每次检测之后更新画面;
(13)if —— 语句告诉游戏脚本执行定义的主循环程序即def main()。
第二个有动画的例程ball.pyimport 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等。
首先在代码开始的地方有三重的双括号""" """,括号内的叫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( )函数,所以这个函数对于理解游戏代码是个关键!第一个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桢的速度更新屏幕。
本文源自: