设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
楼主: 六祈
打印 上一主题 下一主题

[RMVX发布] 技能树系统+技能投点升级(这次没那么疼了,可以直接用了

[复制链接]

Lv1.梦旅人

旅之愚者

梦石
0
星屑
240
在线时间
812 小时
注册时间
2007-7-28
帖子
2148

贵宾

跳转到指定楼层
1
发表于 2010-9-12 08:00:08 | 显示全部楼层 |只看大图 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 六祈 于 2011-1-10 21:12 编辑

意外的发现1对n技能比较符合技能树的情形,于是重新写了一个

使用方法$scene = Scene_Skill_Tree(id),这个id是角色在数据库里的id

技能树设定如图:
注意:说明里必须有skill_tree
备注里如图所写,levelx表示第几层的技能,数字是技能的id,connection里是以数组为元素的数组,表示一前一后(不可颠倒)的技能id

并且目前只支持1前置技能1后置或者1前置n后置,【不支持n前置1后置,画图的算法没想好


然后需要让角色一级学会这个技能树【不能在普通技能列表里看见】


然后是技能成长的部分,技能树里的技能备注里如图这样写:【注意使用本系统的话,不同人物习得同个技能需要多做一份,即一个id的技能只能在一支技能树中出现】

这部分目前即使没设定也不会出错

最后附上工程和截图



自动画技能树.rar (244.29 KB, 下载次数: 10767)

评分

参与人数 2星屑 +14 +2 收起 理由
一瞬间的幻觉 + 14 美工如果能华丽些就完美了
小幽的马甲 + 2

查看全部评分

Lv1.梦旅人

旅之愚者

梦石
0
星屑
240
在线时间
812 小时
注册时间
2007-7-28
帖子
2148

贵宾

2
 楼主| 发表于 2010-9-12 08:03:52 | 显示全部楼层
本帖最后由 六祈 于 2011-1-10 21:16 编辑

连一帖发布代码

Skill_Level
  1. #技能等级

  2. #————————————注意————————————————————————
  3. #———除了本页脚本外,还需要在存读档中追加dump和load技能数据库——————
  4. #————————————注意————————————————————————
  5. module RPG
  6.   class Skill < UsableItem
  7.     #定义技能等级上限的常数
  8.     MAX_LEVEL = 10
  9.     def level
  10.       return @level.nil? ? 0 : @level
  11.     end
  12.    
  13.     def level=(level)
  14.       @level = [level , MAX_LEVEL].min
  15.     end
  16.    
  17.     def learned?
  18.       return level > 0
  19.     end
  20.    
  21.     def level_top?
  22.       return level == MAX_LEVEL
  23.     end
  24.    
  25.     def base_damage
  26.       n = @base_damage
  27.       @base_damage_plus ||= self.read_note("base_damage")
  28.       return @base_damage_plus.nil? ? n : (n + @base_damage_plus * level)
  29.     end
  30.    
  31.     def base_damage_plus
  32.       @base_damage_plus || 0
  33.     end
  34.    
  35.     def atk_f
  36.       n = @atk_f
  37.       @atk_f_plus ||= self.read_note("atk_f")
  38.       return @atk_f_plus.nil? ? n : (n + @atk_f_plus * level)
  39.     end
  40.    
  41.     def atk_f_plus
  42.       @atk_f_plus || 0
  43.     end
  44.    
  45.     def spi_f
  46.       n = @spi_f
  47.       @spi_f_plus ||= self.read_note("spi_f")
  48.       return @spi_f_plus.nil? ? n : (n + @spi_f_plus * level)
  49.     end
  50.    
  51.     def spi_f_plus
  52.       @spi_f_plus || 0
  53.     end
  54.    
  55.     def mp_cost
  56.       n = @mp_cost
  57.       @mp_cost_plus ||= self.read_note("mp_cost")
  58.       return @mp_cost_plus.nil? ? n : (n + @mp_cost_plus * level)
  59.     end
  60.    
  61.     def mp_cost_plus
  62.       @mp_cost_plus || 0
  63.     end
  64.   end
  65. end
复制代码
Skill_Leaf
  1. #在技能树图中用于表示节点的类

  2. class Skill_Leaf
  3.   attr_reader :x , :y , :id
  4.   
  5.   def initialize(skill_id)
  6.     @id = skill_id
  7.     @post_skills = []
  8.     @x = 0
  9.     @y = 0
  10.   end
  11.   
  12.   def learned?
  13.     skill.learned?
  14.   end
  15.   
  16.   def set_x(x)
  17.     @x = x
  18.   end
  19.   
  20.   def set_y(y)
  21.     @y = y
  22.   end
  23.   
  24.   def skill
  25.     $data_skills[@id]
  26.   end
  27.   
  28.   def skill_icon
  29.     $data_skills[@id].icon_index
  30.   end
  31.   
  32.   def set_pre_skill(skill_id)
  33.     @pre_skill = $data_skills[skill_id]
  34.   end
  35.   
  36.   def can_learn?
  37.     return ((@pre_skill.nil? or @pre_skill.learned?) and !skill.level_top?)
  38.   end
  39.   
  40.   def post_skills
  41.     @post_skills
  42.   end
  43.   
  44.   def add_post_skill(skill_id)
  45.     @post_skills.push(skill_id) unless @post_skills.include?(skill_id)
  46.   end

  47. end
复制代码
Skill_Help
  1. #描绘技能属性及升级变化的窗口

  2. class Window_Skill_Help < Window_Base
  3.   attr_reader :skill_id
  4.   def initialize(skill_id)
  5.     super(0 , 0 , 180 , 176)
  6.     @skill_id = skill_id
  7.     refresh
  8.   end
  9.   
  10.   def refresh
  11.     self.contents.clear
  12.     skill = $data_skills[@skill_id]
  13.     self.contents.draw_text(0 , 0 , 146 , 24 , skill.name , 1)
  14.     self.contents.draw_text(0 , 24 , 72 , 24 , "LV")
  15.     self.contents.draw_text(72 , 24 , 74 , 24 , "%3d" % skill.level + (skill.level_top? ? "" : "→" + "%3d" % (skill.level + 1)))
  16.     self.contents.draw_text(0 , 48 , 72 , 24 , "基础伤害")
  17.     self.contents.draw_text(72 , 48 , 74 , 24 , "%3d" % skill.base_damage +
  18.     (skill.level_top? ? "" : "→" + "%3d" % (skill.base_damage + skill.base_damage_plus)))
  19.     self.contents.draw_text(0 , 72 , 72 , 24 , "MP消耗")
  20.     self.contents.draw_text(72 , 72 , 74 , 24 , "%3d" % skill.mp_cost +
  21.     (skill.level_top? ? "" : "→" + "%3d" % (skill.mp_cost + skill.mp_cost_plus)))
  22.     self.contents.draw_text(0 , 96 , 72 , 24 , "攻击相关")
  23.     self.contents.draw_text(72 , 96 , 74 , 24 , "%3d" % skill.atk_f +
  24.     (skill.level_top? ? "" : "→" + "%3d" % (skill.atk_f + skill.atk_f_plus)))
  25.     self.contents.draw_text(0 , 120 , 72 , 24 , "精神相关")
  26.     self.contents.draw_text(72 , 120 , 74 , 24 , "%3d" % skill.spi_f +
  27.     (skill.level_top? ? "" : "→" + "%3d" % (skill.spi_f + skill.spi_f_plus)))
  28.   end
  29.   
  30.   def skill_id=(id)
  31.     @skill_id = id
  32.     refresh
  33.   end
  34.   
  35. end
复制代码
Window_Skill_Tree
  1. class Window_Skill_Tree < Window_Base
  2.   #连线粗细
  3.   LINE_WEIGHT = 3
  4.   #同一技能导出多个技能时x值的分散程度
  5.   WIDTH = 240
  6.   #整体y值位移(为了美观)
  7.   Y_MOVE = -20
  8.   attr_reader :x_index , :y_index
  9.   def initialize(tree_id)
  10.     super(0 , 0 , 240 , 360)
  11.     @x_index = 0
  12.     @y_index = 0
  13.     #定义连线颜色
  14.     @color = Color.new(175 , 28 , 200)
  15.     #转换技能树为各个节点
  16.     create_tree_levels(tree_id)
  17.     #计算各节点y坐标
  18.     calculate_y
  19.     #计算各节点x坐标(x过大或负值过大均会修正)
  20.     calculate_x
  21.     #刷新(描绘点和连线)
  22.     refresh
  23.     #更新选择框
  24.     update_cursor
  25.   end
  26.   
  27.   def refresh
  28.     self.contents.clear
  29.     draw_leaves
  30.     draw_branches
  31.   end
  32.   
  33.   def create_tree_levels(tree_id)
  34.     @levels = []
  35.     level = 0
  36.     @skills = {}
  37.     while(temp = $data_skills[tree_id].read_note("level_" + (level + 1).to_s))
  38.       @levels[level] = []
  39.       temp.each do |id|
  40.         @levels[level].push(@skills[id] = Skill_Leaf.new(id))
  41.       end
  42.       level += 1
  43.     end
  44.     connections = $data_skills[tree_id].read_note("connections")
  45.     connections.each do |line|
  46.       @skills[line[0]].add_post_skill(line[1])
  47.       @skills[line[1]].set_pre_skill(line[0])
  48.     end
  49.     @level_max = @levels.size
  50.   end
  51.   
  52.   def calculate_y
  53.     @delta_y = (self.height - 32) / @levels.size / 2
  54.     @levels.each_with_index do |level , i|
  55.       level.each do |skill|
  56.         skill.set_y(@delta_y * (i * 2 + 1) + Y_MOVE)
  57.       end
  58.     end
  59.   end
  60.   
  61.   def calculate_x
  62.     @levels[0].each_index do |index|
  63.       @levels[0][index].set_x((self.width - 32) / @levels[0].size * (index * 2 + 1) / 2)
  64.     end
  65.     for i in 0...@level_max - 1
  66.       @levels[i].each do |pre_skill|
  67.         size = pre_skill.post_skills.size.to_f
  68.         pre_skill.post_skills.each_with_index do |id , index|
  69.           @skills[id].set_x(pre_skill.x + (((index + 1)/ (size + 1) - 0.5)* WIDTH).to_i)
  70.         end
  71.       end
  72.     end
  73.     @levels.each do |level|
  74.       level.sort!{|a , b| a.x <=> b.x}
  75.     end
  76.     temp = @levels.flatten
  77.     middle = self.width / 2 - 16
  78.     max_x = temp.map{|leaf| (leaf.x - middle).abs}.max
  79.     if max_x > middle - 20
  80.       temp.each do |leaf|
  81.         leaf.set_x(middle + (leaf.x - middle) * (middle - 20) / max_x)
  82.       end
  83.     end
  84.   end
  85.   
  86.   def draw_leaves
  87.     @levels.each do |level|
  88.       level.each do |skill|
  89.         draw_icon(skill.skill_icon , skill.x - 12 , skill.y - 12 , skill.learned?)
  90.       end
  91.     end
  92.   end
  93.   
  94.   def draw_branches
  95.     @skills.each_value do |skill|
  96.       next if @levels[@level_max - 1].include?(skill)
  97.       draw_lines(skill)
  98.     end
  99.   end
  100.   
  101.   def draw_lines(pre_skill)
  102.     return if pre_skill.post_skills.size == 0
  103.     post_skills = pre_skill.post_skills
  104.     case post_skills.size
  105.     when 1
  106.       post_skill = @skills[post_skills[0]]
  107.       self.contents.fill_rect(pre_skill.x , pre_skill.y + 12 , LINE_WEIGHT ,
  108.        post_skill.y - pre_skill.y - 24 , color)
  109.     else
  110.       self.contents.fill_rect(pre_skill.x , pre_skill.y + 12 , LINE_WEIGHT ,
  111.        @delta_y - 12 , color)
  112.       x_start = post_skills.map{|id| @skills[id].x}.min
  113.       x_end = post_skills.map{|id| @skills[id].x}.max
  114.       self.contents.fill_rect(x_start , pre_skill.y + @delta_y ,
  115.        x_end - x_start , LINE_WEIGHT , color)
  116.       post_skills.each do |id|
  117.         self.contents.fill_rect(@skills[id].x , pre_skill.y + @delta_y ,
  118.          LINE_WEIGHT , @skills[id].y - pre_skill.y - @delta_y - 12 , color)
  119.       end
  120.     end
  121.   end

  122.   def update
  123.     super
  124.     if Input.trigger?(Input::LEFT)
  125.       Sound.play_cursor unless @levels[@y_index].size == 1
  126.       @x_index -= 1
  127.       @x_index %= @levels[@y_index].size
  128.       update_cursor
  129.       return
  130.     end
  131.     if Input.trigger?(Input::RIGHT)
  132.       Sound.play_cursor unless @levels[@y_index].size == 1
  133.       @x_index += 1
  134.       @x_index %= @levels[@y_index].size
  135.       update_cursor
  136.       return
  137.     end
  138.     if Input.trigger?(Input::UP)
  139.       Sound.play_cursor
  140.       @y_index -= 1
  141.       @y_index %= @level_max
  142.       @x_index = [@x_index , @levels[@y_index].size - 1].min
  143.       update_cursor
  144.       return
  145.     end
  146.     if Input.trigger?(Input::DOWN)
  147.       Sound.play_cursor
  148.       @y_index += 1
  149.       @y_index %= @level_max
  150.       @x_index = [@x_index , @levels[@y_index].size - 1].min
  151.       update_cursor
  152.       return
  153.     end
  154.   end
  155.   
  156.   def update_cursor
  157.     if @x_index < 0 or @y_index < 0 # 当光标位置小于0
  158.       self.cursor_rect.empty        # 隐藏光标
  159.     else
  160.       skill = @levels[@y_index][@x_index]
  161.       rect = Rect.new(skill.x - 12 , skill.y - 12 , 24 , 24)
  162.       self.cursor_rect = rect       # 更新光标矩形
  163.     end
  164.   end
  165.   
  166.   def skill_leaf
  167.     @levels[@y_index][@x_index]
  168.   end
  169.   
  170.   def color
  171.     @color
  172.   end
  173.   
  174. end
复制代码
Scene_Skill_Tree
  1. #使用方法:$scene = Scene_Skill_Tree(actor_id)

  2. class Scene_Skill_Tree < Scene_Base
  3.   def initialize(actor_id)
  4.     @actor = $game_actors[actor_id]
  5.   end
  6.   
  7.   def start
  8.     @trees = @actor.skill_trees
  9.     @tree_window = Window_Command.new(160 , @trees.map{|id| $data_skills[id].name})
  10.     @tree_window.x = 400
  11.     @skill_window = Window_Skill_Tree.new(@trees[0])
  12.     @map_spriteset = Spriteset_Map.new
  13.     @description_window = Window_Base.new(240 , 0 , 120 , 56)
  14.     refresh_description
  15.     @help_window = Window_Skill_Help.new(skill_id)
  16.     @help_window.z = 9999
  17.     @help_window.visible = false
  18.     move_help_window
  19.   end
  20.   
  21.   def update
  22.     if @tree_window.active
  23.       update_tree
  24.       return
  25.     end
  26.     if @skill_window.active
  27.       update_skill
  28.       return
  29.     end
  30.   end
  31.   
  32.   def terminate
  33.     @skill_window.dispose
  34.     @map_spriteset.dispose
  35.     @description_window.dispose
  36.     @help_window.dispose
  37.     @tree_window.dispose
  38.   end
  39.   
  40.   def update_tree
  41.     @tree_window.update
  42.     if Input.trigger?(Input::B)
  43.       Sound.play_cancel
  44.       $scene = Scene_Map.new
  45.       return
  46.     end
  47.     if Input.trigger?(Input::C)
  48.       Sound.play_decision
  49.       @skill_window = Window_Skill_Tree.new(@trees[@tree_window.index])
  50.       @help_window.visible = true
  51.       @help_window.update
  52.       @skill_window.active = true
  53.       @tree_window.active = false
  54.       return
  55.     end
  56.   end
  57.   
  58.   def update_skill
  59.     @skill_window.update
  60.     refresh_help_window
  61.     if Input.trigger?(Input::B)
  62.       Sound.play_cancel
  63.       @help_window.visible = false
  64.       @tree_window.active = true
  65.       return
  66.     end
  67.     if Input.trigger?(Input::C)
  68.       unless (@skill_window.skill_leaf.can_learn? and @actor.skill_point > 0)
  69.         Sound.play_buzzer
  70.         return
  71.       else
  72.         Sound.play_decision
  73.         @skill_window.skill_leaf.skill.level += 1
  74.         @actor.skill_point -= 1
  75.         @actor.learn_skill(skill_id)
  76.         @skill_window.refresh
  77.         refresh_description
  78.         @help_window.refresh
  79.         return
  80.       end
  81.     end
  82.   end
  83.   
  84.   def refresh_description
  85.     @description_window.contents.clear
  86.     @description_window.contents.draw_text(0 , 0 , 88 , 24 , "技能点: " + "%2d" % @actor.skill_point , 2)
  87.   end
  88.   
  89.   def skill_id
  90.     @skill_window.skill_leaf.id
  91.   end
  92.   
  93.   def refresh_help_window
  94.     if skill_id != @help_window.skill_id
  95.       @help_window.skill_id = skill_id
  96.       move_help_window
  97.     end
  98.   end
  99.   
  100.   def move_help_window
  101.     @help_window.x = @skill_window.skill_leaf.x + 48
  102.     @help_window.y = [@skill_window.skill_leaf.y + 24 , 416 - @help_window.height].min
  103.   end
  104.   
  105. end
复制代码
Game_Actor追加
  1. class Game_Actor
  2.   #每升一级获得技能点常数
  3.   SKILL_POINT_PER_LEVEL = 5
  4.   #获得技能树
  5.   def skill_trees
  6.     @skills.find_all{|skill_id| $data_skills[skill_id].description.index("skill_tree")}
  7.   end
  8.   #常规技能中排除技能树
  9.   def skills
  10.     result = []
  11.     for i in @skills
  12.       next if $data_skills[i].description.index("skill_tree")
  13.       result.push($data_skills[i])
  14.     end
  15.     return result
  16.   end
  17.   #技能点的读写
  18.   def skill_point
  19.     return @skill_point.nil? ? 0 : @skill_point
  20.   end
  21.   
  22.   def skill_point=(p)
  23.     @skill_point = p
  24.   end
  25.   #追加定义,升级获得技能点
  26.   alias :ski_lv_up :level_up
  27.   def level_up
  28.     ski_lv_up
  29.     self.skill_point += SKILL_POINT_PER_LEVEL
  30.   end
  31.   
  32. end
复制代码
回复 支持 反对

使用道具 举报

Lv1.梦旅人

旅之愚者

梦石
0
星屑
240
在线时间
812 小时
注册时间
2007-7-28
帖子
2148

贵宾

3
 楼主| 发表于 2010-9-12 19:43:03 | 显示全部楼层
回复 禾西 的帖子

禾西前辈

愚者前几天做过一个画技能树的东东
http://rpg.blue/thread-155608-1-1.html
这个仅仅是画树,满足了n对1的情况,算法是将点集合用数组传入,边集合用哈希(键为前置技能id,值为后置),之后计算技能树的层次确定y值,第一层平均铺好x值,从第二层开始,每个后置技能的x值均为前置技能的x平均数,画了之后感觉挺美观的。

后来想到技能树还是一前置n后置常见一些,于是又做了今天这个产物,这个的算法是简单的将后置技能的x值分散开来(如果多于一个),感觉上不如前一个好看

另外愚者的问题在于,这两种算法有点没法融合到一起去
回复 支持 反对

使用道具 举报

Lv1.梦旅人

旅之愚者

梦石
0
星屑
240
在线时间
812 小时
注册时间
2007-7-28
帖子
2148

贵宾

4
 楼主| 发表于 2010-9-14 01:30:46 | 显示全部楼层
回复 禾西 的帖子

禾西前辈,愚者认真的读了下您的代码,发现两个问题:1、计算深度时,似乎都只计算第一个前置技能的深度了?2、第二步计算xx时,如果index这个数组不是根据yy来排序的话,似乎会产生不可意料的错误呢
   

点评

所以說要從左至右從上至下排列啊……如果第一第二個前置技能的深度不一樣的話,畫出來的圖會很糾結的。事實上如果想跨組雜交的話,還不如用背景圖覆蓋Orz。所以這是蛋痛腳本,沒有之一。   发表于 2010-9-14 01:48
回复 支持 反对

使用道具 举报

Lv1.梦旅人

旅之愚者

梦石
0
星屑
240
在线时间
812 小时
注册时间
2007-7-28
帖子
2148

贵宾

5
 楼主| 发表于 2010-9-15 22:45:12 | 显示全部楼层
回复 沉影不器 的帖子
回沉影前辈:
愚者是使用了一个技能作为技能树数据的载体
1.该技能【在范例中最后一号技能】说明里添加skill_tree,角色只要习得该技能就拥有该技能树,并且用于设置技能树的技能不会在技能菜单内显示
2.该技能的备注里添加技能树数据
   level1=[id,id]开始,数组内是技能id,层数无上限
   connection=[]数组内以二元数组记录两个有联系的技能

基本上就是这样啦~~

   
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-5-18 14:24

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表