Python游戏引擎开发(六):动画的小小研究
今天我们来研究动画,其实这个动画就是一个Sprite
+Bitmap
的结合体。不造什么是Sprite
和Bitmap
?=__=#看来你是半路杀进来的,快去看看前几章吧:
Python游戏引擎开发(一):序
Python游戏引擎开发(二):创建窗口以及重绘界面
Python游戏引擎开发(三):显示图片
Python游戏引擎开发(四):TextField文本类
Python游戏引擎开发(五):Sprite精灵类和鼠标事件
动画的原理
一般而言,我们的动画是用的这样一种图片:
播放动画的时候,像播放电影一样,这张图就是胶卷。我们可以弄一个放映机,放映机的镜头大小就是每个动作小图的大小。如果我们的胶卷不停地移动,那么就会连成动画,如下图:
如何实现这个效果呢?我们在第三章中学到了如何显示图片,其中提到了BitmapData
类(不懂?良辰劝你去读读前几章),这个类中有个两个方法:setCoordinate
和setProperty
用于设置图片显示的位置和大小:
bmpd.setCoordinate(x, y)
bmpd.setProperty(x, y, width, height)
参数图解如下:
在播放动画时,我们的“胶卷”就是一个Bitmap
图片显示对象,其中包含了一个BitmapData
对象,我们通过调用这个对象的上述两个方法,就能实现动画播放。
不过到此好像还是少了什么?也许你会问,动画是个连续的过程,且每帧动画之间需要间隔一点时间,是不是少了一个计时器?是的,是的,是的,重要的事情说三遍,我们的确少了一个计时器类似物。不过别急。大家还记得第三章中提到的显示对象的_show
方法吗?这个方法是在窗口的paintEvent
中被调用的,paintEvent
又是在一个计时器中被调用的(涉及第二章内容)。等等……计时器……所以我们其实已经有计时器了,差了个进入计时器的接口罢了。
时间轴事件
既然少了个接口,那么加个不就完了嘛。更改DisplayObject
的_show
方法:
def _show(self, c):if not self.visible:return# 加入时间轴事件入口self._loopFrame()c.save()c.translate(self.x, self.y)c.setOpacity(self.alpha * c.opacity())c.rotate(self.rotation)c.scale(self.scaleX, self.scaleY)self._loopDraw(c)c.restore()
就加入了时间轴事件入口那一行代码。这个方法在子类Sprite
中具体实现:
def _loopFrame(self):e = object()e.currentTarget = selfs.__enterFrameListener(e)
其中__enterFrameListener
为新加入Sprite
的属性,是时间轴事件的监听器。与鼠标事件相同,我们向监听器传入一个参数,用于获取事件信息。
更改Sprite
的addEventListener
使其能加入时间轴事件:
def addEventListener(self, eventType, listener):if eventType == Event.ENTER_FRAME:self.__enterFrameListener = listenerelse:self.mouseList.append({"eventType" : eventType,"listener" : listener})
再在Event
类中定义一下时间轴事件ENTER_FRAME
:
class Event(Object):ENTER_FRAME = "enter_frame"# more code...
使用时,这么写就OK:
layer = Sprite()
layer.addEventListener(Event.ENTER_FRAME, onframe)def onframe(e):print("enter frame")
简单的动画类
动画类:
class Animation(Sprite):def __init__(self, bitmapData = BitmapData(), frameList = [[AnimationFrame()]]):super(Animation, self).__init__()
这个类需要一个BitmapData
对象作为参数,还需要一个list
对象,这个list
是用来装AnimationFrame
对象的帧列表,AnimationFrame
顾名思义是一个保存每帧数据的类。代码实现如下:
class AnimationFrame(object):def __init__(self, x = 0, y = 0, width = 0, height = 0):super(AnimationFrame, self).__init__()self.x = xself.y = yself.width = widthself.height = height
其中x
,y
属性储存了每帧位于图片上的位置,width
和height
储存每帧的宽高。
对于一般的动画图片(上文中的示例图片),每帧都是均匀分布在图片上的,所以我们可以加入一个函数进行帧的均匀裁剪,这样一来,我们获取帧列表就会方便很多。为Animation
类添加如下代码:
def divideUniformSizeFrames(width = 0, height = 0, col = 1, row = 1):result = []frameWidth = width / colframeHeight = height / rowfor i in range(row):rowList = []for j in range(col):frame = AnimationFrame(j * frameWidth, i * frameHeight, frameWidth, frameHeight)rowList.append(frame)result.append(rowList)return result
接下来,我们调用这个函数,传入相应参数就可以切割出帧列表了。如下:
l = Animation.divideUniformSizeFrames(160, 160, 4, 4)# 得到如下列表:
[
[AnimationFrame(0, 0, 40, 40), AnimationFrame(40, 0, 40, 40), AnimationFrame(80, 0, 40, 40), AnimationFrame(120, 0, 40, 40)],
[AnimationFrame(0, 40, 40, 40), AnimationFrame(40, 40, 40, 40), AnimationFrame(80, 40, 40, 40), AnimationFrame(120, 40, 40, 40)],
[AnimationFrame(0, 80, 40, 40), AnimationFrame(40, 80, 40, 40), AnimationFrame(80, 80, 40, 40), AnimationFrame(120, 80, 40, 40)],
[AnimationFrame(0, 120, 40, 40), AnimationFrame(40, 120, 40, 40), AnimationFrame(80, 120, 40, 40), AnimationFrame(120, 120, 40, 40)]
]
接下来就是实现播放动画了,修改Animation
类:
class Animation(Sprite):def __init__(self, bitmapData = BitmapData(), frameList = [[AnimationFrame()]]):super(Animation, self).__init__()self.bitmapData = bitmapDataself.frameList = frameListself.bitmap = Bitmap(bitmapData)self.currentRow = 0self.currentColumn = 0self.addEventListener(Event.ENTER_FRAME, self.__onFrame)def __onFrame(self, e):currentFrame = self.frameList[self.currentRow][self.currentColumn]self.bitmap.bitmapData.setProperty(currentFrame.x, currentFrame.y, currentFrame.width, currentFrame.height)self.currentColumn += 1if self.currentColumn >= len(self.frameList[self.currentRow]):self.currentColumn = 0
由于这个类继承自Sprite
,所以就继承了加入事件的addEventListener
方法。以上代码实现的是播放一排动画,大家可以自行拓展为播放一列动画或者播放整组动画。
这样一来,写入以下代码就能播放动画了:
# 加载图片
loader = Loader()
loader.load("./player.png")# 动画数据
bmpd = BitmapData(loader.content)
l = Animation.divideUniformSizeFrames(160, 160, 4, 4)# 加入动画
anim = Animation(bmpd, l)
addChild(anim)
预告:下一篇我们来绘制矢量图形。
欢迎大家继续关注我的博客
转载请注明出处:Yorhom’s Game Box
http://blog.csdn.net/yorhomwang
Python游戏引擎开发(六):动画的小小研究相关推荐
- Python游戏引擎开发(一):序
邂逅Python 写了这么久的html5,感觉html5学得差不多了,是时候去接触更多的语言来扩充自己的能力了.我先后看了Swift,Java等语言.首先开发Swift需要一台mac,对于我这个寒士而 ...
- python游戏引擎开发二_python制作galgame引擎(二)
上一篇主要涉及的其实是我个人的一些初期目标,以及解决方式.虽然提了提Parser类的实现,但是代码毕竟不是主要讨论的对象.而且很明显的,上一篇几乎与galgame制作无关-- 这一篇主要讨论的实现,中 ...
- python怎么制作游戏图片_Python游戏引擎开发(二):显示图片
本篇文章是Python游戏引擎开发系列的第二篇文章,主要介绍如何显示图片,大家可以学习下. 在上一章中我们讲了如何创建窗口以及对界面进行重绘.可能有朋友不理解为什么要进行全窗口的重绘呢?我在这里可以大 ...
- 游戏引擎开发和物理引擎_视频游戏开发的最佳游戏引擎
游戏引擎开发和物理引擎 In this article, we'll look at some of the most popular game engines for video game deve ...
- 用C++实现跨平台游戏引擎开发
游戏开发系列 用C++实现跨平台游戏引擎开发 你是否梦想写一部格斗游戏但却无从着手呢?是否你只因游戏开发好玩而对之感兴趣?本文我们将分析一个通用的跨平台游戏引擎,每个游戏开发新手都可以自由地使用它. ...
- 【转载】浅析游戏引擎开发
浅析游戏引擎开发 1 引言 电脑游戏作为一种娱乐方式越来越为人们所接受.即时通讯开发对于电脑游戏来说, 游戏引擎是用于控制游戏功能的 主程序, 如接受玩家控制信息的输入, 选择合适的声音以合适的音量播 ...
- 视频教程-三维游戏引擎开发-图形理论基础-其他
三维游戏引擎开发-图形理论基础 2004年毕业于西南科技大学,计算机科学技术专业,从事软件开发,游戏开发,擅长游戏开发,桌面应用,手机游戏. 张立铜 ¥117.00 立即订阅 扫码下载「CSDN程序员 ...
- 游戏引擎与游戏引擎开发入门
早想写一点游戏设计的文章与大家交流,一是经验的问题,二是公司正在紧张的游戏制作期,实在抽不出多少时间,一直没有动手,今天忽然头脑发热,写了一段,以后准备陆续写一些游戏创意,策划,制作,流程管理,和制作 ...
- 游戏引擎开发入门教程_v20210102
游戏引擎(Game Engine)是一款游戏的"发动机",是游戏的核心部件,同时也是一个大型软件系统.游戏画面是否绚丽和流畅,游戏场面是否震撼和真实,这些都是由引擎决定的. 从编程 ...
最新文章
- 往往存储与计算机硬盘或其他,硬盘是计算机系统中信息资源最重要的存储设备其所存放信息-Read.DOC...
- wxWidgets:Erase wxWidgets示例
- 【Python数据挖掘课程】九.回归模型LinearRegression简单分析氧化物数据
- 梯度下降和随机梯度下降_梯度下降和链链接系统
- stringredistemplate设置过期时间_Redis的过期删除策略和内存淘汰机制
- jq处理返回来json_4个小窍门,让你在Python中高效使用JSON
- 四大招让无处不在的工作空间成为可能?揭秘Ivanti 的战略布局
- 红橙Darren视频笔记 Behavior的工作原理源码分析
- 怎么查江苏省计算机一级成绩,江苏省计算机一级查询成绩在哪里查-江苏省计算机一级查询成绩查询网址-常州宝...
- Linux 串口、usb转串口驱动分析(2-1) 【转】
- CommandName 限制
- OHSAS18001与ISO14001体系的一体化及其审核(转载)
- Houdini图文笔记:Houdini Indie正版声明
- 因为mac不支持移动硬盘的NTFS格式,mac电脑无法写入移动硬盘的终极解决办法(方便好用)
- 苹果直营店_请谨慎选择百邦苹果售后维修,亲身体验,倒不如直接去直营店呢...
- 如何在51单片机实现日程提醒(生日闹钟)
- 【良心推荐两款软件】eDiary记笔记软件+截图识别文字软件
- 美颜sdk常用功能的实现原理
- Sigar获取网卡流量信息
- 三角形顺时针和逆时针的判定
热门文章
- Adobe Lightroom Classic 2021(LR 2021)照片编辑软件
- 程序员常说的「哈希表」是个什么鬼?
- 分享万能java字符串编码转换工具类
- 内外网同时访问路由配置(WIN11)
- typora使用picgo拖拽复制自动上传到chevereto私有图床(mac版)
- 雾计算机和云计算机哪个好,怎么理解云计算和雾计算还有边缘计算
- 漫威宇宙——每一部都是一场盛宴
- GBase xdm查询条件要求
- 为什么选择mac os系统,Mac os系统六大优点
- matlab C 混编 --- 在MATLAB中使用c语言函数