这又是Pygame教程系列的一个——OVA篇,类似于py2exe篇一样,额外写的,也许不是pygame游戏开发必须的东西,但是知道了绝对大有裨益。因此友情大放送~

看pygame模块介绍的时候,细心的人会发现有一个pygame.sprite模块,而在讲动画的时候,虽然引入了精灵这个概念,却没有使用这个模块。在官方文档上也说了,这个模块是轻量级的,在游戏开发中也未必要使用。讲解动画的时候为了避免太多新东西,直接把一个surface画来画去,难道没有人觉得不和谐么:)我们这次试着使用Sprite把动画变的更简单一些(不过这里没有使用GameObjects,两者结合更健康~)。

“sprite”,中文翻译“精灵”,在游戏动画一般是指一个独立运动的画面元素,在pygame中,就可以是一个带有图像(Surface)和大小位置(Rect)的对象。 精灵特别适合用在OO语言中,比如Python。

pygame.sprite.Sprite是pygame精灵的基类,一般来说,你总是需要写一个自己的精灵类继承一下它然后加入自己的代码。举个例子:

Python

import cStringIO, base64

import pygame

from pygame.locals import *

class Ball(pygame.sprite.Sprite):

def __init__(self, color, initial_position):

pygame.sprite.Sprite.__init__(self)

ball_file = cStringIO.StringIO(base64.decodestring(

"""iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ

bWFnZVJlYWR5ccllPAAABBJJREFUeNqsVj2PG1UUvfPp8XictXfHa+9mlyJCNEQRWiToqACJAgGC

LqJNlQZR0IFEj8RPSJkGGooUpEWJkGhR0tAAElI2tsfjjxnPjIdz7oyDF2wSUK72yN43793z7rkf

Y8N2HFmbbVliGIYiyzIpy1Isy3oHeMswzLOyXJ2tVit9VhTFAxz5Cfge+A7IZIcZmySObQudwIE0

veanraB1w/O8l5x6D9eXy6UkSaJYLBa6BvsNuAV8uY3sCQlvX4LANM0Xw/Dgdhj2Xm02m+K6LqPR

PXmeS5qmMp/PZTabyXQ6lclkosS1/QJcB+5vkthrAkoAuc4uHx//0B8MvCAIxG/5jEg0kpIkmcwX

icTxBIhlHWEURXoedgW4B3wIfHuBJM9yMQ3j5PTk5N7g6MjtdrrS3e9Ku90GUUvc2hkdMYJx5Ivn

NRC19UReRlRLR/sGeB34UUkMJBcJlcHg6K4SdDvS7/el1+tJp7MnQdCWRqMhDGWZLmWCCFog9rBm

GBYc50rOKON4uqkSC+IQSC3moeX7N09PX/i4AwLkAoQDxeFhHziU8CCUzt6e+EFLc2QaJi4mFQHy

kQLZMpME+WJF1sabdYA7Nq4jQbv9OZPs+75cgkSMYH9/X6PhJ9dpTLjruFLkBRyjACBd1BoLzzY8

T3O0IRntJvCZDXsTTnq262CzrzmgRHu4+QEIQhAxNzRWU1mTxfjOwvBIAOlIYNnWtja5bqM33mN/

sBEdx9bNPOQ1PWlqZJdAFKoMrEI6R+9gj6t7cUl1zjKnjFvsfaybr1Uqlv94ypXSKCud+aefpezs

7O3LL9s4c5U65gCrhGDDpUkqyWIuU1STweNlJRe7nAlmA+ZaVbnmiD4KFNEWC+3VqjB5YImDdMA+

YKONx2OVgxefojRL8CzmCxkOhxLhWYy+mGIvz6RKmv096X91PErP4Byazapbs3vZB45bVQqTzBzQ

kjQBQSTnjx7JcDTCRSLkKNY9SbKACsttHKZdrIqHILnGCNhoDU0qG83U5mNUVTOKShRPYo3m8fAc

nT/S/3mWFy2KrXKNOFbuI+Rr1FvLsB731Ho2m2pU7I1Sx8pSHTLaESIZjob6nfso2w77mSR3IMsN

zh4mmLOIBAkO6fjAgESdV1MYiV4kiUZHRDjD3E0Qza580D+rjsUdAQEj4fRl8wUkqBttPeo5RlJI

uB71jIASc8D+i4W8IoX8CviC5cuI+JlgpLsgcF1ng6RQyaoX1oWX1i67DTxe9w+9/EHW9VOrngCW

ZfNFpmvVWOfUzZ/mfG0HwHBz4ZV1kz8nvLuL+YPnRPDJ00J8A/j9fzrnW+sjeUbjbP8amDyj86z+

tXL5PwzOC4njj4K3gavA8cazczYacLd+p/+6y8mfAgwAsRuLfp/zVLMAAAAASUVORK5CYII="""))

self.image = pygame.image.load(ball_file, 'file').convert_alpha()

self.rect = self.image.fill(color, None, BLEND_ADD)

self.rect.topleft = initial_position

pygame.init()

screen = pygame.display.set_mode([350, 350])

ball = Ball((255, 0, 0), (100, 100))

screen.blit(ball.image, ball.rect)

pygame.display.update()

while pygame.event.poll().type != KEYDOWN:

pygame.time.delay(10)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

importcStringIO,base64

importpygame

frompygame.localsimport*

classBall(pygame.sprite.Sprite):

def__init__(self,color,initial_position):

pygame.sprite.Sprite.__init__(self)

ball_file=cStringIO.StringIO(base64.decodestring(

"""iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ

bWFnZVJlYWR5ccllPAAABBJJREFUeNqsVj2PG1UUvfPp8XictXfHa+9mlyJCNEQRWiToqACJAgGC

LqJNlQZR0IFEj8RPSJkGGooUpEWJkGhR0tAAElI2tsfjjxnPjIdz7oyDF2wSUK72yN43793z7rkf

Y8N2HFmbbVliGIYiyzIpy1Isy3oHeMswzLOyXJ2tVit9VhTFAxz5Cfge+A7IZIcZmySObQudwIE0

veanraB1w/O8l5x6D9eXy6UkSaJYLBa6BvsNuAV8uY3sCQlvX4LANM0Xw/Dgdhj2Xm02m+K6LqPR

PXmeS5qmMp/PZTabyXQ6lclkosS1/QJcB+5vkthrAkoAuc4uHx//0B8MvCAIxG/5jEg0kpIkmcwX

icTxBIhlHWEURXoedgW4B3wIfHuBJM9yMQ3j5PTk5N7g6MjtdrrS3e9Ku90GUUvc2hkdMYJx5Ivn

NRC19UReRlRLR/sGeB34UUkMJBcJlcHg6K4SdDvS7/el1+tJp7MnQdCWRqMhDGWZLmWCCFog9rBm

GBYc50rOKON4uqkSC+IQSC3moeX7N09PX/i4AwLkAoQDxeFhHziU8CCUzt6e+EFLc2QaJi4mFQHy

kQLZMpME+WJF1sabdYA7Nq4jQbv9OZPs+75cgkSMYH9/X6PhJ9dpTLjruFLkBRyjACBd1BoLzzY8

T3O0IRntJvCZDXsTTnq262CzrzmgRHu4+QEIQhAxNzRWU1mTxfjOwvBIAOlIYNnWtja5bqM33mN/

sBEdx9bNPOQ1PWlqZJdAFKoMrEI6R+9gj6t7cUl1zjKnjFvsfaybr1Uqlv94ypXSKCud+aefpezs

7O3LL9s4c5U65gCrhGDDpUkqyWIuU1STweNlJRe7nAlmA+ZaVbnmiD4KFNEWC+3VqjB5YImDdMA+

YKONx2OVgxefojRL8CzmCxkOhxLhWYy+mGIvz6RKmv096X91PErP4Byazapbs3vZB45bVQqTzBzQ

kjQBQSTnjx7JcDTCRSLkKNY9SbKACsttHKZdrIqHILnGCNhoDU0qG83U5mNUVTOKShRPYo3m8fAc

nT/S/3mWFy2KrXKNOFbuI+Rr1FvLsB731Ho2m2pU7I1Sx8pSHTLaESIZjob6nfso2w77mSR3IMsN

zh4mmLOIBAkO6fjAgESdV1MYiV4kiUZHRDjD3E0Qza580D+rjsUdAQEj4fRl8wUkqBttPeo5RlJI

uB71jIASc8D+i4W8IoX8CviC5cuI+JlgpLsgcF1ng6RQyaoX1oWX1i67DTxe9w+9/EHW9VOrngCW

ZfNFpmvVWOfUzZ/mfG0HwHBz4ZV1kz8nvLuL+YPnRPDJ00J8A/j9fzrnW+sjeUbjbP8amDyj86z+

tXL5PwzOC4njj4K3gavA8cazczYacLd+p/+6y8mfAgwAsRuLfp/zVLMAAAAASUVORK5CYII="""))

self.image=pygame.image.load(ball_file,'file').convert_alpha()

self.rect=self.image.fill(color,None,BLEND_ADD)

self.rect.topleft=initial_position

pygame.init()

screen=pygame.display.set_mode([350,350])

ball=Ball((255,0,0),(100,100))

screen.blit(ball.image,ball.rect)

pygame.display.update()

whilepygame.event.poll().type!=KEYDOWN:

pygame.time.delay(10)

那一大堆的字符串,相信懂Python的人会明白的,不明白的请去查阅一下base64编码和Python对应的StringIO、base64库。我这里使用这种方法而不是直接读取文件,只是想告诉大家pygame.image.load方法不仅仅可以读取文件,也可以读取文件对象。是不是感觉一下子思路开阔了?Python那么多方便的文件对象,以后游戏的资源文件就可以不用一一独立放出来了,使用zipfile,我们很容易就可以把资源文件打包起来,这样看起来咱的游戏可就专业多了~这是后话,以后有机会再讲。

而本例没有直接画一个圆,而是使用用了颜色混合的方法,这样可以画出有立体感的球体,效果如左图。而上面一大堆的字符串,其实就是那个球体的图像文件编码以后的东西。这个和本教程没啥大联系,请自行学习光与色的知识……

但是但是,看了上面的代码大家一定会有意见了,这样感觉比直接用Surface写的代码还多啊!一点好处都没有的样子。确实会有这样的错觉,但是一个球看不出好处来,多个球呢?我们就可以这么写了:

Python

balls = []

for color, location in [([255, 0, 0], [50, 50]),

([0, 255, 0], [100, 100]),

([0, 0, 255], [150, 150])]:

boxes.append(Box(color, location))

...

for b in balls: screen.blit(b.image, b.rect)

pygame.display.update()

# 我们还能用一种更牛的重绘方式

# rectlist = [screen.blit(b.image, b.rect) for b in balls]

# pygame.display.update(rectlist)

# 这样的好处是,pygame只会重绘有更改的部分

1

2

3

4

5

6

7

8

9

10

11

12

13

14

balls=[]

forcolor,locationin[([255,0,0],[50,50]),

([0,255,0],[100,100]),

([0,0,255],[150,150])]:

boxes.append(Box(color,location))

...

forbinballs:screen.blit(b.image,b.rect)

pygame.display.update()

# 我们还能用一种更牛的重绘方式

# rectlist = [screen.blit(b.image, b.rect) for b in balls]

# pygame.display.update(rectlist)

# 这样的好处是,pygame只会重绘有更改的部分

我就不给出完整代码和效果图了,请大家自己试验。

不过光这样还不足以体现sprite的好处,sprite最大的优势在于动画,这里就需要用一下update方法,举一个例子,把第一个程序,从33行开始换成下面的代码:

Python

class MoveBall(Ball):

def __init__(self, color, initial_position, speed, border):

super(MoveBall, self).__init__(color, initial_position)

self.speed = speed

self.border = border

self.update_time = 0

def update(self, current_time):

if self.update_time < current_time:

if self.rect.left < 0 or self.rect.left > self.border[0] - self.rect.w:

self.speed[0] *= -1

if self.rect.top < 0 or self.rect.top > self.border[1] - self.rect.h:

self.speed[1] *= -1

self.rect.x, self.rect.y = self.rect.x + self.speed[0], self.rect.y + self.speed[1]

self.update_time = current_time + 10

pygame.init()

screen = pygame.display.set_mode([350, 350])

balls = []

for color, location, speed in [([255, 0, 0], [50, 50], [2,3]),

([0, 255, 0], [100, 100], [3,2]),

([0, 0, 255], [150, 150], [4,3])]:

balls.append(MoveBall(color, location, speed, (350, 350)))

while True:

if pygame.event.poll().type == QUIT: break

screen.fill((0,0,0,))

current_time = pygame.time.get_ticks()

for b in balls:

b.update(current_time)

screen.blit(b.image, b.rect)

pygame.display.update()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

classMoveBall(Ball):

def__init__(self,color,initial_position,speed,border):

super(MoveBall,self).__init__(color,initial_position)

self.speed=speed

self.border=border

self.update_time=0

defupdate(self,current_time):

ifself.update_time

ifself.rect.left<0orself.rect.left>self.border[0]-self.rect.w:

self.speed[0]*=-1

ifself.rect.top<0orself.rect.top>self.border[1]-self.rect.h:

self.speed[1]*=-1

self.rect.x,self.rect.y=self.rect.x+self.speed[0],self.rect.y+self.speed[1]

self.update_time=current_time+10

pygame.init()

screen=pygame.display.set_mode([350,350])

balls=[]

forcolor,location,speedin[([255,0,0],[50,50],[2,3]),

([0,255,0],[100,100],[3,2]),

([0,0,255],[150,150],[4,3])]:

balls.append(MoveBall(color,location,speed,(350,350)))

whileTrue:

ifpygame.event.poll().type==QUIT:break

screen.fill((0,0,0,))

current_time=pygame.time.get_ticks()

forbinballs:

b.update(current_time)

screen.blit(b.image,b.rect)

pygame.display.update()

我们可以看到小球欢快的运动起来,碰到边界就会弹回来,这才是sprite类的真正用处。每一个Sprite类都会有各自的速度属性,每次调用update都会各自更新自己的位置,主循环只需要update+blit就可以了,至于各个小球到底在一个怎样的状态,完全可以不在意。不过精灵的魅力还是不仅在此,上面的代码中我们把每个精灵加入一个列表,然后分别调用每个精灵的update方法,太麻烦了!使用pygame.sprite.Group类吧,建立它的一个实例balls,然后用add方法把精灵加入,然后只需要调用balls.update(args..)就可以了,连循环的不用写。同样的使用balls.draw()方法,你可以让pygame只重绘有变化的部分。请尝试使用(记住还有一个balls.clear()方法,实际写一下就知道这个方法用来干嘛了)。

尽管我们已经说了很多,也着实领略到了精灵的好处,但故事还没有结束,pygame.sprite有着层与碰撞的概念。层的引入是因为Group默认是没有次序的,所以哪个精灵覆盖哪个精灵完全就不知道了,解决方法嘛,使用多个Group、使用OrderedUpdates,或者使用LayeredUpdates,至于具体使用方法,相信如果您需要用到的时候,已经到相当的高度了,随便看看文档就明白了,我就不多说了;而碰撞,又是一个无底洞啊,下次有机会再讲吧~

python游戏代码示例_用Python和Pygame写游戏-从入门到精通(Sprite篇)相关推荐

  1. python turtle代码大全_通过构建简单的骰子游戏学习如何使用Python编程

    Python是一种通用的编程语言,可以用于创建桌面应用程序.3D图形.视频游戏,甚至是网站.它是一种很棒的第一编程语言,因为它很容易学习,而且比复杂的语言(如C.C++或Java)更简单.Python ...

  2. python独立log示例_带有Python示例的math.log()方法

    python独立log示例 Python math.log()方法 (Python math.log() method) math.log() method is a library method o ...

  3. python独立log示例_带有Python示例的math.log1p()方法

    python独立log示例 Python math.log1p()方法 (Python math.log1p() method) math.log1p() method is a library me ...

  4. 以下python注释代码中_以下Python注释代码,不正确的是()_学小易找答案

    [单选题]数字0-9是十进制的数码,全部数码的个数称为( ). [单选题]企业将款项汇往异地银行开设采购专户,根据收到的银行汇款凭证回单联,应借记的会计科目是( ).(2018年) [多选题]在201 ...

  5. python常用语法和示例_使用Python中的示例进行输入和输出操作

    python常用语法和示例 A Program needs to interact with the user to accomplish the desired task; this is done ...

  6. 以下python注释代码中_以下 Python注释代码不正确的是()

    以下 Python注释代码不正确的是() 答:// Python注释代码 According to Truman Doctrine, the US aimed to establish its heg ...

  7. python游戏代码示例_代码实例1:python 小人打架游戏

    中断了几年的python学习最近被重新拾起来了,实在是因为工作上需要用到的地方太多.不立flag了,记录学习成果,慢慢更新吧. 小人打架程序代码如下: ------------------------ ...

  8. python游戏代码示例_练习项目20:使用python制作游戏(中)

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 上一篇教程,我们通过实现一个敌机由上至下的循环过程,初步了解了pygame这个模块的使用. 接下来,我们进行第二阶段,真正的实现一个通过鼠标控制的小游戏. ...

  9. python2048小游戏代码视频_用Python实现小游戏2048

    转自:Python中文网社区论坛 直接上代码吧! import random from sys import exit from copy import deepcopy import pygame ...

最新文章

  1. iOS 解决app退出后台应用重新启动的问题
  2. R语言axis函数自定义可视化的坐标轴刻度线(axis ticks)
  3. Python argparse模块基本用法
  4. flink file sink
  5. 深入理解connect by
  6. iBATIS sql中的处理特殊符号的做法
  7. select不能触发change_SQL之警觉触发
  8. IOS开发学习笔记033-UIScrollView
  9. 网络安全:个人网站防黑安全技巧
  10. 旧物回收类网站源码v2.4
  11. vue 导出excel
  12. FAT32文件操作系统(主要针对SD卡)
  13. 为什么html字体之间有间隔,css字体间隔怎么调整?css文字间隔的调整方法
  14. shopex PHP Notice,解决最新shopex乱码问题
  15. java migration_JetPack知识点实战系列九:Room数据库Migration
  16. 平衡二叉树 构造方法RR RL LL LR
  17. Python几种基本的字符串格式化方法
  18. SpringBoot整合Elasticsearch BBoss
  19. 树莓派--seafile搭建私人网盘
  20. html自定义字体缓存,PixiJS:加载自定义字体

热门文章

  1. C#之详解飞行棋大战
  2. 圣诞节 一些很暖心的文字
  3. [shader]动态天空球
  4. 【学习笔记】医学图像文件存储的格式及Python中的读取方式
  5. r语言的runmed函数_使用R语言爬取DailyMed药物信息
  6. 解决vue-pdf 打包后生成worker文件报错问题
  7. 炉石传说脚本自学之路
  8. web和http相关知识点总结
  9. 完全理解乘法快速幂及其两种写法的解析
  10. STM32 F103C8T6 标准库换晶振 硬件8MHZ 换12MHZ实测方法