今天我们来研究动画,其实这个动画就是一个Sprite+Bitmap的结合体。不造什么是SpriteBitmap?=__=#看来你是半路杀进来的,快去看看前几章吧:

Python游戏引擎开发(一):序

Python游戏引擎开发(二):创建窗口以及重绘界面

Python游戏引擎开发(三):显示图片

Python游戏引擎开发(四):TextField文本类

Python游戏引擎开发(五):Sprite精灵类和鼠标事件

动画的原理

一般而言,我们的动画是用的这样一种图片:

播放动画的时候,像播放电影一样,这张图就是胶卷。我们可以弄一个放映机,放映机的镜头大小就是每个动作小图的大小。如果我们的胶卷不停地移动,那么就会连成动画,如下图:

如何实现这个效果呢?我们在第三章中学到了如何显示图片,其中提到了BitmapData类(不懂?良辰劝你去读读前几章),这个类中有个两个方法:setCoordinatesetProperty用于设置图片显示的位置和大小:

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的属性,是时间轴事件的监听器。与鼠标事件相同,我们向监听器传入一个参数,用于获取事件信息。

更改SpriteaddEventListener使其能加入时间轴事件:

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

其中xy属性储存了每帧位于图片上的位置,widthheight储存每帧的宽高。

对于一般的动画图片(上文中的示例图片),每帧都是均匀分布在图片上的,所以我们可以加入一个函数进行帧的均匀裁剪,这样一来,我们获取帧列表就会方便很多。为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游戏引擎开发(六):动画的小小研究相关推荐

  1. Python游戏引擎开发(一):序

    邂逅Python 写了这么久的html5,感觉html5学得差不多了,是时候去接触更多的语言来扩充自己的能力了.我先后看了Swift,Java等语言.首先开发Swift需要一台mac,对于我这个寒士而 ...

  2. python游戏引擎开发二_python制作galgame引擎(二)

    上一篇主要涉及的其实是我个人的一些初期目标,以及解决方式.虽然提了提Parser类的实现,但是代码毕竟不是主要讨论的对象.而且很明显的,上一篇几乎与galgame制作无关-- 这一篇主要讨论的实现,中 ...

  3. python怎么制作游戏图片_Python游戏引擎开发(二):显示图片

    本篇文章是Python游戏引擎开发系列的第二篇文章,主要介绍如何显示图片,大家可以学习下. 在上一章中我们讲了如何创建窗口以及对界面进行重绘.可能有朋友不理解为什么要进行全窗口的重绘呢?我在这里可以大 ...

  4. 游戏引擎开发和物理引擎_视频游戏开发的最佳游戏引擎

    游戏引擎开发和物理引擎 In this article, we'll look at some of the most popular game engines for video game deve ...

  5. 用C++实现跨平台游戏引擎开发

    游戏开发系列 用C++实现跨平台游戏引擎开发 你是否梦想写一部格斗游戏但却无从着手呢?是否你只因游戏开发好玩而对之感兴趣?本文我们将分析一个通用的跨平台游戏引擎,每个游戏开发新手都可以自由地使用它. ...

  6. 【转载】浅析游戏引擎开发

    浅析游戏引擎开发 1 引言 电脑游戏作为一种娱乐方式越来越为人们所接受.即时通讯开发对于电脑游戏来说, 游戏引擎是用于控制游戏功能的 主程序, 如接受玩家控制信息的输入, 选择合适的声音以合适的音量播 ...

  7. 视频教程-三维游戏引擎开发-图形理论基础-其他

    三维游戏引擎开发-图形理论基础 2004年毕业于西南科技大学,计算机科学技术专业,从事软件开发,游戏开发,擅长游戏开发,桌面应用,手机游戏. 张立铜 ¥117.00 立即订阅 扫码下载「CSDN程序员 ...

  8. 游戏引擎与游戏引擎开发入门

    早想写一点游戏设计的文章与大家交流,一是经验的问题,二是公司正在紧张的游戏制作期,实在抽不出多少时间,一直没有动手,今天忽然头脑发热,写了一段,以后准备陆续写一些游戏创意,策划,制作,流程管理,和制作 ...

  9. 游戏引擎开发入门教程_v20210102

    游戏引擎(Game Engine)是一款游戏的"发动机",是游戏的核心部件,同时也是一个大型软件系统.游戏画面是否绚丽和流畅,游戏场面是否震撼和真实,这些都是由引擎决定的. 从编程 ...

最新文章

  1. 往往存储与计算机硬盘或其他,硬盘是计算机系统中信息资源最重要的存储设备其所存放信息-Read.DOC...
  2. wxWidgets:Erase wxWidgets示例
  3. 【Python数据挖掘课程】九.回归模型LinearRegression简单分析氧化物数据
  4. 梯度下降和随机梯度下降_梯度下降和链链接系统
  5. stringredistemplate设置过期时间_Redis的过期删除策略和内存淘汰机制
  6. jq处理返回来json_4个小窍门,让你在Python中高效使用JSON
  7. 四大招让无处不在的工作空间成为可能?揭秘Ivanti 的战略布局
  8. 红橙Darren视频笔记 Behavior的工作原理源码分析
  9. 怎么查江苏省计算机一级成绩,江苏省计算机一级查询成绩在哪里查-江苏省计算机一级查询成绩查询网址-常州宝...
  10. Linux 串口、usb转串口驱动分析(2-1) 【转】
  11. CommandName 限制
  12. OHSAS18001与ISO14001体系的一体化及其审核(转载)
  13. Houdini图文笔记:Houdini Indie正版声明
  14. 因为mac不支持移动硬盘的NTFS格式,mac电脑无法写入移动硬盘的终极解决办法(方便好用)
  15. 苹果直营店_请谨慎选择百邦苹果售后维修,亲身体验,倒不如直接去直营店呢...
  16. 如何在51单片机实现日程提醒(生日闹钟)
  17. 【良心推荐两款软件】eDiary记笔记软件+截图识别文字软件
  18. 美颜sdk常用功能的实现原理
  19. Sigar获取网卡流量信息
  20. 三角形顺时针和逆时针的判定

热门文章

  1. Adobe Lightroom Classic 2021(LR 2021)照片编辑软件
  2. 程序员常说的「哈希表」是个什么鬼?
  3. 分享万能java字符串编码转换工具类
  4. 内外网同时访问路由配置(WIN11)
  5. typora使用picgo拖拽复制自动上传到chevereto私有图床(mac版)
  6. 雾计算机和云计算机哪个好,怎么理解云计算和雾计算还有边缘计算
  7. 漫威宇宙——每一部都是一场盛宴
  8. GBase xdm查询条件要求
  9. 为什么选择mac os系统,Mac os系统六大优点
  10. matlab C 混编 --- 在MATLAB中使用c语言函数