じ☆ve冰风 发表于 2024-4-20 01:39:10

八方向像素移动 优化版

原脚本链接: 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之前新建一页帖进去即生效~

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 == 108or list.code == 408
      if list.parameters =~ /允许斜触发/
          @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_iif@x.is_a?(Float)
    @y = @y.to_iif@y.is_a?(Float)
end
def player_passable?(dir = @direction, px = @x, py = @y)
    case dir
    when8
      (py - 0.5).to_i == py.to_ior(passable?(px.to_i, py.to_i, 8)and
      passable?((px + 0.5).to_i, py.to_i, 8))
    when2
      passable?(px.to_i, py.to_i, 2)and
      passable?((px + 0.5).to_i, py.to_i, 2)
    when4
      (px - 0.5).to_i == px.to_ior(passable?(px.to_i, py.to_i, 4)and
      passable?(px.to_i, (py + 0.5).to_i, 4))
    when6
      passable?(px.to_i, py.to_i, 6)and
      passable?(px.to_i, (py + 0.5).to_i, 6)
    when1
      (player_passable?(4)and player_passable?(2, @x - 0.5))or
      (player_passable?(2)and player_passable?(4, @x, @y + 0.5))
    when3
      (player_passable?(6)and player_passable?(2, @x + 0.5))or
      (player_passable?(2)and player_passable?(6, @x, @y + 0.5))
    when7
      (player_passable?(4)and player_passable?(8, @x - 0.5))or
      (player_passable?(8)and player_passable?(4, @x, @y - 0.5))
    when9
      (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_ior
          (y - 0.5).to_i == y.to_i
          next
      end
      end
      # 事件坐标与目标一致的情况下
      if event.x == x.to_iand event.y == y.to_iand.include?(event.trigger)
      # 跳跃中以外的情况下、启动判定是正面的事件
      ifnot event.jumping? andnot event.over_trigger?
          event.start
          result = true
      end
      end
    end
    return result
end
def player_check_event_trigger_touch(dir)
    case dir
    when8
      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
    when2
      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
    when4
      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
    when6
      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
    when1
      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
    when3
      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
    when7
      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
    when9
      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_iand event.y == @y.to_i)or
      (!event.touch_4and event.x == (@x + 0.5).to_iand event.y == @y.to_i)or
      (!event.touch_4and event.x == @x.to_iand event.y == (@y + 0.5).to_i))
      # 跳跃中以外的情况下、启动判定是同位置的事件
      ifnot 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_ior
          (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_iand event.y == new_y.to_i)or
          (!event.touch_4and event.x == (new_x + 0.5).to_iand event.y == new_y.to_i)or
          (!event.touch_4and event.x == new_x.to_iand event.y == (new_y + 0.5).to_i))
      # 跳跃中以外的情况下、启动判定是正面的事件
      ifnot event.jumping? andnot event.over_trigger?
          event.start
          result = true
      end
      end
      nextif event.touch_4
      case@direction
      when2
      if triggers.include?(event.trigger)and
          ((event.x == @x.to_i - 1and event.y == @y.to_i + 1)or
          (event.x == @x.to_i + 1and event.y == @y.to_i + 1))
          # 跳跃中以外的情况下、启动判定是斜面的事件
          ifnot event.jumping? andnot event.over_trigger?
            event.start
            result = true
          end
      end
      when4
      nextif@x.to_i != (@x + 0.5).to_i
      if triggers.include?(event.trigger)and
          ((event.x == @x.to_i - 1and event.y == @y.to_i - 1)or
          (event.x == @x.to_i - 1and event.y == @y.to_i + 1))
          # 跳跃中以外的情况下、启动判定是斜面的事件
          ifnot event.jumping? andnot event.over_trigger?
            event.start
            result = true
          end
      end
      when6
      nextif@x.to_i != (@x + 0.5).to_i
      if triggers.include?(event.trigger)and
          ((event.x == @x.to_i + 1and event.y == @y.to_i - 1)or
          (event.x == @x.to_i + 1and event.y == @y.to_i + 1))
          # 跳跃中以外的情况下、启动判定是斜面的事件
          ifnot event.jumping? andnot event.over_trigger?
            event.start
            result = true
          end
      end
      when8
      if triggers.include?(event.trigger)and
          ((event.x == @x.to_i - 1and event.y == @y.to_i - 1)or
          (event.x == @x.to_i + 1and event.y == @y.to_i - 1))
          # 跳跃中以外的情况下、启动判定是斜面的事件
          ifnot event.jumping? andnot 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_ior
            (new_y - 0.5).to_i == new_y.to_i
            next
            end
          end
          # 事件坐标与目标一致的情况下
          if triggers.include?(event.trigger)and
            ((event.x == new_x.to_iand event.y == new_y.to_i)or
            (!event.touch_4and event.x == (new_x + 0.5).to_iand event.y == new_y.to_i)or
            (!event.touch_4and event.x == new_x.to_iand event.y == (new_y + 0.5).to_i))
            # 跳跃中以外的情况下、启动判定是正面的事件
            ifnot event.jumping? andnot 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_movethen
      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_movethen
      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_movethen
      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_movethen
      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_movethen
      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_movethen
      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_movethen
      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_movethen
      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_forcingor$game_temp.message_window_showing
      # 如果方向键被按下、主角就朝那个方向移动
      case Input.dir8
      when1
      move_lower_left
      when2
      move_down
      when3
      move_lower_right
      when4
      move_left
      when6
      move_right
      when7
      move_upper_left
      when8
      move_up
      when9
      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()
      # 没有可以启动的事件的情况下
      if result == false
          # 调试模式为 ON 并且按下 CTRL 键的情况下除外
          unless$DEBUGand 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()
      check_event_trigger_there()
      end
    end
end
end




            本帖来自P1论坛作者龙夫三拳tan,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg.blue/forum.php?mod=viewthread&tid=410504若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。
页: [1]
查看完整版本: 八方向像素移动 优化版