赞 | 0 |
VIP | 10 |
好人卡 | 49 |
积分 | 10 |
经验 | 22958 |
最后登录 | 2020-8-1 |
在线时间 | 2161 小时 |
Lv3.寻梦者 酱油的
- 梦石
- 0
- 星屑
- 1020
- 在线时间
- 2161 小时
- 注册时间
- 2007-12-22
- 帖子
- 3271
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
好了,论文地狱终于过去。这下可以做点自己喜欢的事情,比如RM的脚本研究。
这次要说的是一点关于默认战斗画面的解读。好让大家熟悉一下默认作者的思路。不过,与其说是研究,多少有点不恰当。当中的知识更多地关于教学。面对的主要是新人,因为动不动就从F1学起,恐怕也太过枯燥。禾西是实用主义者,暂时用不上的东西绝对不学。
--------------------------------------------------------------------------------
首先打开一个新工程,按下F11进入脚本编辑,转到Scene_Battle 1这个脚本,然后开始解读。
在line:11,我们可以看到
这个方法。
在英语当中,main可以解释为「主」如同在「主要、主题...」中。
而对于Scene类脚本,main方法可以说的唯一的「主体」。当我们运行一个Scene脚本($scene = Scene_×××.new)的时候,脚本就会自动运行当中的main方法。
那么,在main这个方法当中定义了甚么东西呢?这个关系到我们调用战斗画面.new(Scene_Battle.new)会出现甚么东西,所以就看一下吧!
大致来说,main当中包含了这些东西:
def main
# 战斗之前
1.初始化(准备) 「战斗用数据」
2.生成各种窗口
3.生成活动块
4.执行过渡(窗口的切换)
# 战斗之中
5.战斗
6.更新
# 战斗之后
7.刷新地图
8.释放所有窗口
end # line:99
这个就是战斗画面的整个运作原理。
下面就等我们细看一下,究竟有具体有甚么东西:
1.初始化(准备)
line:12
# 初始化战斗用的各种暂时数据
$game_temp.in_battle = true
$game_temp.battle_turn = 0
$game_temp.battle_event_flags.clear
$game_temp.battle_abort = false
$game_temp.battle_main_phase = false
$game_temp.battleback_name = $game_map.battleback_name
$game_temp.forcing_battler = nil
# 初始化战斗用事件解释器
$game_system.battle_interpreter.setup(nil, 0)
# 准备队伍
@troop_id = $game_temp.battle_troop_id
$game_troop.setup(@troop_id)
如同解释所说,这里初始化(意思为:「建立,设置」)了「战斗用的临时数据」。作用就如同我们看戏之间,演员们所做的「幕后工作」。这个时候窗口还没有生成。所有的动作都是秘密的,不公开的。
那么这里定义了甚么东西呢?
主要是更改一些标志:
$game_temp.in_battle = true # 「角色处于战斗当中」标志 为 true
$game_temp.battle_turn = 0 # 建立「回合数」=0
$game_temp.battle_event_flags.clear # 清除所有战斗事件
$game_temp.battle_abort = false # 「战斗中断」标志 为 false
$game_temp.battle_main_phase = false # 「战斗状态」标志 为 false
$game_temp.battleback_name = $game_map.battleback_name # 读取「战斗背景」文件名
$game_temp.forcing_battler = nil # 清除「强制行动的战斗者」
以及建立一些数据:
# 初始化战斗用事件解释器
$game_system.battle_interpreter.setup(nil, 0)
# 准备队伍 <-(这里指的是「敌人队伍」)
@troop_id = $game_temp.battle_troop_id # 读取敌人队伍ID
$game_troop.setup(@troop_id) # 把敌人队伍Id 告诉 Game_Troop这个脚本,然后建
立起敌人的所有数据
这样说大概有点模糊。
不过暂时我们不需要理解,这里让人感兴趣的东西不多。
除了当中的某一句以外大部分都是必要的,而且没有办法更改。
所以现在只要知道我们的「游戏程序」已经准备好战斗了,其它回头再看。
先看看那句我们某些人大概会感到有趣的语句先。
@troop_id = $game_temp.battle_troop_id # 读取敌人队伍ID
这句语法决定了我们将会遇到的敌人。
当我们按全局搜索(Ctrl+Alt+F)时,我们惊奇地发现$game_temp.battle_troop_id在除战斗脚本外三个地方有提及。
Interpreter 6(事件解释)
Scene_Map(地图画面)
Scene_Title(游戏开始画面)
这里代表了我们将可以在遇到三种敌人:
1.明雷-通过事件遇到敌人
2.暗雷-在地图随机遇敌
3.测试-在数据库当中指定测试敌人
这是个有趣的发现,因为通过这句语法。我们顺藤摸瓜地找到了设置地图遇敌的语法:
脚本:Scene_Map
line:102
# 遇敌计数为 0 且、且遇敌列表不为空的情况下
if $game_player.encounter_count == 0 and $game_map.encounter_list != []
# 不是在事件执行中或者禁止遇敌中
unless $game_system.map_interpreter.running? or
$game_system.encounter_disabled
# 确定队伍
n = rand($game_map.encounter_list.size)
troop_id = $game_map.encounter_list[n]
# 队伍有效的话
if $data_troops[troop_id] != nil
# 设置调用战斗标志
$game_temp.battle_calling = true
$game_temp.battle_troop_id = troop_id
$game_temp.battle_can_escape = true
$game_temp.battle_can_lose = false
$game_temp.battle_proc = nil
end
end
end
至于作用嘛,聪明的你大概已经想到了。反正是题外话,不说太多。
想要改变地图遇敌判断的人就在这里添加判断语法(if)吧。
2.生成命令窗口 以及 更改位置、显示状态、活动状态等。
line:25
# 生成角色命令窗口
s1 = $data_system.words.attack
s2 = $data_system.words.skill
s3 = $data_system.words.guard
s4 = $data_system.words.item
@actor_command_window = Window_Command.new(160, [s1, s2, s3, s4])
@actor_command_window.y = 160
@actor_command_window.back_opacity = 160
@actor_command_window.active = false
@actor_command_window.visible = false
# 生成其它窗口
@party_command_window = Window_PartyCommand.new
@help_window = Window_Help.new
@help_window.back_opacity = 160
@help_window.visible = false
@status_window = Window_BattleStatus.new
@message_window = Window_Message.new
这里的说明应该很通俗易懂。
要说的只有解释一下语法:
×××.new是一个窗口生成语法,在Scene类脚本当中被大量使用。
以及生成了些甚么窗口:
01.角色的行动命令窗口
@actor_command_window = Window_Command.new(160, [s1, s2, s3, s4])
在这以上的
s1 = $data_system.words.attack
s2 = $data_system.words.skill
s3 = $data_system.words.guard
s4 = $data_system.words.item
都是在转换一些变量,让脚本看起来顺眼一点,以及难以理解一点。
具体如下:
s1 = $data_system.words.attack # 系统当中的「攻击」描述文字
s2 = $data_system.words.skill # 系统当中的「技能」描述文字
s3 = $data_system.words.guard # 系统当中的「防御」描述文字
s4 = $data_system.words.item # 系统当中的「物品」描述文字
这些文字都可以在数据库的系统的用语里面改变。
然后在初始化行动命令窗口的时候,作为参数返回给系统。
系统会根据这些需要描述的文字,决定窗口行数与高度。
至于语法当中的160,就是窗口的宽。
至于列数,默认脚本没有定义。但是我们可以在Window_Command当中动手脚。
然后改变一下「行动命令窗口」的y值(横向位置)
@actor_command_window.y = 160
再改变一下「行动命令窗口」的透明度
@actor_command_window.back_opacity = 160
最后是把「行动命令窗口」活动状态冻结起来(不能作出选择)
@actor_command_window.active = false
并隐藏起来
@actor_command_window.visible = false
=.=凸这里是我最诟病的地方。
因为是在主体当中生成,结果全局的「行动命令窗口」都被锁死!所有人用统一的「行动命令窗口」。
当然,我们可以选择不在这里生成。然后只要在dispose(释放,解放)部分修改一下就可以了。
不过,请稍微记得这里的问题。在「战斗」部分我们再探讨这个诟病,到时候你就会知道我所言不虚。
原作者的「某设定」真是让人无爱……—o—|||(这不是人身攻击)
02.「战」或「逃」的选择窗口
@party_command_window = Window_PartyCommand.new
从这句看来,原作者的趣味有点怪异。(牢骚)
明明是「战」或「逃」的选择窗口,偏偏要用个「全体选择」这样漂亮的词汇来作为变量名字。让人一看之下不知所云。
不过也不影响,反正很多人都对他没有兴趣-v-|||。
03.帮助窗口
@help_window = Window_Help.new
这里还是稍微改变了窗口的透明度(这样比较好看)
@help_window.back_opacity = 160
一开始的时候这个窗口是隐藏的
@help_window.visible = false
这个帮助窗口的用途很大。除了技能、物品的功能描述以外,同时还在逃跑成功的时候提示「逃跑」,使用技能的时候提示技能名字,使用物品时候提示物品名字。在选择敌人时提示敌人名字,选择队友时候提示队友状态等等。这个还是在下次「见面」的时候再说吧!
04.角色状态的窗口
@status_window = Window_BattleStatus.new
这里就是我们看到sp,hp,人物名字,当前状态的窗口。
在
脚本:Window_BattleStatus
方法:refresh
line:39
当中调整
主要作用是描绘血条。具体方法就不说了,一般人都是由血条描绘学起的。
05.信息窗口
@message_window = Window_Message.new
也就是战斗事件当中的对话窗口。没有甚么好说,价值不多,需要改动的人也好像很少。(据我所知)
3.生成活动块
@spriteset = Spriteset_Battle.new
这里调用的是Spriteset_Battle脚本,作用是生成战斗参与者(我方+敌方)的图象。
具体不说,反正不会改动到。而且也不是三两语可以解释清楚的。
# 初始化等待计数
@wait_count = 0
建立了这么一个全类变量而已,具体作用在后面才会提到。主要处理动画进行当中的等待行为。
4.执行过渡(窗口的切换)
# 执行过渡
if $data_system.battle_transition == ""
Graphics.transition(20)
else
Graphics.transition(40, "Graphics/Transitions/" +
$data_system.battle_transition)
end
进行从以 freeze 方法固定的画面到现在画面的渐变,其实也就是遇敌的画面。设置位置忘记了=v=,知道的同学告诉一下。
5.战斗
不要相信注释 囧rz 这里的自动战斗回合真的不知所云。反正知道这里开始调用战斗更新方法,战斗开始了就好……
留以后再说,这个是一个颇重要的语法。(大概==|||)
6.更新
# 主循环
loop do
# 刷新游戏画面
Graphics.update
# 刷新输入信息
Input.update
# 刷新画面
update
# 如果画面切换的话就中断循环
if $scene != self
break
end
end
从F1我们知道loop do是无限循环语法,直到我们说break(破坏,中断)才停止。
在loop do循环当中,我们不断地调用
# 刷新游戏画面
Graphics.update
# 刷新输入信息
Input.update
# 刷新画面
update
这三个方法。它们使得我们的画面不断被更新,从而达到战斗的效果。
其中:
Graphics.update用于不断地刷新画面(必要语句)
Input.update则在不断监视我们是否有按下键盘上任何的键(必要语句)
然后,update才是我们需要注意的最重要的方法。
它提供了整个战斗过程的解释,我们将会在下面详细地解析一下。现在不是时候,我们还是继续解读main方法。
# 如果画面切换的话就中断循环
if $scene != self
break
end
也就是当$scene发生改变的时候就结束战斗。这个判断语法的作用是:一旦我们改变变量$scene,战斗就会被强制中断。
这里的作用一定要记住,这是个满重要的语法,一般来说必不可少,而且不对它作出任何的修改。
7.刷新地图
如同解释所说,当我们通过了,而且中止了loop do的无限循环后,通常我们就会重新返回到地图画面(测试除外)。然后刷新一下地图,这里的刷新,其实主要的还是对于公共事件以及地图事件事件的更新。也就是说,战斗以后应该消失的事件就让它消失,得到物品就得到物品,完成任务就完成任务。
8.释放所有窗口以及活动块 # 准备过渡
Graphics.freeze
# 释放窗口
@actor_command_window.dispose
@party_command_window.dispose
@help_window.dispose
@status_window.dispose
@message_window.dispose
if @skill_window != nil
@skill_window.dispose
end
if @item_window != nil
@item_window.dispose
end
if @result_window != nil
@result_window.dispose
end
# 释放活动块
@spriteset.dispose
# 标题画面切换中的情况
if $scene.is_a?(Scene_Title)
# 淡入淡出画面
Graphics.transition
Graphics.freeze
end
# 战斗测试或者游戏结束以外的画面切换中的情况
if $BTEST and not $scene.is_a?(Scene_Gameover)
$scene = nil
end
释放所有当前存在的窗口,不要让它们留在画面当中。
这里要说一下的是:
根据F1所说:
「准备渐变,固定现在的画面。从这之后一直到调用 transition 方法,其间禁止一切画面更换。」
在这个语法调用的时候,整个画面都会被锁死。不会进行任何的update(刷新)行为。
如果能理解就最好,不能理解也没差。反正一般不需要修改。
另外就是:
line:78以下的几个判断
if @skill_window != nil
@skill_window.dispose
end
if @item_window != nil
@item_window.dispose
end
if @result_window != nil
@result_window.dispose
end
这里的判断主要是释放不是在main当中生成的窗口。比如:
@skill_window # 技能选择窗口
@item_window # 物品选择窗口
@result_window # 战斗结果窗口
这些脚本都是在update过程当中应时生成的。通过这个语法,当最后它们仍然存在的时候(!=nil),就会自动释放。否则,如果直接释放就出现NoMethodError「undefined method 'dispose' for nil:NilClass 」的提示。
此外,还记得上面说过的「诟病」吗?
我说过如果不在main当中生成的窗口,都可以在这里用上述方法释放。(以防万一)
如果选择在update当中生成「行动命令窗口」(如同我所说的一样。),就必须在这里改变dispose方法。
这样说,应该比较清楚吧?
另外,当战斗测试或者游戏结束中,战斗结束后会把$scene归nil,当$scene = nil的时候,我们的游戏会释放窗口,然后跳出结束程序。
至于:
# 标题画面切换中的情况
if $scene.is_a?(Scene_Title)
# 淡入淡出画面
Graphics.transition
Graphics.freeze
end
作用就如同遇敌画面一样:
在战斗结束之后用渐变的方式返回地图。
作用就是让画面好看一点……Orz
main 方法至此大功告成。大家对于main 这个方法总算有了一点理解了吧?
整个战斗画面就是按照这样的逻辑进行。至于更详细的解读,就看下一贴。关于update方法的解读。
如果对于当中的解读有任何的异议或者补充,禾西非常欢迎有人就这个题目来一同「探讨」。
PS:文字是用word转的,有任何错误恕不负责=v=+
============================================================================这里,让我们继续解读战斗画面
在main以后,我们首先遇到judge,然后是battle_end(result),接着是setup_battle_event。
这些方法我们都暂时跳过不看。因为按照我们现在的思维,我们无法理解。
最后来到
line:220
记得在main方法当中(line:62),我们曾经遇到过update的调用。
对于方法的调用,Ruby(或者RGSS)没有先定义的必要。因此,这里我们先调用了update,然后再在后面定义是完全没有问题的。
update在英语当中解释为更新,在这里更多地表示画面的改变。通过这个语法,我们才能实现「战斗」的效果。否则画面一闪而过,我们不知道发生甚么事就结束了战斗,是件很囧的事情。
原則上,update會不斷地調用(大概一帧一次,亦就是1/40秒一次。)
OK,废话结束。下面我们还是看一下update里面有甚么东西吧!
def update
1.执行战斗事件
2.系统 (计时器)、刷新画面
3.刷新各窗口
4.「冻结」战斗画面
5.进行战斗
end
1.执行战斗事件
line:221
# 执行战斗事件中的情况下
if $game_system.battle_interpreter.running?
# 刷新解释器
$game_system.battle_interpreter.update
# 强制行动的战斗者不存在的情况下
if $game_temp.forcing_battler == nil
# 执行战斗事件结束的情况下
unless $game_system.battle_interpreter.running?
# 继续战斗的情况下、再执行战斗事件的设置
unless judge
setup_battle_event
end
end
# 如果不是结束战斗回合的情况下
if @phase != 5
# 刷新状态窗口
@status_window.refresh
end
end
end
上面这些语句非常复杂,主要是用来进行战斗事件的。所谓「战斗事件」,就是我们在数据库-队伍-战斗事件当中设定的所有行为。当中把一个队伍当作一个单独事件来使用。余下的不说太多。事件的设置是新手知识。
由于这里的复杂性,因此解说相对充分。
这里想补充一下几点:
1.
# 执行战斗事件中的情况下
if $game_system.battle_interpreter.running?
这个语法的根本在Interpreter 1的60行
def running?
return @list != nil
end
当自身的列表为空的时候就返回true。这个有点难以理解,不过一般说来很少人需要动它。值得我们留意的是231行的setup_battle_event
这是我们跳过了的方法,刚才我们没有办法读懂,但是现在我们可以再回头去看它。(update部分暂时放下)
他的执行条件值得深究。
一共有四重条件
1.当执行战斗事件中
2.当「强制行动的战斗者」不存在
3.unless(「除非……否则」,英语中作为if的反意词)执行战斗事件结束
4.unless 继续战斗(judge为true)-judge为true的时候结束战斗,为false时继续战斗
关于$game_system.battle_interpreter.running?的问题,我们暂时不研究。因为这个关系到事件解释的问题,就算RTAB脚本也没有动它。
比较吸引我们注意的,应该是那几句刚才skiped(跳过了)的方法:judge,setup_battle_event。
首先是judge
line:103
def judge
# 全灭判定是真、并且同伴人数为 0 的情况下
if $game_party.all_dead? or $game_party.actors.size == 0
# 允许失败的情况下
if $game_temp.battle_can_lose
# 还原为战斗开始前的 BGM
$game_system.bgm_play($game_temp.map_bgm)
# 战斗结束
battle_end(2)
# 返回 true
return true
end
# 设置游戏结束标志
$game_temp.gameover = true
# 返回 true
return true
end
# 如果存在任意 1 个敌人就返回 false
for enemy in $game_troop.enemies
if enemy.exist?
return false
end
end
# 开始结束战斗回合 (胜利)
start_phase5
# 返回 true
return true
end
这个方法是用来判断「胜」或「败」的。因为方法自身能够被当作变量使用,所以judge有true or false的值,通过return语法(结束并返回值)来付予。
另外,重复一下:judge为true的时候结束战斗,为false时继续战斗
这里是判断「是否需要继续战斗」的方法,条件见「注释」:
# 全灭判定是真、并且同伴人数为 0 的情况下
if $game_party.all_dead? or $game_party.actors.size == 0
下面出现了个分歧
# 允许失败的情况下
if $game_temp.battle_can_lose
end
# 否则:
# 设置游戏结束标志
$game_temp.gameover = true
# 返回 true
return true
这里主要用于「明雷」(通过事件发生战斗)。
如果允许失败,就: # 还原为战斗开始前的 BGM
$game_system.bgm_play($game_temp.map_bgm)
# 战斗结束,返回参数「2」
battle_end(2)
# 返回 true否则:
# 设置游戏结束标志
$game_temp.gameover = true
# 返回 true
return true
这里我们看到调用了一个battle_end(2)的方法,在下面line:135我们找到他的身影
#--------------------------------------------------------------------------
# ● 战斗结束
# result : 结果 (0:胜利 1:失败 2:逃跑)
#--------------------------------------------------------------------------
def battle_end(result)
end
2是对于结果(result)的付值。通过注释我们知道2是等于逃跑的。不过其实意义不大。整个方法当中只有在
# 调用战斗返回调用
if $game_temp.battle_proc != nil
$game_temp.battle_proc.call(result)
$game_temp.battle_proc = nil
end
当中有调用。
作用是告诉Interpreter(事件解释器)这场战斗的结果,然后,根据战斗的结果控制分歧。其余的解释,用到再说。
重新跑回line:157,我们看看setup_battle_event究竟有甚么作为?
line:157
def setup_battle_event
# 正在执行战斗事件的情况下
if $game_system.battle_interpreter.running?
return
end
# 搜索全部页的战斗事件
for index in 0...$data_troops[@troop_id].pages.size
# 获取事件页
page = $data_troops[@troop_id].pages[index]
# 事件条件可以参考 c
c = page.condition
# 没有指定任何条件的情况下转到下一页
unless c.turn_valid or c.enemy_valid or
c.actor_valid or c.switch_valid
next
end
# 执行完毕的情况下转到下一页
if $game_temp.battle_event_flags[index]
next
end
# 确认回合条件
if c.turn_valid
n = $game_temp.battle_turn
a = c.turn_a
b = c.turn_b
if (b == 0 and n != a) or
(b > 0 and (n < 1 or n < a or n % b != a % b))
next
end
end
# 确认敌人条件
if c.enemy_valid
enemy = $game_troop.enemies[c.enemy_index]
if enemy == nil or enemy.hp * 100.0 / enemy.maxhp > c.enemy_hp
next
end
end
# 确认角色条件
if c.actor_valid
actor = $game_actors[c.actor_id]
if actor == nil or actor.hp * 100.0 / actor.maxhp > c.actor_hp
next
end
end
# 确认开关条件
if c.switch_valid
if $game_switches[c.switch_id] == false
next
end
end
# 设置事件
$game_system.battle_interpreter.setup(page.list, 0)
# 本页的范围是 [战斗] 或 [回合] 的情况下
if page.span <= 1
# 设置执行结束标志
$game_temp.battle_event_flags[index] = true
end
return
end
end
这里我们可以看到作者的细心。因为setup_battle_event的其中一个条件是「当执行战斗事件中」
# 执行战斗事件中的情况下
if $game_system.battle_interpreter.running?
但是,实际上他真正需要的条件是
# 执行战斗事件结束的情况下
unless $game_system.battle_interpreter.running?
在英语当中,if 和 unless 是一对反意词。(if 是「当」;unless是「不当」。但是中文没有这个词语,因此我们姑且称它「除非……否则」),这里本来是一个矛盾的判断,但是由于当中调用了
line:224
$game_system.battle_interpreter.update
而使得这组矛盾的判断成立,具体原因不需要懂(至少暂时不需要,如果有兴趣的话可以看一下interpreter的脚本)。
回到正题,因为这里调用了一个「矛盾」的条件判断。原本的作者恐怕程序会出错(虽然少见,但是很正常的事。),他在这里多建立了一个判断:
# 正在执行战斗事件的情况下
if $game_system.battle_interpreter.running?
return
end
这句的意思大概是「当正在执行战斗事件时(出现错误)」,return(在Ruby当中表示方法「结束」)。这样子,可以减少出错的机会。
然后检索所有的战斗事件页(这个就是事件太多会减慢运行速度的原因,搜索全部的事件页是需要不少内存以及时间的。)
# 搜索全部页的战斗事件
for index in 0...$data_troops[@troop_id].pages.size
# 获取事件页
page = $data_troops[@troop_id].pages[index]
替换变量,把事件的所有条件都记录在临时变量「c」(只能在本方法中调用)当中。当然这个做法是为了让脚本看起来更清爽,减少程序员打字动作,但是弄得脚本模糊不清的一个方法。牢骚就不发了,毕竟自己也常常喜欢这样。
# 事件条件可以参考 c
c = page.condition
在取得条件以后,就进行确认条件的动作。当条件复合,就建立并运行事件,此外就结束方法。
这个是比较复杂的问题,就算说了也未必清楚。因此这里稍微带过,毕竟这下的目的不是弄清「事件」的运作方法。==|||
2.系统 (计时器)、刷新画面
line:242
# 系统 (计时器)、刷新画面
$game_system.update
$game_screen.update
# 计时器为 0 的情况下
if $game_system.timer_working and $game_system.timer == 0
# 中断战斗
$game_temp.battle_abort = true
end
还记得地图事件上面的「定时器操作」这个选项无?这里的作用就是
$game_system.update # 更新定时器
$game_screen.update # 刷新画面
主要用作限时战斗,当定时器为0时,战斗会自动结束:
# 计时器为 0 的情况下
if $game_system.timer_working and $game_system.timer == 0
# 中断战斗
$game_temp.battle_abort = true
end
大概就是这个用途而已……-o-
3.刷新各窗口
# 刷新窗口
@help_window.update # 刷新帮助窗口
@party_command_window.update # 刷新「战」或「逃」选择窗口
@actor_command_window.update # 刷新「行动命令窗口」
@status_window.update # 刷新「角色状态窗口」
@message_window.update # 刷新「信息窗口」
所有在main当中生成的窗口都需要在这里进行更新。不是的就免了,会发生NoMathodError的。
# 刷新活动块
@spriteset.update
如同注释
# 处理过渡中的情况下
if $game_temp.transition_processing
# 清除处理过渡中标志
$game_temp.transition_processing = false
# 执行过渡
if $game_temp.transition_name == ""
Graphics.transition(20)
else
Graphics.transition(40, "Graphics/Transitions/" +
$game_temp.transition_name)
end
end
执行过渡(也就是渐变),这里的注释很清楚,不需要重复了。
4.「冻结」战斗画面 # 显示信息窗口中的情况下
if $game_temp.message_window_showing
return
end
# 显示效果中的情况下
if @spriteset.effect?
return
end
# 游戏结束的情况下
if $game_temp.gameover
# 切换到游戏结束画面
$scene = Scene_Gameover.new
return
end
# 返回标题画面的情况下
if $game_temp.to_title
# 切换到标题画面
$scene = Scene_Title.new
return
end
# 中断战斗的情况下
if $game_temp.battle_abort
# 还原为战斗前的 BGM
$game_system.bgm_play($game_temp.map_bgm)
# 战斗结束
battle_end(1)
return
end
# 等待中的情况下
if @wait_count > 0
# 减少等待计数
@wait_count -= 1
return
end
# 强制行动的角色存在、
# 并且战斗事件正在执行的情况下
if $game_temp.forcing_battler == nil and
$game_system.battle_interpreter.running?
return
end
这里有点趣味,原因是这里是冻结窗口画面的判断语句。但是这里所说的「冻结」,并不是真正意义上的冻结。只是结束update的方法,不进行接下来的战斗画面而做出的「伪?冻结」
冻结的「原因」很多,比如:
01.
# 显示信息窗口中的情况下
if $game_temp.message_window_showing
return
end
这里冻结的理由是信息窗口在开启当中,证明正在进行对话。因此不「想」有动作打扰而冻结画面。
02.
# 显示效果中的情况下
if @spriteset.effect?
return
end
因为战斗效果显示正在当中而冻结,很合理。不过呢,RTAB的脚本当中删除了这个冻结的判断,从而实现实时战斗效果(技能效果)的显示。
03.
# 游戏结束的情况下
if $game_temp.gameover
# 切换到游戏结束画面
$scene = Scene_Gameover.new
return
end
因为战斗失败而冻结……(紧止鞭尸@=o=)
04.
# 返回标题画面的情况下
if $game_temp.to_title
# 切换到标题画面
$scene = Scene_Title.new
return
end
返回标题画面,因为渐变执行当中而冻结画面。
05.
# 中断战斗的情况下
if $game_temp.battle_abort
# 还原为战斗前的 BGM
$game_system.bgm_play($game_temp.map_bgm)
# 战斗结束
battle_end(1)
return
end
战斗中断,因为渐变执行当中而冻结画面。
06.
# 等待中的情况下
if @wait_count > 0
# 减少等待计数
@wait_count -= 1
return
end
由于战斗动画正在播放,所以全体等待。
07.
# 强制行动的角色存在、
# 并且战斗事件正在执行的情况下
if $game_temp.forcing_battler == nil and
$game_system.battle_interpreter.running?
return
end
事件执行当中,而全体人员行动不能。
如果还想加点甚么冻结判断,或者消除那些冻结判断(比如鞭尸的恶趣味 囧rz),都可以在这里改。
5.进行战斗
# 回合分支
case @phase
when 1 # 自由战斗回合
update_phase1
when 2 # 同伴命令回合
update_phase2
when 3 # 角色命令回合
update_phase3
when 4 # 主回合
update_phase4
when 5 # 战斗结束回合
update_phase5
end
从这里看到,更新那段战斗画面是由@phase决定的。(RTAB当中的RT条就是靠增加了@phase == 0时候的更新实现的。)
这个是战斗画面的重点,留到下次再说。希望这样的解说对于update的运作还算清晰。 |
|