您的位置:首页 > 编程语言 > C语言/C++

021 VS2013 C++ 行为型游戏AI

2015-12-09 15:18 453 查看


直接贴代码:

#include <Windows.h>

//全局函数声明
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hInstance, int nShowCmd);
void MyPaint(HDC hdc);
BOOL Game_CleanUp(HWND hwnd);//在此函数中进行资源的清理
//****对战消息新增函数*********************************
void MsgInsert(char* str);

//****玩家怪物生命值判断函数*************************
void CheckDie(int hp, bool player);

#define WINDOW_WIDTH 640 //为窗口宽度定义的宏,以方便在此处修改窗口宽度
#define WINDOW_HEIGHT 480 //为窗口高度定义的宏,以方便在此处修改窗口高度
#define WINDOW_TITLE "游戏开发的梦想" //为窗口标题定义的宏

//定义结构
struct chr
{
int        nHp;
int        fHp;
int        lv;
int        w;
int        kind;
};
//全局变量
HBITMAP    bg, sheep, girl, skill, slash, magic, recover, game;
HDC        hdc, mdc, bufdc;
HWND    hWnd;
DWORD    tPre, tNow;
int        pNum, f, txtNum;
bool    attack, over;
chr        player, monster;
char    text[5][100];
//--------------------------------------------WinMain() 入口函数-----------------------------------------------
//应用程序的入口函数
//-------------------------------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
MSG msg = { 0 };//定义并初始化msg
MyRegisterClass(hInstance);

if (!InitInstance(hInstance, nShowCmd))
{
return FALSE;
}

//游戏循环
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
tNow = GetTickCount();
if (tNow - tPre >= 40)//相差0.04秒时再进行重绘操作
MyPaint(hdc);
}
}

return msg.wParam;
}

//--------------------------------------------MyRegisterClass() 函数-------------------------------------------
//注册窗口
//-------------------------------------------------------------------------------------------------------------
ATOM MyRegisterClass(HINSTANCE hInstance)
{
//创建窗口第一步:开始设计一个完整的窗口类
WNDCLASSEX wndClass;//定义一个窗口类
wndClass.cbSize = sizeof(WNDCLASSEX);//设置结构体的字节数大小
wndClass.style = CS_HREDRAW | CS_VREDRAW;//设置窗口的样式
wndClass.lpfnWndProc = (WNDPROC)WndProc;//设置指向窗口过程函数的指针
wndClass.cbClsExtra = 0;//窗口类的附加内存,取0就可以了
wndClass.cbWndExtra = 0;//窗口的附加内存,依然取0就行了
wndClass.hInstance = hInstance;//指定包含窗口过程的程序的实例句柄
wndClass.hIcon = (HICON) ::LoadImage(NULL, "icon.ico", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);//加载自定义ico图标
wndClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);//指定窗口类的光标句柄
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//指定一个灰色画刷句柄
wndClass.lpszMenuName = NULL;//用一个以空终止的字符串,指定菜单资源的名字.
wndClass.lpszClassName = "GameClass";//指定窗口类的名称
//wndClass.hIconsm = NULL;

//创建窗口第二步:注册窗口类
return RegisterClassEx(&wndClass);//设计完窗口后,需要对窗口类进行注册,这样才能创建该类型的窗口
}

//--------------------------------------------InitInstance() 函数----------------------------------------------
//加载资源
//-------------------------------------------------------------------------------------------------------------
BOOL InitInstance(HINSTANCE hInstance, int nShowCmd)
{
HBITMAP bmp;

//创建窗口第三步:正式创建窗口
//创建窗口函数
hWnd = CreateWindow("GameClass", WINDOW_TITLE, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
//创建窗口第四步:窗口的移动,显示和更新
MoveWindow(hWnd, 250, 80, WINDOW_WIDTH, WINDOW_HEIGHT, true);//调整窗口显示时的位置及窗口的大小
ShowWindow(hWnd, nShowCmd);//设定显示窗口时的状态
UpdateWindow(hWnd);//将窗口绘制于显示设备上

hdc = GetDC(hWnd);
mdc = CreateCompatibleDC(hdc);
bufdc = CreateCompatibleDC(hdc);
//建立空白的位图
bmp = CreateCompatibleBitmap(hdc, 640, 480);
SelectObject(mdc, bmp);
//加载图片
bg = (HBITMAP)LoadImage(NULL, "bg.bmp", IMAGE_BITMAP, 640, 480, LR_LOADFROMFILE);
sheep = (HBITMAP)LoadImage(NULL, "sheep.bmp", IMAGE_BITMAP, 133, 220, LR_LOADFROMFILE);
girl = (HBITMAP)LoadImage(NULL, "girl.bmp", IMAGE_BITMAP, 480, 148, LR_LOADFROMFILE);
skill = (HBITMAP)LoadImage(NULL, "skill.bmp", IMAGE_BITMAP, 74, 60, LR_LOADFROMFILE);
slash = (HBITMAP)LoadImage(NULL, "slash.bmp", IMAGE_BITMAP, 196, 162, LR_LOADFROMFILE);
magic = (HBITMAP)LoadImage(NULL, "magic.bmp", IMAGE_BITMAP, 200, 100, LR_LOADFROMFILE);
recover = (HBITMAP)LoadImage(NULL, "recover.bmp", IMAGE_BITMAP, 300, 150, LR_LOADFROMFILE);
game = (HBITMAP)LoadImage(NULL, "over.bmp", IMAGE_BITMAP, 289, 74, LR_LOADFROMFILE);

player.nHp = player.fHp = 50;    //
player.lv = 2;                    //
player.w = 4;                    //

monster.nHp = monster.fHp = 100;    //
monster.lv = 1;                        //
monster.w = 1;                        //
txtNum = 0;

MyPaint(hdc);
return TRUE;
}

//--------------------------------------------MyPaint() 函数---------------------------------------------------
//绘制图形
//-------------------------------------------------------------------------------------------------------------
void MyPaint(HDC hdc)
{
char str[100];
int i, damage;

//贴上背景图
SelectObject(bufdc, bg);
BitBlt(mdc, 0, 0, 640, 480, bufdc, 0, 0, SRCCOPY);

//显示对战消息
for (i = 0; i<txtNum; i++)
TextOut(mdc, 0, 360 + i * 18, text[i], strlen(text[i]));

//贴上怪物图
if (monster.nHp>0)
{
SelectObject(bufdc, sheep);
BitBlt(mdc, 70, 180, 133, 110, bufdc, 0, 110, SRCAND);
BitBlt(mdc, 70, 180, 133, 110, bufdc, 0, 0, SRCPAINT);
wsprintf(str, "%d / %d", monster.nHp, monster.fHp);
TextOut(mdc, 100, 320, str, strlen(str));
}

//帖上玩家图
if (player.nHp > 0)
{
SelectObject(bufdc, girl);
BitBlt(mdc, 500, 200, 60, 74, bufdc, pNum * 60, 74, SRCAND);
BitBlt(mdc, 500, 200, 60, 74, bufdc, pNum * 60, 0, SRCPAINT);
wsprintf(str, "%d / %d", player.nHp, player.fHp);
TextOut(mdc, 510, 320, str, strlen(str));
}

if (over)                //帖上游戏结束图标
{
SelectObject(bufdc, game);
BitBlt(mdc, 200, 200, 289, 37, bufdc, 0, 37, SRCAND);
BitBlt(mdc, 200, 200, 289, 37, bufdc, 0, 0, SRCPAINT);
}
else if (!attack)        //贴上攻击命令图标
{
SelectObject(bufdc, skill);
BitBlt(mdc, 500, 350, 74, 30, bufdc, 0, 30, SRCAND);
BitBlt(mdc, 500, 350, 74, 30, bufdc, 0, 0, SRCPAINT);
}
else
{
f++;

//第5—10个画面时显示玩家攻击图标
if (f >= 5 && f <= 10)
{
SelectObject(bufdc, slash);
BitBlt(mdc, 100, 160, 98, 162, bufdc, 98, 0, SRCAND);
BitBlt(mdc, 100, 160, 98, 162, bufdc, 0, 0, SRCPAINT);

//第10个画面时计算怪物受伤害程度并加入消息
if (f == 10)
{
damage = rand() % 10 + player.lv*player.w;
monster.nHp -= (int)damage;

wsprintf(str, "玩家攻击...玩家对怪物造成了 %d 的伤害", damage);
MsgInsert(str);

CheckDie(monster.nHp, false);
}
}

srand(tPre);

//第15个画面时判断怪物进行哪项动作
if (f == 15)
{
if (monster.nHp > 20)                //生命值大于20
{
if (rand() % 10 != 1)
monster.kind = 0;
else
monster.kind = 1;
}
else                                //生命值小于20
{
switch (rand() % 5)
{
case 0:                        //普通攻击
monster.kind = 0;
break;
case 1:                        //施放攻击魔法
monster.kind = 1;
break;
case 2:                        //使尽全力攻击
monster.kind = 2;
break;
case 3:                        //补血
monster.kind = 3;
break;
case 4:                        //逃跑
monster.kind = 4;
break;
}
}
}

//第26-30个画面时显示玩家攻击图标
if (f >= 26 && f <= 30)
{
switch (monster.kind)
{
case 0:                            //普通攻击
SelectObject(bufdc, slash);
BitBlt(mdc, 480, 150, 98, 162, bufdc, 98, 0, SRCAND);
BitBlt(mdc, 480, 150, 98, 162, bufdc, 0, 0, SRCPAINT);

//第30个画面时计算玩家受伤害程度并加入显示消息
if (f == 30)
{
damage = rand() % 10 + monster.lv*monster.w;
player.nHp -= (int)damage;

wsprintf(str, "怪物攻击...怪物对玩家造成了 %d 的伤害", damage);
MsgInsert(str);

CheckDie(player.nHp, true);
}
break;
case 1:                            //施放攻击魔法
SelectObject(bufdc, magic);
BitBlt(mdc, 480, 190, 100, 100, bufdc, 100, 0, SRCAND);
BitBlt(mdc, 480, 190, 100, 100, bufdc, 0, 0, SRCPAINT);

//第30个画面时计算玩家受伤害程度并加入显示消息
if (f == 30)
{
damage = rand() % 10 + 3 * monster.w;
player.nHp -= (int)damage;

wsprintf(str, "怪物魔法攻击...怪物对玩家造成了 %d 的伤害", damage);
MsgInsert(str);

CheckDie(player.nHp, true);
}
break;
case 2:                            //使尽全力攻击
SelectObject(bufdc, slash);
BitBlt(mdc, 480, 150, 98, 162, bufdc, 98, 0, SRCAND);
BitBlt(mdc, 480, 150, 98, 162, bufdc, 0, 0, SRCPAINT);

//第30个画面时计算玩家受伤害程度并加入显示消息
if (f == 30)
{
damage = rand() % 10 + monster.lv*monster.w * 5;
player.nHp -= (int)damage;

wsprintf(str, "怪物全力攻击...怪物对玩家造成了 %d 的伤害", damage);
MsgInsert(str);

CheckDie(player.nHp, true);
}
break;
case 3:                            //补血
SelectObject(bufdc, recover);
BitBlt(mdc, 60, 160, 150, 150, bufdc, 150, 0, SRCAND);
BitBlt(mdc, 60, 160, 150, 150, bufdc, 0, 0, SRCPAINT);

//第30个画面时怪物恢复生命值并加入显示消息
if (f == 30)
{
monster.nHp += 30;

wsprintf(str, "怪物魔法补血...恢复了 30 生命值", damage);
MsgInsert(str);
}
break;
case 4:
//第30个画面时判断怪物是否逃跑成功
if (f == 30)
{
if (rand() % 3 == 1)    //逃跑成功几率为1/3
{
over = true;
monster.nHp = 0;

wsprintf(str, "怪物逃跑...逃跑成功");
MsgInsert(str);
}
else
{
wsprintf(str, "怪物逃跑...逃跑失败");
MsgInsert(str);
}
}
break;
}
}

if (f == 30)            //回合结束
{
attack = false;
f = 0;
}
}

BitBlt(hdc, 0, 0, 640, 480, mdc, 0, 0, SRCCOPY);

tPre = GetTickCount();

pNum++;
if (pNum == 8)
pNum = 0;
}
//****对战消息新增函数*********************************
void MsgInsert(char* str)
{
if (txtNum < 5)
{
wsprintf(text[txtNum], str);
txtNum++;
}
else
{
for (int i = 0; i < txtNum; i++)
wsprintf(text[i], text[i + 1]);

wsprintf(text[4], str);
}
}

//****玩家怪物生命值判断函数*************************
void CheckDie(int hp, bool player)
{
char str[100];

if (hp <= 0)
{
over = true;
if (player)
{
wsprintf(str, "你被怪物找败了...");
MsgInsert(str);
}
else
{
wsprintf(str, "怪物歼灭...");
MsgInsert(str);
}
}
}

//--------------------------------------------Game_CleanUp() 函数----------------------------------------------
//资源清理函数,在此函数中进行退出前的资源的清理工作
//-------------------------------------------------------------------------------------------------------------
BOOL Game_CleanUp()
{
ClipCursor(NULL);            //解除鼠标限制

DeleteDC(mdc);
DeleteDC(bufdc);
DeleteObject(bg);
DeleteObject(sheep);
DeleteObject(girl);
DeleteObject(skill);
DeleteObject(slash);
DeleteObject(magic);
DeleteObject(recover);
DeleteObject(game);
ReleaseDC(hWnd, hdc);
return TRUE;
}

//--------------------------------------------WndProc() 窗口消息回调函数---------------------------------------
//窗口过程函数WndProc,对窗口消息进行处理
//-------------------------------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
int x, y;
switch (message)
{
case WM_PAINT://窗口重绘消息
{
hdc = BeginPaint(hwnd, &ps);
MyPaint(hdc);
EndPaint(hwnd, &ps);
}
break;
case WM_LBUTTONDOWN://单击鼠标左键消息
{
x = LOWORD(lParam);//取得鼠标X坐标
y = HIWORD(lParam);//取得鼠标Y坐标
if (x >= 500 && x <= 574 && y >= 350 && y <= 380)
attack = true;
}
break;
case WM_KEYDOWN://若是键盘按下消息
{
if (wParam == VK_ESCAPE)//如果按下的键是ESC
{
if (MessageBox(hwnd, "退出?", "提示", MB_YESNO | MB_ICONQUESTION) == IDYES)
DestroyWindow(hwnd);//销毁窗口,并发送一条WM_DESTROY消息
}
}
break;
case WM_CLOSE://关闭按钮
{
if (MessageBox(hwnd, "是否要退出?", "提示", MB_YESNO | MB_ICONQUESTION) == IDYES)
DestroyWindow(hwnd);//销毁窗口,并发送一条WM_DESTROY消息
else
return(0);
}
break;
case WM_DESTROY://窗口结束消息
{
//删除资源
Game_CleanUp();
PostQuitMessage(0);//向系统表明有个线程有终止的请求,用来响应WM_DESTROY消息
}
break;
default://若是上述case条件都不符合,则执行该default语句
{
return DefWindowProc(hwnd, message, wParam, lParam);//调用默认的窗口过程
}
}
return 0;//正常退出
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: