『アニメーションによる座標移動』はプログラムの簡略化のために実際にアニメーションによる移動値を使って
入力に沿った方向に移動するプログラムとなっていなかったので、『方向入力によるキャラクター移動( カメラ固定 )』と
組み合わせて入力した方向への移動にアニメーションによる移動値を使用するようにしたのがこちらのサンプルです。
( プログラムの実行に必要なファイルはこちら )
// アニメーションによる座標移動 + 方向入力によるキャラクター移動( カメラ固定 )
#include "DxLib.h"
#include <math.h>
// DxChara.x での走りアニメーションの番号
#define ANIM_RUN 1
// DxChara.x での待機アニメーションの番号
#define ANIM_NEUTRAL 4
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int ModelHandle ;
float AnimTotalTime ;
float AnimNowTime ;
int AnimAttachIndex ;
int RunFlag ;
int MoveAnimFrameIndex ;
VECTOR Position ;
int Input ;
int MoveFlag ;
float Angle ;
VECTOR PrevPosition ;
VECTOR NowPosition ;
VECTOR MoveVector ;
float SinParam ;
float CosParam ;
// ウインドウモードで起動
ChangeWindowMode( TRUE ) ;
// DXライブラリの初期化
if( DxLib_Init() < 0 ) return -1 ;
// 3Dモデルの読み込み
ModelHandle = MV1LoadModel( "DxChara.x" ) ;
// 向きを初期化
Angle = 0.0f ;
// 走っているフラグを倒す
RunFlag = FALSE ;
// 待機アニメーションをアタッチ
AnimAttachIndex = MV1AttachAnim( ModelHandle, ANIM_NEUTRAL ) ;
// 待機アニメーションの総時間を取得しておく
AnimTotalTime = MV1GetAttachAnimTotalTime( ModelHandle, AnimAttachIndex ) ;
// アニメーション再生時間を初期化
AnimNowTime = 0.0f ;
MV1SetAttachAnimTime( ModelHandle, AnimAttachIndex, AnimNowTime ) ;
// アニメーションで移動をしているフレームの番号を検索する
MoveAnimFrameIndex = MV1SearchFrame( ModelHandle, "BasePoint" ) ;
// アニメーションで移動をしているフレームを無効にする
MV1SetFrameUserLocalMatrix( ModelHandle, MoveAnimFrameIndex, MV1GetFrameLocalMatrix( ModelHandle, MoveAnimFrameIndex ) ) ;
// 3Dモデルの座標を初期化
Position = VGet( 0.0f, 0.0f, 0.0f ) ;
// 描画先を裏画面にする
SetDrawScreen( DX_SCREEN_BACK ) ;
// カメラの位置と向きを設定
SetCameraPositionAndTarget_UpVecY( VGet( 0.0f, 1200.0f, -2000.0f ), VGet( 0.0f, 400.0f, 0.0f ) );
// カメラのクリッピング距離を設定
SetCameraNearFar( 16.0f, 5000.0f );
// 背景の色を灰色にする
SetBackgroundColor( 128, 128, 128 ) ;
// メインループ(何かキーが押されたらループを抜ける)
while( ProcessMessage() == 0 )
{
// 画面のクリア
ClearDrawScreen() ;
// ゲームパッド+キーボードの入力を取得
Input = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;
// 移動しているかどうかのフラグを倒す
MoveFlag = FALSE ;
// 方向入力の判定
// ( 最初に斜め入力の判定を、その後上下左右単体の入力の判定をしています )
if( ( Input & PAD_INPUT_LEFT ) != 0 && ( Input & PAD_INPUT_UP ) != 0 )
{
Angle = 135.0f ;
MoveFlag = TRUE ;
}
else
if( ( Input & PAD_INPUT_UP ) != 0 && ( Input & PAD_INPUT_RIGHT ) != 0 )
{
Angle = -135.0f ;
MoveFlag = TRUE ;
}
else
if( ( Input & PAD_INPUT_RIGHT ) != 0 && ( Input & PAD_INPUT_DOWN ) != 0 )
{
Angle = -45.0f ;
MoveFlag = TRUE ;
}
else
if( ( Input & PAD_INPUT_DOWN ) != 0 && ( Input & PAD_INPUT_LEFT ) != 0 )
{
Angle = 45.0f ;
MoveFlag = TRUE ;
}
else
if( ( Input & PAD_INPUT_LEFT ) != 0 )
{
Angle = 90.0f ;
MoveFlag = TRUE ;
}
else
if( ( Input & PAD_INPUT_RIGHT ) != 0 )
{
Angle = -90.0f ;
MoveFlag = TRUE ;
}
else
if( ( Input & PAD_INPUT_DOWN ) != 0 )
{
Angle = 0.0f ;
MoveFlag = TRUE ;
}
else
if( ( Input & PAD_INPUT_UP ) != 0 )
{
Angle = 180.0f ;
MoveFlag = TRUE ;
}
// 今までと状態が変化した場合はアニメーションを変更する
if( RunFlag != MoveFlag )
{
// 走っているかどうかのフラグを保存
RunFlag = MoveFlag ;
// 今までアタッチしていたアニメーションをデタッチ
MV1DetachAnim( ModelHandle, AnimAttachIndex ) ;
// 新しいアニメーションをアタッチ
if( RunFlag )
{
AnimAttachIndex = MV1AttachAnim( ModelHandle, ANIM_RUN ) ;
}
else
{
AnimAttachIndex = MV1AttachAnim( ModelHandle, ANIM_NEUTRAL ) ;
}
// アニメーションの総時間を取得しておく
AnimTotalTime = MV1GetAttachAnimTotalTime( ModelHandle, AnimAttachIndex ) ;
// アニメーション再生時間を初期化
AnimNowTime = 0.0f ;
MV1SetAttachAnimTime( ModelHandle, AnimAttachIndex, AnimNowTime ) ;
}
// アニメーション時間を進める前の『アニメーションで移動をしているフレームの座標』を取得しておく
PrevPosition = MV1GetAttachAnimFrameLocalPosition( ModelHandle, AnimAttachIndex, MoveAnimFrameIndex ) ;
// アニメーション再生時間を進める
AnimNowTime += 200.0f ;
// アニメーション再生時間がアニメーションの総時間を越えているかどうかで処理を分岐
if( AnimNowTime >= AnimTotalTime )
{
// 超えている場合は、まず『アニメーション再生時間を進める前の「アニメーションで移動しているフレームの座標」』と、
// 『アニメーションの終端での「アニメーションで移動しているフレームの座標」』との差分を移動ベクトルとする
MV1SetAttachAnimTime( ModelHandle, AnimAttachIndex, AnimTotalTime ) ;
NowPosition = MV1GetAttachAnimFrameLocalPosition( ModelHandle, AnimAttachIndex, MoveAnimFrameIndex ) ;
MoveVector = VSub( NowPosition, PrevPosition ) ;
// 新しいアニメーション再生時間は、アニメーション再生時間からアニメーション総時間を引いたもの
AnimNowTime -= AnimTotalTime ;
// 次に『新しいアニメーション再生時間での「アニメーションで移動をしているフレームの座標」と
// 『アニメーション再生時間0での「アニメーションで移動しているフレームの座標」』との差分を移動ベクトルに加算する
MV1SetAttachAnimTime( ModelHandle, AnimAttachIndex, 0.0f ) ;
PrevPosition = MV1GetAttachAnimFrameLocalPosition( ModelHandle, AnimAttachIndex, MoveAnimFrameIndex ) ;
MV1SetAttachAnimTime( ModelHandle, AnimAttachIndex, AnimNowTime ) ;
NowPosition = MV1GetAttachAnimFrameLocalPosition( ModelHandle, AnimAttachIndex, MoveAnimFrameIndex ) ;
MoveVector = VAdd( MoveVector, VSub( NowPosition, PrevPosition ) ) ;
}
else
{
// 新しいアニメーション再生時間をセット
MV1SetAttachAnimTime( ModelHandle, AnimAttachIndex, AnimNowTime ) ;
// 『新しいアニメーション再生時間での「アニメーションで移動をしているフレームの座標」』と、
// 『アニメーション再生時間を進める前の「アニメーションで移動をしているフレームの座標」』との差分を移動ベクトルとする
NowPosition = MV1GetAttachAnimFrameLocalPosition( ModelHandle, AnimAttachIndex, MoveAnimFrameIndex ) ;
MoveVector = VSub( NowPosition, PrevPosition ) ;
}
// キャラクターの向きに合わせて移動ベクトルの角度を回転させて、キャラクターモデルの座標に加算
SinParam = sin( -Angle / 180.0f * DX_PI_F ) ;
CosParam = cos( -Angle / 180.0f * DX_PI_F ) ;
Position.x += MoveVector.x * CosParam - MoveVector.z * SinParam ;
Position.z += MoveVector.x * SinParam + MoveVector.z * CosParam ;
// 3Dモデルに新しい座標をセット
MV1SetPosition( ModelHandle, Position ) ;
// 新しい向きをセット
MV1SetRotationXYZ( ModelHandle, VGet( 0.0f, Angle / 180.0f * DX_PI_F, 0.0f ) ) ;
// 3Dモデルの描画
MV1DrawModel( ModelHandle ) ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
}
// DXライブラリの後始末
DxLib_End() ;
// ソフトの終了
return 0 ;
}
戻る