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

Project1

 找回密码
 注册会员
搜索
查看: 1043|回复: 3
打印 上一主题 下一主题

请教用脚本解决有时限的状态

 关闭 [复制链接]

Lv1.梦旅人

梦石
0
星屑
50
在线时间
0 小时
注册时间
2008-6-17
帖子
41
跳转到指定楼层
1
发表于 2009-5-18 20:00:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
60~70号状态有时间限制为30秒,时间一到无论在地图上还是战斗中,自动去除状态。不要用事件法
版务信息:本贴由楼主自主结贴~

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
2
发表于 2009-5-19 10:26:57 | 只看该作者
用线程?首先一个状态的附加必然要调用 Game_Battler 的 add_state 方法,于是我们就从这个方法下手,在状态确实被添加时打开一个计时线程,计时完毕时就调用 remove_state 去除这个状态,线程终止~

但由于在去除状态之后窗口还没有刷新(菜单中和战斗中的状态窗口),所以可以给 Scene_Battle 和 Scene_Menu 添加一个外部可访问的方法来刷新窗口,这个时候必须考虑线程时间片周期的问题了,否则会导致一些问题——

在单核 CPU 的机器上,60-70号状态可能有多个角色同时被附加,这个时候多个线程开启并计时,到 30 秒后第一个线程开始刷新窗口,在这个过程中,很可能就会发生刷新到一半,比如刚调用完描绘角色名字的方法时突然时间片到期,线程进入等待队列,另一个线程开始执行,这个线程再次描绘了角色的名字一遍,然后又把执行权交由队列中下一个线程

这样就会发生窗口文字“重影”或者“闪烁”的现象,前者是由于多个线程绘制了相同的内容两次,后者却是由于 self.contents.clear 多次被调用;在多核 CPU 的机器上,多个线程可经由多个内核运转,是真正意义上的线程并发运行,所以上面说的情况更是必然发生~

需要做的就让给每个线程在刷新窗口的时候进入一个临界区,在刷新完成之前拒绝其他线程的运行,Ruby 的线程可以通过改变 Thread.critical 这个静态变量来实现线程的同步~
插入以下脚本,注意红色部分,传递给 remove_state_after 的第二个参数就是多少秒后去掉状态:
class Scene_Menu
  def refresh_status_window
    @status_window.refresh
  end

end

class Scene_Battle
  def refresh_status_window
    @status_window.refresh
  end

end

class Game_Battler
  def remove_state_after(state_id, sec)
    Thread.new {
      for i in 0...sec
        sleep 1
      end
      remove_state(state_id)
      Thread.critical = true
      # 如果在战斗中或主菜单已经打开就刷新状态窗口
      if $scene.class == Scene_Menu || $scene.class == Scene_Battle
        $scene.refresh_status_window
      end
      Thread.critical = false
    }
  end

  #--------------------------------------------------------------------------
  # ● 附加状态
  #     state_id : 状态 ID
  #     force    : 强制附加标志 (处理自动状态时使用)
  #--------------------------------------------------------------------------
  def add_state(state_id, force = false)
    # 无效状态的情况下
    if $data_states[state_id] == nil
      # 过程结束
      return
    end
    # 无法强制附加的情况下
    unless force
      # 已存在的状态循环
      for i in @states
        # 新的状态和已经存在的状态 (-) 同时包含的情况下、
        # 本状态不包含变化为新状态的状态变化 (-)
        # (ex : 战斗不能与附加中毒同时存在的场合)
        if $data_states.minus_state_set.include?(state_id) and
           not $data_states[state_id].minus_state_set.include?(i)
          # 过程结束
          return
        end
      end
    end
    # 无法附加本状态的情况下
    unless state?(state_id)
      # 状态 ID 追加到 @states 序列中
      @states.push(state_id)
      remove_state_after(state_id, 30) if 60..70 === state_id
      # 选项 [当作 HP 0 的状态] 有效的情况下
      if $data_states[state_id].zero_hp
        # HP 更改为 0
        @hp = 0
      end
      # 所有状态的循环
      for i in 1...$data_states.size
        # 状态变化 (+) 处理
        if $data_states[state_id].plus_state_set.include?(i)
          add_state(i)
        end
        # 状态变化 (-) 处理
        if $data_states[state_id].minus_state_set.include?(i)
          remove_state(i)
        end
      end
      # 按比例大的排序 (值相等的情况下按照强度排序)
      @states.sort! do |a, b|
        state_a = $data_states[a]
        state_b = $data_states[ b ]
        if state_a.rating > state_b.rating
          -1
        elsif state_a.rating < state_b.rating
          +1
        elsif state_a.restriction > state_b.restriction
          -1
        elsif state_a.restriction < state_b.restriction
          +1
        else
          a <=> b
        end
      end
    end
    # 强制附加的场合
    if force
      # 设置为自然解除的最低回数 -1 (无效)
      @states_turn[state_id] = -1
    end
    # 不能强制附加的场合
    unless  @states_turn[state_id] == -1
      # 设置为自然解除的最低回数
      @states_turn[state_id] = $data_states[state_id].hold_turn
    end
    # 无法行动的场合
    unless movable?
      # 清除行动
      @current_action.clear
    end
    # 检查 HP 及 SP 的最大值
    @hp = [@hp, self.maxhp].min
    @sp = [@sp, self.maxsp].min
  end
end

系统信息:本贴由楼主认可为正确答案,66RPG感谢您的热情解答~
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
129 小时
注册时间
2009-3-29
帖子
432
3
发表于 2009-5-19 15:52:17 | 只看该作者
简直是无语了!!!{/fd}{/fd} 看到楼上的回答令我汗颜!{/gg}
好像紫苏大人每次回答问题都是这么热心{/cy} 小弟佩服啊!{/qiang}{/qiang}
正好顺便问一句,状态的定量上限怎么改呢{/fd}{/fd}
做一个游戏也用这么长时间........
PS:说我自己呢
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
0 小时
注册时间
2008-6-17
帖子
41
4
 楼主| 发表于 2009-5-19 18:12:19 | 只看该作者
佩服!!

以上脚本只能插入在新脚本里吗?我如果直接在Game_Battler 2里改动,再附加状态就会出错

回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2025-1-15 06:31

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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