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

Project1

 找回密码
 注册会员
搜索
查看: 4700|回复: 10

[通用发布] 突破RMXP动画192x192大小限制

[复制链接]

Lv5.捕梦者 (版主)

梦石
1
星屑
23963
在线时间
3338 小时
注册时间
2011-7-8
帖子
3925

开拓者

发表于 2017-3-2 12:21:02 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 guoxiaomi 于 2017-3-3 11:54 编辑

一、 动机和背景
主要动机是 @89444640 在水区里的“无缝特效”主题,提到RMXP的动画图块只能是192x192大小,无法展示更高清晰度的动画。
@soulsaga 提出了解决方案的关键是修改:
RUBY 代码复制
  1. sprite.src_rect.set(pattern % 5 * 192, pattern / 5 * 192, 192, 192)

在得到这一提示之后我找到了这一行的代码在脚本中的位置是在 RPG::Sprite 的 animation_set_sprites(sprites, cell_data, position) 方法内,此方法用于获取每一帧展示动画的内容。从这里着手修改就可以突破192x192的限制。但是无法对编辑器进行修改,所以编辑器里看上去是乱的。

在解决这个问题后,我在6R上搜索“动画 大小”。截至目前可以看到有14个主题,时间跨度从2006年一直到2016年。大部分主题的解决方案是多图拼合,但是2016年的主题“如何调整技能动画默认读取的大小”中 @魔法丶小肉包 在 2 楼给出了同样的思路。

所以在 VA 修改 animation_set_sprites 是可行的,这也是主题为通用发布的原因。

二、解决方案
先上脚本,在给说明,本脚本只是 XP 适用:
RUBY 代码复制
  1. #==============================================================================
  2. # 全图动画 (突破 RMXP 动画 192 * 192 限制)
  3. #==============================================================================
  4. # 用法:
  5. # 1. 动画图片设置:
  6. #    1.1 宽度 640
  7. #    1.2 所有的子图片竖着排列
  8. #    1.3 图片名包含 ★全图320★ 这里 320 是单张高度值
  9. #    1.4 图片名包含 ★全图320YS160★ 则播放的动画会向下移动 160 像素
  10. # 2. 数据库动画设置
  11. #    2.1 选择一帧,添加一个单元
  12. #    2.2 位置:上 在正常动画上方(z=3000);
  13. #        位置:中 在正常动画下方(z=1500)
  14. #        位置:下 在敌人下方(z=0);
  15. #        位置:画面 z = x 坐标* y 坐标 * 放大率
  16. #    2.3 式样:此帧播放的子图片位置
  17. #    2.4 左右反转、不透明度和合成方式可以正常使用
  18. #    2.5 X坐标、Y坐标、放大率、旋转角度不可以正常使用
  19. #==============================================================================
  20. # 作者:guoxiaomi 脚本来自 rpg.blue
  21. #==============================================================================
  22.  
  23. module RPG
  24.   class Sprite < ::Sprite
  25.     def animation_set_sprites(sprites, cell_data, position)
  26.       # --------------------------------------------------------
  27.       # 图片文件名里包含★全图320★
  28.       # --------------------------------------------------------
  29.       if @_animation && @_animation.animation_name =~ /★全图(\d+).*★/
  30.         full_screen = true
  31.         width = 640
  32.         height = $1.to_i
  33.         y_shift = 0
  34.         if @_animation.animation_name =~ /★全图\d+YS(\d+)★/
  35.           y_shift = $1.to_i
  36.         end
  37.       else
  38.         full_screen = false
  39.       end
  40.       # --------------------------------------------------------
  41.       # 这 16 个点是动画上的单元数,最多 16 个,然后每个进行处理
  42.       for i in 0..15
  43.         sprite = sprites[i]
  44.         # cell_data[i, 0] 是该单元的图片在动画图片中的位置
  45.         pattern = cell_data[i, 0]
  46.         # 如果 patten = -1, or nil,本帧画面上不显示,处理下一个单元
  47.         # 如果 sprite == nil,处理下一个单元
  48.         if sprite == nil or pattern == nil or pattern == -1
  49.           sprite.visible = false if sprite != nil
  50.           next
  51.         end        
  52.         sprite.visible = true
  53.  
  54.         if full_screen
  55.           # --------------------------------------------------------
  56.           # 全图的情况
  57.           # --------------------------------------------------------
  58.           sprite.src_rect.set(0, pattern * height, width, height)
  59.           sprite.x = width / 2
  60.           sprite.y = height / 2 + y_shift
  61.           sprite.ox = width / 2
  62.           sprite.oy = height / 2
  63.           # 高度:位置为 上中下高度分别是 3000/1500/0(敌人背后)
  64.           # 位置为 画面 时,高度为 x 坐标* y 坐标 * 放大率
  65.           case position
  66.           when 0
  67.             sprite.z = 3000 # 普通动画上方
  68.           when 1
  69.             sprite.z = 1500 # 普通动画下方
  70.           when 2
  71.             sprite.z = 0 # 敌人下方
  72.           when 3
  73.             sprite.z = cell_data[i, 1] * cell_data[i, 2] * cell_data[i, 3] # 自定义高度
  74.           end
  75.           sprite.mirror = (cell_data[i, 5] == 1) # 镜像
  76.           sprite.opacity = cell_data[i, 6] * self.opacity / 255.0 # 透明度
  77.           sprite.blend_type = cell_data[i, 7] # 混合方式
  78.         else
  79.           # --------------------------------------------------------
  80.           # 正常的情况
  81.           # --------------------------------------------------------
  82.           # 这里找到该单元的图片在动画图片中的位置和大小                  
  83.           sprite.src_rect.set(pattern % 5 * 192, pattern / 5 * 192, 192, 192)                  
  84.           # 位置:画面的情况
  85.           if position == 3
  86.             # 无论是战斗中还是地图上,尚未发现self.viewport为nil的情况  
  87.             # self 是显示动画的 Sprite
  88.             if self.viewport != nil
  89.               # viewport存在,x 为viewport中心,y 为viewport高 - 160
  90.               sprite.x = self.viewport.rect.width / 2
  91.               sprite.y = self.viewport.rect.height - 160
  92.             else
  93.               # viewport不存在,中心设于游戏窗口中心(标准640*480)
  94.               sprite.x = 320
  95.               sprite.y = 240
  96.             end
  97.           else
  98.             # 位置:上中下的情况
  99.             # 中的情况,图片中心位置和显示动画的 Sprite中心重合
  100.             sprite.x = self.x - self.ox + self.src_rect.width / 2
  101.             sprite.y = self.y - self.oy + self.src_rect.height / 2
  102.             # 上的情况,图片上移自身 1/4 的高度
  103.             sprite.y -= self.src_rect.height / 4 if position == 0
  104.             # 下的情况,图片下移自身 1/4 的高度
  105.             sprite.y += self.src_rect.height / 4 if position == 2
  106.           end
  107.           # cell_data[i, 1] 是该单元的图片的
  108.           sprite.x += cell_data[i, 1] # x 偏移量
  109.           sprite.y += cell_data[i, 2] # y 偏移量
  110.           sprite.z = 2000 # 高度
  111.           sprite.ox = 96 # 图片的 中心 位置 x
  112.           sprite.oy = 96 # 图片的 中心 位置 y,中心位置要和画面的中心位置重合
  113.           sprite.zoom_x = cell_data[i, 3] / 100.0 # x 放大率
  114.           sprite.zoom_y = cell_data[i, 3] / 100.0 # y 放大率
  115.           sprite.angle = cell_data[i, 4] # 旋转
  116.           sprite.mirror = (cell_data[i, 5] == 1) # 镜像
  117.           sprite.opacity = cell_data[i, 6] * self.opacity / 255.0 # 透明度
  118.           sprite.blend_type = cell_data[i, 7] # 混合方式
  119.         end
  120.       end
  121.     end
  122.   end
  123. end
  124. #==============================================================================
  125. # 作者:guoxiaomi 脚本来自 rpg.blue
  126. #==============================================================================


从这个方法的构造中可以看出,方法把原来的动画图片进行了切割,并且读入数据库里的数据来控制每一帧。方法的参数是:sprites, cell_data, position。
sprites 是待修改的 sprites,这个方法利用编辑器里的设置,修改了数组 sprites 的值,在方法后面的处理中,sprites 数组里的内容进行闪烁更新,从而在图片上显示动画。
cell_data 是每一帧里的各单元设置,cell_data 是二维数组(Table),第一索引是单元的编号,第二索引是不同的设置选项,值为设置的值。
position 是动画的位置“上、中、下、画面”,这个值是整个动画共享的。

下面介绍如何改写方法:
1. 在方法的开始,读取动画的文件名,@_animation.animation_name 判断是否有特别的标记。然后根据标记,决定后面是按照正常动画播放(full_screen = false),还是特殊处理(full_screen = true)。由于某些时候 @_animation = nil,这里添加了一句避免报错。
2. 判断 full_screen 的值,正常播放的部分一个字不改,特殊处理的部分要按照约定的格式来处理。约定的格式是图片宽度为 640,且每个子图片是竖着排列的,子图片的高度也写在文件名里。
3. 按照约定,首先根据 pattern 的值设置 sprite.src_rect ,其次设置sprite的 x, y, ox, oy 四个属性;关于 z 属性,我做了一些处理,利用了编辑器里对 position 的设置,让动画位于敌人背后,普通动画背后或前方。此外,编辑器里的镜像、不透明度和混合方式是照常使用。
4. 由于本来就是全图的动画,所以编辑器里的x坐标、y坐标、缩放和旋转被弃用了。关于这些数据要怎么用起来,可以自行定义。我的用法是在 position == 3 的时候,用 x坐标、y坐标、缩放三者的乘积决定 z 属性。

三、结论
修改 animation_set_sprites 是可行的,也是各版本通用的。由于这个方法直接关系到编辑器里的数据,而且不在F11里显示,所以很少会被别的脚本修改。忽视了这个方法,也可能是一直未能突破192x192限制的原因。

四、水区原帖
无缝特效,包含了范例和Q&A

评分

参与人数 3星屑 +252 收起 理由
89444640 + 120 非常感谢。
soulsaga + 66 支持大神
MeowSnow + 66 厉害

查看全部评分

熟悉rgss和ruby,xp区版主~
正在填坑:《膜拜组传奇》讲述膜拜组和学霸们的故事。
已上steam:与TXBD合作的Reformers《变革者》
* 战斗调用公共事件 *
* RGSOS 网络脚本 *

Lv3.寻梦者

梦石
0
星屑
4120
在线时间
1892 小时
注册时间
2010-8-16
帖子
811

短篇八RM组季军

发表于 2017-3-2 19:28:44 | 显示全部楼层
大佬你看我都跪下了!!!

点评

大佬我不是基佬!我喜欢妹子!我没有不良嗜好!我是既单纯又不做作的男子汉,和外面那些妖艳贱货不一样!既然大佬执意,那我就用邮箱联系大佬吧   发表于 2017-3-2 21:47
感觉gay里gay气的,而且我不是什么dalao……邮件联系吧,我这几年已经习惯用邮件了……  发表于 2017-3-2 21:40
大佬我并没有什么机密,我就是想和你进行一些身心之间的交流,而且我觉得QQ可以很好的把我们的思路融汇贯通,还望大佬恩准!  发表于 2017-3-2 21:35
hhh~如果涉及到机密无法在论坛上公开,邮件联系我吧[email protected],我平时不上QQ。  发表于 2017-3-2 21:16
Steam页面:
http://store.steampowered.com/app/486850
https://store.steampowered.com/app/865180/
志同道合QQ&E-mail:[email protected]
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
52
在线时间
4 小时
注册时间
2017-11-26
帖子
7
发表于 2017-12-14 23:23:24 | 显示全部楼层
真厉害
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
52
在线时间
4 小时
注册时间
2017-11-26
帖子
7
发表于 2017-12-15 21:57:08 | 显示全部楼层
我想问一下,动画帧数如果超过16个咋办,能否突破帧数限制?

点评

动画帧数不是没有上限吗?  发表于 2017-12-16 11:48
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
14096
在线时间
2139 小时
注册时间
2019-1-24
帖子
1121

R考场第七期纪念奖

发表于 2019-6-8 18:36:05 | 显示全部楼层
有3个疑问请教下。
第一、原图我标记了下,标记红色点的位置是每一帧的初始位置,每张大小是640*320像素大小
第二、我在动画编辑器里面,看你制作的例子是13帧,并且是用了前13个192*192图块,我就很不理解了,不应该用我标记红点的位置,每隔3张点一下吗?
第三、我画方框的位置,因为在动画编辑器里面显示不完全,这13帧你是怎么调的?13帧都重合在左上角吗?
1 (2).png
2.png
3.png
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
3789
在线时间
1964 小时
注册时间
2013-1-3
帖子
9531
发表于 2020-4-6 23:06:35 | 显示全部楼层
今天发现的问题,战斗者有状态动画时会与全屏动画冲突
推荐把loop_animation也重新定义一下
我的做法是重新定义了update_animation
补充一下啊,挖坟什么的别在意

评分

参与人数 1+1 收起 理由
guoxiaomi + 1 我很赞同

查看全部评分

《宿愿·寻剑篇》正式版已经发布!快去看看!点击进入论坛发布贴
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

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

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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