【python游戏编程之旅】第六篇---pygame中的Sprite(精灵)模块和加载动画
本系列博客介绍以python+pygame库进行小游戏的开发。有写的不对之处还望各位海涵。
直到现在我们已经学了很多pygame基础知识了,从这篇博客开始我们将会学习pygame中高级部分,更多和精灵模块,冲突检测相关的知识。
一、Sprite模块、sprite对象
在pygame.sprite模块里面包含了一个名为Sprite类,他是pygame本身自带的一个精灵。但是这个类的功能比较少,因此我们新建一个类对其继承,在sprite类的基础上丰富,以方便我们的使用。
首先来了解一下如何使用sprite类来加载动画吧。
1、精灵序列图
将要加载的动画帧放在一个精灵序列图里面,然后在程序里面调用它。pygame会自动更新动画帧,这样一个动态的图像就会展现在我们面前了。
下面是一个典型的精灵序列图:行和列的索引都是从0开始的。

2、加载精灵图序列:
在加载一个精灵图序列的时候,我们需要告知程序一帧的大小,(传入帧的宽度和高度,文件名)。
除此之外,还需要告诉精灵类,精灵序列图里面有多少列。load函数可以加载一个精灵序列图。
def load(self, filename, width, height, columns):
self.master_image = pygame.image.load(filename).convert_alpha()
self.frame_width = width
self.frame_height = height
self.rect = 0,0,width,height
self.columns = columns
3.更新帧
一个循环动画通常是这样工作的:从第一帧不断的加载直到最后一帧,然后在折返回第一帧,并不断重复这个操作。
self.frame += 1
if self.frame > self.last_frame:
self.frame = self.first_frame
self.last_time = current_time
但是如果只是这样做的话,程序会一股脑地将动画播放完了,我们想让它根据时间间隔一张一张的播放,因此加入定时的代码。
pygame中的time模块有一个get_ticks()方法可以满足定时的需要。
ticks = pygame.time.get_ticks()
然后将ticks变量传递给sprite的update函数,这样就可以轻松让动画按照帧速率来播放了。哦,帧速率还没有设置,咱们现在设置一下帧速率。
启动一个定时器,然后调用tick(num)函数就可以让游戏以num帧来运行了。
framerate = pygame.time.Clock()
framerate.tick(60)
4、绘制帧
sprite.draw()方法是用来绘制帧的,但是这个函数是由精灵来自动调用的,我们没有办法重写它,因此需要在update函数里面做一些工作。
首先需要计算单个帧左上角的x,y位置值(x表示列编号,y表示行编号):
frame_x = (self.frame % self.columns) * self.frame_width
#用帧数目除以行数,然后在乘上帧的高度
frame_y = (self.frame // self.columns) * self.frame_height
然后将计算好的x,y值传递给位置rect属性。
frame_x = (self.frame % self.columns) * self.frame_width
frame_y = (self.frame // self.columns) * self.frame_height
rect = ( frame_x, frame_y, self.frame_width, self.frame_height )
self.image = self.master_image.subsurface(rect)
5、精灵组
当程序中有大量的实体的时候,操作这些实体将会是一件相当麻烦的事,那么有没有什么容器可以将这些精灵放在一起统一管理呢?答案就是精灵组。
pygame使用精灵组来管理精灵的绘制和更新,精灵组是一个简单的容器。
使用pygame.sprite.Group()函数可以创建一个精灵组:
group = pygame.sprite.Group()
group.add(sprite_one)
精灵组也有update和draw函数:
group.update()
group.draw()
二、自定义的精灵类
好了,通过前面的学习,我们已经了解了一些精灵的知识了,现在我们将前面说到的方法封装成一个自定义的类,以方便我们的调用,这个类继承自pygame.sprite.Sprite:
class MySprite(pygame.sprite.Sprite):
def __init__(self, target):
pygame.sprite.Sprite.__init__(self) #基类的init方法
self.target_surface = target
self.image = None
self.master_image = None
self.rect = None
self.topleft = 0,0
self.frame = 0
self.old_frame = -1
self.frame_width = 1
self.frame_height = 1
self.first_frame = 0
self.last_frame = 0
self.columns = 1
self.last_time = 0 def load(self, filename, width, height, columns):
self.master_image = pygame.image.load(filename).convert_alpha()
self.frame_width = width
self.frame_height = height
self.rect = 0,0,width,height
self.columns = columns
rect = self.master_image.get_rect()
self.last_frame = (rect.width // width) * (rect.height // height) - 1 def update(self, current_time, rate=60):
#更新动画帧
if current_time > self.last_time + rate:
self.frame += 1
if self.frame > self.last_frame:
self.frame = self.first_frame
self.last_time = current_time if self.frame != self.old_frame:
frame_x = (self.frame % self.columns) * self.frame_width
frame_y = (self.frame // self.columns) * self.frame_height
rect = ( frame_x, frame_y, self.frame_width, self.frame_height )
self.image = self.master_image.subsurface(rect)
self.old_frame = self.frame
好了现在我们写一个小程序来测试一下这个类的性能怎么样。
这里我用ps制作了一个简单的精灵序列图,咱们就用这个萌萌的嗷大喵好了:
代码:
import pygame
from pygame.locals import * class MySprite(pygame.sprite.Sprite):
def __init__(self, target):
pygame.sprite.Sprite.__init__(self)
self.target_surface = target
self.image = None
self.master_image = None
self.rect = None
self.topleft = 0,0
self.frame = 0
self.old_frame = -1
self.frame_width = 1
self.frame_height = 1
self.first_frame = 0
self.last_frame = 0
self.columns = 1
self.last_time = 0 def load(self, filename, width, height, columns):
self.master_image = pygame.image.load(filename).convert_alpha()
self.frame_width = width
self.frame_height = height
self.rect = 0,0,width,height
self.columns = columns
rect = self.master_image.get_rect()
self.last_frame = (rect.width // width) * (rect.height // height) - 1 def update(self, current_time, rate=60):
if current_time > self.last_time + rate:
self.frame += 1
if self.frame > self.last_frame:
self.frame = self.first_frame
self.last_time = current_time if self.frame != self.old_frame:
frame_x = (self.frame % self.columns) * self.frame_width
frame_y = (self.frame // self.columns) * self.frame_height
rect = ( frame_x, frame_y, self.frame_width, self.frame_height )
self.image = self.master_image.subsurface(rect)
self.old_frame = self.frame pygame.init()
screen = pygame.display.set_mode((800,600),0,32)
pygame.display.set_caption("精灵类测试")
font = pygame.font.Font(None, 18)
framerate = pygame.time.Clock() cat = MySprite(screen)
cat.load("sprite.png", 100, 100, 4)
group = pygame.sprite.Group()
group.add(cat) while True:
framerate.tick(30)
ticks = pygame.time.get_ticks() for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
key = pygame.key.get_pressed()
if key[pygame.K_ESCAPE]:
exit() screen.fill((0,0,100)) group.update(ticks)
group.draw(screen)
pygame.display.update()
效果图:萌萌的嗷大喵跃然于屏幕上。看起来功能还不错的说。

大家也可以制作一些自己喜欢的精灵序列图,然后加载并查看他们的效果。
关于精灵与精灵之间的冲突检测,精灵与组之间的碰撞检测,我们将会放在下个博客一起学习。
【python游戏编程之旅】第六篇---pygame中的Sprite(精灵)模块和加载动画的更多相关文章
- 【python游戏编程之旅】第二篇--pygame中的IO、数据
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 在上一篇中,我们介绍了pygame的入门操作http://www.cnblogs.com/msxh/p/49 ...
- 【python游戏编程之旅】第九篇---嗷大喵快跑小游戏开发实例
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 前几期博客我们一起学习了,pygame中的冲突检测技术以及一些常用的数据结构. 这次我们来一起做一个简单的酷 ...
- 【python游戏编程之旅】第一篇---初识pygame
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 一.pygame简介 Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础 ...
- 【python游戏编程之旅】第七篇---pygame中的冲突检测技术
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 上一个博客我们一起学习了pygame中的Sprite模块和如何加载动画:http://www.cnblogs ...
- 【python游戏编程之旅】第五篇---嗷大喵爱吃鱼小游戏开发实例
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 我们一同在前几期的博客中已经学到了很多pygame的基本知识了,现在该做个小游戏实战一下了. 前几期博客链接 ...
- 【python游戏编程之旅】第四篇---pygame中加载位图与常用的数学函数。
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 在上一篇博客中,我们学习了pygame事件与设备轮询.http://www.cnblogs.com/msxh ...
- 【python游戏编程之旅】第三篇---pygame事件与设备轮询
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 在上一篇博客中,我们学习了pygame中的IO.数据http://www.cnblogs.com/msxh/ ...
- 【python游戏编程之旅】第八篇---pygame游戏开发常用数据结构
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 上一个博客我们一起学习了pygame中冲突检测技术:http://www.cnblogs.com/msxh/ ...
- 少儿编程:python趣味编程第二课,如何在pygame中写文字
python趣味编程第二课:本文仅针对8-16岁的青少年,所以流程是按如何去教好中小学生走的,并不适合成人找工作学习,因为进度也是按照青少年走的 大家好,我是C大叔,上一篇文章已经跟大家介绍了一款开发 ...
随机推荐
- Ionic2 Tutorial
build your first app Now that you have Ionic and its dependencies installed, you can build your firs ...
- Python中如何读取xml的数据
<?xml version="1.0" encoding="utf-8" ?> - <catalog> <maxid>4&l ...
- ViewPager部分源码分析一:加载数据
onMeasure()调用populate(),完成首次数据初始化. populate()维护ViewPager的page,包括mItems和mAdapter. populate(): if (cur ...
- MVC学习笔记---MVC框架执行顺序
一.把路由添加到路由表, 二.注册ControllerBuilder(老板)和默认工厂(DefaultControllerFactory) 2.1默认工厂获取可以创建的Controller. 三.由于 ...
- Pyqt 获取windows系统中已安装软件列表
开始之前的基础知识 1. 获取软件列表 在Python的标准库中,_winreg可以操作Windows的注册表.获取已经安装的软件列表一般是读去windows的注册表: SOFTWARE\Micros ...
- 安装oracle 12c RAC遇到的一些问题
(1) 安装grid软件,停止在38%很长时间不动,日志显示正常 解决方法: 由于是虚拟机安装,设置的内存为600M,关闭虚拟机,把内存调成1GB,问题解决~在38%Linking RMAN Ut ...
- CXF学习(2) helloworld
0.新建一个项目取名wsserver. pom.xml 文件如下 <project xmlns="http://maven.apache.org/POM/4.0.0" xml ...
- 攻城狮在路上(壹) Hibernate(八)--- 映射Hibernate组成关系
一.使用组成关系的原则: 在不导致数据冗余的前提下,尽可能减少数据库表的数目及表之间的外键参照关系,因为建立多个表的连接是很耗时的操作. 举例说明:Customer类中的Address属性,可以通过组 ...
- JqueryEasyUI 解决IE下datagrid无法刷新的问题 分类: JavaScript JqueryEasyUI 2014-09-20 10:05 510人阅读 评论(1) 收藏
问题描述: 在使用JqueryEasyUI 时,发现在IE下$('#table').datagrid('reload');无效,数据并没有被刷新,究其原因,是因为刷新时,datagrid请求的url没 ...
- jquery中ajax的简单使用
一.load() 这是最简单的一个函数,传入一个url他会异步加载该url的内容,然后将内容插入每一个选中的元素中,替换掉其中已经存在的内容. 所以最简单的用法是: $("#myDiv&qu ...