《2048》是一款在2014年意外窜红的数字游戏,玩法比较简单,而之后基于原版2048也衍生出了不少其他版本,火的一塌糊涂。本文将基于cocos2dx来开发实现2048这款游戏。
开发环境
操作系统:win7
开发工具:Visual studio 2012
引擎版本:cocos2dx 3.6
游戏玩法
4*4的卡片布局,玩家通过手势上下左右滑动来累加卡片数值,直到累加到2048。为方便后面的开发上的逻辑更加清晰,具体玩法逻辑我们可以细分如下:
- 开始时棋盘内随机出现两个数字,出现的数字仅可能为2或4
- 玩家可以选择上下左右四个方向,若棋盘内的数字出现位移或合并,视为有效移动
- 玩家选择的方向上若有相同的数字则合并,每次有效移动可以同时合并,但不可以连续合并
- 合并所得的所有新生成数字想加即为该步的有效得分
- 玩家选择的方向行或列前方有空格则出现位移
- 每有效移动一步,棋盘的空位(无数字处)随机出现一个数字(依然可能为2或4)
- 棋盘被数字填满,无法进行有效移动,判负,游戏结束
- 棋盘上出现2048,判胜,游戏结束
游戏实现
了解了上述游戏玩法规则胡,接下来我们就基于cocos2dx来对游戏2048进行相关实现。
1. 游戏场景创建
根据我们对游戏的了解,主场景上主要显示信息有4*4的卡片布局矩阵,以及游戏分数的显示。因此我们创建GameScene类(Layer的子类),即游戏的主场景,负责游戏的基本信息的显示,同事还负责管理游戏的交互逻辑和分数更新。细分如下:
- 游戏主要操作区卡片矩阵的创建显示;
- 游戏交互处理(主要是Touch一类的操作);
- 游戏结果更新、显示;
- 其他(按钮控件、声音处理…)
游戏主场景GameScene类的声明:
#ifndef __GAME_SCENE_H__
#define __GAME_SCENE_H__
#include "cocos2d.h"
#include "cardSprite.h"
#include "MenuLayer.h"
class GameScene :public cocos2d::Layer
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(GameScene);
public:
// Touch开始事件监听
virtual bool onTouchBegan(cocos2d::Touch *pTouch, cocos2d::Event *pEvent);
virtual void onTouchEnded(cocos2d::Touch *pTouch, cocos2d::Event *pEvent);
// 上下左右四个方向的滑动操作处理
bool moveLeft();
bool moveRight();
bool moveUp();
bool moveDown();
//创建4*4卡片矩阵
void createCardMatrix (Size size);
void randomCreateCard();
//判断游戏赢输
void checkGameWin();
void checkGameOver();
//重新开始游戏菜单项
void restart(Ref *sender);
private:
cocos2d::LabelTTF *scoreLabel;
LabelTTF *restartBtn; //重新开始的按钮
LabelTTF *isSoundBtn; //声音切换按钮
CardSprite *cardArr[4][4]; //数字卡片矩阵
CardSprite *cardArrAction[4][4]; //用于动画的临时数字卡片矩阵
MenuLayer *menuLayer; //菜单层
Point startPt; //触摸开始点
int offsetX, offsetY; //触摸水平和竖直方向偏移量
int score; //当前分数
int bestScore; //最好分数
bool sound; //声音变量
timeval tv; //当前时间
};
#endif // __GAME_SCENE_H__
注:相关函数、变量在后续步骤中逐一说明。
2. 卡片精灵CardSpirit
卡片类是组成2048游戏的基础,4*4的方格的16个位置放置不同的卡片,每个位置为独立的一张卡片。每个卡片都有着各自的位置信息、数字信息、颜色信息等独特信息。因此,我们基于Sprite精灵类派生CarSprite类,封装实现卡片类。根据我们的分析,卡片类主要要实现的功能如下:
- 卡片的创建及初始化;
- 卡片属性更新(卡片数字、卡片背景颜色);
卡片类CardSprite的声明:
/** @class GameMainScene
* @brief 游戏主场景
* @author 7-sevens
* @date 2015/03/01
*/
#ifndef __CARD_SPRITE_H__
#define __CARD_SPRITE_H__
#include "cocos2d.h"
USING_NS_CC;
class CardSprite :public Sprite
{
public:
// 创建游戏卡
static CardSprite* createCard(int num, int cardWidth, int cardHeight, float px, float py);
virtual bool init();
CREATE_FUNC(CardSprite);
// 设置数字
void setNumber(int num);
// 获取数字
int getNumber();
LayerColor* getCardLayer();
private:
void cardInit(int num, int cardWidth, int cardHeight, float px, float py);
private:
LabelTTF *cardLabel; //卡片数字标签控件
LayerColor *cardBgColour; //背景
int number;
};
#endif // __CARD_SPRITE_H__
我们可以从游戏中看到,每张卡片有背景颜色和一个数字,所以我们在头文件需要声明它这两个属性。
卡片类CardSprite的相关实现:
(1)卡片的创建初始化
CardSprite* CardSprite::createCard(i