#============================================================================== # [ZTBS] -Zenith Tactical Battle System- タクティカルバトルシステム #  〜+B8:カーソル滑らか移動〜 by 水夜 #  ver0.90 Zenith Creation (http://zenith.ifdef.jp/) #------------------------------------------------------------------------------ # マップ上での戦略的なバトルを実現。 #============================================================================== module ZTBSB8 # カーソルの速度上昇値 CURSOR_SPEEDUP = 2 # キャラクターの速度上昇値 CHARACTER_SPEEDUP = 1 # 速度上昇のキー DASH_KEY = Input::A end #============================================================================== # ■ Game_Character #============================================================================== class Game_Character #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_writer :x # X 座標(書込み可) attr_writer :y # Y 座標(書込み可) #-------------------------------------------------------------------------- # ● フレーム更新 #-------------------------------------------------------------------------- def update return if @not_update ztbs_update end #-------------------------------------------------------------------------- # ● フレーム更新 (移動) #-------------------------------------------------------------------------- alias :ztbsb8_update_move :update_move def update_move if $game_system.in_tactics # 移動速度からマップ座標系での移動距離に変換 if Input.press?(ZTBSB8::DASH_KEY) distance = 2 ** (@move_speed + ZTBSB8::CHARACTER_SPEEDUP) else distance = 2 ** @move_speed end # 論理座標が実座標より下の場合 if @y * 128 > @real_y # 下に移動 @real_y = [@real_y + distance, @y * 128].min end # 論理座標が実座標より左の場合 if @x * 128 < @real_x # 左に移動 @real_x = [@real_x - distance, @x * 128].max end # 論理座標が実座標より右の場合 if @x * 128 > @real_x # 右に移動 @real_x = [@real_x + distance, @x * 128].min end # 論理座標が実座標より上の場合 if @y * 128 < @real_y # 上に移動 @real_y = [@real_y - distance, @y * 128].max end # 移動時アニメが ON の場合 if @walk_anime # アニメカウントを 1.5 増やす @anime_count += 1.5 # 移動時アニメが OFF で、停止時アニメが ON の場合 elsif @step_anime # アニメカウントを 1 増やす @anime_count += 1 end else ztbsb8_update_move end end end #============================================================================== # ■ Game_Player #============================================================================== class Game_Player < Game_Character #-------------------------------------------------------------------------- # ● 指定位置に移動 # x : X 座標 # y : Y 座標 #-------------------------------------------------------------------------- def moveto(x, y) super # センタリング center(x, y) unless $game_system.in_tactics # エンカウント カウントを作成 make_encounter_count end end #============================================================================== # ■ Sprite_Cursor #============================================================================== class Sprite_Cursor < RPG::Sprite #-------------------------------------------------------------------------- # ● オブジェクト初期化 # viewport : ビューポート # character : キャラクター (Game_Character) #-------------------------------------------------------------------------- def initialize(viewport, x, y) super(viewport) self.bitmap = RPG::Cache.picture(ZTBS::CURSOR) self.src_rect.x = 0 self.src_rect.y = 0 self.src_rect.width = self.bitmap.height self.ox = self.bitmap.height / 2 self.oy = self.bitmap.height self.z = 999 @anime_count = 0 @cell_max = self.bitmap.width / self.bitmap.height moveto(x, y) @real_x = @map_x * 128 @real_y = @map_y * 128 update end #-------------------------------------------------------------------------- # ● 移動中判定 #-------------------------------------------------------------------------- def moving? # 論理座標と実座標が違っていれば移動中 return (@real_x != @map_x * 128 or @real_y != @map_y * 128) end #-------------------------------------------------------------------------- # ● センタリング #-------------------------------------------------------------------------- def center(x, y) max_x = ($game_map.width - 20) * 128 max_y = ($game_map.height - 15) * 128 $game_map.display_x = [0, [x * 128 - Game_Player::CENTER_X, max_x].min].max $game_map.display_y = [0, [y * 128 - Game_Player::CENTER_Y, max_y].min].max end #-------------------------------------------------------------------------- # ● 指定位置に移動 # x : X 座標 # y : Y 座標 #-------------------------------------------------------------------------- def moveto(x, y) @map_x = x % $game_map.width @map_y = y % $game_map.height $game_player.x = @map_x $game_player.y = @map_y end #-------------------------------------------------------------------------- # ● フレーム更新 #-------------------------------------------------------------------------- def update super unless moving? moveto($game_player.x, $game_player.y) end # スプライトの座標を設定 self.x = screen_x self.y = screen_y # 移動速度からマップ座標系での移動距離に変換 if Input.press?(ZTBSB8::DASH_KEY) distance = 2 ** ($game_player.move_speed + ZTBSB8::CURSOR_SPEEDUP) else distance = 2 ** $game_player.move_speed end # 論理座標が実座標より下の場合 if @map_y * 128 > @real_y # 下に移動 @real_y = [@real_y + distance, @map_y * 128].min end # 論理座標が実座標より左の場合 if @map_x * 128 < @real_x # 左に移動 @real_x = [@real_x - distance, @map_x * 128].max end # 論理座標が実座標より右の場合 if @map_x * 128 > @real_x # 右に移動 @real_x = [@real_x + distance, @map_x * 128].min end # 論理座標が実座標より上の場合 if @map_y * 128 < @real_y # 上に移動 @real_y = [@real_y - distance, @map_y * 128].max end # センタリング center(@real_x / 128.0, @real_y / 128.0) end end #============================================================================== # ■ Spriteset_Map #============================================================================== class Spriteset_Map #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :cursor_sprite # カーソルスプライト #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize if $game_system.in_tactics # ビューポートを作成 @viewport1 = Viewport.new(0, 0, 640, 480) @viewport2 = Viewport.new(0, 0, 640, 480) @viewport3 = Viewport.new(0, 0, 640, 480) @viewport2.z = 200 @viewport3.z = 5000 # タイルマップを作成 @tilemap = Tilemap.new(@viewport1) @tilemap.tileset = RPG::Cache.tileset($game_map.tileset_name) for i in 0..6 autotile_name = $game_map.autotile_names[i] @tilemap.autotiles[i] = RPG::Cache.autotile(autotile_name) end @tilemap.map_data = $game_map.data @tilemap.priorities = $game_map.priorities # パノラマプレーンを作成 @panorama = Plane.new(@viewport1) @panorama.z = -1000 # フォグプレーンを作成 @fog = Plane.new(@viewport1) @fog.z = 3000 # エリアスプライトを作成 @area_sprites = [] # レンジスプライトを作成 @range_sprites = [] # 「簡易版マップ処理軽量化」でのエラー防止 if defined?($onscreen) # キャラクタースプライトを作成 @character_sprites = [] @party_sprites = [] for i in $game_map.events.keys.sort sprite = Sprite_Character.new(@viewport1, $game_map.events[i]) @character_sprites[i] = sprite $onscreen[i] = true end @cursor_sprite = Sprite_Cursor.new(@viewport1, $game_player.x, $game_player.y) @party_sprites.push(@cursor_sprite) else # キャラクタースプライトを作成 @character_sprites = [] for i in $game_map.events.keys.sort sprite = Sprite_Character.new(@viewport1, $game_map.events[i]) @character_sprites.push(sprite) end @cursor_sprite = Sprite_Cursor.new(@viewport1, $game_player.x, $game_player.y) @character_sprites.push(@cursor_sprite) end # 天候を作成 @weather = RPG::Weather.new(@viewport1) # ピクチャを作成 @picture_sprites = [] for i in 1..50 @picture_sprites.push(Sprite_Picture.new(@viewport1, $game_screen.pictures[i])) end # タイマースプライトを作成 @timer_sprite = Sprite_Timer.new # フレーム更新 update else ztbs_initialize end end #-------------------------------------------------------------------------- # ● セットアップ #-------------------------------------------------------------------------- def tactics_setup # エリアスプライトを作成 @area_sprites = [] # レンジスプライトを作成 @range_sprites = [] # カーソルを作成 @cursor_sprite = Sprite_Cursor.new(@viewport1, $game_player.x, $game_player.y) if defined? $onscreen @party_sprites.push(@cursor_sprite) else @character_sprites.push(@cursor_sprite) end end end #============================================================================== # ■ Interpreter #============================================================================== class Interpreter #-------------------------------------------------------------------------- # ● フレーム更新 #-------------------------------------------------------------------------- def update # ループカウントを初期化 @loop_count = 0 # ループ loop do # ループカウントに 1 加算 @loop_count += 1 # イベントコマンド 100 個を実行した場合 if @loop_count > 100 # フリーズ防止のため、Graphics.update を呼ぶ Graphics.update @loop_count = 0 end # マップがイベント起動時と異なる場合 if $game_map.map_id != @map_id # イベント ID を 0 にする @event_id = 0 end # 子インタプリタが存在する場合 if @child_interpreter != nil # 子インタプリタを更新 @child_interpreter.update # 子インタプリタの実行が終わった場合 unless @child_interpreter.running? # 子インタプリタを消去 @child_interpreter = nil end # 子インタプリタがまだ存在する場合 if @child_interpreter != nil return end end # メッセージ終了待機中の場合 if @message_waiting return end # カーソルが移動中の場合 if $scene == Scene_Map and $game_system.in_tactics if $scene.spriteset.cursor_sprite.moving? if self == $game_system.map_interpreter return end end end # 移動完了待機中の場合 if @move_route_waiting # プレイヤーが移動ルート強制中の場合 if $game_player.move_route_forcing return end # ループ (マップイベント) for event in $game_map.events.values # このイベントが移動ルート強制中の場合 if event.move_route_forcing return end end # 移動完了待機中フラグをクリア @move_route_waiting = false end # ボタン入力待機中の場合 if @button_input_variable_id > 0 # ボタン入力の処理を実行 input_button return end # ウェイト中の場合 if @wait_count > 0 # ウェイトカウントを減らす @wait_count -= 1 return end # アクションを強制されているバトラーが存在する場合 if $game_temp.forcing_battler != nil return end # 各種画面の呼び出しフラグがセットされている場合 if $game_temp.battle_calling or $game_temp.shop_calling or $game_temp.name_calling or $game_temp.menu_calling or $game_temp.save_calling or $game_temp.gameover return end # 実行内容リストが空の場合 if @list == nil # メインのマップイベントの場合 if @main # 起動中のイベントをセットアップ setup_starting_event end # 何もセットアップされなかった場合 if @list == nil return end end # イベントコマンドの実行を試み、戻り値が false の場合 if execute_command == false return end # インデックスを進める @index += 1 end end #-------------------------------------------------------------------------- # ● 指定イベントへカーソルジャンプ #-------------------------------------------------------------------------- def cursor_moveto_event(event_id) if $game_system.in_tactics event = $game_map.events[event_id] $scene.spriteset.cursor_sprite.moveto(event.x, event.y) # カーソル位置のバトラー(イベント)取得 $scene.get_cursor_battler # ヘルプウィンドウにアクター or エネミーをセット $scene.set_battler_info end return true end #-------------------------------------------------------------------------- # ● 指定座標へカーソルジャンプ #-------------------------------------------------------------------------- def cursor_moveto_position(x, y) if $game_system.in_tactics $scene.spriteset.cursor_sprite.moveto(event.x, event.y) # カーソル位置のバトラー(イベント)取得 $scene.get_cursor_battler # ヘルプウィンドウにアクター or エネミーをセット $scene.set_battler_info end return true end end #============================================================================== # ■ Scene_Map #============================================================================== class Scene_Map #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :spriteset # スプライトセットの参照 #-------------------------------------------------------------------------- # ● フレーム更新 (アクターフェーズ) #-------------------------------------------------------------------------- def update_phase1 # ウィンドウ位置調整 move_window # 戦闘不能復活判定 battler_revival # 勝敗判定 if judge return end # エフェクト中の場合 if effect? return end # カーソル移動中の場合 if @spriteset.cursor_sprite.moving? return end # イベント実行中の場合 if $game_system.map_interpreter.running? return end # セレクト中の場合 if @select != nil and @select != 10 update_select return end # リザルトウィンドウ表示中の場合 if defined? result_window and result_window return end # ステップに応じて更新 case $game_system.tactics_step when 0 update_phase1_step0 when 1 update_phase1_step1 when 2 update_phase1_step2 when 3 update_phase1_step3 when 4 update_phase1_step4 when 5 update_phase1_step5 when 6 update_phase1_step6 when 7 update_step7 when 8 update_step8 when 9 update_step9 when 10 update_step10 end end #-------------------------------------------------------------------------- # ● フレーム更新 (アクターフェーズ ステップ 2 : 移動前コマンド) #-------------------------------------------------------------------------- def update_phase1_step2 if defined?(XRXS_CP_SYSTEM) if @active_battler == nil for i in $game_system.tactics_actors.keys if $game_map.events[i].blink @active_battler = $game_map.events[i] @attacker = $game_system.tactics_actors[i] end end end # 行動できない場合 if @attacker.restriction == 4 # ステップを 10 に設定 $game_system.tactics_step = 10 return end if $game_player.x != @active_battler.x or $game_player.y != @active_battler.y @spriteset.cursor_sprite.moveto(@active_battler.x, @active_battler.y) @battler = @active_battler set_battler_info end end # カーソルが動いていない場合 unless @spriteset.cursor_sprite.moving? # コマンドウィンドウを作成 make_command_window if @command_window == nil # B ボタンが押された場合 if Input.trigger?(Input::B) # キャンセル SE を演奏 $game_system.se_play($data_system.cancel_se) # コマンドウィンドウを解放 dispose_command_window # カーソル固定を解除 $game_player.not_update = false # ステップ 1 へ移行 $game_system.tactics_step = 1 end # C ボタンが押された場合 if Input.trigger?(Input::C) # 決定 SE を演奏 $game_system.se_play($data_system.decision_se) # コマンドによって分岐 case @command_window.index # 移動 when 0 # コマンドウィンドウ解放 dispose_command_window # 移動エリアをセット set_movable_area(0) # カーソル固定を解除 $game_player.not_update = false # ステップ 3 へ移行 $game_system.tactics_step = 3 # 行動バトラー設定 @active_battler = @battler # 防御 when 1 # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # 防御状態に設定 @attacker.current_action.kind = 0 @attacker.current_action.basic = 1 # コマンドウィンドウ解放 dispose_command_window # ステップ 10 へ移行 $game_system.tactics_step = 10 # 攻撃 when 2 # コマンドウィンドウ解放 dispose_command_window # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # アクションを設定 @attacker.current_action.kind = 0 @attacker.current_action.basic = 0 # 攻撃エリアをセット set_attack_area(0) # カーソル固定を解除 $game_player.not_update = false # ステップ 6 へ移行 $game_system.tactics_step = 6 # ステップ 2 帰還フラグ @back_step2 = true # スキル when 3 # コマンドウィンドウ解放 dispose_command_window # セレクト へ移行 @select = 2 # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # セレクトウィンドウを作成 make_select_window(1, @attacker) # アクションを設定 @attacker.current_action.kind = 1 # ステップ 2 帰還フラグ @back_step2 = true # アイテム when 4 # コマンドウィンドウ解放 dispose_command_window # セレクト へ移行 @select = 3 # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # セレクトウィンドウを作成 make_select_window(2) # アクションを設定 @attacker.current_action.kind = 2 # ステップ 2 帰還フラグ @back_step2 = true # その他 else if defined?("talk_event") # 「待機」のための分岐 if defined?(XRXS_CP_SYSTEM) and @command_window.index == 5 # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # コマンドウィンドウ解放 dispose_command_window # ステップ 10 へ移行 $game_system.tactics_step = 10 else @comindex = @command_window.index @comvalue = @command_window.commands[@comindex] # コマンドウィンドウ解放 dispose_command_window # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # アクションを設定 @attacker.current_action.kind = 0 @attacker.current_action.basic = @comindex # 攻撃エリアをセット set_attack_area(0) # カーソル固定を解除 $game_player.not_update = false # ステップ 6 へ移行 $game_system.tactics_step = 6 # ステップ 2 帰還フラグ @back_step2 = true end # 待機 else # コマンドウィンドウ解放 dispose_command_window # ステップ 10 へ移行 $game_system.tactics_step = 10 end end end end end #-------------------------------------------------------------------------- # ● フレーム更新 (エネミーフェーズ) #-------------------------------------------------------------------------- def update_phase2 # ウィンドウ位置調整 move_window # 戦闘不能復活判定 battler_revival # 勝敗判定 if judge return end # エフェクト中の場合 if effect? return end # カーソル移動中の場合 if @spriteset.cursor_sprite.moving? return end # イベント実行中の場合 if $game_system.map_interpreter.running? return end # リザルトウィンドウ表示中の場合 if defined? result_window and result_window return end # ステップに応じて更新 case $game_system.tactics_step when 0 update_phase2_step0 when 1 update_phase2_step1 when 2 update_phase2_step2 when 3 update_phase2_step3 when 4 update_phase2_step4 when 5 update_phase2_step5 when 6 update_phase2_step6 when 7 update_step7 when 8 update_step8 when 9 update_step9 when 10 update_step10 end if $game_system.tactics_step != 1 return end end #-------------------------------------------------------------------------- # ● フレーム更新 (エネミーフェーズ ステップ 1 : アクション作成) #-------------------------------------------------------------------------- def update_phase2_step1 unless defined?(XRXS_CP_SYSTEM) if @active_battler.acted next_enemy return end end @wait_count = ZTBS::ENEMY_THINKING if $game_player.x != @active_battler.x or $game_player.y != @active_battler.y @spriteset.cursor_sprite.moveto(@active_battler.x, @active_battler.y) @battler = @active_battler end # ヘルプウィンドウにアクター or エネミーをセット set_battler_info # アクション作成 @attacker.make_tactical_action # ステップを 2 に設定 $game_system.tactics_step = 2 end end