打僵尸采用win32API编写,具体实现功能:
A.仿照打地鼠游戏编写,只不过显示的是僵尸
B.僵尸出现是慢慢冒出来的
C.能统计得分,同时出现僵尸数量随分数上升
D.打击僵尸有爆炸特效
透明贴图,爆炸动画处理
太简单了,就像打地鼠。
游戏背景地图是一张植物大战僵尸草地的图片,其中每个格子对应着将要出现的僵尸的位置。
hBmpBackground=(HBITMAP)LoadImage(hinstance,MAKEINTRESOURCE(IDB_BITMAPground), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); void backgroudDraw()//游戏进程背景绘制 { SelectObject(hdcImageStore, hBmpBackground ); BitBlt( hdcImageDraw, 0,0, C_TILE_W*C_MAP_W,C_TILE_H*C_MAP_H, hdcImageStore,0, 0 , SRCCOPY); }
hBmpBackground是一个HBITMAP全局变量,从资源中获得背景地图的句柄,然后载入到内存位图hdcImageDraw中。
这里最多同时出现3个僵尸。定义一个僵尸结构体数组,这里只有3个元素,对应的就是出现的僵尸。当bActiveFlg为true时,显示出来这个僵尸。
typedef struct { bool bActiveFlg; int iXpos; // λÖÃX int iYpos; // λÖÃY }__ZOMBIE; __ZOMBIE ZOMBIE[3];
<span style="font-family: 宋体; font-size: 12pt; text-indent: 21pt; background-color: rgb(255, 255, 255);">地图也同时定义一个结构体。地图是绿色与浅绿色相间的就是每个格子,一共有</span><span style="font-size: 12pt; background-color: rgb(255, 255, 255); font-family: 'Times New Roman';">5</span><span style="font-family: 宋体; font-size: 12pt; text-indent: 21pt; background-color: rgb(255, 255, 255);">行,</span><span style="font-size: 12pt; text-indent: 21pt; background-color: rgb(255, 255, 255); font-family: 'Times New Roman';">9</span><span style="font-family: 宋体; font-size: 12pt; text-indent: 21pt; background-color: rgb(255, 255, 255);">列格子,这里用一个</span><span style="font-size: 12pt; text-indent: 21pt; background-color: rgb(255, 255, 255); font-family: 'Times New Roman';">5*9</span><span style="font-family: 宋体; font-size: 12pt; text-indent: 21pt; background-color: rgb(255, 255, 255);">二维数组表示。</span>
typedef struct { char bExisteFlg; int iXmap; // λÖÃX int iYmap; }__MAP; __MAP MAP[5][9];
地图初始化,把二维数组的iXmap,iYmap坐标与具体的行列号对应起来。
这里的坐标是左上角为原点的屏幕坐标。后面只要知道MAP的行列号就知道对应的坐标。
typedef struct { char bExisteFlg; int iXmap; // λÖÃX int iYmap; }__MAP; __MAP MAP[5][9];
地图初始化,把二维数组的iXmap,iYmap坐标与具体的行列号对应起来。
这里的坐标是左上角为原点的屏幕坐标。后面只要知道MAP的行列号就知道对应的坐标。
void mapInit () { int i,j; for ( i = 0; i < 5; i++) { for (j = 0; j < 9; j++) { MAP[i][j].iXmap=30+80*j; MAP[i][j].iYmap=80+100*i; } } }
随机产生僵尸的出现坐标。主要是随机产生iAZomX,iAZomY数组的每个元素。其中iAZomX数组每个元素随机为0~4的值,iAZomY数组每个元素随机为0~8的值,对应的三个僵尸的初始位置就置为地图二维数组对应iAZomX行,iAZomY列的元素位置。同时地图二维数组上相应位置标记有僵尸,置1对应1号僵尸,置2对应这个格子是2号僵尸。
void coordChange () { int i,j,k; static int iAZomX[3]={0,0,0}; static int iAZomY[3]={0,0,0}; for ( i = 0; i < 3; i++) { iAZomX[i]=rand()%5; iAZomY[i]=rand()%9; } for ( i = 0;i < 3;i++ ) { ZOMBIE[i].iXpos=MAP[iAZomX[i]][iAZomY[i]].iXmap; ZOMBIE[i].iYpos=MAP[iAZomX[i]][iAZomY[i]].iYmap; } for ( i = 0; i < 5; i++) { for (j = 0; j < 9; j++) { if ( i== iAZomX[0] && j == iAZomY[0]) MAP[i][j].bExisteFlg=1; else if ( i== iAZomX[1] && j == iAZomY[1]) MAP[i][j].bExisteFlg=2; else if ( i== iAZomX[2] && j == iAZomY[2]) MAP[i][j].bExisteFlg=3; else MAP[i][j].bExisteFlg=0; } } }
随着分数iScore的增加,依次激活相应数量的僵尸,即使僵尸的bActiveFlg标志置为1,激活了的僵尸就会显示出来。
bool randomCreate ( DWORD dwTime ) { static long int iLastUpdate=0; if( ( dwTime - iLastUpdate )>100 ) //µ±Ê±¼ä´óÓÚ100ʱ²¥·ÅÏÂÒ»¸ö¶¯» { iLastUpdate = dwTime; cSumFlg++; if(cSumFlg >= 12) { if(iScore < 100) ZOMBIE[0].bActiveFlg=1; if( 100 <= iScore &&iScore < 200) { ZOMBIE[1].bActiveFlg=1; ZOMBIE[0].bActiveFlg=1; } if( 200 <= iScore) { ZOMBIE[1].bActiveFlg=1; ZOMBIE[2].bActiveFlg=1; ZOMBIE[0].bActiveFlg=1; } coordChange(); cSumFlg = 0; } } return true; }
使用全局变量cSumFlg,cSumFlg在randomCreate 函数中是会自增的,每次贴僵尸图与cSumFlg结合起来。僵尸显示的纵坐标ZOMBIE[i].iYpos+100-cSumFlg*10,每次显示在y方向递增cSumFlg*10。
<pre name="code" class="cpp">void zombieDraw(DWORD dwTime ) { int i = 0; SelectObject(hdcImageStore, hBmpZombie); for (i = 0; i < 3; i++) { if ( ZOMBIE[i].bActiveFlg == 1) { transparentPaint( hdcImageDraw,ZOMBIE[i].iXpos, ZOMBIE[i].iYpos+100-cSumFlg*10, 80, cSumFlg*10, 0,0, RGB(255,255,255) ); } } }
响应鼠标左键点击消息,扫描地图二维数组,当鼠标点击坐标落在对应的地图某个格子中,判断那个格子中是否有僵尸标记,有的话清空地图格子的僵尸标记,并且把对应僵尸数组中那个元素的bActiveFlg属性置零。这样在绘图中因为某僵尸的bActiveFlg为0就不会继续绘制那个僵尸了,实现打死僵尸效果。
for ( row = 0; row < 5; row++) { for (col = 0; col < 9; col++) { if ( MAP[row][col].bExisteFlg!=0&&LOWORD(lParam)<=MAP[row][col].iXmap+80&&LOWORD(lParam)>=MAP[row][col].iXmap&&HIWORD(lParam)<=MAP[row][col].iYmap+100&&HIWORD(lParam)>=MAP[row][col].iYmap) { if(MAP[row][col].bExisteFlg == 1) ZOMBIE[0].bActiveFlg=0; else if(MAP[row][col].bExisteFlg == 2) ZOMBIE[1].bActiveFlg=0; else if(MAP[row][col].bExisteFlg == 3) ZOMBIE[2].bActiveFlg=0; cHitFlg=1; MAP[row][col].bExisteFlg=0;
首先定义一个爆炸结构体。
struct Explosion { int p_nX; //爆炸位置x int p_nY; // 爆炸位置y int m_nCurFrame; // 当前帧 int m_nType; // 爆炸类型 int m_oldUpdate; // 播放下一张连续图更新时间 struct Explosion *next; }; struct Explosion *Explosionhead ; //全局爆炸链表
爆炸链表里面能存十个元素,说明同时能进行十个爆炸。把当前帧置为-1,这样每次从爆炸链表里取某个还没播放的元素进行爆炸的播放。
void bombInit() { int i; struct Explosion *e; //´´½¨±¬Õ¨Á´±í if(Explosionhead==NULL) { Explosionhead=(struct Explosion*)malloc(sizeof(struct Explosion)); Explosionhead->next=NULL; } e=Explosionhead; for( i=0; i<10; i++ ) { e->next=(struct Explosion*)malloc(sizeof(struct Explosion)); e->m_nCurFrame=-1; e->m_oldUpdate=0; e->m_nType=0; e->next->next=NULL; e=e->next; } }
遍历爆炸链表,找到还没播放帧为-1的元素,即那个元素没处于播放状态,把它播放帧置零,表示激活了,并把相应的打击的坐标传入。
void PlayExplosion( int nX, int nY, int nType ) { int i; struct Explosion *e; e=Explosionhead; // ±¬Õ¨´¦Àí for( i=0; i<10; i++ ) { // if( !((e->m_nCurFrame==-1) ? false : true) ) //ÅжÏÕâ¸ö±¬Õ¨³ÉÔ±ÊÇ·ñÒѾ±»¼¤»îÁË Èç¹ûû±»¼¤»î if( e->m_nCurFrame==-1 ) { e->p_nX= nX; e->p_nY= nY; e->m_nType= nType; e->m_nCurFrame = (nType==0)?0:0; break;//Õâ¸öbreak ÊÇʲôÒâ˼ } e=e->next; } }
当某爆炸元素处在激活状态,即播放帧不为-1,进行播放帧随着时间递增。
bool ExplosionEnterFrame(int *nCurFrame , int *nType , int *oldUpdate , DWORD dwTime ) { if( *nCurFrame == -1 ) return false; if( ( dwTime - *oldUpdate )>=100 ) //µ±Ê±¼ä´óÓÚ100ʱ²¥·ÅÏÂÒ»¸ö¶¯» { *oldUpdate = dwTime; (*nCurFrame)++; if( *nType == 0 && *nCurFrame>2 ) //±¬Õ¨ÀàÐÍnTypeΪ0£¬²¥·ÅͼƬÉÙ£¬Ê±¼äÒ²¶Ì£¬Ò»°ãÊÇ»÷ÖÐÕÏ°Îï { *nCurFrame = -1; } if( *nType == 1 && *nCurFrame>7 ) //±¬Õ¨ÀàÐÍnTypeΪ1£¬½«²¥·ÅÍê7¸öͼƬ£¬Ê±¼ä³¤£¬Ò»°ãÊÇ»÷ÖÐÄ¿±ê { *nCurFrame = -1; } } return true; }
遍历爆炸链表,当某元素播放帧不为-1时,每次从爆炸的横向长图片中取出与播放帧nCurFrame对应的位置的一小块进行贴图,结合时间播放帧递增,实现换图功能,爆炸的特效得以实现。
void ExplosionDraw(int nX , int nY , int m_nCurFrame) { if( m_nCurFrame != -1 ) //µÈÓÚ-1²»»æÖƱ¬Õ¨ { SelectObject(hdcImageStore , hBmpBomb ); transparentPaint( hdcImageDraw, nX-16, nY-16, 32,32, m_nCurFrame*32, 0, RGB(0x0,0x0,0x0) ); } } // »æÖƱ¬Õ¨³¡Ãæ void DrawExplosion( ) { int i=0; struct Explosion *e; e=Explosionhead; for( i=0; i<10; i++ ) { ExplosionDraw(e->p_nX , e->p_nY , e->m_nCurFrame); e=e->next; } }
设计报告下载
点击打开链接点击打开链接