前言: 本教学难度并不高,但是比较繁琐。看完之后,你会完全理解战斗的动作系统怎么去制作,而且改造于你手,无冲突无卡机。请保持耐心并跟着制作。 首先先看这几个教学: 1、shownews.asp?id=131,45度战斗 + 横版战斗制作方法,这个是不带特殊素材效果的。如果你的素材紧缺,不用看了,看到这个教学基本就OK了。 对于原创度很高的游戏,可能基本到这一步就差不多了。此录像为本教学的基础,诸如设置动画、坐标等内容在本教学不再赘述。
2、shownews.asp?id=258,这个是添加了待机动画。改用行走图而已,bug很少。用于三国凡人传等游戏的制作方法,可以参考。
3、shownews.asp?id=201 + shownews.asp?id=210,超级横版战斗。所有下面有的效果里面都有,但是使用起来比较困难。
好了,既然以上几个教学不能满足你,那么我来告诉你怎么打造自己的战斗吧。很多人自己会做,但是不会有我讲得这么清楚,所以我再讲一遍,希望不会再讲第N遍了哦!
0、一个变量的公开: class Game_Battler中,attr_reader :battler_name改为attr_accessor :battler_name 否则这个变量不能随意修改。
1、待机动画 原理:常规战斗的情况下,有两种让图像动起来的方法。一种是使用循环动画,另一种是不断更改角色的战斗图。
怎样给角色添加循环动画呢?你可以设置一个状态名为“正常”,然后在这个状态附带循环动画里面制作上角色的待机动画。如果需要,可以附带这个脚本:shownews.asp?id=381,会防止挨打动画丢失。这种方法的特点是可以制作复杂的待机动作,缺点是占用了循环动画,导致一些状态动画不能显示了。
另一种方法是更改角色战斗图,这个方法没有副作用,但是需要一些脚本知识。为了方便,我们将待机动画的4个动作放在一张战斗图里面,横着排列。(你如果脚本知识牢靠,可以不使用本教学的方法,本教学仅做统一范例而已)
这张图片的名字是li.png,将作为角色的战斗图。
角色战斗图的刷新是在Sprite_Battler里面。所以,现在修改一下这个脚本。
初始化的部分:
def initialize(viewport, battler = nil) super(viewport) @battler = battler @battler_visible = false end | 添加两个属性:
def initialize(viewport, battler = nil) super(viewport) @battler = battler @battler_visible = false #★★★★★★★★★★★★ @nx = 0 @xbit = 0 #★★★★★★★★★★★★ end | @nx表示当前的帧数,@xbit表示当前的图像。刚开始的时候都是0值。
刷新的部分def update,找到这段
# 文件名和色相与当前情况有差异的情况下 if @battler.battler_name != @battler_name or @battler.battler_hue != @battler_hue # 获取、设置位图 @battler_name = @battler.battler_name @battler_hue = @battler.battler_hue self.bitmap = RPG::Cache.battler(@battler_name, @battler_hue) @width = bitmap.width @height = bitmap.height self.ox = @width / 2 self.oy = @height # 如果是战斗不能或者是隐藏状态就把透明度设置成 0 if @battler.dead? or @battler.hidden self.opacity = 0 end end | 这段表示如果战斗中角色战斗图更换则重新换图片。在此下面添加一个刷新效果:
# 文件名和色相与当前情况有差异的情况下 if @battler.battler_name != @battler_name or @battler.battler_hue != @battler_hue # 获取、设置位图 @battler_name = @battler.battler_name @battler_hue = @battler.battler_hue self.bitmap = RPG::Cache.battler(@battler_name, @battler_hue) @width = bitmap.width @height = bitmap.height self.ox = @width / 2 self.oy = @height # 如果是战斗不能或者是隐藏状态就把透明度设置成 0 if @battler.dead? or @battler.hidden self.opacity = 0 end end if @battler.is_a?(Game_Actor) @nx += 1 @nx %= 40 #每帧+1,40帧一个循环 @xbit = @nx / 10 * self.bitmap.width/4 #获得当前的图像坐标 self.src_rect.set(@xbit, 0, self.bitmap.width/4, self.bitmap.height) #设置当前战斗图的图像 end | 这段就是表示,如果这个battler是角色的时候,每隔10帧角色的动画更新一次。好了。你把上面的图像和脚本放到自己的游戏中,就已经是具有待机动画的了。坐标可能不是很好,自己调一下即可。
2、挨打,防御,受伤(hp小于一半)的动画
现在我们另有这么几张图片:
这张图片的名字是li★2.png
这张图片的名字是li★3.png
这张图片的名字是li★4.png
这张图片的名字是li★5.png
那么,我们怎么制作角色的防御动作和挨打动作呢?(注:我为了偷懒,上面的4张图其实上几乎没有动态,你换为自己的素材即可)
首先我们先找到脚本中控制挨打和显示伤害的部分。如果脚本比较熟你应该知道是在Scene_Battle 4中(齐时战斗的设置中讲到过了): #-------------------------------------------------------------------------- # ● 刷新画面 (主回合步骤 4 : 对像方动画) #-------------------------------------------------------------------------- def update_phase4_step4 # 对像方动画 for target in @target_battlers target.animation_id = @animation2_id target.animation_hit = (target.damage != "Miss") end # 限制动画长度、最低 8 帧 @wait_count = 8 # 移至步骤 5 @phase4_step = 5 end #-------------------------------------------------------------------------- # ● 刷新画面 (主回合步骤 5 : 显示伤害) #-------------------------------------------------------------------------- def update_phase4_step5 # 隐藏帮助窗口 @help_window.visible = false # 刷新状态窗口 @status_window.refresh # 显示伤害 for target in @target_battlers if target.damage != nil target.damage_pop = true end end # 移至步骤 6 @phase4_step = 6 end | 下面修改一下这段。我们在显示“对象方动画(update_phase4_step4)”的地方将角色的战斗图改为“防御”或者“挨打”的样子,“显示伤害(update_phase4_step5)”的时候再改回来。 修改如下:
#-------------------------------------------------------------------------- # ● 刷新画面 (主回合步骤 4 : 对像方动画) ★ #-------------------------------------------------------------------------- def update_phase4_step4 # 对像方动画 for target in @target_battlers target.animation_id = @animation2_id target.animation_hit = (target.damage != "Miss") if target.is_a?(Game_Actor) target.battler_name = target.battler_name.split(/★/)[0] if (target.current_action.kind == 0 and target.current_action.basic == 1) or target.damage == "Miss" or target.damage.to_i <= 0 target.battler_name = target.battler_name + "★3" else target.battler_name = target.battler_name + "★4" end end end # 限制动画长度、最低 8 帧 @wait_count = 8 # 移至步骤 5 @phase4_step = 5 end #-------------------------------------------------------------------------- # ● 刷新画面 (主回合步骤 5 : 显示伤害) #-------------------------------------------------------------------------- def update_phase4_step5 # 隐藏帮助窗口 @help_window.visible = false # 刷新状态窗口 @status_window.refresh # 显示伤害 for target in @target_battlers if target.damage != nil target.damage_pop = true end if target.is_a?(Game_Actor) target.battler_name = target.battler_name.split(/★/)[0] if target.hp < target.maxhp/2 target.battler_name = target.battler_name + "★5" end end end # 移至步骤 6 @phase4_step = 6 end | 我来解释一下红字的部分。
if target.is_a?(Game_Actor) #如果挨打的是角色的时候
target.battler_name = target.battler_name.split(/★/)[0] #先把角色的战斗图文件名改为默认的战斗图文件名(也就是忽略现在文件名中★后面的部分),防止出一些意外。也就是说,如果现在处于“受伤”的情况,则本来数据库设置战斗图为“li”,此刻却是“li★5”
if (target.current_action.kind == 0 and target.current_action.basic == 1) or target.damage <= 0 #如果角色的行动是“防御”的时候或者伤害<0的时候(当然,这个防御你可以自己修改功能,比如“防御回气”或者“召唤宠物”等。那你就自己修改一下触发条件即可)
target.battler_name = target.battler_name + "★3" #挨打者的文件名改为原名+★3。比如原来文件名是“li”,现在就变成了“li★3”
else #除此以外,也就是没“防御”的时候
target.battler_name = target.battler_name + "★4" #挨打者文件名改为原名+★4。原名“li”,现在变成了“li★4”
end
下面再来看后面显示伤害的时候。有了上面的基础,应该很简单了吧: if target.is_a?(Game_Actor) #当是角色的时候 target.battler_name = target.battler_name.split(/★/)[0] #文件名还原 if target.hp < target.maxhp/2 #如果角色生命小于一半 target.battler_name = target.battler_name + "★5" #把战斗图改为受伤图 end end | 这样角色就有防御和挨打的图了。不过我并不推荐这种方法制作受伤动画,因为如果你用了★5的受伤动画,则你需要在Game_Battler 3的def item_effect中增加战斗图的更改。否则角色在战场被打个半死,在地图上吃药补满血后,回到战场还是使用的受伤战斗图。此外还需要在公共事件的增减HP的地方增加战斗图更改的脚本——总之,自己改吧。原理掌握了就什么都不怕了。
3、死亡图
死亡图相对麻烦一点。注意到Sprite_Battler中如下几个地方:
# 如果是战斗不能或者是隐藏状态就把透明度设置成 0 if @battler.dead? or @battler.hidden self.opacity = 0 end | 以及: if @battler.damage == nil and @battler.dead? if @battler.is_a?(Game_Enemy) $game_system.se_play($data_system.enemy_collapse_se) else $game_system.se_play($data_system.actor_collapse_se) end collapse @battler_visible = false end | 以及: if not @battler.hidden and not @battler.dead? and (@battler.damage == nil or @battler.damage_pop) appear @battler_visible = true end |
修改一下吧: # 如果是战斗不能或者是隐藏状态就把透明度设置成 0 if @battler.is_a?(Game_Enemy) if @battler.dead? or @battler.hidden self.opacity = 0 end end | 这个就是改为只有敌人死的时候才让敌人消失。 if @battler.damage == nil and @battler.dead? if @battler.is_a?(Game_Enemy) $game_system.se_play($data_system.enemy_collapse_se) collapse else $game_system.se_play($data_system.actor_collapse_se) @battler.battler_name = @battler.battler_name.split(/★/)[0] @battler.battler_name = @battler.battler_name + "★2" end @battler_visible = false end | 当我方死亡的时候修改战斗图。 unless @battler_visible # 出现 if not @battler.hidden and not @battler.dead? and (@battler.damage == nil or @battler.damage_pop) if @battler.is_a?(Game_Enemy) appear else @battler.battler_name = @battler.battler_name.split(/★/)[0] end @battler_visible = true end end | 当我方复活的时候修改战斗图
行了。完成了~~
Final、调整位置 把默认没有写出来的脚本修改一下(这个脚本在RMXP的帮助中搜索damage可以获得): module RPG class Sprite < ::Sprite def damage(value, critical) dispose_damage if value.is_a?(Numeric) damage_string = value.abs.to_s else damage_string = value.to_s end bitmap = Bitmap.new(160, 48) bitmap.font.name = "Arial Black" bitmap.font.size = 32 bitmap.font.color.set(0, 0, 0) bitmap.draw_text(-1, 12-1, 160, 36, damage_string, 1) bitmap.draw_text(+1, 12-1, 160, 36, damage_string, 1) bitmap.draw_text(-1, 12+1, 160, 36, damage_string, 1) bitmap.draw_text(+1, 12+1, 160, 36, damage_string, 1) if value.is_a?(Numeric) and value < 0 bitmap.font.color.set(176, 255, 144) else bitmap.font.color.set(255, 255, 255) end bitmap.draw_text(0, 12, 160, 36, damage_string, 1) if critical bitmap.font.size = 20 bitmap.font.color.set(0, 0, 0) bitmap.draw_text(-1, -1, 160, 20, "CRITICAL", 1) bitmap.draw_text(+1, -1, 160, 20, "CRITICAL", 1) bitmap.draw_text(-1, +1, 160, 20, "CRITICAL", 1) bitmap.draw_text(+1, +1, 160, 20, "CRITICAL", 1) bitmap.font.color.set(255, 255, 255) bitmap.draw_text(0, 0, 160, 20, "CRITICAL", 1) end @_damage_sprite = ::Sprite.new(self.viewport) @_damage_sprite.bitmap = bitmap @_damage_sprite.ox = 80 @_damage_sprite.oy = 20 @_damage_sprite.x = self.x @_damage_sprite.x -= self.bitmap.width/2 if @battler.is_a?(Game_Actor) @_damage_sprite.y = self.y - self.oy / 2 @_damage_sprite.z = 3000 @_damage_duration = 40 end end end | 修改一下挨打的时候文字的位置。
再修改一下指针位置: class Arrow_Actor < Arrow_Base中的 self.x = self.actor.screen_x改为 self.x = self.actor.screen_x - 100
就算全部完成了。
如果你的敌人也要待机动画和挨打、防御动画,上面素有的.is_a?(Game_Actor)和.is_a?(Game_Enemy)这种区别对待的东西全部去掉即可。Happy~
|