一个功能简单的贪吃蛇游戏

1.创建一个基于对话框的程序

2.添加如下所示的编辑框,文本框


并设置这几个按钮位置属性如下


3.准备一张背景图,放入res文件夹内,这样,准备工作就做好了,现在来添加代码了

4.添加Gdi+支持(见前文)

5.在主对话框类中添加两个结构

struct Snake
{
	int x;//位置
	int y;
	int direction;//方向
	
};

struct Food
{
	int x;
	int y;//位置

};
添加共有成员
int m_width;//游戏区宽度
	int m_height ;//游戏区高度
	Image* img;//背景图
	
	list<Snake>snake;//蛇
	Food food;//食物

别忘记添加对list的支持

#include<list>
using std::list;

初始化背景图

在主对话框构造函数中

img = Image::FromFile(_T("res/bkg.jpg"));

6.添加宏,4个方向宏,2个蛇大小宏

#define SNAKE_LEFT 3
#define SNAKE_UP 1
#define SNAKE_RIGHT 2
#define SNAKE_DOWN 0

#define SNAKE_WIDTH 20
#define SNAKE_HEIGHT 20

7.添加定时器消息,初始化在InitInstance()函数中

SetTimer(0, 1000, NULL);

	srand(300);
	//蛇位置初始化
	Snake snakes;
	snakes.x = rand() % 300;
	snakes.y = rand() % 300;
	snakes.direction = rand() % 3;
	for (int i = 0; i < 5; i++)
	{
		snakes.x += SNAKE_WIDTH;
		snake.push_back(snakes);
	}
	//食物初始化
	srand(2000);
	food.x = rand() % m_width;
	food.y = rand() % m_height;

8.添加绘制蛇主体和食物的函数DrawSnake()

void CSnakeDlg::DrawSnake(Graphics & gh)
{
	SolidBrush brush(Color(120,0,0,0));
	
	IsHit();

	gh.FillRectangle(&brush, RectF(food.x, food.y, SNAKE_WIDTH, SNAKE_HEIGHT));//绘制食物

	for (auto &i : snake)
	{
		gh.FillRectangle(&brush, RectF(i.x, i.y, SNAKE_WIDTH, SNAKE_HEIGHT));//绘制蛇
	}
}

再添加碰撞检测函数IsHit()

void CSnakeDlg::IsHit()
{
	SnakeRun();
	Snake head = snake.back();
	if (head.x<0 || head.x>m_width || head.y<0 || head.y>m_height)//撞墙判断
		OnCancel();
}
每一帧蛇移动一次,只动蛇头和蛇尾
void CSnakeDlg::SnakeRun()
{
//只动蛇头和蛇尾,推断出下一步蛇头的位置,压入列表中 ,然后删除蛇尾
	//蛇头是尾元素
	Snake snakes = snake.back();
	Snake head;
	switch (snakes.direction)
	{
	case SNAKE_LEFT:
		head.direction = snakes.direction;
		head.x = snakes.x - SNAKE_WIDTH;
		head.y = snakes.y;
		break;
	case SNAKE_DOWN:
		head.direction = snakes.direction;
		head.x = snakes.x;
		head.y = snakes.y+ SNAKE_HEIGHT;
		break;
	case SNAKE_RIGHT:
		head.direction = snakes.direction;
		head.x = snakes.x + SNAKE_WIDTH;
		head.y = snakes.y;
		break;
	case SNAKE_UP:
		head.direction = snakes.direction;
		head.x = snakes.x ;
		head.y = snakes.y- SNAKE_HEIGHT;
		break;
	}
	snake.push_back(head);
	if(!IsEat())//没有吃到食物就弹出头部
	snake.pop_front();
	
}
是否吃到食物判断
bool CSnakeDlg::IsEat()
{
	Snake snakes = snake.back();
	PointF ptCenter1, ptCenter2;
	ptCenter1.X = snakes.x + SNAKE_WIDTH/2;
	ptCenter1.Y = snakes.y + SNAKE_HEIGHT/2;
	ptCenter2.X = food.x + SNAKE_WIDTH/2;
	ptCenter2.Y = food.y + SNAKE_HEIGHT/2;
	PointF pt = ptCenter1 - ptCenter2;
	if(pt.X<SNAKE_WIDTH&&pt.X>-SNAKE_WIDTH&&pt.Y<SNAKE_HEIGHT&&pt.Y>-SNAKE_HEIGHT)
	
	{

		food.x = rand() % m_width;
		food.y = rand() % m_height;

		return true;
	}
	return false;
}


9.添加WM_SIZE消息

获取对话框的大小并保存

void CSnakeDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialogEx::OnSize(nType, cx, cy);
	m_width = cx-100;
	m_height = cy;

	// TODO: 在此处添加消息处理程序代码
}

10,添加对按键的支持

添加虚函数PreTranslateMessage(),该函数在Windows处理之前拦截按键消息

BOOL CSnakeDlg::PreTranslateMessage(MSG* pMsg)
{
	Snake &head = snake.back();
	// TODO: 在此添加专用代码和/或调用基类
	switch (pMsg->wParam)
	{
	case VK_LEFT:
		if (head.direction != SNAKE_RIGHT)//方向不能相反
			head.direction = SNAKE_LEFT;
		break;
	case VK_RIGHT:
		if (head.direction != SNAKE_LEFT)
			head.direction = SNAKE_RIGHT;
		break;
	case VK_UP:
		if (head.direction != SNAKE_DOWN)
			head.direction = SNAKE_UP;
		break;
	case VK_DOWN:
		if (head.direction != SNAKE_UP)
			head.direction = SNAKE_DOWN;
		break;
	}
	return CDialogEx::PreTranslateMessage(pMsg);
}

11.利用双缓冲将该游戏绘制出来

void CSnakeDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDC* pDC = this->GetDC();
		CBitmap bmp;
		CDC m_dcMemory;
		m_dcMemory.CreateCompatibleDC(pDC);
		bmp.CreateCompatibleBitmap(pDC, m_width, m_height);
		m_dcMemory.SelectObject(&bmp);
		Graphics gh(m_dcMemory.GetSafeHdc());
		{
			gh.DrawImage(img, 0, 0, m_width, m_height);//背景

			DrawSnake(gh);
		}
		pDC->BitBlt(0, 0, m_width, m_height, &m_dcMemory, 0, 0, SRCCOPY);
		CDialogEx::OnPaint();
	}
}

12.利用计时器将做出流畅游戏

void CSnakeDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	OnPaint();
	CDialogEx::OnTimer(nIDEvent);
}

游戏完成

该游戏还有许多不完善的地方

得分功能没有设计;小蛇自我碰撞检测没有设计,游戏开始暂停也没有设计

效果



猜你喜欢

转载自blog.csdn.net/qq_33012981/article/details/80405203