Skip to content

第01回 環境確認とプロジェクト構造

次回: 第02回 ゲームループと描画

今回の授業内容

  • 最終的に作る2Dシューティングゲームの仕様を確認する
  • 開始用プロジェクトをVisual Studioで動かす
  • フォルダ分割の意味と構成を確認する(SourceAssetsの役割)
  • main.cppGame.hGame.cppの役割を読む
  • 次回以降にコードを追加していく土台を用意する

この授業で作るもの

この授業では、DXライブラリを使った2Dシューティングゲームを13回で作ります
完成版では、プレイヤーを移動させ、弾を撃ち、敵を倒し、スコア、HP、残り時間、ゲーム状態を管理します

完成版の仕様は最初に確認しますが、完成版コードを写す授業ではありません
第01回では最小構成のプロジェクトを動かし、第02回以降で機能を1つずつ追加します
1つの機能を追加するたびにビルドして動作を確認するため、途中のどの回で止まっても、その時点までの実装は動く状態になります

完成形の仕様

項目仕様
画面サイズ640x480
操作矢印キーまたはWASDで移動、ZまたはSpaceでショット
開始タイトル画面でEnter
プレイヤーHPを3持ち、敵に当たるとダメージを受ける
最大48発を固定配列で管理する
最大24体を固定配列で管理し、一定間隔で出現する
エフェクト最大32個を固定配列で管理し、敵撃破時に表示する
クリア条件スコアが30に到達する、または制限時間を生き残る
ゲームオーバー条件プレイヤーのHPが0になる
リトライ結果画面でEnterを押す

画像と音声は任意素材として扱います
素材がない状態でも、図形描画と無音でゲームロジックを確認できる構成にします
これは手抜きではなく、素材の準備状況に関係なく全員が同じ進度で実装を進められるようにするための設計です

授業の設計方針

この授業には、あらかじめ2つの方針があります

1つ目は、最初の6回はクラスを作らず、Gameクラスの中に構造体と配列を直接書くことです
プレイヤー、弾、敵をいきなり別クラスへ分けると、クラス同士がどんな情報をやり取りしているかが見えにくくなります
まず1つのクラスの中で全体の流れを書き切り、そのクラスが肥大化して見通しが悪くなる感覚を持ってから、第07回でクラスへ分割します
分割の前後で動作が変わらないことを確認できると、クラス分割が「動きを変える作業」ではなく「置き場所を整理する作業」だと実感できます

2つ目は、DXライブラリの各機能を独立した授業として扱わないことです
入力、衝突判定、画像、音、状態管理は、すべて同じシューティングゲームを完成させるための手段として登場します
1つの完成物を通して学ぶことで、機能同士がどう連携するかを合わせて学べます

今回の開始状態

配布ファイルからstarter.zipをダウンロードして展開します
第01回では、この開始用プロジェクトだけを使います

ファイル構成
  • Project
    • Source
      • main.cpp
      • Common.h
      • Game.h
      • Game.cpp
    • Assets
      • Images
      • Sounds

SourceにはC++のソースコードを置きます
Assetsには画像や音声など、実行時に読み込むファイルを置きます
この2つを分けるのは、コードの変更とゲーム素材の変更を別々に扱えるようにするためです
たとえば画像を差し替えるだけであれば、Source側を再ビルドする必要はありません

最初に読むファイル

main.cppはゲームを起動する入口です
DXライブラリの初期化、ウィンドウ設定、Gameの実行、終了処理を担当します

cpp
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    SetGraphMode(screenWidth, screenHeight, 32);
    ChangeWindowMode(TRUE);
    SetMainWindowText(L"Game Programming Practice C++/DX Library Intro");

    if (DxLib_Init() == -1)
        return -1;

    SetDrawScreen(DX_SCREEN_BACK);

    Game game;
    if (game.Initialize())
        game.MainLoop();
    game.Finalize();

    DxLib_End();
    return 0;
}

DxLib_Init()はDXライブラリ全体を使えるようにする関数で、失敗すると-1を返します
失敗時にそのまま処理を続けると、初期化されていない機能を呼び出してクラッシュするため、-1のときはmainをすぐ終了します
SetDrawScreen(DX_SCREEN_BACK)は、画面へ直接描かず裏画面へ描いてから一括で表示する設定です
1枚ずつ描くと描画途中がちらついて見えるため、裏画面を使ってからScreenFlip()で表画面へ切り替えます

game.Initialize()falseを返した場合はMainLoop()を呼びません
初期化に失敗した状態でゲームを動かすと、存在しないデータへアクセスする恐れがあるためです
第01回のInitialize()は常にtrueを返しますが、この形は第08回で画像読み込みの成否を扱うときにそのまま使います

Game.hは、ゲーム全体が持つ関数の宣言です
Game.cppは、それらの関数の中身です
第02回以降は、主にGame.hGame.cppへ機能を追加します

実装手順

  1. DXライブラリ用のVisual Studioプロジェクトを作成する
  2. starter/Source内の.h.cppをプロジェクトへ追加する
  3. Assetsフォルダを実行ファイルから見える位置へ配置する
  4. ビルドして、ウィンドウにDX Library Projectと表示されることを確認する
  5. Common.hscreenWidthscreenHeightが画面サイズに使われていることを確認する

第01回ではゲーム機能を追加しません
環境を整え、次回から同じプロジェクトを継続して編集できる状態にします

よくある問題

  • DxLib.hが見つからない場合は、プロジェクトのインクルードディレクトリにDXライブラリのヘッダーパスが登録されているか確認する
  • リンクエラーが出る場合は、ライブラリディレクトリと追加の依存ファイル(DxLib.libなど)が正しく設定されているか確認する
  • 黒い画面だけで文字が出ない場合は、SetDrawScreen(DX_SCREEN_BACK)ScreenFlip()が呼ばれているか確認する
  • Sourceに追加した.cppがVisual Studioプロジェクトへ登録されているか確認する。ファイルをエクスプローラーへコピーしただけでは、ソリューションエクスプローラー上に表示されていてもビルド対象にならない場合がある
  • ウィンドウがすぐ閉じる場合は、DxLib_Init()-1を返していないか、デバッグ実行でリターン値を確認する

今回の完成条件

  • 開始用プロジェクトをビルドして実行できる
  • SourceAssetsの違いを説明できる
  • main.cppがゲームの入口であることを説明できる
  • Game.hGame.cppの役割の違いを説明できる
  • 次回以降に同じプロジェクトを継続して編集できる

まとめ

今回は、完成形の仕様と開始用プロジェクトの構造を確認しました
次回は、この最小プロジェクトへプレイヤーの仮図形を追加します