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

Project1

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

[RMVA发布] 【渣作品】VA脚本教程(三)<2013.3.21 完结>

[复制链接]

Lv1.梦旅人

梦石
0
星屑
48
在线时间
841 小时
注册时间
2010-8-11
帖子
1135
跳转到指定楼层
1
 楼主| 发表于 2013-3-9 02:44:55 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 945127391 于 2013-3-21 22:19 编辑

注意事项
一.本教程提供给一些已经有一点脚本基础的学习者们(至少你要知道变量啊函数啊什么的),如果你没有达到,那我希望你打开着VA的F1文档来看这篇教程;
二.如果你已经有一点脚本基础了,我也希望你打开着F1来看,因为我将在以下的教程中引用到许多F1里的内容;
三.本教程不会太多的说一些理论性的东西(比如浮点数是什么啊之类的),免得说多错多= =;
四.本人由于第一次写教程,所以有(fei)点(chang)乱,请多多包容;
五.如果有什么疑问或者发现了什么错误之处,又或者有什么意见或建议,欢迎回复,毕竟我也是个学习者而已。

如果你把上面的给看完了,就可以就绪看下去了。
玖肆伍的脚本教程(三)
之前太忙了,所以拖到现在才说……实在很抱歉……
然后,这是这个脚本教程系列的最后一章了……也许……
好吧,现在把昨天的作业给说一下:
①draw_icon是在Window_Base里定义的方法。
②先在refresh里添加一句:
  1. draw_actor_exp($game_party.members[0], 0, 96, self.contents.width)
复制代码
然后在窗口的脚本里添加以下这一个方法:
  1. #----------------------------------------------------------------------------
  2. # * 描绘EXP槽
  3. #----------------------------------------------------------------------------
  4. def draw_actor_exp(actor, x, y, width=124)
  5.   rate = actor.exp.to_f / actor.next_level_exp.to_f
  6.   draw_gauge(x, y, width, rate, Color.new(0, 255, 0), Color.new(100, 255, 100))
  7.   self.contents.font.color = text_color(16)
  8.   self.contents.draw_text(x, y, 56, 24, "EXP")
  9.   self.contents.font.color = Color.new(255, 255, 255)
  10.   en = "#{actor.exp}/#{actor.next_level_exp}"
  11.   self.contents.draw_text(x, y, width, 24, en, 2)
  12. end
复制代码
至于原理……我就不说了,自己慢慢吃透吧……
嗯……这次我们要说的是关于窗口的各种属性,比如visible啊、opacity啥的。
但在这之前,我们要先把Window_MapStatus显示到地图上来。
先来分析一下我们之前用来显示出口的方法,其实重点就在几句脚本里。
  1. $w = Window_MapStatus.new
复制代码
这句脚本其实是把Window_MapStatus的一个实例代入$w这个变量里,方便对其进行修改而又不会污染Window_MapStatus里的代码。
  1. $w.update
复制代码
这是用来更新窗口的,本质上是调用了$w(也就是Window_MapStatus)里的update方法。
仔细看看,我们写的代码里,也有update这个方法,且定义如下:
  1. def update
  2.   super
  3.   refresh
  4. end
复制代码
这里头有一个super,是用来调用父类的同名方法的,我们目前不需要知道的那么清楚,只需要知道在这里,他是调用了父类(Window_Base)里的update方法。
然后,我们看到第三行——refresh这句话上面。
我们之前的那两课都一直在写显示窗口的内容,其实都是在refresh方法里写的。
一般来说,描绘窗口的内容的代码都可以写在refresh里。但是要注意的是,Window_Base里并没有refresh这个方法,所以你的窗口如果是直接继承Window_Base的话,就不要用super了。
于是,我们就能看出,在update里调用refresh,是为了让它每一次刷新的时候都重绘一次窗口。这是最简单的方法,如果你的窗口十分简单,就可以这样。但是如果你的窗口很复杂(= =),每帧调用会很卡的。
基本上,显示窗口都脱离不开这两个方法。
理论讲完了,我们来实践一下吧!
新建一个脚本页,在里面输入:
  1. class Scene_Map < Scene_Base
  2.   #----------------------------------------------------------------------------
  3.   # * 重命名方法
  4.   #----------------------------------------------------------------------------
  5.   alias ms_sta start
  6.   #----------------------------------------------------------------------------
  7.   # * 开始处理
  8.   #----------------------------------------------------------------------------
  9.   def start
  10.     ms_sta
  11.   end
  12. end
复制代码
这是为Scene_Map添加东东而做准备。而这里有一个很重要的知识点——alias。
这是给方法起别名的(话说我为什么没有在可爱的F1里找到关于这个的说明!?),好吧,那就凭自己的理解来说明这个方法……
比如说,有以下语句:
  1. @i = 0
  2. def a
  3.   @i += 1
  4. end
  5. alias a2 a
  6. def b
  7.   a2
  8.   @i *= 15
  9. end
  10. p b
复制代码
最后的结果是什么呢?0?还是15?
很明显的,结果是15。
为什么呢,@i的初始值是0,而方法b里有一句@i *= 15,不应该是0*15=0吗?????
因为第5行给方法a起了一个别名a2,因为执行了这个操作,所以以后调用a和调用a2都是一样的——执行方法a里的内容。
所以实际上,在方法b的开头就给@i加上了1,所以正确的运算其实是(@i + 1) * 15 = 15。
我们要记住alias的正确使用方法:
alias 别名 方法
(注意空格)
但是,我还是没有看出alias有什么重要啊~?我直接把原方法里的内容复制黏贴过去不就可以了吗?
不可以哦,我们试想一下,有一天我们把脚本发去给别人用,而别人的其他外挂脚本里头有没有用到alias,这样子就会导致不可预知的错误(冲突)。原因是其他的脚本里定义到了一些东西,而你的脚本里的方法又覆盖了它定义的东西,这和把他的那个方法删掉了没什么区别,自然就会出错。而如果大家都使用alias的话,脚本的兼容性就会增强很多。
所以说,aliassuper都是两个很重要的东西。
好了,脱轨这么久,我们回到原来的内容上。
根据刚才对alias的解释,大家都应该知道alias ms_sta start是啥意思吧,没错,就是用来防止原来的Scene_Map里的start被覆盖的。
好了,然我们进行下一步:在start方法里加上一句:
  1. @mapstatus_window = Window_MapStatus.new
复制代码
然后再把显示窗口的那个事件删掉,然后再运行……

哇哇!出现了呢!
来,我们来升升级,哇!升到99级了呢!
好好玩~(= =)
但是,为什么我们没有用到update呢?
根据RMVA的脚本RGSS里的Scene_Base里,updatedispose的写法来说,窗口updatedispose都是自动的,说以就节省了制作者的很多心思。
抱歉我一开始忘了这一点,所以开头的脚本有一点错误,现已纠正,抱歉。
好了好了,一般来说这样就可以用了~
但是为什么好像好卡的样子!?
那是因为每帧刷新,而刷新的时候顺便重绘内容的原因。因为本来描绘文字就需要一段时间,现在还要每帧都描绘这么多文字,自然就要卡喽~
那要怎么解决呢?
首先,先把Window_MapStatusupdate内的refresh改成:
  1. refresh if $refresh
复制代码
实际上,这句话是给调用refresh方法设了个条件:当$refreshtrue时。也就相当于以下这段脚本:
  1. if $refresh == true
  2.   refresh
  3. end
复制代码
但是,全局变量的初始值是nil,而我们又不给它更改数值的话,他永远都不会是true
于是乎,我们就要设定它在哪儿变成true,哪儿又变回false
变回false就比较简单了,直接在refresh if $refresh后面加上一句:
  1. $refresh = false
复制代码
就可以了。
但是,它要在哪里变成true呢?
我们这个窗口里,要描绘的是头像、名字、状态、HP槽、MP槽、TP槽和EXP槽。所以我们就要考虑到在更改角色、更变状态、改变HP/MP/TP/EXP的时候刷新,也就是把$refresh变为true
p.s 更周全的是要考虑到更变名称和头像时刷新,但是我很懒……
而这些家伙几乎全都在Game_BaseBatterGame_Actor还有Game_Party里,以下是脚本:
  1. class Game_Actor < Game_Battler
  2.   #----------------------------------------------------------------------------
  3.   # * 重命名方法
  4.   #----------------------------------------------------------------------------
  5.   alias ms_refresh refresh
  6.   alias ms_tp tp=
  7.   alias ms_add_state add_state
  8.   #--------------------------------------------------------------------------
  9.   # * 刷新
  10.   #--------------------------------------------------------------------------
  11.   def refresh
  12.     ms_refresh
  13.     $refresh = true
  14.   end
  15.   #----------------------------------------------------------------------------
  16.   # * 更改 TP
  17.   #----------------------------------------------------------------------------
  18.   def tp=(tp)
  19.     ms_tp(tp)
  20.     $refresh = true
  21.   end
  22.   #----------------------------------------------------------------------------
  23.   # * 附加状态
  24.   #----------------------------------------------------------------------------
  25.   def add_state(state_id)
  26.     ms_add_state(state_id)
  27.     $refresh = true
  28.   end
  29. end

  30. class Game_Party
  31.   #----------------------------------------------------------------------------
  32.   # * 重命名方法
  33.   #----------------------------------------------------------------------------
  34.   alias ms_swap_order swap_order
  35.   #----------------------------------------------------------------------------
  36.   # * 交换顺序
  37.   #----------------------------------------------------------------------------
  38.   def swap_order(index1, index2)
  39.     ms_swap_order(index1, index2)
  40.     $refresh = true
  41.   end
  42. end
复制代码
(因为时间关系,我就不详细说了,不过我相信根据注释,也不难看懂吧……)
这种用变量判断刷新的方法,不是最好的方法,却是最简单的方法。
测试一下,已经不卡了,看~我多厉害~(众:滚!!)
好吧,我们现在要开始介绍Window的属性了。
首先第一个,当然是最最重要的opacity啦~
opacity其实是用来控制窗口内除了描绘内容以外的的其它地方(背景+边框)的不透明度的,也就是说,想要窗口只显示内容,把opacity设为0就好了。
F1里是这样说的:
窗口的不透明度(0~255)。超出此范围的数值会自动修正。

一般l来说,初始化窗口的属性都是在initialize里初始化的,所以我们可以在initialize里加一句话:
  1. self.opacity = 0
复制代码
看看效果~

真的把背景给隐藏起来了呢!看吧,这比之前的简单多了~
但是呢,这个窗口这么大,好像出现了一些问题呢,比如说~

主角呢?主角去哪儿了?
很明显,他被埃里克的头像挡住了。
那我们要怎么办呢?对了!我们可以把内容调成半透明!
好啊,试试看吧:在initialize里加上下面这句话:
  1. self.contents_opacity = 75
复制代码
看看效果吧:

啊,这下主角就看得很清楚了,所以你也知道contents_opacity的功能了吧,没错,就是修改窗口的内容的不透明度。
照例放上F1:
窗口内容的不透明度(0~255)。超出此范围的数值会自动修正。默认值为255。

但是这样子的话,不会导致窗口看不清楚吗?
所以,我们要使角色走上去才变成半透明,也就是说,又要开始写一大堆脚本了。
先把刚刚添上那句self.contents_opacity = 75删掉,然后再update里添上这样一段脚本:
  1. if $game_player.screen_x >= 0 and $game_player.screen_x <= self.width and
  2.        $game_player.screen_y >= 0 and $game_player.screen_y <= self.height
  3.       self.contents_opacity = 75
  4.     else self.contents_opacity = 255
  5.     end
复制代码
我相信,通过之前的学习,这段脚本里唯一需要解释的就是$game_player.screen_x$game_player.screen_y了吧。
顾名思义,这是用来获取玩家在画面上的x、y坐标的。
这个就是用来判断玩家是否走到了窗口的范围里,如果是,就半透明窗口,否则窗口恢复原状。
这样就人性化很多了吧!
说到这里,这节课就讲完了。现在,我们的窗口脚本就像以下这样了:
  1. class Game_Actor < Game_Battler
  2.   #----------------------------------------------------------------------------
  3.   # * 重命名方法
  4.   #----------------------------------------------------------------------------
  5.   alias ms_refresh refresh
  6.   alias ms_tp tp=
  7.   alias ms_add_state add_state
  8.   #--------------------------------------------------------------------------
  9.   # * 刷新
  10.   #--------------------------------------------------------------------------
  11.   def refresh
  12.     ms_refresh
  13.     $refresh = true
  14.   end
  15.   #----------------------------------------------------------------------------
  16.   # * 更改 TP
  17.   #----------------------------------------------------------------------------
  18.   def tp=(tp)
  19.     ms_tp(tp)
  20.     $refresh = true
  21.   end
  22.   #----------------------------------------------------------------------------
  23.   # * 附加状态
  24.   #----------------------------------------------------------------------------
  25.   def add_state(state_id)
  26.     ms_add_state(state_id)
  27.     $refresh = true
  28.   end
  29. end
  30. class Game_Party
  31.   #----------------------------------------------------------------------------
  32.   # * 重命名方法
  33.   #----------------------------------------------------------------------------
  34.   alias ms_swap_order swap_order
  35.   #----------------------------------------------------------------------------
  36.   # * 交换顺序
  37.   #----------------------------------------------------------------------------
  38.   def swap_order(index1, index2)
  39.     ms_swap_order(index1, index2)
  40.     $refresh = true
  41.   end
  42. end
  43. #==============================================================================
  44. # ** Window_MapStatus
  45. #==============================================================================
  46. class Window_MapStatus < Window_Base
  47.   #----------------------------------------------------------------------------
  48.   # * 初始化
  49.   #----------------------------------------------------------------------------
  50.   def initialize
  51.     super(0, 0, 273, 144)
  52.     self.opacity = 0
  53.     refresh
  54.   end
  55.   #----------------------------------------------------------------------------
  56.   # * 刷新画面
  57.   #----------------------------------------------------------------------------
  58.   def update
  59.     super
  60.     refresh if $refresh
  61.     $refresh = false
  62.     if $game_player.screen_x >= 0 and $game_player.screen_x <= self.width and
  63.        $game_player.screen_y >= 0 and $game_player.screen_y <= self.height
  64.       self.contents_opacity = 75
  65.     else self.contents_opacity = 255
  66.     end
  67.   end
  68.   #----------------------------------------------------------------------------
  69.   # * 更新内容
  70.   #----------------------------------------------------------------------------
  71.   def refresh
  72.     self.contents.clear
  73.     draw_actor_face($game_party.members[0], 0, 0)
  74.     draw_actor_name($game_party.members[0], 0, 0)
  75.     draw_actor_level($game_party.members[0], 101, 0)
  76.     draw_actor_icons($game_party.members[0], 0, 72)
  77.     draw_actor_hp($game_party.members[0], 101, 24, self.contents.width - 101)
  78.     draw_actor_mp($game_party.members[0], 101, 48, self.contents.width - 101)
  79.     draw_actor_tp($game_party.members[0], 101, 72, self.contents.width - 101)
  80.     draw_actor_exp($game_party.members[0], 0, 96, self.contents.width)
  81.   end
  82.   #----------------------------------------------------------------------------
  83.   # * 描绘EXP槽
  84.   #----------------------------------------------------------------------------
  85.   def draw_actor_exp(actor, x, y, width=124)
  86.     rate = actor.exp.to_f / actor.next_level_exp.to_f
  87.     draw_gauge(x, y, width, rate, Color.new(0, 255, 0), Color.new(100, 255, 100))
  88.     self.contents.font.color = text_color(16)
  89.     self.contents.draw_text(x, y, 56, 24, "EXP")
  90.     self.contents.font.color = Color.new(255, 255, 255)
  91.     en = "#{actor.exp}/#{actor.next_level_exp}"
  92.     self.contents.draw_text(x, y, width, 24, en, 2)
  93.   end
  94.   #----------------------------------------------------------------------------
  95.   # * 描绘值槽
  96.   #----------------------------------------------------------------------------
  97.   def draw_gauge(x, y, width, rate, color1, color2)
  98.     fill_w = (width * rate).to_i
  99.     self.contents.gradient_fill_rect(x, y+12, fill_w, 6, color1, color2, true)
  100.     self.contents.gradient_fill_rect(x, y+18, fill_w, 6, color2, color1, true)
  101.     self.contents.fill_rect(x, y+12, width, 2, Color.new(255, 255, 255))
  102.     self.contents.fill_rect(x, y+22, width, 2, Color.new(255, 255, 255))
  103.     self.contents.fill_rect(x, y+14, 2, 8, Color.new(255, 255, 255))
  104.     self.contents.fill_rect(x+width-2, y+14, 2, 8, Color.new(255, 255, 255))
  105.   end
  106. end
  107. class Scene_Map < Scene_Base
  108.   #----------------------------------------------------------------------------
  109.   # * 重命名方法
  110.   #----------------------------------------------------------------------------
  111.   alias ms_sta start
  112.   #----------------------------------------------------------------------------
  113.   # * 开始处理
  114.   #----------------------------------------------------------------------------
  115.   def start
  116.     ms_sta
  117.     @mapstatus_window = Window_MapStatus.new
  118.   end
  119. end
复制代码
你写对了吗?
以下是范例:
http://pan.baidu.com/share/link?shareid=416364&uk=2735273937
总结
在这节课,我们主要学了以下的东西:
名称
LZ的说明
F1/默认脚本里的说明
alias 旧方法名 新方法名
给旧方法名的方法起一个别名(新方法名)
可以给一个方法或全局变量指定其别名。指定的方法名称可以是标识符或符号(不可使用如 obj.method 这样的表达式)。调用方法时不会计算别名的参数表达式。
使用方法别名时,既使重新定义该方法,该方法的原有定义依然会被保留。当想要改变方法的行为,又要在新定义的方法内使用旧定义方法的结果时可以使用。
super
调用父类同名方法的内容。
呼叫超类中正由当前方法所覆盖的函数。若是省略了括号和参数,当前方法的参数则原封不动的传递给超类中的同名方法。若是调用超类方法而不想使用当前参数时,用空的括号如: super( )。

名称
LZ的说明
F1/默认脚本里的说明
window.opacity
窗口内除了内容以外其他所有元素的不透明度。
窗口的不透明度(0~255)。超出此范围的数值会自动修正。
window.contents_opacity
窗口内容的不透明度。
窗口内容的不透明度(0~255)。超出此范围的数值会自动修正。默认值为255。
关于窗口的三个主要方法,我们放到培优班再说。
培优班
窗口的newupdatedispose.
这三个方法是十分重要的,在VA里,对于写脚本的我们来说,update和dispose都是可以忽略的,因为根据Scene_Base的内容,所有的窗口都是会自动刷新和释放的,所以一般都是无视这两个家伙的。我在这里就说一说他们的功能吧!
window.new是最基础的,用于生成一个window的实例,没有它,后面的一切都没有用。而这个生成的实例,一般都会代入到某个变量中,方便后来对其修改。比如说,我们首次接触的就是:
  1. $w = Window_MapStatus.new
复制代码
它的意义就是把Window_Status的实例代入到$w里,然后才能使用$w.update来刷新窗口。
window.update其实就是调用了窗口内一个叫update的方法。原则上,这个方法是每帧调用的,所以有什么要刷新的一般都写到这个方法内。
window.dispose是调用了dispose这个方法。这个方法是用来释放窗口的,就相当于这个窗口不用了,把它扔进垃圾桶是一样的。
现在,我们就学了关于窗口类的三个基本方法:
名称
LZ的说明
F1/默认脚本里的说明
window.new
生成window的实例。
——
window.update
刷新window。

实际是调用了update这个方法。

刷新光标的闪烁和暂停标记的动画。原则上每一帧都会调用一次。
window.dispose
释放window。

实际上是调用了dispose这个方法。

释放窗口。若窗口已释放则什么都不做。
后记
从9号写到21好,足足用了12天,想必这是我偷懒的结果吧……
当初的那一份热情似乎已经不见了呢,所以这一篇写得格外马虎。
有神马问题可以问我。
还有,这是最后一篇了……

Lv1.梦旅人

梦石
0
星屑
50
在线时间
47 小时
注册时间
2013-2-1
帖子
108
2
发表于 2013-3-9 20:12:46 | 只看该作者
等死了终于来了。。。快抢一楼。。。

点评

已完结,欢迎来踩。  发表于 2013-3-21 22:21
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
22 小时
注册时间
2012-7-15
帖子
8
3
发表于 2013-3-10 01:39:14 | 只看该作者
赶上直播了么·

点评

不是直播……是连载……  发表于 2013-3-10 11:37
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
47 小时
注册时间
2013-7-26
帖子
10
4
发表于 2013-8-11 20:29:47 | 只看该作者
按SAVE時STATUS跑到存檔上面了0.0/~是什麼問題?

点评

怎么会……截一下图  发表于 2013-8-11 23:53
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
47 小时
注册时间
2013-7-26
帖子
10
5
发表于 2013-8-12 19:53:55 | 只看该作者
yuyuyuyui 发表于 2013-8-11 20:29
按SAVE時STATUS跑到存檔上面了0.0/~是什麼問題?

保上圖片

science game1 - 複製.jpg (111.43 KB, 下载次数: 11)

science game1 - 複製.jpg

点评

没有dispose。  发表于 2013-9-5 06:15
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
55
在线时间
249 小时
注册时间
2011-12-2
帖子
363
6
发表于 2013-9-4 15:24:21 | 只看该作者
本帖最后由 倾灬城 于 2013-9-5 13:42 编辑

现在回复算挖坟吗=-=——左边没有白字

太懒所以没认真读前面的教程=-=直接拿了最后的脚本=-=
所以当角色升级后会发生数字重叠的现象……

还需要改哪里求帮助QAQ

______________________________________
可以讲一下吗?还需要修改哪里QAQ?@945127391  

QQ图片20130904154005.jpg (19.91 KB, 下载次数: 6)

QQ图片20130904154005.jpg

点评

= =把脚本发出来吧……你用的那个……  发表于 2013-9-15 17:33
我用的时候,没有出现这个问题哦~不过看起来像是没有调用clear的后果  发表于 2013-9-5 06:22
你說霜冷長河,蒹葭蒼蒼。
後來伊人何在?獨坐未央。

哪怕跌到新兵,我也要尽全力去援助好人
哪怕被封被删,我也要尽全力去喷伸手党
不是说作为小白不能提问或让别人帮忙,只是有些人你们这样肆无忌惮地伸手甚至连句感谢都不会说你们家里人到底知不知道
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
65
在线时间
148 小时
注册时间
2010-5-20
帖子
97
7
发表于 2013-9-20 04:51:10 | 只看该作者
那麼如果我想顯示隊伍內所有的人呢? 要弄5個這樣的腳本嗎 OTZ||||
而且如果隊伍沒人的話就不顯示的 腳本是怎樣?

点评

大概不需要,因为同一个窗口可以显示不同的人,但是这里还没有实现罢了。  发表于 2013-9-20 09:56
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
28 小时
注册时间
2016-3-21
帖子
30
8
发表于 2016-3-21 22:46:05 | 只看该作者
本帖最后由 战斗的双手 于 2016-3-21 22:48 编辑

多谢!!!!!!!!!!!!!!!!!!!!!
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-4-26 00:00

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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