MFC双人版俄罗斯方块

来源:互联网 发布:nginx lvs 负载均衡 编辑:程序博客网 时间:2024/04/30 09:49

俄罗斯方块

第一次单独完成了一个小游戏,虽然是按照老师编的实验指导书上面单人版俄罗斯方块改过来的,但是还是很有成就感的。


砖块实现思路: 给砖块设置一个中心点,然后依次按照中心块的位置设置其他块的坐标,在移动和变换砖块时,只需要变换中心块的位置,然后其他块跟着一起移动。这样做既可以有利于旋转,实现起来也比较简单.


游戏截图:


启动界面


进入游戏界面



类的定义:

首先定义2个基类CBin和CBrick, CBin用来游戏界面的绘制,CBrick是一个抽象类,用来作为各种方块的基类,所以就有了5个派生类CIBrick, CLBrick, CSBrick, COBrick, CTBrick

//CBin类

class CBin {
private:
unsigned char** image;
unsigned int width;
unsigned int height;
public:
CBin(unsigned int w, unsigned int h);
~CBin();
unsigned int getWidth() { return width; };
unsigned int getHeight() { return height; };
void getImage(unsigned char** destImage);
void setImage(unsigned char** srcImage);
unsigned int removeFullLines();
};


//CBrick类

class CBrick {
protected:
unsigned int orientation; //表示砖块的状态
unsigned int posX; //砖块特定点的 X 坐标
unsigned int posY; //砖块特定点的 Y 坐标
unsigned char colour; //砖块的颜色
public:
unsigned int getOrientation() { return orientation; };
unsigned int getPosX() { return posX; };
unsigned int getPosY() { return posY; };
unsigned char getColour() { return colour; };
void setOrientation(unsigned int newOrient) { orientation = newOrient; };
void setPosX(unsigned int newPosX) { posX = newPosX; };
void setPosY(unsigned int newPosY) { posY = newPosY; };
void setColour(unsigned char newColour) { colour = newColour; };
virtual int shiftLeft(CBin* bin) = 0;
virtual int shiftRight(CBin* bin) = 0;
virtual int shiftDown(CBin* bin) = 0;
virtual int rotateClockwise(CBin* bin) = 0;
virtual int checkCollision(CBin* bin) = 0;
virtual void operator>>(unsigned char** binImage) = 0;
virtual void putAtTop(unsigned int newOrient, unsigned int newPosX) = 0;
};


//CIBrick必须实现CBrick里面全部的函数,以上其他函数是内联函数所以就有了下面几个函数

class CIBrick : public CBrick {
public:
int shiftLeft(CBin* bin);
int shiftRight(CBin* bin);
int shiftDown(CBin* bin);
int rotateClockwise(CBin* bin);
int checkCollision(CBin* bin);
void operator>>(unsigned char** binImage);
void putAtTop(unsigned int newOrient, unsigned int newPosX);
};



双人版的思路是在单人版的基础上实现的,在TetrisView类里面定义两个对象

//TetrisView.h文件

class CTetrisView : public CView
{
protected: // 仅从序列化创建
CTetrisView();
DECLARE_DYNCREATE(CTetrisView)


// 特性
public:
CTetrisDoc* GetDocument() const;
public:
void DrawImage(CBin* bin, unsigned char** image, CDC* pDC);


// 操作
public:


CBin *bin; //定义玩家1的游戏矩形框指针
CBrick *activeBrick; //定义指向当前下落砖块的指针
int gameOver; //判断游戏是否结束
int brickInFlight; //判断砖块是否处于下落状态
int brickType; //砖块类别
unsigned int initOrientation; //初始状态
int notCollide; //冲突否
unsigned int numLines; //消的行数
unsigned char** outputImage;
int difficulty;

//以下为玩家2的内容定义
public:
CBin *bin1; //定义玩家2游戏矩形框指针
CBrick *activeBrick1; //定义指向当前下落砖块的指针
int gameOver1; //判断游戏是否结束
int brickInFlight1; //判断砖块是否处于下落状态
int brickType1; //砖块类别
unsigned int initOrientation1; //初始状态
int notCollide1; //冲突否
unsigned int numLines1; //消的行数
unsigned char** outputImage1;


// 重写
public:
virtual void OnDraw(CDC* pDC);  // 重写以绘制该视图
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);


// 实现
public:
virtual ~CTetrisView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif


protected:


// 生成的消息映射函数
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnGameStart();
afx_msg void OnDiffEasy();
afx_msg void OnDiffMid();
afx_msg void OnDiffSup();
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
void ShowActiveBrick(CDC* dc);
COLORREF GetLightColor(COLORREF m_crBody);
COLORREF GetDarkColor(COLORREF m_crBody);
};


//双缓冲加载位图

void CTetrisView::OnDraw(CDC* pDC)
{
CTetrisDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
int m_nWidth, m_nHeight;
int nWidth, nHeight;
CRect windowRect;
GetClientRect(&windowRect);
nWidth = windowRect.Width();
nHeight = windowRect.Height();


CDC MemDC; //首先定义一个显示设备对象
CBitmap MemBitmap;//定义一个位图对象 //随后建立与屏幕显示兼容的内存显示设备
MemDC.CreateCompatibleDC(NULL);//这时还不能绘图,因为没有地方画
MemBitmap.CreateCompatibleBitmap(pDC, nWidth, nHeight);//建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小,也可以自己定义
CBitmap *pOldBit = MemDC.SelectObject(&MemBitmap);//将位图选入到内存显示设备中
//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上
MemDC.FillSolidRect(0, 0, nWidth, nHeight, RGB(0, 0, 0));//先用背景色将位图清除干净,这里我用的是白色作为背景 你也可以用自己应该用的颜色


//插入图片
CDC TempMemDC;
CBitmap b1;
b1.LoadBitmap(IDB_BITMAP3);
TempMemDC.CreateCompatibleDC(pDC);
TempMemDC.SelectObject(&b1);// MemDC2与图片链接
MemDC.BitBlt(0, 0, nWidth, nHeight, &TempMemDC, 0, 0, SRCCOPY);


//显示玩家1的当前方块
ShowActiveBrick(&MemDC);
//绘制界面
DrawImage(bin, outputImage, &MemDC);
DrawImage(bin1, outputImage1, &MemDC);

pDC->BitBlt(0, 0, nWidth, nHeight, &MemDC, 0, 0, SRCCOPY);//将内存中的图拷贝到屏幕上进行显示
MemDC.SelectObject(pOldBit);
MemBitmap.DeleteObject();
MemDC.DeleteDC();
}


//绘制游戏面板

void CTetrisView::DrawImage(CBin *bin, unsigned char** image, CDC *pDC)

{

CRect rc;
CRect rc1;
COLORREF BrickColor[8] = {0xFF0000,0x00FF00,0x0000FF, 0x00FFFF, 0xFFFF00, 0x800080, 0xDEB887};
if (width == 10 + LocateOfPlayer1Game)
{
for (i = 0; i < height; i++)
{
for (j = LocateOfPlayer1Game; j < width; j++)
{
rc = CRect(j*nSize, i*nSize, (j + 1)*nSize, (i + 1)*nSize);
//绘制面板
if (image[i][j] != 0)
{
pDC->FillRect(rc, &CBrush(BrickColor[image[i][j]]));
pDC->Draw3dRect(rc, GetLightColor(BrickColor[image[i][j]]), GetDarkColor(BrickColor[image[i][j]]));
}
}
}
}

原创粉丝点击