#============================================================================== # ■ 隊列ジャンプ実装 (VX Ace用) #------------------------------------------------------------------------------ # バージョン : 1.06 # 最終更新日 : 2012/04/19 # 製作者 : CanariAlternate # サイト名 : カルトの鳥篭 # サイトURL : http://canarialt.blog.fc2.com #------------------------------------------------------------------------------ # 設置場所 : 「隊列強制認識」より下。対応Ver1.08以降 # # 機能 : 隊列をジャンプに対応させます。 # # 仕様 : 隊列の先頭(プレイヤー) 〜 隊列の最後尾 のジャンプが終了するまでダッシュが # 禁止されます。この間に移動速度が変化すると隊列の間隔がずれる為です。 # # : 隊列の先頭(プレイヤー) 〜 隊列の最後尾 のジャンプが終了するまでの間は # 移動速度の変更を行わないことを推奨します。理由は上記と同様です。 # # : 隊列のキャラクターはVX Aceのデフォルトの仕様ではパーティ人数に関係なく3人 # 生成されています。隊列歩行をOFFにしていても透明なだけで隊列はプレイヤー # の後ろを行進しています。 # 当スクリプトでは可視状態の隊列のキャラクターのみジャンプを行います。 # その為、特に長距離ジャンプの直後などは不可視状態の隊列のキャラクターが # 壁の中に居るという状況がありえます。 # この状態でメンバーの追加や隊列歩行のONなどで不可視が解除されると # 隊列のキャラクターが壁の中に出現したりします。 # これに対する対策としては直前に場所移動を実行したり隊列強制認識を使って # 隊列のキャラクターに対してイベントの位置設定を実行したりです。 # # ※隊列のキャラクターは壁の中に出現したとしてもすり抜けてプレイヤーを # 追いかけてきます。なのでこれらは見た目の問題となります。 # #------------------------------------------------------------------------------ # 更新履歴 : 2012/04/12 Ver1.00 隊列ジャンプ実装を作成 # : 2012/04/13 Ver1.01 1/2倍速以下で正常に動作しないのを修正 # : 2012/04/14 Ver1.02 同期が上手くいかないのでアルゴリズムを変更 # : 2012/04/16 Ver1.03 同期が上手くいかないのでアルゴリズムを変更 # : 2012/04/18 Ver1.04 隊列の人数が5人以上でも同期できるように修正 # : 2012/04/19 Ver1.05 可視の隊員がジャンプ終了でダッシュ禁止解除に修正 # : 2012/04/19 Ver1.06 場所移動時にジャンプ状態が初期化されてないのを修正 #============================================================================== $imported ||= {} $imported["CanariAlternate_Jump_Follower"] = true if $imported["CanariAlternate_Jump_Follower"] #============================================================================== # ■ Game_CharacterBase #------------------------------------------------------------------------------ #  キャラクターを扱う基本のクラスです。全てのキャラクターに共通する、座標やグ # ラフィックなどの基本的な情報を保持します。 #============================================================================== class Game_CharacterBase #-------------------------------------------------------------------------- # ● 指定位置に移動 [alias] #-------------------------------------------------------------------------- alias _moveto_calt moveto def moveto(x, y) @jump_count = 0 # ジャンプ状態も初期化 _moveto_calt(x, y) end end #============================================================================== # ■ Game_Player #------------------------------------------------------------------------------ #  プレイヤーを扱うクラスです。イベントの起動判定や、マップのスクロールなどの # 機能を持っています。このクラスのインスタンスは $game_player で参照されます。 #============================================================================== class Game_Player < Game_Character attr_writer :jump_point # ジャンプ記憶変数 attr_reader :jump_count #-------------------------------------------------------------------------- # ● ジャンプ記憶変数の取得 [new] #-------------------------------------------------------------------------- def jump_point return @jump_point ||= [] end #-------------------------------------------------------------------------- # ● 場所移動の実行 [alias] #-------------------------------------------------------------------------- alias _perform_transfer_calt perform_transfer def perform_transfer @jump_point = [] if transfer? # ジャンプ記憶変数の初期化 _perform_transfer_calt end #-------------------------------------------------------------------------- # ● 追従と同期を禁止 [alias] #-------------------------------------------------------------------------- if $imported["CanariAlternate_Overwrite_Follower"] alias _follow_disable_calt follow_disable def follow_disable _follow_disable_calt @jump_point = [] # ジャンプ記憶変数の初期化 end end #-------------------------------------------------------------------------- # ● ジャンプが実行されるか判定 [new] # x_plus : X 座標加算値 # y_plus : Y 座標加算値 #-------------------------------------------------------------------------- def jump_judge(x_plus, y_plus) x_plus != 0 || y_plus != 0 end #-------------------------------------------------------------------------- # ● ジャンプ [alias] # x_plus : X 座標加算値 # y_plus : Y 座標加算値 #-------------------------------------------------------------------------- alias _jump_calt jump def jump(x_plus, y_plus) @duplication = true if jump_point.size == 0 # 重複実行防止 @followers.move if jump_judge(x_plus, y_plus) # 隊列の追従を呼出 _jump_calt(x_plus, y_plus) # 再定義前の処理 if $imported["CanariAlternate_Overwrite_Follower"] # 隊列強制認識を実装 return if @followers.follow_disable # 追従が禁止されている時 end return if @followers.visible_last_follower_index == 0 # 可視状態の隊員がいない @jump_point.push([1, @x, @y]) if jump_judge(x_plus, y_plus) # ジャンプ情報を記憶 end #-------------------------------------------------------------------------- # ● ダッシュ状態判定 [alias] #-------------------------------------------------------------------------- alias _dash_calt? dash? def dash? # 可視状態の隊員全員がジャンプ終了するまでダッシュ禁止 if jump_point.size > 0 || @followers.visible_folloers.any? {|follower| follower.jumping? } if $imported["CanariAlternate_Overwrite_Follower"] # 隊列強制認識を実装 return false unless @followers.follow_disable # 追従が禁止されていない時 else return false end end _dash_calt? end #-------------------------------------------------------------------------- # ● フレーム更新 [alias] #-------------------------------------------------------------------------- alias _update_calt update def update if jump_point.size > 0 @followers.move if moving? && !@duplication # 移動中かつ重複実行でない @duplication = false if @duplication # 重複実行防止を偽を代入 end _update_calt end #-------------------------------------------------------------------------- # ● 移動に関する計算式の取得 [new] #-------------------------------------------------------------------------- def move_speed_formula 2 ** get_move_speed end #-------------------------------------------------------------------------- # ● 移動に必要なフレーム数の取得 [new] #-------------------------------------------------------------------------- def real_move_frame 256 / move_speed_formula end #-------------------------------------------------------------------------- # ● 移動速度の取得 [new] #-------------------------------------------------------------------------- def get_move_speed @move_speed end #-------------------------------------------------------------------------- # ● ジャンプ時間の計算 [new] # cnt : 計算途中のデータ, char : 計算対象 #-------------------------------------------------------------------------- def jump_frame_formula(cnt, char) jump_point.size.times do |i| # ジャンプ時間計算 if jump_point[i][0] == char.member_index # 基準座標からの移動距離を計算 px = jump_point[i][1] - cnt[1] py = jump_point[i][2] - cnt[2] # ジャンプ時間を加算 cnt[0] += 2 * (10 + Math.sqrt(px * px + py * py).round - get_move_speed) cnt[1] = jump_point[i][1] # 基準X座標を更新 cnt[2] = jump_point[i][2] # 基準Y座標を更新 end end sx = char.preceding_character.x - cnt[1] sy = char.preceding_character.y - cnt[2] if char.member_index > 1 # 先導キャラがプレイヤーでない if sx != 0 || sy != 0 cnt[0] += real_move_frame cnt[1] = char.preceding_character.x cnt[2] = char.preceding_character.y end # 先導キャラを対象に計算を行う cnt = jump_frame_formula(cnt, char.preceding_character) # 再帰的に else # 先導がプレイヤー if sx != 0 || sy != 0 # 実座標から移動済みフレーム数を逆算 rx = char.preceding_character.real_x - cnt[1] ry = char.preceding_character.real_y - cnt[2] fx = rx.abs / (move_speed_formula / 256.0) fy = ry.abs / (move_speed_formula / 256.0) cnt[0] += fx > fy ? fx : fy # 移動済フレーム数を加算 elsif char.preceding_character.jumping? # ジャンプ未終了フレーム数を減算 cnt[0] -= char.preceding_character.jump_count end end return cnt end #-------------------------------------------------------------------------- # ● ジャンプ処理中の追従処理の実行判定 [new] # char : 実行判定の対象 #-------------------------------------------------------------------------- def jump_follower_move?(char) return true if jump_point.size == 0 # ジャンプ記憶変数が空なら実行 @duplication = true unless moving? # 停止中なら重複実行防止に真を代入 # 先頭キャラとのフレーム数の差, 計算用基準座標x, 計算用基準座標y cnt = [0, char.x, char.y] if char.jumping? # ジャンプ中 cnt[0] += char.jump_count # ジャンプ未終了フレーム数を加算 elsif char.moving? # 移動している # 実座標から移動未終了フレーム数を逆算 rx = char.real_x - cnt[1] ry = char.real_y - cnt[2] fx = rx.abs / (move_speed_formula / 256.0) fy = ry.abs / (move_speed_formula / 256.0) cnt[0] += fx > fy ? fx : fy # 移動未終了フレーム数を加算 end cnt = jump_frame_formula(cnt, char) # ジャンプ時間の計算 # 先頭とのフレーム数の差が必要な間隔以上なら実行 return (cnt[0] >= real_move_frame * char.member_index) ? true : false end end #============================================================================== # ■ Game_Follower #------------------------------------------------------------------------------ #  フォロワーを扱うクラスです。フォロワーとは、隊列歩行で表示する、先頭以外の # 仲間キャラクターのことです。Game_Followers クラスの内部で参照されます。 #============================================================================== class Game_Follower < Game_Character attr_reader :preceding_character attr_reader :member_index attr_reader :jump_count #-------------------------------------------------------------------------- # ● 先導キャラクターを追う [override] #-------------------------------------------------------------------------- def chase_preceding_character unless moving? return unless $game_player.jump_follower_move?(self) # 実行判定 sx = distance_x_from(@preceding_character.x) sy = distance_y_from(@preceding_character.y) # ジャンプ処理 if $game_player.jump_point.size > 0 jp_exe = false # 実行判定結果 jpdel = false # 記憶用済み判定結果 $game_player.jump_point.size.times do |i| if $game_player.jump_point[i][0] == @member_index && !jp_exe $game_player.jump_point[i][0] += 1 jp_exe = i # 用済み判定 jpdel = i if $game_player.jump_point[i][0] > $game_player.followers.visible_last_follower_index end end if jp_exe x_plus = $game_player.jump_point[jp_exe][1] - x y_plus = $game_player.jump_point[jp_exe][2] - y jump(x_plus, y_plus) $game_player.jump_point.delete_at jpdel if jpdel # 用済みなら消去 return end end # 衝突判定(先導キャラの移動先には進入しない) # ※この機能はジャンプとは関連が無いので消去しても全体に影響は無い。 if (sx.abs > 1 || sy.abs > 1) && @member_index > 1 # 自己の移動予定座標の演算 plan_x = @x # 移動予定座標X plan_y = @y # 移動予定座標Y if sx != 0 && sy != 0 plan_x += sx > 0 ? -1 : 1 plan_y += sy > 0 ? -1 : 1 elsif sx != 0 plan_x += sx > 0 ? -1 : 1 elsif sy != 0 plan_y += sy > 0 ? -1 : 1 end # 先導キャラの移動予定座標の演算 p_sx = @preceding_character.distance_x_from(@preceding_character.preceding_character.x) p_sy = @preceding_character.distance_y_from(@preceding_character.preceding_character.y) p_plan_x = @preceding_character.x # 移動予定座標X p_plan_y = @preceding_character.y # 移動予定座標Y if p_sx != 0 && p_sy != 0 p_plan_x += p_sx > 0 ? -1 : 1 p_plan_y += p_sy > 0 ? -1 : 1 elsif p_sx != 0 p_plan_x += p_sx > 0 ? -1 : 1 elsif p_sy != 0 p_plan_y += p_sy > 0 ? -1 : 1 end # 同座標へ移動予定の場合は向き変更のみ行い終了 if plan_x == p_plan_x && plan_y == p_plan_y if sx.abs > sy.abs set_direction(sx > 0 ? 4 : 6) else set_direction(sy > 0 ? 8 : 2) end return end end # プリセット処理 if sx != 0 && sy != 0 move_diagonal(sx > 0 ? 4 : 6, sy > 0 ? 8 : 2) elsif sx != 0 move_straight(sx > 0 ? 4 : 6) elsif sy != 0 move_straight(sy > 0 ? 8 : 2) end end end end #============================================================================== # ■ Game_Followers #------------------------------------------------------------------------------ #  フォロワーの配列のラッパーです。このクラスは Game_Player クラスの内部で使 # 用されます。 #============================================================================== class Game_Followers #-------------------------------------------------------------------------- # ● 可視状態隊員の最後尾の member_index を取得 [new] #-------------------------------------------------------------------------- def visible_last_follower_index v_folloers = visible_folloers return v_folloers.size == 0 ? 0 : v_folloers[-1].member_index end end end