2048游戏之——C++与控制台
概要
我是Kpurek,首次在CSDN写blog,请多指教。
本文讲解我如何根据既定规则,设计2048游戏的框架结构,包括类设计、游戏流程设计、算法设计。因为游戏比较简单,设计起来思路容易理清,用控制台实现的话效果也不会很差(能玩)
最初版的效果:(还没有优化随机生成方法)
本项目开源,GitHub地址。
需求
1、显示4*4数字矩阵,左对齐
2、键盘输入,检测方向键,上下左右对应2048界面的上向左右滑动。
3、能够控制帧率,并尽量使界面流畅、舒适
4、游戏结束时暂停游戏
因此根据这些简单的需求,我构思出了以下的游戏框架:
1、核心部分:
存储游戏的信息,包括方块的值等信息;
实现游戏的核心算法,包括移动、合并方块以及判断游戏状态。
用于将矩阵对象渲染到屏幕上;
能够接受消息,例如键盘输入信息;
发送消息,例如游戏结束;
2、控制部分:
控制游戏流程,包括接收消息、处理消息等功能。
3、消息部分:
用于核心组件和控制组件的通信;
检测键盘事件;
处理游戏状态信息;
这个部分主要起到解耦作用,方便更改游戏的输入方式、状态信息。
4、还需要一个游戏循环状态机
我将它放在了main函数中。
因此,根据以上的框架,我设计出以下几个类:
设计
一、Map类
class Map
{
public:
构造
Map();
//析构,用于RAII的自动回收
~Map();
随机生成方块
void RandomCreate();
//渲染矩阵
void Draw()const;
//检测、更新事件
void Update(Event& ev);
//返回矩阵大小
size_t size()const;
private:
//向上操作
void Move_UP();
//向下
void Move_DOWN();
//向左
void Move_LEFT();
//向右
void Move_RIGHT();
//是否游戏结束
bool isOver();
private:
//Map的矩阵
int** Mapper;
//每次随机生成的方块数量不能超过2:
const int AdditionNumber = 2;
//矩阵大小
size_t m_size;
};
二、Event类
class Event //
{
public:
// 由键盘事件获取消息
void CheckKeyEvent();
//原本应该有的push和get方法(公有),游戏对象能够发送消息
//但本游戏几乎不需要,因此省略
/*
void pushEvent();
vector<STATE> getEvent()const;
*/
public:
使用vector容器搭建的数组,作为消息队列:
vector<STATE>state;
};
三、GameController类
class GameController
{
public:
//构造
GameController();
public:
//清空画面
void clear();
//渲染
void draw(Map const& map);
//控制
void display();
//设置帧率
void SetFPS(int const& fps);
//获取事件
void PullEvent(Event const& ev);
//窗口是否为打开状态
bool isOpen()const;
private:
//退出游戏
void exit();
//游戏结束
void GameOver();
private:
//是否打开
bool isOpening;
//是否结束
bool isGameOver;
//是否操作了矩阵
bool isMoved;
//每一帧的开始事件
time_t StartTime;
//帧率
int FPS;
//帧间间隔
time_t FrameTime;
};
各个类的成员、方法,都已经做了详细的注释;
可能有一点容易混淆:
Map类和GameController类都有一个名为draw的方法,一个是Draw一个是draw。要注意,这两个方法不止是名字有区别:Map的Draw是被GameController内部调用的,不会在我们的游戏循环内被直接调用。
也就是这样一个过程:
游戏循环(状态机)—调用—>GameController.draw()—调用—>Map.Draw()
那么说到状态,我使用了一个非常简单但使用的方法来定义游戏的状态——枚举。
枚举定义在了以下的总头文件中:
四、total.h
#pragma once
#include<iostream>
#include<conio.h>
#include<ctime>
#include<cassert>
#include<vector>
using namespace std;
各种宏
//ESC的ASCII
#define ESC_ASC 27
//方向键的前字符ASCII
#define DIRECTION_ASC 224
//方向键后字符ASCII
#define UP_ASC 72
#define DOWN_ASC 80
#define LEFT_ASC 75
#define RIGHT_ASC 77
//游戏公共事件的枚举类
enum class STATE
{
//游戏结束事件
GAME_OVER