1、Python+Pygame 游戏学习(初级教程)大学生交流网,学习,交流,游戏学习教程第一章:安装及矩形、圆型画图pygame 是一个设计用来开发游戏的 python 模块,其实说白了和 time、os 、sys 都是一样的东东。今天开始正式学习 pygame,下载地址:www.pygame.org,具体安装方法就不讲了,很简单。下载后安装完成即可,在 pygame 的学习中,本文使用了 spe 编辑器,感觉还不错。1、pygamee 窗口 pygamepygame 绘制图形前,首先需要建立一个窗口,说来很简单,请看下面的代码,怎么样,是不是很简单。import pygame #这句不用注释了
2、吧,呵呵pygame.init() #模块初始化,任何 pygame 程序均需要执行此句screencaption=pygame.display.set_caption(hello world)#定义窗口的标题为hello worldscreen=pygame.display.set_mode(640,480) #定义窗口大小为 640*480screen.fill(255,255,255)#用白色填充窗口2、窗口退出pygame 有一个事件循环,不断检查用户在做什么。事件循环中,如何让循环中断下来(pygame 形成的窗口中右边的插号在未定义前是不起作用的) ,常用的代码如下:while T
3、rue:for event in pygame.event.get():if event.type=pygame.QUIT:sys.exit()3、pygamee 中的颜色在 screen.fill(255,255,255)这一语句中,已经看 出,pygame 使用的是 RGB 系统。纯绿色用0,255,0,纯蓝色用0,0 ,255,纯红色用255,0,0。如果不使用 RGB 记 法,pygame还提供了一个命名颜色列表,也可以直接使用这些命名颜色。定义好的颜色句有 600 多个,可以在 colordict.py 文件中查看具体名 称。使用命名列 表时,首先要在程序最前面导 入THECOLOR
4、S。from pygame.color import THECOLORS然后使用某个命名颜色:pygame.draw.circle(screen,THECOLOR S“red“,100,100,30,0)4、圆形pygame.draw.circle()用来画圆形,具体包括五个参数: (1)画圆的表面,在本例中用 screen创建了一个窗口,所以是画在 screen 表面上。(2) 用什么颜色来画,如用红色255,0,0 。(3)在什么位置画,top,left。(4)直径。(5)线宽,其中 0 表示完成填充。pygame.draw.circle(screen,255,0,0,100,100,30
5、,0)5、矩形pygame.draw.rect()用来创建一个矩形。Rect(left,top,width,height)用来定义位置和宽高,具体代码如下:pygame.draw.rect(screen,255,0,0,250,150,300,200,0)也可以用下面的定义方法rect_list=250,150,300,200pygame.draw.rect(screen,255,0,0,rect_list,0)或者my_rect=pygame.Rect(250,150,300,200)pygame.draw.rect(screen,255,0,0,my_rect,0)6、实例利用 rando
6、m 模块随机生成大小和位置在表面上绘画,具体代码如下:#小五义 http:/ pygame,sysimport timeimport randompygame.init()screencaption=pygame.display.set_caption(hello world)screen=pygame.display.set_mode(640,480)screen.fill(255,255,255)for i in range(10):zhijing=random.randint(0,100)width=random.randint(0,255)height=random.randint(0
7、,100)top=random.randint(0,400)left=random.randint(0,500)pygame.draw.circle(screen,0,0,0,top,left,zhijing,1)pygame.draw.rect(screen,255,0,0,left,top,width,height,3)pygame.display.flip()while True:for event in pygame.event.get():if event.type=pygame.QUIT:sys.exit()第二章:从画点到动画1、单个像素(画点)利用 pygame 画点主要有三种
8、方法:方法一:画长宽为 1 个像素的正方形 1#小五义 http:/ pygame,syspygame.init()screen=pygame.display.set_caption(hello world!)screen=pygame.display.set_mode(640,480)screen.fill(255,255,255)pygame.draw.rect(screen,0,0,0,150,50,1,1,1) #画 1*1 的矩形,线宽为 1,这里不能是 0,因为1*1 无空白区域。pygame.display.flip()while True:for event in pygame
9、.event.get():if event.type=pygame.QUIT:sys.exit()方法二:画个直径为 1 的圆#小五义 http:/ pygame,syspygame.init()screen=pygame.display.set_caption(hello world!)screen=pygame.display.set_mode(640,480)screen.fill(255,255,255)pygame.draw.circle(screen,0,0,0,150,200,1,1)pygame.display.flip()while True:for event in pyg
10、ame.event.get():if event.type=pygame.QUIT:sys.exit()方法三:这种方法并不是画上去的,而是改变了 surfacce 上某个点的颜色,这样看上去像是surfacce画了一个点 screeenset_at() 。另外,如果要得到某个像素的颜色,可以使用 screeenget_at() 。#小五义 http:/ pygame,syspygame.init()screen=pygame.display.set_caption(hello world!)screen=pygame.display.set_mode(640,480)screen.fill(
11、255,255,255)screen.set_at(150,150,255,0,0)#将 150,150 改为红色。pygame.display.flip()while True:for event in pygame.event.get():if event.type=pygame.QUIT:sys.exit()2、连接多个点形成线pygame.draw.lines()方法可以将多个点连接成为线。该方法有 5 个参数:surface 表面、颜色 、 闭 合 线 或 者 非 闭 合 线 ( 如 果 闭 合 为 True, 否 则 为 False ) , 点 的 列 表 , 线 宽 。pygam
12、e.draw.lines(surface, color,False/True,plotpoints,1)。下面的例子画出了一条马路,具体如下:#小五义 http:/ pygame,sysdef lineleft(): #画马路左边界plotpoints=for x in range(0,640):y=-5*x+1000plotpoints.append(x,y)pygame.draw.lines(screen,0,0,0,False,plotpoints,5)pygame.display.flip()def lineright():#画马路右边界plotpoints=for x in rang
13、e(0,640):y=5*x-2000plotpoints.append(x,y)pygame.draw.lines(screen,0,0,0,False,plotpoints,5)pygame.display.flip()def linemiddle():#画马路中间虚线plotpoints=x=300for y in range(0,480,20):plotpoints.append(x,y)if len(plotpoints)=2:pygame.draw.lines(screen,0,0,0,False,plotpoints,5)plotpoints=pygame.display.fli
14、p()pygame.init()screen=pygame.display.set_caption(hello world!)screen=pygame.display.set_mode(640,480)screen.fill(255,255,255)lineleft()lineright()linemiddle()while True:for event in pygame.event.get():if event.type=pygame.QUIT:sys.exit()3、引用图像在 pygame 中引用图像最简单的以夷伐夷是 image 函数。下面在马路的实例中,加入一辆汽车。首先 pyg
15、ame.image.load() 函数从硬盘 加载一个图像,并创建一个名为 my_car 的对象。这里,my_car 是一个 surface,不过是存在内存中,并未显示出来,然后用 blit(块移)方 法将 my_car 复制到 screen 表面上,从而显示出来。具体代码如下:#小五义 http:/ pygame,sysdef lineleft():plotpoints=for x in range(0,640):y=-5*x+1000plotpoints.append(x,y)pygame.draw.lines(screen,0,0,0,False,plotpoints,5)pygame.
16、display.flip()def lineright():plotpoints=for x in range(0,640):y=5*x-2000plotpoints.append(x,y)pygame.draw.lines(screen,0,0,0,False,plotpoints,5)pygame.display.flip()def linemiddle():plotpoints=x=300for y in range(0,480,20):plotpoints.append(x,y)if len(plotpoints)=2:pygame.draw.lines(screen,0,0,0,Fa
17、lse,plotpoints,5)plotpoints=pygame.display.flip()def loadcar(): #载入 car 图像my_car=pygame.image.load(ok1.jpg) #当前文件夹下的 ok1.jpg 文件screen.blit(my_car,320,320)pygame.display.flip()pygame.init()screen=pygame.display.set_caption(hello world!)screen=pygame.display.set_mode(640,480)screen.fill(255,255,255)li
18、neleft()lineright()linemiddle()loadcar()while True:for event in pygame.event.get():if event.type=pygame.QUIT:sys.exit()素材:ok1.jpg4、动画计算机动画实际上就是把图像从一个地方移动到另一个地方,同时几个连接动作交待显示就会产生逼真的效果。因此,在做动画中,最基本要考虑的因素主要是三 个,一是时间,什么时间移动,多长时间变下一个动作,二是位置,从什么位置到什么位置,三是动作,前后两个动作的连续性。在这个例子中,因为车是俯视的, 所以车轮转动实际是看不到的,所以 不用 考虑
19、 连续 动作 的变 化, 而是 只考 虑车 的位 置和 多长 时 间移 动即 可。 第一 步pygame.time.delay()来实现 时间延迟;第二步利用 pygame.draw.rect()把原来位置的图像覆盖掉;第三步 screen.blit()在新位置引入图像。下面的例子实现 了汽车从驶入到驶出的过程。#小五义 http:/ pygame,sysdef lineleft():plotpoints=for x in range(0,640):y=-5*x+1000 plotpoints.append(x,y)pygame.draw.lines(screen,0,0,0,False,pl
20、otpoints,5)pygame.display.flip()def lineright():plotpoints=for x in range(0,640):y=5*x-2000 plotpoints.append(x,y)pygame.draw.lines(screen,0,0,0,False,plotpoints,5)pygame.display.flip()def linemiddle():plotpoints=x=300for y in range(0,480,20):plotpoints.append(x,y)if len(plotpoints)=2:pygame.draw.li
21、nes(screen,0,0,0,False,plotpoints,5)plotpoints=pygame.display.flip()def loadcar(yloc):my_car=pygame.image.load(ok1.jpg)locationxy=310,ylocscreen.blit(my_car,locationxy)pygame.display.flip()if _name_=_main_:pygame.init()screen=pygame.display.set_caption(hello world!)screen=pygame.display.set_mode(640
22、,480)screen.fill(255,255,255)lineleft()lineright()linemiddle()while True:for event in pygame.event.get():if event.type=pygame.QUIT:sys.exit()for looper in range(480,-140,-50):pygame.time.delay(200)pygame.draw.rect(screen,255,255,255,310,(looper+132),83,132,0)loadcar(looper)第三章:时间、事件、文字1、运动速率上节中,实现了一
23、辆汽车在马路上由下到上行驶,并使用了 pygame.time.delay(200) 来进行时间延迟。看了很多参考材料,基本每个材料都 会谈到不同配置机器下运动速率的问题,有的是通过设定频率解决,有的是通过设定速度解决,自己本身水平有限,看了几篇,觉得还是Beginning Game Development with Python and Pygame这里面提到一个方法比较好。代码如下,代码里更改的地方主要是 main 里的代码,其中利用 clock=pygame.time.Clock()来定义时钟,speed=250.0 定义了速度,每秒 250 像 素, time_passed=clock.
24、tick()为上次运行时 间 单 位 是 毫 秒 , time_passed_seconds=time_passed/1000.0 将 单 位 改 为 秒 ,distance_moved=time_passed_seconds*speed 时间乘以速度得到移动距离,这样就能保证更加流畅。#小五义 http:/ pygame,sysdef lineleft():plotpoints=for x in range(0,640):y=-5*x+1000 plotpoints.append(x,y)pygame.draw.lines(screen,0,0,0,False,plotpoints,5)py
25、game.display.flip()def lineright():plotpoints=for x in range(0,640):y=5*x-2000 plotpoints.append(x,y)pygame.draw.lines(screen,0,0,0,False,plotpoints,5)pygame.display.flip()def linemiddle():plotpoints=x=300for y in range(0,480,20):plotpoints.append(x,y)if len(plotpoints)=2:pygame.draw.lines(screen,0,
26、0,0,False,plotpoints,5)plotpoints=pygame.display.flip()def loadcar(yloc):my_car=pygame.image.load(ok1.jpg)locationxy=310,ylocscreen.blit(my_car,locationxy)pygame.display.flip()if _name_=_main_:pygame.init()screen=pygame.display.set_caption(hello world!)screen=pygame.display.set_mode(640,480)screen.f
27、ill(255,255,255)lineleft()lineright()linemiddle()clock=pygame.time.Clock()looper=480 speed=250.0while True:for event in pygame.event.get():if event.type=pygame.QUIT:sys.exit()pygame.draw.rect(screen,255,255,255,310,(looper+132),83,132,0)time_passed=clock.tick()time_passed_seconds=time_passed/1000.0d
28、istance_moved=time_passed_seconds*speedlooper-= distance_moved2if looper480:looper=-480pygame.draw.rect(screen,255,255,255,310,(looper-132),83,132,0)loadcar(looper)3、字体及字符显示使用字体模块用来做游戏的文字显示,大部分游戏都会有诸如比分、时间、生命值等的文字信息。pygame 主要是使用 pygame.font 模块来完成,常用到的一些方法是:pygame.font.SysFont(None, 16),第一个参数是说明字体的,可
29、以是 “arial“等,这里 None 表示默认字体。第二个参数表示字的大小。如果无法知道当前系统中装了哪些字体,可 以使用 pygame.font.get_fonts()来获得所有可用字体。pygame.font.Font(“AAA.ttf“, 16),用来使用 TTF 字体文件。render(“hello world!“, True, (0,0,0), (255, 255, 255),render 方法用来创建文字。第一个参数是写的文字;第二个参数是否开启抗锯齿,就是说 True 的话字体会比较平滑,不过相应的速度有一点 点影响;第三个参数是字体的颜色;第四个是背景色,无表示透明。下面将上
30、面的例子添加当前汽车坐标:#小五义 http:/ pygame,sysdef lineleft():plotpoints=for x in range(0,640):y=-5*x+1000 plotpoints.append(x,y)pygame.draw.lines(screen,0,0,0,False,plotpoints,5)pygame.display.flip()def lineright():plotpoints=for x in range(0,640):y=5*x-2000 plotpoints.append(x,y)pygame.draw.lines(screen,0,0,0
31、,False,plotpoints,5)pygame.display.flip()def linemiddle():plotpoints=x=300for y in range(0,480,20):plotpoints.append(x,y)if len(plotpoints)=2:pygame.draw.lines(screen,0,0,0,False,plotpoints,5)plotpoints=pygame.display.flip()def loadcar(yloc):my_car=pygame.image.load(ok1.jpg)locationxy=310,ylocscreen
32、.blit(my_car,locationxy)pygame.display.flip()def loadtext(xloc,yloc):textstr=location:+str(xloc)+,+str(yloc)text_screen=my_font.render(textstr, True, (255, 0, 0)screen.blit(text_screen, (50,50)if _name_=_main_:pygame.init()screen=pygame.display.set_caption(hello world!)screen=pygame.display.set_mode
33、(640,480)my_font=pygame.font.SysFont(None,22)screen.fill(255,255,255)loadtext(310,0)lineleft()lineright()linemiddle()looper=480while True:for event in pygame.event.get():if event.type=pygame.QUIT:sys.exit()elif event.type = pygame.KEYDOWN:if event.key=pygame.K_UP:looper=looper-50if looper480:looper=
34、-132screen.fill(255,255,255)loadtext(310,looper)lineleft()lineright()linemiddle()loadcar(looper)loadtext(310,looper)这个例子里直接让背景重绘一下,就不会再像 1、2 里面那样用空白的 rect 去覆盖前面的模块了。第四章:声音pygame.mixer 是一个用来处理声音的模块,其含义为“混音器”。游戏中对声音的处理一般包括制造声音和播放声音两部分,这里仅学习了播放声音部分。1、pygamee.mixerr 启动与初始化 pygamee.mixerrpygame.mixer.ini
35、t():mixer 的初始化。程序中,使用时,一般放在最前面的几句代码中:import pygamepygame.init()pygame.mixer.init()2、播放声音片段 wav 文件 wav播放声音片段 wav 文件时,pygame.mixer 使用 Sound 对象,格式为:soundwav=pygame.mixer.Sound(“filename.wav“) #filename.wav 文件名soundwav.play()在游戏中,往往用下面的代码来完成:#小五义 http:/ pygame,syspygame.init()pygame.mixer.init()screen=p
36、ygame.display.set_mode(640,480)pygame.time.delay(1000)#等待 1 秒让 mixer 完成初始化soundwav=pygame.mixer.Sound(“filename.wav“)soundwav.play()while 1:for event in pygame.event.get():if event.type=pygame.QUIT:sys.exit()3、播放 mp3、wma、ogg 音乐文件 mp3 wma ogg这里只是学习了一个 mp3 文件,如果非 windows 系统,那可以试试 ogg 文件。播放音乐文件主要使用 pyg
37、ame.mixer 中的 music 模块,主要方法为:pygame.mixer.music.load(“filename.mp3“)pygame.mixer.music.play(n,start,stop)#第一个参数为播放次数,如果是-1 表示循环播放,省略表示只播放 1 次。第二个参数和第三个参数分别表示播放的起始和结束位置。完整的代码为:#小五义 http:/ pygame,syspygame.init()pygame.mixer.init()screen=pygame.display.set_mode(640,480)pygame.time.delay(1000)pygame.mix
38、er.music.load(“filename.mp3“)pygame.mixer.music.play()while 1:for event in pygame.event.get():if event.type=pygame.QUIT:sys.exit()程序在运行时,一旦开始播放音乐,就会继续做下一件事情,也就是说,如果我们要播放两首歌,那么pygame.mixer.music.load(“filename1.mp3“)pygame.mixer.music.play()pygame.mixer.music.load(“filename2.mp3“)pygame.mixer.music.p
39、lay()这段代码运行后,就会出现两首歌同时在播放的情况。实际中,我们常常需要播放完一首,再播放另一首,这样就需要利用 pygame.mixer.music.get_busy() 函数来判断,如果函数返回值为 True 那么说明目前处于忙的状态,否则返回 False。例如:#小五义 http:/ pygame,syspygame.init()pygame.mixer.init()screen=pygame.display.set_mode(640,480)pygame.time.delay(1000)pygame.mixer.music.load(“filename.mp3“)pygame.m
40、ixer.music.play()soundwav=pygame.mixer.Sound(“filename.wav“)while 1:for event in pygame.event.get():if event.type=pygame.QUIT:sys.exit()if not pygame.mixer.music.get_busy():soundwav.play()pygame.time.delay(5000)#等待 5 秒让 filename.wav 播放结束sys.exit()4、控制音量pygame.mixer.music.set_volume()用来控制音量,取值范围为 0-1
41、.0 的浮点数。0 为最小值,1 为最大值。5、制作 mp3 播放器中遇到的问题 mp3python+wxpython+pygame 完全可以很容易方便的做出一个 mp3 播放器,但是在制作中遇到两个问题:一是中文歌曲名的显示,通过搜索已经解决,加上# encoding=GBK二是 pygame 在播放 mp3 文件时,发现并不是所有的 mp3 文件都有播放,常常会出现播放声音不正确的情况,有时只是杂响。经过与 python 学习交流群 (2)中的 easy 交流, easy 提出位速 128kbps 的 mp3 文件可以播放,但从网上下了几个 128kbps 的 mp3 测试后,发现播放不正
42、常 的情况依然存在。不知道哪位大牛能解决这一问题,希望能把解决方法告知一下,谢谢。因此,如果您打算写一个 mp3 的播放工具,python 能做 mp3 播放的模块很多,这里,我觉得可以考虑使用 mp3play 模块,比较方便简单。目前版本为 mp3play 0.1.15,具体下载地址为 http:/pypi.python.org/pypi/mp3play/。这里简单介绍一下其主要方法:play(n,starms,endms):播放,第一个参数表示次数,第二、三个参数表示播放的起止位置,单位是毫秒。stop(): 停止。pause(), unpause(): 暂停和开始。isplaying()
43、:ispaused():seconds():判断是否正在播放,如果返回为 TRUE,表示正在播放歌曲。判断是否为暂停,如果返回为 TRUE,表示暂停。返回 mp3 文件共多少秒,注意这里的单位是秒。milliseconds(): 返回 mp3 文件共多少毫秒,注意这里的单位是毫秒。mp3play 首页上给出的例子为:#小五义 http:/ mp3playfilename= rC:music.mp3#播放 c 盘下的 music.mp3 文件clip = mp3play.load(filename)clip.play()import timetime.sleep(min(30, clip.sec
44、onds()#如果 mp3 文件的长度小于 30 少时,全部播放完,否则仅播放 30 秒。clip.stop()第五章:精灵据说在任天堂 FC 时代,精灵的作用相当巨大,可是那时候只知道怎么玩超级玛丽、魂斗罗,却对精灵一点也不知。 pygame.sprite.Sprite 就是 Pygame 里面用来实现精灵的一个类,使用时,并不需要对它实例化,只需要继承他,然后按需写出自己的类 就好了,因此非常简单实用。一、什么是精灵精灵可以认为成是一个个小图片,一种可以在屏幕上移动的图形对象,并且可以与其他图形对象交互。精灵图像可以是使用 pygame 绘制函数绘制的图像,也可以是原来就有的图像文件。二、
45、sprritee 中主要且常用的变量(更多详细的见 http:/www.pygame.org/docs/ref/sprite.html#pygame.sprite.Sprite)self.image 这个负责显示什么。如 self.image=pygame.Surface(x,y)说明该精灵是一个 x,y 大小的距 形,self.image=pygame.image.load(filename)说明该精灵调用显示 filename 这个图片文件。self.image.fill(color),负责对 self.image 着色,如 self.image=pygame.Surface(x,y)se
46、lf.image.fill(255,0,0)对 x,y 距形填充红色。self.rect 负责在哪里显示。一般来说,先用 self.rect=self.image.get_rect()获得 image 距形大小,然后给 self.rect 设定 显示的位置,一般用 self.rect.topleft(topright 、bottomleft、bottomright)来设定某一个角的显示位置。 另外,self.rect.top、self.rect.bottom 、self.rect.right 、self.rect.left分别表示上下左 右。self.update 负责使精灵行为生效。Spri
47、te.add 添加精灵到 group 中去。Sprite.remove 从 group 中删除Sprite.kill 从 groups 中全部删除精灵Sprite.alive 判断精灵是否属于 groups三、建立一个简单的精灵所有精灵在建立时都是从 pygame.sprite.Sprite 中继承的。(1)做一个精灵,绘制一个宽 30、高 30 的距形,具体代码如下:class Temp(pygame.sprite.Sprite):def _init_(self,color,initial_position):pygame.sprite.Sprite._init_(self)self.image= pygame.Surface(30,30)self.image.fill(color)self.rect=self.image.get_rect()self.rect.topleft=initial_position这里逐 句进