#▽△▽ XRXSv9. BaST-VX.CAM1. 二軸3DバトルカメラXC. ▽△▽ # # publish 2011/ 1/ 1 # update - /14c # #============================================================================== # カスタマイズポイント #============================================================================== class XRXSV_BattleCam3D # # バトルバックをカメラに連動させる? # BattleBackMoving = false # # 回転軸とする画面中央位置座標 # CX = 272 CY = 264 # # バトラーグラフィック拡大率 # EnemySize = 0.6 ActorSize = 1.2 # # # [カメラ挙動](サイドビューバトラーモーション用) # # ・標準攻撃アングル(単体攻撃などの通常攻撃や単体スキル) #   0 : 基本ズームアウト #   1 : 20°回転ズームイン #   2 : ホライジング MoveTypeActorAttack = 2 MoveTypeEnemyAttack = 1 # # ・画面全体(基準位置「画面」)設定のアニメーションのスキルの行動時 #   0 : 基本ズームアウト #   1 : 20°回転ズームイン #   2 : ホライジング MoveTypeFullScreenAnimationSkill = 1 # # ・仲間を対象とした行動時(回復や補助魔法など) #   0 : 基本ズームアウト #   1 : 20°回転ズームイン #   2 : ホライジング MoveTypeActorOnly = 1 MoveTypeEnemyOnly = 1 # # ジャンプ登場のために最初にカメラを右にずらす? # MoveTypeStartAtRight = true # # # [BattleFloor] # # ・中央Y座標 BattleFloorCY = 80 # # ・基本見下ろし角度[単位:度] DefaultAV = 8 # # # [制作者用] # # ・バトルフロアグラフィック3D垂直角度によるn値[n/16] BFVirticalAngleRate = Math.sin(DefaultAV * Math::PI / 180) * 16 # # ・カメラZ値に対するキャラクターZ値の比率[1/n] BattlerZDivision = 2 end #============================================================================== # バトル中のカメラ挙動指定 #============================================================================== class Scene_Battle < Scene_Base def update_battle_cam $game_temp.xcam.update end def xcam_reset $game_temp.xcam.reset end def xcam_turn_refresh $game_temp.xcam.go_reset targets = [] for enemy in $game_party.members + $game_troop.members targets.push(enemy) if enemy.exist? end $game_temp.xcam.watch(nil, targets) end def wait_for_xcam update_basic while $game_temp.xcam.moving? end end #============================================================================== # バトルカメラ3DXC. #============================================================================== class XRXSV_BattleCam3D attr_reader :x attr_reader :y attr_reader :z attr_reader :ah attr_reader :av #-------------------------------------------------------------------------- # ○ 初期化と位置指定 #-------------------------------------------------------------------------- def initialize reset end def reset @lock = false @x = Graphics.width / 2 @y = Graphics.height / 2 @z = 185 @ah = 0 @av = XRXSV_BattleCam3D::DefaultAV @active_battler = nil @targets = [] @x_max = 0 @moved = false if XRXSV_BattleCam3D::MoveTypeStartAtRight @x_max = 32 @x += 32 @z = 148 end @zoomout_mode = false go_reset end def go_reset @x_dest = Graphics.width / 2 @y_dest = Graphics.height / 2 @z_dest = 185 @ah_dest = 0 @av_dest = XRXSV_BattleCam3D::DefaultAV end def watch(active_battler, targets) return if @lock @active_battler = active_battler @targets = targets end def set_horize(active_battler, targets) return if @lock @zoomout_mode = false actor_only = true enemy_only = true for battler in ([active_battler] + targets).compact actor_only &= battler.is_a?(Game_Actor) enemy_only &= battler.is_a?(Game_Enemy) end @av_dest = XRXSV_BattleCam3D::DefaultAV if not $game_party.members[0].in_floor? @ah_dest = 0 elsif actor_only set_actor_only(active_battler, targets) elsif enemy_only set_enemy_only(active_battler, targets) else akill = active_battler.action.skill animation = (akill and $data_animations[akill.animation_id]) to_screen = (animation and animation.position == 3) if active_battler.is_a?(Game_Actor) if to_screen set_actor_screen(active_battler, targets) else set_actor_attack(active_battler, targets) end else if to_screen set_enemy_screen(active_battler, targets) else set_enemy_attack(active_battler, targets) end end end if @zoomout_mode go_reset end end #-------------------------------------------------------------------------- # カスタムカメラムーブ #-------------------------------------------------------------------------- case XRXSV_BattleCam3D::MoveTypeActorOnly when 0 def set_actor_only(active_battler, targets) @zoomout_mode = true end when 1 def set_actor_only(active_battler, targets) @ah_dest = -20 @av_dest = 8 end when 2 def set_actor_only(active_battler, targets) @ah_dest = calc_horizing(active_battler, targets) @av_dest = 6 end end case XRXSV_BattleCam3D::MoveTypeEnemyOnly when 0 def set_enemy_only(active_battler, targets) @zoomout_mode = true end when 1 def set_enemy_only(active_battler, targets) @ah_dest = 20 @av_dest = 6 end when 2 def set_enemy_only(active_battler, targets) @ah_dest = calc_horizing(active_battler, targets) @av_dest = 6 end end case XRXSV_BattleCam3D::MoveTypeFullScreenAnimationSkill when 0 def set_actor_screen(active_battler, targets) @zoomout_mode = true end def set_enemy_screen(active_battler, targets) @zoomout_mode = true end when 1 def set_actor_screen(active_battler, targets) @ah_dest = -50 @av_dest = 6 end def set_enemy_screen(active_battler, targets) @ah_dest = -20 end when 2 def set_actor_screen(active_battler, targets) @ah_dest = calc_horizing(active_battler, targets) @av_dest = 6 end def set_enemy_screen(active_battler, targets) @ah_dest = calc_horizing(active_battler, targets) @av_dest = 6 end end case XRXSV_BattleCam3D::MoveTypeActorAttack when 0 def set_actor_attack(active_battler, targets) @zoomout_mode = true end when 1 def set_actor_attack(active_battler, targets) @ah_dest = -16 end when 2 def set_actor_attack(active_battler, targets) @ah_dest = calc_horizing(active_battler, targets) @av_dest = 6 end end case XRXSV_BattleCam3D::MoveTypeEnemyAttack when 0 def set_enemy_attack(active_battler, targets) @zoomout_mode = true end when 1 def set_enemy_attack(active_battler, targets) @ah_dest = 12 end when 2 def set_enemy_attack(active_battler, targets) @ah_dest = calc_horizing(active_battler, targets) @av_dest = 6 end end def calc_horizing(active_battler, targets) ax = active_battler.screen_x ay = active_battler.screen_y min_x, max_x, min_y, max_y = targets_extent(targets) cx = (min_x + max_x) / 2 cy = (min_y + max_y) / 2 ah_dest = ((Math.atan2((cy - ay), (cx - ax).abs)) * 180 / Math::PI).to_i * -1 return [[ah_dest, -360].max, 360].min end #-------------------------------------------------------------------------- # #-------------------------------------------------------------------------- def targets_extent(targets) min_x = 640 max_x = 0 min_y = 480 max_y = 0 for target in targets if target.in_floor? nx = target.screen_x ny = target.screen_y nb = target.battler_size min_x = nx - nb if min_x > nx - nb max_x = nx + nb if max_x < nx + nb min_y = ny if min_y > ny max_y = ny if max_y < ny exist = true end end return min_x, max_x, min_y, max_y end #-------------------------------------------------------------------------- # ○ フレーム更新 #-------------------------------------------------------------------------- def update return if @lock @moved = false battlers = ([@active_battler] + @targets).compact if not battlers.empty? and not @zoomout_mode min_x, max_x, min_y, max_y = targets_extent(battlers) @x_dest = (max_x + min_x) / 2 @y_dest = (max_y + min_y) / 2 - 64 @z_dest = [[185 * ((max_x - min_x)) / 544, 37].max, 185].min end if @z != @z_dest @z = slide(@z, @z_dest, 6) if false ###@z == @z_dest @x_max = (185 - @z) * 27 / 37 @y_max = (185 - @z) * 8 / 37 if @x_dest < Graphics.width / 2 - @x_max @x_dest = Graphics.width / 2 - @x_max elsif @x_dest > Graphics.width / 2 + @x_max @x_dest = Graphics.width / 2 + @x_max end if @y_dest < Graphics.height / 2 - @y_max @y_dest = Graphics.height / 2 - @y_max elsif @y_dest > Graphics.height / 2 + @y_max @y_dest = Graphics.height / 2 + @y_max end end @moved = true #return end if @x != @x_dest @x = slide(@x, @x_dest, 8) @moved = true end if @y != @y_dest @y = slide(@y, @y_dest, 4) @moved = true end if @ah != @ah_dest @ah = slide(@ah, @ah_dest, 6) @ah -= 360 if @ah >= 181 @moved = true end if @av != @av_dest @av = slide(@av, @av_dest, 0.2) @moved = true end end def moving? return @moved end #-------------------------------------------------------------------------- # ○ スライド (現在地・目的地から行くべき現在地を返す) #-------------------------------------------------------------------------- def slide(from, to, move_speed) #, to_min, to_max) # 結果を判別 if (to - from).abs <= move_speed result = to else sign = from > to ? -1 : 1 result = from + sign * move_speed end # 範囲によって返却 return result #[[result, to_min].max, to_max].min end #-------------------------------------------------------------------------- # #-------------------------------------------------------------------------- def reverse? return ((self.ah + 90) % 360 >= 180) end def direction_angle return [2,6,8,4][((self.ah + 45) % 360) / 90] end #-------------------------------------------------------------------------- # 水平アングル適用後のX座標 #-------------------------------------------------------------------------- def xh rah = (self.ah % 360) * Math::PI / 180 camxd = self.x - XRXSV_BattleCam3D::CX camx = (Math.cos(rah) * camxd).to_i + XRXSV_BattleCam3D::CX return camx end end #============================================================================== # スプライト - カメラ位置/ズーム対応 #============================================================================== class Spriteset_Battle if XRXSV_BattleCam3D::BattleBackMoving alias xrxsv9cam1_update_battleback update_battleback def update_battleback xrxsv9cam1_update_battleback zoom = 185.00 / $game_temp.xcam.z @battleback_sprite.zoom_x = zoom @battleback_sprite.zoom_y = zoom @battleback_sprite.ox = 320 - (Graphics.width / 2 - $game_temp.xcam.xh) @battleback_sprite.oy = 240 - (Graphics.height / 2 - $game_temp.xcam.y ) end end alias xrxsv9cam1_create_battlefloor create_battlefloor def create_battlefloor xrxsv9cam1_create_battlefloor @battlefloor_sprite.ox = @battlefloor_sprite.bitmap.width / 2 @battlefloor_sprite.oy = XRXSV_BattleCam3D::BattleFloorCY @battlefloor_sprite.x = XRXSV_BattleCam3D::CX @battlefloor_sprite.y = XRXSV_BattleCam3D::CY end alias xrxsv9cam1_update_battlefloor update_battlefloor def update_battlefloor xrxsv9cam1_update_battlefloor rav = ($game_temp.xcam.av % 360) * Math::PI / 180 v_compress = (Math.sin(rav) * 16) / XRXSV_BattleCam3D::BFVirticalAngleRate zoom = 185.00 / $game_temp.xcam.z @battlefloor_sprite.zoom_x = zoom @battlefloor_sprite.zoom_y = zoom * v_compress @battlefloor_sprite.x = XRXSV_BattleCam3D::CX - ($game_temp.xcam.xh - Graphics.width / 2) @battlefloor_sprite.y = XRXSV_BattleCam3D::CY - ($game_temp.xcam.y - Graphics.height / 2) end end module XRXSV9CAM1_SpriteUpdateAnimation def animation_set_sprites(frame) if in_floor? and @animation.position <= 2 @animation_ox = x - ox + width / 2 @animation_oy = y - oy if @animation.position == 1 @animation_oy += height / 2 elsif @animation.position == 2 @animation_oy += height end super n = (self.battler.is_a?(Game_Actor) ? XRXSV_BattleCam3D::ActorSize : XRXSV_BattleCam3D::EnemySize) zoom = n * 185.00 / ($game_temp.xcam.z - (self.z - 385)) for sprite in @animation_sprites next unless sprite sprite.zoom_x = sprite.zoom_x * zoom sprite.zoom_y = sprite.zoom_y * zoom sprite.mirror = $game_temp.xcam.reverse? end else super end end def update_battler_xcam # 現在のカメラ角度をラジアンに変換 rah = ($game_temp.xcam.ah % 360) * Math::PI / 180 rav = ($game_temp.xcam.av % 360) * Math::PI / 180 # # 1.カメラアングル計算 # (1.カメラ位置補正 # 2.エアカメラ座標→グラウンドカメラ座標変換 # 3.二軸(水平・垂直)アングル補正 # 4.グラウンドカメラ座標→エアカメラ座標変換) # xd = self.x - XRXSV_BattleCam3D::CX # エア座標での中央とのX差 yd = self.y - XRXSV_BattleCam3D::CY # エア座標での中央とのY差 gxd = Math.sqrt(xd ** 2 + yd ** 2) # グラウンド座標での中央とのX差(三平方の定理) gra = Math.atan2(yd, xd) # グラウンド座標での既回転角度 # グラウンド座標での中央とのY差は常に0(地に足が付いている状態) raa = (gra + rah) # 角度合算 newx = (Math.cos(raa) * gxd).to_i # 角度適用した中央とのX差 yd2 = (Math.sin(raa) * gxd).to_i # 3D水平軸の適用 zd = (Math.cos(rav) * yd2).to_i # 3Dカメラ距離の計算 newy = (Math.sin(rav) * yd2).to_i # 3D垂直軸・カメラアングル適用後のエア座標 # # 2.カメラ距離計算(2D処理)とカメラ相対距離による各自ズーム率 # cam_distance = $game_temp.xcam.z - (zd / XRXSV_BattleCam3D::BattlerZDivision).to_i if cam_distance >= 1 self.x = XRXSV_BattleCam3D::CX + (newx - ($game_temp.xcam.xh - Graphics.width / 2)) * 185 / cam_distance self.y = XRXSV_BattleCam3D::CY + (newy - ($game_temp.xcam.y - Graphics.height / 2)) * 185 / cam_distance self.z = 385 - cam_distance n = (self.battler.is_a?(Game_Actor) ? XRXSV_BattleCam3D::ActorSize : XRXSV_BattleCam3D::EnemySize) zoom = n * 185.00 / cam_distance self.zoom_x = zoom self.zoom_y = zoom else self.zoom_x = 0 # 擬似的に非表示(カメラ位置より手前にある場合) end self.mirror = $game_temp.xcam.reverse? end def in_floor? return (@battler and @battler.in_floor?) end end class Sprite_Battler < Sprite_Base include XRXSV9CAM1_SpriteUpdateAnimation alias xrxsv9cam1_update_battler_bitmap update_battler_bitmap def update_battler_bitmap xrxsv9cam1_update_battler_bitmap update_battler_xcam if in_floor? end end #============================================================================== # バトラーグラフィックサイズ取得機能 #============================================================================== class Game_Battler def battler_size bitmap = Cache.battler(self.battler_name, self.battler_hue) return (bitmap ? ([bitmap.width / 2, bitmap.height].max * XRXSV_BattleCam3D::EnemySize).to_i : 0) end end class Game_Actor < Game_Battler def battler_size return (96 * XRXSV_BattleCam3D::ActorSize).to_i end end