怎样把所有的功能组织起来,形成一个完整的游戏呢?游戏状态。不同的游戏状态下,对应不同的图片显示、逻辑处理、按键响应。这样就形成了一个结构清晰的框架。各个模块相对独立,也方便扩展。
由于是消息处理机制,所有功能对应到消息处理函数WndProc,程序框架如下:
消息处理函数WndProc
{
绘图消息WM_PAINT:
状态1:状态1绘图。
状态2:状态2绘图。
……
计时消息WM_TIMER:
状态1:状态1逻辑处理。发WM_PAINT消息,通知绘图。
状态2:状态2逻辑处理。发WM_PAINT消息,通知绘图。
……
按键消息WM_KEYDOWN WM_KEYUP:
状态1:状态1逻辑处理。发WM_PAINT消息,通知绘图。
状态2:状态2逻辑处理。发WM_PAINT消息,通知绘图。
……
}
逻辑处理后是否发WM_PAINT消息,依据具体情况而定。
程序入口:
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MyRegisterClass(hInstance); //类注册
//初始化
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
//消息循环
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
整个消息处理循环,是默认的结构。
说明:InitInstance函数复杂初始化。类注册函数MyRegisterClass中,把菜单栏取消了,即wcex.lpszMenuName=NULL,其它不变。
消息处理函数WndProc
代码:
switch (message)
{
case WM_PAINT:
//窗口DC
hwindow = BeginPaint(hWnd, &ps);
//初始化空图
SelectObject(hscreen,hmapnull);
switch(gamemap.iGameState)
{
case GAME_ERR:
//地图文件加载错误
gamemap.viewx=0; //视图坐标
//显示错误信息
bmPre.Stretch(2,2,0); //背景图片
myfont.SelectColor(TC_WHITE,TC_BLACK);//文字颜色
myfont.SelectFont(0); //字体
myfont.ShowText(150,290,pPreText[3]); //显示文字
break;
case GAME_PRE:
//菜单显示
(代码略)
break;
case GAME_HELP:
//菜单项“操作说明”
(代码略)
break;
case GAME_IN_PRE:
//游戏LIFE,WORLD提示
gamemap.viewx=0; //视图坐标
bmPre.Stretch(2,2,2); //背景图片
gamemap.ShowInfo(hscreen); //显示LIFE,WORLD
break;
case GAME_IN: //游戏进行中
case GAME_WIN: //游戏进行中,过关
case GAME_FAIL_WAIT: //游戏进行中,失败
case GAME_PUMP_IN: //游戏进行中,进入水管
bmSky.DrawRollStretch(2,2,gamemap.mapinfo.iBackBmp);//背景图片
gamemap.ShowBkObj(bmMapBkObj); //地图背景物品
gamemap.Show(bmMap); //地图物品
gamemap.ShowAniObj(bmAniObj); //动态元素
gamemap.ShowOther(hscreen); //金钱数量,攻击提示
rmain.Draw(); //玩家角色
break;
case GAME_OVER:
//游戏结束
gamemap.viewx=0;
bmPre.Stretch(2,2,1); //输出图片GAME OVER
break;
case GAME_PASS:
//游戏通关
gamemap.viewx=0;
bmPre.Stretch(2,2,3); //输出图片通关
break;
}
if(gamemap.iScreenScale)
{ //窗口缩放,放大视图区域
StretchBlt(hwindow,0,0,wwingame,hwingame,hscreen, gamemap.viewx,0,GAMEW*32,GAMEH*32,SRCCOPY);
}
else
{ //拷贝视图区域 BitBlt(hwindow,0,0,GAMEW*32,GAMEH*32,hscreen,gamemap.viewx,0,SRCCOPY);
}
EndPaint(hWnd, &ps); //绘图结束
break;
case WM_TIMER:
switch(gamemap.iGameState)
{
case GAME_PRE: //游戏菜单
c1.DecCount();//计时器减1
if(0 == c1.iNum%MENU_ARROW_TIME)
{ //每隔10个时间片(即箭头闪烁的时间),刷新屏幕
InvalidateRect(hWnd,NULL,false);
}
break;
case GAME_IN_PRE: //游戏LIFE,WORLD提示
if(c1.DecCount())
{
//计时结束,进入游戏。
gamemap.SetGameState(GAME_IN);
c1.ReStart(TIME_GAME_IN); //启动计时300秒
}
InvalidateRect(hWnd,NULL,false); //刷新屏幕
break;
case GAME_IN: //游戏进行中
case GAME_WIN: //游戏进行中,过关
c1.DecCount();//计时器计时
if(0 == c1.iNum%SKY_TIME)
{
bmSky.MoveRoll(SKY_SPEED);//云彩移动
}
gamemap.ChangeFrame(c1.iNum);//帧控制
rmain.Move();//人物移动
gamemap.MoveView();//视图移动
gamemap.CheckRole();//角色检测
gamemap.CheckAni(c1.iNum);//逻辑数据检测
gamemap.IsWin(); //胜负检测
InvalidateRect(hWnd,NULL,false); //刷新屏幕
break;
case GAME_WIN_WAIT: //游戏进行中,过关,停顿2秒
if(c1.DecCount())
{
//计时结束,进入游戏LIFE,WORLD提示
gamemap.SetGameState(GAME_IN_PRE);
InvalidateRect(hWnd,NULL,false); //刷新屏幕
}
break;
case GAME_PUMP_IN: //游戏进行中,进入水管,停顿2秒
if(c1.DecCount())
{
//计时结束,切换地图
gamemap.ChangeMap();
gamemap.SetGameState(GAME_IN); //进入游戏
c1.ReStart(TIME_GAME_IN); //启动计时300秒
rmain.SetAni(ROLE_ANI_UP); //设置玩家出水管动画
}
InvalidateRect(hWnd,NULL,false); //刷新屏幕
break;
case GAME_FAIL_WAIT: //游戏进行中,失败,停顿2秒
if(c1.DecCount())
{
//计时结束,加载地图
gamemap.Fail_Wait();
}
break;
case GAME_PASS: //全部通关,停顿2秒
if(c1.DecCount())
{
//计时结束,设置游戏状态:游戏菜单
gamemap.SetGameState(GAME_PRE);
}
InvalidateRect(hWnd,NULL,false); //刷新屏幕
break;
case GAME_OVER: //游戏结束,停顿3秒
if(c1.DecCount())
{
//计时结束,设置游戏状态:游戏菜单
gamemap.SetGameState(GAME_PRE);
}
InvalidateRect(hWnd,NULL,false); //刷新屏幕
break;
}
break;
case WM_KEYDOWN: //按键处理
if(gamemap.KeyProc(wParam))
InvalidateRect(hWnd,NULL,false);
break;
case WM_KEYUP: //按键“抬起”处理
gamemap.KeyUpProc(wParam);
break;
case WM_SIZE: //窗口大小调整,代码略
break;
case WM_DESTROY: //窗口销毁,释放DC, 代码略
break;
消息处理函数完成。
终于,所有模块全部完成,游戏制作完成。整个工程差不多3000行代码。第一个制作超级玛丽的程序员,是否用了这么多代码,肯定没有。当时,应该是汇编。3000行C++代码,还达不到汇编程序下的地图规模、图片特效、游戏流畅度。可见,程序的乐趣无穷。至于,下一个游戏是什么样子,且听下回分解。
附:
超级玛丽第一版源码链接:http://download.csdn.net/source/497676
超级玛丽增强版源码链接:http://download.csdn.net/source/584350