查看: 5643|回复: 6

[原创发布] 八方向像素移动 优化版

[复制链接]
梦石
7
星屑
655
在线时间
131 小时
注册时间
2011-5-12
回帖
120
发表于 2018-10-9 17:55:34 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 龙夫三拳tan 于 2018-10-9 17:57 编辑

原脚本链接: https://rpg.blue/forum.php?mod=viewthread&tid=382432&highlight=%E5%83%8F%E7%B4%A0%E7%A7%BB%E5%8A%A8
原作者: @Hello``Bubble



优化内容:

1. 修复了 某些情况下, 某(些)个事件当前没有满足出现条件的事件页,于是变量@page的值就是个nil导致报错的情况.

2. 提高了操作灵活性, 半自动纠正移动方向. (尤其是贴着墙走时格外明显, 原版很容易出现卡墙不走的情况)

3. 把默认的"禁止斜触发"改成了 "允许斜触发". 因为大多数情况下物品还是不要斜触发的好, 否则两个事件靠在一起时很容易一次性把两个都触发了导致bug.





关于灵活性的提高方面, 如截图所示. 蓝色方向是玩家按键方向 (→+↑); 红色方向是系统自动纠正的移动方向.

原版本里, 假如你右边是一堵墙时, 你按 →+↑, 它判定你有右上角无法通行后, 就会让你傻傻地站在原地.

现在, 同样情况下, 它判定你右上角无法通行后, 会去判断你的上方和右方是否可通行, 然后把移动方向纠正向 上 或者 右. 在迷宫场景较多的游戏里, 这个改动可以大大提高移动手感. 目前测试暂时没bug

希望这个能帮上大家~


依旧是在Main之前新建一页帖进去即生效~

[pre lang="ruby"]class Game_Temp
  attr_accessor :rgss_move, :dir_4
  #alias rgss_initialize_xxxxxxxxx initialize  默认值???
  #def initialize
  #  rgss_initialize_xxxxxxxxx
  #  @rgss_move = false
  #  @dir_4 = false
  #end
end
class Game_Event < Game_Character
  attr_reader :touch_4
  alias rgss_refresh refresh
  def refresh
    rgss_refresh
    @touch_4 = true
    if list != nil
      for list in @page.list
      if list.code == 108 or list.code == 408
        if list.parameters[0] =~ /允许斜触发/
          @touch_4 = false
          break
        end
      end
    end
  end
   
   
  end
end
class Game_Player < Game_Character
  def x(f=nil)
    return !f ? @x.to_i : @x
  end
  def y(f=nil)
    return !f ? @y.to_i : @y
  end
  def to_i
    @x = @x.to_i if @x.is_a?(Float)
    @y = @y.to_i if @y.is_a?(Float)
  end
  def player_passable?(dir = @direction, px = @x, py = @y)
    case dir
    when 8
      (py - 0.5).to_i == py.to_i or (passable?(px.to_i, py.to_i, 8) and
      passable?((px + 0.5).to_i, py.to_i, 8))
    when 2
      passable?(px.to_i, py.to_i, 2) and
      passable?((px + 0.5).to_i, py.to_i, 2)
    when 4
      (px - 0.5).to_i == px.to_i or (passable?(px.to_i, py.to_i, 4) and
      passable?(px.to_i, (py + 0.5).to_i, 4))
    when 6
      passable?(px.to_i, py.to_i, 6) and
      passable?(px.to_i, (py + 0.5).to_i, 6)
    when 1
      (player_passable?(4) and player_passable?(2, @x - 0.5)) or
      (player_passable?(2) and player_passable?(4, @x, @y + 0.5))
    when 3
      (player_passable?(6) and player_passable?(2, @x + 0.5)) or
      (player_passable?(2) and player_passable?(6, @x, @y + 0.5))
    when 7
      (player_passable?(4) and player_passable?(8, @x - 0.5)) or
      (player_passable?(8) and player_passable?(4, @x, @y - 0.5))
    when 9
      (player_passable?(6) and player_passable?(8, @x + 0.5)) or
      (player_passable?(8) and player_passable?(6, @x, @y - 0.5))
    end
  end
  #--------------------------------------------------------------------------
  # ● 接触事件启动判定
  #--------------------------------------------------------------------------
  def check_event_trigger_touch(x, y)
    result = false
    # 事件执行中的情况下
    if $game_system.map_interpreter.running?
      return result
    end
    # 全事件的循环
    for event in $game_map.events.values
      if event.touch_4
        if (x - 0.5).to_i == x.to_i or
          (y - 0.5).to_i == y.to_i
          next
        end
      end
      # 事件坐标与目标一致的情况下
      if event.x == x.to_i and event.y == y.to_i and [1,2].include?(event.trigger)
        # 跳跃中以外的情况下、启动判定是正面的事件
        if not event.jumping? and not event.over_trigger?
          event.start
          result = true
        end
      end
    end
    return result
  end
  def player_check_event_trigger_touch(dir)
    case dir
    when 8
      check_event_trigger_touch(@x, @y - 1)
      if (@x + 0.5).to_i != @x.to_i
        check_event_trigger_touch(@x + 1, @y - 1)
      end
    when 2
      check_event_trigger_touch(@x, @y + 1)
      if (@x + 0.5).to_i != @x.to_i
        check_event_trigger_touch(@x + 1, @y + 1)
      end
    when 4
      check_event_trigger_touch(@x - 1, @y)
      if (@y + 0.5).to_i != @y.to_i
        check_event_trigger_touch(@x - 1, @y + 1)
      end
    when 6
      check_event_trigger_touch(@x + 1, @y)
      if (@y + 0.5).to_i != @y.to_i
        check_event_trigger_touch(@x + 1, @y + 1)
      end
    when 1
      check_event_trigger_touch(@x - 1, @y + 1)
      if (@x + 0.5).to_i != @x.to_i
        check_event_trigger_touch(@x + 1 - 1, @y + 1)
      end
      check_event_trigger_touch(@x, @y + 1)
      check_event_trigger_touch(@x - 1, @y)
      if (@y + 0.5).to_i != @y.to_i
        check_event_trigger_touch(@x - 1, @y + 1)
      end
    when 3
      check_event_trigger_touch(@x + 1, @y + 1)
      if (@x + 0.5).to_i != @x.to_i
        check_event_trigger_touch(@x + 2, @y + 1)
      end
      check_event_trigger_touch(@x, @y + 1)
      check_event_trigger_touch(@x + 1, @y)
      if (@y + 0.5).to_i != @y.to_i
        check_event_trigger_touch(@x + 1, @y + 1)
      end
    when 7
      check_event_trigger_touch(@x - 1, @y - 1)
      if (@x + 0.5).to_i != @x.to_i
        check_event_trigger_touch(@x + 1 - 1, @y - 1)
      end
      check_event_trigger_touch(@x, @y - 1)
      check_event_trigger_touch(@x - 1, @y)
      if (@y + 0.5).to_i != @y.to_i
        check_event_trigger_touch(@x - 1, @y - 1)
      end
    when 9
      check_event_trigger_touch(@x + 1, @y - 1)
      if (@x + 0.5).to_i != @x.to_i
        check_event_trigger_touch(@x + 2, @y - 1)
      end
      check_event_trigger_touch(@x, @y - 1)
      check_event_trigger_touch(@x + 1, @y)
      if (@y + 0.5).to_i != @y.to_i
        check_event_trigger_touch(@x + 1, @y - 1)
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 同位置的事件启动判定
  #--------------------------------------------------------------------------
  def check_event_trigger_here(triggers)
    result = false
    # 事件执行中的情况下
    if $game_system.map_interpreter.running?
      return result
    end
    # 全部事件的循环
    for event in $game_map.events.values
      # 事件坐标与目标一致的情况下
      if triggers.include?(event.trigger) and
        ((event.x == @x.to_i and event.y == @y.to_i) or
        (!event.touch_4 and event.x == (@x + 0.5).to_i and event.y == @y.to_i) or
        (!event.touch_4 and event.x == @x.to_i and event.y == (@y + 0.5).to_i))
        # 跳跃中以外的情况下、启动判定是同位置的事件
        if not event.jumping? and event.over_trigger?
          event.start
          result = true
        end
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # ● 正面事件的启动判定
  #--------------------------------------------------------------------------
  def check_event_trigger_there(triggers)
    result = false
    # 事件执行中的情况下
    if $game_system.map_interpreter.running?
      return result
    end
    # 计算正面坐标
    new_x = @x + (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
    new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
    # 全部事件的循环
    for event in $game_map.events.values
      if event.touch_4
        if (new_x - 0.5).to_i == new_x.to_i or
          (new_y - 0.5).to_i == new_y.to_i
          next
        end
      end
      # 事件坐标与目标一致的情况下
      if !player_passable? and triggers.include?(event.trigger) and
         ((event.x == new_x.to_i and event.y == new_y.to_i) or
          (!event.touch_4 and event.x == (new_x + 0.5).to_i and event.y == new_y.to_i) or
          (!event.touch_4 and event.x == new_x.to_i and event.y == (new_y + 0.5).to_i))
        # 跳跃中以外的情况下、启动判定是正面的事件
        if not event.jumping? and not event.over_trigger?
          event.start
          result = true
        end
      end
      next if event.touch_4
      case @direction
      when 2
        if triggers.include?(event.trigger) and
          ((event.x == @x.to_i - 1 and event.y == @y.to_i + 1) or
          (event.x == @x.to_i + 1 and event.y == @y.to_i + 1))
          # 跳跃中以外的情况下、启动判定是斜面的事件
          if not event.jumping? and not event.over_trigger?
            event.start
            result = true
          end
        end
      when 4
        next if @x.to_i != (@x + 0.5).to_i
        if triggers.include?(event.trigger) and
          ((event.x == @x.to_i - 1 and event.y == @y.to_i - 1) or
          (event.x == @x.to_i - 1 and event.y == @y.to_i + 1))
          # 跳跃中以外的情况下、启动判定是斜面的事件
          if not event.jumping? and not event.over_trigger?
            event.start
            result = true
          end
        end
      when 6
        next if @x.to_i != (@x + 0.5).to_i
        if triggers.include?(event.trigger) and
          ((event.x == @x.to_i + 1 and event.y == @y.to_i - 1) or
          (event.x == @x.to_i + 1 and event.y == @y.to_i + 1))
          # 跳跃中以外的情况下、启动判定是斜面的事件
          if not event.jumping? and not event.over_trigger?
            event.start
            result = true
          end
        end
      when 8
        if triggers.include?(event.trigger) and
          ((event.x == @x.to_i - 1 and event.y == @y.to_i - 1) or
          (event.x == @x.to_i + 1 and event.y == @y.to_i - 1))
          # 跳跃中以外的情况下、启动判定是斜面的事件
          if not event.jumping? and not event.over_trigger?
            event.start
            result = true
          end
        end
      end
    end
    # 找不到符合条件的事件的情况下
    if result == false
      # 正面的元件是柜台的情况下
      if $game_map.counter?(new_x, new_y)
        # 计算 1 元件里侧的坐标
        new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
        new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
        # 全事件的循环
        for event in $game_map.events.values
          if event.touch_4
            if (new_x - 0.5).to_i == new_x.to_i or
              (new_y - 0.5).to_i == new_y.to_i
              next
            end
          end
          # 事件坐标与目标一致的情况下
          if triggers.include?(event.trigger) and
            ((event.x == new_x.to_i and event.y == new_y.to_i) or
            (!event.touch_4 and event.x == (new_x + 0.5).to_i and event.y == new_y.to_i) or
            (!event.touch_4 and event.x == new_x.to_i and event.y == (new_y + 0.5).to_i))
            # 跳跃中以外的情况下、启动判定是正面的事件
            if not event.jumping? and not event.over_trigger?
              event.start
              result = true
            end
          end
        end
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # ● 向上移动
  #     turn_enabled : 本场地位置更改许可标志
  #--------------------------------------------------------------------------
  def move_up(turn_enabled = true)
    if $game_temp.rgss_move then
      to_i ; super ; return
    end
    # 面向上
    if turn_enabled
      turn_up
    end
    # 可以通行的情况下
    if player_passable?(8)
      # 面向上
      turn_up
      # 更新坐标
      @y -= 0.5
      # 歩数増加
      increase_steps
    # 不能通行的情况下
    else
      # 接触事件的启动判定
      player_check_event_trigger_touch(8)
    end
  end
  #--------------------------------------------------------------------------
  # ● 向下移动
  #     turn_enabled : 本场地位置更改许可标志
  #--------------------------------------------------------------------------
  def move_down(turn_enabled = true)
    if $game_temp.rgss_move then
      to_i ; super ; return
    end
    # 面向下
    if turn_enabled
      turn_down
    end
    # 可以通行的场合
    if player_passable?(2)
      # 面向下
      turn_down
      # 更新坐标
      @y += 0.5
      # 增加步数
      increase_steps
    # 不能通行的情况下
    else
      # 接触事件的启动判定
      player_check_event_trigger_touch(2)
    end
  end
  #--------------------------------------------------------------------------
  # ● 向左移动
  #     turn_enabled : 本场地位置更改许可标志
  #--------------------------------------------------------------------------
  def move_left(turn_enabled = true)
    if $game_temp.rgss_move then
      to_i ; super ; return
    end
    # 面向左
    if turn_enabled
      turn_left
    end
    # 可以通行的情况下
    if player_passable?(4)
      # 面向左
      turn_left
      # 更新坐标
      @x -= 0.5
      # 增加步数
      increase_steps
    # 不能通行的情况下
    else
      # 接触事件的启动判定
      player_check_event_trigger_touch(4)
    end
  end
  #--------------------------------------------------------------------------
  # ● 向右移动
  #     turn_enabled : 本场地位置更改许可标志
  #--------------------------------------------------------------------------
  def move_right(turn_enabled = true)
    if $game_temp.rgss_move then
      to_i ; super ; return
    end
    # 面向右
    if turn_enabled
      turn_right
    end
    # 可以通行的场合
    if player_passable?(6)
      # 面向右
      turn_right
      # 更新坐标
      @x += 0.5
      # 增加步数
      increase_steps
    # 不能通行的情况下
    else
      # 接触事件的启动判定
      player_check_event_trigger_touch(6)
    end
  end
  #--------------------------------------------------------------------------
  # ● 向左下移动
  #--------------------------------------------------------------------------
  def move_lower_left
    if $game_temp.rgss_move then
      to_i ; super ; return
    end
    # 没有固定面向的场合
    unless @direction_fix
      # 朝向是右的情况下适合的面是左面、朝向是上的情况下适合的面是下面
      @direction = (@direction == 6 ? 4 : @direction == 8 ? 2 : @direction)
    end
    # 下→左、左→下 的通道可以通行的情况下
    if player_passable?(1)
      # 更新坐标
      @x -= 0.5
      @y += 0.5
      # 增加步数
      increase_steps
    else
      # 接触事件的启动判定
      player_check_event_trigger_touch(1)
      
      #向左或下绕路
      if player_passable?(4)
        move_left
      elsif player_passable?(2)
        move_down
      end
      #------------------
      
    end
  end
  #--------------------------------------------------------------------------
  # ● 向右下移动
  #--------------------------------------------------------------------------
  def move_lower_right
    if $game_temp.rgss_move then
      to_i ; super ; return
    end
    # 没有固定面向的场合
    unless @direction_fix
      # 朝向是右的情况下适合的面是左面、朝向是上的情况下适合的面是下面
      @direction = (@direction == 4 ? 6 : @direction == 8 ? 2 : @direction)
    end
    # 下→右、右→下 的通道可以通行的情况下
    if player_passable?(3)
      # 更新坐标
      @x += 0.5
      @y += 0.5
      # 增加步数
      increase_steps
    else
      # 接触事件的启动判定
      player_check_event_trigger_touch(3)
      
      #向右或下绕路
      if player_passable?(6)
        move_right
      elsif player_passable?(2)
        move_down
      end
      #------------------

    end
  end
  #--------------------------------------------------------------------------
  # ● 向左上移动
  #--------------------------------------------------------------------------
  def move_upper_left
    if $game_temp.rgss_move then
      to_i ; super ; return
    end
    # 没有固定面向的场合
    unless @direction_fix
      # 朝向是右的情况下适合的面是左面、朝向是上的情况下适合的面是下面
      @direction = (@direction == 6 ? 4 : @direction == 2 ? 8 : @direction)
    end
    # 上→左、左→上 的通道可以通行的情况下
    if player_passable?(7)
      # 更新坐标
      @x -= 0.5
      @y -= 0.5
      # 增加步数
      increase_steps
    else
      # 接触事件的启动判定
      player_check_event_trigger_touch(7)
      
      #向左或上绕路
      if player_passable?(4)
        move_left
      elsif player_passable?(8)
        move_up
      end
      #------------------
      
    end
  end
  #--------------------------------------------------------------------------
  # ● 向右上移动
  #--------------------------------------------------------------------------
  def move_upper_right
    if $game_temp.rgss_move then
      to_i ; super ; return
    end
    # 没有固定面向的场合
    unless @direction_fix
      # 朝向是右的情况下适合的面是左面、朝向是上的情况下适合的面是下面
      @direction = (@direction == 4 ? 6 : @direction == 2 ? 8 : @direction)
    end
    # 上→右、右→上 的通道可以通行的情况下
    if player_passable?(9)
      # 更新坐标
      @x += 0.5
      @y -= 0.5
      # 增加步数
      increase_steps
    else
      # 接触事件的启动判定
      player_check_event_trigger_touch(9)
      
      #向右或下绕路
      if player_passable?(6)
        move_right
      elsif player_passable?(8)
        move_up
      end
      #------------------
      
      
    end
  end
  #--------------------------------------------------------------------------
  # ● 画面更新
  #--------------------------------------------------------------------------
  alias rgss_update update
  def update
    if $game_temp.dir_4
      rgss_update
      return
    end
    # 本地变量记录移动信息
    last_moving = moving?
    # 移动中、事件执行中、强制移动路线中、
    # 信息窗口一个也不显示的时候
    unless moving? or $game_system.map_interpreter.running? or
           @move_route_forcing or $game_temp.message_window_showing
      # 如果方向键被按下、主角就朝那个方向移动
      case Input.dir8
      when 1
        move_lower_left
      when 2
        move_down
      when 3
        move_lower_right
      when 4
        move_left
      when 6
        move_right
      when 7
        move_upper_left
      when 8
        move_up
      when 9
        move_upper_right
      end
    end
    # 本地变量记忆坐标
    last_real_x = @real_x
    last_real_y = @real_y
    super
    # 角色向下移动、画面上的位置在中央下方的情况下
    if @real_y > last_real_y and @real_y - $game_map.display_y > CENTER_Y
      # 画面向下卷动
      $game_map.scroll_down(@real_y - last_real_y)
    end
    # 角色向左移动、画面上的位置在中央左方的情况下
    if @real_x < last_real_x and @real_x - $game_map.display_x < CENTER_X
      # 画面向左卷动
      $game_map.scroll_left(last_real_x - @real_x)
    end
    # 角色向右移动、画面上的位置在中央右方的情况下
    if @real_x > last_real_x and @real_x - $game_map.display_x > CENTER_X
      # 画面向右卷动
      $game_map.scroll_right(@real_x - last_real_x)
    end
    # 角色向上移动、画面上的位置在中央上方的情况下
    if @real_y < last_real_y and @real_y - $game_map.display_y < CENTER_Y
      # 画面向上卷动
      $game_map.scroll_up(last_real_y - @real_y)
    end
    # 不在移动中的情况下
    unless moving?
      # 上次主角移动中的情况
      if last_moving
        # 与同位置的事件接触就判定为事件启动
        result = check_event_trigger_here([1,2])
        # 没有可以启动的事件的情况下
        if result == false
          # 调试模式为 ON 并且按下 CTRL 键的情况下除外
          unless $DEBUG and Input.press?(Input::CTRL)
            # 遇敌计数下降
            if @encounter_count > 0
              @encounter_count -= 1
            end
          end
        end
      end
      # 按下 C 键的情况下
      if Input.trigger?(Input::C)
        # 判定为同位置以及正面的事件启动
        check_event_trigger_here([0])
        check_event_trigger_there([0,1,2])
      end
    end
  end
end[/pre]

自动纠正方向

自动纠正方向

自动拐弯

自动拐弯

原帖

原帖

评分

参与人数 1赞 +1 收起 理由
真·可乐 + 1 塞糖

查看全部评分

梦石
0
星屑
796
在线时间
54 小时
注册时间
2018-1-1
回帖
33
发表于 2018-12-2 14:57:54 | 显示全部楼层
不能跟 人物跟随系统 一起用呀~ 角色走的时候队友傻傻的站着不动
回复

使用道具 举报

梦石
7
星屑
655
在线时间
131 小时
注册时间
2011-5-12
回帖
120
 楼主| 发表于 2018-12-5 23:27:47 | 显示全部楼层
2224573639 发表于 2018-12-2 14:57
不能跟 人物跟随系统 一起用呀~ 角色走的时候队友傻傻的站着不动

这个应该原版脚本也不能来着, 我改的部分应该不涉及那些的说
回复

使用道具 举报

梦石
0
星屑
189
在线时间
18 小时
注册时间
2020-5-23
回帖
16
发表于 2020-5-31 02:28:37 | 显示全部楼层
第544行发生了NoMethodError
Undefind method "map_interpreter" for #<Game_system:0x1e0d878>
回复

使用道具 举报

梦石
0
星屑
301
在线时间
149 小时
注册时间
2012-8-26
回帖
37
发表于 2020-8-30 14:27:09 | 显示全部楼层
很好用,比原版行走丝滑多了
想问下,如果我想让事件(不是主角)行走八方向和半格,应该怎么设置?
还有,这个八方向能换行走图吗,就是奔跑状态的八个方向
回复

使用道具 举报

梦石
0
星屑
40
在线时间
0 小时
注册时间
2026-9-26
回帖
4
发表于 4 天前 | 显示全部楼层
太好了,太好了!!感谢!!!!
回复

使用道具 举报

梦石
0
星屑
5367
在线时间
272 小时
注册时间
2022-12-18
回帖
264
发表于 4 天前 | 显示全部楼层
不错不错
回复

使用道具 举报

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

本版积分规则

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

在本版发帖返回顶部