比较早的代码了,属于典型的为了面向对象而面向对象的代码。。。
运行环境VS2019,图形由easyx库实现:https://easyx.cn/。
已经在注释中写出了出现的eaysx库函数的基本作用,注释前带“*”的是easyx的库函数,详情请查阅文档https://docs.easyx.cn/zh-cn/intro
完整的源码见最下方
成品
基本游戏框架搭建
main函数:
#include "Snake.h"
using namespace std;
int main()
{
Snake my_snake;
my_snake.startup();
while (1)
{
my_snake.clean();
my_snake.UpdateWithoutInput();
my_snake.UpdateWithInput();
my_snake.show();
}
my_snake.gameover();
return 0;
}
第一行通过无参的构造函数初始化数据,包括界面宽度等等
startup开始生成画面
进入循环,包括:
- 清除旧画面
- 更新无需用户输入的数据
- 更新需要用户输入的数据
- 根据更新后的数据生成新画面,从而达到动画效果
(退出游戏的部分在UpdateWithoutInput中。)
Snake类
#pragma once
#include<graphics.h>
#include<Windows.h>
#include<conio.h>
#include<ctime>
#include<vector>
#include<cstdlib>
using namespace std;
class Snake
{
public:
Snake();
bool check();//检测生成的食物是否和蛇重合了
void SnakeMove();
void startup();
void clean();
void show();
void UpdateWithoutInput();
void UpdateWithInput();
void gameover();
private:
int High;
int Width;
int Background;
int dir;//方向
int score;
int speed;//画面更新速度,动态难度
int food_x, food_y;
vector<int> snake_x, snake_y; //蛇的每一节的坐标
};
食物只出现一次,所以直接用int类型作为坐标
蛇的长度理论上来说是可以无限增长的,因此使用vector来保存蛇的每一节的坐标。
初始化
初始化的函数包括Snake的无参构造函数和startup函数:
Snake::Snake()
{
High = 720;
Width = 1280;
Background = LIGHTGRAY;//*easyx的颜色宏
dir = 5;//方向参考1235键位,类似wasd
score = 0;
speed = 300;
food_x = rand() % (Width-40) + 21; //限定食物出现在屏幕范围内
food_y = rand() % (High-40) + 21;
snake_x.resize(4), snake_y.resize(4);//蛇的初始长度为4
}
void Snake::startup()
{
srand((unsigned int)(time)(NULL));
initgraph(Width, High);//*easyx初始化函数,以参数生成相应分辨率的窗口
setbkcolor(Background);//*设置背景色
cleardevice();//*清空原有背景
for (int i = 0; i < 4; i++)//初始化蛇的坐标数据
{
snake_x[i] = Width / 2 - 40 * i;
snake_y[i] = High / 2;
}
BeginBatchDraw();//*
//这个函数用于开始批量绘图。
//执行后,任何绘图操作都将暂时不输出到绘图窗口上,
//直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
//主要的用处是保证刷新画面不发生屏幕闪烁
}
动画效果
void Snake::clean()
{
setlinecolor(Background);//*设置线的颜色
setfillcolor(Background);//*设置填充色
for (unsigned i = 0; i < snake_x.size(); i++)
{
fillcircle(snake_x[i], snake_y[i], 20);//*画圆
}
}
void Snake::show()
{
for (unsigned i = 0; i < snake_x.size(); i++)
{
if (i == 0)
{
setfillcolor(LIGHTMAGENTA);
fillcircle(snake_x[i], snake_y[i], 20);
}
else
{
setfillcolor(LIGHTRED);
fillcircle(snake_x[i], snake_y[i], 20);
}
}
FlushBatchDraw();//*与BeginBatchDraw配合使用
setfillcolor(YELLOW);
//*以下均为字体设置与字体显示,用于显示分数
TCHAR s[5];
fillcircle(food_x, food_y, 20);
settextstyle(60, 0, _T("宋体"));
settextcolor(RGB(25, 32, 94));
_stprintf_s(s, 5, _T("%d"), score);
outtextxy(430, 620, _T("Score:"));
outtextxy(640, 620,