查看: 3327|回复: 3

[RMVA发布] 动态值槽脚本(3/16更新)

[复制链接]

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

发表于 2014-3-8 10:39:22 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 taroxd 于 2014-3-16 14:50 编辑

http://rpg.blue/thread-228005-1-1.html 的脚本差不多也是这个效果。
上面的链接的脚本效果也不错,但是我承认我基本看不懂他的脚本……而且似乎会影响到原来血槽的大小之类的。于是我还是按照自己的需求来制作了一个类似的脚本。

这里是发布版。自用版见 http://rpg.blue/thread-344203-2-1.html 16L。除非发现严重Bug,否则只会更新自用版而不会在这里更新。

特点:
值槽完全按照默认脚本设计
值槽上的显示值完全不影响实际值。即:值槽的滚动完全不影响战斗的进行。
值槽滚动的速度可以按照显示的位置分别设置
易于DIY和整合(需要脚本知识,见2L讲解。)

可能会产生脚本兼容性问题(对于导入该脚本的窗口类,该脚本会覆盖 draw_actor_hp 系列方法)
滚动速度并非完全按照设置区域的速度,可能会略快于设置速度。(系统调用的 refresh 方法会导致值槽滚动一次)
值槽每一次滚动都是一次额外的彻底重绘窗口,可能会造成卡顿。(这时应该增大 gauge_refresh_interval 的数值)
两次连续的滚动(如:连续使用两次回复道具)不会叠加,而是会在第一次滚动结束的时间结束(也就是说,第二次使用回复道具不会延长值槽滚动的时间)
值槽的滚动仅对 draw_actor_hp、draw_actor_mp、draw_actor_tp 所绘制的值槽有效

脚本:
[pre lang="ruby" line="1"]
#--------------------------------------------------------------------------
#  ● 动态值槽脚本 Ver1.0 作者:Taroxd
#     可以实现值槽变化时的动态效果。
#     该脚本可能会有较大的不兼容性。如果产生问题,请删除此脚本
#
#--------此处是设置区域,如无必要无需改动---------

#  ↓ 此处为战斗时值槽的设置
  class Window_BattleStatus
    def gauge_rolling_times
      30  # 设置每次值槽变化的刷新次数。该数越大,滚动越慢。
    end
    def gauge_refresh_interval
      1   # 设置两次滚动之间的间隔(单位:帧)。该数越大,滚动越慢且越不连续。
    end   # 增大此数可以提高性能。如果卡顿,可以尝试增大此数。
  end
#  ↑ 战斗场景设置完毕

#  ↓ 此处为菜单中使用道具时值槽的设置
  class Window_MenuStatus < Window_Selectable
    def gauge_rolling_times
      30  # 设置每次值槽变化的刷新次数。该数越大,滚动越慢。
    end
    def gauge_refresh_interval
      2   # 设置两次滚动之间的间隔(单位:帧)。该数越大,滚动越慢且越不连续。
    end   # 增大此数可以提高性能。如果卡顿,可以尝试增大此数。
  end
#  ↑ 使用道具窗口设置完毕

#  ↓ 此处为菜单中使用技能时值槽的设置
  class Window_SkillStatus < Window_Base
    def gauge_rolling_times
      30  # 设置每次值槽变化的刷新次数。该数越大,滚动越慢。
    end
    def gauge_refresh_interval
      2   # 设置两次滚动之间的间隔(单位:帧)。该数越大,滚动越慢且越不连续。
    end   # 增大此数可以提高性能。如果卡顿,可以尝试增大此数。
  end
#  ↑ 使用技能窗口设置完毕

#-------------------更新日志--------------------

#  3/16 修复了对队友使用技能时值槽会重新滚动的bug

#---------不理解脚本者请勿修改以下内容-----------
module RollingGauge
  #--------------------------------------------------------------------------
  # ● 值槽滚动所需的次数
  #--------------------------------------------------------------------------
  def gauge_rolling_times; 30; end
  #--------------------------------------------------------------------------
  # ● 每隔多少帧刷新一次值槽
  #--------------------------------------------------------------------------
  def gauge_refresh_interval; 1; end
  #--------------------------------------------------------------------------
  # ● 初始化
  #--------------------------------------------------------------------------
  def initialize(*)
    @last_gauge_value = {}
    @gauge_fiber      = {}
    @gauge_refresh_counting = 0
    super
  end
  #--------------------------------------------------------------------------
  # ● 更新
  #--------------------------------------------------------------------------
  def update
    super
    update_gauge_rolling
  end
  #--------------------------------------------------------------------------
  # ● 更新值槽
  #--------------------------------------------------------------------------
  def update_gauge_rolling
    @gauge_refresh_counting += 1 unless @gauge_fiber.empty?
    if @gauge_refresh_counting >= gauge_refresh_interval
      refresh
      @gauge_refresh_counting = 0
    end
  end
  #--------------------------------------------------------------------------
  # ● 绘制值槽的方法模板
  #--------------------------------------------------------------------------
  def self.def_draw_actor_(sym)
    module_eval %{
      def draw_actor_#{sym}(actor, x, y, width = 124)
        key = [x, y]
        fiber = @gauge_fiber[key]
        return fiber.resume if fiber
        value = actor.#{sym}
        @last_gauge_value[key] ||= value
        last_value = @last_gauge_value[key]
        if last_value == value
          draw_#{sym}_by_value(actor, value, x, y, width)
          return
        end
        @gauge_fiber[key] = fiber = Fiber.new do
          value = last_value.to_f
          (gauge_rolling_times - 1).times do |i|
            value += (actor.#{sym} - value) / (gauge_rolling_times - i)
            draw_#{sym}_by_value(actor, value.round, x, y, width)
            Fiber.yield
          end
          @last_gauge_value[key] = value = actor.#{sym}
          draw_#{sym}_by_value(actor, value, x, y, width)
          @gauge_fiber.delete(key)
        end
        fiber.resume
      end
    }
  end
  #--------------------------------------------------------------------------
  # ● 定义绘制值槽的方法
  #--------------------------------------------------------------------------
  def_draw_actor_ :hp
  def_draw_actor_ :mp
  def_draw_actor_ :tp
  #--------------------------------------------------------------------------
  # ● 按值绘制 HP
  #--------------------------------------------------------------------------
  def draw_hp_by_value(actor, value, x, y, width = 124)
    draw_gauge(x, y, width, value.to_f / actor.mhp,
      hp_gauge_color1, hp_gauge_color2)
    change_color(system_color)
    draw_text(x, y, 30, line_height, Vocab::hp_a)
    draw_current_and_max_values(x, y, width, value, actor.mhp,
      hp_color(actor), normal_color)
  end
  #--------------------------------------------------------------------------
  # ● 按值绘制 MP
  #--------------------------------------------------------------------------
  def draw_mp_by_value(actor, value, x, y, width = 124)
    draw_gauge(x, y, width, value.to_f / actor.mmp,
      mp_gauge_color1, mp_gauge_color2)
    change_color(system_color)
    draw_text(x, y, 30, line_height, Vocab::mp_a)
    draw_current_and_max_values(x, y, width, value, actor.mmp,
      mp_color(actor), normal_color)
  end
  #--------------------------------------------------------------------------
  # ● 按值绘制 TP
  #--------------------------------------------------------------------------
  def draw_tp_by_value(actor, value, x, y, width = 124)
    draw_gauge(x, y, width, value.to_f / actor.max_tp,
      tp_gauge_color1, tp_gauge_color2)
    change_color(system_color)
    draw_text(x, y, 30, line_height, Vocab::tp_a)
    change_color(tp_color(actor))
    draw_text(x + width - 42, y, 42, line_height, value.to_i, 2)
  end
end

class Window_BattleActor < Window_BattleStatus
  alias draw_actor_hp draw_actor_hp
  alias draw_actor_mp draw_actor_mp
  alias draw_actor_tp draw_actor_tp
end

class Window_BattleStatus < Window_Selectable
  include RollingGauge
end

class Window_MenuStatus < Window_Selectable
  include RollingGauge
end

class Window_SkillStatus < Window_Base
  include RollingGauge
end
[/pre]

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

 楼主| 发表于 2014-3-8 10:39:45 | 显示全部楼层
脚本的讲解:

[pre lang="ruby" line="1"]
# 设置区域省略
module RollingGauge
  #--------------------------------------------------------------------------
  # ● 值槽滚动所需的次数
  #--------------------------------------------------------------------------
  def gauge_rolling_times; 30; end  # 见上方注释
  #--------------------------------------------------------------------------
  # ● 每隔多少帧刷新一次值槽
  #--------------------------------------------------------------------------
  def gauge_refresh_interval; 1; end  # 见上方注释

  # ↑ 以上两个量定义为方法而不是常量,可以便于子类修改,也可以进行动态的计算
  # 想要改动滚动速度,应该在子类对这两个方法进行重定义
  # 如:gauge_rolling_times 可以定义为 $game_party.members.collect(&:mhp).max / 100
  # 可以随着队伍的升级,增加滚动所需要的时间

  #--------------------------------------------------------------------------
  # ● 初始化
  #--------------------------------------------------------------------------
  def initialize(*)              # 不改变参数列表
    @last_gauge_value = {}       # 值槽 => 滚动前值槽上显示的值
    @gauge_fiber      = {}       # 值槽 => 滚动值槽所用的纤程
    @gauge_refresh_counting = 0  # 距离上次刷新值槽已经过了几帧
    super
  end
  #--------------------------------------------------------------------------
  # ● 更新
  #--------------------------------------------------------------------------
  def update
    super
    update_gauge_rolling
  end
  #--------------------------------------------------------------------------
  # ● 更新值槽
  #--------------------------------------------------------------------------
  def update_gauge_rolling
    @gauge_refresh_counting += 1 unless @gauge_fiber.empty?  # 如果还有值槽没有滚动完毕,则更新计数
    if @gauge_refresh_counting >= gauge_refresh_interval     # 此时应该刷新值槽
      refresh                       # 完全重绘,重绘的时候会调用 draw_actor_hp 系列来刷新值槽
      @gauge_refresh_counting = 0   # 计数归零
    end
  end

  # 因为这里hp,mp,tp定义完全相同,因此我在原脚本里偷了个懒。这里仅仅演示hp
  def draw_actor_hp(actor, x, y, width = 124)
    # 这一段判断:如果值槽正在滚动状态,则向前滚动一次(①)
    key = [x, y]                  # 值槽的横纵坐标是值槽的特征。横纵坐标均相同的值槽视为同一值槽。
    fiber = @gauge_fiber[key]     # 获取绘制值槽的纤程
    return fiber.resume if fiber  # 如果当前值槽正在滚动,则从上次停止滚动的地方继续

    # 这一段判断:如果值槽的值不变,则无须滚动(②)
    value = actor.hp              # 获取当前 hp。变量名使用value而不是hp是为了不需要对mp、tp进行修改
    @last_gauge_value[key] ||= value  # 初始化该值槽的信息。这一行代码对一个值槽总共只会执行一次。
    last_value = @last_gauge_value[key]  # 获取值槽上次显示的值
    if last_value == value        # 如果值没有变化
      return draw_hp_by_value(actor, value, x, y, width)  # 直接画出值槽并返回,无须滚动
    end

    # 这一段创建滚动的纤程(③)
    @gauge_fiber[key] = fiber = Fiber.new do  # 创建值槽滚动的纤程
      value = last_value.to_f                 # 初始化需要绘制的值
      (gauge_rolling_times - 1).times do |i|  # 前 n - 1 次滚动
        # 计算公式说明
        # actor.hp - value: 距离滚动目标的差值
        # gauge_rolling_times - i: 值槽滚动剩余的次数
        value += (actor.hp - value) / (gauge_rolling_times - i)
        draw_hp_by_value(actor, value.round, x, y, width)        # 绘制值槽
        Fiber.yield                           # 暂停滚动
      end
      # 最后一次滚动
      @last_gauge_value[key] = value = actor.hp    # 储存当前值槽的值
      draw_hp_by_value(actor, value, x, y, width)  # 最后一次绘制
      @gauge_fiber.delete(key)                     # 表明该值槽已经不需要滚动了
    end

    # 创建的纤程不会立即执行,因此执行一次
    fiber.resume

    # 创建完纤程之后,下一次调用 draw_actor_hp 时,在第①段就会返回,直到滚动完毕为止。
    # 当值槽需要滚动(即 @gauge_fiber 不为空)时,update会定期调用refresh,来进行值槽的滚动。
  end
  #--------------------------------------------------------------------------
  # ● 按值绘制 HP
  #--------------------------------------------------------------------------
  # 如果想要DIY值槽,应该在子类对这个方法进行重定义
  def draw_hp_by_value(actor, value, x, y, width = 124)
    draw_gauge(x, y, width, value.to_f / actor.mhp,
      hp_gauge_color1, hp_gauge_color2)
    change_color(system_color)
    draw_text(x, y, 30, line_height, Vocab::hp_a)
    draw_current_and_max_values(x, y, width, value, actor.mhp,
      hp_color(actor), normal_color)
  end
end

# 战斗状态栏
class Window_BattleStatus < Window_Selectable
  include RollingGauge
end

# 使用道具时的状态栏
class Window_MenuStatus < Window_Selectable
  include RollingGauge
end

# 使用技能时的状态栏
class Window_SkillStatus < Window_Base
  include RollingGauge
end

# 整合方式
class Your_Window
  include RollingGauge
  def gauge_rolling_times; 30; end  # 设置该窗口的值槽滚动速度
  def gauge_refresh_interval; 1; end  # 设置该窗口的值槽滚动间隔
  def draw_hp_by_value(actor, value, x, y, width = 124) # 如果需要
    # 设置该窗口绘制hp的方式
  end
  def draw_all_items  # 如果需要(比如原先绘制值槽不是用draw_actor_hp系列) 注:方法名瞎起的
    # 通过调用 draw_actor_hp 来绘制值槽
  end
end
[/pre]

点评

此处已经不再更新,请阅读使用规约后,用 https://taroxd.github.io/rgss/ 里面的版本  发表于 2017-2-20 07:06
大神,这个脚本我在用,发现一个BUG就是当职业MP最大值是0时,显示MP槽值时会报错。请问可以修复这个吗。  发表于 2017-2-19 23:54
回复

使用道具 举报

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

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部