本帖最后由 miantouchi 于 2019-10-16 22:11 编辑 思考了2天,刚刚有点头绪,赶紧发下。不对的对方,希望指正,我根据这些日子大家论坛的讲解指点,用流程彻底分析了下战斗界面流程以下。暂时今天写这么多,再修正,终于可以睡个好觉了 第一部分:敌方攻击导致我方致死情况 4-1很快过去 4-2 敌方攻击我方,计算出伤害值172. 此时:隐藏:false,死亡:false,伤害:172,战斗伤害标志:false 接着刷新@spriteset.update 此时:隐藏:false,死亡:true,伤害:172,战斗伤害标志:false 4-3敌方白闪攻击动画ID=0 此时赋值 @phase4_step = 4 @spriteset.update-------Sprite_Battler-update 因为@battler_visible =true,所以执行下面的 # 白色闪烁 whiten后,设置@battler.white_flash = false 此时:隐藏:false,死亡:true,伤害:172,战斗伤害标志:false update_phase4-----------case @phase4_step-------- update_phase4_step4进入第四步 4-4我方被攻击动画 首先,赋值给 对象方动画id和命中 target.animation_id = @animation2_id target.animation_hit = (target.damage != "Miss") 接着刷新@spriteset.update 因为@battler_visible =true,所以执行下面的 # 动画,因为此时动画ID = @animation2_id,有值 所以播放被攻击动画,播放后,把对像方动画id归0 此时:隐藏:false,死亡:true,伤害:172,战斗伤害标志:false 4-5我方被攻击显示数值字体。 此时因为第2步有伤害值172,!=nil 所以target.damage_pop = true把伤害标志变成true 接着刷新@spriteset.update 因为@battler_visible =true,所以执行下面的 #伤害因为此时damage_pop = true 所以播放damage动画, damage设置nil,damage_pops和critical设置为false 接下来 死亡判断动画处(伤害值刚刚被设置为nil,并且已经死亡)此时成立 if @battler.damage == nil and @battler.dead? 播放collapse死亡消失动画。 最后设置@battler_visible = false 此时:隐藏:false,死亡:true,伤害:nil,战斗伤害标志:false 第二部分:接下来我方用技能复活阵亡的队员 4-1很快过去了 此时:隐藏:false,死亡:true,伤害:nil,战斗伤害标志:false @battler_visible = false 4-2 我方使用复活技能复活队友,计算出恢复值-541. 此时:隐藏:false,死亡:false,伤害:-541.,战斗伤害标志:false @battler_visible = false 接着刷新@spriteset.update,等着因为上面都不成立,结果什么都没干 4-3 行动方(我方)动画不等于0,@animation1_id != 0 @active_battler.animation_id = @animation1_id @active_battler.animation_hit = true 接着刷新@spriteset.update 此时:隐藏:false,死亡:false,伤害:-541.,战斗伤害标志:false @battler_visible = false 所以,这一步什么都没做 4-4 首先,赋值给 对象方(死亡队员)动画id和命中 target.animation_id = @animation2_id target.animation_hit = (target.damage != "Miss") 接着刷新@spriteset.update 此时:隐藏:false,死亡:false,伤害:-541.,战斗伤害标志:false @battler_visible = false 所以,这一步什么都没做 4-5 此时因为第2步有恢复值-541,不等于空!=nil 所以damage_pop = true把伤害标志变成true(执行关键) 接着刷新@spriteset.update 此时:隐藏:false,死亡:false,伤害:-541.,战斗伤害标志:true @battler_visible = false 所以执行下面的:这一步当中,appear,animation,damage都成立了 接下来update这三个动画次数 第三部分,为什么去掉@battler.damage == nil or @battler.damage_pop会发生,战斗图先出现,施法和复活、伤害值动画后出来。 4-2运行之前:隐藏:false,死亡:true,伤害:nil.,战斗伤害标志:false @battler_visible = false 4-2开始 我方使用复活技能复活队友,死亡变成false,血量恢复506不为空 此时:@battler_visible = false直接成立了 隐藏:false,死亡:false,伤害:-506.,战斗伤害标志:false 接着刷新@spriteset.update, 因为只判断这两项,隐藏:false,死亡:false。appear人物出现了,鬼畜了 此时:@battler_visible = true 4-3开始 因为:@battler_visible = true 隐藏:false,死亡:false,伤害:-506.,战斗伤害标志:false 动画ID不等于nil 显示我方施法动画(反复update) 4-4开始 因为:@battler_visible = true 隐藏:false,死亡:false,伤害:-506.,战斗伤害标志:false 动画ID不等于nil 显示复活动画(反复update) 4-5开始(打开伤害开关) 因为:@battler_visible = true 隐藏:false,死亡:false,伤害:-506.,战斗伤害标志:true 显示恢复血量值(反复update) 所以造成,人物出现-施法动画-复活动画(被复活)-显示恢复血量 第四部分,我方人员中毒情况。 4-1这步 if @active_battler.hp > 0 and @active_battler.slip_damage? @active_battler.slip_damage_effect @active_battler.damage_pop = true end 连续伤害判断成立。上面判断成立 4-1结束 接着刷新@spriteset.update 此时:隐藏:false,死亡:false,伤害:400(中毒扣的血量).,战斗伤害标志:true @battler_visible = true 下面判断成立 if @battler.damage_pop damage(@battler.damage, @battler.critical) @battler.damage = nil @battler.critical = false @battler.damage_pop = false end 反复刷新damage动画,刷新完成后进入4-2 此时:隐藏:false,死亡:false,伤害:nil.,战斗伤害标志:false 所以4-1刷新部分就进行扣血了。 |
miantouchi 发表于 2019-5-29 16:38 1. 进入战斗场景瞬间所有角色都要先出现一遍,这个不算在内。我们讨论的是一个角色被打死之后再复活,被打死之后 @battler_visible 是 false 2. 都包括,看相应源码定义。 3. 其实也没多长 RUBY 代码复制
这些全都只是定义一些数,并没有真正执行操作。真正执行操作的地方: RUBY 代码复制
根据预设的补间动画长度来修改不透明度。但是因为写在 update 中,每一帧只会 update 一次,完成这个动作要 16 帧。 |
本帖最后由 RyanBern 于 2019-5-29 14:18 编辑 来插一脚动画和人物出现顺序问题的说明。有关谁先谁后,我这边的结论是:人物淡入,动画显示,伤害显示这三者是同时出现的。这个是针对我方有人阵亡然后使用复活技能/物品的动画特效,一般的挨打特效不算在内。 因此楼主和菜刀的理解都是有点问题的。 下面代码是出现的判定 RUBY 代码复制
它判断的条件是:在 @battler_visible 为 false 的条件下,如果角色没有隐藏,没有阵亡,目前无伤害/正要显示伤害时,战斗图会出现。在这里比较有意思的是它并不是像菜刀所说“没有伤害要显示时”,而是“正要显示伤害时”。因此得到结论:阵亡队友出现和伤害显示是同时发生的。 至于为什么复活动画也会同时发生,这是因为 Sprite_Battler 里的判定: RUBY 代码复制
只有 @battler_visible = true 时它才会去管动画的显示,否则就算你修改了 animation_id,这些判断也不会执行。 回顾一下 Scene_Battle 的第四阶段(phase 4),它有六个步骤: Step 1:准备行动(公共事件,强制行为,中毒扣血,自然解除状态) Step 2:开始行动(应用行动效果,消耗 SP,计算伤害,扣血) Step 3:设置攻击方动画 Step 4:设置对象方动画 Step 5:设置显示伤害 Step 6:其他刷新 在这里我特别加上了设置二字,来表示在 Scene_Battle 里只是进行了某种设置,而真正执行与否要看 Sprite_Battler 对其的响应。为了说明角色出现,动画播放,伤害显示是在同一时间执行的,我们可以依次过一遍 phase 4 的六个步骤,看看里面究竟有哪些细节。 Step 1:准备行动。此时被复活方还处于 hp = 0 的状态,战斗图不显示(@battler_visible 为 false) Step 2:开始行动。我方成员使用技能,此时回复量已经计算,角色被复活,但由于 damage 不是 nil 且 damage_pop 为 false,@battler_visible 仍旧为 false Step 3:设置攻击方动画。这个正常显示。 Step 4:设置对象方动画。对象方 animation_id 被设置,但没有被播放。原因是 @battler_visible 为 false,导致 Sprite_Battler 不会去检测(见前面代码) Step 5:设置显示伤害。对象方 damage_pop 设置为 true。按照 @battler_visible 修改的判定,只要角色没隐藏,没阵亡,并且有伤害要显示,它就会被设置为 true。一旦 @battler_visible 设置为 true,后面对动画和伤害显示的判定统统生效。因此在 Step 5 会同时发生:角色出现,动画显示,伤害显示。 Step 6:略 楼主的误区在于:没有分清哪些地方是设置,哪些地方是真正执行。在上面分析的 Step 5 中,它有几个关键的语句:appear,animation,damage,这些方法来自于父类 RPG::Sprite,楼主可以在 F1 中查看这个类的定义,你会发现 appear,animation,damage 所做的操作还是进行一系列设置!,而并非像楼主理解的:执行完 appear 一句之后,角色就已经出现了。 菜刀的误区在于:Step 4 虽然在 Step 5 前,但由于 @battler_visible 这个变量影响了 Step 4 的效果,导致 Step 4 的最终效果会延迟到 Step 5 才会执行。 |
本帖最后由 灯笼菜刀王 于 2019-5-28 00:07 编辑 这就是XP默认的伤害显示调用方法 battler.damage != nil 且 battler.damage_pop == true battler.damage 可以是数字,也可以是字符串, 它只是把伤害显示出来, 并没有实际扣血, 扣血操作是另外处理的, 到此,如果你能理解的话, 之前你一直无法想通的那个操作"复活的时候先播放玩动画再爬起来", 现在知道原因了没? 也可以通过让NPC运行这段脚本,.来让伤害显示在地图(scene map)上出现 $a = RPG::Sprite.new $a.x,$a.y = 320,240 $a.damage("天下无敌",true) 不过, 直接运行这段脚本, 伤害显示是不动的, 因为没刷新, 和以前一样做法, 把 $a 拿到 scene map 里去刷新它, 就能看到完整的伤害展示了 然后,你说找不到scnene battler里的刷新? 以前不是了解过了, Sprite battler 是被 Spriteset battle 调用的,而 Spriteset battle 的实例被塞到 @spriteset 这个实变量里了, 它在哪里刷新, 自己搜索下咯 你可以 p @active_battler.index 看看它是什么, 它的定义在 game actor 和 game enemy 里, 角色不用管, 这句话主要是针对敌人的, 当战斗中断的时候(就像米兄说的,计时器导致战斗结束,事件结束战斗等原因), 敌人队伍清空, 这个时候敌人的index就会返回nil, 就此中断不再继续, 避免下面的hp无法操作而出错 ---------------------- 综合考试: 因为行走图(Sprite_Character)和战斗图(Sprite_Battler)是同一个爹, 所以它们的方法是可以共享的, 尝试改造下Sprite_Character, 让行走图也可以通过 damage_pop 来显示伤害吧 提示: 看它们update里的"#动画",对比下两者的不同点和相同点, 然后依样画葫芦试试 |
本帖最后由 miantouchi 于 2019-5-27 20:37 编辑 灯笼菜刀王 发表于 2019-5-26 22:33 今天头疼了一天,吃点药继续克。 1。今天从战斗事件里面找到了,简单体会了下 2.强制行动(立即行动的情况下),会让强制行动人员,在本轮第一个出手。 3,大概理解了就是,我方和敌方人员按速度从大到小排序存放在数组当中,然后依次通过shift方法取出前面的人,依次进行连续伤害、自然解除状态、刷新状态窗口,直到数组size为0,就进行下一回合。 4.(1)你说的搜索 def slip_damage_effect 这句, 这里有操作伤害(即@active_battler.damage != nil)是不是意思,执行def slip_damage_effect这个方法,就能证明是有伤害的,因为这个方法就是计算伤害值的。 (2)Sprite_battler 的 update 是在什么时候调用的什么地方调用这个update刷新的,我怎么找不到? 最后一个作业,测试下了,用完技能,我方第一个人员会出现“天下无敌”字样。 a.damage_pop = false,就不会显示了,证明damage_pop是你上面说的显示开关, 例子中用于在我方人员身上显示,天下无敌的开关。 所以 # 连续伤害 if @active_battler.hp > 0 and @active_battler.slip_damage? @active_battler.slip_damage_effect @active_battler.damage_pop = true end 这段代码,就是获取当前行动者如果HP>0并且这个行动者有连续伤害 那么计算slip_damage_effect伤害值,把这个人员身上的伤害的显示开关打开。 另外,最后一个问题。 @active_battler = @action_battlers.shift # 如果已经在战斗之外的情况下 if @active_battler.index == nil return end 战斗之外的情况下是什么情况,比如我方和敌方攻击6人,我方4人、敌方2人,6个人开始都是未行动人员,挨个就行伤害处理了。 @active_battler.index == nil是啥情况? |
本帖最后由 灯笼菜刀王 于 2019-5-26 22:59 编辑 1, 强制行动, 事件设置的, 具体去看"RMXP入门",不改造脚本的情况下要制作一些特殊战斗效果, 一般就是用它来实现 2, 强制行动(立即行动的情况下)会怎么表现, 了解了自然就能理解, 为什么这里要把行动者抽出来加到数组最前面 3, 你搜索@action_battlers, 可以看到在前面的步骤里, 把角色和敌人根据行动速度保存到这里 @active_battler = @action_battlers.shift 这句就是获得当前行动对象, 具体原理, 搜索F1, array 的 shift 方法, 结合上面的 @action_battlers 保存的内容去理解下, 然后下面的size == 0 就能理解了 @action_battlers.size == 0 就是 @action_battlers 的数组空了, 也就是所有角色和敌人都已经行动过了, 如果还没分出胜负, 就回到步骤3(角色操作指令)重头开始 4, 搜索 def slip_damage_effect 这句, 这里有操作伤害(即@active_battler.damage != nil), 而 damage_pop 就是伤害显示开关, 它的作用在 Sprite_battler 的 update 里体现, 用来让伤害的数字显示出来 这里显示的是异常状态的伤害, 也就是中毒的伤害, 同时,异常状态的持续回合数也在这里扣 这个步骤是确定好行动者, 初始化一些战斗用的临时变量, 并对行动者的异常状态进行操作 ------------------------------------------------------------- 动手做作业: 1, 随便找个技能, 让它关联一个公共事件 2, 公共事件内容, 3,战斗测试, 使用这个技能, 看效果 |
站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作
GMT+8, 2024-11-23 08:44
Powered by Discuz! X3.1
© 2001-2013 Comsenz Inc.