Project1

标题: 【渣作品】VA脚本教程(一)<2013.2.16完结> [打印本页]

作者: 945127391    时间: 2013-2-15 06:31
标题: 【渣作品】VA脚本教程(一)<2013.2.16完结>
本帖最后由 945127391 于 2013-9-19 17:31 编辑

欢迎来到这个帖子内,在阅读正文之前,我希望你先读一些下面这些:
注意事项
一.本教程提供给一些已经有一点脚本基础的学习者们(至少你要知道变量啊函数啊什么的),如果你没有达到,那我希望你打开着VA的F1文档来看这篇教程;
二.如果你已经有一点脚本基础了,我也希望你打开着F1来看,因为我将在以下的教程中引用到许多F1里的内容;
三.本教程不会太多的说一些理论性的东西(比如浮点数是什么啊之类的),免得说多错多= =;
四.本人由于第一次写教程,所以有(fei)点(chang)乱,请多多包容;
五.如果有什么疑问或者发现了什么错误之处,又或者有什么意见或建议,欢迎回复,毕竟我也是个学习者而已。
[line]1[/line]
好了,如果你认真的看完前面的五条,你就可以往下看了。
玖肆伍的脚本教程(一)
今天,我会带领大家写一个在地图显示领队基本状态的窗口,并一步一步的优化。
啥?你要预览图?抱歉,我也没有,因为我是边说边写的。
好了,开始第一步:打开脚本编辑器,并在main之前新建一个脚本;
然后,我们就要开始输入整个窗口的框架了:请在新建的脚本中输入以下的内容:
  1. #==============================================================================
  2. # ** Window_MapStatus
  3. #==============================================================================
  4. class Window_MapStatus < Window_Base
  5.   #----------------------------------------------------------------------------
  6.   # * 初始化
  7.   #----------------------------------------------------------------------------
  8.   def initialize
  9.     super(0, 0, 144, 273)
  10.     refresh
  11.   end
  12.   #----------------------------------------------------------------------------
  13.   # * 刷新画面
  14.   #----------------------------------------------------------------------------
  15.   def update
  16.     super
  17.     refresh
  18.   end
  19.   #----------------------------------------------------------------------------
  20.   # * 更新内容
  21.   #----------------------------------------------------------------------------
  22.   def refresh
  23.     self.contents.clear
  24.   end
  25. end
复制代码
基本上,所有的窗口都离不开这三个方法,有一些窗口还会有dispose这个方法,但是我们现在暂时不需要这个,所以省略不写了。
诶,这位同学你有什么问题?
同学甲:为什么你的注释里用的是“**”和“*”,而VA默认脚本里用的是“■”和“●”?
好吧,这只是一个我在用VX的时候遗留下来的习惯,我们不需要在这种与无关要紧的问题中纠结,快点运行看看吧!

.

……
同学甲:怎么什么都没有!你是不是在耍我们!
哎呀呀,忘记显示了,别激动,接下来就教你怎么显示:
你只要在地图上新建一个事件,触发条件选择并行处理,然后在执行内容里插入脚本指令,输入:
  1. $w = Window_MapStatus.new
复制代码
然后再打开独立开关A,在新建一个事件页,出现条件调成独立开关A被开启时,触发条件也是并行处理,然后再插入脚本指令,输入:
  1. $w.update
复制代码
就可以了。
如果你看不懂我上面在说什么,那就看截图吧:
事件页1:

事件页2:

(关于那一句Window_MapStatus.new,是生成实例的方法,之后会说到,所以这里暂时先跳过。)
(其实这是测试用的方法,真正的显示方法,在后来会说到。)
运行吧,这回你肯定能看到窗口了!

同学乙:(尖叫)怎么是竖着的!说好的(?)横着呢!
哦,这个问题而已啊,看来我是把参数调换了。
回到我们刚刚输入的那个窗口框架,看看第9行的那句:
  1. super(0, 0, 144, 273)
复制代码
这句话其实是用来决定窗口的尺寸的(虽然后期能够改变),很明显的,要解决这个问题,我们必须要把窗口的宽和高改一改。
(P.S:在窗口类里的宽,是指窗口的横向长度,高是指窗口的纵向长度,与它们的长短无关。)
但是,这里有四个数,哪个才是宽和高呢?剩下的那两个数又是用来干嘛的呢?
一般来说,在这句话中的括号里,第一个是决定窗口(左上角)的x坐标的,第二个是决定窗口(左上角)的y坐标的,而第三个数就是用来决定窗口的宽度,第四个数是用来决定窗口的高度的。
好了,这下你知道要改哪里了吧,没错,就是第三个和第四个参数,把他们改成273和144就可以了。

唔……这样看起来顺眼多了,但是到目前为止,窗口里还是空的啊!
没关系,我们将会一步步地向里面添加一些东西。
首先,先写名字:
请在refresh方法里添加以下这句话:
  1. self.contents.draw_text(0, 0, self.contents.width, 24, "艾里克")
复制代码
结果就会像下面这个一样:

等等!self.contents是什么!
嗯……self在这里是指Window_MapStatus自己本身,而contents是窗口类的一个属性,实际上是用来描绘内容的一个位图(Bitmap),也就是说,位图类的方法都可以在这个contents里使用。
同学甲:你怎么证明contents是一个位图?我可没看见是在哪里给它赋值为位图的!
同学甲,你也太粗心了吧……
首先,F1里说的很清楚,它就是一个位图;
其次,请翻到Window_Base里,眼睛看到第75行的那句:
  1. self.contents = Bitmap.new(contents_width, contents_height)
复制代码
接下来还要我说什么吗?
同学甲:但是……但是……它为什么要用contents_widthcontents_height,而不直接用self.widthself.height呢?
哎呀,你还知道self.widthself.height呢,不愧是同学甲……
(P.S 关于self.widthself.height,或许在最后会说到)
实际上,contents的宽和高和窗口的宽和高是不同的,一般来说,contents的宽等于窗口的宽减去24,而高就等于窗口的高减去24,在决定窗口的尺寸的时候必须要考虑上这点,因为contents的尺寸是你可以描绘内容的最大尺寸。
(P.S:在VA里,直接使用contents和使用self.contents的效果是一样的。)
让我们回到self.contents.draw_text(0, 0, self.contents.width, 24, "艾里克")这句话来,
draw_text本身是位图类的方法,所以前面要有个self.contents.,至于预置脚本里直接使用draw_text,完全是因为VA的Window_Base有个叫draw_text的方法,并不代表draw_text是窗口类的方法。
draw_text这个方法的详解如下:
draw_text(x, y, width, height, str, [align])
在(x, y)描绘宽度为width,高度为height的字符串str。
align是对齐方式,0为左对齐,1为居中,2为右对齐。可不填,默认为0(左对齐)。

如果你没看懂的话,也许F1能够帮到你:
在位图区域 (x, y, width, height) 或矩形 rect (Rect 矩形类 ) 中描绘字符串 str 。
若 str 不是字符串对象,则会在执行之前,先调用 to_s 方法转换成字符串。
若文字长度超过区域的宽度,文字宽度会自动缩放,最高缩放60%。
文字的横向对齐方式预设为靠左对齐,可以设置 align 为 1 居中对齐,或设置为 2 靠右对齐。纵向则必定是总是居中对齐。
此处理需要花费时间,因此不建议每画格重绘一次文字。

好吧,他说多了。
所以呢,在窗口上写字,就要用self.contents.draw_text(x, y, width, height, str, [align])
但是,这样描绘并不会跟据领队的变化而变化啊泥煤!
好把我激动了,这样写的确会让他永远只显示“艾里克”三个字,所以我们就要想个方法来让他显示出领队的名字。
不,不是\n[1]这么简单,我们要用一串很长的脚本(其实这不算长):
  1. $game_party.members[0].name
复制代码
这句话可以获得领队的名字,至于是为什么,我们目前还不用理解这么多,以后慢慢说。
所以,我们就要把self.contents.draw_text(0, 0, self.contents.width, 24, "艾里克")替换成:
  1. self.contents.draw_text(0, 0, self.contents.width, 24, $game_party.members[0].name)
复制代码
这样就可以根据领队的变化而变化了(其实这还要依靠update)。
但是,眼睛尖的同学已经发现了预置脚本里有一个draw_actor_name了,
这是用来干什么的呢?
其实这个就是用来描绘名字的,只不过多了一个功能:HP低时显示的名字为红色。
它的本质也是self.contents.draw_text(0, 0, self.contents.width, 24, $game_party.members[0].name)(好吧其实有点不同)。
关于draw_actor_name这个方法的详解如下:
draw_actor_name(actor, x, y, [width])
在(x, y)描绘actor的名字、
width为描绘的宽度,可不填,默认为112。

所以呢,我们可以把self.contents.draw_text(0, 0, self.contents.width, 24, $game_party.members[0].name)这句替换为

(P.S 这里不用加self.contents.了,因为为这是在Window_Base定义的方法。)
好了好了,描绘完名字以后,我们就要画头像了。
怎么在窗口里画头像呢?
不如先在refresh里插入:
  1. face = Cache.face($game_party.members[0].face_name)
  2. self.contents.blt(0, 0, face, face.rect)
  3. face.dispose
复制代码
(P.S $game_party.members[0].face_name 用来获取领队的头像文件名
让我一句句来讲解:
首先,第一句是把一个位图的实例对象赋值给face这个变量,
但是新建一个位图的实例不是应该用
  1. Bitmap.new("Graphics/Faces/#{$game_party.members[0].face_name}")
复制代码
吗?怎么出了个Cache
其实
Cache.face($game_party.members[0].face_name) Bitmap.new("Graphics/Faces/#{$game_party.members[0].face_name}") 其实效果是一样的,但是用Cache还有一个好处,就是当第一次读取到一个图片文件的时候,它就会生成实例并且储存起来,下次再要生成相同的图片的时候,就不用再读取了,直接拿出来就可以了。
所以,用Cache比直接用Bitmap.new要好很多。
第二句,self.contents.不用再说了吧,至于blt,这也是个位图的方法,详解如下:
blt(x, y, src_bitmap, src_rect[, opacity])
在(x, y)处描绘src_bitmap 上的src_rect (那一块区域)。
opacity为透明度,范围在0~255之间,可不填。

也许F1的说明会专业一点:
执行从位图 src_bitmap 的矩形 src_rect  (Rect 矩形类 ) 到指定的位图坐标 (x, y) 之间的区块过渡。
opacity 是透明度,范围 0~255。

至于 face.rect 是获取位图的矩形,相当于:
  1. Rect.new(0, 0, face.width, face.height)
复制代码
(P.S face.width和face.height是用来获取位图的高度和宽度的。)
至于最后一句,是用来释放位图的,免得占内存……
好了,说了那么多,我们运行来看看:

同学乙:怎么全都来了!!!!我只要我的艾里克!!我的艾里克!!
同学,表激动,我们现在就把艾里克“抠”出来,
这就要用到blt方法的src_rect了:
把那句self.contents.blt(0, 0, face, face.rect)改成:
  1. self.contents.blt(0, 0, face, Rect.new(0, 0, 96, 96))
复制代码
你看得出是哪里变了吗?
没错,就是face.rect变成了Rect.new(0, 0, 96, 96)
Rect是啥呢?Rect是矩形的类,一般用来限制范围(好吧其实我也不知道自己在说什么……)。
于是乎,再测试看看:

唔,你的艾里克回来了。
但是呢,这个也会出现之前描绘名字的那时候的问题——不会随着领队的变化而变化,
解决这个问题,我们一般会用$game_party.members[0].face_indexl来获取领队头像的索引,然后再乘于八除于二……
某观众:喂!你说什么!根本就不是什么乘八除二!!!!!!
好吧,我错了,其实我们不必要了解它是怎么算的(其实是我懒得说),我们只要知道有个方法能够方便地描绘角色头像就够了。
(关于它是怎么算的,我们以后可能会说到。)
请把
  1. face = Cache.face($game_party.members[0].face_name)
  2. self.contents.blt(0, 0, face, face.rect)
  3. face.dispose
复制代码
这三句替换为:
  1. draw_actor_face($game_party.members[0], 0, 0)
复制代码
(效果其实没变,所以就不截图了。)
没错!这其实就是传说中的三合一秘籍!(好吧我口胡)
其实draw_actor_face也是Window_Base里定义的方法,它的详解是:
draw_actor_face(actor, x, y, [enabled])
在(x, y)处描绘actor的头像。
enabled为有效度,为false时半透明绘制头像。可不填,默认为true。

同学甲:艾里克的名字呢,去哪儿了?
哎呀呀,失手了……
其实艾里克的名字是有描绘,只不过被后来描绘的头像给盖住了而已,只要把draw_actor_name($game_party.members[0], 0, 0)draw_actor_face($game_party.members[0], 0, 0)调换一下位置就好了。
由此引出一个规则:在Window里,后描绘的会把先描绘的给盖住。
写脚本的时候必须注意这点。
嗯……名字啥的的都描绘完了,接下来我们就要描绘角色的Lv了。
最简单的方法,就是用刚才我教大家的描绘文字的方法来描绘。
就是在refresh里插入以下脚本:
  1. self.contents.draw_text(101, 0, self.contents.text_size("Lv.#{$game_party.members[0].level}").width, self.contents.text_size("Lv.#{$game_party.members[0].level}").height, "Lv.#{$game_party.members[0].level}")
复制代码
(P.S $game_party.members[0].level 是用来获取领队的Lv的。)
嗯……现在看这句脚本没问题了吧,只要你理得清的话。
同学甲:在宽度和高度上的那一坨是啥?????
你是说self.contents.text_size("Lv.#{$game_party.members[0].level}").widthself.contents.text_size("Lv.#{$game_party.members[0].level}").height吧。
好吧其实这种写法简直是一种累赘,因为一般来说根本不用这样写,不过为了向大家讲解啥叫text_size,也只好暂时这样写了。
根据前面的self.contents.,我们知道text_size也是一个位图上的方法,以下就是这个方法的详解:
text_size(str)
获取描绘str要用的范围,返回的是矩形类(Rect)。

照例放上可爱的F1:
获取使用 draw_text 方法描绘 str 字符串时所需要的区域(Rect 矩形类 ) 。该区域不包含轮廓部分 (RGSS3) 和斜体的突出部分。
若 str 不是字符串对象,则会在执行之前,先调用 to_s 方法转换成字符串。

嗯哪,它说到了一个很重要的东西:
该区域不包含轮廓部分和斜体的突出部分。
于是乎,我们就可以用widthheight这两个方法来获取宽和高了。
但是,你看到上面那一坨不会觉得很烦吗?
所以,我一般都会用一些小技巧,比如:
  1. self.contents.draw_text(101, 0, self.contents.width - 101, 24, "Lv.#{$game_party.members[0].level}")
复制代码
(P.S 其实self.contents.width - 101这句话里的101是描绘的x坐标。)
这样不会这么长(虽然依然很长),但是我不建议你把宽度写成148【即 273 - 24 - 101】,因为我不知道什么时候又要改一改这个窗口的宽度的时候,那就麻烦了。
不过有时候你不知道字号(字号不固定)的时候,text_size还是很好用滴,不过呢,如果用text_size来获取高度的话,我一般会这样写:
  1. self.contents.text_size("啊").height
复制代码
不论你要描绘的是什么,都可以用这句。
这又是一个投机取巧的方法哦。
好了,说了这么多,我们来看看效果吧:

唔,这看起来不错……
同学乙:人家的脚本里,“Lv.”都是蓝色的!你的为什么不是!
别急,我正准备说呢。
首先,我们先把刚才描绘Lv的东东分成两句,也就是:
  1. self.contents.draw_text(101, 0, 42, 24, "Lv.")
  2. self.contents.draw_text(137, 0, self.contents.width - 141, 24, $game_party.members[0].level)
复制代码
为什么要这样拆呢?待会儿你就知道了,我们先在self.contents.draw_text(101, 0, 42, 24, "Lv.")前面插入一句很重要的话,那就是:
  1. self.contents.font.color = Color.new(132, 170, 255)
复制代码

嗯,没错数字也变蓝了,不过看到前面那一句……你知道要怎么改了吗?
没错,是用
  1. self.contents.font.color = Color.new(255, 255, 255)
复制代码
但是啊,在哪里插入呢?
对于改变字体的脚本(即self.contents.font.开头的),插入位置是很重要的,否则可能影响整个窗口的字体。
恩恩,你已经猜到了吧,是在self.contents.draw_text(101, 0, 42, 24, "Lv.")之后,self.contents.draw_text(137, 0, self.contents.width - 141, 24, $game_party.members[0].level) 之前。
于是乎,效果就会如下:

唔,用了这么久self.contents.font.color,其实很多同学都不知道是什么吧……
好吧,我现在就解释:
self.contents.的意思没变,然后fontcontents的一个属性,用来控制在contents上描绘的文字的字体。
(实际上,所有的位图类都有font这个属性,而它的作用也一样:用来控制在位图上描绘的文字的字体 。)
color,是font的一个属性,是用来控制描绘的文字的颜色的,它的值必须是颜色类(Color)的实例。
生成Color的实例,除了要用.new以外,还附带4个参数,以下就是这货的详解:
Color.new(R, G, B, [A])
Color.new
其实,你看到RGB以后还需要我说些什么吗?
至于最后那个A,指的是填充度(alpha),范围在0~255。可不填,默认为255.
照例放出F1:
生成色彩对象。alpha 值省略时使用 255。
如果参数没有指定,则默认设定为(0, 0, 0, 0)。 (RGSS3)

所以呢,那句self.contents.font.color = Color.new(132, 170, 255)就是把以下要描绘的文字(contents内)的颜色变成(132, 170, 255)。
但是,你会不会嫌要记着颜色的RGB很烦?
至少我嫌它烦,于是就用了这个方法:
  1. text_color(16)
复制代码
也就是把self.contents.font.color = Color.new(132, 170, 255) 变成self.contents.font.color = text_color(16)
嗯哪,效果一样,因为text_color(16)就等于Color.new(132, 170, 255)
其实呢,我们在对话窗口用的\c[n]的本质就是这货,所以text_color(n)里的n,和窗口皮肤里的那个是一样的。
也就是说,text_color(n)就是获取窗口皮肤右下角色块堆里n号色块的颜色
但是即使是这样,“Lv.”还是不够明显啊,怎么办呢?
我们不如用一下粗体?
首先,在self.contents.draw_text(101, 0, 42, 24, "Lv.")之前插入一句:
  1. self.contents.font.bold = true
复制代码
self.contents.draw_text(101, 0, 38, 42, "Lv.")之后插入一句:
  1. self.contents.font.bold = false
复制代码
其实这句话相当于一个粗体的“开关”,不过我还是详细的解说一下这个方法吧:
self.contents.font.bold = true
以下文字以粗体描绘(也许会叠加其他的效果)。
self.contents.font.bold = false
以下文字关闭粗体。

但是实际上,bold也是font的一个属性,这个属性在F1中的解释如下:
粗体标记。预设为 false。

没错了,这个就是用来控制描绘的文字是不是用粗体的属性。
实际上,描绘等级也有便捷的方法,那就是draw_actor_level了,
其实他最基本的也是我刚说的那两句,只不过没有粗体罢了;
于是,我们就可以把
  1. self.contents.font.color = Color.new(132, 170, 255)
  2. self.contents.font.bold = true
  3. self.contents.draw_text(101, 0, 42, 24, "Lv.")
  4. self.contents.font.bold = false
  5. self.contents.font.color = Color.new(255, 255, 255)
  6. self.contents.draw_text(137, 0, self.contents.width - 141, 24, $game_party.members[0].level)
复制代码
换成
  1. draw_actor_level($game_party.members[0], 101, 0)
复制代码
唔,效果差不多,我就不截图了,直接讲解:
draw_actor_level(actor, x, y)
在(x, y)处描绘actor的等级。

好了好了,这节课就讲到这里,讲到最后,我们的窗口的完整脚本应该为:
  1. #==============================================================================
  2. # ** Window_MapStatus
  3. #==============================================================================
  4. class Window_MapStatus < Window_Base
  5.   #----------------------------------------------------------------------------
  6.   # * 初始化
  7.   #----------------------------------------------------------------------------
  8.   def initialize
  9.     super(0, 0, 273, 144)
  10.     refresh
  11.   end
  12.   #----------------------------------------------------------------------------
  13.   # * 刷新画面
  14.   #----------------------------------------------------------------------------
  15.   def update
  16.     super
  17.     refresh
  18.   end
  19.   #----------------------------------------------------------------------------
  20.   # * 更新内容
  21.   #----------------------------------------------------------------------------
  22.   def refresh
  23.     self.contents.clear
  24.     draw_actor_face($game_party.members[0], 0, 0)
  25.     draw_actor_name($game_party.members[0], 0, 0)
  26.     draw_actor_level($game_party.members[0], 101, 0)
  27.   end
  28. end
复制代码
你改对了吗?
总结
这节课我们讲了什么呢?一起来看看吧!
① 如何创建一个窗口;
② 讲了一些在窗口上描绘内容的方法,比如:
方法名
LZ的解释
F1/默认脚本的解释
self.contents.clear
用来清除窗口的内容,相当于一个板擦。
清除整个位图。
(P.S 其实这里说的位图指的就是contents)
self.contents.draw_text(x, y, width, height, str, [align])
在(x,y)处,以width为宽度,height为高度描绘str。
align是对齐方式,0为左对齐,1为居中,2为右对齐。可不填,默认为0(左对齐)。
在位图区域 (x, y, width, height) 或矩形 rect (Rect 矩形类 ) 中描绘字符串 str 。
若 str 不是字符串对象,则会在执行之前,先调用 to_s 方法转换成字符串。
若文字长度超过区域的宽度,文字宽度会自动缩放,最高缩放60%。
文字的横向对齐方式预设为靠左对齐,可以设置 align 为 1 居中对齐,或设置为 2 靠右对齐。纵向则必定是总是居中对齐。
此处理需要花费时间,因此不建议每画格重绘一次文字。
self.contents.draw_blt(x, y, src_bitmap, src_rect[, opacity])
在(x, y)处描绘src_bitmap 上的src_rect (那一块区域)。
opacity为透明度,范围在0~255之间,可不填。

执行从位图 src_bitmap 的矩形 src_rect  (Rect 矩形类 ) 到指定的位图坐标 (x, y) 之间的区块过渡。
opacity 是透明度,范围 0~255。

方法名
LZ的解释
F1/默认脚本的解释
draw_actor_name(actor, x, y)
在(x, y)处描绘actor的名字。
——
draw_actor_face(actor, x, y)
在(x, y)处描绘actor的头像。
——
draw_actor_level(actor, x, y)
在(x, y)处描绘actor的等级。
——

方法名
LZ的解释
F1/默认脚本的解释
self.contents.text_size(str)
获取在窗口内描绘str所需的范围。【矩形类(Rect)】
获取使用 draw_text 方法描绘 str 字符串时所需要的区域(Rect 矩形类 ) 。该区域不包含轮廓部分 (RGSS3) 和斜体的突出部分。
若 str 不是字符串对象,则会在执行之前,先调用 to_s 方法转换成字符串。

方法名
LZ的解释
F1/默认脚本的解释
self.contents.font.color = Color.new(R, G, B, [A])
把以下的文字的颜色改为(R, B, G, A)。
文字颜色(Color 色彩类 ))。也可以调整 alpha 值。预设为 (255,255,255,255)。
alpha 值也同时用来描绘文字阴影和文字轮廓。
self.contents.font.bold = true/false
开启/关闭文字粗体。
粗体标记。预设为 false。

呐,这节课是完了,但是很明显这个窗口还没写完,所以呢,还会有第二辑第三缉第四辑第五辑第六辑一直到这个窗口完成为止,大家不用担心。
下一课我们要说什么呢?
一.描绘角色状态——draw_icon的使用;
二.描绘HP、MP、EXP槽——fill_rectgradient_fill_rect的使用。
好了,是时候要布置课后作业了:
课后作业(可选)
① 艾里克的头发是白色的,他的名字也是白色的,那岂不是很难看到?
     不如我们把艾里克的名字换成黑色吧!这难不倒你吧~
② 等等!我现在在哪儿!?
     哎呀呀,没有一个显示角色当前坐标的窗口实在很烦呐!
     不如帮我写一个出来吧!
     目标:写出一个能够显示 角色当前的x坐标和y坐标的窗口。
     可以不用写在地图显示的脚本,只写出那个窗口的脚本,毕竟这个目前还没说到。
     提示:
  1. $game_player.x #获取角色当前x坐标
  2. $game_player.y #获取角色当前y坐标
复制代码
培优班
培优班其实是用来说一些本来应该说但是又在正文中没有提及或者略带一提的东西。
之前,我们提到了一个叫self.contents.width的东西,现在就来给大伙解释解释:
self.contents.的意思没变,但是后面的width是位图类的一个方法,是用来获取该位图的宽度的;
height就是用来获取高度的。
也就是说,self.contents.width是用来获取contents的宽度的,而self.contents.height是用来获取contents的高度的。
一般来说,描绘文字用的宽度都是self.contents.width(除非已知准确的宽度),有时视情况还要减去x坐标。
还有呢,就是self.widthself.height了。
其实很多类里都可以用这个方法,其作用都是获取自身的宽和高。
在窗口类里,他就是获取当前窗口的宽和高。
归纳一下,就有下列表格了:
方法名
说明
self.width
获取当前窗口的宽度。
self.height
获取当前窗口的高度。
self.contents.width
获取当前窗口可描绘内容的宽度。
self.contents.height
获取当前窗口可描绘内容的高度。
脸图的算法
实际上,显示脸图的时候,要计算的都在x坐标和y坐标里了,因为宽和高都是固定了的96。
  1. x = face_index % 4 * 96
复制代码
等等,那个%是怎回事?
其实那个%是用来取余的,也就是说,如果有a%b这样子的表达式的话,返回值就是a÷b的余数,当b能够被a整除的时候,返回值为0。
比如,3%2返回1,是因为3除2得一余一。
在这里,face_index永远都在0~7之间,也就是face_index%4的得数永远只有0、1、2、3,再把这个数乘每个头像的宽度——96,就得出了这个头像所在的x坐标了,不难理解吧。
  1. y = face_index / 4 * 96
复制代码
这个就更好理解了,由于在Ruby里,整数之间的运算永远只得整数,而face_index又永远在0~7之间,所以face_index / 4的得数永远只有0和1(0~3得0,4~7得1),再乘于每个头像的高度——96,就得出y坐标了。
脸图的计算,就是这样而已。
Q&A
这里用来放一些读者在回复中提的问题以及我的回答。
Q:使用这个事件显示的窗口不会消失【7L】
A:请不要直接使用这个最后的窗口脚本,以及这种显示方法是十分不好的,只是为了看起来达到效果罢了,第三缉里提到的方法才是正确的。
      此外,凌童鞋前辈在9L也提到了这个问题的解决办法:
包错因为全局变量不会自动保存,所以再次运行之类的就会出错…
在地图上放事件处理窗口可不是好办法哦~
嘛,要达到你说的功能可以这样
  1. class Scene_Map < Scene_Base
  2. alias :old_map_start :start
  3. alias :old_map_update :update
  4. # 以上是给原方法取个别名什么的
  5. def start
  6. old_map_start  # 调用原方法
  7. @mapsta = Window_MapStatus.new  # 创建窗口
  8. end
  9. def update
  10. old_map_update
  11. @mapsta.update  #更新窗口
  12. end
  13. # va用了魔法般的dispose处理所以这东西不用写了
  14. end
复制代码
然后把那个事件删掉就好了,这个怎么用……不解释……
Q:我定义类的时候出错了。【21L @蓝焰。  】
A:我一开始还看不出来出什么问题,直到把它扔进脚本输入框里才发现……多了个空格哦亲~
  1. class Window_ Mapststus < Window_Base
复制代码
下划线和Mapststus中间多了个空格是吧,类名里不能有空格哦~
还有,注意一下你的status拼错了,虽说系统不会在意你英语上的错误,但是这个名字写错了,后面的实例生成或者其他地方用了正确的单词的时候,就会发生错误的说~
后记
呐呐,初次写教程,可能有些说不清楚,欢迎提醒。
有什么意见也可以提出哦~
你们的支持就是我最大的动力!Yeah!
作者: z2z4    时间: 2013-2-15 15:56
还是很复杂的说 。。。。。
作者: acn00269    时间: 2013-2-15 16:08
很详细的说,前排支(wěi)持(suǒ)一下然后慢慢看
作者: z2z4    时间: 2013-2-16 16:27

draw_actor_face(actor, x, y)


在(x, y)处描绘actor的名字。  确定是名字?
作者: jwx555    时间: 2013-2-17 00:01
看完了,受益匪浅

建议:教程的话更多还是严谨些,卖萌过多显得随意。

请求:求一个VA的中文帮助文档,在主站下载的1.0汉化版F1都是日文
作者: 我是老A    时间: 2013-2-17 23:18
jwx555 发表于 2013-2-17 00:01
看完了,受益匪浅

建议:教程的话更多还是严谨些,卖萌过多显得随意。

似乎我有
可惜太大上传不了。
有什么办法吗
作者: 550806810    时间: 2013-2-18 09:15
标题: 问题
本帖最后由 550806810 于 2013-2-18 14:07 编辑

看了表示可以举一反三的感觉……
这种教程活用性很大呢。
又学到了一种事件用脚本。
不过这样的话,返回标题会错误。再读取的时候也会出错呢……怎样做出继续游戏也保持状态的框呢?
作者: gzfate    时间: 2013-2-20 12:45
这个好的帖子 怎么没人顶 = =!
作者: 凌童鞋    时间: 2013-2-21 08:37
标题: RE: 【渣作品】VA脚本教程(一)<2013.2.16完结>
550806810 发表于 2013-2-18 09:15
看了表示可以举一反三的感觉……
这种教程活用性很大呢。
又学到了一种事件用脚本。

包错因为全局变量不会自动保存,所以再次运行之类的就会出错…
在地图上放事件处理窗口可不是好办法哦~
嘛,要达到你说的功能可以这样
  1. class Scene_Map < Scene_Base
  2. alias :old_map_start :start
  3. alias :old_map_update :update
  4. # 以上是给原方法取个别名什么的
  5. def start
  6. old_map_start  # 调用原方法
  7. @mapsta = Window_MapStatus.new  # 创建窗口
  8. end
  9. def update
  10. old_map_update
  11. @mapsta.update  #更新窗口
  12. end
  13. # va用了魔法般的dispose处理所以这东西不用写了
  14. end
复制代码

然后把那个事件删掉就好了,这个怎么用……不解释……
另外…我没测试过所以有没有错不知道呐……(手机党参上)
作者: 945127391    时间: 2013-2-22 22:03
凌童鞋 发表于 2013-2-21 08:37
包错因为全局变量不会自动保存,所以再次运行之类的就会出错…
在地图上放事件处理窗口可不是好办法哦~
...

嗯哪,没错的。
但是我现在用的方法只是一个测试用的方法,
因为打算在第三缉才说这个方法的……
谢谢凌大神。
作者: 神秘来客3    时间: 2013-2-24 15:01
本帖最后由 神秘来客3 于 2013-2-24 17:14 编辑

显示x、y的脚本进入另一个地图之后就不改变了。。。肿么办{:2_270:}
↑傻了
作者: tangtang125125    时间: 2013-7-14 15:35
我觉得,这个可以上图书馆的教程单元了
作者: 黄濑凉太    时间: 2013-7-14 17:16
嗯,很好的一个教程,有实例,感觉比一些单纯解释代码函数什么的有用。
看完这个的确懂了一些东西。谢谢LZ。
作者: 浮游叶    时间: 2013-7-16 15:31
好厉害

果然我还是个脚本盲
作者: 1065052725    时间: 2013-7-21 17:44
很不错的帖子,谢谢,辛苦了
作者: 伪3D春哥    时间: 2013-7-24 13:09
花了很长时间看完,收获丰富,但总感觉LZ一直在自言自语不像在讲解
作者: online2000    时间: 2013-8-1 21:54
楼主辛苦了...虽然说看着感觉挺复杂的,但的确是好东西、
作者: xggzga117    时间: 2013-8-6 19:25
呵呵,好东西,顶!
作者: 张小飞    时间: 2013-9-1 19:13
强悍,话说我是新新小菜鸟
作者: 蓝焰。    时间: 2013-9-9 22:38
看了前面一些后,就在第一页脚本 发现了问题!
class Window_ Mapststus < Window_Base
就是它!!!每次都发生拼写错误!!
后来我才发现原来类的名字不能有大写!?
肯定是M捣的鬼~~可是我家的VA从来没成功定义过一个类...
这是为什么呢................

辛苦啦~
作者: 945127391    时间: 2013-9-13 20:59
蓝焰。 发表于 2013-9-9 22:38
看了前面一些后,就在第一页脚本 发现了问题!
class Window_ Mapststus < Window_Base
就是它!!!每次都 ...

当然可以有大写……
status没拼错?
作者: chg1998    时间: 2013-9-18 23:17
赞一个,第一次看见这类文章,讲的透彻,新手懂了。
作者: 蓝焰。    时间: 2013-9-19 18:01
@945127391
原来我类名打错了...
VA的脚本编辑器里好像有自动补全这个功能吧...即使打错了也可以将错就错,或者搜索字符批量修改.....
好吧说到底是我 英语太差,所以单词都记的不牢靠.....
(至今仍然没有成功定义类的人---明明按照语法来的丫......-----都3台电脑了...学校机房电脑我都试了怎么还不成功QAQ,劳资一定要成功嗷嗷~~)
作者: jkpingkl111    时间: 2013-10-18 23:44
我F1是日语啊,refresh 方法在哪{:2_287:}
作者: 雷欧亦炫    时间: 2013-12-15 17:42
虽然没看懂,但最后的总结给我帮了个大忙,非常感谢。
作者: z12067010    时间: 2013-12-15 19:24
同学丙在哪里
作者: Z061356    时间: 2014-3-31 11:21
我觉得是论坛里写得最好的脚本教程
作者: CH3CH2CZT    时间: 2014-7-5 21:29
我在论坛上所有的脚本教程按照所说的做结果都报错!这个也不例外为什么啊!!我完全按照你说的做的!可就是报错!不光你这个所有的都报错!
作者: 2568567885    时间: 2016-3-5 20:46
太赞了,很有帮助。解释得很详细。
RUBY 代码复制
  1. contents.draw_text(0,0,contents.width,24,$game_party.members[0].name,2)
一点小建议,把名字写居右填写,那里刚好有空位。( `ー´)( ^ω^)
作者: abcxuyin    时间: 2017-11-15 17:28
为什么我一开始就报错了  GAME_INTERPRETER 第1411

作者: 世外游神    时间: 2019-5-15 22:55
我想知道,了解并掌握整个默认脚本运行原理,需要付出多大代价?




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1