分析完后,让我们实际操作一下,输入以下代码:
# 规定代表方向的常量
FORWARD = 0
BACK = 1
# 规定初始运行方向
direction = FORWARD
# 背景精灵
back_sprite = Sprite.new
back_bitmap = Bitmap.new("Graphics/Parallaxes/Mountains1")
back_sprite.bitmap = back_bitmap
# 人物精灵
char_sprite = Sprite.new
char_bitmap = Bitmap.new("Graphics/Characters/Actor4")
char_sprite.bitmap = char_bitmap
char_sprite.y = Graphics.height - 50
# 用于设置源矩阵的参数
x = 0
y = char_bitmap.height / 8 * 2
w = char_bitmap.width / 12
h = char_bitmap.height / 8
# 用于控制源矩阵的取像位置
index = 0
# 循环更新画面
loop do
# 更新源矩阵
char_sprite.src_rect.set(x, y, w, h)
# 改变取像位置
if direction == FORWARD # 正在向前走
index += 1
direction = BACK if index == 2
else
index -= 1
direction = FORWARD if index == 0
end
x = index * w
# 改变x坐标
char_sprite.x += 1
# 画面的更新
Graphics.update
end
运行结果:
作者: KB.Driver
时间: 2019-5-24 17:47
本帖最后由 KB.Driver 于 2019-5-24 17:52 编辑
让我们分析一下核心代码的作用。先看循环外的设置部分:
# 用于设置源矩阵的参数
x = 0
y = char_bitmap.height / 8 * 2
w = char_bitmap.width / 12
h = char_bitmap.height / 8
# 用于控制源矩阵的取像位置
index = 0
在第二课中我们知道矩形由x,y,width,height四个属性组成,因此这里的x,y,w,h就是用于下面设置源矩阵的四个参数。
我们只要打开RMVA编辑器就会知道,我们要用到的小人就是第三行的第一列至第三列。
以第一帧所需要的源矩形为例,让我们看看下面的图。
整个图片一共有八行,因此第三行的左上点的纵坐标就是位图的高度除以8乘以2(第二行的底部就是第三行的顶部),而横坐标为0。
整张图一共有8行12列,因此源矩形的宽度为位图宽度除以12,源矩形高度为位图高度除以8。
这样是不是可以看懂上面的x,y,w,h的用意了呢?
因为动画中需要让源矩形的x坐标发生变化,从而显示出人物的行走动态,我们用一个变量index记录” 帧的编号”。
下面让我们结合循环体内的代码理解index的作用。
...
# 更新源矩阵
char_sprite.src_rect.set(x, y, w, h)
# 改变取像位置
if direction == FORWARD
index += 1
direction = BACK if index == 2
else
index -= 1
direction = FORWARD if index == 0
end
x = index * w
...
前面已经讲解了xywh的作用,因此这里调用了Rect类的set方法一次性为角色精灵的源矩阵的所有属性赋值。
值得一提的是下面的条件语句部分,还记得本课第一节所讲的状态机吗?
人物行走图的动画并不是从左到右然后再次回到最左,而是左中右再到中、左这样的变化。
因此,我们需要一个状态来说明index此时应该增加还是减少。
当index为0也就是对应行走图的左时,index应该增加,而增加到index为2也就是行走图的右边那张时,index就应该转为减少了。
补充说明一句,在ruby中,if语句可以像这里一样用类似英语中“倒装句”的格式来书写,
比如
direction = BACK if index == 2这句和
if index == 2
direction = BACK
end
是完全等效的,但是通过这种倒装的写法能够让代码更加简洁。
最后,不要忘记我们操作index的目的是要改变源矩形的x。
因为不同源矩阵之间的区别仅仅是x坐标相差一个人物的宽w, 因此x与index有x = index * w的对应关系。
作者: KB.Driver
时间: 2019-5-24 17:49
本帖最后由 KB.Driver 于 2019-5-24 17:55 编辑
直到这里为止,代码的运行是没有问题的。
但是我们看着画面,就会觉得人物的行走不太自然。
实际上,这是行走图更新速度过快导致的。
我们每1帧就要改变一次人物的行走图,而人眼无法捕捉这么快的变化。
那么,只要让行走图的更新不要那么快就可以了。让我们修改代码:
# 用于控制源矩阵的取像位置
index = 0
# 缓冲,用于防止更新过快
buffer = 10
# 循环更新画面
loop do
if buffer < 10 # 每10帧改变一次行走图
buffer += 1
else
# 更新源矩阵
char_sprite.src_rect.set(x, y, w, h)
# 改变取像位置
if direction == FORWARD
index += 1
direction = BACK if index == 2
else
index -= 1
direction = FORWARD if index == 0
end
x = index * w
# 清除缓冲
buffer = 0
end
# 改变x坐标
char_sprite.x += 1
# 画面的更新
Graphics.update
end
运行结果:
在这里,我们引入了一个缓冲变量buffer。
每次更新行走图后,buffer的值会变为0。
而当buffer的值小于10的时候,条件语句会让buffer增加1,而不执行下面的行走图改变。
这样就可以达到每过10帧才更新一次行走图的效果,避免了更新速度太快而肉眼无法跟上的问题。
有能力的同学可以尝试完成课后练习2。
注意,本练习有一定的难度和代码工作量。
作者: KB.Driver
时间: 2019-5-24 17:50
本帖最后由 KB.Driver 于 2019-5-24 17:59 编辑
3.5 其他精灵属性的动画演示
除了前面所演示的几种典型的动画,还有大量精灵Sprite类的属性可以加入动画中。
由于这些属性在第一课中已经有所介绍,下面直接以范例的形式给出,不再花大篇幅讲解。
在体会的过程中,可以改变代码中的部分参数来观察动画的变化。
有余力的同学可以完成课后练习3。
1、可见属性变化(闪烁)
back_sprite = Sprite.new
back_bitmap = Bitmap.new("Graphics/Parallaxes/Mountains1")
back_sprite.bitmap = back_bitmap
sprite1 = Sprite.new
sprite1.bitmap = Bitmap.new("Graphics/Battlers/Fanatic")
sprite1_desc = Sprite.new
sprite1_desc.bitmap = Bitmap.new(400, 26)
sprite1_desc.bitmap.draw_text(0,0,400,26,"sprite.visible = !sprite.visible")
# 循环更新画面
loop do
sprite1.visible = !sprite1.visible
# 画面的更新
Graphics.update
end
作者: KB.Driver
时间: 2019-5-24 17:53
本帖最后由 KB.Driver 于 2019-5-24 17:58 编辑
2、放大倍率的变化
back_sprite = Sprite.new
back_bitmap = Bitmap.new("Graphics/Parallaxes/Mountains1")
back_sprite.bitmap = back_bitmap
sprite1 = Sprite.new
sprite1.bitmap = Bitmap.new("Graphics/Battlers/Slime")
sprite1_desc = Sprite.new
sprite1_desc.bitmap = Bitmap.new(300, 26)
sprite1_desc.bitmap.draw_text(0,0,300,26,"sprite1.zoom_x += 0.02")
sprite2 = Sprite.new
sprite2.bitmap = Bitmap.new("Graphics/Battlers/Slime")
sprite2.x = 280
sprite2_desc = Sprite.new
sprite2_desc.bitmap = Bitmap.new(300, 26)
sprite2_desc.bitmap.draw_text(0,0,300,26,"sprite2.zoom_y += 0.02")
sprite2_desc.x = 280
frames = 0
speed = 0.02
rate = 1
# 循环更新画面
loop do
if frames > 29
rate *= -1
frames = 0
end
sprite1.zoom_x += speed * rate
sprite2.zoom_y += speed * rate
frames += 1
# 画面的更新
Graphics.update
end
作者: KB.Driver
时间: 2019-5-24 17:55
本帖最后由 KB.Driver 于 2019-5-24 17:58 编辑
3、角度的变化(旋转)
back_sprite = Sprite.new
back_bitmap = Bitmap.new("Graphics/Parallaxes/Mountains1")
back_sprite.bitmap = back_bitmap
sprite1 = Sprite.new
sprite1.bitmap = Bitmap.new("Graphics/Battlers/Mimic")
sprite1.x = 150
sprite1.y = 150
sprite1_desc = Sprite.new
sprite1_desc.bitmap = Bitmap.new(300, 26)
sprite1_desc.bitmap.draw_text(0,0,300,26,"原点在左上")
sprite2 = Sprite.new
sprite2.bitmap = Bitmap.new("Graphics/Battlers/Mimic")
sprite2.x = 400
sprite2.y = 100
sprite2.ox = sprite2.bitmap.width / 2
sprite2.oy = sprite2.bitmap.height / 2
sprite2_desc = Sprite.new
sprite2_desc.bitmap = Bitmap.new(300, 26)
sprite2_desc.bitmap.draw_text(0,0,300,26,"原点在中心")
sprite2_desc.x = 280
# 循环更新画面
loop do
sprite1.angle += 3
sprite2.angle += 3
# 画面的更新
Graphics.update
end
作者: KB.Driver
时间: 2019-5-24 17:56
本帖最后由 KB.Driver 于 2019-5-24 18:00 编辑
4、不透明度的变化(隐现)
back_sprite = Sprite.new
back_bitmap = Bitmap.new("Graphics/Parallaxes/Mountains1")
back_sprite.bitmap = back_bitmap
sprite1 = Sprite.new
sprite1.bitmap = Bitmap.new("Graphics/Battlers/Vampire")
sprite1.x = 20
sprite1.opacity = 0
sprite2 = Sprite.new
sprite2.bitmap = Bitmap.new("Graphics/Battlers/Vampire")
sprite2.x = 290
sprite2.mirror = true
frames = 0
speed = 5
rate = 1
# 循环更新画面
loop do
if frames > 51
rate *= -1
frames = 0
end
sprite1.opacity += speed * rate
sprite2.opacity -= speed * rate
frames += 1
# 画面的更新
Graphics.update
end
作者: KB.Driver
时间: 2019-5-24 17:59
本帖最后由 KB.Driver 于 2019-5-24 18:01 编辑
5、颜色叠加的变化
back_sprite = Sprite.new
back_bitmap = Bitmap.new("Graphics/Parallaxes/Mountains1")
back_sprite.bitmap = back_bitmap
sprite1 = Sprite.new
sprite1.bitmap = Bitmap.new("Graphics/Battlers/Windspirit")
frames = 0
speed = 3
rate = 1
alpha = 0
# 循环更新画面
loop do
if frames > 85
rate *= -1
frames = 0
end
sprite1.color.set(rand(255), rand(255), rand(255), alpha)
alpha += speed * rate
frames += 1
# 画面的更新
Graphics.update
end
作者: KB.Driver
时间: 2019-5-24 18:00
本帖最后由 KB.Driver 于 2019-5-24 18:05 编辑
6、色调的变化
back_sprite = Sprite.new
back_bitmap = Bitmap.new("Graphics/Parallaxes/Mountains1")
back_sprite.bitmap = back_bitmap
bitmap = Bitmap.new("Graphics/Battlers/Priest")
sprites = Array.new(3){Sprite.new}
sprites.size.times do |i|
sprites[ i ].x = i * 170 - 45
sprites[ i ].y = -20
sprites[ i ].z = 1
sprites[ i ].bitmap = bitmap
end
frames = 0
speed = 5
rate = 1
value = 0
# 循环更新画面
loop do
if frames > 51
rate *= -1
frames = 0
end
sprites[0].tone.set(value, 0, 0)
sprites[1].tone.set(0, value, 0)
sprites[2].tone.set(0, 0, value)
value += speed * rate
frames += 1
# 画面的更新
Graphics.update
end
(不要问我为什么中括号里要加空格,论坛傻乎乎地把数组的第i项[ i ]当做斜体标志看待了……)
作者: KB.Driver
时间: 2019-5-24 18:01
施工中&
作者: KB.Driver
时间: 2019-5-24 18:07
课后练习:
练习1 加速度
利用3.2节所学知识,结合F1文档的Sprite内容,制作以下动画。
妖精从画面左侧出发,方向向右,初速度为1,加速度为0.25。
触碰画面右端后,妖精改为面朝左侧,以初速度为1、加速度为0.25向左出发。
在触碰画面左端后,再次改为面朝右侧,回到初始状态,循环往复。
使用素材(RTP):
"Graphics/ Parallaxes/ Mountains1"
"Graphics/Battlers/ Fairy"
提示:
1、 精灵朝向的改变参考Sprite的mirror属性
2、 要避免精灵加速后跑出画面,可以用条件判断,也可以用取最大最小值的方式加以限制。
例如:x = [ x + 1, 100].min 可以让x变为x+1和100之间的最小值,从而避免让x超出100。
同理,x = [x – 1, 0].max可以让x在变小的过程中不小于0。
作者: KB.Driver
时间: 2019-5-24 18:08
练习2 状态与动画(有一定难度)
利用3.3和3.4节所学知识,制作以下动画。
人物初始位置(50,300),向右移动,速度为4,前进25帧。
随后人物暂停,敌人不透明度减半,并在敌人位置显示斩击动画。
动画显示完后,敌人不透明度恢复,人物向左移动,速度为2,前进50帧。之后循环往复进行。
使用素材(RTP):
" Graphics/Battlebacks1/Grassland"
" Graphics/Battlebacks2/Grassland"
"Graphics/Characters/Actor1"
"Graphics/Battlers/Slime"
"Graphics/Animations/Sword1"
提示:
1、 人物的行走需要一个状态,人物的朝向需要一个状态,人物在行走还是在静止需要一个状态。需要先设计好条件的结构。
2、 Animation动画的演示与行走图的src_rect改变原理相同,需要运用所学知识进行推广。
3、 为了确认动画在敌人身上演示,建议将敌人精灵和动画精灵的ox与oy设置为位图中心,随后将动画精灵的x与y设置为与敌人精灵相同的数值。
作者: KB.Driver
时间: 2019-5-24 18:09
练习3 伪•标题画面
利用本课所学知识,制作以下动画。
初始状态下,塔的远景不可见,塔的近景在y方向上拉长为2倍,不透明度为0。
随后塔的近景以每帧4像素的速度向上移动,不透明度以每帧5点的速度增加。
当塔的近景不透明度达到最大值255后,塔的远景变为可见,塔的近景继续以每帧4像素向上移动,不透明度以每帧5点的速度减少。
塔的近景完全不可见后,标题文字“通天塔”以从左向右遮罩的方式出现,显示速度为4像素每帧。
标题字体微软雅黑,字号72,位置约(175,80)。
待标题遮罩完成,下方三个选项依次淡入,三个选项字体微软雅黑,字号32,位置约为(90,320),(240,320),(390,320)。
选项全部淡入完成后,人物精灵变为可见,以3.3节所学方式面朝向下行走,同时“新游戏”选项的横、纵向缩放比例变为1.2。
使用素材(RTP):
"Graphics/Titles1/Tower1"
"Graphics/Titles1/Tower2"
"Graphics/Characters/Actor4"
提示:
1、 预先规划好状态机如何设置。
2、 标题精灵的遮罩进入可以用src_rect达成。初始状态src_rect.width = 0,而后令其循环增加。
欢迎光临 Project1 (https://rpg.blue/) |
Powered by Discuz! X3.1 |