cocos2dx开发2048游戏

我一共添加了四个类分别为:

(1)游戏启动后的初始界面类SplashScene; 这个界面是游戏启动后的第一个界面。

这个类在AppDelegate::applicationDidFinishLaunching()会被调用

bool AppDelegate::applicationDidFinishLaunching() {
    // initialize director
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    if(!glview) {
        glview = GLView::create("2048");
		glview->setFrameSize(500, 600);
        director->setOpenGLView(glview);
    }

    // turn on display FPS
    director->setDisplayStats(true);

    // set FPS. the default value is 1.0/60 if you don't call this
    director->setAnimationInterval(1.0 / 60);

    // create a scene. it's an autorelease object
    auto scene = Splash::createScene();

    // run
    director->runWithScene(scene);

    return true;
}
其中通过Splash::createScene()创建一个场景,然后通过director->runWithScene(scene)运行此场景。

Splash应继承自Layer类,且拥有四个成员函数:bool init()用来初始化场景;static Splash*createScene()用来创建一个场景;CREATE_FUNC(Splash);使Splash拥有一个create()方法来创建一个Splash的对象(类型为Layer类);void jameToGame(float t)用来跳转到GameScene场景中;

#include"cocos2d.h"
#include<iostream>

USING_NS_CC;
class Splash :public Layer
{
public:
	virtual bool init();
	CREATE_FUNC(Splash);
	static Scene*createScene();
	void jumpToGame(float t);
};
所有类的头文件中应包含"cocos2d.h"的头文件,并且使用cocos2d的命名空间:USING_NS_CC;接着是函数的实现

init函数中应该显示游戏的标题 制作单位等相关信息

#include"SplashScene.h"
#include"GameScene.h"
#include"SimpleAudioEngine.h"
using namespace CocosDenshion;
USING_NS_CC;
bool Splash::init()
{
	if (!Layer::init())
	{
		return false;
	}
	//加载音乐
	SimpleAudioEngine::getInstance()->preloadEffect("1second.wav");
	SimpleAudioEngine::getInstance()->preloadEffect("2.wav");
	Size visibleSize = Director::getInstance()->getVisibleSize();
	Vec2 origin = Director::getInstance()->getVisibleOrigin();
	//显示游戏名称
	auto label = Label::createWithBMFont("fonts/futura-48.fnt", "2048");
	label->setPosition(Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height / 2));
	this->addChild(label,1);
	label->setScale(1.5);
	//显示制作单位
	auto label2 = Label::createWithBMFont("fonts/futura-48.fnt", "made by -cug-ZK");
	label2->setPosition(Point(label2->getContentSize().width/2, visibleSize.height / 4));
	this->addChild(label2,1);
	label2->setScale(0.8);
	//计划任务三秒钟之后进入游戏场景
	this->scheduleOnce(schedule_selector(Splash::jumpToGame), 3);
	return true;
}
Scene* Splash::createScene()
{
	auto scene = Scene::create();
	auto layer = Splash::create();
	scene->addChild(layer);
	return scene;
}
void Splash::jumpToGame(float t)
{
	auto scene = Game::createScene();
	Director::getInstance()->replaceScene(TransitionProgressOutIn::create(0.5, scene));
}
加载音乐应该包含#include"SimpleAudioEngine"   使用命名空间using namespace CocosDenshion;


(2)游戏场景类GameScene类;游戏的主场景;

首先添加一个头文件用来定义游戏相关信息

#define GAME_TILED_WIDTH 100  //格子的宽
#define GAME_TILED_HEIGHT 100  //格子的高
#define GAME_TILED_BOARD_WIDTH 4  //间隔的宽度
#define GAME_ROWS 4 //行数
#define GAME_COLS 4 //列数
enum class E_MOVE_DIR  //移动的方向
{
	UP,
	DOWN,
	LEFT,
	RIGHT
};
接着是GameScene.h的类容:

#include"cocos2d.h"
#include<iostream>
#include"movedTiled.h"
#include"GameDefine.h"
#include"SimpleAudioEngine.h"
USING_NS_CC;
class Game :public Layer
{
private:
	bool m_startMove;//是否开始移动
	int m_x, m_y;//开始触摸的点
public :
	virtual bool init();
	static Scene*createScene();
	CREATE_FUNC(Game);
	E_MOVE_DIR dir;
	int map[GAME_ROWS][GAME_COLS];
	Vector<movedTiled*> m_allTiled;//保存所有块
	void moveAllTiled(E_MOVE_DIR dir);//核心游戏逻辑
	void newMovedTiled();
	void moveUp();
	void moveDown();
	void moveLeft();
	void moveRight();
	LayerColor* color_back;//背景
	int m_score;//分数
};

GameScene.cpp的类容

#include"GameScene.h"
#include"GameOver.h"
using namespace CocosDenshion;
bool Game::init()
{
	if (!Layer::init())
	{
		return false;
	}
	//初始化游戏标题
	Size visibleSize = Director::getInstance()->getVisibleSize();
	Point origin = Director::getInstance()->getVisibleOrigin();
	auto labelGame = Label::createWithBMFont("fonts/futura-48.fnt", "2048");
	labelGame->setPosition(Point(labelGame->getContentSize().width/2, visibleSize.height - labelGame->getContentSize().height));
	this->addChild(labelGame, 1);
	//labelGame->setScale(0.5);
	
	//初始化游戏分数
	m_score = 0;
	auto score = Label::createWithBMFont("fonts/futura-48.fnt", StringUtils::format("%d", this->m_score));
	score->setTag(102);
	score->setPosition(Point(visibleSize.width / 2, visibleSize.height - score->getContentSize().height));
	this->addChild(score);
	score->setScale(0.6);
	
	//初始化游戏网格
	color_back = LayerColor::create(Color4B(161, 134, 190, 255), GAME_TILED_WIDTH*GAME_COLS + GAME_TILED_BOARD_WIDTH*(GAME_COLS + 1),
		GAME_TILED_HEIGHT*GAME_ROWS + GAME_TILED_BOARD_WIDTH*(GAME_ROWS + 1));
	color_back->ignoreAnchorPointForPosition(false);
	color_back->setAnchorPoint(Vec2(0.5, 0.5));
	color_back->setPosition(Point(origin.x + visibleSize.width / 2, origin.y + visibleSize.height / 2));
	this->addChild(color_back, 1);
	
	//初始化网格的每一块
	for (int row = 0; row < GAME_COLS; row++)
	{
		for (int col = 0; col < GAME_COLS; col++)
		{
			auto layerTiled = LayerColor::create(Color4B(104, 104, 104, 255), GAME_TILED_WIDTH, GAME_TILED_HEIGHT);
			//layerTiled->ignoreAnchorPointForPosition(fa)
			layerTiled->setPosition(Point(col*GAME_TILED_WIDTH + (col + 1)*GAME_TILED_BOARD_WIDTH, row*GAME_TILED_HEIGHT + (row + 1)*GAME_TILED_BOARD_WIDTH));
			color_back->addChild(layerTiled);
		}
	}
	
	//初始化逻辑网格数组
	for (int i = 0; i < GAME_ROWS; i++)
	{
		for (int j = 0; j < GAME_COLS; j++)
		{
			map[i][j] = 0;//表示空白

		}
	}
	
	//初始化数字块
	newMovedTiled();
	
	//触摸处理
	
	auto event = EventListenerTouchOneByOne::create();
	event->onTouchBegan = [&](Touch *tou, Event*eve){
		m_x = tou->getLocation().x;
		m_y = tou->getLocation().y;
		m_startMove = true;

		return true;
	};
	event->onTouchMoved = [&](Touch*tou, Event*eve){
		int x = tou->getLocation().x;
		int y = tou->getLocation().y;
		if (m_startMove&&(abs(x - m_x) > 10 || abs(y - m_y) > 10))
		{
			m_startMove = false;
			E_MOVE_DIR dir;
			if (abs(x - m_x) > abs(y - m_y))
			{
				if (x > m_x)
				{
					dir = E_MOVE_DIR::RIGHT;
				}
				else
					dir = E_MOVE_DIR::LEFT;
			}
			else
			{
				if (y > m_y)
				{
					dir = E_MOVE_DIR::UP;
				}
				else
					dir = E_MOVE_DIR::DOWN;
			}
			moveAllTiled(dir);//移动所有的元素块
		}
		//return true;
	};
	//event->onTouchEnded;
	Director::getInstance()->getEventDispatcher()->
		addEventListenerWithSceneGraphPriority(event, this);
	
	//游戏分数
	return true;
}

void Game::newMovedTiled()//产生新块
{
	auto tiled = movedTiled::create();
	int freeCount = 16 - m_allTiled.size();
	if (freeCount == 0)
	{
		
		return;
	}
	
	srand(time(0));
	int num = rand() % freeCount+1;
	int count = 0;
	bool find = false;
	int row, col;
	for (row = 0; row < GAME_COLS; row++)
	{
		for (col = 0; col < GAME_COLS; col++)
		{
			if (map[row][col]==0)
			{
				count++;
				if (count == num)
				{
					find = true;
					break;
				}
			}
		}
		if (find)
		{
			color_back->addChild(tiled);
			tiled->showAt(row, col);
			m_allTiled.pushBack(tiled);
			map[row][col] = m_allTiled.getIndex(tiled) + 1;
			break;
		}
	}
	
}


void Game::moveUp()	//向上移动
{
	for (int col = 0; col < GAME_COLS; col++)
	{
		for (int row = 1; row <GAME_ROWS; row++)
		{
			if (map[row][col] != 0)
			{
				bool flag = false;
				for (int row1 = row; row1 >0; row1--)
				{
					if (map[row1 - 1][col] == 0 && map[row1][col] != 0)
					{
						map[row1 - 1][col] = map[row1][col];
						map[row1][col] = 0;
						m_allTiled.at(map[row1 - 1][col] - 1)->moveTo(row1 - 1, col);
					}
					else if (map[row1 - 1][col] && map[row1][col]&&!flag)
					{
						flag = true;
						int num1 = m_allTiled.at(map[row1 - 1][col] - 1)->m_number;
						int num2 = m_allTiled.at(map[row1][col] - 1)->m_number;
						if (num1 == num2)
						{
							m_score += num1 * 2;
							m_allTiled.at(map[row1 - 1][col] - 1)->doubleNumber();
							m_allTiled.at(map[row1][col] - 1)->removeFromParent();
							m_allTiled.erase(map[row1][col] - 1);
							for (int i = 0; i < GAME_COLS; i++)
							{
								for (int j = 0; j < GAME_COLS; j++)
								{
									if (map[i][j]>map[row1][col])
									{
										map[i][j]--;
									}
								}
							}
							map[row1][col] = 0;
						}
					}
				}				
			}
		}
	}
}


void Game::moveDown()//向下移动
{
	for (int col = 0; col < GAME_COLS; col++)
	{
		for (int row = GAME_COLS-2; row >=0; row--)
		{
			if (map[row][col] != 0)
			{
				bool flag = false;
				for (int row1 = row; row1 <GAME_ROWS-1; row1++)
				{
					if (map[row1 + 1][col] == 0 && map[row1][col] != 0)
					{
						map[row1 + 1][col] = map[row1][col];
						map[row1][col] = 0;
						m_allTiled.at(map[row1 + 1][col] - 1)->moveTo(row1 + 1, col);
					}
					else if (map[row1][col] && map[row1 + 1][col]&&!flag)
					{
						flag = true;
						int num1 = m_allTiled.at(map[row1][col]-1)->m_number;
						int num2 = m_allTiled.at(map[row1 + 1][col]-1)->m_number;
						if (num1 == num2)
						{
							m_score += num1 * 2;
							m_allTiled.at(map[row1 + 1][col] - 1)->doubleNumber();
							m_allTiled.at(map[row1][col] - 1)->removeFromParent();
							m_allTiled.erase(map[row1][col] - 1);
							for (int i = 0; i < GAME_ROWS; i++)
							{
								for (int j = 0; j < GAME_COLS; j++)
								{
									if (map[i][j]>map[row1][col])
									{
										map[i][j]--;
									}
								}
							}
							map[row1][col] = 0;
						}
					}
				}
			}
		}
	}
}


void Game::moveLeft()//向左移动
{
	for (int row = 0; row < GAME_COLS; row++)
	{
		for (int col = 1; col <GAME_ROWS; col++)
		{
			if (map[row][col] != 0)
			{
				bool flag = false;
				for (int col1 = col; col1 >0; col1--)
				{
					if (map[row][col1-1] == 0 && map[row][col1] != 0)
					{
						map[row][col1-1] = map[row][col1];
						map[row][col1] = 0;
						m_allTiled.at(map[row][col1 - 1] - 1)->moveTo(row, col1 - 1);
					}
					else if (map[row][col1-1] && map[row][col1]&&!flag)
					{
						flag = true;
						int num1 = m_allTiled.at(map[row][col1-1] - 1)->m_number;
						int num2 = m_allTiled.at(map[row][col1] - 1)->m_number;
						if (num1 == num2)
						{
							m_score += num1 * 2;
							m_allTiled.at(map[row][col1-1] - 1)->doubleNumber();
							m_allTiled.at(map[row][col1] - 1)->removeFromParent();
							m_allTiled.erase(map[row][col1] - 1);
							for (int i = 0; i < GAME_COLS; i++)
							{
								for (int j = 0; j < GAME_COLS; j++)
								{
									if (map[i][j]>map[row][col1])
									{
										map[i][j]--;
									}
								}
							}
							map[row][col1] = 0;
						}
					}
				}
			}
		}
	}
}


void Game::moveRight()//向右移动
{
	for (int row = 0; row < GAME_COLS; row++)
	{
		for (int col = GAME_COLS-2; col >=0; col--)
		{
			if (map[row][col] != 0)
			{
				bool flag = false;
				for (int col1 = col; col1 <GAME_COLS-1; col1++)
				{
					if (map[row][col1+1] == 0 && map[row][col1] != 0)
					{
						map[row][col1+1] = map[row][col1];
						map[row][col1] = 0;
						m_allTiled.at(map[row][col1+1] - 1)->moveTo(row, col1+1);
					}
					else if (map[row][col1+1] && map[row][col1]&&!flag)
					{
						flag = true;
						int num1 = m_allTiled.at(map[row][col1+1] - 1)->m_number;
						int num2 = m_allTiled.at(map[row][col1] - 1)->m_number;
						if (num1 == num2)
						{
							m_score += num1 * 2;
							m_allTiled.at(map[row][col1+1] - 1)->doubleNumber();
							m_allTiled.at(map[row][col1] - 1)->removeFromParent();
							m_allTiled.erase(map[row][col1] - 1);
							for (int i = 0; i < GAME_COLS; i++)
							{
								for (int j = 0; j < GAME_COLS; j++)
								{
									if (map[i][j]>map[row][col1])
									{
										map[i][j]--;
									}
								}
							}
							map[row][col1] = 0;
						}
					}
				}
			}
		}
	}
}


void Game::moveAllTiled(E_MOVE_DIR dir)//核心游戏逻辑实现
{
	//移动所有块,消除
	switch (dir)
	{
	case E_MOVE_DIR::UP:moveUp();
		break;
	case E_MOVE_DIR::DOWN:moveDown();
		break;
	case E_MOVE_DIR::LEFT:moveLeft();
		break;
	case E_MOVE_DIR::RIGHT:moveRight();
		break;
	default:break;
	}
	//播放音乐
	SimpleAudioEngine::getInstance()->playEffect("1second.wav");

	//产生新块
	Label* score = (Label*)this->getChildByTag(102);
	//分数变化
	score->setString(StringUtils::format("%d", this->m_score));
	newMovedTiled();
	//判定输赢
	bool lose = true;
	if (m_allTiled.size() == 16)
	{
		for (int i = 0; i < GAME_COLS; i++)
		{
			for (int j = 0; j < GAME_COLS; j++)
			{
				int num1 = m_allTiled.at(map[i][j] - 1)->m_number;
				if (i + 1 < GAME_ROWS)//判断向下
				{
					int num2 = m_allTiled.at(map[i+1][j] - 1)->m_number;
					if (num1 == num2)
					{
						lose = false;
						break;
					}
				}
				if (i - 1 >=0)//判断向上
				{
					int num2 = m_allTiled.at(map[i - 1][j] - 1)->m_number;
					if (num1 == num2)
					{
						lose = false;
						break;
					}
				}
				if (j - 1 >=0)//判断向左
				{
					int num2 = m_allTiled.at(map[i][j-1] - 1)->m_number;
					if (num1 == num2)
					{
						lose = false;
						break;
					}
				}
				if (j + 1 < GAME_ROWS)//判断向右
				{
					int num2 = m_allTiled.at(map[i][j+1] - 1)->m_number;
					if (num1 == num2)
					{
						lose = false;
						break;
					}
				}
			}
			if (!lose)
			{
				break;
			}
		}
		if (lose)
		{
			auto scene = GameOver::createScene();
			Director::getInstance()->replaceScene(TransitionFadeDown::create(0.5, scene));
		}
		
	}
	
}
Scene*Game::createScene()
{
	auto scene = Scene::create();
	auto layer = Game::create();
	scene->addChild(layer);
	return scene;
}



(3)格子类movedTiled类.

movedTiled.h

#pragma once
#include<iostream>
#include "cocos2d.h"
USING_NS_CC;
class movedTiled :public Node
{
public:
	movedTiled();
	~movedTiled();
	bool init();
	int m_row;
	int m_col;
	int m_number;
	CREATE_FUNC(movedTiled);
	void showAt(int r, int c);//在r行c列产生一个新块
	void moveTo(int r, int c);//将一个块移动到r行c列(有无动画的区别)
	void doubleNumber();
};
moveTiled.cpp

#include "movedTiled.h"
#include"GameDefine.h"
#include"SimpleAudioEngine.h"
using namespace CocosDenshion;
movedTiled::movedTiled()
{
}


movedTiled::~movedTiled()
{
}
bool movedTiled::init()
{
	if (!Node::init())
	{
		return false;
	}
	auto bk = LayerColor::create(Color4B(200, 200, 200, 255), GAME_TILED_WIDTH, GAME_TILED_HEIGHT);
	bk->setTag(100);
	this->addChild(bk);
	int n = rand() % 10;
	this->m_number = n > 0 ? 2 : 4;

	auto label = Label::createWithBMFont("fonts/bitmapFontChinese.fnt",StringUtils::format("%d",this->m_number));
	label->setTag(101);
	bk->addChild(label);
	if (this->m_number == 4)
	{
		bk->setColor(Color3B(255, 182, 193));
	}
	label->setColor(Color3B(200, 0, 255));
	label->setPosition(Point(bk->getContentSize().width / 2, bk->getContentSize().height / 2));
	label->setScale(0.8);
	return true;
}
void movedTiled::showAt(int r,int c)
{
	moveTo(r, c);
	auto bk = this->getChildByTag(100);
	bk->runAction(Sequence::create(ScaleTo::create(0.2, 0.8), ScaleTo::create(0.2, 1.2), ScaleTo::create(0.2, 1),NULL));
}
void movedTiled::moveTo(int r, int c)
{
	this->m_row = r;
	this->m_col = c;
	this->setPosition(c*GAME_TILED_WIDTH + (c + 1)*GAME_TILED_BOARD_WIDTH, (3 - r)*GAME_TILED_WIDTH + (4 - r)*GAME_TILED_BOARD_WIDTH);
}
void movedTiled::doubleNumber()
{
	this->m_number = this->m_number * 2;
	auto bk=this->getChildByTag(100);
	Label* label = (Label*)bk->getChildByTag(101);
	label->setBMFontFilePath("fonts/bitmapFontChinese.fnt");
	label->setString(StringUtils::format("%d", this->m_number));
	SimpleAudioEngine::getInstance()->playEffect("2.wav");
	bk->runAction(Sequence::create(ScaleTo::create(0.2, 0.8), ScaleTo::create(0.2, 1.2), ScaleTo::create(0.2, 1), NULL));
	switch (this->m_number)
	{
	case 4:
		bk->setColor(Color3B(255, 182, 193));
		break;
	case 8:
		bk->setColor(Color3B(255, 0, 255));
		break;
	case 16:
		bk->setColor(Color3B(138, 43,226));
		break;
	case 32:
		bk->setColor(Color3B(65, 105, 225));
		break;
	case 64:
		bk->setColor(Color3B(30, 144, 255));
		break;
	case 128:
		bk->setColor(Color3B(127, 255, 0));
		break;
	case 256:
		bk->setColor(Color3B(255, 215, 0));
		break;
	case 512:
		bk->setColor(Color3B(210, 105, 30));
		break;
	case 1024:
		bk->setColor(Color3B(255, 69, 0));
		break;
	case 2048:
		bk->setColor(Color3B(188, 143, 143));
		break;
	default:
		break;
	}
}



(4)游戏结束类GameOver;

GameOver.h

#include"cocos2d.h"
USING_NS_CC;
class GameOver :public Layer
{
public:
	bool init();
	CREATE_FUNC(GameOver);
	static Scene* createScene();
	void menuCallBack(Ref *pObject);
};

GameOver.cpp

#include"GameOver.h"
#include"GameScene.h"
bool GameOver::init()
{
	if (!Layer::init())
	{
		return false;
	}
	//显示游戏结束
	Size viewSize = Director::getInstance()->getVisibleSize();
	auto label = Label::createWithBMFont("fonts/futura-48.fnt", "GameOver");
	label->setPosition(Point(viewSize.width / 2, viewSize.height / 2));
	label->setScale(1.5);
	this->addChild(label);
	auto label1 = Label::createWithBMFont("fonts/futura-48.fnt", "Restart Game");
	auto labelItem = MenuItemLabel::create(label1, CC_CALLBACK_1(GameOver::menuCallBack, this));
	labelItem->setPosition(Point(viewSize.width / 2, viewSize.height / 4));
	auto menu = Menu::createWithItem(labelItem);
	menu->setPosition(Point::ZERO);
	this->addChild(menu);
	return true;

}
void GameOver::menuCallBack(Ref*pObject)
{
	auto scene = Game::createScene();
	Director::getInstance()->replaceScene(TransitionFadeDown::create(0.2, scene));
}
Scene* GameOver::createScene()
{
	Scene*scene = Scene::create();
	Layer *layer = GameOver::create();
	scene->addChild(layer);
	return scene;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值