著者:原口 莉奈
私は最近、RPG(Role-Playing Game)の戦闘シーンをC++言語で作成しました。作成には、無償で利用できるゲーム開発用ライブラリ「DXライブラリ」(https://dxlib.xsrv.jp/)を用いています。今回は、その一部であるコマンド選択画面の実装について紹介します。
シェルスクリプトマガジン Vol.93は以下のリンク先でご購入できます。
図2 ビルド用のバッチファイル「build.bat」に記述する内容
1 2 3 4 5 6 |
g++ -c Main.cpp -DDX_GCC_COMPILE -I"DxLib" g++ -o game.exe Main.o -L"DxLib" -lgcc -lDxLib -lDxUseCLib ^ -lDxDrawFunc -ljpeg -lpng -lzlib -ltiff -ltheora_static ^ -lvorbis_static -lvorbisfile_static -logg_static ^ -lbulletdynamics -lbulletcollision -lbulletmath -lopusfile ^ -lopus -lsilk_common -lcelt |
図3 「Main.cpp」ファイルに記述するコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#define WIN_X 256 #define WIN_Y 224 #include <DxLib.h> int WINAPI WinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR IpCmdLine, _In_ int nShowCmd) { ChangeWindowMode(TRUE); DxLib_Init(); // ウィンドウ初期化 SetWindowText("game"); // タイトル SetGraphMode(WIN_X, WIN_Y, 32); // 解像度と色深度 SetBackgroundColor(255, 255, 255); // 背景色 WaitKey(); DxLib_End(); return 0; } |
図5 「Main.cpp」ファイルに記述するコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#define WIN_X 256 #define WIN_Y 224 #include <DxLib.h> #include "Status.h" #include "Battle.h" int WINAPI WinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR IpCmdLine, _In_ int nShowCmd) { ChangeWindowMode(TRUE); DxLib_Init(); SetWindowText("game"); SetGraphMode(WIN_X, WIN_Y, 32); SetBackgroundColor(255, 255, 255); SetDrawScreen(DX_SCREEN_BACK); // 裏画面描画 SetWindowSize(1024, 960); // ウィンドウサイズ Battle.materialLoad(); while (ProcessMessage() == 0) { SetBackgroundColor(0, 0, 0); Battle.BattleDraw(); } DxLib_End(); return 0; } |
図6 「Status.h」ファイルに記述するコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
class BATTLE { public: struct Status { char name[50]; int HP, ATK, DEF; //体力、攻撃力、防御力 }; struct Status player = { "player",30, 10, 5 }; struct Status villain = { "villain",30, 7, 5 }; struct Status* Player = &player; const char* str[4] = { "たたかう", "まもる", "どうぐ", "にげる" }; const char* item[1] = { "回復" }; int firstsym = 80; int sym = firstsym; int sym_limit = firstsym + (4 - 1) * 17; int symbol = -1, symnext = 0; int pattern = 1; int firstarrow = 80; int arrow = firstarrow; int limit; // firstarrow + (num - 1) * 17 int a_posi = -1; int re = 0; int black, white, ms; void materialLoad(); void BattleDraw(); void one(); void two(); void Choices(int x, const char* str[], int n); private: }; |
図7 「Battle.h」ファイルに記述するコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
BATTLE Battle; void BATTLE::materialLoad() { black = GetColor(0, 0, 0); white = GetColor(255, 255, 255); ms = CreateFontToHandle("MS ゴシック", 10, 6, DX_FONTTYPE_ANTIALIASING_4X4); } void BATTLE::Choices(int x, const char* str[], int n) { int w = 0; for (int i = 0; i < n; i++) { DrawBox(x, firstarrow + w, x + 80, firstarrow + 16 + w, white, TRUE); DrawFormatStringToHandle(x + 5, firstarrow + 5 + w, black, ms, str[i]); w += 17; } } // 初期表示 void BATTLE::one() { sym = firstsym; pattern = 2; } // 矢印の移動 void BATTLE::two() { if (symnext == 0) { switch (WaitKey()) { case KEY_INPUT_DOWN: if (sym != sym_limit) sym += 17; break; case KEY_INPUT_UP: if (sym != firstsym) sym -= 17; break; case KEY_INPUT_ESCAPE: DxLib_End(); break; } if (symbol != -1) symnext++; } } void BATTLE::BattleDraw() { SetDrawScreen(DX_SCREEN_BACK); ClearDrawScreen(); switch(pattern): if (pattern == 1) one(); else if (pattern == 2) two(); Choices(160, str, 4); DrawFormatStringToHandle(144, sym, white, ms, "→"); ScreenFlip(); } |
図9 「Status.h」ファイルにHpDraw()関数の記述を追加
1 2 3 4 |
(略) void HpDraw(); void BattleDraw(); (略) |
図10 「Battle.h」ファイルのBattleDraw()関数定義部分をこのように書き換える
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
(略)void BATTLE::HpDraw() { DrawBox(180, 160, 250, 184, white, FALSE); DrawBox(180, 186, 250, 210, white, FALSE); DrawFormatStringToHandle(182, 162, white, ms, "villain\nHP: %d", villain.HP); DrawFormatStringToHandle(182, 188, white, ms, "player\nHP:%d", player.HP); } void BATTLE::BattleDraw() { SetDrawScreen(DX_SCREEN_BACK); ClearDrawScreen(); switch(pattern): if (pattern == 1) one(); else if (pattern == 2) two(); Choices(160, str, 4); DrawFormatStringToHandle(144, sym, white, ms, "→"); HpDraw(); ScreenFlip(); } |