まず、設計目標
1.ターンベースのゲーム、役割のプレーヤーとモンスターのセットを確立し、それらを底に生命の値を示し、
背景2.貼り付け攻撃フラグ、ロゴにマウスクリック、攻撃モンスターを起動するプレイヤー、および下部のモンスターは、出力ステータス情報の左。
3.プレイヤーのターンの後、HPのモンスターに応じて、重大な傷害または死亡を攻撃したり脱出するかを選択するためにどの方法を決定するために、モンスターを回します。
HPは、どちらか0のとき4、マークにゲームの終わりを貼付。
第二に、基本的な考え方
1.初期化プロセス、背景画像、モンスターやHP、選手と彼らのHP、MDCに貼付された攻撃の兆候は、最終的には、HDCに固執します。
2.左側をクリックし、のWndProc関数はメッセージを処理し、マークのカーソル位置を取得し、攻撃範囲、攻撃がtrueに設定されるかどうかを判断します。
3.次に、MyPaint機能に戻り、選手たちは、多くの場合、Fマップで表現、攻撃を開始した画像は、10日絵に更新し、その後、F、最後の6画面のモンスターを掲載攻撃します
顔は、HPのモンスターを減少させた場合、およびテキストボックスの左下隅に損傷を出力し、ステータスモンスターを確認してください。
4.場合は、更新15枚の画像F、これはモンスターのターンで、モンスターHP> 20に設定した場合、90%の確率で通常攻撃を開始するには、魔法攻撃を開始するために、10%の確率で、HPへ
20を下回る状況の5種類があります:Pugong、Moの功、攻撃するために、脱出する血液の戻り、20%の確率で、それぞれ、
5.f 26は、プレイヤーのHPを減らすために更新されて30 F 5枚の絵、のためにマップ選択したモンスターに応じて、画面を更新し、左下隅に状態を出力するときや
血液が脱出または死には低すぎるからです。
ラウンドの6一端、0にFリセット、次のラウンドを待つ、オーバー=真になるまで、トリガは、ゲームの終わりをマーク。
第三に、効果
四、次のように
#include "stdafx.h"
#include <stdio.h>
//结构体:储存怪物或玩家的状态信息
struct chr
{
int nHp;//目前生命值
int fHp;//最大生命值
int lv;//等级
int w;//加权值
int kind;//怪物的行为代号
};
//声明全局变量
HINSTANCE hInst;
HBITMAP bg,sheep,girl,skill,slash,magic,recover,game;//skill--攻击命令图;slash--普通攻击图;magic--怪物魔法攻击图;recover--怪物恢复魔法图;game--游戏结束图
HDC hdc,mdc,bufdc;
HWND hWnd;
DWORD tPre,tNow;
int pNum,f,txtNum;//pNum--玩家跑动图编号;f--每一回合攻击更新的画面数;TxtNum--记录目前所要显示消息的总数
bool attack,over;//attack记录玩家是否点击攻击命令;over一方生命值为0时,设为true
chr player,monster;
char text[5][100];//存储对战时要显示的消息
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void MyPaint(HDC hdc);
void MsgInsert(char*);//****新增要显示的消息到‘text’缓冲区,当显示的消息数目达到显示的上限数目时,删除最先的消息*********************************
void CheckDie(int hp,bool player);//每次攻击之后进行判断
void MyPaint1(HDC hdc,LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
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)
MyPaint(hdc);
}
}
return msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "canvas";
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HBITMAP bmp;
hInst = hInstance;
hWnd = CreateWindow("canvas", "绘图窗口" , WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
MoveWindow(hWnd,100,100,640,520,true);
ShowWindow(hWnd, nCmdShow);
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 = 30;
monster.lv = 1;
monster.w = 1;
txtNum = 0;//显示消息数目
MyPaint(hdc);
return TRUE;
}
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*20,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);
sprintf(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);
sprintf(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++; //递增变量,每回合开始重设为0;
//玩家按下攻击键时,玩家可看到6个画面(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;
sprintf(str," 怪物生命值减少%d HP ",damage);
MsgInsert(str);//text里的内容是从这里传递过去的
CheckDie(monster.nHp,false);//检查怪物是否还活着;flase表示要判断的对象是monster
}
}
srand(tPre);//产生随机数,若int固定,那么在rand下,它是伪随机数,要产生真正的随机数必须是个时刻变化的量
//回合开始后的第15个画面,判断怪物要采取何种行动
if(f == 15)
{
if(monster.nHp > 20)
{
if(rand()%10 != 1)
monster.kind = 0;//90%的几率进行普通攻击
else
monster.kind = 1;//10%的几率进行魔法攻击
}
else
{
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个画面,对玩家HP减掉普通攻击的部分
if(f == 30)
{
damage = rand()%10 + monster.lv*monster.w;
player.nHp -= (int)damage;
sprintf(str," 玩家生命值减少 %d HP ",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个画面,对玩家HP减掉魔法攻击的部分
if(f == 30)
{
damage = rand()%10 + 3*monster.w;
player.nHp -= (int)damage;
sprintf(str," 玩家的生命值减少%d HP ",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个画面,对玩家HP减掉全力攻击的部分
if(f == 30)
{
damage = rand()%10 + monster.lv*monster.w*5;
player.nHp -= (int)damage;
sprintf(str," 玩家的生命值减少 %d HP ",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;
sprintf(str," 怪兽回血值为30 ",damage);
MsgInsert(str);
}
break;
case 4:
//更新到第30个画面,逃跑
if(f == 30)
{
if(rand()%3 == 1) //2/3的几率怪兽死亡,游戏结束
{
over = true;
monster.nHp = 0;
sprintf(str," 怪兽重伤而死! ");
MsgInsert(str);
}
else
{
sprintf(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;
}
//****新增要显示的消息到‘text’缓冲区,当显示的消息数目达到显示的上限数目时,删除最先的消息*********************************
void MsgInsert(char* str)
{
if(txtNum < 5)
{
sprintf(text[txtNum],str);
txtNum++;
}
else
{
for(int i=0;i<txtNum;i++)//有5行的话,各行依次往上前进一行,最新的消息放在最后一行;
sprintf(text[i],text[i+1]);
sprintf(text[4],str);
}
}
//****检查玩家的生存情况*************************
void CheckDie(int hp,bool player)
{
char str[100];
if(hp <= 0)
{
over = true;
if(player)
{
sprintf(str," 玩家战败! ");
MsgInsert(str);
}
else
{
sprintf(str," 怪物战败! ");
MsgInsert(str);
}
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int x,y;
switch (message)
{
case WM_KEYDOWN:
if(wParam==VK_ESCAPE)
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN: //检测攻击范围
if(!attack)
{
x = LOWORD(lParam);
y = HIWORD(lParam);
if(x >= 500 && x <= 574 && y >= 350 && y <= 380)
attack = true;
}
break;
case WM_DESTROY:
DeleteDC(mdc);
DeleteDC(bufdc);
DeleteObject(bg);
DeleteObject(sheep);
DeleteObject(girl);
DeleteObject(skill);
DeleteObject(slash);
DeleteObject(magic);
DeleteObject(recover);
DeleteObject(game);
ReleaseDC(hWnd,hdc);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}