じ☆ve冰风 发表于 2024-4-19 21:33:14

技能树系统

不知道有没有别人做过这个东西呢……自己花一晚上写的这些,拿出来跟大家分享一下。
具体的说明都在代码里面了,有什么地方不明白的尽管在帖子里面问啊!#==============================================================================# 技能树系统 Ver 1.0# 作者:RyanBern#------------------------------------------------------------------------------# 功能特色:#   开放技能点增加系统,每一个角色都有自己独特的技能成长历程。#   通过获得技能点来让技能变得更加强大。在学习技能的过程中,可以解锁同种技能#   的更高级别,也可以解锁威力更大的技能。#   主角的一切技能成长都遵循您的意愿!#==============================================================================# 使用方法#   在脚本的第 88 行起定义你的自定义技能树。#   注意,要一个一个角色的定义,因为不同角色的技能树肯定不同。#   核心定义脚本actor.set_data(id,ar1,ar2)#   id:你要定义的技能ID#   ar1 :是一个数组,记录着该技能的前置技能的ID(这就意味着一个技能的前置技能#          可以有多个),角色必须学会这个技能的所有前置技能才可以学习该技能。#   ar2 :是一个数组,记录着该技能学会之后,可能开启的后置技能。#          设置ar2主要是为了描绘方便,但是会增加使用者的工作量。#   ar1和ar2可以为空,表示该技能没有前置技能或后置技能,用空的方括号[]表示#------------------------------------------------------------------------------#   定义范例:#   # 1号角色#   actor = Game_Skill_Tree.new#   actor.set_data(1,[],) # 定义ID为1的技能,不需要前置技能,可能开启ID为2的技能#   actor.set_data(2,,)#   actor.set_data(3,,) # 定义ID为3的技能,前置技能为ID 2,后置技能为ID 4#   actor.set_data(4,,[])#   actor.skills.sort!#   data.push(actor)#   # 1号角色定义完毕#------------------------------------------------------------------------------#※ 默认每个人升5级就能获得1技能点,即角色在5,10,15...级会得到技能点,如果想#   改变获得技能点的级数,请改下面的SKILLS_PTS_STEP = 5#※ 默认每次打到规定登记会获得1个技能点,如果想改变每次获得的技能点个数,请#   改下面的UPGRADE_GAIN = 1#※ 默认每个技能学习消耗1个技能点,这个暂时不支持更改-_-||#※ 角色各自的技能点保存在游戏的变量当中(也就是$game_variables中),默认保存#   的位置是 NUMBER_SHIFT + 角色的ID,即如果NUMBER_SHIFT == 0,则ID为1的角色#   的技能点数保存在1号变量中,以此类推。当然考虑到这个位置可能实现保存了编者#   的其它数据,固设置数据位移量NUMBER_SHIFT,如果你想从101号变量开始保存,#   只需要改 NUMBER_SHIFT = 100#------------------------------------------------------------------------------#※ 考虑到主菜单场景大家改起来不方便,可以用事件在地图上进行调用。#※ 方法是建立一个新事件,使用脚本$scene = Scene_Skill_Tree.new即可。#※ 当然会写脚本的同学可以把它融入到主菜单中。#※ 使用PageUP和PageDown可以在不同角色之间进行切换#==============================================================================# 界面说明:#   玩家已经习得的技能用黄色字体表示#   玩家能够学习的技能用白色表示#   没有达到学习条件的技能用灰色表示#   已经达到学习条件的,但是技能点不足,无法学习的技能,用红色表示#   在前置技能中,已经学到的技能用白色表示,并且后面有个“√”#   在前置技能中,没有学到的技能用灰色表示#==============================================================================SKILL_PTS_STEP = 5UPGRADE_GAIN = 1NUMBER_SHIFT = 0class Game_Skill_Treeattr_accessor :skillsattr_reader   :prev_skillsattr_reader   :next_skillsdef initialize    @skills = []    @prev_skills = {}    @next_skills = {}end#----------------------------------------------------------------------------# 定义数据类型# skill_id :要定义的技能id# pre_skills :要定义技能之前置技能,是一个数组# post_skills :要定义技能之后置技能,是一个数组#----------------------------------------------------------------------------def set_data(skill_id,pre_skills,post_skills)    @skills.push(skill_id)    @prev_skills = pre_skills    @next_skills = post_skillsendenddef get_skill_treedata = # 开始定义各个主角的技能树# 1号角色# 1号角色定义完毕return data endclass Game_Actor#--------------------------------------------------------------------------# ● 更改 EXP#   exp : 新的 EXP#--------------------------------------------------------------------------def exp=(exp)    @exp = [.min, 0].max    # 升级    while @exp >= @exp_list[@level+1] and @exp_list[@level+1] > 0      @level += 1      # 学会特技      for j in $data_classes[@class_id].learnings      if j.level == @level          learn_skill(j.skill_id)      end      end      # 达到技能点要求就增加技能点      if @level % SKILL_PTS_STEP == 0      $game_variables += UPGRADE_GAIN      end    end    # 降级    while @exp < @exp_list[@level]      @level -= 1    end    # 修正当前的 HP 与 SP 超过最大值    @hp = [@hp, self.maxhp].min    @sp = [@sp, self.maxsp].minenddef skill_can_learn?(skill_id)    skill_tree = $data_skilltree    # 没有对应设置,返回false    if skill_tree == nil      return false    end    skills_need = skill_tree.prev_skills    # 不在技能树中的技能无法习得    if skills_need == nil      return false    end    # 逐个检查    for i in skills_need      # 如果有前置技能没有学习      unless skill_learn?(i)      return false      end    end    # 前置技能全部都学习了    return trueendend#==============================================================================# ■ Window_Skill_Tree#------------------------------------------------------------------------------#  技能树场景中,显示所有技能的窗口。#==============================================================================class Window_Skill_Tree < Window_Selectable#--------------------------------------------------------------------------# ● 初始化对像#   actor : 角色#--------------------------------------------------------------------------def initialize(actor)    super(0, 128, 180, 352)    @actor = actor    @skill_tree = $data_skilltree[@actor.id]    @column_max = 1    refresh    self.index = 0end#--------------------------------------------------------------------------# ● 获取特技#--------------------------------------------------------------------------def skill    return @dataend#--------------------------------------------------------------------------# ● 刷新#--------------------------------------------------------------------------def refresh    if self.contents != nil      self.contents.dispose      self.contents = nil    end    @data = []    # 没有技能树,返回    if @skill_tree == nil      return    end    for i in 0...@skill_tree.skills.size      skill = $data_skills[@skill_tree.skills]      if skill != nil      @data.push(skill)      end    end    # 如果项目数不是 0 就生成位图、重新描绘全部项目    @item_max = @data.size    if @item_max > 0      self.contents = Bitmap.new(width - 32, row_max * 32)      for i in 0...@item_max      draw_item(i)      end    endend#--------------------------------------------------------------------------# ● 描绘项目#   index : 项目编号#--------------------------------------------------------------------------def draw_item(index)    skill = @data    if @actor.skill_learn?(skill.id)      self.contents.font.color = crisis_color    elsif @actor.skill_can_learn?(skill.id)      if $game_variables > 0      self.contents.font.color = normal_color      else      self.contents.font.color = knockout_color      end    else      self.contents.font.color = disabled_color    end    x = 4    y = index* 32    rect = Rect.new(x, y, self.width / @column_max - 32, 32)    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))    bitmap = RPG::Cache.icon(skill.icon_name)    opacity = self.contents.font.color == disabled_color ? 128 : 255    self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)    self.contents.draw_text(x + 28, y, 140, 32, skill.name, 0)end#--------------------------------------------------------------------------# ● 刷新帮助文本#--------------------------------------------------------------------------def update_help    @help_window.set_text(self.skill == nil ? "" : self.skill.description)endend#==============================================================================# ■ Window_Skill_Tree_Status#------------------------------------------------------------------------------#  技能树界面中,显示特技画面、特技使用者的窗口。#==============================================================================class Window_Skill_Tree_Status < Window_Base#--------------------------------------------------------------------------# ● 初始化对像#   actor : 角色#--------------------------------------------------------------------------def initialize(actor)    super(0, 64, 640, 64)    self.contents = Bitmap.new(width - 32, height - 32)    @actor = actor    refreshend#--------------------------------------------------------------------------# ● 刷新#--------------------------------------------------------------------------def refresh    self.contents.clear    draw_actor_name(@actor, 4, 0)    draw_actor_state(@actor, 140, 0)    self.contents.font.color = system_color    self.contents.draw_text(360, 0, 160, 32, "可用技能点:")    skill_pt = $game_variables    if skill_pt == 0      self.contents.font.color = knockout_color    else      self.contents.font.color = normal_color    end    self.contents.draw_text(496, 0, 64, 32, skill_pt.to_s, 2)endendclass Window_Skill_Prev < Window_Basedef initialize(actor,skill)    super(180, 192, 230, 288)    self.contents = Bitmap.new(width - 32, height - 32)    @actor = actor    @skill = skill    refreshenddef skill=(skill)    if @skill != skill      @skill = skill      refresh    endenddef refresh    self.contents.clear    skill_tree = $data_skilltree[@actor.id]    # 没有技能树,结束描绘    if skill_tree == nil or @skill == nil      return    end    skills_need = skill_tree.prev_skills[@skill.id]    skills_need.sort!    for i in 0...skills_need.size      x = 4      y = i * 32      skill = $data_skills]      if @actor.skill_learn?(skills_need)      self.contents.font.color = normal_color      tag = "√"      opacity = 255      else      self.contents.font.color = disabled_color      tag = ""      opacity = 128      end      bitmap = RPG::Cache.icon(skill.icon_name)      self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)      self.contents.draw_text(x + 28, y, 166, 32, skill.name + tag, 0)    endendendclass Window_Skill_Next < Window_Basedef initialize(actor,skill)    super(410, 192, 230, 288)    self.contents = Bitmap.new(width - 32, height - 32)    @actor = actor    @skill = skill    refreshenddef skill=(skill)    if @skill != skill      @skill = skill      refresh    endenddef refresh    self.contents.clear    skill_tree = $data_skilltree[@actor.id]    # 没有技能树,结束描绘    if skill_tree == nil or @skill == nil      return    end    skills_next = skill_tree.next_skills[@skill.id]    skills_next.sort!    for i in 0...skills_next.size      x = 4      y = i * 32      skill = $data_skills]      self.contents.font.color = normal_color      bitmap = RPG::Cache.icon(skill.icon_name)      self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), 255)      self.contents.draw_text(x + 28, y, 166, 32, skill.name, 0)    endendend#==============================================================================# ■ Window_Tip#------------------------------------------------------------------------------#  技能树画面提示窗口#==============================================================================class Window_Tip < Window_Selectable#--------------------------------------------------------------------------# ● 初始化对像#--------------------------------------------------------------------------def initialize    super(160, 176, 320, 128)    self.contents = Bitmap.new(width - 32, height - 32)    @item_max = 2    @column_max = 2    @commands = ["是的","不要"]    refresh    self.index = 0    self.z = 1000end#--------------------------------------------------------------------------# ● 刷新#--------------------------------------------------------------------------def refresh    self.contents.clear    self.contents.font.color = system_color    self.contents.draw_text(4, 0, 328, 32, "您确定要学习该技能吗?")    self.contents.draw_text(4, 32, 328, 32, "本次学习将消耗1个技能点。")    self.contents.font.color = normal_color    for i in 0...@item_max      draw_item(i)    endend#--------------------------------------------------------------------------# ● 描绘项目#   index : 项目编号#--------------------------------------------------------------------------def draw_item(index)    x = 4 + index * 144    self.contents.draw_text(x, 64, 128, 32, @commands)enddef update_cursor_rect    if @Index < 0      self.cursor_rect.empty    else      self.cursor_rect.set(@index * 144, 64, (self.width - 32) / 2, 32)    endendend#==============================================================================# ■ Scene_Skill_Tree#------------------------------------------------------------------------------#  处理特技树画面的类。#==============================================================================class Scene_Skill_Tree#--------------------------------------------------------------------------# ● 初始化对像#   actor_index : 角色索引#--------------------------------------------------------------------------def initialize(actor_index = 0)    @actor_index = actor_indexend#--------------------------------------------------------------------------# ● 主处理#--------------------------------------------------------------------------def main    # 获取角色    @actor = $game_party.actors[@actor_index]    # 生成帮助窗口、状态窗口、特技窗口    @title1 = Window_Base.new(180, 128, 230, 64)    @title2 = Window_Base.new(410, 128, 230, 64)    @title1.contents = Bitmap.new(198, 32)    @title1.contents.draw_text(4, 0, 120, 32, "前置技能")    @title2.contents = Bitmap.new(198, 32)    @title2.contents.draw_text(4, 0, 120, 32, "后置技能")    @help_window = Window_Help.new    @status_window = Window_Skill_Tree_Status.new(@actor)    @skill_window = Window_Skill_Tree.new(@actor)    @prev_window = Window_Skill_Prev.new(@actor,nil)    @next_window = Window_Skill_Next.new(@actor,nil)    # 关联帮助窗口    @skill_window.help_window = @help_window    # 生成信息提示窗口 (设置为不可见・不活动)    @tip_window = Window_Tip.new    @tip_window.visible = false    @tip_window.active = false    # 执行过渡    Graphics.transition    # 主循环    loop do      # 刷新游戏画面      Graphics.update      # 刷新输入信息      Input.update      # 刷新画面      update      # 如果画面切换的话就中断循环      if $scene != self      break      end    end    # 准备过渡    Graphics.freeze    # 释放窗口    @help_window.dispose    @status_window.dispose    @skill_window.dispose    @tip_window.dispose    @prev_window.dispose    @next_window.dispose    @title1.dispose    @title2.disposeend#--------------------------------------------------------------------------# ● 刷新画面#--------------------------------------------------------------------------def update    # 刷新窗口    @help_window.update    @status_window.update    @skill_window.update    @tip_window.update    @prev_window.update    @next_window.update    @skill = @skill_window.skill    @prev_window.skill = @skill    @next_window.skill = @skill    # 特技窗口被激活的情况下: 调用 update_skill    if @skill_window.active      update_skill      return    end    # 目标窗口被激活的情况下: 调用 update_target    if @tip_window.active      update_tip      return    endend#--------------------------------------------------------------------------# ● 刷新画面 (特技窗口被激活的情况下)#--------------------------------------------------------------------------def update_skill    # 按下 B 键的情况下    if Input.trigger?(Input::B)      # 演奏取消 SE      $game_system.se_play($data_system.cancel_se)      # 切换到菜单画面      $scene = Scene_Map.new      return    end    # 按下 C 键的情况下    if Input.trigger?(Input::C)      # 获取特技窗口现在选择的特技的数据      @skill = @skill_window.skill      # 不能使用的情况下      if @skill == nil or not @actor.skill_can_learn?(@skill.id) or $game_variables == 0 or @actor.skill_learn?(@skill.id)      # 演奏冻结 SE      $game_system.se_play($data_system.buzzer_se)      return      else      # 演奏确定 SE      $game_system.se_play($data_system.decision_se)      @tip_window.visible = true      @skill_window.active = false      @tip_window.active = true      return      end    end    # 按下 R 键的情况下    if Input.trigger?(Input::R)      # 演奏光标 SE      $game_system.se_play($data_system.cursor_se)      # 移至下一位角色      @actor_index += 1      @actor_index %= $game_party.actors.size      # 切换到别的特技画面      $scene = Scene_Skill_Tree.new(@actor_index)      return    end    # 按下 L 键的情况下    if Input.trigger?(Input::L)      # 演奏光标 SE      $game_system.se_play($data_system.cursor_se)      # 移至上一位角色      @actor_index += $game_party.actors.size - 1      @actor_index %= $game_party.actors.size      # 切换到别的特技画面      $scene = Scene_Skill_Tree.new(@actor_index)      return    endend#--------------------------------------------------------------------------# ● 刷新画面 (目标窗口被激活的情况下)#--------------------------------------------------------------------------def update_tip    # 按下 B 键的情况下    if Input.trigger?(Input::B)      # 演奏取消 SE      $game_system.se_play($data_system.cancel_se)      # 删除目标窗口      @skill_window.active = true      @tip_window.visible = false      @tip_window.active = false      @tip_window.index = 0      return    end    # 按下 C 键的情况下    if Input.trigger?(Input::C)      $game_system.se_play($data_system.decision_se)      if @tip_window.index == 0      id = @skill_window.skill.id      @actor.learn_skill(id)      $game_variables -= 1      end      @tip_window.active = false      @tip_window.visible = false      @skill_window.active = true      @status_window.refresh      @skill_window.refresh      @tip_window.index = 0    endendendclass Scene_Titlealias m maindef main    $data_skilltree = get_skill_tree    mendend复制代码如果什么地方乱码了请及时告诉我,懂代码的朋友们请多帮帮忙。
下面是界面,感觉比较烂,不过还能用……

还有一个新工程的附件范例,都一并拿去吧……

刚才看了一下,脚本第99 102 158 273 388行都出现了不该出现的东西,大家把那个什么url的删掉就好,或者直接下范例附件。
            本帖来自P1论坛作者我是羊羽我骄傲,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg.blue/forum.php?mod=viewthread&tid=333339若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。
页: [1]
查看完整版本: 技能树系统