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);
}
}
コメント