此处,我感受到复用性的好处,将与显示或平台无关的东西分装在一起,如果能进一步抽象的尽量抽象,就可以充分发挥其复用性。
具体的关于Snake的设计,请参见我的博客《C++版贪吃蛇游戏》。
下面是VC下的游戏界面截图:
在这里说一下VC下与C++不同的及新家的东西。
1)播放背景音乐:
- //引入库
- #include <mmsystem.h>
- #pragma comment(lib,"winmm.lib")
- // TODO: Add your command handler code here
- /加背景音乐
- PlaySound(NULL,NULL,NULL);//停止用playsound函数播放的音乐
- mciSendString( "open ./res/650.mp3 alias bk", 0, 0, 0 );
- mciSendString( "play bk repeat", 0, 0, 0 );
- ///
2)显示的不同,这是最大的变化,但不难,因为在C++中就已用二维数组表示了,这里只需根据二维数组的值,来显示成为不同的图片就行了。
看一部分代码:
- /
- // CSnakeView message handlers
- void CSnakeView::display(int image[20][20],CDC *pDC)
- {
- int nSize=20;
- CRect rect;
- CRect rc;
- CBitmap bitmap9;
- bitmap9.LoadBitmap(IDB_BITMAP8);
- CBrush brush9;
- brush9.CreatePatternBrush(&bitmap9);
- GetClientRect(&rect);
- pDC->FillRect(rect,&brush9);
- // pDC->Rectangle(21,21,421,421);
- CBitmap bitmap10;
- bitmap10.LoadBitmap(IDB_BITMAP9);
- CBrush brush10;
- brush10.CreatePatternBrush(&bitmap10);
- CRect rec1,rec2,rec3,rec4;
- rec1=CRect(0,0,440,20);
- rec2=CRect(420,20,440,440);
- rec3=CRect(0,0,20,440);
- rec4=CRect(20,420,440,440);
- pDC->FillRect(rec1,&brush10);
- pDC->FillRect(rec2,&brush10);
- pDC->FillRect(rec3,&brush10);
- pDC->FillRect(rec4,&brush10);
- for(i=0;i<20;i++)
- {
- for(j=0;j<20;j++)
- {
- rc=CRect(j*nSize+20,i*nSize+20,(j+1)*nSize+20,(i+1)*nSize+20);
- if(image[i][j]!=0)
- {
- if(image[i][j]==3)
- {
- CBitmap bitmap2;
- bitmap2.LoadBitmap(IDB_BITMAP3);
- CBrush brush1;
- brush1.CreatePatternBrush(&bitmap2);
- CBrush *pOldBrush = pDC->SelectObject(&brush1);
- pDC->Ellipse(rc);
- pDC->SelectObject(pOldBrush);
- //pDC->FillRect(rc,&brush1);
- }
- else if(image[i][j]==1)
- {
- if(direction==2)
- {
- CBitmap bitmap;
- bitmap.LoadBitmap(IDB_BITMAP1);
- CBrush brush;
- brush.CreatePatternBrush(&bitmap);
- pDC->FillRect(rc,&brush);
- }
- else if(direction==4)
- {
- CBitmap bitmap4;
- bitmap4.LoadBitmap(IDB_BITMAP5);
- CBrush brush4;
- brush4.CreatePatternBrush(&bitmap4);
- pDC->FillRect(rc,&brush4);
- }
- else if(direction==6)
- {
- CBitmap bitmap5;
- bitmap5.LoadBitmap(IDB_BITMAP6);
- CBrush brush5;
- brush5.CreatePatternBrush(&bitmap5);
- pDC->FillRect(rc,&brush5);
- }
- else if(direction==8)
- {
- CBitmap bitmap6;
- bitmap6.LoadBitmap(IDB_BITMAP7);
- CBrush brush6;
- brush6.CreatePatternBrush(&bitmap6);
- pDC->FillRect(rc,&brush6);
- }
- }
- else if(image[i][j]==2)
- {
- CBitmap bitmap3;
- bitmap3.LoadBitmap(IDB_BITMAP4);
- CBrush brush3;
- brush3.CreatePatternBrush(&bitmap3);
- CBrush *pOldBrush = pDC->SelectObject(&brush3);
- pDC->Ellipse(rc);
- pDC->SelectObject(pOldBrush);
- // pDC->FillRect(rc,&brush3);
- }
- }
- }
- }
- CBitmap bitmap11;
- bitmap11.LoadBitmap(IDB_BITMAP10);
- CBrush brush11;
- brush11.CreatePatternBrush(&bitmap11);
- CRect rec5;
- rec5=CRect(440,0,540,495);
- pDC->FillRect(rec5,&brush11);
- char buf[100];
- //GotoXY(46,9);
- sprintf(buf,"SCORE:%-5d",score); //记录分数
- //pDC->SetBkMode(TRANSPARENT);
- pDC->TextOut(445,120,buf);
- //GotoXY(46,10);
- sprintf(buf,"LEVEL=%-5d",level); //记录等级
- pDC->TextOut(445,150,buf);
- }
3)为了避免屏幕的闪烁,采用双缓冲机制。
代码:
- void CSnakeView::OnDraw(CDC* pDC)
- {
- CSnakeDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- int m_nWidth,m_nHeight;
- CDC m_memDC;
- CBitmap m_memBmp;
- //1.用于映射屏幕的内存环境
- //获取游戏窗口的大小用于设置下面内存为徒的尺寸
- CRect windowRect;
- GetClientRect(&windowRect);
- m_nWidth=windowRect.Width();
- m_nHeight=windowRect.Height();
- //内存设备环境与屏幕内存环境相关联
- m_memDC.CreateCompatibleDC(pDC);
- //内存为图与屏幕关联,大侠为游戏窗口的尺寸
- m_memBmp.CreateCompatibleBitmap(pDC,m_nWidth,m_nHeight);
- //内存设备环境与内存位图关联,以便通过m_memDC在内存为图上画图
- m_memDC.FillSolidRect(windowRect,RGB(255,255,255));
- m_memDC.SelectObject(&m_memBmp);
- display(image,&m_memDC);
- //把内存DC上的图形拷贝到电脑屏幕上
- pDC->BitBlt(0,0,m_nWidth,m_nHeight,&m_memDC,0,0,SRCCOPY);
- m_memDC.DeleteDC(); //删除DC
- m_memBmp.DeleteObject();//删除位图
- // TODO: add draw code for native data here
- }
4)其他的就是采用VC中的按键响应函数及Timer时间控制就OK了,别的都和C++差不多。