C++でのゲーム開発勉強(3)

c++
GitHub - kowara-gan/ProjectCpp: c++勉強用
c++勉強用. Contribute to kowara-gan/ProjectCpp development by creating an account on GitHub.

参考書の3章で作るゲームを作ります。

C++でのゲーム開発勉強(2)
参考書の2章で作るゲームである2Dゲームをつくります。 Visual Studioで新しいプロジェクトを作ります。Project2でc++の空のオブジェクト。 SDL_imageをダウンロードします。SDL_imageは様々な形式の画像ファ...

準備を前回と同じように行います。

ベクトルと基礎物理

参考書第3章はゲームで使うベクトルについて書かれています。参考書ではベクトルの計算にMath.hライブラリ(Vector2、Vector3)を使用します。

ゲームではベクトルを使用して運動や衝突判定をするので重要です。

MoveComponentとInputComponent

2章と違い、運動機能と入力機能をコンポーネントにします。以下のようなコードで移動と回転を制御します。

//位置座標に(前方ベクトル*前進スピード*デルタタイム)を加算
position += GetForward() * forwardSpeed * deltaTime;
//回転角に(回転速度*デルタタイム)を加算
rotation += angularSpeed * deltaTime;

ゲーム内の小惑星にMoveComponentを使用し、宇宙船にInputComponentを使用しています。すべてのComponentにProcessInput関数(実装は空)があり、呼び出されるのでInputComponentも動かすことができます。

//新しく追加されたインプット用関数(Game.cppが使う)
void Actor::ProcessInput(const uint8_t* keyState)
{
	if (mState == EActive)
	{
		// First process input for components
		for (auto comp : mComponents)
		{
			comp->ProcessInput(keyState);
		}
		ActorInput(keyState);
	}
}
//機能追加するときオーバーライドするインプット用関数
void Actor::ActorInput(const uint8_t* keyState)
{
}

ニュートン物理学

参考書第3章は物理的なプログラム(力=質量×加速度)にも触れます。物体の挙動のために以下のようなコードで速度と位置をプログラムします。

//加速度=力の合計/質量
acceleration = sumOfForces / mass;
//速度を更新
velocity += acceleration * deltaTime;
//位置を更新
position += velocity * deltaTime;

Random

ランダムを関数化します。c++は疑似乱数を得る方法が他言語より面倒なことがあります。

#include "Random.h"

void Random::Init()
{
	std::random_device rd;
	Random::Seed(rd());
}

void Random::Seed(unsigned int seed)
{
	sGenerator.seed(seed);
}

float Random::GetFloat()
{
	return GetFloatRange(0.0f, 1.0f);
}

float Random::GetFloatRange(float min, float max)
{
	std::uniform_real_distribution<float> dist(min, max);
	return dist(sGenerator);
}

int Random::GetIntRange(int min, int max)
{
	std::uniform_int_distribution<int> dist(min, max);
	return dist(sGenerator);
}
std::mt19937 Random::sGenerator;

練習問題

宇宙船に衝突判定を実装します。仕様では衝突後、2秒宇宙船を消して画面の中央に戻します。Laser.cppを参考にすればOKです。

// 1秒後に消える
	mDeathTimer -= deltaTime;
	if (mDeathTimer <= 0.0f)
	{
		SetState(EDead);
	}
	else
	{
		// アステロイドと衝突したかを判定
		for (auto ast : GetGame()->GetAsteroids())
		{
			if (Intersect(*mCircle, *(ast->GetCircle())))
			{
				// 衝突したら状態をEDeadに設定
				SetState(EDead);
				ast->SetState(EDead);
				break;
			}
		}
	}

ニュートン物理学を利用した仕様に変更します。MoveComponentに質量、力、速度を持たせて動かします。コンポーネントに力を設定する際にはVector2を使う仕様にするのですが、私は力の合計と速度もVector2で実装しました。宇宙空間らしい慣性の働く動きになります。

 void MoveComponent::Update(float deltaTime)
{
...
  //加速度=力の合計/質量
	Vector2 acceleration = mForces * (1 / mMass);
	//速度を更新
	mVelocity += acceleration * deltaTime;
	//力をクリア
	mForces = Vector2::Zero;

	// 前進スピードが0に近ければ位置を更新しない
	//if (!Math::NearZero(mForwardSpeed))
	if (!Math::NearZero(mVelocity.LengthSq()))
	{
		//位置を更新
		Vector2 pos = mOwner->GetPosition();
		pos += mVelocity * deltaTime;
		// (Screen wrapping code only for asteroids)
		if (pos.x < 0.0f) { pos.x = 1022.0f; }
		else if (pos.x > 1024.0f) { pos.x = 2.0f; }

		if (pos.y < 0.0f) { pos.y = 766.0f; }
		else if (pos.y > 768.0f) { pos.y = 2.0f; }

		mOwner->SetPosition(pos);
	}
}

NEXT

コメント

タイトルとURLをコピーしました