【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:

 1 class MySprite(pygame.sprite.Sprite):
 2     def __init__(self, target):
 3         pygame.sprite.Sprite.__init__(self) #基类的init方法
 4         self.target_surface = target
 5         self.image = None
 6         self.master_image = None
 7         self.rect = None
 8         self.topleft = 0,0
 9         self.frame = 0
10         self.old_frame = -1
11         self.frame_width = 1
12         self.frame_height = 1
13         self.first_frame = 0
14         self.last_frame = 0
15         self.columns = 1
16         self.last_time = 0
17
18     def load(self, filename, width, height, columns):
19         self.master_image = pygame.image.load(filename).convert_alpha()
20         self.frame_width = width
21         self.frame_height = height
22         self.rect = 0,0,width,height
23         self.columns = columns
25         rect = self.master_image.get_rect()
26         self.last_frame = (rect.width // width) * (rect.height // height) - 1
27
28     def update(self, current_time, rate=60):
29         #更新动画帧
30         if current_time > self.last_time + rate:
31             self.frame += 1
32             if self.frame > self.last_frame:
33                 self.frame = self.first_frame
34             self.last_time = current_time
35
37         if self.frame != self.old_frame:
38             frame_x = (self.frame % self.columns) * self.frame_width
39             frame_y = (self.frame // self.columns) * self.frame_height
40             rect = ( frame_x, frame_y, self.frame_width, self.frame_height )
41             self.image = self.master_image.subsurface(rect)
42             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()

效果图:萌萌的嗷大喵跃然于屏幕上。看起来功能还不错的说。

大家也可以制作一些自己喜欢的精灵序列图,然后加载并查看他们的效果。

关于精灵与精灵之间的冲突检测,精灵与组之间的碰撞检测,我们将会放在下个博客一起学习。

时间: 2024-10-05 16:42:25

【python游戏编程之旅】第六篇---pygame中的Sprite(精灵)模块和加载动画的相关文章

【python游戏编程之旅】第二篇--pygame中的IO、数据

本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 在上一篇中,我们介绍了pygame的入门操作http://www.cnblogs.com/msxh/p/4966899.html 这次我们将一起学习pygame中的IO.数据和更多关于字体打印的知识. 一.python输入输出 1.输出 python一次可以打印多个变量,只要用一个逗号将每个变量隔开就可以了.比如: A = 123 B = "ABC" C = 456 D = "DEF&

【python游戏编程之旅】第一篇---初识pygame

本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 参考书籍:<python游戏编程入门> 一.pygame简介 Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础上开发.允许你在 Python 程序中创建功能丰富的游戏和多媒体程序,Pygame 是一个高可移植性的模块可以支持多个操作系统.用它来开发小游戏非常适合. 可以去http://www.pygame.org/hifi.html 下载并安装使用pygame. 二

【python游戏编程之旅】第九篇---嗷大喵快跑小游戏开发实例

本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 前几期博客我们一起学习了,pygame中的冲突检测技术以及一些常用的数据结构. 这次我们来一起做一个简单的酷跑类游戏综合运用以前学到的知识. 程序下载地址:http://yunpan.cn/cLIcJgTvq4tZS 访问密码 901f 源代码网盘地址:http://yunpan.cn/cLIc67S4nNRFY 访问密码 c139 github地址:https://github.com/XINCGer/

【python游戏编程之旅】第七篇---pygame中的冲突检测技术

本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 上一个博客我们一起学习了pygame中的Sprite模块和如何加载动画:http://www.cnblogs.com/msxh/p/5013555.html 这次我们来一起学习pygame中的冲突检测技术. pygame支持非常多的冲突检测技术,我们来一一的看一下他们是如何使用的: 一.精灵与精灵之间的冲突检测 1.两个精灵之间的矩形检测 在只有两个精灵的时候我们可以使用pygame.sprite.col

【python游戏编程之旅】第五篇---嗷大喵爱吃鱼小游戏开发实例

本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 我们一同在前几期的博客中已经学到了很多pygame的基本知识了,现在该做个小游戏实战一下了. 前几期博客链接: 第一篇:初识pygame  http://www.cnblogs.com/msxh/p/4966899.html 第二篇:pygame中的IO.数据  http://www.cnblogs.com/msxh/p/4973003.html 第三篇:pygame事件与设备轮询  http://www

【python游戏编程之旅】第八篇---pygame游戏开发常用数据结构

本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 上一个博客我们一起学习了pygame中冲突检测技术:http://www.cnblogs.com/msxh/p/5027688.html 这次我们来一起学习在pygame游戏里面常用的一些数据结构: 数据,列表,元组,队列,栈. 一.数组与列表 数组可以理解为简化的列表.像我们之前使用的pygame.sprite.Group这样的精灵组,也是一个列表.列表的元素是可变的,它具有添加.删除.搜索.排序等多种

Python之路【第十六篇】:Django【基础篇】

Python之路[第十六篇]:Django[基础篇] Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. 基本配置 一.创建django程序 终端命令:django-admin startproject sitename IDE创建Django程序时,本质上都是自动执行上述命令 其他常用命令: python manage.py runserver

分享《Python 游戏编程快速上手(第3版)》高清中文版PDF+高清英文版PDF+源代码

下载:https://pan.baidu.com/s/1n4hyQq1YFkuLiL2G3388fw 更多资料分享:http://blog.51cto.com/3215120 <Python 游戏编程快速上手(第3版)>高清中文版PDF+高清英文版PDF+源代码高清中文版,带目录和书签,文字能够复制粘贴图.高清英文版,带目录和书签,文字能够复制粘贴.中英文两版对比学习.配套源代码.经典书籍,讲解详细. 其中,高清中文版如图: 原文地址:http://blog.51cto.com/3215120

Pygame - Python游戏编程入门(1)

前言 在上一篇中,我们初步熟悉了pygame的控制流程,但这对于一个游戏而言是远远不够的.所以在这一篇中,我们的任务是添加一架飞机(玩家),并且能够控制它进行移动,这样我们就又离目标进了一步了~ε=ε=(ノ≧∇≦)ノ 正片开始! 1. 把我们的战斗机搬上屏幕 在正式上代码以前,有一点需要说明的,我们可以看到,所有屏幕上出现的元素都在资源文件(resources/image/shoot.png)中,那我们要怎么做才能把一只飞机给裁剪出来呢?在pygame中,所有在屏幕上显示的元素都可以视为一个su