「ゲームエンジンを使わずRPGを作りたい」
そん思ったことはありませんか?
では
WINAPI(+α)だけでRPGを作りましょう
引用元と参考元
わかりやすいのでぜひ見に行ってください
環境とか
・Windows 11
・VSCode V1.95
・windows gcc x64
VisualStudio
は使いません.VSCode
一本です.
使用ライブラリ
・windows.h
・stdlib.h
・stdio.h
使うかもしれないもの
・python3
画像描画
コピペ用
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
//pixel数
int pixel = 48;
//関数宣言
//呼び出し
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//画像描画
int DrowImage(HDC hdc, char* str, int x, int y, int cx, int cy );
//main関数
int WINAPI WinMain
(
//引数
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,
int nCmdShow
)
{
//アプリ関数名
TCHAR szAppName[] = TEXT("TestApp");
//変数宣言
WNDCLASS wc;
HWND hwnd;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;//スタイル指定
wc.lpfnWndProc = WndProc;// ウィンドウプロシージャを登録
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);//アイコン
wc.hCursor = LoadCursor(NULL, IDC_ARROW);//カーソル
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szAppName;
if (!RegisterClass(&wc)) return 0;//error吐いた時の処理
// ウィンドウを作成
hwnd = CreateWindow
(
szAppName,
TEXT("Title"),//ウィンドウ名
WS_OVERLAPPEDWINDOW|WS_MAXIMIZEBOX|WS_MINIMIZEBOX,//ウィンドウスタイル
CW_USEDEFAULT,//表示位置
CW_USEDEFAULT,//表示位置
CW_USEDEFAULT,//x
CW_USEDEFAULT,//y
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd) return 0;//error排他っと期の処理
//ウィンドウ作成
ShowWindow(hwnd, nCmdShow);
//ウィンドウアップデート
UpdateWindow(hwnd);
//mainloop
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
//キー入力メッセージを文字メッセージに変換する。
TranslateMessage(&msg);
//メッセージをウィンドウプロシージャへディスパッチする。
DispatchMessage(&msg);
}
return msg.wParam;
}
//メッセージ処理
LRESULT CALLBACK WndProc
(
//引数
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
//変数宣言
int id;
HDC hdc;
PAINTSTRUCT ps;
LPCREATESTRUCT lpcs;
//メッセージの分岐
switch (uMsg)
{
case WM_CLOSE:
//罰ボタン押された時の処理
id = MessageBox(hwnd, TEXT("exit?"),TEXT("exit"), MB_YESNO | MB_ICONEXCLAMATION );
if (id == IDYES)
{
MessageBox(hwnd, TEXT("OK"), TEXT("OK"), MB_OK);
DestroyWindow(hwnd);
}
return 0;
//ウィンドウを消す
case WM_DESTROY:
//ウィンドウ破壊
PostQuitMessage(0);
return 0;
case WM_CREATE:
return 0;
//ペイント
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
//画像表示
DrowImage(hdc, "ファイル名.bmp",150, 150, 200,300);//ファイル名.bmpを描画
EndPaint(hwnd, &ps);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
//画像描画 HDCobj,アドレス,場所x,場所y,大きさx,大きさy,
int DrowImage(HDC hdc, char* str, int x, int y, int cx, int cy )
{
HDC hdc_2;
//画像読み込み用
HBITMAP image;
//image
image = LoadImage(NULL, str, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
//hdcodj作成
hdc_2 = CreateCompatibleDC(hdc);
//select
SelectObject(hdc_2,image);
//画像描画
BitBlt(hdc, x, y, cx, cy, hdc_2, 0, 0, SRCCOPY);
//hdcobj破壊
DeleteDC(hdc_2);
//画像削除
DeleteObject(image);
//エラーが出れば1を返す
if (image == NULL){return 1;}
else{return 0;}
}
をメッセージウィンドウのコードを 参考 引用しています.
このコードではファイル名.bmp
を表示しています.
ここではDrowImage
関数にhdc
とファイル名(char*)
と場所を入力することで画像を表示させてます.
ただ、WINAPIの仕様でbmp
ファイルにしか表示できません.
jpg
とかは頑張って変換しましょう()
これを改造して動かせるようにします.
キャラを動かす!
グローバル変数にint型
のx
,y
,Up
,Right
,has_run
を追加します.
//x,yの座標
int x=0 ,y=0;
//右左左右キーフラグ
int Up = 0,Right = 0;
//走るフラグ
int has_run = 0;
また、WndProc
関数のswitch
文に以下のコードを追加します
case WM_KEYDOWN:
int vkey = wParam;
if (vkey == VK_UP){Up = -1;}//上キー
if (vkey == VK_DOWN){Up = 1;}//上キー
if (vkey == VK_LEFT){Right = -1;}//上キー
if (vkey == VK_RIGHT){Right = 1;}//上キー
//走りフラグ
if (vkey == VK_SHIFT){has_run = 1 - has_run;}
//リセット
if (vkey != VK_UP&&vkey != VK_DOWN){Up = 0;}
if (vkey != VK_LEFT&&vkey != VK_RIGHT){Right = 0;}
InvalidateRect(hwnd, NULL, TRUE); //再描画
WndProc
関数のswitch
文のcase case WM_PAINT:
に以下のコードを追加します
//走るスピード
int run_spped = 10;
//ダッシュする倍率
int run_as = 2;
if (has_run == 1){run_spped = run_spped * run_as;}
//座標処理
x += Right*run_spped;
y += Up* run_spped;
//画像表示
DrowImage(hdc, "プレイヤー.bmp",x-pixel/2, y-pixel/2, 200,300);
プレイヤー.bmp
を移動させています.なので適宜他のものに変換してください.
おわり
これで動かせるようになりました.
今回はこれで終わりです.
コピペ用
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
//pixel数
int pixel = 48;
//x,yの座標
int x=0 ,y=0;
//右左左右キーフラグ
int Up = 0,Right = 0;
//走るフラグ
int has_run = 0;
//関数宣言
//呼び出し
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//画像描画
int DrowImage(HDC hdc, char* str, int x, int y, int cx, int cy );
//main関数
int WINAPI WinMain
(
//引数
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,
int nCmdShow
)
{
//アプリ関数名
TCHAR szAppName[] = TEXT("TestApp");
//変数宣言
WNDCLASS wc;
HWND hwnd;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;//スタイル指定
wc.lpfnWndProc = WndProc;// ウィンドウプロシージャを登録
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);//アイコン
wc.hCursor = LoadCursor(NULL, IDC_ARROW);//カーソル
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szAppName;
if (!RegisterClass(&wc)) return 0;//error吐いた時の処理
// ウィンドウを作成
hwnd = CreateWindow
(
szAppName,
TEXT("Title"),//ウィンドウ名
WS_OVERLAPPEDWINDOW|WS_MAXIMIZEBOX|WS_MINIMIZEBOX,//ウィンドウスタイル
CW_USEDEFAULT,//表示位置
CW_USEDEFAULT,//表示位置
CW_USEDEFAULT,//x
CW_USEDEFAULT,//y
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd) return 0;//error排他っと期の処理
//ウィンドウ作成
ShowWindow(hwnd, nCmdShow);
//ウィンドウアップデート
UpdateWindow(hwnd);
//mainloop
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
//キー入力メッセージを文字メッセージに変換する。
TranslateMessage(&msg);
//メッセージをウィンドウプロシージャへディスパッチする。
DispatchMessage(&msg);
}
return msg.wParam;
}
//メッセージ処理
LRESULT CALLBACK WndProc
(
//引数
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
//変数宣言
int id;
HDC hdc;
PAINTSTRUCT ps;
LPCREATESTRUCT lpcs;
//メッセージの分岐
switch (uMsg)
{
case WM_CLOSE:
//罰ボタン押された時の処理
id = MessageBox(hwnd, TEXT("exit?"),TEXT("exit"), MB_YESNO | MB_ICONEXCLAMATION );
if (id == IDYES)
{
MessageBox(hwnd, TEXT("OK"), TEXT("OK"), MB_OK);
DestroyWindow(hwnd);
}
return 0;
//ウィンドウを消す
case WM_DESTROY:
//ウィンドウ破壊
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
int vkey = wParam;
if (vkey == VK_UP){Up = -1;}//上キー
if (vkey == VK_DOWN){Up = 1;}//上キー
if (vkey == VK_LEFT){Right = -1;}//上キー
if (vkey == VK_RIGHT){Right = 1;}//上キー
//走りフラグ
if (vkey == VK_SHIFT){has_run = 1 - has_run;}
//リセット
if (vkey != VK_UP&&vkey != VK_DOWN){Up = 0;}
if (vkey != VK_LEFT&&vkey != VK_RIGHT){Right = 0;}
InvalidateRect(hwnd, NULL, TRUE); //再描画
case WM_CREATE:
return 0;
//ペイント
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
//画像表示
//走るスピード
int run_spped = 10;
//ダッシュする倍率
int run_as = 2;
if (has_run == 1){run_spped = run_spped * run_as;}
//座標処理
x += Right*run_spped;
y += Up* run_spped;
//画像表示
DrowImage(hdc, "プレイヤー.bmp",x-pixel/2, y-pixel/2, 200,300);
EndPaint(hwnd, &ps);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
//画像描画 HDCobj,アドレス,場所x,場所y,大きさx,大きさy,
int DrowImage(HDC hdc, char* str, int x, int y, int cx, int cy )
{
HDC hdc_2;
//画像読み込み用
HBITMAP image;
//image
image = LoadImage(NULL, str, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
//hdcodj作成
hdc_2 = CreateCompatibleDC(hdc);
//select
SelectObject(hdc_2,image);
//画像描画
BitBlt(hdc, x, y, cx, cy, hdc_2, 0, 0, SRCCOPY);
//hdcobj破壊
DeleteDC(hdc_2);
//画像削除
DeleteObject(image);
//エラーが出れば1を返す
if (image == NULL){return 1;}
else{return 0;}
}