=begin ▼ 乗り物擬似3D化 for VX メインスクリプト ver. 2.1.1 RPGツクールVX用スクリプト 制作 : 木星ペンギン URL : http://woodpenguin.blog.fc2.com/ ------------------------------------------------------------------------------ メモ 28 : モジュール 59 : ゲームオブジェクト 877 : スプライト 1201 : ウィンドウ 1222 : シーン =end #////////////////////////////////////////////////////////////////////////////// # # 設定項目なし # #////////////////////////////////////////////////////////////////////////////// #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # # ▼ モジュール # #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ module WdTk module Veh3D #-------------------------------------------------------------------------- # ● フレームカウントのリセット #-------------------------------------------------------------------------- def self.reset @@frame_count = 0 @@need_update = true end #-------------------------------------------------------------------------- # ● 更新 #-------------------------------------------------------------------------- def self.update @@frame_count += FrameRate @@need_update = @@frame_count >= 60 @@frame_count %= 60 end #-------------------------------------------------------------------------- # ● 更新が必要かどうか #-------------------------------------------------------------------------- def self.need_update? @@need_update end end end #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # # ▼ ゲームオブジェクト # #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ #============================================================================== # ■ Game_Map #============================================================================== class Game_Map #-------------------------------------------------------------------------- # ● 表示位置の設定 (ループ判定なし) #-------------------------------------------------------------------------- def set_pos(x, y) @display_x = x @display_y = y @parallax_x = x @parallax_y = y end #-------------------------------------------------------------------------- # ● 指定座標にあるオートタイルの種類を取得 #-------------------------------------------------------------------------- def autotile_type(x, y, z) @map.data[x, y, z] >= 2048 ? (@map.data[x, y, z] - 2048) / 48 : -1 end #-------------------------------------------------------------------------- # ● 乗り物の通行可能判定 #-------------------------------------------------------------------------- def vehicle_passable?(x, y, types, through) return true unless types for event in events_xy(x, y) # 座標が一致するイベントを調べる tile_id = event.tile_id if tile_id >= 2048 return types.include?((tile_id - 2048) / 48) elsif tile_id > 0 flag = @passages[tile_id] next if flag & 0x10 != 0 return (through && flag & 0x01 == 0) end end for i in [2, 1, 0] # レイヤーの上から順に調べる tile_id = @map.data[x, y, i] if tile_id >= 2048 return types.include?((tile_id - 2048) / 48) else flag = @passages[tile_id] next if flag & 0x10 != 0 return (through && flag & 0x01 == 0) end end return false # 通行不可 end #-------------------------------------------------------------------------- # ● 着陸可能判定 #-------------------------------------------------------------------------- def land_ok?(x, y, denial) return false if denial && denial.include?(autotile_type(x, y, 1)) return false if denial && denial.include?(autotile_type(x, y, 0)) return passable?(x, y, 0x01) end #-------------------------------------------------------------------------- # ● ループ補正後の X 実座標計算 # real_x : X 実座標 #-------------------------------------------------------------------------- def round_real_x(real_x) if loop_horizontal? return (real_x + width * 256) % (width * 256) else return real_x end end #-------------------------------------------------------------------------- # ● ループ補正後の Y 実座標計算 # real_y : Y 実座標 #-------------------------------------------------------------------------- def round_real_y(real_y) if loop_vertical? return (real_y + height * 256) % (height * 256) else return real_y end end end #============================================================================== # ■ Game_Character #============================================================================== class Game_Character #-------------------------------------------------------------------------- # ☆ キャラクター衝突判定 # x : X 座標 # y : Y 座標 # プレイヤーと乗り物を含め、通常キャラの衝突を検出する。 #-------------------------------------------------------------------------- def collide_with_characters?(x, y) for event in $game_map.events_xy(x, y) # イベントの座標と一致 unless event.through # すり抜け OFF? return true if self.is_a?(Game_Event) # 自分がイベント return true if event.priority_type == 1 # 相手が通常キャラ end end if @priority_type == 1 # 自分が通常キャラ return true if $game_player.pos_nt?(x, y) # プレイヤーの座標と一致 for vehicle in $game_map.vehicles next unless vehicle.pos_nt?(x, y) return true if self.is_a?(Game_Vehicle) # 自分が乗り物 return true unless vehicle.get_here? end end return false end end #============================================================================== # ■ Game_Player #============================================================================== class Game_Player #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_accessor :in_vehicle #-------------------------------------------------------------------------- # ◯ 場所移動の実行 #-------------------------------------------------------------------------- alias _wdtk_veh3d_perform_transfer perform_transfer def perform_transfer vehicle.set_direction(@new_direction) if @transferring && in_vehicle? _wdtk_veh3d_perform_transfer end #-------------------------------------------------------------------------- # ● 現在乗っている乗り物を取得 #-------------------------------------------------------------------------- def vehicle $game_map.vehicles[@vehicle_type] end #-------------------------------------------------------------------------- # ◯ フレーム更新 #-------------------------------------------------------------------------- alias _wdtk_veh3d_update update def update if @in_vehicle return if !movable? or $game_map.interpreter.running? vehicle.process_control last_x = @x last_y = @y @x = vehicle.x @y = vehicle.y @real_x = @x * 256 @real_y = @y * 256 update_vehicle_moving(last_x != @x || last_y != @y) else _wdtk_veh3d_update end end #-------------------------------------------------------------------------- # ● 乗り物で移動した場合の処理 # tile_moving : タイルを移動したかどうか #-------------------------------------------------------------------------- def update_vehicle_moving(tile_moving) if tile_moving increase_steps vehicle.update_bush_depth end return if $game_map.interpreter.running? if tile_moving return if check_touch_event end return if vehicle.process_handling update_encounter if tile_moving end #-------------------------------------------------------------------------- # ☆ 乗り物の処理 #-------------------------------------------------------------------------- def update_vehicle return unless in_vehicle? if @vehicle_getting_on # 乗る途中? if not moving? @vehicle_getting_on = false # 乗る動作終了 @transparent = true # 透明化 vehicle.get_on end elsif @vehicle_getting_off # 降りる途中? if not moving? and vehicle.altitude == 0 @vehicle_getting_off = false # 降りる動作終了 @vehicle_type = -1 # 乗り物タイプ消去 @transparent = false # 透明を解除 end else # 乗り物に乗っている vehicle.sync_with_player # プレイヤーと同時に動かす end end #-------------------------------------------------------------------------- # ◯ エンカウントの更新 #-------------------------------------------------------------------------- alias _wdtk_veh3d_update_encounter update_encounter def update_encounter if in_vehicle? return if debug_through? @encounter_count -= vehicle.encount_rate / 100.0 else _wdtk_veh3d_update_encounter end end #-------------------------------------------------------------------------- # ☆ 乗り物に乗る # 現在乗り物に乗っていないことが前提。 #-------------------------------------------------------------------------- def get_on_vehicle front_x = $game_map.x_with_direction(@x, @direction) front_y = $game_map.y_with_direction(@y, @direction) for i in 0...$game_map.vehicles.size veh = $game_map.vehicles[i] if veh.get_here? @vehicle_type = i if veh.pos?(@x, @y) else @vehicle_type = i if veh.pos?(front_x, front_y) end end if in_vehicle? @vehicle_getting_on = true force_move_forward unless vehicle.get_here? @walking_bgm = RPG::BGM::last # 歩行時の BGM 記憶 return true end return false end #-------------------------------------------------------------------------- # ☆ 乗り物から降りる #-------------------------------------------------------------------------- def get_off_vehicle return unless vehicle.land_ok?(@x, @y, vehicle.angle_dir) vehicle.get_off set_direction(vehicle.sync_dir? ? vehicle.angle_dir : 2) @vehicle_getting_off = true # 降りる動作の開始 @move_speed = 4 # 移動速度を戻す @through = false # すり抜け OFF @walking_bgm.play # 歩行時の BGM 復帰 make_encounter_count # エンカウント初期化 end #-------------------------------------------------------------------------- # ● 乗り物開始処理 #-------------------------------------------------------------------------- def on_vehicle_start @in_vehicle = true vehicle.on_vehicle_start end #-------------------------------------------------------------------------- # ● 乗り物終了処理 #-------------------------------------------------------------------------- def on_vehicle_end @in_vehicle = false center(@x, @y) vehicle.on_vehicle_end unless vehicle.get_here? force_move_forward @transparent = false end end end #============================================================================== # ■ Game_Vehicle #============================================================================== class Game_Vehicle #-------------------------------------------------------------------------- # ● モジュール #-------------------------------------------------------------------------- include Math #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :angle attr_reader :drive_direction attr_accessor :altitude attr_accessor :control #-------------------------------------------------------------------------- # ◯ オブジェクト初期化 #-------------------------------------------------------------------------- alias _wdtk_veh3d_initialize initialize def initialize(type) _wdtk_veh3d_initialize(type) @drive_speed = 0 @drive_direction = 5 @angle = 0 @angle_speed = 0 @control = false end #-------------------------------------------------------------------------- # ● 乗り物データの取得 #-------------------------------------------------------------------------- def param(sym) WdTk::Veh3D.data[@type][sym] end #-------------------------------------------------------------------------- # ● 移動中判定 #-------------------------------------------------------------------------- def moving? @control ? (@drive_speed != 0 or @angle_speed != 0) : super end #-------------------------------------------------------------------------- # ● デバッグすり抜け状態判定 #-------------------------------------------------------------------------- def debug_through? return false unless $TEST return Input.press?(Input::CTRL) end #-------------------------------------------------------------------------- # ● イベントとの衝突判定 #-------------------------------------------------------------------------- def collide_with_events?(x, y) $game_map.events_xy(x, y).any? do |event| not event.through and event.priority_type == 1 end end #-------------------------------------------------------------------------- # ● 乗り物との衝突判定 #-------------------------------------------------------------------------- def collide_with_vehicles?(x, y) $game_map.vehicles.any? {|v| v != self and v.pos_nt?(x, y) } end #-------------------------------------------------------------------------- # ● 指定方向に向き変更 # d : 方向(2,4,6,8) #-------------------------------------------------------------------------- def set_direction(d) super if @driving and d != 0 case @direction when 2; @angle = 180 when 4; @angle = 90 when 6; @angle = 270 when 8; @angle = 0 end stop end end #-------------------------------------------------------------------------- # ● グラフィックの取得 #-------------------------------------------------------------------------- def vehicle_name case @drive_direction when 5; param(:vehicle_name1) or @character_name when 2,4,6,8; param(:vehicle_name2) or param(:vehicle_name1) or @character_name when 1,3,7,9; param(:vehicle_name3) or @character_name end end def vehicle_index case @drive_direction when 5; param(:vehicle_index1) or @character_index when 2,4,6,8; param(:vehicle_index2) or param(:vehicle_index1) or @character_index when 1,3,7,9; param(:vehicle_index3) or @character_index end end #-------------------------------------------------------------------------- # ☆ リフレッシュ #-------------------------------------------------------------------------- def refresh if @driving @map_id = $game_map.map_id sync_with_player stop elsif @map_id == $game_map.map_id moveto(@x, @y) end if @type == 2 @priority_type = @driving ? 2 : 0 else @priority_type = 1 end @move_speed = param(:move_speed) if @driving @drive_direction = 5 @walk_anime = param(:walk_anime) != false @step_anime = param(:step_anime) != false else @walk_anime = @step_anime = false end end #-------------------------------------------------------------------------- # ◯ 乗り物に乗る #-------------------------------------------------------------------------- alias _wdtk_veh3d_get_on get_on def get_on _wdtk_veh3d_get_on @walk_anime = param(:walk_anime) != false @step_anime = param(:step_anime) != false @drive_speed = 0 @drive_direction = 5 @angle = 0 set_direction($game_player.direction) if sync_dir? @angle_speed = 0 $game_temp.next_scene = "vehicle" end #-------------------------------------------------------------------------- # ◯ 乗り物から降りる #-------------------------------------------------------------------------- alias _wdtk_veh3d_get_off get_off def get_off _wdtk_veh3d_get_off $game_temp.next_scene = "map" end #-------------------------------------------------------------------------- # ● 乗り物開始処理 #-------------------------------------------------------------------------- def on_vehicle_start unless @control @control = true @altitude = 8 if @type != 2 $game_switches[param(:switch_id)] = true if param(:switch_id) end end #-------------------------------------------------------------------------- # ● 乗り物終了処理 #-------------------------------------------------------------------------- def on_vehicle_end unless @driving @control = false @altitude = @type == 2 ? 32 : 0 moveto((@real_x + 128) / 256, (@real_y + 128) / 256) $game_switches[param(:switch_id)] = false if param(:switch_id) end end #-------------------------------------------------------------------------- # ● 停止 #-------------------------------------------------------------------------- def stop @drive_speed = 0 @angle_speed = 0 @stop_count = 0 end #-------------------------------------------------------------------------- # ● 移動可能判定 #-------------------------------------------------------------------------- def movable? @driving end #-------------------------------------------------------------------------- # ● 搭乗時向き変更するかどうか #-------------------------------------------------------------------------- def sync_dir? param(:sync_dir) end #-------------------------------------------------------------------------- # ● 同一による搭乗かどうか #-------------------------------------------------------------------------- def get_here? param(:get_here) end #-------------------------------------------------------------------------- # ● エンカウント率の取得 #-------------------------------------------------------------------------- def encount_rate param(:encount) or 0 end #-------------------------------------------------------------------------- # ● エンカウント無効? #-------------------------------------------------------------------------- def encounter_none? encount_rate == 0 end #-------------------------------------------------------------------------- # ● 角度から方向の取得 #-------------------------------------------------------------------------- def angle_dir case (@angle + 45).to_i / 90 when 0,4; 8 when 1; 4 when 2; 2 when 3; 6 end end #-------------------------------------------------------------------------- # ◯ フレーム更新 #-------------------------------------------------------------------------- alias _wdtk_veg3d_update update def update if @control if not @driving and @type == 2 if @altitude > 32 or Graphics.frame_count % (5 - @altitude / 8) == 0 @altitude -= 1 end end else _wdtk_veg3d_update end end #-------------------------------------------------------------------------- # ● ボタンが押されているかどうか #-------------------------------------------------------------------------- def key_press?(sym) sym != nil and Input.press?(Input.const_get(sym)) end #-------------------------------------------------------------------------- # ● ボタンが新たに押されたかどうか #-------------------------------------------------------------------------- def key_trigger?(sym) sym != nil and Input.trigger?(Input.const_get(sym)) end #-------------------------------------------------------------------------- # ● 乗り物操縦時の処理 #-------------------------------------------------------------------------- def process_control update_animation @drive_direction = 5 if key_press?(param(:inp_forward1)) or key_press?(param(:inp_forward2)) process_forward elsif key_press?(param(:inp_backward)) process_backward else process_reduce_drive end unless key_press?(param(:inp_horz)) turn = 0 turn += 1 if key_press?(param(:inp_turnleft1)) turn += 1 if key_press?(param(:inp_turnleft2)) turn -= 1 if key_press?(param(:inp_turnright1)) turn -= 1 if key_press?(param(:inp_turnright2)) process_turn(turn) if @type == 2 process_up if key_press?(param(:inp_up)) process_down if key_press?(param(:inp_down)) end else process_reduce_turn end update_angle if @drive_speed != 0 update_drive(@angle, 2 ** @move_speed * @drive_speed / 32) elsif key_press?(param(:inp_horz)) process_horz end if moving? if @walk_anime @anime_count += 1.5 elsif @step_anime @anime_count += 1 end else update_stop end end #-------------------------------------------------------------------------- # ● 操縦以外の処理 #-------------------------------------------------------------------------- def process_handling if @drive_speed <= 16 if key_trigger?(param(:inp_get_off)) or (param(:inp_get_off) == nil and @altitude <= 32 and key_press?(param(:inp_down))) return stop if $game_player.get_off_vehicle end if key_trigger?(param(:inp_event)) $game_player.set_direction(angle_dir) return stop if $game_player.check_action_event end end if key_trigger?(param(:inp_menu)) return process_menu end end #-------------------------------------------------------------------------- # ● 前進の処理 #-------------------------------------------------------------------------- def process_forward @drive_speed += 1 if @drive_speed < 32 @stop_count = 0 end #-------------------------------------------------------------------------- # ● 後退の処理 #-------------------------------------------------------------------------- def process_backward @drive_speed -= 1 if @drive_speed > -16 @stop_count = 0 end #-------------------------------------------------------------------------- # ● 速度低下の処理 #-------------------------------------------------------------------------- def process_reduce_drive @drive_speed += (0 <=> @drive_speed) end #-------------------------------------------------------------------------- # ● 旋回の処理 #-------------------------------------------------------------------------- def process_turn(speed) if @angle_speed < 24 * speed @angle_speed += 1 if @angle_speed < 32 elsif @angle_speed > 24 * speed @angle_speed -= 1 if @angle_speed > -32 end if speed != 0 @drive_direction += (0 <=> speed) if (param(:dir_type) || 0) >= 1 @stop_count = 0 end end #-------------------------------------------------------------------------- # ● 旋回低下の処理 #-------------------------------------------------------------------------- def process_reduce_turn @angle_speed += (0 <=> @angle_speed) end #-------------------------------------------------------------------------- # ● 上昇の処理 #-------------------------------------------------------------------------- def process_up @altitude += 1 if @altitude < 100 @drive_direction += 3 if (param(:dir_type) || 0) >= 2 end #-------------------------------------------------------------------------- # ● 下降の処理 #-------------------------------------------------------------------------- def process_down @altitude -= 1 if @altitude > 20 @drive_direction -= 3 if (param(:dir_type) || 0) >= 2 end #-------------------------------------------------------------------------- # ● メニュー呼び出しの処理 #-------------------------------------------------------------------------- def process_menu $game_temp.menu_beep = true $game_temp.next_scene = "menu" end #-------------------------------------------------------------------------- # ● 水平移動の処理 #-------------------------------------------------------------------------- def process_horz case Input.dir8 when 1; angle = (@angle + 135) % 360 when 2; angle = (@angle + 180) % 360 when 3; angle = (@angle + 225) % 360 when 4; angle = (@angle + 90) % 360 when 6; angle = (@angle + 270) % 360 when 7; angle = (@angle + 45) % 360 when 8; angle = @angle when 9; angle = (@angle + 315) % 360 else return end update_drive(angle, 2 ** @move_speed / 3) end #-------------------------------------------------------------------------- # ● 向きの更新 #-------------------------------------------------------------------------- def update_angle return unless WdTk::Veh3D.need_update? speed = param(:turning) * @angle_speed / 128.0 * 60 / WdTk::Veh3D::FrameRate @angle = (@angle + speed) % 360 end #-------------------------------------------------------------------------- # ● 移動時の更新 #-------------------------------------------------------------------------- def update_drive(angle, distance) return unless WdTk::Veh3D.need_update? distance = distance * 60 / WdTk::Veh3D::FrameRate x1 = $game_map.round_x((@real_x + 128) / 256) y1 = $game_map.round_y((@real_y + 128) / 256) tx = $game_map.round_real_x(@real_x - (sin(angle * PI / 180) * distance).to_i) ty = $game_map.round_real_y(@real_y - (cos(angle * PI / 180) * distance).to_i) x2 = round_x_with_pos(tx) y2 = round_y_with_pos(ty) if x1 == x2 or vehicle_passable?(x2, y1) @real_x = tx @x = $game_map.round_x((@real_x + 128) / 256) if (y1 == y2 or vehicle_passable?(x1, y2)) and (x1 == x2 or vehicle_passable?(x2, y2)) @real_y = ty @y = $game_map.round_y((@real_y + 128) / 256) end elsif y1 == y2 or vehicle_passable?(x1, y2) @real_y = ty @y = $game_map.round_y((@real_y + 128) / 256) end end #-------------------------------------------------------------------------- # ● 接岸/着陸可能判定 # d : 方向(2,4,6,8) #-------------------------------------------------------------------------- def land_ok?(x, y, d) if get_here? return false unless $game_map.land_ok?(x, y, param(:land_denial)) return false unless $game_map.events_xy(x, y).empty? for vehicle in $game_map.vehicles return false if vehicle != self and vehicle.pos?(x, y) end else x2 = $game_map.x_with_direction(x, d) y2 = $game_map.y_with_direction(y, d) return false unless $game_map.valid?(x2, y2) return false unless $game_map.passable?(x2, y2) return false if collide_with_characters?(x2, y2) end return true end #-------------------------------------------------------------------------- # ● 通行可能判定 #-------------------------------------------------------------------------- def vehicle_passable?(x2, y2) return false unless $game_map.valid?(x2, y2) return true if @through or debug_through? return false unless map_passable?(x2, y2) if @type != 2 and collide_with_events?(x2, y2) stop if $game_player.check_event_trigger_touch(x2, y2) return false end return false if @type != 2 and collide_with_vehicles?(x2, y2) return true end #-------------------------------------------------------------------------- # ● 特定の方向にずらした座標の計算(ループ補正あり) #-------------------------------------------------------------------------- def round_x_with_pos(real_x) if real_x < @x * 256 return $game_map.round_x(real_x / 256) if real_x % 256 < 128 elsif real_x > @x * 256 return $game_map.round_x((real_x + 255) / 256) if real_x % 256 > 128 end return $game_map.round_x((real_x + 128) / 256) end def round_y_with_pos(real_y) if real_y < @y * 256 return $game_map.round_y(real_y / 256) if real_y % 256 < 128 elsif real_y > @y * 256 return $game_map.round_y((real_y + 255) / 256) if real_y % 256 > 128 end return $game_map.round_y((real_y + 128) / 256) end #-------------------------------------------------------------------------- # ● 角度からラジアンの取得 #-------------------------------------------------------------------------- def angle_radian if @angle < 90 sx = [@angle, 45].min elsif @angle < 270 sx = [[180 - @angle, 45].min, -45].max else sx = [@angle - 360, -45].max end sy = [[(@angle - 180).abs - 90, 45].min, -45].max atan2(sx, sy) end #-------------------------------------------------------------------------- # ● 乗り物のマップ通行可能判定 #-------------------------------------------------------------------------- def map_passable?(x, y) $game_map.vehicle_passable?(x, y, param(:passage_tiles), param(:passage_flag)) end #-------------------------------------------------------------------------- # ● 画面座標の計算 #-------------------------------------------------------------------------- def display_x x = @real_x - (view_distance * sin(angle_radian)).to_i + 128 return x % ($game_map.width * 256) - center_x end def display_y y = @real_y - (view_distance * cos(angle_radian)).to_i + 128 return y % ($game_map.height * 256) - center_y end #-------------------------------------------------------------------------- # ● 視界距離の取得 #-------------------------------------------------------------------------- def view_distance 1472 end #-------------------------------------------------------------------------- # ● 画面中央の座標 #-------------------------------------------------------------------------- def center_x Graphics.width * 256 / 64 end def center_y Graphics.height * 256 / 64 end #-------------------------------------------------------------------------- # ● スナップ用原点座標の計算 #-------------------------------------------------------------------------- def snap_ox (@real_x - $game_map.display_x + 128) % ($game_map.width * 256) / 8 end def snap_oy (@real_y - $game_map.display_y + 128) % ($game_map.height * 256) / 8 end #-------------------------------------------------------------------------- # ● 原点 Y 座標の計算 #-------------------------------------------------------------------------- def adjust_oy(sy) height = 350 - @altitude / 10.0 rate = sin((0.75 - 0.5 * sy / 256) * PI) - sin(0.75 * PI) 64 + (height * sy / 256 + (190 - @altitude) * rate).to_i end #-------------------------------------------------------------------------- # ● 表示座標を差し引いた Y 座標の計算 #-------------------------------------------------------------------------- def adjust_y(sy) 160 + ((sy / 16.0) ** 2).to_i end #-------------------------------------------------------------------------- # ● 拡大率の取得 #-------------------------------------------------------------------------- def adjust_zoom(sy) 1.3 + 420.0 / (@altitude + 60) * sy / 308 end #-------------------------------------------------------------------------- # ● 乗り物画面表示座標の取得 #-------------------------------------------------------------------------- def vscreen_x Graphics.width / 2 end def vscreen_y Graphics.height - 40 - (@type == 2 ? @altitude * 2 : 0) end def vscreen_z 100 end #-------------------------------------------------------------------------- # ● 乗り物画面表示拡大率の取得 #-------------------------------------------------------------------------- def vscreen_zoom param(:vehicle_zoom) or 2.0 end end #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # # ▼ スプライト # #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ #============================================================================== # ■ Sprite_Vehicle #============================================================================== class Sprite_Vehicle < Sprite_Base #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_accessor :character #-------------------------------------------------------------------------- # ● オブジェクト初期化 # viewport : ビューポート # character : キャラクター (Game_Character) #-------------------------------------------------------------------------- def initialize(viewport, character = nil) super(viewport) @character = character update end #-------------------------------------------------------------------------- # ● フレーム更新 #-------------------------------------------------------------------------- def update super update_bitmap self.visible = (not @character.transparent) update_src_rect self.x = @character.vscreen_x self.y = @character.vscreen_y self.z = @character.vscreen_z self.zoom_x = self.zoom_y = @character.vscreen_zoom self.opacity = @character.opacity self.blend_type = @character.blend_type self.bush_depth = @character.bush_depth if $game_player.animation_id != 0 animation = $data_animations[$game_player.animation_id] start_animation(animation) $game_player.animation_id = 0 end end #-------------------------------------------------------------------------- # ● 転送元ビットマップの更新 #-------------------------------------------------------------------------- def update_bitmap if @character_name != @character.vehicle_name or @character_index != @character.vehicle_index @character_name = @character.vehicle_name @character_index = @character.vehicle_index self.bitmap = Cache.character(@character_name) sign = @character_name[/^[\!\$]./] if sign != nil and sign.include?('$') @cw = bitmap.width / 3 @ch = bitmap.height / 4 else @cw = bitmap.width / 12 @ch = bitmap.height / 8 end self.ox = @cw / 2 self.oy = @ch end end #-------------------------------------------------------------------------- # ● 転送元矩形の更新 #-------------------------------------------------------------------------- def update_src_rect index = @character_index pattern = @character.pattern < 3 ? @character.pattern : 1 direction = @character.drive_direction direction = 8 if direction == 5 direction += 5 <=> direction if direction % 2 == 1 sx = (index % 4 * 3 + pattern) * @cw sy = (index / 4 * 4 + (direction - 2) / 2) * @ch self.src_rect.set(sx, sy, @cw, @ch) end end #============================================================================== # ■ Spriteset_Vehicle #============================================================================== class Spriteset_Vehicle < Spriteset_Map #-------------------------------------------------------------------------- # ● 定数 #-------------------------------------------------------------------------- RATE = 40 CUT = 2 #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :viewport4 #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(viewport) @veh_viewport0 = Viewport.new(0, 0, Graphics.width, Graphics.height) @veh_viewport4 = viewport @vehicle = $game_player.vehicle create_snap create_scenery create_ground create_vehicle super() end #-------------------------------------------------------------------------- # ● ビューポートの作成 #-------------------------------------------------------------------------- def create_viewports super @viewport1.z = 9990 end #-------------------------------------------------------------------------- # ● 背景の作成 #-------------------------------------------------------------------------- def create_scenery @scenery = Plane.new(@veh_viewport0) @scenery.z = -100 end #-------------------------------------------------------------------------- # ● 地面の作成 #-------------------------------------------------------------------------- def create_ground n = 256 + (Graphics.height - 416) / 2 y1 = @vehicle.adjust_y(0) @ground_sprites = Array.new(n) do |i| y2 = @vehicle.adjust_y(i + 1) next nil if (y2 - y1) <= [i / RATE, CUT].min y1 = y2 sprite = Sprite.new(@veh_viewport0) sprite.x = Graphics.width / 2 #sprite.ox = Graphics.width / 2 sprite.opacity = i * 3 sprite end end #-------------------------------------------------------------------------- # ● 乗り物スプライトの作成 #-------------------------------------------------------------------------- def create_vehicle @sprite_vehicle = Sprite_Vehicle.new(@veh_viewport0, @vehicle) end #-------------------------------------------------------------------------- # ● キャラクタースプライトの作成 #-------------------------------------------------------------------------- def create_characters super @character_sprites.reject! do |sprite| if sprite.character == $game_player or sprite.character == @vehicle sprite.dispose end sprite.disposed? end end #-------------------------------------------------------------------------- # ● 飛行船の影スプライトの作成 #-------------------------------------------------------------------------- def create_shadow super @shadow_sprite.viewport = @veh_viewport0 end #-------------------------------------------------------------------------- # ● 撮影用スプライトの作成 #-------------------------------------------------------------------------- def create_snap @snap_sprite = Sprite.new @snap_sprite.x = Graphics.width / 2 @snap_sprite.y = Graphics.height / 2 + @vehicle.view_distance / 8 @snap_sprite.z = 9999 end #-------------------------------------------------------------------------- # ● 解放 #-------------------------------------------------------------------------- def dispose super dispose_snap dispose_scenery dispose_ground dispose_vehicle end #-------------------------------------------------------------------------- # ● ビューポートの解放 #-------------------------------------------------------------------------- def dispose_viewports @veh_viewport0.dispose super end #-------------------------------------------------------------------------- # ● 撮影用スプライトの解放 #-------------------------------------------------------------------------- def dispose_snap @snap_sprite.dispose end #-------------------------------------------------------------------------- # ● 背景の解放 #-------------------------------------------------------------------------- def dispose_scenery @scenery.bitmap.dispose if @scenery.bitmap && !@scenery.bitmap.disposed? @scenery.dispose end #-------------------------------------------------------------------------- # ● 地面の解放 #-------------------------------------------------------------------------- def dispose_ground @ground_sprites.each {|sprite| sprite.dispose if sprite } end #-------------------------------------------------------------------------- # ● 乗り物スプライトの解放 #-------------------------------------------------------------------------- def dispose_vehicle @sprite_vehicle.dispose end #-------------------------------------------------------------------------- # ● フレーム更新 #-------------------------------------------------------------------------- def update super return unless WdTk::Veh3D.need_update? last_brightness = Graphics.brightness Graphics.brightness = 255 @viewport1.visible = true @veh_viewport0.visible = @viewport2.visible = @viewport3.visible = @veh_viewport4.visible = false update_snap @viewport1.visible = false @snap_sprite.visible = true update_scenery update_ground update_vehicle @snap_sprite.visible = false @veh_viewport0.visible = @viewport2.visible = @viewport3.visible = @veh_viewport4.visible = true Graphics.brightness = last_brightness end #-------------------------------------------------------------------------- # ● タイルマップの更新 #-------------------------------------------------------------------------- def update_tilemap $game_map.set_pos(@vehicle.display_x, @vehicle.display_y) super end #-------------------------------------------------------------------------- # ● 天候の更新 #-------------------------------------------------------------------------- def update_weather super @weather.ox = -@vehicle.angle @weather.oy = 0 end #-------------------------------------------------------------------------- # ● スナップの更新 #-------------------------------------------------------------------------- def update_snap gh = Graphics.height gx = (Graphics.width - gh) / 2 @snap_sprite.ox = @vehicle.snap_ox - gx @snap_sprite.oy = @vehicle.snap_oy @snap_sprite.bitmap.dispose if @snap_sprite.bitmap @snap_sprite.bitmap = Graphics.snap_to_bitmap @snap_sprite.src_rect.set(gx, 0, gh, gh) @snap_sprite.angle = -@vehicle.angle end #-------------------------------------------------------------------------- # ● 背景の更新 #-------------------------------------------------------------------------- def update_scenery if WdTk::Veh3D::Scenery @scenery.bitmap = Cache.parallax(WdTk::Veh3D::Scenery) else @scenery.bitmap = @parallax.bitmap end angle = -@vehicle.angle * WdTk::Veh3D::Repeat % 360 @scenery.ox = @scenery.bitmap.width * angle / 360 end #-------------------------------------------------------------------------- # ● 地面の更新 #-------------------------------------------------------------------------- def update_ground @bitmap.dispose if @bitmap @bitmap = Graphics.snap_to_bitmap next_y = @vehicle.adjust_y(0) last_oy = @vehicle.adjust_oy(0) @ground_sprites.each_with_index do |sprite, i| next unless sprite sprite.bitmap = @bitmap next_oy = @vehicle.adjust_oy(i + 1) width = Math.sqrt(512 ** 2 - (512 - i - 1) ** 2).to_i * 2 width = @bitmap.width if width > @bitmap.width x = (@bitmap.width - width) / 2 height = (next_oy > last_oy ? next_oy - last_oy : 1) sprite.src_rect.set(x, last_oy, width, height) sprite.ox = width / 2 last_oy = next_oy sprite.y = next_y sprite.zoom_x = @vehicle.adjust_zoom(sprite.y - 160) next_y = @vehicle.adjust_y(i + 1) sprite.zoom_y = (next_y - sprite.y).to_f / height end end #-------------------------------------------------------------------------- # ● 乗り物の更新 #-------------------------------------------------------------------------- def update_vehicle @sprite_vehicle.update end #-------------------------------------------------------------------------- # ● 飛行船の影スプライトの更新 #-------------------------------------------------------------------------- def update_shadow if @vehicle.type == 2 @shadow_sprite.x = Graphics.width / 2 @shadow_sprite.y = Graphics.height - 42 + @vehicle.altitude / 4 @shadow_sprite.z = @vehicle.screen_z - 1 @shadow_sprite.opacity = 255 * (90 - @vehicle.altitude / 2) / 90 @shadow_sprite.zoom_x = (200 - @vehicle.altitude) / 90.0 @shadow_sprite.zoom_y = @shadow_sprite.zoom_x else super end end end #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # # ▼ ウィンドウ # #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ #============================================================================== # ■ Window_Message #============================================================================== class Window_Message #-------------------------------------------------------------------------- # ● ビューポートの設定 #-------------------------------------------------------------------------- def viewport=(viewport) super @back_sprite.viewport = viewport @gold_window.viewport = viewport @number_input_window.viewport = viewport end end #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # # ▼ シーン # #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ #============================================================================== # ■ Scene_Map #============================================================================== class Scene_Map #-------------------------------------------------------------------------- # ◯ 画面切り替えの実行 #-------------------------------------------------------------------------- alias _wdtk_veh3d_update_scene_change update_scene_change def update_scene_change return if $game_player.moving? # プレイヤーの移動中? case $game_temp.next_scene when "vehicle" call_vehicle else _wdtk_veh3d_update_scene_change end end #-------------------------------------------------------------------------- # ● 乗り物画面への切り替え #-------------------------------------------------------------------------- def call_vehicle $game_temp.next_scene = nil fadeout(30) $scene = Scene_Vehicle.new end end #============================================================================== # ■ Scene_Vehicle #============================================================================== class Scene_Vehicle < Scene_Map #-------------------------------------------------------------------------- # ● メイン処理 #-------------------------------------------------------------------------- def main start # 開始処理 perform_transition # トランジション実行 post_start # 開始後処理 Input.update # 入力情報を更新 loop do if WdTk::Veh3D.need_update? Graphics.frame_rate = WdTk::Veh3D::FrameRate Graphics.update # ゲーム画面を更新 Graphics.frame_rate = 60 else Graphics.frame_count += 1 end Input.update # 入力情報を更新 WdTk::Veh3D.update update # フレーム更新 break if $scene != self # 画面が切り替わったらループを中断 end Graphics.update pre_terminate # 終了前処理 Graphics.freeze # トランジション準備 terminate # 終了処理 end #-------------------------------------------------------------------------- # ● 開始処理 #-------------------------------------------------------------------------- def start WdTk::Veh3D.reset $game_player.on_vehicle_start super @window_viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) @window_viewport.z = 200 @spriteset.dispose @spriteset = Spriteset_Vehicle.new(@window_viewport) @message_window.viewport = @window_viewport end #-------------------------------------------------------------------------- # ● 終了処理 #-------------------------------------------------------------------------- def terminate $game_player.on_vehicle_end if $scene.is_a?(Scene_Map) super @window_viewport.dispose GC.start end #-------------------------------------------------------------------------- # ● 画面のフェードイン #-------------------------------------------------------------------------- def fadein(*) WdTk::Veh3D.reset super Graphics.frame_reset end #-------------------------------------------------------------------------- # ● 画面のフェードアウト #-------------------------------------------------------------------------- def fadeout(*) WdTk::Veh3D.reset super Graphics.frame_reset end #-------------------------------------------------------------------------- # ● 場所移動の処理 #-------------------------------------------------------------------------- def update_transfer_player return unless $game_player.transfer? fade = (Graphics.brightness > 0) fadeout(30) if fade @spriteset.dispose # スプライトセットを解放 $game_player.perform_transfer # 場所移動の実行 $game_map.autoplay # BGM と BGS の自動切り替え $game_map.update Graphics.wait(15) @spriteset = Spriteset_Vehicle.new(@window_viewport) fadein(30) if fade Input.update end #-------------------------------------------------------------------------- # ● キャンセルボタンによるメニュー呼び出し判定 #-------------------------------------------------------------------------- def update_call_menu end #-------------------------------------------------------------------------- # ● 画面切り替えの実行 #-------------------------------------------------------------------------- def update_scene_change return if $game_player.moving? # プレイヤーの移動中? case $game_temp.next_scene when "map" call_map else super end end #-------------------------------------------------------------------------- # ● マップ画面への切り替え #-------------------------------------------------------------------------- def call_map fadeout(30) Graphics.brightness = 0 $scene = Scene_Map.new end end #============================================================================== # ■ Scene_Base #============================================================================== class Scene_Base #-------------------------------------------------------------------------- # ○ メイン処理 #-------------------------------------------------------------------------- alias _wdtk_veh3d_main main def main _wdtk_veh3d_main if $scene.is_a?(Scene_Map) and $game_player.in_vehicle $scene = Scene_Vehicle.new end end end