挫折不可能!初級ゲームプログラミング完全マニュアル  RSSを登録する

「ゲームが作りたいけどプログラミングなんて全然知らない」「文系だし数学や物理が苦手だけどゲームが作れるだろうか?」そんなアナタのためのメールマガジンです。PCの電源を入れてからどうすればいいのか?から自分のゲームが完成するまでを応援します!

最新号をメルマガでお届けします    
登録 解除

規約に同意して

登録した方には、まぐまぐの公式メルマガ(無料)をお届けします。
2008/08/16

初級ゲームプログラミング完全マニュアル [vol.0059 2008/08/16]

┏┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳┓
┣┛                                                              ┗┫
┃       挫折不可能!  初級ゲームプログラミング完全マニュアル       ┃
┃                                                                  ┃
┃                       第 59 号  2008/08/16                       ┃
┣┓                                                              ┏┫
┗┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻┛
                            - Ads space -
┌┬───────────────────────────────┬┐
││ はじめに                                                     ││
└┴───────────────────────────────┴┘

 みなさま、こんにちは!

 個人ゲーム制作アドバイザーの Byerkut です!

 気がつけば8月も中旬、暑さもそろそろピークでしょうか。

 今、ちょうどお盆休みですのでご先祖様にお線香を上げてきました。

 私は生まれ故郷で仕事をしているので、帰省ラッシュがないだけ楽ですが、

 車などで帰省される方は疲れから来る事故に注意してくださいね。

 さて、今日は地球防衛ゲームの中心のお話です。

┌┬───────────────────────────────┬┐
││本日のラインナップ                                            ││
└┴───────────────────────────────┴┘

  ・今日のメインテーマ
      【地球防衛ゲームの中心で愛を叫ぶ】

  ・あとがき

┌┬───────────────────────────────┬┐
││ みんなの備忘録                                               ││
└┴───────────────────────────────┴┘

  ■Visual C++ 2008 Express Edition をインストールする手順
    http://www.game-create.com/archives/235

  ■Visual C++ 2008 Express Edition でプロジェクトを新規作成する手順
    http://www.game-create.com/archives/270

  ■VC++ 2005 EE でプロジェクトにソースファイルを登録する手順
    http://blog.mag2.com/m/log/0000240151/108824854.html

  ■画像ファイルを LoadImage() 関数で読み込めるようにする手順
    http://www.game-create.com/archives/308

  ■ゲーム用ウィンドウのテンプレート
    http://www.game-create.com/menu/downloads

  ■ビットマップ学習用クラス - Study::Bitmap
    http://www.game-create.com/menu/downloads

┏┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳┓
┃┃                                                              ┃┃
┃┃                      今日のメインテーマ                      ┃┃
┃┃                                                              ┃┃
┃┃              【地球防衛ゲームの中心で愛を叫ぶ】              ┃┃
┃┃                                                              ┃┃
┗┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻┛

 前回までのメルマガで、地球防衛ゲームに爆発エフェクトが

 追加されました。スマブラさながらの爆死エフェクトでしたね。

 せっかく敵に攻め込まれたときのエフェクトができましたので、

 今週からはゲームオーバーの条件を追加していきましょう。



 …と、ここで一息ついてください。



 はい、今週から「敵に3回攻め込まれたらゲームオーバー」という

 新しい仕様を追加していくことになるのですが、実はこれ、

 ゲームプログラミングにおいて悩ましい大きなテーマのひとつなのです。

 どういうことかというと、今の仕様ではプログラムを実行すると、

 すぐにゲームが開始され、敵が降ってくるようになっていると思いますが、

 もし、「3回攻め込まれたらゲームオーバー」という仕様を追加すると、

 ゲーム画面とは別のゲームオーバー画面というのを作る必要があるのです。

 モンハンをやったことがある人は「リタイア」したときの画面を

 思い浮かべてください。画面が灰色になって「ミッション失敗」の

 烙印を押されると思います。ああいう画面を作りたいのです。



 「普通に作ればいいじゃないか?」と思いますか?

 では、どこにゲームオーバー画面を作ればいいか考えていきましょう。



 今回のキモは WinMain() 関数が書いてある template.cpp の解析です。

 地球防衛ゲームで一番最初に実行されるのは WinMain() 関数が書いてある

 template.cpp ですので、ここを理解してしまえばヒントが

 見つかるはずです。



 では早速、先週使っていたプロジェクトを開いてください。

 残っていない場合はダウンロードしてください。

    http://www.game-create.com/archives/575

 開くのは template.cpp です。

 余談なんですが template.cpp という名前は不適切ですね。

 次は bootstrap.cpp とかに変えてみます。



 見ていただきたいのは、次の4つの関数です。

  ・InitializeGame()

  ・FinalizeGame()

  ・UpdateGame()

  ・DrawGame()

 まず InitializeGame() 関数を見てください。

 次のようになっているはずです。

  ------------------------------------------------------------------
  template.cpp
  ------------------------------------------------------------------
    void InitializeGame(HWND hWindow, HDC hBackBuffer)
    {
      std::srand((unsigned int)std::time(NULL));
    
      InitializeBackground(hWindow, hBackBuffer);
      InitializePlayer(hWindow, hBackBuffer);
      InitializePlayerBullets(hWindow, hBackBuffer);
      InitializeEnemiesController(hWindow, hBackBuffer);
      InitializeEffectsController(hWindow, hBackBuffer);
    }
  ------------------------------------------------------------------

 この関数では何をやっているのかというと、他のソースファイルに

 書いてある初期化処理を全部呼び出しています。

 つまり次のような関係になっています。

  template.cpp の InitializeGame()
    ├ background.cpp         の InitializeBackground()        を実行
    ├ player.cpp             の InitializePlayer()            を実行
    ├ player_bullets.cpp     の InitializePlayerBullets()     を実行
    ├ enemies_controller.cpp の InitializeEnemiesController() を実行
    └ effects_controller.cpp の InitializeEffectsController() を実行

 なんと template.cpp は各ソースファイルの親分的存在だったんですね。

 はい、実はソースファイルを追加するたびに、ここに初期化処理を

 こっそり追加しておりました。慣れてきている読者の方は

 とっくに気づかれていると思います。気づかなかった人は

 次回から注意深く template.cpp を眺めてください。

 残りも同じです。適切なタイミングで各ソースファイルの関数を

 呼び出しています。

  template.cpp の FinalizeGame()
    ├ background.cpp         の FinalizeBackground()        を実行
    ├ player.cpp             の FinalizePlayer()            を実行
    ├ player_bullets.cpp     の FinalizePlayerBullets()     を実行
    ├ enemies_controller.cpp の FinalizeEnemiesController() を実行
    └ effects_controller.cpp の FinalizeEffectsController() を実行

  template.cpp の UpdateGame()
    ├ background.cpp         の UpdateBackground()        を実行
    ├ player.cpp             の UpdatePlayer()            を実行
    ├ player_bullets.cpp     の UpdatePlayerBullets()     を実行
    ├ enemies_controller.cpp の UpdateEnemiesController() を実行
    ├ effects_controller.cpp の UpdateEffectsController() を実行
    └ collision_checks.cpp   の CheckCollisionPlayerBulletsAndEnemies() を実行

  template.cpp の DrawGame()
    ├ background.cpp         の DrawBackground()        を実行
    ├ player.cpp             の DrawPlayer()            を実行
    ├ player_bullets.cpp     の DrawPlayerBullets()     を実行
    ├ enemies_controller.cpp の DrawEnemiesController() を実行
    └ effects_controller.cpp の DrawEffectsController() を実行

 …といった具合に template.cpp が中心となっていたわけですね。



 さて、覚えていますでしょうか?

 今回の目的はゲームオーバー画面を作ることです。



 そもそも、なぜ今の仕様だと「いきなりゲームが始まってしまう」の

 でしょうか?その答えは UpdateGame() 関数の中にあります。

  ------------------------------------------------------------------
  template.cpp
  ------------------------------------------------------------------
    void UpdateGame(HWND hWindow, HDC hBackBuffer)
    {
      UpdateBackground(hWindow, hBackBuffer);
      UpdatePlayer(hWindow, hBackBuffer);
      UpdatePlayerBullets(hWindow, hBackBuffer);
      UpdateEnemiesController(hWindow, hBackBuffer);
      UpdateEffectsController(hWindow, hBackBuffer);
    
      CheckCollisionPlayerBulletsAndEnemies(GetPlayerBullets(), GetEnemies());
    }
  ------------------------------------------------------------------

 この UpdateGame() 関数は InitializeGame() 関数が呼ばれた後、

 1秒間に 60 回の間隔で呼び出されます。なぜ 1/60 秒の間隔で

 呼び出されるのか忘れてしまった方は過去記事を参照してください。

    http://archive.mag2.com/0000240151/20080503100000000.html

 では、この関数で呼ばれている関数に注目してください。

  ・背景を更新する UpdateBackground() 関数

  ・プレイヤーを動かす UpdatePlayer() 関数

  ・プレイヤーの弾を動かす UpdatePlayerBullets() 関数

  ・敵キャラを動かす UpdateEnemiesController() 関数

  ・エフェクトを動かす UpdateEffectsController() 関数

 ふむ、これは我々が今まで動かしてきた地球防衛ゲームの組み合わせです。

 このプログラムが実行されると地球防衛ゲームが動くのはうなずけます。

 しかし、これが今回の問題の根源でもあるのです。



 どいういうことかというと、初期化された後 1/60 の間隔で呼ばれる

 ゲームの中心となって動く UpdateGame() 関数が「ゲーム画面」としての

 動きしかしていないということなのです。



 ゲームというのは、本来はたくさんの画面から成り立っているはずです。

 たとえばロゴ画面、オープニング画面、セーブデータの選択画面、

 ゲーム画面、ゲームオーバー画面、エンディング画面…、

 実は UpdateGame() のようなゲームを動かす際の中核となる関数は

 これらの画面を適切に振り分けて関数を呼び分けないといけないのです。

 ソースコードにすると次のようになります。

  ------------------------------------------------------------------
  template.cpp
  ------------------------------------------------------------------
    void UpdateGame(HWND hWindow, HDC hBackBuffer)
    {
      if (/* もしオープニング画面だったら */) {

        UpdateOpening();

      } else if (/* もしゲーム画面だったら *) {

        UpdateBackground(hWindow, hBackBuffer);
        UpdatePlayer(hWindow, hBackBuffer);
        UpdatePlayerBullets(hWindow, hBackBuffer);
        UpdateEnemiesController(hWindow, hBackBuffer);
        UpdateEffectsController(hWindow, hBackBuffer);

        CheckCollisionPlayerBulletsAndEnemies(GetPlayerBullets(), GetEnemies());

      } else if (/* もしゲームオーバー画面だったら */) {

        UpdateGameOver();

      }
    }
  ------------------------------------------------------------------

 わかりますでしょうか?

 ゲームというのはゲーム画面だけではありません。

 いろいろな画面があるからこそ、このように if 文などで、

 「今、処理すべき画面」を適切に判断しなければならないのです。



 これをゲームプログラミング用語で「シーン管理」と言います。



 もし、実際にゲームを作る場合には、かならずシーン管理が

 必要になります。おおざっぱに画面=シーンと考えていただいて

 まずは問題ありません。初級ですので。



 本来はシーン管理というのは1ヶ月かかってでも納得のいくまで

 試行錯誤して、導き出された自分なりの結論に基づいて実装するのですが、

 今回は初級編と言うことで if 文による分岐で実装していきます。

 試行錯誤は慣れてからで良いと思います。

 逆に慣れないとシーン管理の重要性がよくわかりません。



 さて、基礎の話が長くなってしまいましたので、

 実装は次回に持ち越したいと思います。

 今まで template.cpp の役割が変わらなかった方は、

 今回登場した4つの関数の中身に注目してみてください。

 template.cpp の重要性がおわかりいただけるかと思います。

 最近、徐々にレベルが上がっているので、何かわからないことが

 ありましたら、遠慮なさらずに質問してくださいね。



 今回も最後まで読んでいただきましてありがとうございます!

 それでは!

                                                            Byerkut.

┌┬───────────────────────────────┬┐
││ 重要記事のダイジェスト                                       ││
└┴───────────────────────────────┴┘

  ■C++ は計算と記憶しかできない
  ■外部の機能(関数)を借り受けるには #include を使う
  ■#include で借り受けた機能を使うには関数を呼び出す
    http://archive.mag2.com/0000240151/20080203171350000.html

  ■Windows プログラムには必ず WinMain() 関数から開始する
    http://archive.mag2.com/0000240151/20080209215231000.html

  ■プログラムは関数の集まり
  ■プログラムは関数を増やしてソフトウェアを作る
  ■関数には次の要素がある(名前・機能・引数・戻り値)
    http://archive.mag2.com/0000240151/20080216090000000.html
  ■関数を作には次の要素を決める(名前・機能・引数・戻り値)
    http://archive.mag2.com/0000240151/20080608200909000.html

  ■プログラムはソースコードを分散させて大きなソフトを作る
    http://archive.mag2.com/0000240151/20080525121425000.html
    http://archive.mag2.com/0000240151/20080531212858000.html

  ■ゲームを作るためには「入力」「出力」「条件分岐」が必要
    http://archive.mag2.com/0000240151/20080301221623000.html

  ■画像ファイルの絵を画面に表示する際にはメモリに読み込む
   http://archive.mag2.com/0000240151/20080406202024000.html

  ■LoadImage() 関数はコピペで使い回せる
  ■LoadImage() 関数の第2引数は
    メモリに読み込みたい画像ファイルの名前を渡す
  ■LoadImage() 関数で読み込むファイルは
    プロジェクトディレクトリにおいてある必要がある
    http://archive.mag2.com/0000240151/20080413174135000.html

┌┬─────┬─────────────────────────┬┐
││ あとがき │  発行者のつぶやきです                            ││
└┴─────┴─────────────────────────┴┘

 ゲームプログラミング関連の書籍執筆に入りました。

 実用書と言えば実用書なのですが、テーマがゲームですので

 どれだけ冊数が出るのか見当も付きません。

 5,000 部くらい作るのでしょうか?

 まさか同人誌を作る前に書籍を作ることになろうとは…

┌┬───────────────────────────────┬┐
├┘                                                              └┤
│  購読の解除はこちら↓                                            │
│  http://www.game-create.com/contents/gp_beginners_ml             │
├┐                                                              ┌┤
└┴───────────────────────────────┴┘
                            - Ads space -
┌┬───────────────────────────────┬┐
├┘                                                              └┤
│ 「挫折不可能!初級ゲームプログラミング完全マニュアル」は、       │
│ 「いちばんやさしいゲームの作り方」が運営しています。             │
│                                                                  │
│  サイト     : http://www.game-create.com/                        │
│  発行元     : http://www.game-create.com/menu/about              │
│  発行者     : http://www.game-create.com/menu/profile            │
│  問い合わせ : http://www.game-create.com/menu/contact            │
│  利用規約   : http://www.game-create.com/informations/agreement  │
├┐                                                              ┌┤
└┴───────────────────────────────┴┘
                 POWERED BY LIBERTIASTER GAME STYLE.
最新号をメルマガでお届け
登録 解除

規約に同意して

登録した方には、まぐまぐの公式メルマガ(無料)をお届けします。

最近の記事

上へ戻る