泡泡堂开发文档.doc_第1页
泡泡堂开发文档.doc_第2页
泡泡堂开发文档.doc_第3页
泡泡堂开发文档.doc_第4页
泡泡堂开发文档.doc_第5页
免费预览已结束,剩余13页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

人机对战版泡泡堂摘要:本游戏模仿盛大网络版泡泡堂,使用C和windows api编写完成,使用到了碰撞检测,人工智能技术。而人工智能部分又使用到A寻路算法,有限状态机。关键词:绘图,碰撞检测,人工智能。1. 引言:实验主要为了掌握基于windows api 下的C语言图像编程,掌握图像的绘制以及windows消息传递机制。选用熟悉的泡泡堂可以去除其它无关因素,从而能迅速投入学习。本游戏大概于2001被盛大游戏公司所做。游戏把数据处理和图形绘制完全分离.玩家的输入状态使用windows消息处理机制接受.另外使用SetTimer模拟多线程的方法类处理不同的数据和绘图。 A.数据处理大体为:接受玩家的输入,针对相应的输入状态判断输入状态是否有效(如碰撞检测,泡泡放置),从而对数据进行不同的修改。B.人工电脑AI:没有直接修改游戏数据,而是模拟人的输入,使用有限状态机判断模拟应该输入什么,而后改输入状态数据。主要逻辑包括所站区域是否安全,不安全便逃跑;是否有道具可以捡,有便去拾取;是否有障碍物可炸,有便去炸;以及根据人物的方位做相应的操作。C.绘制图像:贴背景图,按照特定的顺序贴大小为40*40的各类图片。D.系统对游戏数据的处理,如时间的变化带来的数据变化如泡泡的生命变化,人物是否被炸到及死亡等。2. 总体框架:先初始化各种资源,然后游戏开始,之后定时选择处理绘图或者游戏数据。选择到游戏数据处理时,使用消息处理机制接受玩家信息,判断消息类型并处理,接着是获取AI的返回信息。接着根据按键和AI返回的信息对游戏人物数据进行修改,然后是系统对数据的处理,最后判断人物是否死亡,死亡则重新开始,否则跳转到定时选择处理绘图或者游戏数据重新继续下一轮的处理。流程图如下:窗口及各类数据初始化游戏开始绘图或数据处理选择图像绘制玩家输入退出按键消息处理获取AI本身输入状态释放各种资源并退出是否可行人物数据修改游戏系统对数据处理玩家死亡游戏结束数据重新初始化图1:游戏流程图3.游戏具体功能实现:3.1.背景图加载为了使游戏图像优美,背景图是十分必要的。先加载图片资源,然后在每次绘图的时候首先绘制此背景图:图1:游戏背景图代码实现:InitImage(hdc, imageDC, bBG, cBG, 800, 600,PicBG.bmp);void InitImage(HDC hdc, HDC imageDC , HDC &bImage, HDC &cImage, int width, int height, char fileName)bImage = CreateCompatibleDC(hdc);cImage = CreateCompatibleDC(hdc);HBITMAP tempImage = (HBITMAP)LoadImage(NULL, fileName, IMAGE_BITMAP, width, height, LR_LOADFROMFILE);SelectObject(imageDC, tempImage);SelectObject(bImage, CreateCompatibleBitmap(hdc, width, height);SelectObject(cImage, CreateCompatibleBitmap(hdc, width, height);for(int i=0; iwidth; i+)for(int j=0; jstate+;role2-state+;if(role1-state = BEGINSTATE + 60)begin = false;role1-state = 1;role2-state = 1;win = 0;else if(end)if(role1 != NULL)if(role1-state state = ENDSTATE;else if(role1-state ENDSTATE + 72)end = false;GameStart();begin = true;elserole1-state+;else if(role2 != NULL)if(role2-state state = ENDSTATE;else if(role2-state ENDSTATE + 72)end = false;GameStart();begin = true;elserole2-state+;elseif(win+ 72)end = false;GameStart();begin = true;elseif(role1 != NULL)DealRole(map, role1, state1);if(role2 != NULL)DealRole(map, role2, state2);break;case 3:struct Popo *temp;temp = rolePopo1;while(temp != NULL)if(temp-life = POPOLIFE)DealExPopo(temp-x, temp-y);elsetemp-life+;temp = temp-next;break;case 4:for(int i=0; iWIDTH; i+)for(int j=0; j 100)mapji+;break;case 5:if(role2-state = DEATH | end | begin)break;state2 = true;bool cdirection = false;bool putPopo = false;int direction;AIDeal(map, role2, role1, rolePopo1, direction, putPopo);if(direction = -1)state2 = false;for(int i=0; ikeyStatei = false;role2-state = 0;else if(role2-keyStatedirection != true)state2 = false;role2-direction = direction;for(int i=0; ikeyStatei = false;role2-keyStatedirection = true;role2-state = 0;if(putPopo)role2-addPopo = true;break;default:break;ReleaseDC(hwnd, hdc);3.3游戏界面绘制:首先加载各种需要的图片,并处理成前景图和掩模图的两种图,贴图的时候分别加载前景图和掩膜图即可。之后按照特定的顺序排序贴上泡泡,障碍物,人物,爆炸图片,使画面具有层次感。 图3:游戏各种绘制代码:InitImage(hdc, imageDC, bBG, cBG, 800, 600,PicBG.bmp);InitImage(hdc, imageDC, bBigPopo, cBigPopo, 648, 72,PicBigPopo.bmp);InitImage(hdc, imageDC, bDraw, cDraw, 204, 68,PicDraw.bmp);InitImage(hdc, imageDC, bExplosion, cExplosion, 560, 200,PicExplosion.bmp);InitImage(hdc, imageDC, bGift0, cGift0, 126, 45,PicGift1.bmp);InitImage(hdc, imageDC, bGift1, cGift1, 126, 45,PicGift2.bmp);InitImage(hdc, imageDC, bGift2, cGift2, 126, 45,PicGift3.bmp);InitImage(hdc, imageDC, bGift3, cGift3, 126, 45,PicGift4.bmp);InitImage(hdc, imageDC, bGift4, cGift4, 126, 45,PicGift5.bmp);InitImage(hdc, imageDC, bGift5, cGift5, 126, 46,PicGift6.bmp);InitImage(hdc, imageDC, bPlayer, cPlayer, 110, 50,PicPlayer.bmp);InitImage(hdc, imageDC, bPopo, cPopo, 132, 41,PicPopo.bmp);InitImage(hdc, imageDC, bRole1, cRole1, 288, 256,PicRole1.bmp);InitImage(hdc, imageDC, bRole1Ani, cRole1Ani, 384, 64,PicRole1Ani.bmp);InitImage(hdc, imageDC, bRole1Start, cRole1Start, 480, 64,PicRole1Start.bmp);InitImage(hdc, imageDC, bRole2, cRole2, 336, 268,PicRole2.bmp);InitImage(hdc, imageDC, bRole2Ani, cRole2Ani, 448, 70,PicRole2Ani.bmp);InitImage(hdc, imageDC, bRole2Start, cRole2Start, 560, 71,PicRole2Start.bmp);InitImage(hdc,imageDC,bSandBlockBuff,cSandBlockBuff,40,44,PicSandBlockBuff.bmp);InitImage(hdc,imageDC,bSandBlockYellow,cSandBlockYellow,40,44,PicSandBlockYellwbmp);InitImage(hdc, imageDC, bSandGround, cSandGround, 80, 40,PicSandGround.bmp);InitImage(hdc,imageDC,bSandShopYellow,cSandShopYellow,40,67,PicSandShopYellow.bmp);InitImage(hdc, imageDC, bShadowGift, cShadowGift, 36, 9,PicShadowGift.bmp);InitImage(hdc, imageDC, bShadowPopo, cShadowPopo, 105, 16,PicShadowPopo.bmp);InitImage(hdc, imageDC, bShadowRole, cShadowRole, 32, 15,PicShadowRole.bmp);InitImage(hdc, imageDC, bShadowBlock, cShadowBlock, 45, 45,PicShadowBlock.bmp);InitImage(hdc, imageDC, bStart, cStart, 204, 68,PicStart.bmp);InitImage(hdc, imageDC, bWin, cWin, 204, 70,PicWin.bmp);开始画图:for(int i=WIDTH-1; i=0; i-)for(int j=0; jy = (role1-y/40 * 40)y1 = role1-y / 40;elsey1 = role1-y/40 + 1;if(role1-x = (role1-x/40 * 40)x1 = role1-x / 40;elsex1 = role1-x/40 + 1;if(role2 != NULL)if(role2-y = (role2-y/40 * 40)y2 = role2-y / 40;elsey2 = role2-y/40 + 1;if(role2-x = (role2-x/40 * 40)x2 = role2-x / 40;elsex2 = role2-x/40 + 1;struct Popo *p = rolePopo1;for(int j=0; j=0; i-)if(mapji = EXPLOSIONCENTRE)PaintExplosion(bufHdc, i, j);else if(mapji = POPO & p != NULL)PaintPopo(p ,bufHdc);if(role1 !=NULL & j = y1 & i = x1-1)PaintRole(bufHdc, role1-direction, role1-state/2, 1, role1);if(role2 !=NULL & j = y2 & i = x2-1)PaintRole(bufHdc, role2-direction, role2-state/2, 2, role2);p = p-next;else if(mapji != SANDGROUND | (mapji = GIFT1 & mapji direction, role1-state/2, 1, role1);if(role2 !=NULL & j = y2 & i = x2)PaintRole(bufHdc, role2-direction, role2-state/2, 2, role2);各个函数原型:void PaintPopo(struct Popo *p, HDC bufDC)BitBlt(bufDC, 20+p-x*40-2, 40+p-y*40-1, 44, 41, cPopo, (p-life%8)/3 * 44, 0, SRCAND);BitBlt(bufDC, 20+p-x*40-2, 40+p-y*40-1, 44, 41, bPopo, (p-life%8)/3 * 44, 0, SRCPAINT);BitBlt(bufDC, 20+p-x*40-4, 40+p-y*40-1+30, 35, 16, cShadowPopo, (p-life%8)/3 * 35, 0, SRCAND);BitBlt(bufDC, 20+p-x*40-4, 40+p-y*40-1+30, 35, 16, bShadowPopo, (p-life%8)/3 * 35, 0, SRCPAINT);void PaintExplosion(HDC bufDC, int i, int j)if(mapji = EXPLOSIONRIGHT)BitBlt(bufDC, 20+i*40, 40+j*40, 40, 40, cExplosion , 40*(mapji - EXPLOSIONRIGHT), 120,SRCAND);BitBlt(bufDC, 20+i*40, 40+j*40, 40, 40, bExplosion,40*(mapji - EXPLOSIONRIGHT), 120 , SRCPAINT);else if(mapji = EXPLOSIONLEFT)BitBlt(bufDC, 20+i*40, 40+j*40, 40, 40, cExplosion, 40*(mapji - EXPLOSIONLEFT), 80, SRCAND);BitBlt(bufDC, 20+i*40, 40+j*40, 40, 40, bExplosion, 40*(mapji - EXPLOSIONLEFT), 80, SRCPAINT);else if(mapji = EXPLOSIONDOWN)BitBlt(bufDC, 20+i*40, 40+j*40, 40, 40, cExplosion , 40*(mapji - EXPLOSIONDOWN),40, SRCAND);BitBlt(bufDC, 20+i*40, 40+j*40, 40, 40, bExplosion, 40*(mapji - EXPLOSIONDOWN), 40, SRCPAINT);else if(mapji = EXPLOSIONUP)BitBlt(bufDC, 20+i*40, 40+j*40, 40, 40, cExplosion , 40*(mapji - EXPLOSIONUP), 0, SRCAND);BitBlt(bufDC, 20+i*40, 40+j*40, 40, 40, bExplosion, 40*(mapji - EXPLOSIONUP), 0, SRCPAINT);else if(mapji = EXPLOSIONCENTRE)BitBlt(bufDC, 20+i*40, 40+j*40, 40, 40, cExplosion , 40*(mapji - EXPLOSIONCENTRE)/2), 160, SRCAND);BitBlt(bufDC, 20+i*40, 40+j*40, 40, 40, bExplosion, 40*(mapji - EXPLOSIONCENTRE)/2), 160, SRCPAINT);DC bufDC, int x, int y, int num, struct Role *trole)int roundX, roundY;roundX = trole-x / 40;roundY = trole-y / 40;if(trole-state DEATH)BitBlt(bufDC, 24+trole-x, 72+trole-y, 32, 15, cShadowRole, 0, 0, SRCAND);BitBlt(bufDC, 24+trole-x, 72+trole-y, 32, 15, bShadowRole, 0, 0, SRCPAINT);if(num = 1)if(trole-state = ENDSTATE)BitBlt(bufDC, 16+trole-x, 20+trole-y, 48, 64, cRole1Ani, 48*(trole-state-ENDSTATE)/3)%6+2), 0, SRCAND);BitBlt(bufDC, 16+trole-x, 20+trole-y, 48, 64, bRole1Ani, 48*(trole-state-ENDSTATE)/3)%6+2), 0, SRCPAINT);else if(trole-state = BEGINSTATE)BitBlt(bufDC, 16+trole-x, 20+trole-y, 48, 64, cRole1Start, 48*(trole-state-BEGINSTATE)/3)%10), 0, SRCAND);BitBlt(bufDC, 16+trole-x, 20+trole-y, 48, 64, bRole1Start, 48*(trole-state-BEGINSTATE)/3)%10), 0, SRCPAINT);elseBitBlt(bufDC, 16+trole-x, 20+trole-y, 48, 64, cRole1, 48*y, 64*x, SRCAND);BitBlt(bufDC, 16+trole-x, 20+trole-y, 48, 64, bRole1, 48*y, 64*x, SRCPAINT);else if(num = 2)if(trole-state = ENDSTATE)BitBlt(bufDC, 12+trole-x, 21+trole-y, 56, 71, cRole2Ani, 56*(trole-state-ENDSTATE)/3)%6+2), 0, SRCAND);BitBlt(bufDC, 12+trole-x, 21+trole-y, 56, 71, bRole2Ani, 56*(trole-state-ENDSTATE)/3)%6+2), 0, SRCPAINT);else if(trole-state = BEGINSTATE)BitBlt(bufDC, 12+trole-x, 21+trole-y, 56, 71, cRole2Start, 56*(trole-state-BEGINSTATE)/3%10), 0, SRCAND);BitBlt(bufDC, 12+trole-x, 21+trole-y, 56, 71, bRole2Start, 56*(trole-state-BEGINSTATE)/3%10), 0, SRCPAINT);elseBitBlt(bufDC, 12+trole-x, 21+trole-y, 56, 67, cRole2, 56*y, 67*x, SRCAND);BitBlt(bufDC, 12+trole-x, 21+trole-y, 56, 67, bRole2, 56*y, 67*x, SRCPAINT)elseif(trole-state = DEATH-12 & trole-state x, 25+trole-y, 72, 72, cBigPopo, (-trole-state-1)/6 * 72, 0, SRCAND);BitBlt(bufDC, 10+trole-x, 25+trole-y, 72, 72, bBigPopo, (-trole-state-1)/6 * 72, 0, SRCPAINT);else if(trole-state state DEATH-HELPTIME-12)BitBlt(bufDC, 10+trole-x, 25+trole-y, 72, 72, cBigPopo, 3*72, 0, SRCAND);if(num = 1)if(DEATH-12-trole-state)/5 % 2 = 0)BitBlt(bufDC, 10+trole-x, 25+trole-y, 72, 72, bRole1Death1, 0, 0, SRCPAINT);elseBitBlt(bufDC, 10+trole-x, 25+trole-y, 72, 72, bRole1Death2, 0, 0, SRCPAINT);elseif(DEATH-12-trole-state)/5 % 2 = 0)BitBlt(bufDC, 10+trole-x, 25+trole-y, 72, 72, bRole2Death1, 0, 0, SRCPAINT);elseBitBlt(bufDC, 10+trole-x, 25+trole-y, 72, 72, bRole2Death2, 0, 0, SRCPAINT);else if(trole-state state DEATH-HELPTIME - 37)BitBlt(bufDC, 10+trole-x, 25+trole-y, 72, 72, cBigPopo, (-trole-state+(DEATH-HELPTIME)/5+5) * 72, 0, SRCAND);BitBlt(bufDC, 10+trole-x, 25+trole-y, 72, 72, bBigPopo, (-trole-state+(DEATH-HELPTIME)/5+5) * 72, 0, SRCPAINT);void PaintXY(int x, int y, HDC bufDC, int value)switch(value)case SANDGROUND:if( (x+1)%2=0 & (y+1)%2 = 0 )| (x+1)%2 =1 & (y+1)%2 = 1)BitBlt(bufDC, 20+x*40 , 40+y*40, 40, 40, bSandGround, 0, 0, SRCCOPY);elseBitBlt(bufDC, 20+x*40 , 40+y*40, 40, 40, bSandGround, 40, 0, SRCCOPY);return;case SANDBLOCKYELLOW:BitBlt(bufDC, 15+x*40 , 40+y*40, 45, 45, cShadowBlock, 0, 0, SRCAND);BitBlt(bufDC, 15+x*40 , 40+y*40, 45, 45, bShadowBlock, 0, 0, SRCPAINT);if( (x+1)%2=0 & (y+1)%2 = 0 )| (x+1)%2 =1 & (y+1)%2 = 1)BitBlt(bufDC, 20+x*40 , 36+y*40, 40, 44, cSandBlockYellow, 0, 0, SRCAND);BitBlt(bufDC, 20+x*40 , 36+y*40, 40, 44, bSandBlockYellow, 0, 0, SRCPAINT);elseBitBlt(bufDC, 20+x*40 , 36+y*40, 40, 44, cSandBlockBuff, 0, 0, SRCAND);BitBlt(bufDC, 20+x*40 , 36+y*40, 40, 44, bSandBlockBuff, 0, 0, SRCPAINT);return;case SANDSHOPYELLOW:BitBlt(bufDC, 15+x*40 , 40+y*40, 45, 45, cShadowBlock, 0, 0, SRCAND);BitBlt(bufDC, 15+x*40 , 40+y*40, 45, 45, bShadowBlock, 0, 0, SRCPAINT);BitBlt(bufDC, 20+x*40 , 13+y*40, 40, 67, cSandShopYellow, 0, 0, SRCAND);BitBlt(bufDC, 20+x*40 , 13+y*40, 40, 67, bSandShopYellow, 0, 0, SRCPAINT);return;case GIFT1:case GIFT2:case GIFT3:case GIFT4:case GIFT5:BitBlt(bufDC, 32+x*40 , 75+y*40, 18, 9, cShadowGift, 18*(giftMapyx/9), 0, SRCAND);BitBlt(bufDC, 32+x*40 , 75+y*40, 18, 9, bShadowGift, 18*(giftMapyx/9), 0, SRCPAINT);BitBlt(bufDC, 20+x*40 , 36+y*40, 42, 45, cGiftvalue-GIFT1, 42*(giftMapyx/6), 0, SRCAND);BitBlt(bufDC, 20+x*40 , 36+y*40, 42, 45, bGiftvalue-GIFT1, 42*(giftMapyx/6), 0, SRCPAINT);return;default:return;3.4碰撞检测:先模拟先前移动,判断前方是否有障碍物。左右侧都无障碍物则无碰撞,向前偏移speed,仅右侧有物则计算是否符合一的范围,符合向左侧偏移speed,右侧有则反之,流程图如下:仅右侧有物符合移动方位向左偏移speed方向障碍物检测左右侧均无障碍物向前speed仅左侧有物符合移动方位向右偏移speed模拟移动有物图4:碰撞检测流程图图5:无物 图6:左侧有物 图7:右侧有物 图8:左右均有物代码:bool MoveJudge(int derect, int &x, int &y, int speed)switch(derect)case UP:if(y - speed 0)y = 0;return false;if(y-speed)/40 != y/40)if(x != x/40 * 40)/是if(CanMove(map,(y-speed)/40, x/40 ) & CanMove(map, (y-speed)/40, x/40+1) )return true;else if(!CanMove(map,(y-speed)/40, x/40 ) & (!CanMove(map, (y-speed)/40, x/40+1) )y = y/40 * 40;/移顶return false;else if(y = y/40 * 40)/一块区域可通且在顶部if(CanMove(map,(y-speed)/40, x/40 )if(x - x/40 * 40 = x/40 * 40)x = x - speed;elsex = x/40 * 40;else /右上可通if(x/40 + 1)*40 - x = SKEW)if(x + speed 520)y = 480;return false;if(y+speed-1)/40 != (y-1)/40 | y = 0) /减1很关键,0的处理也很关键if(x != x/40 * 40)/是if(CanMove(map,(y+speed-1)/40+1, x/40 ) & CanMove(map, (y+speed-1)/40+1, x/40+1) )return true;else if( !CanMove(map,(y+speed-1)/40+1, x/40 ) & !CanMove(map, (y+speed-1)/40+1, x/40+1) )if(y != 0)y = (y-1)/40 * 40 + 40;/移顶return false;else if(y = y/40 * 40)/一块区域可通且在顶部if(CanMove(map, (y+speed-1)/40+1, x/40 )if(x - x/40 * 40 = x/40 * 40)x = x - speed;elsex = x/40 * 40;else /右上可通if(x/40 + 1)*40 - x = SKEW)if(x + speed = (x/40 + 1)*40)x = x + speed;elsex = (x/40 + 1)*40;elseif(y != 0)y = (y-1)/40 * 40 + 40;elseif(CanMove(map, (y+speed-1)/40+1, x/40)return true;elseif(y != 0)y = (y-1)/40 * 40 + 40;elsereturn true;break;case LEFT:if(x - speed 0)x = 0;return false;if(x-speed)/40 != x/40)if(y != y/40 * 40)/是if(CanMove(map,y/40, (x-speed)/40 ) & CanMove(map, y/40+1, (x-speed)/40) )return true;else if(!CanMove(map,y/40, (x-speed)/40 ) & !CanMove(map, y/40+1, (x-speed)/40) )x = x/40 * 40;/移顶return false;else if(x = x/40 * 40)/一块区域可通且在顶部if(CanMove(map, y/40, (x-speed)/40 )if(y - y/40 * 40 = y/40 * 40)y = y - speed;elsey = y/40 * 40;else /右上可通if(y/40 + 1)*40 - y = SKEW)if(y + speed 600)x = 560;return false;if(x

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论