| 赞 | 402 |
| VIP | |
| 好人卡 | |
| 积分 | 251 |
| 经验 | |
| 最后登录 | 2024-7-2 |
| 在线时间 | 3339 小时 |
- 梦石
- 1
- 星屑
- 24088
- 在线时间
- 3339 小时
- 注册时间
- 2011-7-8
- 回帖
- 3862

|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有账号?注册会员
×
本帖最后由 guoxiaomi 于 2017-3-3 11:54 编辑
一、 动机和背景
主要动机是 @89444640 在水区里的“无缝特效”主题,提到RMXP的动画图块只能是192x192大小,无法展示更高清晰度的动画。
@soulsaga 提出了解决方案的关键是修改:
[pre lang="ruby"]sprite.src_rect.set(pattern % 5 * 192, pattern / 5 * 192, 192, 192)[/pre]
在得到这一提示之后我找到了这一行的代码在脚本中的位置是在 RPG::Sprite 的 animation_set_sprites(sprites, cell_data, position) 方法内,此方法用于获取每一帧展示动画的内容。从这里着手修改就可以突破192x192的限制。但是无法对编辑器进行修改,所以编辑器里看上去是乱的。
在解决这个问题后,我在6R上搜索“动画 大小”。截至目前可以看到有14个主题,时间跨度从2006年一直到2016年。大部分主题的解决方案是多图拼合,但是2016年的主题“如何调整技能动画默认读取的大小”中 @魔法丶小肉包 在 2 楼给出了同样的思路。
所以在 VA 修改 animation_set_sprites 是可行的,这也是主题为通用发布的原因。
二、解决方案
先上脚本,在给说明,本脚本只是 XP 适用:
[pre lang="ruby"]#==============================================================================
# 全图动画 (突破 RMXP 动画 192 * 192 限制)
#==============================================================================
# 用法:
# 1. 动画图片设置:
# 1.1 宽度 640
# 1.2 所有的子图片竖着排列
# 1.3 图片名包含 ★全图320★ 这里 320 是单张高度值
# 1.4 图片名包含 ★全图320YS160★ 则播放的动画会向下移动 160 像素
# 2. 数据库动画设置
# 2.1 选择一帧,添加一个单元
# 2.2 位置:上 在正常动画上方(z=3000);
# 位置:中 在正常动画下方(z=1500)
# 位置:下 在敌人下方(z=0);
# 位置:画面 z = x 坐标* y 坐标 * 放大率
# 2.3 式样:此帧播放的子图片位置
# 2.4 左右反转、不透明度和合成方式可以正常使用
# 2.5 X坐标、Y坐标、放大率、旋转角度不可以正常使用
#==============================================================================
# 作者:guoxiaomi 脚本来自 rpg.blue
#==============================================================================
module RPG
class Sprite < ::Sprite
def animation_set_sprites(sprites, cell_data, position)
# --------------------------------------------------------
# 图片文件名里包含★全图320★
# --------------------------------------------------------
if @_animation && @_animation.animation_name =~ /★全图(\d+).*★/
full_screen = true
width = 640
height = $1.to_i
y_shift = 0
if @_animation.animation_name =~ /★全图\d+YS(\d+)★/
y_shift = $1.to_i
end
else
full_screen = false
end
# --------------------------------------------------------
# 这 16 个点是动画上的单元数,最多 16 个,然后每个进行处理
for i in 0..15
sprite = sprites
# cell_data[i, 0] 是该单元的图片在动画图片中的位置
pattern = cell_data[i, 0]
# 如果 patten = -1, or nil,本帧画面上不显示,处理下一个单元
# 如果 sprite == nil,处理下一个单元
if sprite == nil or pattern == nil or pattern == -1
sprite.visible = false if sprite != nil
next
end
sprite.visible = true
if full_screen
# --------------------------------------------------------
# 全图的情况
# --------------------------------------------------------
sprite.src_rect.set(0, pattern * height, width, height)
sprite.x = width / 2
sprite.y = height / 2 + y_shift
sprite.ox = width / 2
sprite.oy = height / 2
# 高度:位置为 上中下高度分别是 3000/1500/0(敌人背后)
# 位置为 画面 时,高度为 x 坐标* y 坐标 * 放大率
case position
when 0
sprite.z = 3000 # 普通动画上方
when 1
sprite.z = 1500 # 普通动画下方
when 2
sprite.z = 0 # 敌人下方
when 3
sprite.z = cell_data[i, 1] * cell_data[i, 2] * cell_data[i, 3] # 自定义高度
end
sprite.mirror = (cell_data[i, 5] == 1) # 镜像
sprite.opacity = cell_data[i, 6] * self.opacity / 255.0 # 透明度
sprite.blend_type = cell_data[i, 7] # 混合方式
else
# --------------------------------------------------------
# 正常的情况
# --------------------------------------------------------
# 这里找到该单元的图片在动画图片中的位置和大小
sprite.src_rect.set(pattern % 5 * 192, pattern / 5 * 192, 192, 192)
# 位置:画面的情况
if position == 3
# 无论是战斗中还是地图上,尚未发现self.viewport为nil的情况
# self 是显示动画的 Sprite
if self.viewport != nil
# viewport存在,x 为viewport中心,y 为viewport高 - 160
sprite.x = self.viewport.rect.width / 2
sprite.y = self.viewport.rect.height - 160
else
# viewport不存在,中心设于游戏窗口中心(标准640*480)
sprite.x = 320
sprite.y = 240
end
else
# 位置:上中下的情况
# 中的情况,图片中心位置和显示动画的 Sprite中心重合
sprite.x = self.x - self.ox + self.src_rect.width / 2
sprite.y = self.y - self.oy + self.src_rect.height / 2
# 上的情况,图片上移自身 1/4 的高度
sprite.y -= self.src_rect.height / 4 if position == 0
# 下的情况,图片下移自身 1/4 的高度
sprite.y += self.src_rect.height / 4 if position == 2
end
# cell_data[i, 1] 是该单元的图片的
sprite.x += cell_data[i, 1] # x 偏移量
sprite.y += cell_data[i, 2] # y 偏移量
sprite.z = 2000 # 高度
sprite.ox = 96 # 图片的 中心 位置 x
sprite.oy = 96 # 图片的 中心 位置 y,中心位置要和画面的中心位置重合
sprite.zoom_x = cell_data[i, 3] / 100.0 # x 放大率
sprite.zoom_y = cell_data[i, 3] / 100.0 # y 放大率
sprite.angle = cell_data[i, 4] # 旋转
sprite.mirror = (cell_data[i, 5] == 1) # 镜像
sprite.opacity = cell_data[i, 6] * self.opacity / 255.0 # 透明度
sprite.blend_type = cell_data[i, 7] # 混合方式
end
end
end
end
end
#==============================================================================
# 作者:guoxiaomi 脚本来自 rpg.blue
#==============================================================================
[/pre]
从这个方法的构造中可以看出,方法把原来的动画图片进行了切割,并且读入数据库里的数据来控制每一帧。方法的参数是: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 |
评分
-
查看全部评分
|