Comments
Description
Transcript
夏休みゲームプログラミング講座 配布資料
2010 夏休みゲームプログラミング講座 配布資料 目次 第1回 作業環境の構築 ................................................................................................................ 3 1. 第一回の講義内容 ................................................................................................................... 3 2. Visual C++ 2010 Express のダウンロード ............................................................................ 3 3. Visual C++ 2010 Express のインストール ........................................................................... 4 4. DX ライブラリのダウンロード ............................................................................................... 4 5. DX ライブラリのインストール ............................................................................................... 4 6. プロジェクトの作製 ............................................................................................................... 5 7. プロジェクトの設定 ............................................................................................................... 6 8. テストウィンドウの表示 ........................................................................................................ 9 9. 終わりに ............................................................................................................................... 10 10. 第2回 参考サイト ........................................................................................................................ 10 ゲームプログラムの構造、画像の表示、キー入力 ......................................................... 10 11. ゲームプログラムの構造 ................................................................................................... 10 12. 画像の表示方法 ................................................................................................................. 12 13. 画像の動かし方 ................................................................................................................. 15 14. キー入力による操作 .......................................................................................................... 18 第3回 弾の発射、連射、敵の出現の作成 ................................................................................. 21 15. 弾の発射............................................................................................................................ 21 16. 弾の連射............................................................................................................................ 26 17. 敵の出現............................................................................................................................ 31 第4回 当たり判定とタイトル画面の作成 ................................................................................. 35 18. 当たり判定 ........................................................................................................................ 35 19. タイトル画面..................................................................................................................... 38 第5回 BGM、効果音の演奏 構造体の導入 ......................................................................... 43 20. BGM の演奏 ...................................................................................................................... 43 21. 効果音をつける ................................................................................................................. 44 22. 構造体 ............................................................................................................................... 45 企画書とゲーム素材の作成 ............................................................................................ 47 第6回 23. ゲーム企画・仕様書作成 ................................................................................................... 48 24. ゲーム素材作成 ................................................................................................................. 49 25. お勧めのゲーム制作ツール ............................................................................................... 49 プログラム設計図の作成................................................................................................ 50 第7回 26. プログラムの設計図とは ................................................................................................... 50 27. サンプル STG フローチャート .......................................................................................... 51 28. フローチャートを使ってソースコードを書く ................................................................... 52 ゲームファイルの作成 ................................................................................................... 52 第8回 29. 完成したゲームの「exe ファイル化」............................................................................... 52 簡易 C 言語資料 .............................................................................................................................. 54 参考文献 ......................................................................................................................................... 59 第1回 作業環境の構築 1. 第一回の講義内容 第一回の講義では開発環境の設定を行う。具体的には C 言語ソフトウェア開発ツールである VisualC++2010Express(以下 VC++)のインストールと DirectX 等を簡単に使うことのできるゲーム ライブラリ、DX ライブラリのセットを行う。 本日の達成目標は VC++でゲームのウィンドウ画面を表示することである。まずは資料を読み、次 に周りの人に聞き、それでもわからない場合は SA に聞くこと。 2. Visual C++ 2010 Express のダウンロード 1. Microsoft VisualStudio ホームページへ行く google で(VisualC++2010)のキーワードで検索する、もしくは このアドレス( http://www.microsoft.com/japan/msdn/vstudio/express/ 2. Visual C++ 2010 Express Web インストール(ダウンロード)をクリック 3. 保存先をデスクトップに指定してダウンロード )を入力する 3. Visual C++ 2010 Express のインストール 1. DL した「VC_web.exe」を実行 2. セットアップへようこそ 「次へ」をクリック マイクロソフトにフィードバックを送信するかどうかは任意でチェックを入れる 3. ライセンス条項 「同意する」にチェックを入れ 4. コピー先フォルダー 「インストール」をクリック 「次へ」をクリック インストールするフォルダはデフォルトのままで OK 5. ダウンロードとインストールの進行状況 時間が経過すると自動で次の画面へ移動 インストールには時間がかかるため、その間に DX ライブラリのインストールを行う 6. セットアップの完了 「終了」をクリック 注意:VC++は製品登録(無料)をしないと 30 日で使用できなくなる。製品登録は VC++のヘル プから行えるので後で製品登録を行うこと。 4. DX ライブラリのダウンロード 1. DX ライブラリのホームページへ行く google で(DX ライブラリ)のキーワードで検索する、もしくは このアドレス( http://homepage2.nifty.com/natupaji/DxLib/index.html )を入力する 2. DX ライブラリのダウンロードページへ行く 3. DXライブラリ VisualC++用(Ver3.03)をダウンロードする 4. 保存先をデスクトップに指定してダウンロード をクリック 5. DX ライブラリのインストール 1. DL した「DxLib_VC3_03.exe」を実行 2. ファイルを展開します 次へをクリック 3. 展開先のフォルダを指定してください 4. 展開を開始します 次へをクリック 5. 展開中… 展開が完了すると自動で次へ進む 6. 展開が完了しました 完了をクリック 7. デスクトップに出来上がった「DxLib_VC」フォルダを C ドライブ(C:¥)に移す 展開先をデスクトップに指定し次へをクリック 6. プロジェクトの作製 1. VC++を起動する デフォルト設定の場合、スタートメニューすべてのプログラム項目の中に 「Microsoft Visual C++ 2010 Express」の項目があるのでそこから起動する 2. 「ファイル」 → 「新規作成」 → 「プロジェクト」 と選択する 新規プロジェクトの開き方 3. 「Win32 プロジェクト」を選択し、「プロジェクト名」を付け、 「ソリューションのディレクトリを作製」チェックをはずして OK をクリックする Win32 プロジェクトが見つからない場合は左のインストールされたテンプレート欄で Win32 を選択する。プロジェクトの場所はデフォルト設定の場合「c:¥Users¥ユーザー名 ¥documents¥visual studio 2010¥Projects」となっている。 注意:プロジェクト名は半角英数字で付けること! プロジェクト設定1 4. Win32 アプリケーションウィザードへようこそ 「次へ」 5. アプリケーションの設定 「Windows アプリケーション」 「空のプロジェクト」 に をクリック チェックを入れて完了をクリック 6. プロジェクトが完成したので、次は C++のソースコードを作製する。 「ソリューションエクスプローラー」→「ソースコードを右クリック」→「追加→新しい項目」 ソリューションエクスプローラーが表示されない場合は「表示」→「その他のウィンドウ」→ 「ソリューションエクスプローラー」で表示することができる。 ソースコードの作製 7. 新しい項目の追加 「C++ファイル」を選択し、 「名前を付けて」 「追加」をクリック 注意:ソースコード名は半角英数字でつけること! 8. ソースコードの完成 7. プロジェクトの設定 1. 「プロジェクト(P)」→「(プロジェクト名)のプロパティ(P)」を開く プロパティの開き方 2. 左側のリストから「構成プロパティ」を選択し、構成(C):を「アクティブ(Debug)」から 「すべての構成」にする 構成の変更 3. 「構成プロパティ」→「全般」を選択し、 文字セットを「マルチバイト文字セットを使用する」に変更する 文字セットの変更 注意:画像では「Unicode 文字セットを使用する」となっているが、設定の際は「マルチバイ ト文字セットを使用する」を選択する 4. 「構成プロパティ」→「C/C++」→「全般」を選択 5. 「追加のインクルードディレクトリ」に DX ライブラリの「プロジェクトに追加すべきファ イル_VC 用」フォルダのアドレスを追加 追加のインクルードディレクトリ 「追加のインクルードディレクトリ」のウィンドウをこのようにして OK をクリックする 6. 「構成プロパティ」→「リンカー」→「全般」を選択 7. 「追加のライブラリディレクトリ」に上と同じように DX ライブラリの 「プロジェクトに追加すべきファイル_VC 用」フォルダのアドレスを追加 8. 構成(C):を「すべての構成」から「Release」にする 9. 「構成プロパティ」→「C/C++」→「コード生成」を選択 10. 「ランタイムライブラリ」の項目を「マルチスレッド(/MT)」に変更する 11. 構成(C):を「Release」から「Debug」にする 12. 「構成プロパティ」→「C/C++」→「コード生成」を選択 13. 「ランタイムライブラリ」の項目を「マルチスレッドデバッグ(/MTd)」に変更する 14. 設定が完了したので 「OK」をクリック 8. テストウィンドウの表示 1. 以下のソースコードを作製した cpp ファイルに書き込む #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode( TRUE ) ; // ウインドウモードに変更 if( DxLib_Init() == -1 ) // DXライブラリ初期化処理 { return -1 ; // エラーが起きたら直ちに終了 } DrawPixel( 320 , 240 , 0xffff ) ; // 点を打つ WaitKey() ; // キー入力待ち DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } 2. 「デバッグ」→「デバッグ開始(S)」を選択、もしくは「F5」を押す 3. 図のウィンドウが表示されれば設定が成功している サンプルウィンドウ 9. 終わりに 以上でゲーム製作に必要な開発環境の設定は完了です。今回は真っ黒な画面が表示されるだけで したが、今後はこのウィンドウにキャラクターや文字数字を配置し、動かしていきます。 ゲーム制作でもっとも必要なものはやる気です。参考サイトを載せておきますので、そのサイト や DX ライブラリのサイトを見てどんどん自分でゲームを作っていってください。 月曜日と木曜日の 15:00~17:00 に 6.306 にてオフィスアワーを行います。わからないことがあっ たら質問に来てください。 10. 参考サイト DX ライブラリ置き場(http://homepage2.nifty.com/natupaji/DxLib/index.html) DX ライブラリ制作者の方のサイト。今後は DX ライブラリの関数リファレンスページから必 要な関数を探し出して使っていくことになる。 C 言語ゲームプログラミングの館(http://dixq.net/g/) DX ライブラリを使ったゲーム制作を一から細かく説明しているサイト。このサイトに記載さ れている内容を試すことで簡単なゲームを作ることができるようになる。 初心者のためのポイント学習 C 言語(http://www9.plala.or.jp/sgwr-t/) C 言語初心者のためのサイト。C 言語でわからないことがあったらまずここを調べてみる。 ProgramingPlace(http://www.geocities.jp/ky_webid/index_old.html) C 言語初心者のためのサイト2。C++の内容まで記載されているため、重宝する。 第2回 ゲームプログラムの構造、画像の表示、キー入力 11. ゲームプログラムの構造 今回の講座で DX ライブラリを用いて作製するゲームは以下のフローチャート順で処理を行っ ていく。この項目ではチャートの一つ一つを順に説明していく。 処理開始 キー入力状況取得 メインループ DXライブラリ初期化 処理 データのロード ゲーム処理 データの解放 画面の更新 DXライブラリの終了 メインループ ウィンドウの メッセージ処理 終了 ゲームフローチャート 1. 処理開始 ゲーム処理の開始地点。DX ライブラリを使ったゲームの場合は毎回同じように記述するた め、既存のソースコードをコピーするだけでいい。 2. DX ライブラリ初期化処理 DX ライブラリの初期化やウィンドウサイズの設定、また、画像の透明色の設定を行う。 3. データのロード ゲームで必要な画像や BGM をこの段階で読み込んでおく。データの読み込みには若干時間 がかかるため、ゲームが動いている最中にロードをするとゲームが一瞬止まってしまう。その ため、最初にまとめてロードしておく必要がある。ゲーム規模が大きくなると全てのデータを 読み込むにはメモリ不足になってしまうので、データを必要とする場面の前にロード時間を設 けてロードし、必要がなくなったら解放するとよい。 4. メインループ ゲームはこのループの中を何度も繰り返し実行することで表現される。ゲームプログラミン グで内容を記述していくのは主にこのループの中である。なお、ループの終了条件(ゲームオ ーバーや Esc キーが押された時等)を記述しておかないと無限ループとなりゲームプログラム が終了しなくなるので注意すること。 5. キー入力状況取得 DX ライブラリを用いたゲームではキーボードやゲームパッド(以下入力端子)を通してゲー ムを操作する。ここではこの処理が実行された瞬間の入力端子の状況を記憶する。例えばキー ボードの Z キーが押されている状態である、ということを記憶しておく。ゲーム中ではその情 報を使いゲームを操作する。1 回前のループの入力端子の状態を記憶しておくことでキーが押 しっぱなしなのか、押され始めた状態なのかを判断することもできる。例えば、1 回前が押さ れている状態で現在も押されている状態ならばキーは放されていないと判断できる。 6. ゲーム処理 ここにゲームの処理を書きこんで行く。例えば STG ゲームの自機を動かしたり、ACT ゲー ムの主人公を飛び跳ねさせたりする。 7. 画面の更新 ゲームの画像を表示する場合はまず画面に描いてある物をすべて消去し、次にキャラクター 等を次々と描画していく。すると毎フレームごとに画面が消えて尐しずつ描きたされていく様 子がプレイヤーの目に映ってしまう。これを回避するためにダブルバッファリングという技術 を使用する。この技術はディスプレイに表示しない部分(裏画面)でゲーム画面を描画し、全て の描画が完了してできあがった画面のみをディスプレイに表示するという技術である。画面の 更新ではゲーム処理で描画された裏画面をディスプレイに表示する。 8. ウィンドウのメッセージ処理 Windows 環境でのソフトプログラムに付きまとう メッセージループ処理を肩代わりする 処理。この処理が何をしているかは特に気にする必要はないが、ループ 1 回につき 1 度この処 理を行わないとパソコンの処理が極端に遅くなる可能性がある。 9. データの解放 読み込んだ画像等のデータは解放しないといつまでもパソコンの中に残ってしまう。そのた め、読み込んだデータの解放を行う。 10. DX ライブラリの終了 DX ライブラリの終了とともにプログラムを終了する。 12. 画像の表示方法 第一回の講義で何も表示されていない真っ黒なウィンドウを生成することができた。次はこの ウィンドウに画像を表示してみる。 //画像表示ソースコードサンプル #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int GHandle ; // グラフィックハンドルを入れる変数を宣言 ChangeWindowMode( TRUE ) ; //ウィンドウモードに変更 if( DxLib_Init() == -1 ) // DXライブラリ初期化処理 return -1; GHandle = LoadGraph( "test.bmp" ) ; // エラーが起きたら直ちに終了 // test.bmp 画像のメモリへの読みこみ DrawGraph( 200 , 150 , GHandle , TRUE) ;// (0,0)座標に画像を表示 WaitKey() ; // キーの入力待ち InitGraph(); // 画像の解放 DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } test.bmp test.bmp を VC++のプロジェクトファイルと同じディレクトリに移し、実行する。 (デフォルト設定の場合、画像を入れるディレクトリは C:¥Users¥(ユーザー名)¥Documents¥Visual Studio 2010¥Projects¥(プロジェクト名) となる) 実行すると図のようなウィンドウが表示され、 キー入力もしくはクリックをすると閉じる。 画面に画像が表示されない場合は test.bmp を 保存する場所を間違えている可能性がある。 ソースコード中の太字で表示してある部分が 画像の表示に必要な部分である。 画像表示サンプル実行画面 //画像表示に必要なコードの解説---------------------------------------------------------------------------------int ○○○; //画像ハンドルを入れる変数の宣言 ○○○ = LoadGraph( "△△△.bmp" ) ; //画像のロード DrawGraph( x 座標 , y 座標 , ○○○ , TRUE ) ; //(x,y)座標に画像の描画 InitGraph() ; //全画像の解放 //---------------------------------------------------------------------------------------------------------------------------ゲーム中で表示する画像は HDD からメモリに読み込み、必要な時にメモリから読みだして表示 する。そのため、LoadGraph 関数で画像をメモリに読み込む必要がある。読み込みが成功すると戻 り値としてグラフィックハンドル(画像識別番号)が返ってくる。なお、LoadGraph 関数をループな どで何度も呼びだすとメモリを急激に使用し、PC の動作が停止する可能性があるので注意すること。 メモリに読み込んだ画像は InitGraph 関数で解放するまでグラフィックハンドルを通して使用す ることができる。DrawGraph 関数の引数としてグラフィックハンドルを渡すと、画面に画像を表示 することができる。なお、DrawGraph 関数の TRUE という引数は透過色の設定である。デフォル トでは RGB(0,0,0)が透過色に設定されているため、黒い部分は表示されない。 練習1: 図のように同じ画像を2つずつ2か所に表示せよ ヒント:変数は 2 つだけ宣言し、LoadGraph 関数は 2回だけ使用すること。InitGraph 関数は1度使用す るだけで全ての画像を解放するため、1度使用するだ けで構わない。 練習1 実行画面サンプル 13. 画像の動かし方 //画像の動かし方 サンプルソースコード #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { //DXライブラリ初期化処理---------------------------------------------------------------------------------------------------ChangeWindowMode( TRUE ) ;//ウィンドウモードに変更 if( DxLib_Init() == -1 ) // DXライブラリ初期化処理 return -1; // エラーが起きたら直ちに終了 SetDrawScreen( DX_SCREEN_BACK );//画面を裏画面にセット //データのロード-------------------------------------------------------------------------------------------------------------------char Key[256]; //キーの入力状況を記録する変数を宣言 int x=0, y=100; //画像の表示位置を記録する変数を宣言 int GHandle ; //グラフィックハンドルを入れる変数を宣言 GHandle = LoadGraph( "test.bmp" ) ; // BMP画像のメモリへの読みこみ //メインループ=================================================================== for(;;) { //キー入力状況取得---------------------------------------------------------------------------------------------------GetHitKeyStateAll(Key); //キーボードのすべてのキーの押下状態を Key に記録する //ゲーム処理------------------------------------------------------------------------------------------------------------x += 2; //画像の表示位置を右方向に2ずらす y += 1; //画像の表示位置を下方向に1ずらす DrawGraph(x, y, GHandle, TRUE); //画像を(x,y)座標に表示する //終了処理--------------------------------------------------------------------------------------------------------------if(Key[KEY_INPUT_ESCAPE] == 1) break; //ESC キーが押されているか判断 //押されている場合、ループを抜ける //画面の更新---------------------------------------------------------------------------------------------------------ScreenFlip(); //裏画面を表画面に反映する ClearDrawScreen(); //裏画面に描かれたものを全て消去 //ウィンドウのメッセージ処理-----------------------------------------------------------------------------------if(ProcessMessage() == -1) //ウィンドウのメッセージ処理 { break; //ウィンドウのメッセージ処理にエラーが発生した場合ループを抜ける } } //データの解放--------------------------------------------------------------------------------------------------------------------InitGraph(); // 画像の解放 //DXライブラリの終了---------------------------------------------------------------------------------------------------------DxLib_End() ; return 0 ; // DXライブラリ使用の終了処理 // ソフトの終了 } 動かす画像は画像表示の際に使用した「test.bmp」を使う。 画像を動かすにあたり重要な部分を太字で記述してある。 このソースコードは改造して今後も使うため、消さずに残しておくこと サンプルコード実行画面 「test.bmp」が右下の方へ動いて行く。 ESCキーを押すと終了する。 画像を表示することができたので、次は表示した画像を動かしてみる。ゲームで画像が動いてい るように見える仕組みは映画やビデオと同じく、尐しずつ違う画像を連続して見せることで動きを 表現するというものである。この項目では画像の表示位置を尐しずつずらし、そのつど描画を行う ことで画像が動く様子を作製する。 なお、今回からゲームプログラムの構造に沿った形でソースコードを記述していく。そのため新 しい内容が一気に増えているが、この項目では画像を動かすために必要な部分だけ解説する。 SetDrawScreen( DX_SCREEN_BACK ); //画面を裏画面にセット DXライブラリがダブルバッファリングを行うように設定する。この処理を記述していないと ダブルバッファリングが行われず画面がちらついてしまう。ダブルバッファリングについての説 明は「2.7 画面の更新」に記載してある。 int x=0, y=100; //画像の表示位置を記録する変数を宣言 画像の表示位置となるx、yの2つの変数を宣言し、それぞれ0と100の数字を代入してい る。そのため、画像の初期表示座標は(0,100)となる。 x += 2; //画像の表示位置を右方向に2ずらす y += 1; //画像の表示位置を下方向に1ずらす DrawGraph(x, y, GHandle, TRUE); //画像を(x,y)座標に表示する x、yの値にそれぞれ2、1を加算している。この処理はメインループの中にあるため、何度 も繰り返し実行される。そのため、ループの1回目はxが 102、yが 1 となり、2回目はxが 104、 y が 2 というように尐しずつ画像の表示座標がずれて表示される。 ScreenFlip(); //裏画面を表画面に反映する この関数が実行されたときにダブルバッファリングのために裏画面(ディスプレイに表示されな い部分)で描画されていた内容が表画面(ディスプレイ)に表示される。 ClearDrawScreen(); //裏画面に描かれたものを全て消去 この関数を実行しないと前のフレームの画像が残ったまま次のフレームで描画が開始されてし まう。 練習2: サンプルソースコードを改造し、画面端まで移動し た画像が逆側の端に移動し、ループするようにせよ ヒント:if()を使用し、x、yの値が画面の幅より大き くなった場合に0を代入することでループするように みせることができる。 画面横幅:640 画面縦幅:480 練習2 実行画面サンプル 14. キー入力による操作 //キー入力による操作 サンプルソースコード #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { //DXライブラリ初期化処理------------------------------------------------------------------------------------//データのロード---------------------------------------------------------------------------------------------------char Key[256]; //キーの入力状況を記録する配列を宣言 int x=0, y=100; //画像の表示位置を記録する変数を宣言 int GHandle ; //グラフィックハンドルを入れる変数を宣言 GHandle = LoadGraph( "test.bmp" ) ; // BMP画像のメモリへの読みこみ for(;;) //メインループ======================================================== { //キー入力状況取得--------------------------------------------------------------------------------------------GetHitKeyStateAll(Key); //キーボードのすべてのキーの押下状態を Key に記録する //ゲーム処理-----------------------------------------------------------------------------------------------------if(Key[KEY_INPUT_LEFT] == 1) //左が押されている場合 { x -= 1; //画像を左方向へずらす } if(Key[KEY_INPUT_RIGHT] == 1) //右が押されている場合 { x += 1; //画像を右方向へずらす } x += 2; //画像の表示位置を右方向に2ずらす y += 1; //画像の表示位置を下方向に1ずらす DrawGraph(x, y, GHandle, TRUE); //画像を(x,y)座標に表示する //終了処理----------------------------------------------------------------------------------------------------------//画面の更新---------------------------------------------------------------------------------------------------------//ウィンドウのメッセージ処理-----------------------------------------------------------------------------------} //データの解放------------------------------------------------------------------------------------------------------------------//DXライブラリの終了-----------------------------------------------------------------------------------------------------} 前項目のソースコードから変更のない DX ライブラリの初期化処理などは記述を省略してある 動かす画像は画像表示の際に使用した「test.bmp」を使う。 キー入力による操作にあたり重要な部分を太字で記述してある。 このソースコードは改造して今後も使うため、消さずに残しておくこと 図 サンプルコード実行画面 左右のキーのうち入力した方向へ画像が移動する 画像を表示して動かすだけでアニメや映画と変わらない。次は画像をプレイヤーの手で動かせる ようにする。サンプルではキーボードの左キーが押されている場合は画像が左に移動し、右キーが 押されている場合が右に移動するようになっている。 DXライブラリの機能にはゲームパッドの状態をキーボードと同じように取得することのできる 機能があるため、ゲームパッド対応のゲームを作ることもできる。ゲームパッド対応させる方法は DXライブラリリファレンスページ参照を参照すること。 なお、Escキーを押すことでゲームを終了する機能もキー入力による操作を使用している。 char Key[256]; //キーの入力状況を記録する配列を宣言 キーボードの入力状況を記録しておくための変数配列を宣言する。配列とは連続している変数 のことで、ここでは char 型の変数が 256 個並んでいる配列を宣言している。 GetHitKeyStateAll(Key); //キーボードのすべてのキーの押下状態を Key に記録する この関数は実行された時のキーボードの押下状態を配列 Key に保存するものである。この関数 が実行される前は配列 Key にはでたらめな数値が入っている。そのため、この関数が実行される 前に配列 Key の値を参照しようとするとエラーが発生して処理が止まることがあるので注意する こと。 if(Key[KEY_INPUT_LEFT] == 1) //左が押されている場合 { x -= 1; } //画像を左方向へずらす if(Key[KEY_INPUT_RIGHT] == 1) //右が押されている場合 { x += 1; } //画像を右方向へずらす 左キーが押されている場合は画像を左へ1ずらし、右キーが押されている場合は右へ1ずらす。 キーの押下状態は配列 Key[キーコード番号]の値が1になっているかを調べることで知ることが できる。値が1の場合はキーが押されており、0の場合は押されていない。キーコードはDXラ イブラリリファレンスページの CheckHitKey の項目に記載されている。また、主要なキーコード は下記に記す。 主要なキーコード KEY_INPUT_LEFT // 左キー KEY_INPUT_UP // 上キー KEY_INPUT_RIGHT // 右キー KEY_INPUT_DOWN // 下キー KEY_INPUT_RETURN // エンターキー KEY_INPUT_ESCAPE KEY_INPUT_SPACE // スペースキー KEY_INPUT_LSHIFT // 左シフトキー KEY_INPUT_LSHIFT KEY_INPUT_F1 ~ KEY_INPUT_F12 // F1~F12 キー KEY_INPUT_A ~ KEY_INPUT_Z // A~Z キー KEY_INPUT_0 ~ KEY_INPUT_9 // 0~9 キー // エスケープキー // 右シフトキー 練習3:サンプルソースコードを改造し、スペースキーが押されている場合は2倍の速さで移動で きるようにせよ。 ヒント:if()else を使う。スペースキーが押されている場合と押されていない場合とで分岐させ、押 されている場合はずらす値を1、押されていない場合はずらす値を2にする。 第3回 弾の発射、連射、敵の出現の作成 15. 弾の発射 //弾の発射 サンプルソースコード #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { //DXライブラリ初期化処理-----------------------------------------------------------------------------------------------//データのロード--------------------------------------------------------------------------------------------------------------char Key[256]; //キーの入力状況を記録する配列を宣言 int x=0, y=100; //画像の表示位置を記録する変数を宣言 int GHandle ; //グラフィックハンドルを入れる変数を宣言 GHandle = LoadGraph( "test.bmp" ) ; // BMP画像のメモリへの読みこみ int player_graph; //自機画像ハンドル int bullet_graph; //弾画像ハンドル int player_x = 200, player_y = 400; //自機の表示位置 int bullet_x = 0 , bullet_y = 0; //弾の表示位置 int bullet_flag = 0; //弾の存在フラグ 1の時は存在するとし、0の時は消滅とする player_graph = LoadGraph("player.png"); //自機画像を読み込む bullet_graph = LoadGraph("bullet.png"); //弾画像を読み込む //メインループ=============================================================== for(;;) { //キー入力状況取得------------------------------------------------------------------------------------------------ //ゲーム処理=========================================================== //自機の移動処理-------------------------------------------------------------------------------------------if(Key[KEY_INPUT_LEFT] == 1) //左が押されている場合 { x -= 1; //画像を左方向へずらす player_x -= 3; //自機を左方向へ動かす } if(Key[KEY_INPUT_RIGHT] == 1) //右が押されている場合 { x += 1; //画像を右方向へずらす player_x += 3; //自機を右方向へ動かす } //弾の移動処理----------------------------------------------------------------------------------------if(bullet_flag == 1) //弾が存在している時のみ処理を行う { bullet_y -= 3; if(bullet_y < 0) //弾を上方向へ動かす //弾が画面外へ出たか判断 { bullet_flag = 0;//弾を消滅させる } } //弾の発射処理-----------------------------------------------------------------------------------------if(Key[KEY_INPUT_Z] == 1) //Zキーが押されているか判断 { if(bullet_flag == 0) //弾が消滅しているか判断 { bullet_flag = 1; //弾を出現させる bullet_x = player_x; //弾の発射位置を設定する bullet_y = player_y; } } //画像の描画処理---------------------------------------------------------------------------------------------------------DrawGraph(x, y, GHandle, TRUE); //画像を(x,y)座標に表示する DrawGraph(player_x, player_y, player_graph, TRUE); if(bullet_flag == 1) //自機を表示する //弾が存在しているか判断 { DrawGraph(bullet_x, bullet_y, bullet_graph, TRUE); //弾を表示する } //終了処理--------------------------------------------------------------------------------------------------//画面の更新-----------------------------------------------------------------------------------------------//ウィンドウのメッセージ処理-----------------------------------------------------------------------} //データの解放-----------------------------------------------------------------------------------------------//DXライブラリの終了-----------------------------------------------------------------------------------------------} ・このソースコードは「キー入力による操作 サンプルソースコード」を改造したものである ・元のソースコードから削除された部分は 取り消し線 で表示されている。 ・新しく追加された部分は 太字 で表示されている。 ・弾の発射について重要な部分は 網掛け で表示されている。 ・前項目のソースコードから変化のない部分は記述を省略してある ・このソースコードからは今までの仮画像 (test.bmp)ではなく、シューティングゲーム用の画 像 (player.png、bullet.png)を使用する。画像は各自で用意すること。 ・サンプルで使用した画像 図 2 図 1 弾画像(bullet.png) 自機画像(player.png) ・実行画面 図 3 実行画面サンプル ・キーボードの左右のキーでキャラクターを移動させることができる。 ・ESCキーを押すと終了する ・Zキーを押すと弾が自機から発射される。 ただし、弾が画面内に存在しているときは弾を発射することができない ・弾は発射されると一定速度で上へ移動し、画面枠に接触すると消滅する 画像の表示方法と動かし方はわかった。ここからは簡単なシューティングゲームを作っていく。 まずはキー入力による操作で左右に動かしたグラフィックを自機として、自機から弾を発射できる ようにする。 なお、サンプルのソースコードでは読み取りやすくするためにゲーム処理内の処理ごとに「//-------」 でわけ、自機の座標や画像ハンドルの変数名に player_を付けている。 int bullet_flag = 0; 弾の存在フラグとして bullet_flag という変数を用意する。この変数の値が1の時は弾が存在す るものとして、弾の移動や表示の処理がされる。また、弾が存在するときに弾が発射されるとす でに存在する弾が途中で消えて次弾となってしまう。その問題を解決するため、弾の存在フラグ が0の時しか弾を発射することができないようにする。 弾の移動処理 まず、弾が存在する時のみこの処理は行われる。次に今回作製するシューティングゲームでは 弾は上方向にしか移動しない。そのため、弾の移動は弾のy座標を減らすことでだけである。 弾は発射されたあと、画面外へ出て行ったときに消滅する。画面外へ出たかの判断は弾の座標 が画面外かどうかで判断する。弾が画面外へ出ている時に存在フラグを0とすることで弾は消滅 したことになる。この条件を変化させることで射程の短い弾や敵にあたると消滅する弾を作るこ とができる。 弾の発射処理 弾が発射される条件は2つある。まず、攻撃キーが押されている時であること。もうひとつは 弾が画面上に存在しないことである。弾が画面上に存在しないとは bullet_flag が 0 である時であ る。2つの条件を満たしているときに発射処理は実行される。 弾の発射をゲームとして表現するにはどのようにしたらよいか? サンプルコードでは弾を画 面に表示させ、弾の座標を自機座標と同じにすることで表現する。 練習4:弾を発射するボタンを増やし、ボタンによって違う弾が発射されるようにせよ ヒント:違う弾とは弾速や画像の違いで表現することができる。 16. 弾の連射 //弾の連射 サンプルソースコード #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { //DXライブラリ初期化処理 //データのロード char Key[256]; //キーの入力状況を記録する配列を宣言 int player_graph; //自機画像ハンドル int bullet_graph; //弾画像ハンドル int player_x = 200, player_y = 400; //自機の表示位置 int bullet_x = 0;, bullet_y = 0; //弾の表示位置 int bullet_flag = 0; //弾の存在フラグ int bullet_x[20], bullet_y[20]; //弾の表示位置20個 int bullet_flag[20]/; //弾の存在フラグ20個 int cool_time=0; //次弾発射までの時間 int i=0; //for 文回転用変数 for(i=0; i<20; i+=1){ //それぞれの弾の変数に初期値を入れる bullet_x[i] = 0; bullet_y[i] = 0; bullet_flag[i] = 0; } player_graph = LoadGraph("player.png"); //自機画像を読み込む bullet_graph = LoadGraph("bullet.png"); //弾画像を読み込む //メインループ============================================================ for(;;){ //キー入力状況取得--------------------------------------------------------------------//ゲーム処理======================================================== //自機の移動処理------------------------------------------------------------------------------------------- //弾の移動処理---------------------------------------------------------------------------------------------for(i=0; i<20; i += 1) //弾は20発あるのでループを20回行う{ if(bullet_flag[i] == 1){ //弾が存在している時のみ処理を行う bullet_y[i] -= 3; //弾を上方向へ動かす if(bullet_y[i] < 0){ //弾が画面外へ出たか判断 bullet_flag[i] = 0; //弾を消滅させる } } } //弾の発射処理------------------------------------------------------------------------------------------if(Key[KEY_INPUT_Z] == 1){ //Zキーが押されているか判断 if(cool_time < 0){ //次弾が発射できない期間が0より小さい場合のみ弾を発射 for(i=0; i<20; i+=1){ //20発ある弾のうち、発射可能な弾を調べる if(bullet_flag[i] == 0){ break; //弾が発射可能 //ここでループを抜けると //変数 i には発射可能な弾の番号が入っている } } if(bullet_flag == 0){ //弾が消滅しているか判断 if(i < 20){ //全ての弾が発射状態の場合、i は20になる。 //i が20より小さい場合のみ処理を行う cool_time = 5; //次弾が発射できない期間を設定 bullet_flag[i] = 1; //弾を出現させる bullet_x[i] = player_x; //弾の発射位置を設定する bullet_y[i] = player_y; } } } } cool_time -= 1; //次弾発射までのカウントを減らす //画像の表示処理--------------------------------------------------------------------DrawGraph(player_x, player_y, player_graph, TRUE); for(i=0; i<20; i+=1) //自機を表示する //弾20発の分だけ処理を行う { if(bullet_flag[i] == 1) //弾が存在しているか判断 { DrawGraph(bullet_x[i], bullet_y[i], bullet_graph, TRUE); //弾を表示する } } //終了処理-------------------------------------------------------------------------//画面の更新-----------------------------------------------------------------------//ウィンドウのメッセージ処理-----------------------------------------------------} //データの解放-------------------------------------------------------------------------//DXライブラリの終了-------------------------------------------------------------------------} ・このソースコードは「弾の発射 サンプルソースコード」を改造したものである ・元のソースコードから削除された部分は 取り消し線 で表示されている。 ・新しく追加された部分は 太字 で表示されている。 ・重要な部分は 網掛け で表示されている。 ・前項目のソースコードから変化のない部分は記述を省略してある ・このソースコードでは全体の行数を短くするため、下記のように「if」や「for」の「{ }」の頭の位置を 「()」の直後にしてある。 if(i==1){ } ↑このように記述してある ・キーボードの左右のキーでキャラクターを移動 させることができる。 ・ESCキーを押すと終了する ・Zキーを押している間、弾が連射される ・弾は最大20発同時に表示され、20発以上 発射しようとしても弾が発射されない サンプルコード実行画面 弾を発射することができるようになったが、現段階では1発ずつしか発射することができない。 この項目では配列を使い、弾を連射することができるようにする。配列を応用することで弾だけで なく、数多く出現する敵キャラなども作ることができるようになる。 配列を使った弾の変数 bullet_x[20], bullet_y[20], bullet_flag[20]; 弾の座標、フラグを配列を使って20発分作製する。配列については別紙「簡易プログラミン グ資料」参照のこと。なお、弾の画像ハンドルはロードした弾の画像が1つだけのため、ひとつ でいい。 ループを使った配列の初期化 int i=0; for(i=0; i<20; i+=1){ bullet_x[i] = 0; bullet_f[i] = 0; bullet_flag[i] = 0; } 20回繰り返されるループ。{ }の中の処理を i の数値を 0~19 まで変化させながら 20 回繰り返 される。 弾が 20 発になったため、初期値を入力するためには「bullet_x[0]=0; bullet_x[1]=0…」と 20 回も入力しなくてはならなくなった。それではソースコードが無駄に長くなってしまうため、20 回繰り返すループを使用して初期値を入れる。 弾の移動や弾の描画の部分でも同じようにループが使われ、20 回分の処理が行われている。 弾の発射間隔の調整 int cool_time; if(cool_time < 0){ } cool_time = 5; cool_time -= 1; cool_time は弾を発射してから次の弾が発射可能になるまでの時間である。cool_time は毎フレ ームごとに cool_time -= 1; で値が減っていく。弾が発射されると cool_time の値は 5 となり、次 のフレームで 4、次で 3、2、1、0…と減っていく。弾が発射可能なのは cool_time の値が0以下 の時としておくことで、5 フレームの間弾が発射を不可能にすることができる。 発射する弾の選択 for(i=0; i<20; i+=1){ if(bullet_flag[i] == 0){ break; } } 弾を発射するとき、どの弾を発射するかを決めている。0番から 19 番まである弾を0番から一 つずつ発射可能か調べていき、発射可能な弾を見つけるとその場でループ(for(i=0; i<20; i+=1){ } のこと)を抜ける。 ループを抜けた時の i の番号の弾は発射可能であるため、 i 番目の弾を発射する。 全ての弾が発射できない場合、ループは 20 回実行され、i の値は 20 となる。弾は 0~19 番ま での 20 発であるため、i が 20 だと存在しない弾を指定しまう。そのため「if( i < 20)」という条 件を加えて 20 以上の配列番号を指定しないようにしている。 右図を弾の配列とする。灰色の部分が画面に存在して おり発射不可能の弾とし、白い部分が発射可能の弾とす る。この配列の場合、for(;;)文は以下のようになる。 for( i=0; i<10 ; i+=1){ 処理 } パターンAの場合は 0 番が発射可能のため、i=0 でル ープを抜け、0 番の弾が発射される。 0 1 2 3 4 5 6 7 8 9 A B C D E パターン B の場合は 0 番が不可能、1 番が不可能と一 図 発射する弾の選択例 つ一つ確認していき、6 番の時点で発射可能となり、i=6 でループを抜ける。パターン C では 0 番、パターン D では 2 番の弾が発射される。 パターンEの場合は 0 番、1 番、と調べていき、9 番を調べる。その後、i+=1 で i は 10 となり、 i<10 の条件を満たさなくなりループを抜ける。処理を抜けた段階で i は 10 となっており、存在し ない弾を指定していることとなるが、存在しない弾は発射されないようになっているため、弾は 発射されない。 練習5:サンプルではボタンを押している間、常に弾を発射し続ける。そこで、サンプルを改造 してボタンを一度押したときには一発の弾しか発射されないようにせよ。なお、弾を連射したい 場合はボタンを連打することで連射できるようにすること。 ヒント:キーが押されているか判断するとき int Key[256] int old_Key[256] 判断結果 に使われている Key 配列だが、Key 配列ひと ○ ○ 押し続けている ○ × 押し始めた × ○ 放された直後 × × 放されている つではボタンが押しているか放されているか の2つの情報しか得ることができない。そこ で、Key 配列と同じ大きさを持つ名前の違う 配列(例えば old_Key)を作り、そこに 1 フレ 2 つの配列を使ったキーの状態判断表 ーム前の Key 配列の状態を保存する。キーが 押されているかを判断するところで二つの配列の状態を調べることでキーが押され続けている、 押し始めである、放した、放されている、の 4 つの状態を知ることができる。 ボタンを一度押したときには 1 発の弾しか発射されないことは、弾の発射条件を押し始めの時 に限定することで実現できる。 注意:この方法を使う場合、最初のフレームでは old_Key 配列には値が入っていない。その状 態で old_Key 配列の値を参照しようとするとエラーが発生してしまう。そのため、配列を宣言し た後でループを回して old_Key に初期値(0)を入れておく必要がある。 17. 敵の出現 //敵の出現 サンプルソースコード #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){ //DXライブラリ初期化処理--------------------------------------------------------------------//データのロード int enemy_graph; //敵画像ハンドル int enemy_x[10], enemy_y[10]; //敵の表示位置10個 int enemy_flag[10]; //敵の存在フラグ10個 int enemy_counter=0; //敵の出現タイミングをはかるためのカウンター for(i=0; i<10; i+=1){ //それぞれの敵の変数に初期値を入れる enemy_x[i] = 0; enemy_y[i] = 0; enemy_flag[i] = 0; } enemy_graph = LoadGraph("enemy.png"); //敵画像を読み込む //メインループ=============================================================== for(;;){ //キー入力状況取得----------------------------------------------------------------------------------------//ゲーム処理======================================================= //自機の移動処理----------------------------------------------------------------------------------------------//弾の移動処理------------------------------------------------------------------------------------------------//敵の移動処理-----------------------------------------------------------------------------------------------for(i=0; i<10; i+=1){ if(enemy_flag[i] == 1){ //敵が存在している時のみ処理を行う enemy_y[i] += 2; //敵を下方向へ動かす if(enemy_y[i] > 480){ //敵が画面外へ出たか判断 enemy_flag[i] = 0; //敵を消滅させる } } } //弾の発射処理---------------------------------------------------------------------------------------------------//敵の出現処理------------------------------------------------------------------------------------------------------if(enemy_counter%30 == 0){ //30 カウントごとに処理を行う for(i=0; i<10; i+=1){ //弾の発射と同じく 10 体の敵の中から出現可能な敵を調べる if(enemy_flag[i] == 0){ break; } } if(i < 10){ //全ての敵が出現できない場合、 //i は10になっている。i が10より小さい場合のみ処理を行う enemy_flag[i] = 1; //敵を出現させる enemy_x[i] = GetRand(640); //敵のx座標を //0~640 までの値からランダムに決定する enemy_y[i] = 0; //敵の出現位置は画面上端のため、y座標は0とする } } enemy_counter += 1; //---------------------------------------------------------------------------------------------------------------------------- //画像の表示処理----------------------------------------------------------------------------------------for(i=0; i<10; i+=1){ //敵 10 体分だけ処理を行う if(enemy_flag[i] == 1){ //敵が存在しているか判断 DrawGraph(enemy_x[i], enemy_y[i], enemy_graph, TRUE); //敵を表示する } } //終了処理-------------------------------------------------------------------------------------------------//画面の更新----------------------------------------------------------------------------------------------//ウィンドウのメッセージ処理----------------------------------------------------------------------} //データの解放---------------------------------------------------------------------------------------------------------//DXライブラリの終了---------------------------------------------------------------------------------------------} このソースコードから新たに敵画像(“enemy.png”)を使用する。画像は各自で用意 すること。 図 4 enemy.png ・このソースコードは「弾の連射 サンプルソースコード」を改造したものである ・元のソースコードから削除された部分は 取り消し線 で表示されている。 ・新しく追加された部分は 太字 で表示されている。 ・重要な部分は 網掛け で表示されている。 ・前項目から変化のない部分は省略してある。 ・画像のロード、画像の表示処理も一部省略してある。 ・このソースコードでは全体の行数を短くするため、下記のように「if」や「for」の「{ }」の頭の位置を 「()」の直後にしてある。 if(i==1){ } ↑このように記述してある ・キーボードの左右のキーでキャラクターを移動させる ことができる。 ・ESCキーを押すと終了する ・Zキーを押している間、弾が連射される ・弾は最大20発同時に表示され、20発以上発射しよ うとしても弾が発射されない ・0.5 秒ごとに画面上端から敵が降ってくる。 ・敵は下方向へのみ移動し、画面下端に消えると消滅す る ・敵はあたり判定をもっておらず、自機や弾が触れても サンプルコード実行画面 なにもおこらない この項目では敵を出現させる。敵は画面上端からランダムに出現し下方向に移動していき、画面 の下端を越すと消滅する。また、この段階ではあたり判定は作製しないため、敵は自機や弾をすり 抜けて移動していく。 敵の処理は基本的に弾と同じである。弾との違いは下方向へ移動すること、消滅方法、出現方法、 出現座標の指定方法だけである。そのため、解説する部分は弾との違いの部分だけとする。 敵の消滅 弾は上方向へ移動し(y -= 3)、画面の上端を超える(y < 0)と消滅した。敵の場合もほぼ同じで下 方向へ移動し(y += 2)、画面の下端を超える(y > 480)と消滅する。なお、480 とはデフォルト設定 の時の画面の縦幅のことである。ちなみに横幅は 640 であり、これらの幅は DX ライブラリの SetWindowSizeExtendRate 関数で変更することができる。詳しくはDXライブラリのリファレ ンスを参照すること。 カウンターを用いた一定間隔ごとの敵の出現 if(enemy_counter%30 == 0){ //30 カウントごとに処理を行う 「%30」とは「30で割った余り」という意味である。毎フレーム 1 ずつ増加していく enemy_counter を30で割った場合、その余りは 0、1、2…28、29、0、1、2、…と0~29ま での値を繰り返すことになる。そのため、余りが0となるのは 30 フレームに1度となり、 enemy_counter%30==0 は 30 カウントごとに処理が行われることとなる。 乱数を用いた敵の出現座標の設定 enemy_x[i] = GetRand(640); //敵のx座標を 0~640 までの値からランダムに決定する GetRand 関数は0から引数で指定した数値までのどれかの数値を返す関数である。そのため、 enemy_x には 0~640 までの値のどれかが入る。また、敵の y 座標は 0 としてあるため、敵の出 現座標は x 座標が 0~640、y座標が 0 となり、敵は画面上部からランダムに出現することになる。 練習6:サンプルコードを改造し、一定時間後にボス敵が出現するようにせよ。また、ボスキャラ クターは通常の敵とは違う動きをして画面に残り続けるようにすること。 ヒント:なし。各自で好みのボス敵を作ること。 第4回 当たり判定とタイトル画面の作成 18. 当たり判定 //あたり判定 サンプルソースコード //DX ライブラリ初期化------------------------------------------------------------------------------------------------------------------//データのロード------------------------------------------------------------------------------------------------------------------int player_size_x = 40; //プレイヤーあたり判定サイズx int player_size_y = 30; //プレイヤーあたり判定サイズy int bullet_size_x = 10; //弾あたり判定サイズx int bullet_size_y = 10; //弾あたり判定サイズy int enemy_size_x = 40; //敵あたり判定サイズx int enemy_size_y = 40; //敵あたり判定サイズy int j=0; //for 文回転用変数2 //メインループ========================================================================= for(;;){ //キー入力状況取得------------------------------------------------------------------------------------------------------------------//ゲーム処理--------------------------------------------------------------------------------------------------------------------------- //あたり判定処理-------------------------------------------------------------------------------------------------------------------//弾と敵^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ for(i=0; i<20; i+=1){ //弾の回数分処理を行う for(j=0; j<10; j+=1){ //敵の回数分処理を行う //敵と弾が両方とも存在している場合 if(bullet_flag[i] == 1 && enemy_flag[j] == 1){ //あたり判定の判断 if(bullet_x[i] < enemy_x[j] + enemy_size_x && bullet_x[i] + bullet_size_x > enemy_x[j] && bullet_y[i] < enemy_y[j] + enemy_size_y && bullet_y[i] + bullet_size_y > enemy_y[j]){ bullet_flag[i] = 0; //命中したので弾を消す enemy_flag[j] = 0; //命中したので敵を消す } } } } //敵と自機 for(i=0; i<10; i+=1){ //敵の回数分処理を行う if(enemy_flag[i] == 1){ //敵が存在している場合 //あたり判定の判断 if(enemy_x[i] < player_x + player_size_x && enemy_x[i] + enemy_size_x > player_x && enemy_y[i] < player_y + player_size_y && enemy_y[i] + enemy_size_y > player_y){ enemy_flag[i] = 0; //命中したので敵を消す //自機に攻撃が命中したが、 //命中した後の処理を作っていないため //現段階ではなにも記述しない } } } //--------------------------------------------------------------------------------------------------------------------} ・このソースコードは「敵の出現 サンプルソースコード」に追記するものである ・新しく追加された部分は 太字 で表示されている。 ・重要な部分は 網掛け で表示されている。 ・このソースコードは全体の行数を尐なくするため「敵の出現」までのソースコードをほぼ省略してい る。 ・キーボードの左右のキーでキャラクターを移動させることができる。 ・ESCキーを押すと終了する ・Zキーを押している間、弾が連射される ・弾は最大20発同時に表示され、20発以上発射しようとしても弾が発射されない ・0.5 秒ごとに画面上端から敵が降ってくる。 ・敵は下方向へのみ移動し、画面下端に消えると消滅する ・敵が弾にあたると敵と弾の両方が消滅する ・敵が自機にあたると弾が消えるが、自機にはなにもおこらない あたり判定の判別方法は2つの四角形が重なっ ているかどうかで判断する。範囲が重なっている とは ・左上の座標が相手の右下の座標より左上にある ・右下の座標が相手の左上の座標より右下にある の2つの条件を同時に満たしている状態をさす。 まずはAとDのx座標に注目する。Aの左上の x座標は 26 で、右下のx座標は 85 である。そし てDの左上のx座標は 65 で右下のx座標は 117 だ。条件である「左上の座標が相手の右下の座標 当たり判定例 より左上にある」をx座標に注目してみると、 「A の左がDの右より小さい」 「Aの右がDの左より大きい」図のAとDの場合、Aの左は 26 でDの 右の 117 より小さく、A の右の 85 は D の左の 65 より大きい。そのため、x座標で比べるとAと Dは重なっていると言える。この条件式と同じことをy座標でも行い、両方が正しい場合2つの 矩形は重なっており、あたり判定はあたっていると言える。 ソースコード中では「bullet_x[i] < enemy_x[j] + enemy_size_x &&」として表現されている。 bullet_x[i]は矩形の左端のx座標、enemy_x[j] + enemy_size_x は矩形の右端のx座標を意味して いる。&&は両方の条件が正しい場合のみ正しいとう条件文(A && B ではAとBの両方がただしく ないと正しいと判断されない)である。 なお、DrawGraph 関数で画像を表示する際は画像の左上の座標が指定した座標となる。画像の 右端や下端の座標を求める場合は「指定した座標+画像の幅」で座標を得ることができる。 練習7:矩形ではなく対象との直線距離を用いたあた り判定を実装せよ ヒント:直線距離を用いたあたり判定は矩形の重なり によるあたり判定よりも仕組みが簡単である。 右図の場合、Cの長さが2つの円の半径の合計より短 ければ当たっている、長ければ当たっていないという仕 組みである。Cの長さは(A の2乗+Bの2乗)の平方根 を求めることで得ることができる。 計算式で表すならば、 A*A + B*B < (赤の半径+青の半径) * (赤の半径+青の半径) が正しい場合、あたっていると表現される。 円を用いた当たり判定 19. タイトル画面 //タイトル画面 サンプルソースコード //DXライブラリ初期化処理------------------------------------------------------------------------------------------------------------//データのロード--------------------------------------------------------------------------------------------------------------------------int game_state = 0; //ゲームの状態 int white = GetColor(255, 255, 255); //白色データ char OldKey[256]; //1フレーム前のキーの入力状況を記録する配列 for(i=0; i<256; i+=1){ //Key、OldKey 配列の全ての変数に0を入れる Key[i] = 0; OldKey[i] = 0; } for(;;){ //メインループ================================================================== //キー入力状況取得------------------------------------------------------------------------------------------------------------for(i=0; i<256; i+=1){ //1 フレーム前のキー状況をコピー OldKey[i] = Key[i]; } GetHitKeyStateAll(Key); //キーボードのすべてのキーの押下状態を Key に記録する //ゲーム処理=============================================================== switch(game_state){ case 0: //ゲームの状態ごとに処理をわける //タイトル処理^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SetFontSize(32); //フォントサイズの設定 DrawString(100, 100, "サンプル☆シューティング", white);//タイトルの表示 SetFontSize(16); //フォントサイズの設定 DrawString(100, 400, "Z キーを押すと開始します", white); //開始方法の表示 if(Key[KEY_INPUT_Z] == 1 && OldKey[KEY_INPUT_Z] != 1){//Zキーが押されている場合 game_state = 1; //ゲーム処理へ移行 } break; case 1: //タイトル処理終了 //ゲーム処理^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //自機の移動処理------------------------------------------//弾の移動処理---------------------------------------------//敵の移動処理---------------------------------------------//弾の発射処理---------------------------------------------//敵の出現処理---------------------------------------------//あたり判定処理-------------------------------------------//---------------------------------------------------------break; //ゲーム処理終了 case 2: //ゲームオーバー処理^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SetFontSize(26); //フォントサイズの設定 DrawString(100, 300, "ゲームオーバー", white);//タイトルの表示 if(Key[KEY_INPUT_Z] == 1 && OldKey[KEY_INPUT_Z] != 1){//Zキーが押されている場合 //初期化処理 for(i=0; i<20; i+=1){ //弾の全消去 bullet_flag[i] = 0; } for(i=0; i<10; i+=1){ //敵の全消去 enemy_flag[i] = 0; } player_x = 200; //自機の初期位置の設定 player_y = 400; //自機の初期位置の設定 game_state = 0; //ゲーム処理へ移行 } break; default: //ゲームオーバー処理終了 //タイトル、ゲーム、ゲームオーバー以外の状態の処理 break; //それ以外の状態処理終了 } //終了処理------------------------------------------------------------------------------------------------------------//画面の更新---------------------------------------------------------------------------------------------------------//ウィンドウのメッセージ処理---------------------------------------------------------------------------------} ・このソースコードは「あたり判定 サンプルソースコード」に追記するものである ・新しく追加された部分は 太字 で表示されている ・重要な部分は 網掛け で表示されている ・このソースコードは全体の行数を尐なくするため「あたり判定」までのソースコードをほ ぼ省略している。ただし、新しく追記する部分をわかりやすくするため一部省略せずに残し ているため注意すること。 ・キーボードの左右のキーでキャラクターを移動させることができる。 ・ESCキーを押すと終了する ・Zキーを押している間、弾が連射される ・弾は最大20発同時に表示され、20発以上発射しようとしても弾が発射されない ・0.5 秒ごとに画面上端から敵が降ってくる。 ・敵は下方向へのみ移動し、画面下端に消えると消滅する ・敵が弾にあたると敵と弾の両方が消滅する ・ゲームを開始するとタイトル画面が表示され、Zキーが押されるとゲームが開始される ・自機が敵とあたるとゲームオーバー画面が表示される ・ゲームオーバー画面でZキーが押されるとタイトル画面に戻る 図 5 ゲーム画面移行図 自機が動き、弾を撃ち、敵を撃墜できる。現段階でシューティングゲームはほぼ完成していると 言える。この項目ではゲームにタイトル画面とゲームオーバー画面を追加し、自機と敵が衝突した 時にはゲームオーバー画面に移行するようにする。そして、この項目を終えた段階でサンプルのシ ューティングゲームは完成したものとする。 ゲームの状態分け ゲームの状態をタイトル、ゲーム、ゲームオーバーの3つの状態にわけ、処理を状態ごとにわけ る。ゲームの状態は「int game_state」に記憶しておき、game_state の値が 0 の時はタイトル処理、 1 の時はゲーム処理、2 の時はゲームオーバー処理を行うものとする。 ゲームの状態を分けるときに使われている「swich(game_state){}」について説明をする。これは swicth 文といい、 「( )」内の変数の値により「{ }」内の処理を分ける文である。 「( )」内の変数 の値と同じ「case 値:」の部分へ処理が移る(case に同じ値がない場合は default の処理へ処理が移 る)。そして、 「break;」 の部分で switch 文を抜ける。なお、case の後の処理の最後に「break;」が ない場合、次にある case の中の処理も実行してしまうため注意すること。 右の例の場合 int a=0; ・ 「a」の値が0の場合:処理0と処理1が実行される switch( a ){ ・「a」の値が1の場合:処理1が実行される case 0: //処理0 ・「a」の値が2の場合:処理2が実行される ・「a」の値が 200 の場合:処理2が実行される case 1: //処理1 break; default: //処理2 break; } 文字の表示 「DrawString( x座標, y座標, “表示する文字”, 文字色);」 DrawString 関数を使うことで画面に文字を描画することができる。関数の引数は上記のとおり である。文字色は「GetColor(R 値, G 値, B 値)」関数で得ることができる。サンプルでは「int white」に「white = GetColor(255, 255, 255);」で白い色の値を入れている。 なお、 「DrawFormatString」関数を使うことで変数の値を文字として表示することもできる。 この機能を使うことでゲームのスコアを表示することもできる。 Key 配列を2つ使ったキー入力 第2回の項目 14 練習③を参照 練習8:ゲームを開始し、一定時間自機が敵に接触せずに生き残ると「ゲームクリア」と表示され るクリア画面へ移行するようにせよ。 ヒント:ゲーム状態へ移行した後に1フレームごとに1ずつ値が増加していくカウンターを作り、 その値が一定値以上になった時にゲーム状態をクリア状態へ移行するようにする。クリア状態の画 面はゲームオーバー状態の文字が違うだけで構わない。 第5回 BGM、効果音の演奏 構造体の導入 講義資料④まで終わらせた時点でサンプルのゲームは完成している。講義資料⑤では必 須ではないが、あると便利な機能を紹介する。それぞれの機能は独立しているため、現在 のソースコードに追加するだけで使うことができる。 全ての項目を実践する必要はないので、必要な項目のみ実践すること。 20. BGM の演奏 サンプルソースコード PlaySoundFile( "test.mp3" , DX_PLAYTYPE_LOOP) ; for(;;){ //「test.mp3」の演奏 //メインループ //省略 } StopSoundFile(); //BGMの演奏停止 この項目では BGM(バックグラウンドミュージック)を再生できるようにする。BGM はゲームの 雰囲気を伝え、プレイヤーをゲームに引き込むための非常に重要な要素である。 DXライブラリでは mp3、wav、Ogg のファイル形式の音声ファイルを BGM として演奏するこ とができる。DXライブラリの機能の中には BGM のボリュームやパンの設定を行えるものもある が、この講義では解説しない。必要ならば DX ライブラリのリファレンスを参照して使用すること。 PlaySoundFile(“test.mp3”, DX_PLAYTYPE_LOOP); PlaySoundFile(再生する音声ファイル , 再生形式); 再生する音声ファイル: 画像を表示する時と同じように project ファイル内に保存した音声ファイル名 再生形式: DX_PLAYTYPE_NORMAL ノーマル再生 音声ファイルの再生が終了するまで処理を止める DX_PLAYTYPE_BACK バックグラウンド再生 他の処理を実行しながら音声ファイルを再生する。音声ファイルはループしない DX_PLAYTYPE_LOOP ループ再生 バックグラウンド再生と同じだが、音声ファイルがループする ゲームの BGM は基本的にループさせ、停止命令を出すまで演奏し続けるため、BGM の再生形式 はループ再生にする。 StopSoundFile(); BGM を停止させる処理。 よくあるミス メインループの中で PlaySoundFile 関数を毎フレーム呼び出してしまい、音声ファイルの最初 の一瞬のみが再生され続け、結果としてなにも聞こえないというミスがよくある。PlaySoundFile 関数を呼び出す場所はタイトルパートからゲームパートに変わる瞬間などにして、1度だけ呼び 出すようにすること。 21. 効果音をつける サンプルソースコード int se_handle; //効果音ハンドルを入れる変数 se_handle = LoadSoundMem(“test.wav”); //効果音を読みとる for(;;){ //メインループ //省略 PlaySoundMem( se_handle , DX_PLAYTYPE_BACK ) ; //効果音の演奏 } InitSoundMem(); //効果音の解放 この項目では効果音を鳴らすことができるようにする。シューティングゲームでは自機が弾を発 射した時や弾が敵に命中した時などに効果音を鳴らすことでゲームを盛り上げることができる。 DXライブラリでの効果音の扱い方は画像の扱い方と同じである。変数を用意し、そこにロード したファイルのハンドルを入れ、使いたいところでハンドルを使って使用する。そして最後はロー ドしたファイルを解放する。 また、SEを再生する方法は前項目で行った BGM の再生と同じである。BGM との違いは2点あ り、ひとつは再生形式がループ再生ではなくバックグラウンド再生になっていること。そしてもう ひとつは音声ファイルを先に読み込んでいることである。音声ファイルの読み込みには時間がかか るため、効果音のように頻繁に使用される音声ファイルは先にメモリに読み込んでおき、読み込み 時間を短縮するほうがいい。 LoadSoundMem(“test.wav”); 画像表示の際の LoadGraph 関数とほぼ同じ仕様。 PlaySoundMem(se_handle, DX_PLAYTYPE_BACK); 効果音を演奏したいときに呼びだす。DX_PLAYTYPE_BACK については前項目の音声ファイ ルの再生方式を参照すること。 InitSoundMem(); 画像表示の際の InitGraph 関数とほぼ同じ仕様。 22. 構造体 構造体とは 複数の変数データをまとめて一つのデータとして扱う方法。この方法を使うことで変数をまと めてソースコードを見やすくすることができる。 構造体の書き方 struct 構造体型名{ //構造体の定義 変数型 変数名; //構造体の中身の定義 }; int WINAPI WinMain(省略){ struct 構造体型名 構造体名; 構造体名.変数名; //構造体の定義 //構造体内の変数の使い方 return 0; } 構造体を使用する場合、WinMain 関数の前にどのような構造体なのかを定義する。そして WinMain 関数の中で定義した構造体を変数のように宣言することで構造体の中にある変数をま とめて管理することができるのである。 サンプルソースコード #include "DxLib.h" struct obj{ int x, y; //座標 int flag; //存在フラグ int size_x, size_y;//あたり判定サイズ }; int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){ //DXライブラリ初期化処理 //省略 //データのロード int player_graph; //自機画像ハンドル int bullet_graph; //弾画像ハンドル int enemy_graph; //敵画像ハンドル int player_x = 200, player_y = 400; //自機の表示位置 int bullet_x[20], bullet_y[20]; //弾の表示位置20個 int bullet_flag[20]; //弾の存在フラグ20個 int cool_time=0; //次弾発射までの時間 int enemy_x[10], enemy_y[10]; //敵の表示位置20個 int enemy_flag[10]; //敵の存在フラグ20個 int enemy_counter=0; //敵の出現タイミングをはかるためのカウンター int player_size_x = 40; //プレイヤーあたり判定サイズx int player_size_y = 30; //プレイヤーあたり判定サイズy int bullet_size_x = 10; //弾あたり判定サイズx int bullet_size_y = 10; //弾あたり判定サイズy int enemy_size_x = 40; //敵あたり判定サイズx int enemy_size_y = 40; //敵あたり判定サイズy struct obj player; //プレイヤーの宣言 struct obj bullet[20]; //弾を 20 発宣言 struct obj enemy[10]; //敵を 10 体宣言 player.x = 200; //自機に初期座標を入れる player.y = 400; //自機に初期座標を入れる player.flag = 1; //使用しないがプレイヤーフラグに初期値を入れる player.size_x = 40; //プレイヤーあたり判定サイズを入れる player.size_y = 40; //プレイヤーあたり判定サイズを入れる for(i=0; i<20; i+=1){ //弾20発分の初期値を入れる bullet[i].x = 0; //省略 } for(i=0; i<10; i+=1){ //敵10体分の初期値を入れる //省略 } //省略 for(;;){ //メインループ //省略 DrawGraph(player_x, player_y, player_graph, TRUE); //自機を表示する DrawGraph(player.x, player.y, player_graph, TRUE); //自機を表示する //省略 } //省略 自機、弾、敵がそれぞれ持つ座標、存在フラグ、あたり判定サイズを構造体としてまとめた。 そのため、いままでそれぞれの変数を使っていた部分を全て構造体に書き変える必要がある。ソ ースコード中では一部を除き書き変える部分も省略してある。 構造体の使い方 サンプルソースコードのように共通する変数をまとめることで管理しやすくする。構造体は座 標系をまとめた物以外にも RPG の主人公ステータスやパズルゲームのマスごとの情報など、様々 なところで使うことができる。さらに構造体の中に構造体を入れることもできる。 第6回 企画書とゲーム素材の作成 ゲーム作りフロー ゲームのアイデアを考える 企画書・仕様書を作って何を作るのか決める プログラムの設計図を書く ゲームプログラムを打ち込む テスト、調整 ゲーム完成 ゲームの素材を作る、集める 23. ゲーム企画・仕様書作成 1. ゲーム企画書とは ゲームの企画書とは、これからどんなゲームを作るかを他人に説明する書類である。一人で ゲームを制作する場合は必ずしも企画書を作る必要はないが、どんなゲームを作るのかを具体 的に考えるために企画書を作ることは有効である。 2. ゲームの概要、ルールを考える まず、どんなゲームを作りたいのかを考える。たとえば、 「できるだけ単純で簡単に作れる STG」や「ドラゴンクエストとポケットモンスターのおもしろいところを掛け合わせた RPG」 などである。いくつかの概要を考え、その内容を深く掘り下げていく。その際に考えた内容は できる限りメモにとっておくこと。 3. ゲーム画面のイメージを描き出す 次にやるべきことはゲーム画面のイメージを描きだ すことである。頭の中でもやもやとしているものを視 覚的に表現することでこれから作るゲームがどんなゲ ームなのかをより具体的に考えることができるように なる。ここで描きだした物はあくまでも初期案である ため、後々変更していくことになっても構わない。 4. ゲームの仕様決定 どんなゲーム画面になるかが決まったら、次はゲー ゲーム画面デザイン ムの仕様を決めていく。例えば ・自機は左右にしか移動できない ・弾はボタンを押している間連射することができる ・敵はランダムに出現し、下方向にのみ移動する ・自機の画像はサイズが 40,40pix でファイル名は player.bmp である などが仕様である。仕様はできるだけ細かく決めておいた方が後々変更などが起きなくてよい。 5. 企画書の作製 ゲーム画面と仕様が決定し、どんなゲームを作るかが決まったら、それを他人に説明できる ように企画書を作製する。企画書は書式や形式は決まっておらず、それを読んだ人がどんなゲ ームなのかを理解できればどんな形式でも構わない。 なお、今回の講座では企画書と仕様書は同じものとする。そのため、企画書の中に各種仕様 も書きこんでおくこと。 24. ゲーム素材作成 1. ゲーム素材とは ゲーム素材とはゲーム中で使う画像や音声ファイルなどのことである。ゲームは素材を通し てプレイヤーの目や耳に入るため、ゲームの素材はゲームのイメージを決定づけると言っても 過言ではない。そのため、ゲームのイメージに合った物を調達する必要がある。 ゲーム素材は自分で作る、インターネット等から素材を集める、協力者に制作を依頼するな どして集める方法がある。 2. インターネットのフリー素材 インターネットにはフリー素材として数多くの素材があるため、その中からゲームのイメー ジに合ったデータをダウンロードしてきて使う。 この方法で素材を集める場合、著作権に気をつける必要がある。ここでは著作権に対しての 詳細な説明は省くが、制作者の許可なく制作物を使用することは犯罪であることを意識するこ と。 3. 自作する ペイントやフォトショップ等のお絵描きソフトを使い画像を 作る。SSW や初音ミクなどの DTM ソフトを使って音楽を作る。 こうして自分の力で素材を作り、それをゲームに使う。 画像作りに便利なお絵描きソフトを「お勧めのゲーム制作ツ 自作画像 ール」の項目にまとめてある。もちろん、自分の使いなれてい るツールがあるのならばそちらを使っても構わない。 4. 協力者につくってもらう 絵を描ける友人や音楽を作れる友人にゲームの素材を作ってもらう。相手にどんなゲームを 作るのかをきちんと説明すること。 25. お勧めのゲーム制作ツール 1. 画像作製 Gimp フリーで PhotoShop なみの機能を持った画像編集ソフトウェア。 Pixia レイヤ機能などを備えた高機能なペイント/フォトレタッチソフト。数多く公開されて いるプラグインにより様々な機能拡張が可能。 EDGE 256 色専用のドット絵エディタ。初心者でも使いやすい。 2. BGM作製 Music Studio Producer MIDI も AUDIO も使えて、各種エフェクター、ミキサーや波形編集等も備えているの で、DTM 初心者には十分のソフト。ダウンロードサイトは日本のサイトで、説明書もダ ウンロードできるので問題なく使っていける。 ACID Xpress ループシーケンス系 DAW、ACID のフリーウェア版です。ドラッグ&ドロップするだ けの簡単操作で曲が作れます。 3. ゲームエディタ RPG ツクールシリーズ 有名なゲームエディタソフト。スクリプト言語を使うことでオリジナリティあふれるゲ ームを作ることもできる。 WOLF RPG エディター フリーの RPG ツクールとでもいうべきソフト。ただし、RPG ツクールと比べて自由度 が高く、若干上級者向けである。 第7回 プログラム設計図の作成 26. プログラムの設計図とは プログラムを組むことはプラモデルを組み立てることと似ている。DX ライブラリの DrawGraph などの関数はプラモデルのパーツのようなものだ。関数を組み合わせてゲ ームを組み立てる。 プラモデルに設計図が必要なようにプログラムにも設計図が必要である。設計図を見 ながら作ることで自分が今どの部分を作っており、この先どのように作ればいいのかを 知ることができる。ある程度以上の規模のソースコードを組む際は設計図を書いておく とプログラム作製が効率的になり、時間的効率があがる。 プログラムの設計図には様々な種類や方法があるが、今回の講座ではフローチャート を採用する。今回の講座でフローチャートを書く目的はプログラムの設計図を作りプロ グラム全体の流れを知ることであるため、フローチャートの正式な書き方の説明は省く。 フローチャートの作製には Excel を使う。セルに処理を行う順に処理内容を書いて行 き、色や囲いをつけて見やすくすることでフローチャートとする。 27. サンプル STG フローチャート 開始 0:タイトル処理 1:ゲーム処理 2:ゲームオーバー処理 DX ライブラリの初期化 開始 開始 開始 データのロード 文字表示 自機の移動処理 文字表示 メインループ Z キーが押された場合 弾の移動処理 Z キーが押された ゲーム状態を キー入力状況取得 敵の移動処理 ゲーム処理へ移す データの初期化 弾の発射処理 ゲーム処理により分岐 ゲーム状態をタイトル処 分岐終了 敵の出現処理 理へ あたり判定処理 分岐終了 0:タイトル処理 1:ゲーム処理 2:ゲームオーバー処理 終了 タイトルパート 弾-敵 フロー 終了 ESC が押されていたら ループを抜ける 画面の更新 あたり判定処理 敵-自機 描画処理 終了 ウィンドウのメッセージ処理 ゲームパートフロー メインループ終了 データ解放 DX ライブラリの終了 終了 メインフロー ゲームオーバーパートフロー 28. フローチャートを使ってソースコードを書く フローチャートが完成したらフローチャートを参考にソースコードを作製する。コメント機能 (//コメント)を使い、処理の前にフローチャートのどの部分に対応しているかを書いていく。 フローチャートを無視したソースコードを作製するとフローチャートの信用性がなくなりフロー チャートの意味がなくなってしまうため、必ずフローチャート通りにソースコードを作製すること。 フローチャートの通りに組めない場合はフローチャートを書きなおしてからソースコードを作製す ること。 例 //描画処理----------------------------------------------------------------------------------------------------DrawGraph(player_x, player_y, player_graph, TRUE); //自機を表示する for(i=0; i<20; i+=1){ //弾20発の分だけ処理を行う if(bullet_flag[i] == 1){ //弾が存在しているか判断 DrawGraph(bullet_x[i], bullet_y[i], bullet_graph, TRUE); //弾を表示する } } for(i=0; i<10; i+=1){ //敵 10 体分だけ処理を行う if(enemy_flag[i] == 1){ //敵が存在しているか判断 DrawGraph(enemy_x[i], enemy_y[i], enemy_graph, TRUE); //敵を表示する } } 第8回 ゲームファイルの作成 29. 完成したゲームの「exe ファイル化」 現状ではゲームをプレイするためには VC++でプロジェクトファイルを開き、デバッグをしなけ ればならない。しかしそれでは VC++が入っている PC でしかゲームがプレイできない。 そこで、この項目では完成したゲームを実行ファイル(exe ファイル)として出力し、以下の動作環 境を満たした全てのマシンで動かすことができるようにする方法を説明する。 動作環境 Windows98 以降の OS 動作環境 DirectX9 以降 32MB 以上の空きメモリ ソリューション構成を「Debug」から「Release」にする 操作1 デバッグする 操作2 デバッグ後はソリューション構成を Debug に戻しておくこと。なお、Debug ではなくソリュ ーションのビルドやデバッグなしで開始でも exe ファイルは出力される。 「Release」フォルダ内に exe ファイルが出力されている exe ファイルの場所1 exe ファイルの場所2 exe ファイル以外にも多数のファイルが入っているが、exe ファイル以外のファイルがなくても 正常に動作する。そのため、別のフォルダに exe ファイルだけを移しても正常に動作する。 exe ファイルを入れたフォルダと同じフォルダに素材ファイルを入れる 画像や音声ファイルは exe ファイルと同じディレクトリに存在しないと読み込まない。その ため、exe ファイルと同じフォルダに素材ファイルを入れる。 以上でゲームファイルの完成とする。 簡易 C 言語資料 C 言語プログラミングのお約束 1. プログラムの開始、終了 C言語のプログラムはメイン関数と呼ばれるところから始まる。DXライブラリを使ったゲ ームプログラミングの場合、開始位置は int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){ の直後からである。 終了場所はメイン文の{ } の中にある「return 0;」である。 2. 「;」セミコロン C 言語プログラミングの場合、文章の最後には「;」を付けなければいけない。 「;」は命令の 終わりを意味しており、 「;」がくるまでは改行があってもひとつの命令という意味になる。 3. 使える文字 C 言語プログラミングではコメント部分を除いて全角文字を使うことができない。使える文 字は全て半角英数字である。 4. コメント コメントとはプログラムのソースコード上に記述するメモ書きである。 「//」の後から行末ま での間はコメント扱いとなり、プログラムの内容として扱われない。また、 「//」以外にも */」の間もコメントとして扱われる。VC++の場合、コメント部分は文字の色が変わ 「/* る。 変数 1. int ____; 変数とは プログラムのデータ(数値等)を記憶しておくもの。ゲームのキャラクターの座標、ゲーム中 に表示する文字データなど、全てのデータは変数としてパソコンのメモリ上に記憶されている。 2. 変数の書き方 変数を作る時: 変数の種類 変数の名前; 例:int test; (「int」が変数の種類 「test」が変数の名前) 変数に値を入れる時: 変数の名前 演算子 値; 例:test = 25; (「test」が変数の種類 「=」が演算子(代入) 「25」が値) この例の場合、変数 test に 25 という値を入れるという意味になる 3. 変数の使い方 値を入れられた変数は数値と同じように使うことができる。 例:int test1 = 30; int test2 =0; test = test2; この処理の場合、test2 には 30 の値が入る。 4. 変数の種類 表 変数種類表 int 整数型 数字が入る変数 char 文字型 文字(半角英数字)や短い数値が入る変数 float 単精度実数型 少数がある数字が入る変数 double 倍精度実数型 使える桁数が増えた float long 使える桁数が増えた int 表 演算子一覧表 = 配列 1. 倍長整数型 代入 a = 5; a は 5 + 加算 a = 5 + 5; a は 10 - 減算 a = 5 - 5; a は 0 * 乗算 a = 5 * 5; a は 25 / 除算 a = 5 / 5; a は 1 % 剰余 a = 7 % 5; a は 2 int ____[__]; 配列とは 変数に番号を付けたもの。たくさんいる敵キャラクターや弾などに使う。 2. 配列の書き方使い方 配列を作る時: 変数の種類 変数の名前[ 変数の数 ]; 例:int enemy_x[ 30 ]; (int 型の enemy_x という変数が 30 個できあがった。番号は 0~29 番と振られている) 配列を使う時: 変数の名前[ 変数の番号 ]; とすることで通常の変数と同じように扱える。 例:enemy_x[ 0 ] = 30 ; (enemy_x の 0 番目の変数に 30 を入れた) 条件分岐 1. if(____){ } 条件分岐とは 処理を条件に従い分岐させること。たとえばある変数の値が20以上か19以下かで処理を 分ける時などに使う。 2. 条件分岐の書き方 if( 条件式 ){ 処理 } else { 処理 } 例:if( player_x <= 0 ){ player_x = 0; } (player_x という変数が0以下の場合、player_x に 0 を入れる) 例2:if( player_x >= 640 ){ player_hp = 0; }else{ player_hp += 50; } (player_x という変数が 640 以上の場合、player_x は0になり、それ以外の場合 player_x は 50 が加算される) 3. 条件式の種類 表 条件式一覧表 A == B A と B が同じ A != B A と B が違う A<B A が B より小さい A>B A が B より大きい A <= B A が B 以下 A >= B A が B 以上 ループ 1. for(___; ___; ___){ } ループとは 何度も繰り返し実行される処理のことである。ゲームのメインループや配列の全ての番号に 値を入れる時などに使う。 2. ループの書き方 for(処理1 ; 条件式 ; 処理3) { 処理2 } 処理1 → 条件式 → 処理2 → 処理3 → 条件式 → 処理2 →処理3 → ・・・ 条件式が間違っている場合は処理2へ行かずにループを抜ける。条件式は if と同じように使う ことができる。 例:for( i=0; i<20; i += 1){ enemy_x[ i ] += 1; } (enemy_x の 0 番から 19 番までの全ての変数に1が加算される) 関数 1. 関数とは 引数を与えることでその値になんらかの処理をして値を戻り値として返すもの。DXライブ ラリはたくさんの関数が詰まったセットのようなものである。 2. 関数の書き方使い方 関数名( 引数 ); 例:DrawGraph( 0 , 0 , GHandle , TRUE ) ; DrawGraph が関数名、( )の中が引数である。 例:color = GetColor( 255, 255, 255 ); 変数 color に R255,G255,B255 の色の色番号が戻り値として入る。 デバッグとよくあるミス 1. デバッグとは プログラムのバグを探す行為の事。プログラミングの半分以上がデバッグ作業である。 2. ソースコードのミスの探し方 VC++ではソースコードをビルドした時(F5、F7 を押した時もしくはデバッグ、ビルドを選 択した時)にソースコードが間違っていると出力ウィンドウに error として原因の行番号、対処 方法が出力される。一つのミスが多くの error を誘発している場合もあるため、一番上の error から一つずつ解消していくといい。 3. よくあるソースコードのミス ・ 「;」が抜けている ・関数の引数の入れ方が違う 文字を入れるところに数字を入れているなど ・スペルミス DrawGraph を DrowGraph と書いてしまうなど 第一回目の講座ででた質問 ソースコードが動かない include ファイルを開けません。”DxLib.h” 追加のインクルードディレクトリ、追加のライブラリディレクトリの設定が間違って いる。(資料① 7.5 7.7) '0x3000': この文字を識別子で使用することはできません 全角スペースがソースコード中に記述されている。メモ帳等にソースコードを記述し、 それをコピーしてソースコードに張り付けることをしても発生する様子。ソースコード 中の全てのスペースを消すことで解消することができる。 “~~~~” 定義されていない識別子です 誤字、脱字等の理由で識別子が認識されていない。エラーが示す行に誤字脱字がない かもう一度よく調べる。 構文エラー : 識別子 '~~~' 誤字、脱字等の理由で識別子が認識されていない。エラーが示す行に誤字脱字がないか もう一度よく調べる。 左側 中かっこ '{' に対応するものが '~~~' で見つかる前に EOF が検出されまし た。 「{ }」の閉じ忘れ。エラーが示す「{ }」が閉じられているか確認する。 識別子が見つかりませんでした 誤字、脱字等の理由で識別子が認識されていない。エラーが示す行に誤字脱字がない かもう一度よく調べる。 新しいプロジェクトを作ったがまた設定をしなければならないのか? 新しくプロジェクトを作った場合はもう一度設定をしなければならない。 新しいソースコードをどこに書けばいいか? ・新しくプロジェクトを作製する。 ・現在のソースコードをすべてコメントアウトして新しく書きこむ。 コメントアウトのやり方:コメントにする行数を選択(全てコメントアウトする場合は全 選択)して VC++のコメントアウトボタンを押す ・打ち込んだソースコードをすべて切り取り、メモ帳などにコピーし、新しく書きこむ。 参考文献 Microsoft Visual Studio Express ( http://www.microsoft.com/japan/msdn/vstudio/express/#top )<2010/08/09 アクセス> DX ライブラリ置き場 ( http://homepage2.nifty.com/natupaji/DxLib/index.html )<2010/08/12 アクセス> C 言語ゲームプログラミングの館 ( http://dixq.net/g/ ) <2010/08/12 アクセス> 初心者のためのポイント学習 C 言語 ( http://www9.plala.or.jp/sgwr-t/ ) <2010/08/12 アクセス> ProgramingPlace ( http://www.geocities.jp/ky_webid/index_old.html ) <2010/08/12 アクセス>