![表紙の写真](https://assets.st-note.com/production/uploads/images/8937174/rectangle_large_type_2_71ecc13ebe6059a3b94666f98e1d7c80.jpg?width=1200)
ゲームループ(2)
ゲームの進行はとても単純です。キャラクタを動かし、そしてキャラクタを描画します。1体動かして1体描画するのではなく、すべてのキャラクタを動かして、すべてのキャラクタを描画します。
たとえば、ダミーの関数を呼び出すとすれば、次のように書くことができます。
While(System::Update())
{
MoveAllCharacters();
DrawAllCharacters();
}
OpenSiv3Dだからこれだけ簡素に処理を書けますが、DirectXを使って処理を書こうとすると、Windowのメインループを書いてWindowsのメッセージを処理させ、次にDirectXのメッセージを処理させ、その上でゲーム処理を書かなければなりません。かなり面倒です。
Taskシステムを使った実装
Taskシステムを使うと「タスクコールグループ」という概念を利用できるので、ゲームループを次のように書くことができます。
While(System::Update())
{
TaskCall::All::Update(TaskGroups::Moving);
TaskCall::All::Update(TaskGroups::Drawing);
}
次のソースコードは、キーボードを使って自機を動かすためのサンプルです。タスクコールグループを分けて、移動処理をさせてから、描画処理をさせています。
タスクグループを分けるには汎整数値でグルーピングIDを振ればよいので、公式サイトに合わせて列挙体を使います。そろそろリファクタリングしてソースコードを分割したくなってきますね。
#include <Siv3D.hpp>
#include <rnfs.h>
typedef TextureRegion SoftwareSpriteT;
enum TaskGroups {
Moving,
Drawing
};
class Player : public Task {
private:
Vec2 m_Pos;
TaskCall m_Move;
TaskCall m_Draw;
Array<SoftwareSpriteT>& m_Sprite;
int m_Framecounter;
public:
Player(Array<SoftwareSpriteT>& player) : Task(TaskDestroyMode::None)
, m_Pos(Vec2(0, 0))
, m_Move(this, &Player::Move, TaskGroups::Moving)
, m_Draw(this, &Player::Draw, TaskGroups::Drawing)
, m_Sprite(player)
, m_Framecounter(0)
{}
private:
void Move()
{
if (KeyUp.pressed()) {
m_Pos.y--;
}
else if (KeyDown.pressed()) {
m_Pos.y++;
}
if (KeyLeft.pressed()) {
m_Pos.x--;
}
else if (KeyRight.pressed()) {
m_Pos.x++;
}
}
void Draw()
{
m_Sprite.at(0).draw(m_Pos);
}
};
void Main()
{
if (static_cast<int>(Graphics::GetDisplayRefreshRateHz()) != 60)
{
Graphics::SetTargetFrameRateHz(60);
}
Texture texPlayer(U"player.png");
Array<SoftwareSpriteT> player;
for (int x : {0}) {
player.push_back(texPlayer(64, 80, 32, 16));
}
Create<Player>(player);
while (System::Update())
{
TaskCall::All::Update(TaskGroups::Moving);
TaskCall::All::Update(TaskGroups::Drawing);
}
Task::All::Clear();
}
やっと自機を登場させることができました。DirectXで作成したときも、じっくりプログラムをする時間が取れなかったので、このようにひとつずつフレームワークの動作を確認しながら実行させていました。