見出し画像

カメラに合わせてプレイヤー中心のミニマップ:3Dサンプルプログラム

実装イメージ

・カメラは常にプレイヤーを見るカメラにしています。
・3D空間の座標を2Dに変換してミニマップに円を描画しています。
・カメラに合わせたミニマップの表示にするためにプレイヤーをミニマップの中心にしています。
・ミニマップの敵はプレイヤーからの相対座標に描画しています。

#include "DxLib.h"
#include <math.h>

// 度をラジアンに変換する
#define D2R(deg) ((deg)*DX_PI_F/180.0f)
// 敵の最大数
#define MAX_ENEMY	10
// ミニマップの中心座標
#define MINIMAP_X	400.0f
#define MINIMAP_Y	100.0f

// ステージモデルハンドル
int StageHandle;

// プレイヤーモデルハンドル
int PlayerHandle;
// プレイヤーの座標
VECTOR PlayerPos;
// プレイヤーの向き
VECTOR PlayerAngle;

// 敵モデルハンドル
int EnemyHandle;
// 敵の座標
VECTOR EnemyPos[MAX_ENEMY];
// 敵の向き
VECTOR EnemyAngle[MAX_ENEMY];

// カメラ座標
VECTOR CameraPos;
// 注視点座標
VECTOR CameraTarget;

// ミニマップ画像ハンドル
int MiniMapGraph;

// ==============================
// *** 初期化処理 ***
// ==============================
void Game_Init()
{
	// 3Dモデルの読み込み
	StageHandle = MV1LoadModel( "stage.mqo" );
	PlayerHandle = MV1LoadModel( "player.mqo" );
	EnemyHandle = MV1LoadModel( "enemy.mqo" );
	// ミニマップ画像の読み込み
	MiniMapGraph = LoadGraph( "ミニマップ.png" );

	// プレイヤー座標は原点から
	PlayerPos = VGet( 0.0f, 0.0f, 0.0f );
	// 回転なしの状態から開始
	PlayerAngle = VGet( 0.0f, D2R( 0.0f ), 0.0f );

	for( int i = 0; i < MAX_ENEMY; i++ ){
		// 敵座標は原点付近にランダム
		EnemyPos[i].x = GetRand( 30 ) - 15;
		EnemyPos[i].y = 0.0f;
		EnemyPos[i].z = GetRand( 30 ) - 15;
		// 向きもランダム
		EnemyAngle[i] = VGet( 0.0f, D2R( GetRand( 360 ) ), 0.0f );
	}

	// カメラ座標と注視点の初期設定
	CameraTarget = VGet( 0.0f, 0.0f, -5.0f );
	CameraPos = VGet( 0.0f, 10.0f, -25.0f );
}
// ==============================
// *** 更新処理 ***
// ==============================
void Game_Update()
{
	// 左右キーで向きの変更
	if( CheckHitKey( KEY_INPUT_RIGHT ) ){
		PlayerAngle.y += D2R( 2.0f );
	}
	if( CheckHitKey( KEY_INPUT_LEFT ) ){
		PlayerAngle.y -= D2R( 2.0f );
	}

	// 向きに合わせて座標移動
	if( CheckHitKey( KEY_INPUT_UP ) ){
		PlayerPos.x += sinf( PlayerAngle.y ) * 0.1f;
		PlayerPos.z += cosf( PlayerAngle.y ) * 0.1f;
	}

	// カメラ座標はプレイヤー座標から少し離れたところ
	CameraPos = VAdd( PlayerPos, VGet( 0.0f, 5.0f, -7.0f ) );
	// 注視点の座標はプレイヤー座標の少し上
	CameraTarget = VAdd( PlayerPos, VGet( 0.0f, 2.0f, 0.0f ) );
}
// ==============================
// *** 描画処理 ***
// ==============================
void Game_Draw()
{
	// カメラの位置と注視点をセット
	SetCameraPositionAndTarget_UpVecY( CameraPos, CameraTarget );

	// ステージモデルの描画
	MV1DrawModel( StageHandle );

	// 敵モデルの描画
	for( int i = 0; i < MAX_ENEMY; i++ ){
		MV1SetPosition( EnemyHandle, EnemyPos[i] );
		MV1SetRotationXYZ( EnemyHandle, EnemyAngle[i] );
		MV1DrawModel( EnemyHandle );
	}
		
	// プレイヤーモデルの座標をセットする
	MV1SetPosition( PlayerHandle, PlayerPos );
	// プレイヤーモデルの回転値をセットする
	MV1SetRotationXYZ( PlayerHandle, PlayerAngle );
	// プレイヤーモデルを描画する
	MV1DrawModel( PlayerHandle );

	// ミニマップ画像の描画
	SetDrawBlendMode( DX_BLENDMODE_ALPHA, 128 );
	DrawRotaGraphF( MINIMAP_X, MINIMAP_Y, 1.0f, 0.0f, MiniMapGraph, TRUE );
	SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0 );

	// ミニマップに敵の円を描画(プレイヤーからの相対位置)
	for( int i = 0; i < MAX_ENEMY; i++ ){
		float enemy_x = MINIMAP_X + ( EnemyPos[i].x - PlayerPos.x ) * 3.0f;
		float enemy_y = MINIMAP_Y - ( EnemyPos[i].z - PlayerPos.z ) * 3.0f;
		DrawCircle( enemy_x, enemy_y, 3.0f, GetColor( 200, 100, 200 ) );
	}

	// プレイヤーの円を描画(ミニマップの中心)
	float player_x = MINIMAP_X;
	float player_y = MINIMAP_Y;
	DrawCircle( player_x, player_y, 3.0f, GetColor( 100, 100, 255 ) );
}
// ==============================
// *** 終了処理 ***
// ==============================
void Game_End()
{
	MV1DeleteModel( StageHandle );
	MV1DeleteModel( PlayerHandle );
	MV1DeleteModel( EnemyHandle );

	DeleteGraph( MiniMapGraph );
}

サンプルプログラムで記述している描画や操作関係はDXライブラリを使っていますが、DXライブラリを使わない開発でも処理としては同じような実装で動作すると思います。

いいなと思ったら応援しよう!