赞 | 97 |
VIP | 0 |
好人卡 | 1 |
积分 | 76 |
经验 | 10334 |
最后登录 | 2024-6-22 |
在线时间 | 1227 小时 |
Lv4.逐梦者
- 梦石
- 0
- 星屑
- 7618
- 在线时间
- 1227 小时
- 注册时间
- 2008-12-14
- 帖子
- 555
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 if216 于 2020-5-18 02:04 编辑
出处
https://github.com/futokoro/RPGMaker
原文链接
https://github.com/futokoro/RPGMaker/blob/master/battleSystem.md。
我正在研发这个:https://rpg.blue/thread-481629-1-1.html
所以顺便翻了文章。
正文:
战斗系统的解析
作为插件创建的笔记,内容大体如下:
1.战斗场景的呼出
2.在地图场景和战斗场景之间切换
3.战斗镜头的初始化
4.战斗的开始
5.选择命令
6.回合处理
7.回合终了
8.战斗中断的判定
9.战斗终了
除非战斗终了,否则「选择命令」~「战斗中断的命令」重复。
【战斗场景的呼出】
战斗场景呼出的方法、以下两种方式。
在地图上遇到
事件中执行「战斗处理」
在地图上遇到
Scene_Map.prototype.update()内的Scene_Map.prototype.updateScene()下
Scene_Map.prototype.updateEncounter()执行
Scene_Map.prototype.updateEncounter = function() {
if ($gamePlayer.executeEncounter()) {
SceneManager.push(Scene_Battle);
}
};
$gamePlayer.executeEncounter()判定
Game_Player.prototype.executeEncounter = function() {
if (!$gameMap.isEventRunning() && this._encounterCount <= 0) {
this.makeEncounterCount();
var troopId = this.makeEncounterTroopId();
if ($dataTroops[troopId]) {
BattleManager.setup(troopId, true, false);
BattleManager.onEncounter();
return true;
} else {
return false;
}
} else {
return false;
}
};
内部的处理
Game_Player._encounterCount是随着玩家在地图上移动而减小的值。 计数(敌人出现的步数)。 如果此值等于或小于0,
请执行以下操作:
$gamePlayer.makeEncounterCount()
遭遇战斗计数重置(敌人出现的步数)以参与战斗。
BattleManager.setup(troopId, true, false)
战斗的初始化。内部执行以下:
BattleManager.setup = function(troopId, canEscape, canLose) {
this.initMembers(); //BattleManager类的初期化
this._canEscape = canEscape; //逃走可能标志(可能还是要战斗)
this._canLose = canLose; //失败可能标志(遭遇战斗不可)
$gameTroop.setup(troopId); //出现的敌人团体的设定
$gameScreen.onBattleStart(); //停止事件命令的“屏幕”效果。イベントコマンドによる「画面」効果を止める。
this.makeEscapeRatio(); //逃走率的计算
};
BattleManager.onEncounter()
先发制人的攻击和突击的判定
单击后执行
SceneManager.push(Scene_Battle)执行、战斗场景的予约。
SceneManager.push = function(sceneClass) {
this._stack.push(this._scene.constructor);//现在的场景保存
this.goto(sceneClass);//向下一个场景移动
};
SceneManager.goto()内,以下处理被执行。
SceneManager.goto = function(sceneClass) {
if (sceneClass) {
this._nextScene = new sceneClass();//将输入场景保留到下一个场景
}
if (this._scene) {
this._scene.stop();//现在的场景终了处理
}
};
结果,操作了终止地图场景并切换到战斗场景的过程。
事件中执行「战斗处理」
Game_Interpreter.prototype.command301()执行
Game_Interpreter.prototype.command301 = function() {
if (!$gameParty.inBattle()) {
var troopId;
if (this._params[0] === 0) { // Direct designation
troopId = this._params[1];
} else if (this._params[0] === 1) { // Designation with a variable
troopId = $gameVariables.value(this._params[1]);
} else { // Same as Random Encounter
troopId = $gamePlayer.makeEncounterTroopId();
}
if ($dataTroops[troopId]) {
BattleManager.setup(troopId, this._params[2], this._params[3]);
BattleManager.setEventCallback(function(n) {
this._branch[this._indent] = n;
}.bind(this));
$gamePlayer.makeEncounterCount();
SceneManager.push(Scene_Battle);
}
}
return true;
};
内部处理
BattleManager.setup(troopId, canEscape, canLose)
战斗的初期化处理。逃走可否,敗北可否、取决于事件命令的设置。
BattleManager.setEventCallback(callback)
保留这些事件,以便在战斗结束后执行胜,败事件的相应处理。
$gamePlayer.makeEncounterCount()
重设遭遇战的步数计数
SceneManager.push(Scene_Battle)战斗场景的预约。
在地图场景和战斗场景之间切换
Scene_Map.prototype.stop()内Scene_Map.prototype.launchBattle执行。
Scene_Map.prototype.launchBattle = function() {
BattleManager.saveBgmAndBgs(); //現在的BGM和BGS保存
this.stopAudioOnBattleStart(); //播放的音效停止
SoundManager.playBattleStart(); //战斗開始时的SE鳴响
this.startEncounterEffect(); //执行效果以切换到战斗场景
this._mapNameWindow.hide();
};
对战场执行切换效果
Scene_Map.prototype.startEncounterEffect = function() {
this._spriteset.hideCharacters();
this._encounterEffectDuration = this.encounterEffectSpeed();
};
这之后、Scene_Map.prototype.update()中执行以下操作
Scene_Map.prototype.updateEncounterEffect()
Scene_Map.prototype.updateEncounterEffect = function() {
if (this._encounterEffectDuration > 0) {
this._encounterEffectDuration--;
var speed = this.encounterEffectSpeed();
var n = speed - this._encounterEffectDuration;
var p = n / speed;
var q = ((p - 1) * 20 * p + 5) * p + 1;
var zoomX = $gamePlayer.screenX();
var zoomY = $gamePlayer.screenY() - 24;
if (n === 2) {
$gameScreen.setZoom(zoomX, zoomY, 1);
this.snapForBattleBackground(); //現在的画面作为快照保存
this.startFlashForEncounter(speed / 2);
}
$gameScreen.setZoom(zoomX, zoomY, q);
if (n === Math.floor(speed / 6)) {
this.startFlashForEncounter(speed / 2);
}
if (n === Math.floor(speed / 2)) {
BattleManager.playBattleBgm(); //战斗BGM播放
this.startFadeOut(this.fadeSpeed()); //淡出開始
}
}
};
处理完成后,地图场景将完全结束,并切换到战斗场。
战斗场景的構成
RPGmaker MV的与战斗流程有关的类如下。
战斗流程有关的类
rpg_scenes.js
oScene_Battle类
rpg_managers.js
oBattleManager 类
这些类的处理将在战斗场景流程的基础知识中进行解释。 此外,每个类别的主从关系:主是Scene_Battle,在BattleManager
中是从属。 首先,Scene_Battle进行处理,然后在其中运行BattleManager。
战斗场景显示的类
rpg_sprites.js
oSpriteset_Battle类 …以下的Sprite_***的全体类、战斗背景也在这表示
oSprite_Actor类 …主要是表示使用者的SV角色的类,在前视图中也使用。
oSprite_Enemy类
oSprite_Animation类 …战斗动画制作的表示
oSprite_Damage类 …显示伤害弹出
oSprite_StateOverlay类 ...在演员的SV角色上显示状态叠加动画
oSprite_StateIcon类 …在敌人中显示状态图标
oSprite_Weapon类 …在演员的SV角色的动作上显示武器图像
rpg_windows.js
oWindow_BattleLog类 …虽然是显示战斗日志的类,但也控制战斗动画和损伤弹出的时机等。
oWindow_PartyCommand类
oWindow_ActorCommand类
oWindow_BattleStatus类
oWindow_BattleActor类
oWindow_BattleEnemy类
oWindow_BattleSkill类
oWindow_BattleItem类
这些类的处理将在显示战斗场景的基础上进行解释。
战斗场景中与数据及其处理有关的类
rpg_objects.js
oGame_Temp类 …保留常见事件时的存储位置
oGame_System类
oGame_Switches类
oGame_Variables类
oGame_Screen类 …除了控制屏幕效果(闪光,抖动等)外,它还涉及在事件发生时显示图片
oGame_Item类 …技能和物品数据管理
oGame_Action类 …控制使用技能和物品的效果(成功/失败,避免击中,损坏金额等)
oGame_ActionResult类 …管理使用技能和物品的结果
oGame_Actor类
oGame_Enemy类
oGame_Party类
oGame_Troop类 …组织敌方团体的类,以及控制为敌方团体设定的战斗事件的类
oGame_Interpreter类 …控制公共和战斗事件中事件命令的执行
战斗场景の流程基础
在PRG Maker MV中,战斗场景流程大致分为七个过程。这些过程中的每一个在此都称为阶段(* 1)。 * 1您可以在
BattleManager._phase中获得战斗的当前阶段。
七个阶段如下
# 阶段名称 BattleManager._phaseの内容
1 战斗初始化阶段 init
2 战斗开始阶段 start
3 命令输入阶段 input
4 回合阶段 turn
5 行动阶段 action
6 回合结束阶段 turnEnd
7 战斗结束阶段 battleEnd
在每个阶段中,“战斗初始化”,“战斗开始”和“战斗结束”阶段在每个战斗中执行一次,但是“命令输入”,“回合”,
“动作”和“结束回合”阶段为只要继续执行就执行。 从“命令输入”到“回合结束”的一系列流程意味着战斗中只有一回合
。
同样,在一回合内,对参与战斗的每个演员和敌人重复执行“回合”和“行动”阶段。例如,如果演员1和演员2与敌人1参加战
斗,
命令输入阶段 ⇒
Actor1的回合(開始) ⇒Actor1的行动阶段 ⇒ Actor1的回合(结束) ⇒
Actor2的回合(開始) ⇒Actor2的行动阶段 ⇒ Actor2的回合(结束) ⇒
Enemey1的回合(開始) ⇒Enemey1的行动阶段 ⇒Enemey1的回合(结束) ⇒
回合终了阶段⇒
下一轮指令输入阶段 ⇒...
像这样,回合前进。
在下文中将描述每个阶段的处理内容。
回到战斗场景的基础上
战斗初始化阶段
在战斗初始化阶段,首先进行战斗场面的启动处理。
1.首先,战斗场景作成
Scene_Battle.prototype.create()
2.接下来,执行战斗场景开始处理
Scene_Battle.prototype.start()
3.之后,重复执行更新处理,直到战斗场景结束
Scene_Battle.prototype.update()
create
Scene_Battle.prototype.create = function() {
Scene_Base.prototype.create.call(this);
this.createDisplayObjects();
};
在核心脚本中
、Scene_Base.prototype.create是空的(什么都不做)。
Scene_Battle.prototype.createDisplayObjects = function() {
this.createSpriteset();
this.createWindowLayer();
this.createAllWindows();
BattleManager.setLogWindow(this._logWindow);
BattleManager.setStatusWindow(this._statusWindow);
BattleManager.setSpriteset(this._spriteset);
this._logWindow.setSpriteset(this._spriteset);
};
在此,生成诸如构成战斗画面,背景和窗口的角色图像之类的对象。
对象生成顺序,生成顺序如下。
1.Spriteset_Battle
i.战斗背景的基础
ii.map中设定的战斗背景
iii.Enemy角色
ive.使用者角色(在前视图中生成透明角色)
2.战斗日志窗口Window_BattleLog
3.状态窗口Window_BattleStatus
4.party命令窗口
5.actor命令窗口
6.帮助窗口
7.技能选择窗口
8.物品选择窗口
9.使用者选择窗口
10.敌人窗口
11.消息窗口
12.文本滚动窗口
关联对象
以下对象与BattleManager相关联。
Spriteset_Battle
Window_BattleLog
Window_BattleStatus
这是为了在BattleManager中控制各种精灵,战斗日志,状态显示。
Spriteset_Battle还与Window_BattleLog相关联。 这是因为,为了配合战斗记录的显示时机和技能的动作和动画的显示时机
,Window_BattleLog方面控制着精灵。
层
另外,由于Spriteset_Battle和战斗场景窗口与其他层相关联地显示,因此即使精灵和窗口重叠也可以透过显示。 但是,如果
在同一层上显示的内容重叠,例如精灵和窗口,则不透明,只显示后来生成的对象。
start
Scene_Battle.prototype.start()执行。在其中执行BattleManager.startBattle()
Scene_Battle.prototype.start = function() {
Scene_Base.prototype.start.call(this);
this.startFadeIn(this.fadeSpeed(), false); //淡入执行
BattleManager.playBattleBgm(); //战斗BGM播放
BattleManager.startBattle();
};
BattleManager.startBattle()中、将战斗阶段更改为‘start’。
BattleManager.startBattle = function() {
this._phase = 'start'; //开始战斗阶段
$gameSystem.onBattleStart(); //战斗次数增加1
$gameParty.onBattleStart(); //行为状态,sv角色的动作和tp 初始化
$gameTroop.onBattleStart(); //行为状态,tp 初始化
this.displayStartMessages(); //显示战斗开始时的消息
};
行为状态(ActionState)
用于设置该角色当前状态的参数。 (造词)
undecided(未定),inputting(正在键入命令),waitting(待機中),acting(行動中)的任一个字符串存储。
战斗开始时就会变成undecided状态。
update
Scene_Battle.prototype.update的处理内容如下。
Scene_Battle.prototype.update = function() {
var active = this.isActive();
$gameTimer.update(active);
$gameScreen.update();
this.updateStatusWindow();
this.updateWindowPositions();
if (active && !this.isBusy()) {
this.updateBattleProcess();
}
Scene_Base.prototype.update.call(this);
};
$gameTimer.update(active)
计时器更新。
$gameScreen.update()
画面効果处理更新。
Scene_Battle.prototype.updateStatusWindow()
此过程控制状态窗口的显示/不显示。具体来说
显示消息时隐藏状态和命令窗口
没有消息显示时显示状态窗口
Scene_Battle.prototype.updateWindowPositions()
此过程控制状态窗口的显示位置。具体来说
在显示命令窗口时右对齐屏幕
在不显示命令窗口的情况下显示在屏幕中央
Scene_Battle.prototype.updateBattleProcess()
在此中、BattleManager.update()和Scene_Battle.prototype.changeInputWindow()被执行、处理战斗场面。
Scene_Battle.prototype.updateBattleProcess = function() {
if (!this.isAnyInputWindowActive() || BattleManager.isAborting() ||
BattleManager.isBattleEnd()) {
BattleManager.update();
this.changeInputWindow();
}
};
Scene_Base.prototype.update
Scene_Base.prototype.update = function() {
this.updateFade(); //更新屏幕淡入淡出效果
this.updateChildren(); //Scene_Battle的children更新
};
Scene_Base.prototype.updateChildren
更新addchild()中scene_battle的children对象。
addChild()でScene_Battleのchildrenにしたオブジェクトを更新する。
Scene_Base.prototype.updateChildren = function() {
this.children.forEach(function(child) {
if (child.update) {
child.update();
}
});
};
BattleManager.update
BattleManager.update()以下内容,按照战斗阶段进行战斗的过程。
BattleManager.update = function() {
if (!this.isBusy() && !this.updateEvent()) {
switch (this._phase) {
case 'start':
this.startInput();
break;
case 'turn':
this.updateTurn();
break;
case 'action':
this.updateAction();
break;
case 'turnEnd':
this.updateTurnEnd();
break;
case 'battleEnd':
this.updateBattleEnd();
break;
}
}
};
又、Scene_Battle.prototype.changeInputWindow()内容如下,战斗阶段为input时,执行操作者的指令选择处理。
Scene_Battle.prototype.changeInputWindow = function() {
if (BattleManager.isInputting()) {
if (BattleManager.actor()) {
this.startActorCommandSelection();//每个actor的命令显示和选择处理
} else {
this.startPartyCommandSelection();//party命令显示和选择过程
}
} else {
this.endCommandSelection();//隐藏命令窗口
}
};
BattleManager.isInputting确定是否输入战斗阶段。
BattleManager.isInputting = function() {
return this._phase === 'input';
};
战斗阶段开始时,使用BattleManager.update()执行以下操作。
BattleManager.startInput()
BattleManager.startInput = function() {
this._phase = 'input'; //预订下一阶段
$gameParty.makeActions(); //Actor行为的初始设置
$gameTroop.makeActions(); //初始化敌人的行为
this.clearActor(); //初始化参与者的选定状态,以便没有人被选中
if (this._surprise || !$gameParty.canInput()) {
this.startTurn(); //如果该命令出乎意料或Actor无法输入该命令,请执行该过程以转到‘turn’阶段
}
};
完成后,进入输入阶段。
補足
$gameParty.makeActions()
初始化参与者的动作。在此,从特征中读取每个演员的动作数,并设置可以输入命令的次数。
$gameTroop.makeActions()
初始化敌人的行为。对于敌人,请设置在此阶段要使用的技能。
BattleManager.clearActor()
初始化参与者的选定状态,以便没有人被选中。可以通过BattleManager.actor()获得参与者的选定状态。如
Scene_Battle.prototype.changeInputWindow()的内容中所述,有必要执行此过程,因为除非有人选择了party命令,否
则不会显示party命令。
$gameParty.canInput()
确定聚会上是否有人接受命令输入。不接受动作输入的状态为
1.隐藏(当设置为敌方组中的“出现在中间”并且尚未出现时)
2.将动作约束设置为“无”以外的状态
3.具有自动战斗的特征。 Actor没有隐藏的设置,但这是因为canInput()方法是演员和敌人通用的。
战斗场景的基础
【命令输入阶段】
战斗阶段input时、Scene_Battle.prototype.changeInputWindow()执行调用命令的方法
由于使用者以无人选择的状态开始,因此首先在scene_battle.prototype.startpartycommandselection()中显示party命令。
选择“战斗”命令以运行scene_battle.prototypecommandfight()。 在内部,执行
scene_battle.prototype.selectnextcommand()。
Scene_Battle.prototype.selectNextCommand = function() {
BattleManager.selectNextCommand();
this.changeInputWindow();
};
BattleManager.selectNextCommand()
将Actor选择转移到Party中的下一个角色。如果未选择任何人,则移至Party的开始。如果从战斗方的最后一个角色执行,则执行BattleManager.startTurn()。
将角色移动到下一个角色后,使用Scene_Battle.prototype.schangeInputWindow()显示角色命令。
选择战斗方最后一个角色的命令时,将执行移至turn阶段的方法。
BattleManager.startTurn = function() {
this._phase = 'turn'; //转到下一个阶段,turn阶段。
this.clearActor(); //谁都不选。
$gameTroop.increaseTurn(); //增加1个turn
this.makeActionOrders(); //设置Actor和Enemy的行为顺序。
$gameParty.requestMotionRefresh(); // SV角色动作的再设定。
this._logWindow.startTurn(); //回合开始的日志处理实行。
};
BattleManager.makeActionOrders()
设定演员和敌人的行动顺序。对于每个演员和敌人,按照以下方法将速度数字化,并以速度降序确定动作顺序。
Game_Action.prototype.speed = function() {
var agi = this.subject().agi; //角色的敏捷性(AGI)作为基础值
//该值与0到(5+敏捷性的25%)之间的随机值相加
var speed = agi + Math.randomInt(Math.floor(5 + agi / 4));
if (this.item()) {
speed += this.item().speed; //增加技能速度校正, 进一步增加速度补技能
}
if (this.isAttack()) {
//对于普通攻击,请为诸如actor之类的功能添加攻击速度校正值。
speed += this.subject().attackSpeed();
}
return speed;
};
【Turn阶段】
战斗阶段结束时执行BattleManager.updateTurn()。在回合阶段,将根据BattleManager.makeActionOrders()确定的动作顺序逐一执行动作。
此时,执行动作的角色存储在BattleManager._subject中。
BattleManager.updateTurn = function() {
$gameParty.requestMotionRefresh();
if (!this._subject) {
this._subject = this.getNextSubject();
}
if (this._subject) {
this.processTurn();
} else {
this.endTurn();
}
};
BattleManager.getNextSubject()
引用下一个行动顺序中的角色。在上面的if语句中,如果未设置动作执行字符,则执行此方法并将下一个动作顺序中的字符存储在BattleManager._subject中。
但是,如果每个人都已经采取了行动,即使执行该行动也将为null。
BattleManager.processTurn()
如果存在动作执行角色,则调用执行该角色选择的技能的过程。 一个角色执行两次此方法。
第一次是因为选择了动作而执行了动作执行处理,
第二次是在初始化动作之后执行结束处理,然后移至下一个角色。
BattleManager.processTurn = function() {
var subject = this._subject;
var action = subject.currentAction(); //参考该角色选择的动作
if (action) {
//如果角色处于困惑并且不采取任何措施,请改为普通攻击
action.prepare();
if (action.isValid()) { //确定是否可以执行所选的动作
this.startAction(); //调用技能执行过程
}
subject.removeCurrentAction(); //初始化所选动作
} else {//如果未选择任何操作,则执行以下过程
subject.onAllActionsEnd(); //执行该角色的动作结束处理
this.refreshStatus(); //重绘状态窗口
this._logWindow.displayAutoAffectedStatus(subject);
this._logWindow.displayCurrentState(subject);
this._logWindow.displayRegeneration(subject);
this._subject = this.getNextSubject(); //切换下一角色
}
};
Game_Battler.prototype.onAllActionsEnd()
针对该角色执行以下动作结束处理。 动作结果的初始化,状态取消的确定和增强。
Window_BattleLog.prototype.displayAutoAffectedStatus(subject)
显示被赋予技能目标角色的状态的状态日志
Window_BattleLog.prototype.displayCurrentState(subject)
在行动的角色现在被赋予的状态下,显示优先度最高的连续记录
Window_BattleLog.prototype.displayRegeneration(subject)
弹出HP再生率引起的HP损伤。
BattleManager.endTrun()
没有行动实行角色(全员行动完毕)的情况下,呼叫回合结束的处理。
BattleManager.endTurn = function() {
this._phase = 'turnEnd'; //下一阶段是turnEnd
this._preemptive = false; //先制攻撃标志关闭
this._surprise = false; //不意标志关闭
this.allBattleMembers().forEach(function(battler) {
battler.onTurnEnd();
this.refreshStatus();
this._logWindow.displayAutoAffectedStatus(battler);
this._logWindow.displayRegeneration(battler);
}, this);
//如果您使用事件命令的“行动强制”添加了操作,请清除该标志
if (this.isForcedTurn()) {
this._turnForced = false;
}
};
Game_Battler.prototype.onTurnEnd()
对参加战斗的所有角色实行回合结束处理。
Game_Battler.prototype.onTurnEnd = function() {
this.clearResult(); //行動結果的初始化
this.regenerateAll(); //HP、MP、TP恢复効果的発動
if (!BattleManager.isForcedTurn()) {
this.updateStateTurns(); //回合经过时 状态的更新
this.updateBuffTurns(); //回合经过时 状态的更新
}
this.removeStatesAuto(2); //回合经过时 释放状态
};
【回合结束阶段】
战斗阶段是turnEnd 时、BattleManager.updateTurnEnd()执行。但是,内容仅执行BattleManager.startInput()
BattleManager.updateTurnEnd = function() {
this.startInput();
};
【战斗中断的判定】
在战斗中,如果您符合以下条件1至4或执行条件5 BattleManager.endBattle()执行,并将阶段转换为battleEnd
1.技能效果的“逃跑”使派对全体人员逃走($gameParty.isEmpty())
2.执行事件命令“暂停战斗”(BattleManager.isAborting())
3.角色全滅($gameParty.isAllDead())
4.敌人全滅($gameTroop.isAllDead())
5.party指令「逃跑」成功
上述1~4的判定在battlemanager.checkbattleend()中执行
BattleManager.checkBattleEnd = function() {
if (this._phase) {
if (this.checkAbort()) {
return true;
} else if ($gameParty.isAllDead()) {
this.processDefeat();
return true;
} else if ($gameTroop.isAllDead()) {
this.processVictory();
return true;
}
}
return false;
};
BattleManager.checkBattleEnd()仅在BattleManager.updateEventMain()中没有发生战斗事件时才进行确定。
BattleManager.updateEventMain = function() {
$gameTroop.updateInterpreter();
$gameParty.requestMotionRefresh();
if ($gameTroop.isEventRunning() || this.checkBattleEnd()) {
return true;
}
$gameTroop.setupBattleEvent();
if ($gameTroop.isEventRunning() || SceneManager.isSceneChanging()) {
return true;
}
return false;
};
敌人全灭的场合=战斗勝利
BattleManager.processVictory = function() {
$gameParty.removeBattleStates();
$gameParty.performVictory();
this.playVictoryMe();
this.replayBgmAndBgs();
this.makeRewards();
this.displayVictoryMessage();
this.displayRewards();
this.gainRewards();
this.endBattle(0);
};
角色全滅的場合=战斗敗北
BattleManager.processDefeat = function() {
this.displayDefeatMessage();
this.playDefeatMe();
if (this._canLose) {
this.replayBgmAndBgs();
} else {
AudioManager.stopBgm();
}
this.endBattle(2);
};
各方都以“逃脱”的技能效果逃跑($gameParty.isEmpty()为真时)
执行事件命令“暂停战斗”(BattleManager.isAborting()为真)
BattleManager.checkAbort = function() {
if ($gameParty.isEmpty() || this.isAborting()) {
SoundManager.playEscape();
this._escaped = true;
this.processAbort();
}
return false;
};
BattleManager.processAbort = function() {
$gameParty.removeBattleStates();
this.replayBgmAndBgs();
this.endBattle(1);
};
根据this._escaped=true的处理,逃跑的实行和事件命令“战斗的中断”,逃跑判定。 执行Party命令“逃跑”并成功
Scene_Battle.prototype.commandEscape = function() {
BattleManager.processEscape();
this.changeInputWindow();
};
BattleManager.processEscape = function() {
$gameParty.performEscape();
SoundManager.playEscape();
var success = this._preemptive ? true : (Math.random() < this._escapeRatio); --->先制攻撃时、逃成功率为100%
if (success) {
this.displayEscapeSuccessMessage();
this._escaped = true;
this.processAbort(); ---> 成功后执行BattleManager.processAbort()
} else {
this.displayEscapeFailureMessage();
this._escapeRatio += 0.1;
$gameParty.clearActions();
this.startTurn();
}
return success;
};
BattleManager.endBattle()运行时,阶段转换为 battleEnd 。
BattleManager.endBattle = function(result) {
this._phase = 'battleEnd'; //下一阶段到 battleEnd 。
//战斗结束后,如果已经预定好了活动,回调。
if (this._eventCallback) {
this._eventCallback(result);
}
if (result === 0) {
$gameSystem.onBattleWin();
} else if (this._escaped) {
$gameSystem.onBattleEscape();
}
};
搭配YEP_BattleEngineCore的场合,在以下情况下不会执行BattleManager.checkBattleEnd()中的中断确定。
战斗阶段为 'actionList``actionTargetList``action``phaseChange 的場合
事件执行中
此外,在YEP_X_BattleSysATB的情况下,直接在BattleManager.update()下更改了BattleManager.checkBattleEnd(
)的处理。
【战斗终了阶段】
战斗阶段为 battleEnd 时、BattleManager.updateTurnEnd()执行。
BattleManager.updateBattleEnd = function() {
if (this.isBattleTest()) {
AudioManager.stopBgm();
SceneManager.exit();
} else if (!this._escaped && $gameParty.isAllDead()) {
if (this._canLose) {
$gameParty.reviveBattleMembers();
SceneManager.pop();
} else {
SceneManager.goto(Scene_Gameover);
}
} else {
SceneManager.pop();
}
this._phase = null;
};
【战斗中的事件执行】
通过战斗事件和技能项目的效果来执行事件,整理此时的处理流程,基本流程如下:
设置要执行的事件
执行设置事件
处理战斗事件
战斗事件集
战斗事件集中、$gameTroop.setupBattleEvent()执行。
参照设定为敌组的事件页面this.troop().pages,每页用this.meetsconditions(page)进行条件判定,用
this._interpreter.setup(page.list)设定满足条件的页面的事件。
Game_Troop.prototype.setupBattleEvent = function() {
if (!this._interpreter.isRunning()) {
if (this._interpreter.setupReservedCommonEvent()) {
return;
}
var pages = this.troop().pages;
for (var i = 0; i < pages.length; i++) {
var page = pages;
if (this.meetsConditions(page) && !this._eventFlags) {
this._interpreter.setup(page.list);
if (page.span <= 1) {
this._eventFlags = true;
}
break;
}
}
}
};
$gameTroop.setupBattleEvent()在、BattleManager.updateEventMain()中执行。
BattleManager.updateEventMain = function() {
$gameTroop.updateInterpreter();
$gameParty.requestMotionRefresh();
if ($gameTroop.isEventRunning() || this.checkBattleEnd()) {
return true;
}
$gameTroop.setupBattleEvent();
if ($gameTroop.isEventRunning() || SceneManager.isSceneChanging()) {
return true;
}
return false;
};
BattleManager.updateEventMain()在、BattleManager.updateEvent()中执行。 如下switch语句中的case所示,战斗事
件只能在start阶段,turn阶段或turnend阶段执行。
BattleManager.updateEvent = function() {
switch (this._phase) {
case 'start':
case 'turn':
case 'turnEnd':
if (this.isActionForced()) {
this.processForcedAction();
return true;
} else {
return this.updateEventMain();
}
}
return this.checkAbort();
};
战斗事件执行
要执行设置的事件,请运行$gameTroop.updateInterpreter()。
Game_Troop.prototype.updateInterpreter = function() {
this._interpreter.update();
};
Game_Interpreter.prototype.update = function() {
while (this.isRunning()) {
if (this.updateChild() || this.updateWait()) {
break;
}
if (SceneManager.isSceneChanging()) {
break;
}
if (!this.executeCommand()) {
break;
}
if (this.checkFreeze()) {
break;
}
}
};
$gameTroop.updateInterpreter()在、BattleManager.updateEventMain()中执行。
设置战斗事件后,由于$gameTroop.isEventRunning()确定为真,因此在BattleManager.updateEventMain()中不执行
$gameTroop.setupBattleEvent(),而是重复事件执行处理。
Game_Troop.prototype.isEventRunning = function() {
return this._interpreter.isRunning();
};
Game_Interpreter.prototype.isRunning = function() {
return !!this._list;
};
整理后,在Scene_Battle.prototype.update循环期间,通过反复运行$gameTroop.updateInterpreter()来推进事件。
Scene_Battle.prototype.update
oScene_Battle.prototype.updateBattleProcess()
BattleManager.update()
BattleManager.updateEvent()
BattleManager._phase仅在阶段是'start``turn``turnEnd‘时、执行BattleManager.updateEventMain()
$gameTroop.updateInterpreter()逐行执行设置的事件。
$gameTroop.isEventRunning()由于为真,因此updateEventMain()的返回值为真。
BattleManager.updateEventMain()的返回值为真,因此battlemanager.updateevent()的返回值为真。
由于BattleManager.updateEvent()的返回值为true,因此BattleManager._phase将在不执行每个阶段处理的情况下结束
处理。
※如果仅循环执行$gameTroop.updateInterpreter(),则事件不会继续执行。
使用YEP_BattleEngineCore的場合、BattleManager._phase为 ’start``turn``turnEnd``actionList``actionTargetList‘
的任一时刻BattleManager.updateEventMain()执行。
技能・物品効果事件的处理
【在战斗场景中显示精灵】
战斗场景中的Sprite由Spriteset_Battle类共同管理。此类产生的精灵是
1.战斗背景
2.在地图上设置战斗背景
3.敌人角色
4. Actor角色(在正面视图中,创建透明角色)
战斗场景精灵生成
Spriteset_Base.prototype.initialize = function() {
Sprite.prototype.initialize.call(this);
this.setFrame(0, 0, Graphics.width, Graphics.height);
this._tone = [0, 0, 0, 0];
this.opaque = true;
this.createLowerLayer();
this.createToneChanger();
this.createUpperLayer();
this.update();
};
Spriteset_Battle.prototype.createLowerLayer = function() {
Spriteset_Base.prototype.createLowerLayer.call(this);
this.createBackground();
this.createBattleField();
this.createBattleback();
this.createEnemies();
this.createActors();
};
Spriteset_Base.prototype.createToneChanger = function() {
if (Graphics.isWebGL()) {
this.createWebGLToneChanger();
} else {
this.createCanvasToneChanger();
}
};
Spriteset_Base.prototype.createUpperLayer = function() {
this.createPictures();
this.createTimer();
this.createScreenSprites();
};
战斗シーンスプライトの更新
Spriteset_Battle.prototype.update = function() {
Spriteset_Base.prototype.update.call(this);
this.updateActors();
this.updateBattleback();
};
战斗背景
敌人角色
Actor角色
演员精灵的生成
演员角色由Spriteset_Battle.prototype.createActors生成。
Spriteset_Battle.prototype.createActors = function() {
this._actorSprites = [];
for (var i = 0; i < $gameParty.maxBattleMembers(); i++) {
this._actorSprites = new Sprite_Actor();
this._battleField.addChild(this._actorSprites);
}
};
生成的精灵对象存储在spriteset_battle._actorsprites[n]中。 它还注册为Spriteset_Battle._battleFirld的children。
但是,此时生成的精灵对象与使用者数据没有关联。
new Sprite_Actor()生成使用者精灵,但此时执行的方法如下:
initialize()
oinitMembers()
createShadowSprite() 为阴影图像生成精灵
createWeaponSprite() 为武器图像生成精灵
createMainSprite() 现在为角色图像生成精灵
createStateSprite() 生成状态叠加精灵
osetBattler(battler) 与actor数据关联,但在生成精灵时为空数据
omoveToStartPosition() 设置初始位置
moveToStartPosition()
将演员精灵移动到初始位置。
Sprite_Actor.prototype.moveToStartPosition = function() {
this.startMove(300, 0, 0);
};
数値意思是、左起X座標を+300、Y座標+0、移動时間为0。
演员角色的位置和运动在“活动演员角色”中进行了说明。
与使用者数据相关联
当执行Spriteset_Battle.prototype.updateActors时,它将与actor数据链接。
Spriteset_Battle.prototype.updateActors = function() {
var members = $gameParty.battleMembers();
for (var i = 0; i < this._actorSprites.length; i++) {
this._actorSprites.setBattler(members);
}
};
在setBattler()中,按照Party的排列顺序,将使用者数据与使用者sprite相关联。
setBattler(battler)
Sprite_Actor.prototype.setBattler = function(battler) {
Sprite_Battler.prototype.setBattler.call(this, battler);
var changed = (battler !== this._actor);
if (changed) {
this._actor = battler;
if (battler) {
this.setActorHome(battler.index());
}
this.startEntryMotion();
this._stateSprite.setup(battler);
}
};
通过从空状态设置参与者数据来执行以下处理。
setActorHome(index)
在此,基准站立位置是根据演员的配置顺序来设定的。 (除了当前位置)
Sprite_Actor.prototype.setActorHome = function(index) {
this.setHome(600 + index * 32, 280 + index * 48);
};
以第一个角色的坐标(600,280)为基准,在x上各偏离32,在y上各偏离48。 另外,画面的左上方是(0,0)。
在该处理之前,由于在moveToStartPosition中将x坐标设定为300,因此战斗开始时的初期位置在画面外。
关于使用者精灵的位置和移动,将通过使用者精灵的移动进行说明。
startEntryMotion()
在这里,设定战斗开始时的使用者精灵的初期动作。
Sprite_Actor.prototype.startEntryMotion = function() {
if (this._actor && this._actor.canMove()) {
this.startMotion('walk');
this.startMove(0, 0, 30);
} else if (!this.isMoving()) {
this.refreshMotion();
this.startMove(0, 0, 0);
}
};
如果可以行动(this._actor.canMove()判定),则设定前进动作(walk),如果不能行动(赋予不能行动的状态等),则设
定与此时的行动者的状态相适应的动作。
并且,通过在startMove(0, 0, 30)中从战斗开始位置(画面外)移动到基准站立位置,进行战斗开始时从画面外移动的动作。
关于使用者精灵的动作,用使用者精灵的动作进行说明。
更新使用者精灵
使用者精灵的更新在Sprite_Actor.prototype.update中执行。 使用者精灵的更新内容及其顺序如下。
更新动画精灵
更新角色图像精灵
更新动画
更新损伤弹出菜单
更新角色选择效果
更新阴影精灵
更新动作
Sprite_Actor.prototype.update = function() {
Sprite_Battler.prototype.update.call(this);
this.updateShadow();
if (this._actor) {
this.updateMotion();
}
};
Sprite_Battler.prototype.update = function() {
Sprite_Base.prototype.update.call(this);
if (this._battler) {
this.updateMain();
this.updateAnimation();
this.updateDamagePopup();
this.updateSelectionEffect();
} else {
this.bitmap = null;
}
};
更新角色图像精灵
Sprite_Actor.prototype.updateMain = function() {
Sprite_Battler.prototype.updateMain.call(this);
if (this._actor.isSpriteVisible() && !this.isMoving()) {
this.updateTargetPosition();
}
};
Sprite_Battler.prototype.updateMain = function() {
if (this._battler.isSpriteVisible()) {
this.updateBitmap();
this.updateFrame();
}
this.updateMove();
this.updatePosition();
};
更新动画
移动使用者精灵
要移动使用者精灵,基本上使用startMove()
startMove(x, y, direction)
startMove()中、通过相对于标准站立位置的相对坐标指示目的地的方法
Sprite_Battler.prototype.startMove = function(x, y, duration) {
if (this._targetOffsetX !== x || this._targetOffsetY !== y) {
this._targetOffsetX = x;
this._targetOffsetY = y;
this._movementDuration = duration;
if (duration === 0) {
this._offsetX = x;
this._offsetY = y;
}
}
};
它是一种设置移动目标的方法,实际移动的过程由updateMove()和updatePosition()方法执行。这两种方法都在
updateMain()方法中执行。
当执行startMove(0、0,任意)时,操作将返回到参考站立位置。
updateMove()
在此,算出与在startmove中指定的移动时间一致的帧单位的移动距离,并将其设定为_offsetX和_offsetY。
Sprite_Actor.prototype.updateMove = function() {
var bitmap = this._mainSprite.bitmap;
if (!bitmap || bitmap.isReady()) {
Sprite_Battler.prototype.updateMove.call(this);
}
};
Sprite_Battler.prototype.updateMove = function() {
if (this._movementDuration > 0) {
var d = this._movementDuration;
this._offsetX = (this._offsetX * (d - 1) + this._targetOffsetX) / d;
this._offsetY = (this._offsetY * (d - 1) + this._targetOffsetY) / d;
this._movementDuration--;
if (this._movementDuration === 0) {
this.onMoveEnd();
}
}
};
updatePosition()
通过将updatemove中设置的_offsetx和_offsety添加到基准位置(_homex,_homey)来更新当前位置
Sprite_Battler.prototype.updatePosition = function() {
this.x = this._homeX + this._offsetX;
this.y = this._homeY + this._offsetY;
};
注意,这里的x和y是演员精灵的显示位置,与演员的角色图像的显示位置不同。
Sprite_Actor.prototype.updateTargetPosition()
战斗中,演员精灵前后移动的处理由updatetargetposition()控制。 根据演员的游戏数据($gameactor),演员精灵的站
立位置,战斗场景的状态进行判断,决定如何行动。
Sprite_Actor.prototype.updateTargetPosition = function() {
if (this._actor.isInputting() || this._actor.isActing()) {
this.stepForward();
} else if (this._actor.canMove() && BattleManager.isEscaped()) {
this.retreat();
} else if (!this.inHomePosition()) {
this.stepBack();
}
};
执行此方法的配置如下:
Scene_Battleク类的update()
oSpriteset_Battle类的update()
Sprite_Actor类的update()
Sprite_Actor类的updateMain()
Sprite_Actor类的updateTargetPosition()
Sprite_Actor.prototype.updateMain = function() {
Sprite_Battler.prototype.updateMain.call(this);
if (this._actor.isSpriteVisible() && !this.isMoving()) {
this.updateTargetPosition();
}
};
this._actor.isSpriteVisible()
查看演员数据以确定是否显示使用者的精灵。 实际上,演员的情况是根据是否是侧视图模式来判断的。
Game_Actor.prototype.isSpriteVisible = function() {
return $gameSystem.isSideView();
};
this.isMoving()
查看演员精灵数据以确定是否正在移动。
Sprite_Battler.prototype.isMoving = function() {
return this._movementDuration > 0;
};
正在移动表示精灵数据的_movementduration大于0。 在startmove()方法中设置行程时间时,此值会发生变化。 向前进一
步
请参见使用者数据,如果使用者的行为状态是inputting或acting,则它会以12帧从标准站立位置向屏幕左侧移动48个像素。
Sprite_Actor.prototype.stepForward = function() {
this.startMove(-48, 0, 12);
};
行为状态inputting是BattleManager类的changeActor(newActorIndex, lastActorActionState)方法,表示由
newActorIndex指定的使用者。 此方法在命令输入阶段切换使用者时执行。 执行此方法的配置如下:
Scene_Battle类的selectNextCommand()方法
oBattleManager类的selectNextCommand()方法
BattleManager类的schangeActor(newActorIndex, lastActorActionState)方法
Game_Actor类的setActionState(actionState)方法 ← actionState=inputting
Scene_Battle类的selectNextCommand()方法的执行构成如下:
Scene_Battle类的changeInputWindow()(命令输入阶段)
oScene_Battle类的startPartyCommandSelection()
Scene_Battle类的commandFight()
Scene_Battle类的selectNextCommand() → 如果在派对命令中选择了“战斗”
oScene_Battle类的startActorCommandSelection()
Scene_Battle类的commandAttack()
Scene_Battle类的selectEnemySelection()
Scene_Battle类的onEnemyOk()
Scene_Battle类的selectNextCommand() → 在使用者命令中选择了“攻击”,然后选择了其敌人目标。
Scene_Battle类的commandGuard()
Scene_Battle类的selectNextCommand() → 如果为使用者命令选择了“防御”
Scene_Battle类的onSkillOk()
Scene_Battle类的onSelectAction()
Scene_Battle类的selectNextCommand() → 如果您在使用者命令中选择了“技能”,并且不需要为该技能选择目标。
Scene_Battle类的selectActorSelection()
Scene_Battle类的onActorOk()
Scene_Battle类的selectNextCommand() → 在使用者命令中选择“技能”,然后选择了主角目标。
Scene_Battle类的selectEnemySelection()
Scene_Battle类的onEnemyOk()
Scene_Battle类的selectNextCommand() → 如果在使用者命令中选择了“技能”,然后选择了敌人目标。
Scene_Battle类的onItemOk()
Scene_Battle类的onSelectAction()
Scene_Battle类的selectNextCommand() → 如果在使用者命令中选择了“物品”,并且不需要选择使用目标。
Scene_Battle类的selectActorSelection()
Scene_Battle类的onActorOk()
Scene_Battle类的selectNextCommand() → 在使用者命令中选择了“物品”,然后选择了主角目标。
Scene_Battle类的selectEnemySelection()
Scene_Battle类的onEnemyOk()
Scene_Battle类的selectNextCommand() → 在使用者命令中选择了“物品”,然后选择了敌人目标。
行动状态是acting、运行game_actor类的performactionstart(action)方法的使用者,action中指定的行为是防御以外的
状态。执行此方法的配置如下:
BattleManager类的updateTurn()方法(turn阶段)
oBattleManager类的processTurn()方法
BattleManager类的startAction()方法
Window_BattleLog类的startAction(subject, action, targets)方法
Window_BattleLog类的performActionStart(subject, action)方法
Game_Actor类的performActionStart(action)方法
Game_Actor类的setActionState(actionState)方法 ← actionState=acting
确切地说,该方法不是向前迈出的一步,而是站在从标准站立位置开始的X坐标方向上-48像素的位置。因此,在用某种方法进
一步前进(移动到画面左侧)的情况下,如果调用该方法,就会后退,这一点要注意。
撤退
当actor可以动作(chanMove())并且设置了逃跑标志(BattleManager.isEscaped())时,它将从标准站立位置移至屏幕右侧300像素(30帧)。
Sprite_Actor.prototype.retreat = function() {
this.startMove(300, 0, 30);
};
通常,在Maker MV中,屏幕宽度为816像素,而Party的第一个角色的标准站立位置为600像素。如果从此处向右移动300像素
,则为900像素,因此actor子画面将移出屏幕。 这是“退出”时移动到屏幕外部的机制。
向后退一步(返回标准位置)
如果它既不向前也不向后,也不处于标准站立位置,则移动以返回到标准站立位置。
Sprite_Actor.prototype.stepBack = function() {
this.startMove(0, 0, 12);
};
演员动画
refreshMotion()
演员精灵的动画演示
演员精灵的伤害弹出动画的演示
演员精灵状态堆叠
显示战斗场景窗口 |
评分
-
查看全部评分
|