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

Project1

 找回密码
 注册会员
搜索
查看: 4994|回复: 11
打印 上一主题 下一主题

[原创发布] 日历的RGSS3入门教程 - 精灵与位图Lv2 初识位图与矩形

[复制链接]

Lv5.捕梦者

梦石
10
星屑
39440
在线时间
1914 小时
注册时间
2010-11-14
帖子
3315

R考场第七期纪念奖

跳转到指定楼层
1
发表于 2019-3-17 12:27:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 KB.Driver 于 2019-5-24 18:11 编辑

上一课: 日历的RGSS3入门教程 - 精灵与位图Lv1 初识精灵


精灵与位图Lv2 初识位图与矩形
课程难度:★★☆☆☆ 沙包
涉及的RGSS知识:
类:Sprite,Bitmap,Rect, Color ,Font
模块:Graphics
其他:F1文档的基础使用
涉及的Ruby知识:实例方法



上一课中,我们认识了怎样从路径中读取图像到位图,再将位图交给精灵以显示在屏幕上。
与此同时,为了获得显示的效果,我们学习了精灵的不少属性。这次我们将开始进入位图与矩形的学习。
矩形(Rect)是RGSS中与精灵(Sprite)和位图(Bitmap)密不可分的一个数据对象。
正如它的名字所说,它所有的属性都是为了描述一个数学上的长方形而存在的。
在数学中要确定一个长方形有很多方法,例如确定长方形的三个点等,这里就不一一列举了。
RGSS中的矩形一共只有4个属性,分别是横纵坐标x与y和宽度width、高度height。
为了更好地理解矩形,让我们看一看矩形在Photoshop中的表现形式。


当我们用矩形工具随便一拉,信息就会显示四个数据,分别是矩形左上角那一点的x,y坐标和矩形的宽度高度。
在RGSS中,矩形也是靠这四个数据来吃饭的。

下一课:日历的RGSS3入门教程 - 精灵与位图Lv3 精灵更新与状态机

评分

参与人数 6+6 收起 理由
miantouchi + 1 精品文章
百里_飞柳 + 1 精品文章
真·可乐 + 1 精品文章
Mayaru + 1 精品文章
RMVXA + 1 精品文章
Nil2018 + 1 精品文章

查看全部评分

用头画头像,用脚写脚本

Lv5.捕梦者

梦石
10
星屑
39440
在线时间
1914 小时
注册时间
2010-11-14
帖子
3315

R考场第七期纪念奖

2
 楼主| 发表于 2019-3-17 12:28:38 | 只看该作者
本帖最后由 KB.Driver 于 2019-3-17 12:31 编辑

这一次,我们继续来用精灵和位图绘制场景,首先,我们输入以下代码。

# 背景精灵
back_sprite = Sprite.new
back_bitmap = Bitmap.new("Graphics/Battlebacks1/Cobblestones1")
back_sprite.bitmap = back_bitmap
# 女英雄精灵
heroine_sprite = Sprite.new
heroine_bitmap = Bitmap.new("Graphics/Battlers/Hero_f")
heroine_sprite.bitmap = heroine_bitmap
heroine_sprite.x = Graphics.width - heroine_sprite.width
heroine_sprite.y = Graphics.height - heroine_sprite.height - 100
# 敌人精灵
enemy_sprite = Sprite.new
enemy_bitmap = Bitmap.new("Graphics/Battlers/Rat")
enemy_sprite.bitmap = enemy_bitmap
enemy_sprite.y = Graphics.height - enemy_sprite.height - 100
# 只更新图像
rgss_stop


运行结果:


像上次一样,我们生成了几个精灵的实例,并将它们显示在了屏幕上。
我们先分析一下这份代码中陌生的部分。

heroine_sprite.x = Graphics.width - heroine_sprite.width
heroine_sprite.y = Graphics.height - heroine_sprite.height - 100


Graphics是RGSS中的一个模块。
模块用最浅显的话来说就是一个知识版权受保护的图书馆,它里面有着我们所需要的某些关键的信息。
模块与类最大的不同之处在于模块无法产生实例,也就是这个图书馆不允许被仿造。
所有想要得到图书馆服务的人都必须打上图书馆的名字,表示他的服务来自于这个图书馆。

在这两句代码中我们用到了Graphics模块的width与height两个方法。
由于前面所说的原因,模块这个“图书馆”无法“被复制”(无法生成实例),因此在调用方法时我们直接写Graphics这个模块的名字。

Graphics.width是整个游戏画面的宽度,Graphics.height是整个游戏画面的高度。
这两个属性的默认值分别是544和416,但是尽量不要直接用这两个数字。
一方面,如果某一天因为特殊原因而改变了游戏画面的大小,每一个你所写的数字都必须由你手动修改。
另一方面,Graphics.width比544更能看出代码中这个数据的用途,方便日后阅读与拓展。

heroine_sprite.x = Graphics.width - heroine_sprite.width
这句代码的意思十分明确,就是让heroine_sprite出现在屏幕的最右端。
因为精灵的原点ox默认在精灵的最左侧,所以x值必须在画面宽度的基础上减去精灵占用的宽度,这样精灵的右侧就会贴住画面右侧。

heroine_sprite.y = Graphics.height - heroine_sprite.height - 100
后面一句则是让heroine_sprite在贴住画面下侧的基础上,往上方平移100像素。

让精灵贴边在后面的程序编写中会经常碰到,应当牢牢地记住这种用法。

用头画头像,用脚写脚本
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
10
星屑
39440
在线时间
1914 小时
注册时间
2010-11-14
帖子
3315

R考场第七期纪念奖

3
 楼主| 发表于 2019-3-17 12:29:38 | 只看该作者
本帖最后由 KB.Driver 于 2019-3-17 12:35 编辑



回到运行结果,虽然女英雄和大老鼠都站在了石头路上,
但美中不足的是,这只大老鼠似乎并没有看向女英雄,画面上看不出战斗的态势。
我们应该想办法让大老鼠“回头”看右边,这就需要将老鼠的精灵镜像翻转一下。

# 敌人精灵
...
enemy_sprite.mirror = true # 让精灵左右翻转(默认值:false)
rgss_stop


运行结果:


好了,现在我们的女英雄与大老鼠四目相对,随时可能开打。
虽然战斗场景已经搭建了出来,石头路似乎缺少了战斗场景应有的紧张感。我们试着换一个背景。

# 背景精灵
back_sprite = Sprite.new
back_bitmap = Bitmap.new("Graphics/Battlebacks1/Cobblestones1")
back_bitmap2 = Bitmap.new("Graphics/Battlebacks1/Ruins2")
back_sprite.bitmap = back_bitmap #把原来这一行删掉,写成下面的
back_sprite.bitmap = back_bitmap2
...


运行结果:


好了,现在战斗场景变成了荒郊野岭。


用头画头像,用脚写脚本
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
10
星屑
39440
在线时间
1914 小时
注册时间
2010-11-14
帖子
3315

R考场第七期纪念奖

4
 楼主| 发表于 2019-3-17 12:31:53 | 只看该作者
本帖最后由 KB.Driver 于 2019-3-17 12:38 编辑

不过,女英雄独自来到这种地方多危险啊,如果只是在城镇与郊外的交界处还好。
为了营造出交界线的效果,我们需要把女英雄所在的半边地板变回城镇的石头路。

在此之前,我们显示位图都是直接把整个位图搬上屏幕,现在要只把半边位图画出来,就不得不依靠前面所说的矩形了。
我们需要的效果是背景只有右半边变成以前的石头路,因此我们可以把石头路位图的右半边“复制”到郊外位图的右半边来。

这里我们第一次要用到实例方法,我先解释一下。
之前我们在学习精灵Sprite类时,都是通过设置Sprite的属性来达到目标。
实例方法顾名思义,就是在实例身上调用的方法。
相比于直接设置属性,方法的作用主要是通过方法内进行的计算帮助我们获取信息或者间接地设置属性。
这里我们使用Bitmap实例的blt方法,让我们输入下面的代码。

# 背景精灵
back_sprite = Sprite.new
back_bitmap = Bitmap.new("Graphics/Battlebacks1/Cobblestones1")
back_bitmap2 = Bitmap.new("Graphics/Battlebacks1/Ruins2")
# 准备复制的矩形
blt_rect = back_bitmap2.rect # 每个位图对象都有自己的矩形rect属性
blt_rect.width /= 2 # 将复制来的矩形rect的宽度减半
# 复制位图
back_bitmap.blt(0, 0, back_bitmap2, blt_rect)
back_sprite.bitmap = back_bitmap2 #删除这一行,改成下面的
back_sprite.bitmap = back_bitmap

# 女英雄精灵
...


运行结果:


这里我们用到了位图的矩形rect属性,这是一个x与y都为0,宽度width与高度height刚好与位图相同的矩形。
通过位图的rect属性我们可以快速地构建一个与位图相关的矩形,比如在这里,
我们将位图的矩形赋值给用于blt方法的blt_rect,然后将矩形的宽度变为一半,这样blt所复制过去的部分将只有src_bitmap的左半边。
用头画头像,用脚写脚本
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
10
星屑
39440
在线时间
1914 小时
注册时间
2010-11-14
帖子
3315

R考场第七期纪念奖

5
 楼主| 发表于 2019-3-17 12:35:09 | 只看该作者
本帖最后由 KB.Driver 于 2019-3-17 12:41 编辑

在详细解释位图Bitmap类的实例方法blt之前,我们来学一下怎样查看RGSS3的F1文档。
F1文档的中文翻译可以在VA讨论区的图书馆中找到。



打开F1文档,我们选择RGSS参考→游戏库→RGSS内建类→Bitmap



在Bitmap类中,我们可以在方法里找到文档中对于blt的说明是这样的:


这里解释一下如何看懂这一段文档。
blt出现在Bitmap的“方法”中,代表这是Bitmap的实例方法,只能在Bitmap的实例上调用。
blt后面的括号代表这个方法需要接受参数,并且这些参数分别是x,y,src_bitmap,src_rect还有一个中括号框起来的opacity。
中括号框起来的参数为可选参数,在使用该方法时可以提供也可以省略。
而前面的参数都是必须提供的,否则会导致参数错误(ArgumentError),使用时必须注意。

下面的说明告诉我们这个方法的用途,用大白话说就是:
把另一个位图src_bitmap中位于矩形src_rect里的部分复制到调用blt方法的位图上,放置的位置由前两个参数x,y决定。




怎么样,有没有感觉到矩形的重要用途?
用头画头像,用脚写脚本
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
10
星屑
39440
在线时间
1914 小时
注册时间
2010-11-14
帖子
3315

R考场第七期纪念奖

6
 楼主| 发表于 2019-3-17 12:38:35 | 只看该作者
本帖最后由 KB.Driver 于 2019-3-17 12:43 编辑



回到运行结果上来。
虽然场地是隔开了,但是中间的交界处却有着明显的不协调感。
我们希望把中间的交界处给盖住。
这一次,我们可以从F1手册中寻找这样的方法。经过一番搜寻,我们发现了fill_rect方法。



fill_rect方法可以在调用它的位图的某个矩形内填满指定的颜色,我们要盖住中间的交界线,
可以选择把位图宽度一半的位置左边1像素开始,宽度为3像素,高度与位图相等的矩形填满黑色。
注意,fill_rect所能填充的范围不会超过位图的大小。
目前我们还不清楚怎样设置颜色为黑色,因此我们点进说明里蓝色的Color链接一看究竟。



在方法的括号后面,每一个单词是一个参数,调用方法时必须传入相应数量的参数。
注意最后一个用中括号包围的[, alpha],它表示不透明度alpha这个参数是可以省略的。
F1文档告诉我们,要生成一个颜色Color类的实例至少需要我们指定这个颜色的RGB值即红red、绿green、蓝blue。

黑色的RGB值均为0,而不透明度为255,所以我们要生成的Color就是Color.new(0,0,0)。
F1文档已经说了,只要指定了RGB值,省略不透明度时将使用255。

# 复制位图
back_bitmap.blt(0, 0, back_bitmap2, blt_rect)
# 盖住中间的交界线
color = Color.new(0,0,0) # 纯黑
back_bitmap.fill_rect(blt_rect.width - 1, 0, 3, blt_rect.height, color)
back_sprite.bitmap = back_bitmap

# 女英雄精灵
...


运行结果:

用头画头像,用脚写脚本
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
10
星屑
39440
在线时间
1914 小时
注册时间
2010-11-14
帖子
3315

R考场第七期纪念奖

7
 楼主| 发表于 2019-3-17 12:41:07 | 只看该作者
本帖最后由 KB.Driver 于 2019-3-17 12:50 编辑

好了,这样一来分界线就被遮住了。
然而,一道黑线在中线也不是特别美观,如果是往两边渐变的黑色,视觉效果可能更好。
我们找到F1文档中的gradient_fill_rect方法,它与fill_rect类似,只不过需要我们设置两种颜色以便产生渐变。


我们设置渐变的颜色分别为纯黑Color.new(0,0,0)与透明Color.new,修改之前的代码。

...
# 盖住中间的交界线
color = Color.new(0,0,0) # 纯黑
color1 = Color.new # 透明色
gradient_width = 20 # 渐变的单边宽度
rect = Rect.new(blt_rect.width - gradient_width, 0, gradient_width, blt_rect.height) # 左半边渐变的矩形
back_bitmap.gradient_fill_rect(rect, color1, color) # 左半边渐变是由透明到纯黑
rect.x += gradient_width # 调整起始x坐标,变为右半边渐变的矩形
back_bitmap.gradient_fill_rect(rect, color, color1) # 右半边渐变是由纯黑到透明
back_bitmap.fill_rect(blt_rect.width - 1, 0, 3, blt_rect.height, color)

back_sprite.bitmap = back_bitmap
# 女英雄精灵
...


运行结果:


咦,不应该是渐变吗?为什么是纯黑的呢?
大家还记得上一课我们一开始显示男神的时候吗,游戏的背景本来就是全黑的.
因此当我们给背景涂上哪怕是透明度很低的黑色,它与背景的黑色一结合就成了纯黑。
这时候,我们就需要增加一个新的精灵来承载这段渐变了,否则背景本身就会被破坏掉。

修改代码:

# 复制位图
back_bitmap.blt(0, 0, back_bitmap2, blt_rect)
# 盖住中间的交界线
#color = Color.new(0,0,0) # 纯黑
#color1 = Color.new # 透明
#gradient_width = 20 # 渐变的单边宽度
#rect = Rect.new(blt_rect.width - gradient_width, 0, gradient_width, blt_rect.height) # 左半边渐变的矩形
#back_bitmap.gradient_fill_rect(rect, color1, color) # 左半边渐变是由透明到纯黑
#rect.x += gradient_width # 调整起始x坐标,变为右半边渐变的矩形
#back_bitmap.gradient_fill_rect(rect, color, color1) # 右半边渐变是由纯黑到透明
# back_bitmap.fill_rect(blt_rect.width - 1, 0, 3, blt_rect.height, color)

back_sprite.bitmap = back_bitmap
# 黑色渐变精灵
gradient_sprite = Sprite.new
# 盖住中间的交界线
color = Color.new(0,0,0) # 纯黑
color1 = Color.new # 透明
gradient_width = 20 # 渐变的单边宽度
gradient_bitmap = Bitmap.new(gradient_width * 2, blt_rect.height)
rect = gradient_bitmap.rect
rect.width /= 2
gradient_bitmap.gradient_fill_rect(rect, color1, color) # 左半边渐变是由透明到纯黑
rect.x += rect.width
gradient_bitmap.gradient_fill_rect(rect, color, color1) # 右半边渐变是由纯黑到透明
gradient_sprite.bitmap = gradient_bitmap
gradient_sprite.x = blt_rect.width - gradient_width

# 女英雄精灵
...

用头画头像,用脚写脚本
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
10
星屑
39440
在线时间
1914 小时
注册时间
2010-11-14
帖子
3315

R考场第七期纪念奖

8
 楼主| 发表于 2019-3-17 12:44:24 | 只看该作者
本帖最后由 KB.Driver 于 2019-3-17 12:52 编辑

运行结果:


在这里,我们通过Bitmap.new(width, height)自己生成了一个宽度为width,高度为height的位图实例。
这个位图和前面我们从文件路径中读取的不一样,它的每个像素都是透明的,因此需要我们自己对它进行绘制。
我们把之前在back_bitmap上绘制失败的代码转移到这里,最后调整渐变精灵gradient_sprite的横坐标,就达到了我们需要的效果。

最后,让我们在画面中间增加一个“VS”的文字,让这场战斗更加白热化吧。
查过F1文档,draw_text方法可以满足我们的需要。
另外,为了知道这个自定义位图的大小,我们需要Bitmap实例的text_size方法。
两个方法的文档说明可以参考下图。



接下来,我们再生成一个文字精灵和一个文字位图,用来在渐变之上显示“VS”。

# 盖住中间的交界线
...
gradient_sprite.bitmap = gradient_bitmap
gradient_sprite.x = blt_rect.width - gradient_width
# VS文字精灵
text_sprite = Sprite.new
text_bitmap = Bitmap.new(1, 1) # 先生成一个最小的位图,用于调用text_size方法
text_size = text_bitmap.text_size("VS") # text_size是一个矩形(Rect)对象
text_size.width += 4
text_size.height += 4 # F1文档说明,测量的大小不包括文字边框,因此拓宽4像素备用
text_bitmap = Bitmap.new(text_size.width, text_size.height) # 重新生成合适的位图
text_bitmap.draw_text(text_size, "VS")
text_sprite.bitmap = text_bitmap
# 文字精灵居中
text_sprite.ox = text_sprite.width / 2
text_sprite.oy = text_sprite.height / 2
text_sprite.x = Graphics.width / 2
text_sprite.y = Graphics.height / 2


这里解释一下所做的工作。
位图在生成时必须指定大小,但是我们一开始并不知道绘制“VS”两个字母需要多大的位图。
而且即使我们知道了,万一以后更换了游戏字体,这个数值又会改变。
因此我们需要先通过生成一个Bitmap实例,调用它的text_size方法来知道我们需要多大的位图。

text_size方法会返回一个矩形,矩形的宽与高就是我们需要的位图大小,因此我们重新根据测量好的大小生成text_bitmap。
注意,F1文档已经说明这个测量的大小不包括轮廓,因此我们将矩形的宽与高事先拓展4像素以防万一。

生成位图后,draw_text就像之前fill_rect一样,我们要指定矩形与绘制内容。
只不过这次的绘制内容不是颜色,而是一个字符串”VS”。
最后,我们调整文字精灵的位置,将其置于画面的正中心。
将精灵的ox与oy调整为位图宽度与高度的一半后,精灵的原点就是位图的中心。
再把原点变化后的精灵的x与y分别设为画面宽度与高度的一半,这样位图的中心就到达了画面的中心。



用头画头像,用脚写脚本
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
10
星屑
39440
在线时间
1914 小时
注册时间
2010-11-14
帖子
3315

R考场第七期纪念奖

9
 楼主| 发表于 2019-3-17 12:49:22 | 只看该作者
本帖最后由 KB.Driver 于 2019-3-17 12:55 编辑

运行结果:


毫无疑问,这个“VS”实在是太小了。
通过查阅F1,我们得知Bitmap有字体font属性,我们可以在绘制前修改这个字体font的大小size。
不要忘记把绘制前测量大小的临时位图也赋予同样的字体。

# VS文字精灵
text_sprite = Sprite.new
fontsize = 64 # 字体大小
text_bitmap = Bitmap.new(1, 1) # 先生成一个最小的位图,用于调用text_size方法
text_bitmap.font.size = fontsize
text_size = text_bitmap.text_size("VS") # text_size是一个矩形(Rect)对象
...
text_bitmap = Bitmap.new(text_size.width, text_size.height) # 重新生成合适的位图
text_bitmap.font.size = fontsize
...
# 文字精灵居中
...


运行结果:


好了,到此我们回顾一下这堂课所讲的内容。

一、
        矩形(Rect)被广泛运用于精灵(Sprite)与位图(Bitmap)中,
它一共有x,y,宽度width,高度height四个属性。

二、
        一个位图(Bitmap)可以通过blt方法把其他位图src_bitmap上某个矩形src_rect内的数据
复制到自己以x,y为左上顶点的范围里。

三、
        除了读取文件路径,还可以通过指定宽度width与高度height用Bitmap.new(width,height)生成指定大小的空白位图。
这个空白位图需要我们自己调用位图的各种绘制方法来为它添加内容。

四、
        常见的位图的绘制方法包括blt(用其他位图填充),fill_rect(用纯色填充矩形),
gradient_fill_rect(用指定的两种颜色渐变填充矩形),draw_text(用文字填充矩形)。

五、
        RGSS的颜色类Color有RGBA四个属性,即红red,绿green,蓝blue,不透明度alpha。
用Color.new可以获得一个透明色,用Color.new(red, green, blue)可以获得一个指定RGB值的完全不透明的颜色。

六、
        位图(Bitmap)的字体font属性是一个字体(Font)对象,
字体(Font)有字号(size)等多种属性,这里不一一列举,可以通过F1文档查阅。
用头画头像,用脚写脚本
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
10
星屑
39440
在线时间
1914 小时
注册时间
2010-11-14
帖子
3315

R考场第七期纪念奖

10
 楼主| 发表于 2019-3-17 12:52:52 | 只看该作者
本帖最后由 KB.Driver 于 2019-3-17 12:56 编辑

课后练习:

利用本课所学知识,结合F1文档的Bitmap内容,绘制以下场景。

使用素材(RTP):
"Graphics/Battlebacks1/Clouds"
"Graphics/Battlebacks1/Sky"
"Graphics/Battlers/Wizard_m"
"Graphics/Battlers/Willowisp"


用头画头像,用脚写脚本
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-4-23 16:43

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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