2 / 4 フレームワークの構成
処理の担当と、入力から更新・描画までのつながり
主要コンポーネントの解説
完成サンプルの主要コンポーネントと、それぞれの役割を解説します。
ゲームは大きく分けて、ゲームのルールを管理するコアロジックと、コアロジックを支えるフレームワークに分かれています。
ゲーム体験の多くはコアロジック側の実装によって決まりますが、手当たり次第に改造を進めるとフレームワークの動作を破壊し、意図した動作を導き出せなくなってしまうかもしれません。
どこを拡張すれば目的を達成できるのかを意識しながら、スマートに改造を進めていきましょう。
Game クラスと GameModel クラス
Gameクラスは入力・モデル更新・描画・音声を準備提供し、ゲームの全体を包含して管理します。
一方で、GameModelクラスはゲーム本体にあたり、戦闘・経験値・強化・勝敗といったゲームルールの管理を担当します。
この二つのクラスが、ゲームの動作の中核を担っています。
Gameがフレームワーク側の処理を担当し、GameModelがコアロジックを担当する形です。
void Game::Update(float seconds)
{
model.Update(ReadFrameInput(), seconds);
HandleEvents(model.GetEvents(), seconds);
}
void Game::Draw() const
{
renderer.Draw(model);
}入力・描画・音声の担当クラス
Inputクラスはキー入力、Rendererクラスはゲーム状態の描画、SoundManagerクラスは音声の管理を担当します。
例えば効果音の発声は、GameModelで起きた発射・命中などのイベントをGameが音声再生につなげて行われます。
これらはクラスはゲーム内容によって異なるものと、様々なゲームで再利用可能なものが混在しています。
自身のゲームで何が再利用できるかを考えながら、必要な要素を追加していきましょう。
プレイヤー・敵・武装と各管理クラス
Player、Enemy、Weaponといったゲームを構成する各要素は、それぞれ個別のクラスに分割されています。
その上でEnemyManager、AttackManager、PickupManagerなどのマネージャークラスがオブジェクトを生成・更新しています。
ゲームの動作基盤
起動・初期化・終了とメインループ
main.cppでDxLibを初期化し、Game::Runで素材読み込みとメインループを実行します。
終了時はGameを破棄してからDxLib_Endを呼びます。
#include <DxLib.h>
#include "AutoShooter/Application.h"
#include "AutoShooter/Game.h"
// アプリケーションのエントリーポイントとしてDXライブラリとゲームを実行する
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
if (!dxgame::autoshooter::InitializeDxLib())
return 1;
int result = 0;
// DxLib_Endを呼ぶ前にGameを破棄し、画像や音声のハンドルを安全に解放する
{
dxgame::autoshooter::Game game;
if (!game.Run())
result = -1;
}
DxLib_End();
return result;
}入力の取得・時間の管理・更新・描画の流れ
Game::MainLoopでは入力を取得し、更新、描画、画面の切り替えを繰り返します。
今回、フレームレートはリフレッシュレートに依存せず、固定の更新間隔でゲームを進行させる方式を採用しています。
Update(config::DeltaTime);
Draw();
ScreenFlip();画像・マップ・音声の読み込み
Game::InitializeからRenderer::LoadAllとSoundManager::LoadAllを呼び、画像・マップ・音声を読み込みます。
素材の読み込みに失敗した場合は、ゲームループへ進まずエラーを表示します。
オブジェクトの生成・更新・再利用
攻撃などは固定長配列の空き要素を使って生成します。
活動を終えた要素は、次の生成で再利用します。
bool AttackManager::SpawnShot(Vector2 position, Vector2 velocity, Weapon::Type type, const Weapon::Stats& stats)
{
for (auto& shot : shots)
{
if (shot.IsActive())
continue;
shot.Spawn(position, velocity, type, stats);
return true;
}
return false;
}- 主要コンポーネントの役割とつながり
- ゲームの実行を支える処理とゲームルールの区別