用Win API实现游戏《是男人就下100层》(游戏入门&追爱)
此教程为追爱而写,如果你觉得这篇教程还不错请在我的博客留言
为了向一个女孩证明自己决定寻找一千个陌生人祝福,
希望你能留下你的祝福
谢谢
地址:
http://blog.
还有写的其它教程,也是为此而写
用VB6实现俄罗斯方块游戏(游戏编程入门教程)&追爱
http://bbs.
源代码下载
http://fangcun.
游戏目录下
是男人就下100层,是一个蛮好玩的游戏,
相信很多朋友都曾玩过,
那么你是否想自己做一个呢。
那让我们一起来吧!
首先是数据结构
//常量
//窗口大小
#define WINDOW_WIDTH 320
#define WINDOW_HEIGHT 320
//计时器ID
#define TIMER 1
//板块类型
//石板
#define BOARD_STONE 0
//木板
#define BOARD_WOOD 1
//钉板
#define BOARD_DOG 2
//弹簧
#define BOARD_SPRING 3
//板块元素数
#define BOARD_COUNT 10
//角色高度
#define ROLE_HEIGHT 32
//角色宽度
#define ROLE_WIDTH 32
//角色状态
//向左
#define ROLE_LEFT 0
//向右
#define ROLE_RIGHT 1
//发呆
#define ROLE_LOGY 2
//全局变量
HDC g_hDrawDC;//绘制设备上下文
HBITMAP g_hDrawBmp;//绘制位图
bool g_bStart=false;//指示是否开始游戏
HWND g_hMainWnd;//主窗口句柄
HINSTANCE g_hInstance;//程序实例句柄
struct Board//板块描述
{
int nType;//板块类型
int nState;//板块状态
int nStep;//计数
int x,y;//板块位置
};
Board g_Board[BOARD_COUNT];
struct Role//角色信息
{
int nState;//角色状态用于绘制图片0,向左,1,向右,2发呆
int nStep;//向左向右的步数0~2
int nFloorCount;//当前层数
int x,y;//角色位置
int Count;//角色生命数
} g_Role;
char g_strInfo[10];//提示信息
这些描述整个游戏的状态
游戏中使用Timer(计时器)来实现板块的上移以及人物的自动下降6
case WM_TIMER:
if(g_bStart)//游戏已开始
{
//板块上升
BoardDeal();
Draw();
}
break;
//板块上升处理,构成循环
//同时处理角色上升
void BoardDeal()
{
int i;
int j;
int nMaxY;
bool bMoved=false;//角色是否移动过
for(i=0;i<BOARD_COUNT;i++)
{
g_Board[i].y-=5;
if(g_Board[i].y<-16)
{
j=0;
//寻找最大y坐标
nMaxY=0;
for(;j<BOARD_COUNT;j++)
{
if(g_Board[j].y>nMaxY)
{
nMaxY=g_Board[j].y;
}
}
g_Role.nFloorCount++;
g_Board[i].nType=rand()%4;
g_Board[i].x=rand()%145;
g_Board[i].y=nMaxY+64;
g_Board[i].nStep=0;
g_Board[i].nState=0;
}
if(g_Board[i].nState>0) g_Board[i].nState++;
if(g_Board[i].nState>4) g_Board[i].nState=0;
if(g_Board[i].nType==BOARD_WOOD)
{
if(g_Board[i].nState==4)
{
g_Board[i].nStep++;
g_Board[i].nState=1;
if(g_Board[i].nStep>2)
{
j=0;
//寻找最大y坐标
nMaxY=0;
for(;j<BOARD_COUNT;j++)
{
if(g_Board[j].y>nMaxY)
{
nMaxY=g_Board[j].y;
}
}
g_Board[i].nType=rand()%4;
g_Board[i].x=rand()%145;
g_Board[i].y=nMaxY+64;
g_Board[i].nStep=0;
g_Board[i].nState=0;
}
}
}
if(g_Role.y+ROLE_HEIGHT>=g_Board[i].y-8 && g_Role.y+ROLE_HEIGHT<=g_Board[i].y+8 &&
g_Role.x>=g_Board[i].x-16 && g_Role.x+ROLE_WIDTH<=g_Board[i].x+96+16)
{
g_Role.y=g_Board[i].y-ROLE_HEIGHT;
if(g_Board[i].nType==BOARD_WOOD)
{
if(g_Board[i].nState==0)
{
g_Board[i].nState=1;
strcpy(g_strInfo,"木板要碎了");
}
}
else if(g_Board[i].nType==BOARD_SPRING)
{
if(g_Board[i].nState==0)
{
g_Board[i].nState=1;
strcpy(g_strInfo,"跳啊跳");
}
if(g_Board[i].nState==4)
{
g_Role.y-=48;
}
}
else if(g_Board[i].nType==BOARD_DOG)
{
char str[20];
char str2[20];
g_Role.Count--;
if(g_Role.Count<0)
{
g_bStart=false;
strcpy(str,"你输了!成绩为");
itoa(g_Role.nFloorCount,str2,10);
strcat(str,str2);
MessageBox(g_hMainWnd,str,"TheMan",MB_OK);
g_bStart=true;
GameInit();
return;
}
g_bStart=false;
strcpy(g_strInfo,"生命-1");
Draw();
Sleep(1000);
g_bStart=true;
//寻找y坐标次大的板块
j=0;
int nT;
nT=i;
for(;j<BOARD_COUNT;j++)//找到最大板块
{
if(g_Board[nT].y<g_Board[j].y)
nT=j;
}
for(j=0;j<BOARD_COUNT;j++)
{
if(g_Board[j].y<g_Board[nT].y && g_Board[j].y>g_Board[i].y)
{
nT=j;
}
}
g_Board[nT].nState=0;
g_Board[nT].nType=BOARD_STONE;
g_Role.y=g_Board[nT].y-ROLE_HEIGHT;
g_Role.x=g_Board[nT].x+(96/2)-(32/2);
}
else if(g_Board[i].nType==BOARD_STONE)
{
strcpy(g_strInfo,"");
}
bMoved=true;
}
}
if(!bMoved)
{
g_Role.y+=8;
}
if(g_Role.y>320 || g_Role.y<12)
{
Role tR;
int x,y;
char str[20];
char str2[20];
g_Role.Count--;
if(g_Role.Count<0)
{
g_bStart=false;
strcpy(str,"你输了!成绩为");
itoa(g_Role.nFloorCount,str2,10);
strcat(str,str2);
MessageBox(g_hMainWnd,str,"TheMan",MB_OK);
g_bStart=true;
GameInit();
return;
}
g_bStart=false;
strcpy(g_strInfo,"生命-1");
Draw();
Sleep(1000);
g_bStart=true;
memcpy(&tR,&g_Role,sizeof(g_Role));
GameInit();
x=g_Role.x;
y=g_Role.y;
memcpy(&g_Role,&tR,sizeof(g_Role));
g_Role.x=x;
g_Role.y=y;
}
}
按键有WM_KEYDOWN处理
case WM_KEYDOWN://键入按键
nKey=(int)wParam;
if(!g_bStart)//游戏开始
{
GameInit();
g_bStart=true;
Draw();
}
else
{
if(nKey==VK_LEFT)
{
g_Role.nState=ROLE_LEFT;
g_Role.nStep=(g_Role.nStep+1)%3;
g_Role.x-=10;
if(g_Role.x<0) g_Role.x=0;
}
else if(nKey==VK_RIGHT)
{
g_Role.nState=ROLE_RIGHT;
g_Role.nStep=(g_Role.nStep+1)%3;
g_Role.x+=10;
if(g_Role.x>240-ROLE_WIDTH) g_Role.x=240-ROLE_WIDTH;
}
Draw();
}
break;
游戏画面在一个函数Draw中绘制出来并在WM_PAINT中调用复制画面
case WM_PAINT://窗口被重画
BitBlt(GetDC(hWnd),0,0,WINDOW_WIDTH,WINDOW_HEIGHT,g_hDrawDC,0,0,SRCCOPY);
break;
//绘制游戏画面
void Draw()
{
HDC hDC;
HBITMAP hBmp;
HBITMAP hOldBmp;
//创建临时DC
hDC=CreateCompatibleDC(GetDC(g_hMainWnd));
//绘制白色底色
RECT rt;
rt.left=0;
rt.top=0;
rt.right=WINDOW_WIDTH;
rt.bottom=WINDOW_HEIGHT;
FillRect(g_hDrawDC,&rt,NULL);
//绘制木板
int i;
for(i=0;i<BOARD_COUNT;i++)
{
if(g_Board[i].nType==BOARD_STONE)//绘制石板
{
hBmp=LoadBitmap(g_hInstance,"石板");
//绑定位图
hOldBmp=(HBITMAP)SelectObject(hDC,hBmp);
TransparentBlt(g_hDrawDC,g_Board[i].x,g_Board[i].y,96,16,hDC,0,0,96,16,0xFF00FF);
SelectObject(hDC,hOldBmp);
DeleteObject(hBmp);
}
else if(g_Board[i].nType==BOARD_WOOD)//绘制木板
{
if(g_Board[i].nState==0)
{
hBmp=LoadBitmap(g_hInstance,"木板");
//绑定位图
hOldBmp=(HBITMAP)SelectObject(hDC,hBmp);
TransparentBlt(g_hDrawDC,g_Board[i].x,g_Board[i].y,96,16,hDC,0,0,96,16,0xFF00FF);
}
else if(g_Board[i].nState<4)
{
hBmp=LoadBitmap(g_hInstance,"碎木板");
//绑定位图
hOldBmp=(HBITMAP)SelectObject(hDC,hBmp);
TransparentBlt(g_hDrawDC,g_Board[i].x,g_Board[i].y,96,16,hDC,0,0,96,16,0xFF00FF);
}
SelectObject(hDC,hOldBmp);
DeleteObject(hBmp);
}
else if(g_Board[i].nType==BOARD_DOG)//绘制钉板
{
hBmp=LoadBitmap(g_hInstance,"钉板");
//绑定位图
hOldBmp=(HBITMAP)SelectObject(hDC,hBmp);
TransparentBlt(g_hDrawDC,g_Board[i].x,g_Board[i].y,96,16,hDC,0,0,96,16,0xFF00FF);
SelectObject(hDC,hOldBmp);
DeleteObject(hBmp);
}
else if(g_Board[i].nType==BOARD_SPRING)//绘制弹簧
{
if(g_Board[i].nState==0)
{
hBmp=LoadBitmap(g_hInstance,"弹簧");
//绑定位图
hOldBmp=(HBITMAP)SelectObject(hDC,hBmp);
TransparentBlt(g_hDrawDC,g_Board[i].x,g_Board[i].y,96,16,hDC,0,0,96,16,0xFF00FF);
}
else if(g_Board[i].nState<=4)
{
hBmp=LoadBitmap(g_hInstance,"弹簧压缩");
//绑定位图
hOldBmp=(HBITMAP)SelectObject(hDC,hBmp);
TransparentBlt(g_hDrawDC,g_Board[i].x,g_Board[i].y,96,8,hDC,0,0,96,8,0xFF00FF);
}
SelectObject(hDC,hOldBmp);
DeleteObject(hBmp);
}
}
//绘制狗牙
hBmp=LoadBitmap(g_hInstance,"狗牙");
//绑定位图
hOldBmp=(HBITMAP)SelectObject(hDC,hBmp);
TransparentBlt(g_hDrawDC,0,0,240,16,hDC,0,0,240,16,0xFF00FF);
SelectObject(hDC,hOldBmp);
DeleteObject(hBmp);
//绘制角色
if(g_Role.nState==ROLE_LEFT)//向左
{
hBmp=LoadBitmap(g_hInstance,"左");
//绑定位图
hOldBmp=(HBITMAP)SelectObject(hDC,hBmp);
TransparentBlt(g_hDrawDC,g_Role.x,g_Role.y,ROLE_WIDTH,ROLE_HEIGHT,hDC,g_Role.nStep*ROLE_WIDTH,0,ROLE_WIDTH,ROLE_HEIGHT,0xFF00FF);
SelectObject(hDC,hOldBmp);
DeleteObject(hBmp);
}
else if(g_Role.nState==ROLE_RIGHT)//向右
{
hBmp=LoadBitmap(g_hInstance,"右");
//绑定位图
hOldBmp=(HBITMAP)SelectObject(hDC,hBmp);
TransparentBlt(g_hDrawDC,g_Role.x,g_Role.y,ROLE_WIDTH,ROLE_HEIGHT,hDC,g_Role.nStep*ROLE_WIDTH,0,ROLE_WIDTH,ROLE_HEIGHT,0xFF00FF);
SelectObject(hDC,hOldBmp);
DeleteObject(hBmp);
}
else if(g_Role.nState==ROLE_LOGY)//发呆
{
hBmp=LoadBitmap(g_hInstance,"发呆");
//绑定位图
hOldBmp=(HBITMAP)SelectObject(hDC,hBmp);
TransparentBlt(g_hDrawDC,g_Role.x,g_Role.y,ROLE_WIDTH,ROLE_HEIGHT,hDC,0,0,ROLE_WIDTH,ROLE_HEIGHT,0xFF00FF);
SelectObject(hDC,hOldBmp);
DeleteObject(hBmp);
}
DeleteDC(hDC);
//绘制分界线
MoveToEx(g_hDrawDC,240,0,NULL);
LineTo(g_hDrawDC,240,320);
HBRUSH hBr;
rt.left=241;
rt.top=0;
rt.bottom=320;
rt.right=320;
hBr=CreateSolidBrush(0xFFFFFF);
FillRect(g_hDrawDC,&rt,hBr);
DeleteObject(hBr);
char str[20];
strcpy(str,"层数:");
TextOut(g_hDrawDC,241,20,str,strlen(str));
itoa(g_Role.nFloorCount,str,10);
TextOut(g_hDrawDC,250,40,str,strlen(str));
strcpy(str,"生命:");
//绘制状态信息
TextOut(g_hDrawDC,241,70,str,strlen(str));
itoa(g_Role.Count,str,10);
TextOut(g_hDrawDC,250,90,str,strlen(str));
TextOut(g_hDrawDC,241,150,g_strInfo,strlen(g_strInfo));
BitBlt(GetDC(g_hMainWnd),0,0,WINDOW_WIDTH,WINDOW_HEIGHT,g_hDrawDC,0,0,SRCCOPY);
}