学C++的时候,课程设计编写了C++版的贪吃蛇游戏,当时,将很多的东西都分装在了Snake类中,所以,将其移植到VC中,只需将Snake类稍作修改,然后添加到VC中即可。
此处,我感受到复用性的好处,将与显示或平台无关的东西分装在一起,如果能进一步抽象的尽量抽象,就可以充分发挥其复用性。
具体的关于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++差不多。
转载请标明出处:http://blog.csdn.net/u012027907