=begin 坂道スクリプト for XP ver 0.1.1.1         by 半生 http://www.tktkgame.com http://www11.atpages.jp/namahanka/ $game_player.slope(dx,dy)  プレイヤーの座標[px, py]と目的地[px+dx, py+dy]を結ぶ直線上を左右のキー入力  で移動できるようにします。範囲外に移動すると解除されます。 $game_player.slope(dx,dy,upper_line, lower_line)  上upper_line列,下lower_line列分の幅をもたせることが出来ます。  起動イベントは結局列数*2必要になります。 ■ 更新履歴 ver 0.1.1.1 (2010/11/18)  導入前のセーブデータでもそれなりに動くように修正。 ver 0.1.1.0 (2010/04/10)  公開。 =end module HnMoveBind class Bind_Root attr_reader :mb_dir attr_accessor :line_range attr_accessor :line attr_reader :rx attr_reader :ry attr_reader :angle def initialize(sx=-1,sy=-1,tx=-1,ty=-1,mb_dir=0) @m_binding = false set_root(sx,sy,tx,ty, mb_dir) @line_range = 0..0 @line = 0 end def binding? @m_binding end def ox(rx, ry) return 0 unless @m_binding return 0 if @mb_dir != 2 return 0 unless inside_ry?(ry) return (@rx[1] - @rx[0]) * (ry - @ry[0]) / (@ry[1] - @ry[0]) + @rx[0] - rx + @line * 128 end def oy(rx, ry) return 0 unless @m_binding return 0 if @mb_dir != 1 return 0 unless inside_rx?(rx) return (@ry[1] - @ry[0]) * (rx - @rx[0]) / (@rx[1] - @rx[0]) + @ry[0] - ry + @line * 128 end def mx(ry, m_x) if !@m_binding or @mb_dir != 2 return m_x end return @rx[0] / 128 + @line if (ry == @ry[0]) return @rx[1] / 128 + @line if (ry == @ry[1]) return m_x unless inside_ry?(ry) new_rx = @rx[0] + ( (@rx[1] - @rx[0]) * (ry - @ry[0])) / (@ry[1] - @ry[0]) return (new_rx + 127) / 128 + @line end def my(rx, m_y) if !@m_binding or @mb_dir != 1 return m_y end return @ry[0] / 128 + @line if (rx == @rx[0]) return @ry[1] / 128 + @line if (rx == @rx[1]) return m_y unless inside_rx?(rx) new_ry = @ry[0] + ( (@ry[1] - @ry[0]) * (rx - @rx[0])) / (@rx[1] - @rx[0]) return (new_ry + 127) / 128 + @line end def between_rx?(rx) rx.between?(@rx.min, @rx.max) end def between_ry?(ry) ry.between?(@ry.min, @ry.max) end def inside_rx?(rx) return false if rx >= @rx.max return false if rx <= @rx.min return true end def inside_ry?(ry) return false if ry >= @ry.max return false if ry <= @ry.min return true end def set_root(sx,sy,tx,ty, mb_dir) self.clear @mb_dir = mb_dir @mb_dir = 0 if @mb_dir > 2 if @mb_dir == 0 return end if @mb_dir == 1 return self.clear if sx == tx if (tx > sx) @rx = [sx * 128, tx * 128] @ry = [sy * 128, ty * 128] else @rx = [tx * 128, sx * 128] @ry = [ty * 128, sy * 128] end if @ry[1] > @ry[0] @angle = -1 elsif @ry[1] < @ry[0] @angle = 1 else @angle = 0 end @step = Math.hypot(1, (ty - sy).to_f / (tx - sx)) else return self.clear if sy == ty if (ty > sy) @rx = [sx * 128, tx * 128] @ry = [sy * 128, ty * 128] else @rx = [tx * 128, sx * 128] @ry = [ty * 128, sy * 128] end if @rx[1] > @rx[0] @angle = -1 elsif @rx[1] < @rx[0] @angle = 1 else @angle = 0 end @step = Math.hypot(1, (tx - sx).to_f / (ty - sy)) end @line = 0 @m_binding = true end def step return 1.0 unless @m_binding if @mb_dir == 1 and (@direction == 4 or @direction == 6) return @step elsif @mb_dir == 2 and (@direction == 2 or @direction == 8) return @step else return 1.0 end end def clear @m_binding = false @line_range = (0..0) @line = 0 @rx = [0,0] @ry = [0,0] @angle = 0 @step = 1.0 end end module Character_Bind attr_reader :m_bind def initialize(*args) super(*args) init_mbind() end def init_mbind @m_bind = Bind_Root.new @last_real_x = 0 @last_real_y = 0 end def m_bind init_mbind() if @m_bind.nil? return @m_bind end def move_bind(sx,sy,tx,ty,mb_dir, range=[0,0]) m_bind.set_root(sx,sy,tx,ty, mb_dir) @m_bind.line_range = Range.new(range.min, range.max) end def mbind(dx,dy,mb_dir, minus=0, plus=0) range = [ [0 - minus, 0].min, [plus, 0].max ] move_bind(@x,@y,@x + dx,@y + dy,mb_dir, range) end def slope(dx, dy, up=0, down=0) range = [ [0 - up, 0].min, [down, 0].max ] move_bind(@x,@y,@x + dx,@y + dy,1, range) end def mb_clear m_bind.clear end def screen_x if m_bind.binding? temp_rx = @real_x @real_x += @m_bind.ox(@x*128,@real_y) sx = super @real_x = temp_rx sx else super end end def screen_y if m_bind.binding? temp_ry = @real_y @real_y += @m_bind.oy(@real_x,@y*128) sy = super @real_y = temp_ry sy else super end end def move_left(turn_ok = true) if m_bind.binding? if @m_bind.mb_dir == 1 and @m_bind.between_rx?(@real_x - 1) turn_left @x -= 1 @y = @m_bind.my(@x*128,@y) @real_y = @y*128 increase_steps elsif @m_bind.mb_dir == 2 and @m_bind.inside_ry?(@real_y) turn_left if turn_ok if @m_bind.line_range.include?(@m_bind.line - 1) @m_bind.line -= 1 @x -= 1 increase_steps end else @m_bind.clear if passable?(@x, @y, 4) super end else super end end # End def move_left def move_right(turn_ok = true) if m_bind.binding? if @m_bind.mb_dir == 1 and @m_bind.inside_rx?(@real_x + 1) turn_right @x += 1 @y = @m_bind.my(@x*128,@y) @real_y = @y*128 increase_steps elsif @m_bind.mb_dir == 2 and @m_bind.inside_ry?(@real_y) turn_right if turn_ok if @m_bind.line_range.include?(@m_bind.line + 1) @m_bind.line += 1 @x += 1 increase_steps end else @m_bind.clear if passable?(@x, @y, 6) super end else super end end # End def move_right def move_up(turn_ok = true) if m_bind.binding? if @m_bind.mb_dir == 2 and @m_bind.inside_ry?(@real_y - 1) turn_up @y -= 1 @real_y = (@y+1)*128 @x = @m_bind.mx(@y*128,@x) @real_x = @x*128 increase_steps elsif @m_bind.mb_dir == 1 and @m_bind.inside_rx?(@real_x) turn_up if turn_ok if @m_bind.line_range.include?(@m_bind.line - 1) @m_bind.line -= 1 @y -= 1 increase_steps end else @m_bind.clear if passable?(@x, @y, 8) super end else super end end # End def move_up def move_down(turn_ok = true) if m_bind.binding? if @m_bind.mb_dir == 2 and @m_bind.inside_ry?(@real_y + 1) turn_down @y += 1 @x = @m_bind.mx(@y*128,@x) @real_x = @x*128 increase_steps elsif @m_bind.mb_dir == 1 and @m_bind.inside_rx?(@real_x) turn_down if turn_ok if @m_bind.line_range.include?(@m_bind.line + 1) @m_bind.line += 1 @y += 1 increase_steps end else @m_bind.clear if passable?(@x, @y, 2) super end else super end end # End def move_down end # End module HnMoveBind::Character_Bind end class Game_Player include HnMoveBind::Character_Bind # 更新 # 再定義orz def update # ローカル変数に移動中かどうかを記憶 last_moving = moving? # 移動中、イベント実行中、移動ルート強制中、 # メッセージウィンドウ表示中のいずれでもない場合 unless moving? or $game_system.map_interpreter.running? or @move_route_forcing or $game_temp.message_window_showing # 方向ボタンが押されていれば、その方向へプレイヤーを移動 case Input.dir4 when 2 move_down when 4 move_left when 6 move_right when 8 move_up end end # ローカル変数に座標を記憶 last_real_x = @real_x last_real_y = @real_y if m_bind.binding? last_real_x += @m_bind.ox(@x*128, @real_y) last_real_y += @m_bind.oy(@real_x, @y*128) end super mb_real_x = @real_x mb_real_y = @real_y if @m_bind.binding? mb_real_x += @m_bind.ox(@x*128, @real_y) mb_real_y += @m_bind.oy(@real_x, @y*128) end # キャラクターが下に移動し、かつ画面上の位置が中央より下の場合 if mb_real_y > last_real_y and mb_real_y - $game_map.display_y > CENTER_Y # マップを下にスクロール $game_map.scroll_down(mb_real_y - last_real_y) end # キャラクターが左に移動し、かつ画面上の位置が中央より左の場合 if mb_real_x < last_real_x and mb_real_x - $game_map.display_x < CENTER_X # マップを左にスクロール $game_map.scroll_left(last_real_x - mb_real_x) end # キャラクターが右に移動し、かつ画面上の位置が中央より右の場合 if mb_real_x > last_real_x and mb_real_x - $game_map.display_x > CENTER_X # マップを右にスクロール $game_map.scroll_right(mb_real_x - last_real_x) end # キャラクターが上に移動し、かつ画面上の位置が中央より上の場合 if mb_real_y < last_real_y and mb_real_y - $game_map.display_y < CENTER_Y # マップを上にスクロール $game_map.scroll_up(last_real_y - mb_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 # ▼ 他の斜め移動系スクリプト対策 ▼ alias :_hn_slope__move_lower_left :move_lower_left unless method_defined?(:_hn_slope__move_lower_left) def move_lower_left if m_bind.binding? if @m_bind.mb_dir == 1 if @m_bind.angle < 0 move_down else move_left end else if @m_bind.angle < 0 move_left else move_down end end else _hn_slope__move_lower_left end end alias :_hn_slope__move_lower_right :move_lower_right unless method_defined?(:_hn_slope__move_lower_right) def move_lower_right if m_bind.binding? if @m_bind.mb_dir == 1 if @m_bind.angle > 0 move_down else move_right end else if @m_bind.angle > 0 move_right else move_down end end else _hn_slope__move_lower_right end end alias :_hn_slope__move_upper_left :move_upper_left unless method_defined?(:_hn_slope__move_upper_left) def move_upper_left if m_bind.binding? if @m_bind.mb_dir == 1 if @m_bind.angle > 0 move_up else move_left end else if @m_bind.angle > 0 move_left else move_up end end else _hn_slope__move_upper_left end end alias :_hn_slope__move_upper_right :move_upper_right unless method_defined?(:_hn_slope__move_upper_right) def move_upper_right if m_bind.binding? if @m_bind.mb_dir == 1 if @m_bind.angle < 0 move_up else move_right end else if @m_bind.angle < 0 move_right else move_up end end else _hn_slope__move_upper_right end end # ▲ 他の斜め移動系スクリプト対策 ▲ end