443 lines
19 KiB
Ruby
443 lines
19 KiB
Ruby
#==============================================================================
|
||
# ■ Game_CharacterBase
|
||
#------------------------------------------------------------------------------
|
||
# キャラクターを扱う基本のクラスです。全てのキャラクターに共通する、座標やグ
|
||
# ラフィックなどの基本的な情報を保持します。
|
||
#==============================================================================
|
||
|
||
class Game_CharacterBase
|
||
#--------------------------------------------------------------------------
|
||
# ● 公開インスタンス変数
|
||
#--------------------------------------------------------------------------
|
||
attr_reader :id # ID
|
||
attr_reader :x # マップ X 座標(論理座標)
|
||
attr_reader :y # マップ Y 座標(論理座標)
|
||
attr_reader :real_x # マップ X 座標(実座標)
|
||
attr_reader :real_y # マップ Y 座標(実座標)
|
||
attr_reader :tile_id # タイル ID(0 なら無効)
|
||
attr_reader :character_name # 歩行グラフィック ファイル名
|
||
attr_reader :character_index # 歩行グラフィック インデックス
|
||
attr_reader :move_speed # 移動速度
|
||
attr_reader :move_frequency # 移動頻度
|
||
attr_reader :walk_anime # 歩行アニメ
|
||
attr_reader :step_anime # 足踏みアニメ
|
||
attr_reader :direction_fix # 向き固定
|
||
attr_reader :opacity # 不透明度
|
||
attr_reader :blend_type # 合成方法
|
||
attr_reader :direction # 向き
|
||
attr_reader :pattern # パターン
|
||
attr_reader :priority_type # プライオリティタイプ
|
||
attr_reader :through # すり抜け
|
||
attr_reader :bush_depth # 茂み深さ
|
||
attr_accessor :animation_id # アニメーション ID
|
||
attr_accessor :balloon_id # フキダシアイコン ID
|
||
attr_accessor :transparent # 透明状態
|
||
#--------------------------------------------------------------------------
|
||
# ● オブジェクト初期化
|
||
#--------------------------------------------------------------------------
|
||
def initialize
|
||
init_public_members
|
||
init_private_members
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 公開メンバ変数の初期化
|
||
#--------------------------------------------------------------------------
|
||
def init_public_members
|
||
@id = 0
|
||
@x = 0
|
||
@y = 0
|
||
@real_x = 0
|
||
@real_y = 0
|
||
@tile_id = 0
|
||
@character_name = ""
|
||
@character_index = 0
|
||
@move_speed = 4
|
||
@move_frequency = 6
|
||
@walk_anime = true
|
||
@step_anime = false
|
||
@direction_fix = false
|
||
@opacity = 255
|
||
@blend_type = 0
|
||
@direction = 2
|
||
@pattern = 1
|
||
@priority_type = 1
|
||
@through = false
|
||
@bush_depth = 0
|
||
@animation_id = 0
|
||
@balloon_id = 0
|
||
@transparent = false
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 非公開メンバ変数の初期化
|
||
#--------------------------------------------------------------------------
|
||
def init_private_members
|
||
@original_direction = 2 # 元の向き
|
||
@original_pattern = 1 # 元のパターン
|
||
@anime_count = 0 # アニメカウント
|
||
@stop_count = 0 # 停止カウント
|
||
@jump_count = 0 # ジャンプカウント
|
||
@jump_peak = 0 # ジャンプの頂点のカウント
|
||
@locked = false # ロックフラグ
|
||
@prelock_direction = 0 # ロック前の向き
|
||
@move_succeed = true # 移動成功フラグ
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 座標一致判定
|
||
#--------------------------------------------------------------------------
|
||
def pos?(x, y)
|
||
@x == x && @y == y
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 座標一致と「すり抜け OFF」判定(nt = No Through)
|
||
#--------------------------------------------------------------------------
|
||
def pos_nt?(x, y)
|
||
pos?(x, y) && !@through
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● プライオリティ[通常キャラと同じ]判定
|
||
#--------------------------------------------------------------------------
|
||
def normal_priority?
|
||
@priority_type == 1
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 移動中判定
|
||
#--------------------------------------------------------------------------
|
||
def moving?
|
||
@real_x != @x || @real_y != @y
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● ジャンプ中判定
|
||
#--------------------------------------------------------------------------
|
||
def jumping?
|
||
@jump_count > 0
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● ジャンプの高さを計算
|
||
#--------------------------------------------------------------------------
|
||
def jump_height
|
||
(@jump_peak * @jump_peak - (@jump_count - @jump_peak).abs ** 2) / 2
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 停止中判定
|
||
#--------------------------------------------------------------------------
|
||
def stopping?
|
||
!moving? && !jumping?
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 移動速度の取得(ダッシュを考慮)
|
||
#--------------------------------------------------------------------------
|
||
def real_move_speed
|
||
@move_speed + (dash? ? 1 : 0)
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 1 フレームあたりの移動距離を計算
|
||
#--------------------------------------------------------------------------
|
||
def distance_per_frame
|
||
2 ** real_move_speed / 256.0
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● ダッシュ状態判定
|
||
#--------------------------------------------------------------------------
|
||
def dash?
|
||
return false
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● デバッグすり抜け状態判定
|
||
#--------------------------------------------------------------------------
|
||
def debug_through?
|
||
return false
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 姿勢の矯正
|
||
#--------------------------------------------------------------------------
|
||
def straighten
|
||
@pattern = 1 if @walk_anime || @step_anime
|
||
@anime_count = 0
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 逆方向の取得
|
||
# d : 方向(2,4,6,8)
|
||
#--------------------------------------------------------------------------
|
||
def reverse_dir(d)
|
||
return 10 - d
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 通行可能判定
|
||
# d : 方向(2,4,6,8)
|
||
#--------------------------------------------------------------------------
|
||
def passable?(x, y, d)
|
||
x2 = $game_map.round_x_with_direction(x, d)
|
||
y2 = $game_map.round_y_with_direction(y, d)
|
||
return false unless $game_map.valid?(x2, y2)
|
||
return true if @through || debug_through?
|
||
return false unless map_passable?(x, y, d)
|
||
return false unless map_passable?(x2, y2, reverse_dir(d))
|
||
return false if collide_with_characters?(x2, y2)
|
||
return true
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 斜めの通行可能判定
|
||
# horz : 横方向(4 or 6)
|
||
# vert : 縦方向(2 or 8)
|
||
#--------------------------------------------------------------------------
|
||
def diagonal_passable?(x, y, horz, vert)
|
||
x2 = $game_map.round_x_with_direction(x, horz)
|
||
y2 = $game_map.round_y_with_direction(y, vert)
|
||
(passable?(x, y, vert) && passable?(x, y2, horz)) ||
|
||
(passable?(x, y, horz) && passable?(x2, y, vert))
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● マップ通行可能判定
|
||
# d : 方向(2,4,6,8)
|
||
#--------------------------------------------------------------------------
|
||
def map_passable?(x, y, d)
|
||
$game_map.passable?(x, y, d)
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● キャラクターとの衝突判定
|
||
#--------------------------------------------------------------------------
|
||
def collide_with_characters?(x, y)
|
||
collide_with_events?(x, y) || collide_with_vehicles?(x, y)
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● イベントとの衝突判定
|
||
#--------------------------------------------------------------------------
|
||
def collide_with_events?(x, y)
|
||
$game_map.events_xy_nt(x, y).any? do |event|
|
||
event.normal_priority? || self.is_a?(Game_Event)
|
||
end
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 乗り物との衝突判定
|
||
#--------------------------------------------------------------------------
|
||
def collide_with_vehicles?(x, y)
|
||
$game_map.boat.pos_nt?(x, y) || $game_map.ship.pos_nt?(x, y)
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 指定位置に移動
|
||
#--------------------------------------------------------------------------
|
||
def moveto(x, y)
|
||
@x = x % $game_map.width
|
||
@y = y % $game_map.height
|
||
@real_x = @x
|
||
@real_y = @y
|
||
@prelock_direction = 0
|
||
straighten
|
||
update_bush_depth
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 指定方向に向き変更
|
||
# d : 方向(2,4,6,8)
|
||
#--------------------------------------------------------------------------
|
||
def set_direction(d)
|
||
@direction = d if !@direction_fix && d != 0
|
||
@stop_count = 0
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● タイル判定
|
||
#--------------------------------------------------------------------------
|
||
def tile?
|
||
@tile_id > 0 && @priority_type == 0
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● オブジェクトキャラクター判定
|
||
#--------------------------------------------------------------------------
|
||
def object_character?
|
||
@tile_id > 0 || @character_name[0, 1] == '!'
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● タイルの位置から上にずらすピクセル数を取得
|
||
#--------------------------------------------------------------------------
|
||
def shift_y
|
||
object_character? ? 0 : 4
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 画面 X 座標の取得
|
||
#--------------------------------------------------------------------------
|
||
def screen_x
|
||
$game_map.adjust_x(@real_x) * 32 + 16
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 画面 Y 座標の取得
|
||
#--------------------------------------------------------------------------
|
||
def screen_y
|
||
$game_map.adjust_y(@real_y) * 32 + 32 - shift_y - jump_height
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 画面 Z 座標の取得
|
||
#--------------------------------------------------------------------------
|
||
def screen_z
|
||
@priority_type * 100
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● フレーム更新
|
||
#--------------------------------------------------------------------------
|
||
def update
|
||
update_animation
|
||
return update_jump if jumping?
|
||
return update_move if moving?
|
||
return update_stop
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● ジャンプ時の更新
|
||
#--------------------------------------------------------------------------
|
||
def update_jump
|
||
@jump_count -= 1
|
||
@real_x = (@real_x * @jump_count + @x) / (@jump_count + 1.0)
|
||
@real_y = (@real_y * @jump_count + @y) / (@jump_count + 1.0)
|
||
update_bush_depth
|
||
if @jump_count == 0
|
||
@real_x = @x = $game_map.round_x(@x)
|
||
@real_y = @y = $game_map.round_y(@y)
|
||
end
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 移動時の更新
|
||
#--------------------------------------------------------------------------
|
||
def update_move
|
||
@real_x = [@real_x - distance_per_frame, @x].max if @x < @real_x
|
||
@real_x = [@real_x + distance_per_frame, @x].min if @x > @real_x
|
||
@real_y = [@real_y - distance_per_frame, @y].max if @y < @real_y
|
||
@real_y = [@real_y + distance_per_frame, @y].min if @y > @real_y
|
||
update_bush_depth unless moving?
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 停止時の更新
|
||
#--------------------------------------------------------------------------
|
||
def update_stop
|
||
@stop_count += 1 unless @locked
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 歩行/足踏みアニメの更新
|
||
#--------------------------------------------------------------------------
|
||
def update_animation
|
||
update_anime_count
|
||
if @anime_count > 18 - real_move_speed * 2
|
||
update_anime_pattern
|
||
@anime_count = 0
|
||
end
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● アニメカウントの更新
|
||
#--------------------------------------------------------------------------
|
||
def update_anime_count
|
||
if moving? && @walk_anime
|
||
@anime_count += 1.5
|
||
elsif @step_anime || @pattern != @original_pattern
|
||
@anime_count += 1
|
||
end
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● アニメパターンの更新
|
||
#--------------------------------------------------------------------------
|
||
def update_anime_pattern
|
||
if !@step_anime && @stop_count > 0
|
||
@pattern = @original_pattern
|
||
else
|
||
@pattern = (@pattern + 1) % 4
|
||
end
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 梯子判定
|
||
#--------------------------------------------------------------------------
|
||
def ladder?
|
||
$game_map.ladder?(@x, @y)
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 茂み深さの更新
|
||
#--------------------------------------------------------------------------
|
||
def update_bush_depth
|
||
if normal_priority? && !object_character? && bush? && !jumping?
|
||
@bush_depth = 8 unless moving?
|
||
else
|
||
@bush_depth = 0
|
||
end
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 茂み判定
|
||
#--------------------------------------------------------------------------
|
||
def bush?
|
||
$game_map.bush?(@x, @y)
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 地形タグの取得
|
||
#--------------------------------------------------------------------------
|
||
def terrain_tag
|
||
$game_map.terrain_tag(@x, @y)
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● リージョン ID の取得
|
||
#--------------------------------------------------------------------------
|
||
def region_id
|
||
$game_map.region_id(@x, @y)
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 歩数増加
|
||
#--------------------------------------------------------------------------
|
||
def increase_steps
|
||
set_direction(8) if ladder?
|
||
@stop_count = 0
|
||
update_bush_depth
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● グラフィックの変更
|
||
# character_name : 新しい歩行グラフィック ファイル名
|
||
# character_index : 新しい歩行グラフィック インデックス
|
||
#--------------------------------------------------------------------------
|
||
def set_graphic(character_name, character_index)
|
||
@tile_id = 0
|
||
@character_name = character_name
|
||
@character_index = character_index
|
||
@original_pattern = 1
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 正面の接触イベントの起動判定
|
||
#--------------------------------------------------------------------------
|
||
def check_event_trigger_touch_front
|
||
x2 = $game_map.round_x_with_direction(@x, @direction)
|
||
y2 = $game_map.round_y_with_direction(@y, @direction)
|
||
check_event_trigger_touch(x2, y2)
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 接触イベントの起動判定
|
||
#--------------------------------------------------------------------------
|
||
def check_event_trigger_touch(x, y)
|
||
return false
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● まっすぐに移動
|
||
# d : 方向(2,4,6,8)
|
||
# turn_ok : その場での向き変更を許可
|
||
#--------------------------------------------------------------------------
|
||
def move_straight(d, turn_ok = true)
|
||
@move_succeed = passable?(@x, @y, d)
|
||
if @move_succeed
|
||
set_direction(d)
|
||
@x = $game_map.round_x_with_direction(@x, d)
|
||
@y = $game_map.round_y_with_direction(@y, d)
|
||
@real_x = $game_map.x_with_direction(@x, reverse_dir(d))
|
||
@real_y = $game_map.y_with_direction(@y, reverse_dir(d))
|
||
increase_steps
|
||
elsif turn_ok
|
||
set_direction(d)
|
||
check_event_trigger_touch_front
|
||
end
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 斜めに移動
|
||
# horz : 横方向(4 or 6)
|
||
# vert : 縦方向(2 or 8)
|
||
#--------------------------------------------------------------------------
|
||
def move_diagonal(horz, vert)
|
||
@move_succeed = diagonal_passable?(x, y, horz, vert)
|
||
if @move_succeed
|
||
@x = $game_map.round_x_with_direction(@x, horz)
|
||
@y = $game_map.round_y_with_direction(@y, vert)
|
||
@real_x = $game_map.x_with_direction(@x, reverse_dir(horz))
|
||
@real_y = $game_map.y_with_direction(@y, reverse_dir(vert))
|
||
increase_steps
|
||
end
|
||
set_direction(horz) if @direction == reverse_dir(horz)
|
||
set_direction(vert) if @direction == reverse_dir(vert)
|
||
end
|
||
end
|