=begin ■ドット単位移動 for VX RGSS2 DAIpage■ α0.01 ●機能と使い方●  ・プレイヤーをドット単位の移動に無理矢理変更。  ・他のイベントは従来どおり。  ・「移動ルートの強制」は従来どおりに機能。   その際には移動前に論理座標に強制的に動かし、位置補正します。 乗り物の乗り降りの際も同様。  ・斜め移動(向きによって角度が変わる)機能つき。 ●再定義している箇所●  Game_Map、Game_Character、Game_Vehicle、Game_Playerの一部を再定義。  ※同じ箇所を変更するスクリプトと併用した場合は競合する可能性があります。 ●要修正課題● ・イベントから抵触の際にポジション取りによっては近づいてこない  コレをどうするか ・移動ルートの強制をもっと自然に(強制位置補正が不自然。特に下、右方向時。) ・マップループへの対応(上手くいった…のか?) ●素材化にあたって● ・デフォスピードを少数点単位で設定できる ・歩行アニメ速度を設定できる ・斜めON/OFFの切替え ・斜め移動タイプの変更 ・専用ボタンでジャンプ機能をつけるか? ・ダッシュ時グラ変更機能をつける? ・斜め専用グラ変更機能をつけるか…? ・無意味な再定義を減らす =end #============================================================================== # ■ Game_Player #============================================================================== class Game_Player < Game_Character #-------------------------------------------------------------------------- # ● オブジェクト初期化(エイリアス) #-------------------------------------------------------------------------- alias dai_dot_move_initialize initialize def initialize dai_dot_move_initialize @dot_move = false @dot_count = 0 @agreement = false end #-------------------------------------------------------------------------- # ● 移動ルートの強制(エイリアス) #-------------------------------------------------------------------------- alias dai_dot_force_move_route force_move_route def force_move_route(move_route) @agreement = true dai_dot_force_move_route(move_route) end #-------------------------------------------------------------------------- # ● 移動中判定(エイリアス) #-------------------------------------------------------------------------- alias dai_dot_moving? moving? def moving? if @move_route_forcing or @vehicle_getting_on or @vehicle_getting_off return dai_dot_moving? end return false end #-------------------------------------------------------------------------- # ● 方向ボタンによる移動処理(再定義) #-------------------------------------------------------------------------- def move_by_input return unless movable? return if $game_map.interpreter.running? case Input.dir8 when 1 then move_dot_lower_left when 2 then move_dot_down when 3 then move_dpt_lower_right when 4 then move_dot_left when 6 then move_dot_right when 7 then move_dot_upper_left when 8 then move_dot_up when 9 then move_dot_upper_right else @dot_move = false straighten end end #-------------------------------------------------------------------------- # ● 移動距離(ドット)の取得 #-------------------------------------------------------------------------- def move_dot_speed a = dash? ? 2 : 1 return 2 ** @move_speed * a end #-------------------------------------------------------------------------- # ● 移動可能判定(再定義) #-------------------------------------------------------------------------- def movable? return false if @move_route_forcing # 移動ルート強制中 return false if @vehicle_getting_on # 乗る動作の途中 return false if @vehicle_getting_off # 降りる動作の途中 return false if $game_message.visible # メッセージ表示中 return false if in_airship? and not $game_map.airship.movable? return true end #-------------------------------------------------------------------------- # ● 強制的に一歩前進(再定義) #-------------------------------------------------------------------------- def force_move_forward @agreement = true @through = true # すり抜け ON move_forward # 一歩前進 @through = false # すり抜け OFF @agreement = false end #-------------------------------------------------------------------------- # ● 下に移動(ドット) #-------------------------------------------------------------------------- def move_dot_down turn_down dy = 0 for i in 1..move_dot_speed dy += 1 if dot_passable?(@real_x, @real_y + i) end @real_y = $game_map.round_r_y(@real_y + dy) update_dot_move(dy) end #-------------------------------------------------------------------------- # ● 左に移動(ドット) #-------------------------------------------------------------------------- def move_dot_left turn_left dx = 0 for i in 1..move_dot_speed dx += 1 if dot_passable?(@real_x - i, @real_y) end @real_x = $game_map.round_r_x(@real_x - dx) update_dot_move(dx) end #-------------------------------------------------------------------------- # ● 右に移動(ドット) #-------------------------------------------------------------------------- def move_dot_right turn_right dx = 0 for i in 1..move_dot_speed dx += 1 if dot_passable?(@real_x + i, @real_y) end @real_x = $game_map.round_r_x(@real_x + dx) update_dot_move(dx) end #-------------------------------------------------------------------------- # ● 上に移動(ドット) #-------------------------------------------------------------------------- def move_dot_up turn_up dy = 0 for i in 1..move_dot_speed dy += 1 if dot_passable?(@real_x, @real_y - i) end @real_y = $game_map.round_r_y(@real_y - dy) update_dot_move(dy) end #-------------------------------------------------------------------------- # ● 左下に移動(ドット) #-------------------------------------------------------------------------- def move_dot_lower_left d = direction_type a = d == 2 ? 2 : 1 b = d == 2 ? 1 : 2 if d == 2 turn_down else turn_left end dx = 0 for i in 1..move_dot_speed / a dx += 1 if dot_passable?(@real_x - i, @real_y) end @real_x = $game_map.round_r_x(@real_x - dx) dy = 0 for i in 1..move_dot_speed / b dy += 1 if dot_passable?(@real_x, @real_y + i) end @real_y = $game_map.round_r_y(@real_y + dy) return if dx == 0 && dy == 0 if d == 2 && dy == 0 turn_left elsif d == 4 && dx == 0 turn_down end update_dot_move(dx + dy) end #-------------------------------------------------------------------------- # ● 右下に移動(ドット) #-------------------------------------------------------------------------- def move_dpt_lower_right d = direction_type a = d == 2 ? 2 : 1 b = d == 2 ? 1 : 2 if d == 2 turn_down else turn_right end dx = 0 for i in 1..move_dot_speed / a dx += 1 if dot_passable?(@real_x + i, @real_y) end @real_x = $game_map.round_r_x(@real_x + dx) dy = 0 for i in 1..move_dot_speed / b dy += 1 if dot_passable?(@real_x, @real_y + i) end @real_y = $game_map.round_r_y(@real_y + dy) return if dx == 0 && dy == 0 if d == 2 && dy == 0 turn_right elsif d == 4 && dx == 0 turn_down end update_dot_move(dx + dy) end #-------------------------------------------------------------------------- # ● 左上に移動(ドット) #-------------------------------------------------------------------------- def move_dot_upper_left d = direction_type a = d == 2 ? 2 : 1 b = d == 2 ? 1 : 2 if d == 2 turn_up else turn_left end dx = 0 for i in 1..move_dot_speed / a dx += 1 if dot_passable?(@real_x - i, @real_y) end @real_x = $game_map.round_r_x(@real_x - dx) dy = 0 for i in 1..move_dot_speed / b dy += 1 if dot_passable?(@real_x, @real_y - i) end @real_y = $game_map.round_r_y(@real_y - dy) return if dx == 0 && dy == 0 if d == 2 && dy == 0 turn_left elsif d == 4 && dx == 0 turn_up end update_dot_move(dx + dy) end #-------------------------------------------------------------------------- # ● 右上に移動(ドット) #-------------------------------------------------------------------------- def move_dot_upper_right d = direction_type a = d == 2 ? 2 : 1 b = d == 2 ? 1 : 2 if d == 2 turn_up else turn_right end dx = 0 for i in 1..move_dot_speed / a dx += 1 if dot_passable?(@real_x + i, @real_y) end @real_x = $game_map.round_r_x(@real_x + dx) dy = 0 for i in 1..move_dot_speed / b dy += 1 if dot_passable?(@real_x, @real_y - i) end @real_y = $game_map.round_r_y(@real_y - dy) return if dx == 0 && dy == 0 if d == 2 && dy == 0 turn_right elsif d == 4 && dx == 0 turn_up end update_dot_move(dx + dy) end #-------------------------------------------------------------------------- # ● 向きの縦横を取得 #-------------------------------------------------------------------------- def direction_type case @direction when 2 then d = 2 when 4 then d = 4 when 6 then d = 4 when 8 then d = 2 end return d end #-------------------------------------------------------------------------- # ● 通行可能判定(ドット) #-------------------------------------------------------------------------- def dot_passable?(r_x, r_y) r_x = $game_map.round_r_x(r_x) # 横方向ループ補正 r_y = $game_map.round_r_y(r_y) # 縦方向ループ補正 return false unless dot_map_valid?(r_x, r_y) # マップ外? return true if @through or debug_through? # すり抜け ON? return false unless dot_map_passable?(r_x, r_y) # マップが通行不能? return false if dot_collide_with_characters?(r_x, r_y) # キャラクターに衝突? return true # 通行可 end #-------------------------------------------------------------------------- # ● マップ通行可能判定(四隅それぞれが通行可能範囲内かを検出) #-------------------------------------------------------------------------- def dot_map_passable?(r_x, r_y) p = pos_candidate(r_x, r_y) for a in p return false unless map_passable?(a[0], a[1]) end return true end #-------------------------------------------------------------------------- # ● マップ外判定(四隅それぞれがマップ内かを検出) #-------------------------------------------------------------------------- def dot_map_valid?(r_x, r_y) p = pos_candidate(r_x, r_y) for a in p return false unless $game_map.valid?(a[0], a[1]) end return true end #-------------------------------------------------------------------------- # ● 属する座標を取得 #-------------------------------------------------------------------------- def pos_candidate(r_x = @real_x, r_y = @real_y) a = dot_four_corners(r_x, r_y) b = [] b.push [a[0] / 256, a[2] / 256] b.push [a[1] / 256, a[2] / 256] b.push [a[1] / 256, a[3] / 256] b.push [a[0] / 256, a[3] / 256] return b end #-------------------------------------------------------------------------- # ● 論理座標候補4点から、最も面積が広い座標を取得 #-------------------------------------------------------------------------- def set_pos four = dot_four_corners pos = pos_candidate r = 0 for i in pos x = i[0] * 256 + 256 y = i[1] * 256 + 256 rx = x - four[0] <= 256 ? x - four[0] : four[1] % 256 ry = y - four[2] <= 256 ? y - four[2] : four[3] % 256 if rx * ry >= r r = rx * ry xy = i end end return xy end #-------------------------------------------------------------------------- # ● キャラクター衝突判定 #-------------------------------------------------------------------------- def dot_collide_with_characters?(r_x = @real_x, r_y = @real_y) for i in pos_candidate(r_x, r_y) for event in $game_map.events_xy(i[0], i[1]) unless event.through # すり抜け OFF? if event.priority_type == 1 # 相手が通常キャラ event.dot_contact?(dot_four_corners) return true end end end end return false end #-------------------------------------------------------------------------- # ● ドット移動時の処理 #-------------------------------------------------------------------------- def update_dot_move(dot) @dot_move = true @dot_count += dot if @dot_count >= 256 update_encounter $game_party.increase_steps $game_party.on_player_walk @dot_count = 0 end @anime_count += dot / 3 end #-------------------------------------------------------------------------- # ● 論理座標と一致判定 #-------------------------------------------------------------------------- def pos_agreement? return (@real_x == @x * 256 or @real_y == @y * 256) end #-------------------------------------------------------------------------- # ● 論理座標と一致させる #-------------------------------------------------------------------------- def move_pos_agreement a = (@x * 256) - @real_x b = (@y * 256) - @real_y dx = 0 dy = 0 for i in 1..move_dot_speed / 2 dx += 1 if dot_passable?(@real_x + i, @real_y) end for i in 1..move_dot_speed / 2 dy += 1 if dot_passable?(@real_x, @real_y - i) end if dx.abs >= dy.abs if dy > 0 turn_right else turn_right end else if dx > 0 turn_down else turn_up end end dx = a if dx > a dy = b if dy > b @real_x = $game_map.round_r_x(@real_x + dx) @real_y = $game_map.round_r_y(@real_y + dy) return if dx == 0 && dy == 0 @anime_count += (dx + dy) / 3 end #-------------------------------------------------------------------------- # ● アニメカウントの更新 #-------------------------------------------------------------------------- def dot_update_animation if @anime_count > 32 @pattern = (@pattern + 1) % 4 @anime_count = 0 end end #-------------------------------------------------------------------------- # ● 接触(重なり)によるイベント起動判定 #-------------------------------------------------------------------------- def check_touch_event return false if $game_message.visible return false if in_airship? return check_event_trigger_here([1,2]) end #-------------------------------------------------------------------------- # ● 決定ボタンによるイベント起動判定 #-------------------------------------------------------------------------- def check_action_event return false if pos_candidate(@real_x, @real_y).uniq.size >= 3 return false if $game_message.visible return false if not Input.trigger?(Input::C) return false if in_airship? return false unless dot_front_event? return true if check_event_trigger_here([0]) return check_event_trigger_there([0,1,2]) end #-------------------------------------------------------------------------- # ● 正面にイベントが存在? #-------------------------------------------------------------------------- def dot_front_event? case @direction when 2 then a, b = 0, +32 when 4 then a, b = -32, 0 when 6 then a, b = +32, 0 when 8 then a, b = 0, -32 end return dot_collide_with_characters?(@real_x + a, @real_y + b) end #-------------------------------------------------------------------------- # ● 乗り物に乗船可能か? #-------------------------------------------------------------------------- def vehicle_pos? front_x = $game_map.x_with_direction(@x, @direction) front_y = $game_map.y_with_direction(@y, @direction) if $game_map.airship.pos?(@x, @y) # 飛行船と重なっている? return true elsif $game_map.ship.pos?(front_x, front_y) # 正面に大型船がある? return true elsif $game_map.boat.pos?(front_x, front_y) # 正面に小型船がある? return true end return false end #-------------------------------------------------------------------------- # ● 乗り物から降船可能か? #-------------------------------------------------------------------------- def vehicle_off? if in_airship? # 飛行船 return false unless airship_land_ok?(@x, @y) # 着陸できない? else # 小型船・大型船 front_x = $game_map.x_with_direction(@x, @direction) front_y = $game_map.y_with_direction(@y, @direction) return false unless can_walk?(front_x, front_y) # 接岸できない? end return true end #-------------------------------------------------------------------------- # ● フレーム更新(再定義) #-------------------------------------------------------------------------- def update unless @move_route_forcing or @agreement or @vehicle_getting_on or @vehicle_getting_off update_pos end last_dot_move = @dot_move last_real_x = $game_map.round_r_x(@real_x) last_real_y = $game_map.round_r_y(@real_y) if jumping? # ジャンプ中 update_jump end if @agreement move_pos_agreement # 位置補正中 if pos_agreement? @agreement = false update_animation end return end if @wait_count > 0 # ウェイト中 @wait_count -= 1 elsif @move_route_forcing # 移動ルート強制中 move_type_custom update_move update_animation elsif @vehicle_getting_on or @vehicle_getting_off update_move update_animation else move_by_input check_action_event unless in_airship? if last_dot_move == false && @dot_move @pattern = (@pattern + 1) % 4 @anime_count = 0 end end get_vehicle_update update_b(last_real_x, last_real_y) end #-------------------------------------------------------------------------- # ● 基本更新 #-------------------------------------------------------------------------- def update_b(last_real_x, last_real_y) update_scroll(last_real_x, last_real_y) update_vehicle dot_update_animation end #-------------------------------------------------------------------------- # ● 乗り物の乗り降りの更新 #-------------------------------------------------------------------------- def get_vehicle_update if (not $game_message.visible) && Input.trigger?(Input::C) if vehicle_pos? && (not in_vehicle?) get_on_vehicle return elsif in_vehicle? get_off_vehicle if vehicle_off? return end end end #-------------------------------------------------------------------------- # ● 座標の更新 #-------------------------------------------------------------------------- def update_pos last_pos = [@x, @y] @x = $game_map.round_x(set_pos[0]) @y = $game_map.round_y(set_pos[1]) if last_pos != [@x, @y] check_touch_event update_bush_depth end end end #============================================================================== # ■ Game_Character #============================================================================== class Game_Character #-------------------------------------------------------------------------- # ● キャラクターの四隅を取得 #-------------------------------------------------------------------------- def dot_four_corners(r_x = @real_x, r_y = @real_y) lx = r_x + 32 rx = r_x + 256 - 32 uy = r_y + 32 dy = r_y + 256 - 32 if $game_map.loop_horizontal? lx = $game_map.round_r_x(lx) rx = $game_map.round_r_x(rx) end if $game_map.loop_vertical? uy = $game_map.round_r_y(uy) dy = $game_map.round_r_y(dy) end return [lx, rx, uy, dy] end #-------------------------------------------------------------------------- # ● 通行可能判定(再定義) #-------------------------------------------------------------------------- def passable?(x, y) x = $game_map.round_x(x) # 横方向ループ補正 y = $game_map.round_y(y) # 縦方向ループ補正 return false unless $game_map.valid?(x, y) # マップ外? return true if @through or debug_through? # すり抜け ON? return false unless map_passable?(x, y) # マップが通行不能? return false if collide_with_characters?(x, y) # キャラクターに衝突? return false if $game_player.pos_candidate.include?([x, y]) return true # 通行可 end #-------------------------------------------------------------------------- # ● ドット単位接触判定 #-------------------------------------------------------------------------- def dot_contact?(r) a = dot_four_corners b = ((a[0] - r[0]) < 256 && (a[1] - r[1]) < 256) or ((a[0] - r[0]) < -256 && (a[1] - r[1]) < -256) return b end end #============================================================================== # ■ Game_Vehicle #============================================================================== class Game_Vehicle < Game_Character #-------------------------------------------------------------------------- # ● 移動可能判定(再定義) #-------------------------------------------------------------------------- def movable? return false if (@type == 2 and @altitude < MAX_ALTITUDE) return true end end #============================================================================== # ■ Game_Map #============================================================================== class Game_Map #-------------------------------------------------------------------------- # ● 有効座標判定(再定義) #-------------------------------------------------------------------------- def valid?(x, y) a = x >= 0 && x < width b = y >= 0 && y < height a = true if loop_horizontal? b = true if loop_vertical? return (a && b) end #-------------------------------------------------------------------------- # ● ドットの属する座標を算出 #-------------------------------------------------------------------------- def dot_xy(rx, ry) ax = rx % 256 ay = ry % 256 x = (rx - ax) / 256 y = (ry - ay) / 256 return [x, y] end #-------------------------------------------------------------------------- # ● ループ補正後の X 実座標計算 #-------------------------------------------------------------------------- def round_r_x(r_x) if loop_horizontal? return (r_x + width * 256) % (width * 256) else return r_x end end #-------------------------------------------------------------------------- # ● ループ補正後の Y 実座標計算 #-------------------------------------------------------------------------- def round_r_y(r_y) if loop_vertical? return (r_y + height * 256) % (height * 256) else return r_y end end end