设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 3796|回复: 8

[原创发布] [Done]真.动画播放的提速=_= [BY FantasyDR]

 关闭 [复制链接]
头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
发表于 2005-10-23 21:29:36 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
原来的那篇文章,实在有点误人子弟了。虽然前面大体分析过程没有错误,但是后面的改法有点效率低下,而且存在错误……我也就不细说了。下面已经改过了……

最近我发了个叫做《Strike》的射击游戏Demo,虽然很卡,不过速度上面应该比纯事件制作的快一些。其中子弹的效果是一个空白的事件,然后在其身上播放一种动画来表现。最初很快发现一个问题,即使在P4,2.8G的CPU的机器上面,按下子弹发射键依然会卡一下才能继续。

这对于游戏的表现力很有影响,所以就探察了一下原因。

开始以为是并行事件调用的原因,后来发现,如果一个动画正在播放中,那么再次播放它就不会有停顿。如果是一个独立的动画,开始的时候就会卡。于是看是分析动画播放相关的内容,追溯到RPG::Sprite这个内部类。

还好,帮助里面厚道的给出了RPG::Sprite的实现方法,否则真的死在这里了。而且,帮助文件里面厚道的提示了以下内容:
显示的动画图像从 RPG::Cache 模块中取得,动画结束时为了节约内存而被释放。

现在又仔细理解了一下那个RPG::Sprite的定义,发现还是不要把Sprite的dispos也去掉为好,因为显示层的关系。

根据这条线索,阅读RPG:Sprite的代码实现,发现每次播放动画前,会载入动画所需的素材图片。接下来分析了下代码,发现其实原本素材的bitmap是存放在一个Hash表里面的,也就是本来是可以实现类似缓存加速的效果的,当有动画调用这副素材,这副素材的引用数量就被加1,如果这个动画播放完毕,引用数量减1,当引用数量为0,素材图片被释放……

问题就在这里。

这也就解释了为什么同样的动画一起播放反而不卡的原因,因为只有一次new和一次dispose,中间都是直接取Hash里面的对象,省略了大量的初始化时间。


那么改造方案也就出炉了,重载这个方法,去掉相关的资源释放的内容。以下是代码,从帮助里面粘贴出来,代码中被我注释掉的是释放资源相关的内容。只有在头一次按播放某个动画的时候会稍微卡一下,机子好的话不会有感觉,以后都不会卡了。

而且,其实速度的关键就是那张动画图片的加载,现在可以确定,这种改法至多会让你浪费掉Animation目录下面的图片所消耗的内存,其他没有任何副作用。
但是觉得RM游戏动画播放所消耗的内存应该不足以致命吧?至少我的游戏是正常的……

如果在调用动画之前卡一下觉得不爽的朋友们,就加入这个脚本吧。
甚至可以可以尝试动态Loding。在需要的时候,把Animation目录下面的图片随便用
RPG::Cache.animation("文件名",色相值)
赋给某个变量,这样就相当于预载入了图片。播放的时候一点都不会卡:)
那么,文件多的话,做一个Loding画面也就不过分了:)


脚本请插入工程的Main之前:

  1. module RPG
  2.   class Sprite < ::Sprite
  3.     def dispose_animation
  4.       if @_animation_sprites != nil
  5.         sprite = @_animation_sprites[0]
  6.         if sprite != nil
  7.           @@_reference_count[sprite.bitmap] -= 1
  8.         #  if @@_reference_count[sprite.bitmap] == 0
  9.         #    sprite.bitmap.dispose
  10.         #  end
  11.         end
  12.         for sprite in @_animation_sprites
  13.           sprite.dispose
  14.         end
  15.         @_animation_sprites = nil
  16.         @_animation = nil
  17.       end
  18.     end
  19.   end
  20. end
复制代码


              [本贴由 柳柳 于 2005-10-24 6:51:42 最后编辑]
签名被屏蔽
头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
 楼主| 发表于 2005-10-23 21:29:36 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
原来的那篇文章,实在有点误人子弟了。虽然前面大体分析过程没有错误,但是后面的改法有点效率低下,而且存在错误……我也就不细说了。下面已经改过了……

最近我发了个叫做《Strike》的射击游戏Demo,虽然很卡,不过速度上面应该比纯事件制作的快一些。其中子弹的效果是一个空白的事件,然后在其身上播放一种动画来表现。最初很快发现一个问题,即使在P4,2.8G的CPU的机器上面,按下子弹发射键依然会卡一下才能继续。

这对于游戏的表现力很有影响,所以就探察了一下原因。

开始以为是并行事件调用的原因,后来发现,如果一个动画正在播放中,那么再次播放它就不会有停顿。如果是一个独立的动画,开始的时候就会卡。于是看是分析动画播放相关的内容,追溯到RPG::Sprite这个内部类。

还好,帮助里面厚道的给出了RPG::Sprite的实现方法,否则真的死在这里了。而且,帮助文件里面厚道的提示了以下内容:
显示的动画图像从 RPG::Cache 模块中取得,动画结束时为了节约内存而被释放。

现在又仔细理解了一下那个RPG::Sprite的定义,发现还是不要把Sprite的dispos也去掉为好,因为显示层的关系。

根据这条线索,阅读RPG:Sprite的代码实现,发现每次播放动画前,会载入动画所需的素材图片。接下来分析了下代码,发现其实原本素材的bitmap是存放在一个Hash表里面的,也就是本来是可以实现类似缓存加速的效果的,当有动画调用这副素材,这副素材的引用数量就被加1,如果这个动画播放完毕,引用数量减1,当引用数量为0,素材图片被释放……

问题就在这里。

这也就解释了为什么同样的动画一起播放反而不卡的原因,因为只有一次new和一次dispose,中间都是直接取Hash里面的对象,省略了大量的初始化时间。


那么改造方案也就出炉了,重载这个方法,去掉相关的资源释放的内容。以下是代码,从帮助里面粘贴出来,代码中被我注释掉的是释放资源相关的内容。只有在头一次按播放某个动画的时候会稍微卡一下,机子好的话不会有感觉,以后都不会卡了。

而且,其实速度的关键就是那张动画图片的加载,现在可以确定,这种改法至多会让你浪费掉Animation目录下面的图片所消耗的内存,其他没有任何副作用。
但是觉得RM游戏动画播放所消耗的内存应该不足以致命吧?至少我的游戏是正常的……

如果在调用动画之前卡一下觉得不爽的朋友们,就加入这个脚本吧。
甚至可以可以尝试动态Loding。在需要的时候,把Animation目录下面的图片随便用
RPG::Cache.animation("文件名",色相值)
赋给某个变量,这样就相当于预载入了图片。播放的时候一点都不会卡:)
那么,文件多的话,做一个Loding画面也就不过分了:)


脚本请插入工程的Main之前:

  1. module RPG
  2.   class Sprite < ::Sprite
  3.     def dispose_animation
  4.       if @_animation_sprites != nil
  5.         sprite = @_animation_sprites[0]
  6.         if sprite != nil
  7.           @@_reference_count[sprite.bitmap] -= 1
  8.         #  if @@_reference_count[sprite.bitmap] == 0
  9.         #    sprite.bitmap.dispose
  10.         #  end
  11.         end
  12.         for sprite in @_animation_sprites
  13.           sprite.dispose
  14.         end
  15.         @_animation_sprites = nil
  16.         @_animation = nil
  17.       end
  18.     end
  19.   end
  20. end
复制代码


              [本贴由 柳柳 于 2005-10-24 6:51:42 最后编辑]
签名被屏蔽

Lv2.观梦者

梦石
0
星屑
260
在线时间
1373 小时
注册时间
2005-10-16
帖子
5113

贵宾

发表于 2005-10-23 21:33:29 | 显示全部楼层
好的,我就把那帖删掉了~~{/dy}
我只个搬答案的
叔叔我已经当爹了~
婚后闪人了……
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
 楼主| 发表于 2005-10-23 21:35:27 | 显示全部楼层
呵呵,谢谢啦:)
签名被屏蔽
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
500
发表于 2005-10-23 22:09:13 | 显示全部楼层
强!到死都不明白是怎么回事……
总之用了~
绝对异位面领域
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
260
在线时间
1373 小时
注册时间
2005-10-16
帖子
5113

贵宾

发表于 2005-10-23 22:17:40 | 显示全部楼层
就理解成第一次读取时先把内容放到一个快表里,下次用的时候就比较容易找到并调用……{/pz}
我只个搬答案的
叔叔我已经当爹了~
婚后闪人了……
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
 楼主| 发表于 2005-10-23 22:31:30 | 显示全部楼层
RGSS原本就是那样做的,这个脚本没有改变这部分。

只是觉得它不应该在没有动画引用到某素材的时候,就释放这个素材。因为很可能下一时刻这个动画又被播放。所以,这个脚本是去掉了释放的相关内容。

之所以写了这么多字,一是因为分析的比较辛苦(虽然最后改起来其实没什么技术含量-_-b),二是希大家能多少了解一下动画模块的工作过程。抛个砖……希望引来好东西:)
签名被屏蔽
回复 支持 反对

使用道具 举报

Lv1.梦旅人

66RPG站长

梦石
0
星屑
54
在线时间
615 小时
注册时间
2005-10-10
帖子
5734

RMVX自由创作大赛亚军第2届短篇游戏比赛亚军第5届短篇游戏比赛冠军

发表于 2005-10-24 14:48:53 | 显示全部楼层
更新完毕
我把讨论地址连接到这个贴子了
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
 楼主| 发表于 2005-10-24 15:59:18 | 显示全部楼层
嗯,多谢:)
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-4-19 07:24

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表