Appearance
第07回 クラス分割入門
前回: 第06回 敵と衝突判定 / 次回: 第08回 画像とリソース管理
今回の授業内容
Gameに集まった処理を役割ごとに分けるPlayer、Bullet、Enemyクラスを追加する- データと処理を同じ型にまとめる
publicとprivateで触れる範囲を整理する- 分割前後で動作が変わらないことを確認する
今回の開始状態
第06回終了時点では、Game内にプレイヤー、弾、敵のデータと処理があります。
今回の終了時点では、それらを別ファイルのクラスへ移します。
新しい機能を増やす回ではありません。
動作を保ったまま、コードの置き場所を整理する回です。
変更するファイル
| ファイル | 変更内容 |
|---|---|
Player.h / Player.cpp | プレイヤーの位置、移動、描画、HPを移す |
Bullet.h / Bullet.cpp | 弾の発射、更新、描画、無効化を移す |
Enemy.h / Enemy.cpp | 敵の出現、更新、描画、無効化を移す |
Game.h / Game.cpp | 各クラスを呼び出す側へ整理する |
まずBulletを分ける
最初に、影響範囲の小さいBulletから分けます。Bullet.hを作り、弾が持つ値と操作をまとめます。
cpp
class Bullet
{
public:
void Spawn(float startX, float startY);
void Update();
void Draw() const;
bool IsActive() const;
void Deactivate();
Rect GetRect() const;
private:
Vec2 position = {};
float speed = 8.0f;
bool active = false;
};Game側は、bullet.activeを直接触るのではなく、関数を通して操作します。
cpp
if (!bullet.IsActive())
{
bullet.Spawn(playerPosition.x, playerPosition.y - 22.0f);
return;
}PlayerとEnemyを分ける
Bulletを分けた後で、Playerを移します。
プレイヤーは入力を使うため、Update()でInputを参照として受け取ります。
cpp
void Player::Update(const Input& input)
{
Vec2 move = {};
if (input.IsDown(KEY_INPUT_LEFT) || input.IsDown(KEY_INPUT_A))
move.x -= 1.0f;
position.x += move.x * speed;
}最後にEnemyを分けます。
敵は、出現位置と速度をSpawn()で受け取る形にします。
cpp
void Enemy::Spawn(float startX, float startY, float moveSpeed)
{
position = { startX, startY };
speed = moveSpeed;
active = true;
}Gameの役割を整理する
分割後のGameは、細かい移動や描画ではなく、全体の呼び出し順を管理します。
cpp
player.Update(input);
for (Bullet& bullet : bullets)
bullet.Update();
for (Enemy& enemy : enemies)
enemy.Update();
CheckCollisions();衝突判定では、それぞれのクラスからRectを受け取ります。
cpp
if (IsOverlapping(enemy.GetRect(), bullet.GetRect()))
{
enemy.Deactivate();
bullet.Deactivate();
++score;
}動作確認
Bulletだけを分けた時点でビルドして、弾が出ることを確認するPlayerを分けた時点でビルドして、移動とHP表示を確認するEnemyを分けた時点でビルドして、敵生成と衝突を確認する- 分割前と同じ操作で同じ結果になることを確認する
よくある問題
.cppを追加した後は、Visual Studioプロジェクトへ登録されているか確認するprivateにした変数へGameから直接アクセスしている箇所は、関数経由に直す- 循環インクルードが起きた場合は、必要なヘッダーだけをインクルードしているか確認する
今回の完成条件
Player、Bullet、Enemyを別ファイルへ分けられるpublicとprivateの役割を説明できるGameが全体の呼び出し順を管理する形に整理できる- 分割前後でゲームの動作を維持できる
まとめ
今回は、増えてきた処理をクラスへ分けました。
次回は、図形描画を画像描画へ置き換えるため、画像管理を追加します。