首页
社区
课程
招聘
[原创]vc++游戏源码
发表于: 2008-9-23 14:03 4815

[原创]vc++游戏源码

2008-9-23 14:03
4815
背景位图:800*600   IDB_BITMAP1

我方飞机:50*50     IDB_BITMAP2

敌方飞机:50*50     IDB_BITMAP3

我方子弹:50*50     IDB_BITMAP4

对方子弹:50*50     IDB_BITMAP6

炸毁飞机:60*60     IDB_BITMAP5  为了更好显示爆炸效果

火力位图:50*50     IDB_BITMAP7
飞机游戏,主角当然是飞机。飞机分成两方:玩者的一方(分为单人和双人,由于前面已经实现了俄罗斯方块游戏和老鼠游戏的双人游戏,这里只是实现游戏的单人版,双人版就作为读者的练习)和计算机的一方。我们称为正方和对方。

正方:具有生命力(本游戏设置为5),有火力(本游戏包括三种:单火力、双火力和强火力),生命力每次被炸毁就减一,而当火力值大于5时,生命力和火力强度同增。而火力,开始是0,表示单火力,之后,每次添加一个火力值就加一。

反方:由计算机按时地、随机地产生飞机,按时地发射子弹,按时地移动子弹的位置。(游戏的实现,往往就是因为要实现计算机的这些按时的“智能”的操作。)

火力:之所以把火力作为一个角色,因为它的存在,是独立的;它的作用又是为正方服务的,它的产生也是我们对程序的专门设置而实现的。我们可以忽略它的存在,同时,由于本游戏的特点(其实也是许多游戏的特点),我们由必须依靠它的存在,它可以给我们生命力和火力。

背景:我把背景做为一个角色,确实有一点不大合理,但是,每个人做事都是有他的原因的。我在这里把它提出来,只是为了强调一下它的作用。

游戏的实现:

依然是全屏,而且是更彻底的全屏,或许应该说是真正的全屏。

支持多种分辨率,当然,前面一章后面我们已经讲了一种方案,这里介绍的是另外一种。由于位图的限制,我们不可能总是画那么多的位图,我们也不可能利用放大缩小位图的方法,这样会产生严重的闪烁。那么,我们可以利用留空白的方法,我们制造最基本的位图,宽800,然后,利用获取屏幕大小的函数取得屏幕分辨率的大小,然后设法把位图显示在屏幕的中间。

背景位图的显示,由于我们的背景位图大小是有限制的,高度不可以大于2000
添加类名为:CGame
所有的变量和函数都添加到这个类里面。如下:

   //显示信息

      void DrawMessage(CDC*pDC,int width,int height);

      //火力位图是否出现

      void FireOutIf();

      //子弹移动

      void shotmove();

      //敌机发射子弹

      void Enemyshot();

      //敌机出现

      void Enemyplaneout();

      //我方射击

      void Shot();

      //设置透明位图

      void TransparentBitmap(HDC hdc, HBITMAP hBitmap,

                                       short xStart, short yStart, short xadd,short yadd,

                                          COLORREF cTransparentColor);

      //透明色

    COLORREF cTransparentColor;

      //飞机爆炸位图

      CBitmap enemydead;

      //敌机子弹位图

      CBitmap bmenemyshot;

      //敌机位图

      CBitmap enemy;

      //我方子弹

      CBitmap bmshot;

      //我方飞机

      CBitmap plane;

      //我方飞机数量

      short numplane;

      //背景数组

      int back[15][12];

      //飞机出现位置

      int xStart,yStart;

      //火力位图

      CBitmap bmfire;

      //火力位置

      CPoint pointfire;

      //是否出现

      bool iffire;

      //火力强度

      int fire;

CmainFrame:

       CRect m_FullScreenRect;//全屏显示时的窗口位置

       void OnFullScreen();

、、、、、、、、、、、、、、、、、、
class CMy6_1View :

             //暂停

                    bool bPause;

                    //屏幕宽度

                    int width;

                    //屏幕高度

                    int height;

                    //类CGame

                    CGame game;

                    //背景位图移动大小:10

                    int goup;

                    //背景位图

                    CBitmap backmap;

    当然,下面三个函数是少不了的:

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

             afx_msg void OnTimer(UINT nIDEvent);

             afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);

显示界面:

我方子弹:2

          敌方飞机:3

          敌机子弹:向左下角:4

          敌机子弹:向正下方:5

          敌机子弹:向右下角:6

          敌机炸毁:7

          我机炸毁:8

    说明:敌机子弹的不同的值是为了下一次下移的需要。

          我方飞机和火力分别用一个点表示。

   void CMy6_1View::OnDraw(CDC* pDC)

{

      int i,j;

      CMy6_1Doc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      // TODO: add draw code for native data here

      CRect WindowRect;

      GetWindowRect(&WindowRect);

      //屏幕宽度

      width=WindowRect.right-WindowRect.left;

      //屏幕高度

      height=WindowRect.bottom-WindowRect.top;

      CDC Dc;

       if(Dc.CreateCompatibleDC(pDC)==FALSE)

               AfxMessageBox("Can't create DC");

      //在不同位置显示位图

     Dc.SelectObject(backmap);

      //显示两张位图使它们连接

      pDC->BitBlt((width-800)/2,0,800,height,&Dc,0,goup-2000,SRCCOPY);

      pDC->BitBlt((width-800)/2,0,800,height,&Dc,0,goup,SRCCOPY);

      CClientDC dc(this);

      //显示

      //检查背景数组

      for(i=0;i<15;i++)

             for(j=0;j<12;j++)

             {

                    //显示我方子弹

                    if(game.back[i][j]==2)

                           //利用透明显示函数

                           game.TransparentBitmap(dc.GetSafeHdc(), game.bmshot,(width-800)/2+i*50+20,j*height/600*50, 0,0, game.cTransparentColor);     

                    //显示敌机

                    if(game.back[i][j]==3)

                           game.TransparentBitmap(dc.GetSafeHdc(), game.enemy,(width-800)/2+i*50+20,j*height/600*50, 0,0, game.cTransparentColor);     

                    //飞机炸毁

                    if(game.back[i][j]==7||game.back[i][j]==8)

                           game.TransparentBitmap(dc.GetSafeHdc(), game.enemydead,(width-800)/2+i*50+20,j*height/600*50, 0,0, game.cTransparentColor);     

                    //敌机子弹

                    if((game.back[i][j]==5)||(game.back[i][j]==4)||(game.back[i][j]==6))

                           game.TransparentBitmap(dc.GetSafeHdc(), game.bmenemyshot,(width-800)/2+i*50+20,j*height/600*50, 0,0, game.cTransparentColor);     

             }

             //显示火力位图

      game.TransparentBitmap(dc.GetSafeHdc(), game.bmfire,(width-800)/2+game.pointfire.x*50+20,  game.pointfire.y*height/600*50, 0,0, game.cTransparentColor);

      //显示我方飞机

      game.TransparentBitmap(dc.GetSafeHdc(), game.plane,(width-800)/2+game.xStart*50+20,  game.yStart*height/600*50, 0,0, game.cTransparentColor);     

      //显示信息

      game.DrawMessage(pDC,width,height);

      //信息的飞机位图

      game.TransparentBitmap(dc.GetSafeHdc(), game.plane,(width-800)/2+20,  height-80, 0,0, game.cTransparentColor);      

      //信息的火力位图

      game.TransparentBitmap(dc.GetSafeHdc(), game.bmfire,(width-800)/2+800-120, height-80, 0,0, game.cTransparentColor);     

}

添加信息提示:

   void CGame::DrawMessage(CDC *pDC,int width,int height)

{

      int nOldDC=pDC->SaveDC();      

      //设置字体

      CFont font;   

      if(0==font.CreatePointFont(250,"Comic Sans MS"))

                                  {

                                         AfxMessageBox("Can't Create Font");

                                  }

      pDC->SelectObject(&font);

    //设置字体颜色及其背景颜色

      CString str;

      pDC->SetTextColor(RGB(0,10,244));

      pDC->SetBkColor(RGB(0,255,0));

    //输出数字

      str.Format("%d",numplane);  

      pDC->TextOut((width-800)/2+70,height-80,str);

      str.Format("%d",fire);   

      pDC->TextOut((width-800)/2+800-70,height-80,str);

      pDC->TextOut((width-800)/2+200,height-40,"暂停:F3   退出:Esc");

      pDC->RestoreDC(nOldDC);

}

下面设置时间间隔:

   int CMy6_1View::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

      if (CView::OnCreate(lpCreateStruct) == -1)

             return -1;

      

      // TODO: Add your specialized creation code here

      SetTimer(1,200,NULL);

      return 0;

}

时间段的操作:

第一点就是移动背景位图。

第二点是实现对方的智能操作。

第三点是清理背景数组不该再出现的位图。

   void CMy6_1View::OnTimer(UINT nIDEvent)

{

      // TODO: Add your message handler code here and/or call default

      int i,j;

      //背景位图下移

      goup- =10;

      //位图到了边界

      if(goup<0)

      //位图在开头

             goup=2000;

      //每100点,即两秒执行一次

      if(goup%100==0)

      {

             //出现敌机

             game.Enemyplaneout();

             //敌机发射

             game.Enemyshot();

      }

      if(goup%1100==0)

             //火力位图操作

             game.FireOutIf();

      //重画

      OnDraw(GetDC());

      //数组清空

      for(i=0;i<15;i++)

             for(j=0;j<12;j++)

                    if(game.back[i][j]==2||game.back[i][j]==7||game.back[i][j]==8)

                           game.back[i][j]=0;

      //敌机子弹移动

      game.shotmove();

      CView::OnTimer(nIDEvent);

}

键盘操作:
void CMy6_1View::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)

{

      // TODO: Add your message handler code here and/or call default

      switch(nChar)

      {

      case VK_F3:

             //暂停是否

             bPause=!bPause;

             //是,设置计时器

             if(bPause)

                    SetTimer(1,200,NULL);

             //否,停止计时

             else

                    KillTimer(1);

             break;

      //子弹按钮

      case VK_SPACE:

             //我方发射子弹

             game.Shot();

             break;

             //左移

      case VK_LEFT:

             //位置减1

             game.xStart--;

             //边界

             if(game.xStart<0)

                    game.xStart=0;

             break;

             //道理同上

      case VK_RIGHT:

             game.xStart++;

             if(game.xStart>14)

                    game.xStart=14;

             break;            

      //上移

      case VK_UP:

             if(game.yStart>0)

                    game.yStart--;

             break;

      //下移

      case VK_DOWN:

             if(game.yStart<10)

                    game.yStart++;

             break;

      }

      //如果火力位图位置和我方飞机位置相同

      if((game.pointfire.x==game.xStart)&&(game.pointfire.y==game.yStart))

             {

             //火力位图消失

                    game.iffire=false;

           if(game.fire>5)

                    {

                           game.fire++;

                           game.numplane++;

                    }

                    else

                           game.fire++;

                    //火力位图移动到见不到的地方

                    game.pointfire.y=-1;

             }

      OnDraw(GetDC());

      CView::OnKeyDown(nChar, nRepCnt, nFlags);

}

透明位图函数的添加:

   void CGame::TransparentBitmap(HDC hdc, HBITMAP hBitmap,

                                       short xStart, short yStart, short xadd,short yadd,

                                          COLORREF cTransparentColor){}

我方发射子弹:

//以2表示子弹

void CGame::Shot()

{

      int i;

      //火力0  一线火力

      if(fire==0)

             //从飞机前方到尽头

             for(i=0;i<yStart;i++)

             {

                    //如果有敌机

                    if(back[xStart][i]==3)

                           //敌机被炸位图

                           back[xStart][i]=7;

                    else

                           //我方子弹位图

                           back[xStart][i]=2;

             }

             //火力1  两线火力

      if(fire==1)

      {

             for(i=1;i<=yStart;i++)

             {

                    //如果不出界

                    if((xStart-i)>=0)

                    {

                           //左上角

                           if(back[xStart-i][yStart-i]==3)

                                  back[xStart-i][yStart-i]=7;

                           else

                                  back[xStart-i][yStart-i]=2;

                    }

                    //如果不出界

                    if((xStart+i)<15)

                    {

                           //右上角

                           if(back[xStart+i][yStart-i]==3)

                                  back[xStart+i][yStart-i]=7;

                           else

                                  back[xStart+i][yStart-i]=2;

                    }

             }

      }

      //其他  三线火力

      if(fire>1)

      {

             for(i=1;i<=yStart;i++)

             {

                    if((xStart-i)>=0)

                    {

                           if(back[xStart-i][yStart-i]==3)

                                  back[xStart-i][yStart-i]=7;

                           else

                                  back[xStart-i][yStart-i]=2;

                    }

                    //正前方

                    if(back[xStart][i]==3)

                           //敌机被炸位图

                           back[xStart][yStart-i]=7;

                    else

                        back[xStart][yStart-i]=2;

                    if((xStart+i)<15)

                    {

                           if(back[xStart+i][yStart-i]==3)

                                  back[xStart+i][yStart-i]=7;

                           else

                                  back[xStart+i][yStart-i]=2;

                    }

                    

             }

            

      }

}

敌机出现:

利用随机函数,让敌机在前面三排随意出现。其中,do~while循环语句表示必定要产生一只敌机。

void CGame::Enemyplaneout()

{

      int x,y;

      //初始化随即数种子

      srand(GetTickCount());

      //循环到飞机出现为止

    do

      {

             x=rand()%15;

             y=rand()%3;

             //如果位置空

             if(back[x][y]==0)

                    //显示敌机

                    back[x][y]=3;

      }while(back[x][y]==0);

}

敌机发射子弹:

检查前面三排,如果有敌机,如果敌机的前面三个位置有不为零的,给相应的值。注释如下:

   void CGame::Enemyshot()

{

      int i,j;

      for(i=0;i<15;i++)

             for(j=0;j<12;j++)

                    if(back[i][j]==3)

                    {

                           //如果左下方空

                           if(back[i-1][j+1]==0)

                                  //数组赋值4,表示子弹向左下方移动

                                  back[i-1][j+1]=4;

                           //如果下方空

                           if(back[i][j+1]==0)

                                  //数组赋值5,表示子弹向下方移动

                                  back[i][j+1]=5;

                           //如果右下方空

                           if(back[i+1][j+1]==0)

                                  //数组赋值5,表示子弹向右下方移动

                                  back[i+1][j+1]=6;

                    }

}

敌机子弹移动:

具体情况是,清除这一次的背景数组的值,移动,检查是否出界,否则赋相应的值。接着检查我方飞机是否被炸,并做相应处理。

   void CGame::shotmove()

{

      int i,j;

      for(j=11;j>=0;j--)

             for(i=14;i>=0;i--)

             {

                    //数组赋值4,表示子弹向左下方移动

                    if(back[i][j]==4)

                    {

                           //清除数组

                           back[i][j]=0;

                           //如果不出界

                           if(i>0)

                                  //如果左下方空

                                  if(back[i-1][j+1]==0)

                                         //数组赋值4,表示子弹向左下方移动

                                         back[i-1][j+1]=4;

                    }

                    if(back[i][j]==5)

                    {

                           back[i][j]=0;

                           if(back[i][j+1]==0)

                                  back[i][j+1]=5;

                    }

                    if(back[i][j]==6)

                    {

                           back[i][j]=0;

                           if(i<14)

                                  if(back[i+1][j+1]==0)

                                         back[i+1][j+1]=6;

                    }

                    //如果有敌机或子弹

                    if((back[xStart][yStart]==3)||(back[xStart][yStart]==4)||(back[xStart][yStart]==5)||(back[xStart][yStart]==6))

                    {

                           //数组赋值8,表示我方被炸

                           back[xStart][yStart]=8;

                           //飞机数量减1

                           numplane--;

                    }

                    //如果敌方子弹到了下方边界

                    if((back[i][11]==4)||(back[i][11]==5)||(back[i][11]==6))

                           //赋值0

                           back[i][11]=0;

             }

}

火力实现:

火力位图是定时地出现,位置当然是随机的。但是,出现时必须先判断,如果已经出现,下移;如果没有出现,才出现。而当它的位置和我方飞机位置相同时,我方火力增强,甚至生命力增强。

       //火力位图是否出现

void CGame::FireOutIf()

{

       //没有出现

       if(!iffire)

       {

              //随机位置

              pointfire.x=rand()%15;

              pointfire.y=rand()%8;

              //出现

              iffire=true;

       }

       //出现

       else

       {

              //如果和我方飞机位置相同

              if((pointfire.x==xStart)&&(pointfire.y==yStart))

              {

                     //不出现

                     iffire=false;

                     //如果火力大于5

                     if(fire>5)

                     {

                            //火力加强

                            fire++;

                            //飞机数量加强

                            numplane++;

                     }

                     //否则

                     else

                            //火力加强

                            fire++;

                     //消失

                     pointfire.y=-1;

              }

              else

              {

                     //位置下移

                     pointfire.y++;

                     //出界

                     if(pointfire.y>11)

                            //不出现

                            iffire=false;

              }                          

       }

              

}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//