#include "Camera.h" #include "System.h" #include "Input.h" #include "Stage.h" #include "StageData.h" #include // カメラの当たり判定サイズ #define COLLISION_SIZE (15.0f) // カメラの角度変更速度 #define ANGLE_SPEED (3.0f) // カメラとプレイヤーの距離 #define PLAYER_DISTANCE (500.0f) // カメラが注視点とするプレイヤーの座標のY座標に足す値 #define PLAYER_OFFSET_Y (120.0f) // カメラの初期水平角度 #define DEFAULT_H_ANGLE (DX_PI_F) // カメラの初期垂直角度 #define DEFAULT_V_ANGLE (0.4f) // カメラの画角 #define CAMERA_FOV (40.0f) // カメラの座標を目標座標に近づける計算で除算に使用する値 #define MOVE_DIV_NUM (0.17f) // カメラの情報 typedef struct _SCameraInfo { // カメラの座標 VECTOR Position; // カメラの注視点座標 VECTOR LookAtPosition; // カメラ揺らし座標を無視したカメラの座標 VECTOR OrigPosition; // カメラ揺らし座標を無視したカメラの注視点座標 VECTOR OrigLookAtPosition; // カメラの目標座標 VECTOR TargetPosition; // カメラの目標注視点座標 VECTOR TargetLookAtPosition; // カメラの注視点に対する水平角度 float HAngle; // カメラの注視点に対する垂直角度 float VAngle; // カメラの座標からカメラの注視点座標へのベクトル VECTOR Direction; // カメラから見て右方向のベクトル VECTOR RightDirection; // カメラの正面方向のY成分を抜いたベクトル VECTOR FrontDirection; // カメラを揺らす処理を行っているかどうか bool Shake; // カメラを揺らす幅 float ShakeWidth; // カメラを揺らす時間 float ShakeTime; // カメラを揺らす処理の経過時間計測用変数 float ShakeTimeCounter; // カメラを揺らす処理で使用する sin に渡す角度 float ShakeAngle; // カメラを揺らす処理で使用する sin に渡す角度の変化速度 float ShakeAngleSpeed; // カメラを揺らす処理で算出したカメラ座標に足す座標 VECTOR ShakePosition; } SCameraInfo; static SCameraInfo g_CamInfo; // カメラの処理を初期化する void Camera_Initialize( void ) { // 各パラメータに初期値をセットする g_CamInfo.HAngle = DEFAULT_H_ANGLE; g_CamInfo.VAngle = DEFAULT_V_ANGLE; g_CamInfo.Shake = false; g_CamInfo.ShakePosition = VGet( 0.0f, 0.0f, 0.0f ); } // カメラの状態推移処理を実行する void Camera_Step( // 推移させる時間( 単位:秒 ) float StepTime ) { SCharaInfo *PCInfo; VECTOR CameraStickInput; float MoveScale; VECTOR TempV; float NotHitDistance; float HitDistance; float TestDistance; VECTOR TestPosition; VECTOR Direction; // プレイヤーのキャラ情報構造体のアドレスを取得する PCInfo = System_GetPlayerCharaInfo(); // プレイヤーが注視点になるので、プレイヤーが存在しない場合は何もせず終了 if( PCInfo == NULL ) { return; } // カメラの操作入力を取得する CameraStickInput = GetCameraStickInput(); // 水平方向の角度変更入力の処理 g_CamInfo.HAngle += -CameraStickInput.x * ANGLE_SPEED * StepTime; if( g_CamInfo.HAngle < -DX_PI_F ) { g_CamInfo.HAngle += DX_TWO_PI_F; } if( g_CamInfo.HAngle > DX_PI_F ) { g_CamInfo.HAngle -= DX_TWO_PI_F; } // 垂直方向の角度変更入力の処理 g_CamInfo.VAngle += CameraStickInput.y * ANGLE_SPEED * StepTime; if( g_CamInfo.VAngle < -DX_PI_F / 2.0f + 0.6f ) { g_CamInfo.VAngle = -DX_PI_F / 2.0f + 0.6f; } if( g_CamInfo.VAngle > DX_PI_F / 2.0f - 0.6f ) { g_CamInfo.VAngle = DX_PI_F / 2.0f - 0.6f; } // カメラを揺らす処理を行うかどうかのフラグが立っていたらカメラを揺らす処理を行う if( g_CamInfo.Shake ) { // sin を使用した揺らし座標の算出 g_CamInfo.ShakePosition.y = sin( g_CamInfo.ShakeAngle ) * ( 1.0f - ( g_CamInfo.ShakeTimeCounter / g_CamInfo.ShakeTime ) ) * g_CamInfo.ShakeWidth; g_CamInfo.ShakePosition.x = 0.0f; g_CamInfo.ShakePosition.z = 0.0f; // 揺らし処理に使用する sin に渡す角度の変更処理 g_CamInfo.ShakeAngle += g_CamInfo.ShakeAngleSpeed * StepTime; // 揺らす時間が経過したら揺らし処理を終了する g_CamInfo.ShakeTimeCounter += StepTime; if( g_CamInfo.ShakeTimeCounter >= g_CamInfo.ShakeTime ) { g_CamInfo.Shake = false; } } else { // 揺らされていない場合は揺らし処理による加算座標を0にする g_CamInfo.ShakePosition = VGet( 0.0f, 0.0f, 0.0f ); } // 目標注視点座標の算出 g_CamInfo.TargetLookAtPosition = PCInfo->Position; g_CamInfo.TargetLookAtPosition.y += PLAYER_OFFSET_Y; // 目標座標の算出 g_CamInfo.TargetPosition.x = 0.0f; g_CamInfo.TargetPosition.z = cos( g_CamInfo.VAngle ) * PLAYER_DISTANCE; g_CamInfo.TargetPosition.y = sin( g_CamInfo.VAngle ) * PLAYER_DISTANCE; g_CamInfo.TargetPosition.x = - sin( g_CamInfo.HAngle ) * g_CamInfo.TargetPosition.z; g_CamInfo.TargetPosition.z = cos( g_CamInfo.HAngle ) * g_CamInfo.TargetPosition.z; g_CamInfo.TargetPosition = VAdd( g_CamInfo.TargetPosition, g_CamInfo.TargetLookAtPosition ); // カメラの揺らし処理を無視したカメラの座標、注視点座標をそれぞれの目標座標に近づける MoveScale = StepTime / MOVE_DIV_NUM; TempV = VSub( g_CamInfo.TargetPosition, g_CamInfo.OrigPosition ); TempV = VScale( TempV, MoveScale ); g_CamInfo.OrigPosition = VAdd( g_CamInfo.OrigPosition, TempV ); TempV = VSub( g_CamInfo.TargetLookAtPosition, g_CamInfo.OrigLookAtPosition ); TempV = VScale( TempV, MoveScale ); g_CamInfo.OrigLookAtPosition = VAdd( g_CamInfo.OrigLookAtPosition, TempV ); // カメラの揺らし処理を無視したカメラの座標、注視点座標にカメラの揺らし処理による // 加算座標を足した座標を現在のカメラの座標、注視点座標とする g_CamInfo.Position = VAdd( g_CamInfo.OrigPosition, g_CamInfo.ShakePosition ); g_CamInfo.LookAtPosition = VAdd( g_CamInfo.OrigLookAtPosition, g_CamInfo.ShakePosition ); // カメラの座標からカメラの注視点座標へのベクトルを算出 g_CamInfo.Direction = VNorm( VSub( g_CamInfo.LookAtPosition, g_CamInfo.Position ) ); // カメラから見て右方向のベクトルを算出 g_CamInfo.RightDirection = VNorm( VCross( g_CamInfo.Direction, VGet( 0.0f, -1.0f, 0.0f ) ) ); // カメラの正面方向のY成分を抜いたベクトルを算出 g_CamInfo.FrontDirection = VNorm( VCross( VGet( 0.0f, -1.0f, 0.0f ), g_CamInfo.RightDirection)); // カメラ座標から注視点座標の間にコリジョン用ポリゴンが存在するかチェック if( Stage_HitCheck( g_CamInfo.Position, g_CamInfo.LookAtPosition, COLLISION_SIZE ) ) { // コリジョン用ポリゴンが存在しない座標までカメラ座標を注視点に近づける // 注視点座標からカメラ座標へのベクトルを算出 Direction = VNorm( VSub( g_CamInfo.Position, g_CamInfo.LookAtPosition ) ); // ポリゴンに当たらない距離をセット NotHitDistance = 0.0f; // ポリゴンに当たる距離をセット HitDistance = PLAYER_DISTANCE; do { // 当たるかどうかテストする距離を算出( 当たらない距離と当たる距離の中間 ) TestDistance = NotHitDistance + ( HitDistance - NotHitDistance ) / 2.0f; // テスト用のカメラ座標を算出 TestPosition = VAdd( g_CamInfo.LookAtPosition, VScale( Direction, TestDistance ) ); // 新しい座標でコリジョン用ポリゴンに当たるかテスト if( Stage_HitCheck( TestPosition, g_CamInfo.LookAtPosition, COLLISION_SIZE )) { // 当たったら当たる距離を TestDistance に変更する HitDistance = TestDistance; } else { // 当たらなかったら当たらない距離を TestDistance に変更する NotHitDistance = TestDistance; } // HitDistance と NoHitDistance が十分に近づいていなかったらループ }while( HitDistance - NotHitDistance > 1.0f ); // カメラの座標をセット g_CamInfo.Position = TestPosition; g_CamInfo.OrigPosition = TestPosition; } // リスナーの位置を変更 Set3DSoundListenerPosAndFrontPos_UpVecY( g_CamInfo.Position, g_CamInfo.TargetLookAtPosition ); } // カメラの設定を行う void Camera_Setup( void ) { // カメラの写す範囲を設定 SetupCamera_Perspective( CAMERA_FOV * DX_PI_F / 180.0f ); SetCameraNearFar( CAMERA_NEAR_Z, CAMERA_FAR_Z ); SetCameraPositionAndTarget_UpVecY( g_CamInfo.Position, g_CamInfo.LookAtPosition ); } // カメラを揺らす処理を開始する void Camera_Shake( // 揺れる幅 float ShakeWidth, // 揺れる時間 float ShakeTime, // 揺れの速度 float ShakeAngleSpeed ) { g_CamInfo.Shake = true; g_CamInfo.ShakeWidth = ShakeWidth; g_CamInfo.ShakeTimeCounter = 0.0f; g_CamInfo.ShakeTime = ShakeTime; g_CamInfo.ShakeAngle = 0.0f; g_CamInfo.ShakeAngleSpeed = ShakeAngleSpeed; } // カメラの向いている方向を取得する // 戻り値 : カメラの向いている方向のベクトル VECTOR Camera_FrontDirection( void ) { return g_CamInfo.FrontDirection; } // カメラの向いている方向から見て右方向を取得する // 戻り値 : カメラの向いている方向から見て右方向のベクトルを取得する VECTOR Camera_RightDirection( void ) { return g_CamInfo.RightDirection; }