天天看点

【cocos2dx 3.2】2048

打包好的APK:http://pan.baidu.com/share/link?shareid=847502897&uk=185595768

游戏分析请看【Android重制2048】

打包方法:

(1)将工程导入eclipse中(记得将xml文档中调成竖屏模式)

(2)将VS工程中的D:\hello\Card\cocos2d\cocos\2d\platform\android\java\src里的org文件夹拖进eclipse的src

(3)修改eclipse工程中jni文件下的Android.mk文件

参考:http://blog.csdn.net/gf771115/article/details/34414449

(4)打开CMD,运行到VS工程中的proj.android下,执行Build_native.py

(5)成功后重新导入工程到eclipse中

(6)最后导出apk

效果:

【cocos2dx 3.2】2048

AppDelegate.cpp(修改分辨率和屏幕大小)

#include "AppDelegate.h"
#include "HelloWorldScene.h"

USING_NS_CC;

AppDelegate::AppDelegate() {

}

AppDelegate::~AppDelegate() 
{
}

bool AppDelegate::applicationDidFinishLaunching() {
    // initialize director
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    if(!glview) {
		//修改屏幕大小
        glview = GLView::createWithRect("My2048",Rect(0,0,286,512),1.0f);
        director->setOpenGLView(glview);
    }
	//分辨率适应
	glview->setDesignResolutionSize(268,512,ResolutionPolicy::EXACT_FIT);
   
    director->setDisplayStats(true);

    director->setAnimationInterval(1.0 / 60);

    auto scene = HelloWorld::createScene();

    director->runWithScene(scene);

    return true;
}

void AppDelegate::applicationDidEnterBackground() {
    Director::getInstance()->stopAnimation();
}

void AppDelegate::applicationWillEnterForeground() {
    Director::getInstance()->startAnimation();
}
           

2.游戏主场景

HelloWorld.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "Card.h"

USING_NS_CC;

class HelloWorld : public Layer
{
public:
 
    static Scene* createScene();

    virtual bool init();  
    
    void menuCloseCallback(Ref* pSender);

    CREATE_FUNC(HelloWorld);

	//自动生成卡片
	void autoCreateCard();

	//判断是否游戏结束
	void checkGameOver();

	//判断是否移动
	bool isMoveLeft();
	bool isMoveRight();
	bool isMoveUp();
	bool isMoveDown();

private:
	//记录按下时坐标和偏移量
	float startX,startY,offsetX,offsetY;

	//创建触控监听
	bool onTouchBegan(Touch *t, Event *e);
	void onTouchEnded(Touch *t, Event *e);

	//创建卡片
	void createCard(Size size);

	//储存卡片的二维数组,以便控制每一张卡片
	Card* cardArr[4][4];

	//游戏分数
	int score ;
	//显示分数的控件
	LabelTTF *scoreLabel;

	//设置重新开始游戏按钮
	LabelTTF *restartBtn;
};

#endif // __HELLOWORLD_SCENE_H__
           

HelloWorld.cpp

#include "HelloWorldScene.h"

USING_NS_CC;

Scene* HelloWorld::createScene()
{
    auto scene = Scene::create();
    
    auto layer = HelloWorld::create();

    scene->addChild(layer);

    return scene;
}

bool HelloWorld::init()
{
 
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Point origin = Director::getInstance()->getVisibleOrigin();

	//加入游戏背景
	auto layerClourBG = LayerColor::create(Color4B(180,170,160,255));
	this->addChild(layerClourBG);

	//加入游戏标题
	auto title = LabelTTF::create("My2048","Arial",60);
	title->setColor(Color3B(255,255,153));
	title->setPosition(Point(visibleSize.width/2,visibleSize.height-50));
	addChild(title);
	
	//加入restart按钮
	restartBtn = LabelTTF::create("Restart","Arial",30);
	restartBtn->setColor(Color3B(204,255,253));
	restartBtn->setPosition(Point(visibleSize.width/2,visibleSize.height-110));
	addChild(restartBtn);

	//加入游戏分数
	auto slabel = LabelTTF::create("Score","Arial",30);
	slabel->setPosition(Point(visibleSize.width/5,visibleSize.height-150));
	addChild(slabel);

	score = 0;
	scoreLabel = LabelTTF::create("0","Arial",30);
	scoreLabel->setPosition(Point(visibleSize.width/2+60,visibleSize.height-150));
	addChild(scoreLabel);

	//创建触控监听
	auto listener = EventListenerTouchOneByOne::create();
	listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan,this);
	listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded,this);
	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
	
	//调用卡片生成方法
	createCard(visibleSize);

	//一开始生成随机数
	autoCreateCard();
	autoCreateCard();



	return true;
}

bool HelloWorld::onTouchBegan(Touch *t, Event *e)
{
	//记录开始点击的坐标
	Point startPoint = t->getLocation();
	startX = startPoint.x;
	startY = startPoint.y;

	if(restartBtn->getBoundingBox().containsPoint(restartBtn->convertToNodeSpace(t->getLocation())))
	{
		Director::getInstance()->replaceScene(TransitionFade::create(1,HelloWorld::createScene()));
	}

	return true;
}


void HelloWorld::onTouchEnded(Touch *t, Event *e)
{
	//计算出偏移量,用于判断用户的滑动方向意图
	Point endPoint = t->getLocation();
	offsetX = startX - endPoint.x;
	offsetY = startY - endPoint.y;

	//如果X轴的偏移量比Y轴的大,则说明是水平方向的滑动
	if(abs(offsetX) > abs(offsetY))
	{
		//向左滑动
		if(offsetX > -5){
			if(isMoveLeft())
				//调用生成随机数
				autoCreateCard();
				//判断游戏是否结束
				checkGameOver();
		}
		//向右滑动
		else{
			if(isMoveRight())
				autoCreateCard();
				checkGameOver();
		}
	}
	else
	{
		//向上滑动
		if(offsetY > -5){
			if(isMoveUp())
				autoCreateCard();
				checkGameOver();
		}
		//向下滑动
		else{
			if(isMoveDown())
				autoCreateCard();
				checkGameOver();
		}
	}
}

//逻辑一样,只需实现一个方向的逻辑,其他复制修改就好了
bool HelloWorld::isMoveLeft()
{
	bool moved = false;
	for (int y = 0; y < 4; y++)
	{
		for (int x = 0; x < 4; x++)
		{
			for(int x1 = x+1; x1 < 4 ; x1++)
			{
				if(cardArr[x1][y]->getNumber() > 0)
				{   //当前位置为空,而同一行的有不为空的数字,就把它移到空的位置,接着把原位置清零
					if(cardArr[x][y]->getNumber() <= 0){
						cardArr[x][y]->setNumber(cardArr[x1][y]->getNumber());
						cardArr[x1][y]->setNumber(0);
						//再扫描一次,确保所有结果正确
						x--;
						moved = true;
					}else if(cardArr[x][y]->getNumber() == cardArr[x1][y]->getNumber())
					{//当前位置不为空,而且同一行有数字,相同的就叠加,并清空原位置
							cardArr[x][y]->setNumber(cardArr[x1][y]->getNumber()*2);
							cardArr[x1][y]->setNumber(0);
							//合并时同时加分
							score += (cardArr[x][y]->getNumber());
							scoreLabel->setString(__String::createWithFormat("%i",score)->getCString());
							moved = true;
					}
					break;
				}
			}
		}
	}
	return moved;
}

bool HelloWorld::isMoveRight()
{
	bool moved = false;
	for (int y = 0; y < 4; y++)
	{
		for (int x = 3; x >= 0; x--)
		{
			for(int x1 = x-1; x1 >= 0 ; x1--)
			{
				if(cardArr[x1][y]->getNumber() > 0)
				{   //当前位置为空,而同一行的有不为空的数字,就把它移到空的位置,接着把原位置清零
					if(cardArr[x][y]->getNumber() <= 0)
					{
						cardArr[x][y]->setNumber(cardArr[x1][y]->getNumber());
						cardArr[x1][y]->setNumber(0);
						//再扫描一次,确保所有结果正确
						x++;
						moved = true;
					}
					else if(cardArr[x][y]->getNumber() == cardArr[x1][y]->getNumber())
					{//当前位置不为空,而且同一行有数字,相同的就叠加,并清空原位置
						cardArr[x][y]->setNumber((cardArr[x1][y]->getNumber())*2);
					    cardArr[x1][y]->setNumber(0);
						score += (cardArr[x][y]->getNumber());
						scoreLabel->setString(__String::createWithFormat("%i",score)->getCString());
						moved = true;
					}	
				break;
				}
			}
		}
	}
	return moved;
}

bool HelloWorld::isMoveUp()
{
	bool moved = false;
	for (int x = 0; x < 4; x++)
	{
		for (int y = 0; y < 4; y++)
		{
			for(int y1 = y+1; y1 < 4 ; y1++)
			{
				if(cardArr[x][y1]->getNumber() > 0)
				{   //当前位置为空,而同一行的有不为空的数字,就把它移到空的位置,接着把原位置清零
					if(cardArr[x][y]->getNumber() <= 0)
					{
						cardArr[x][y]->setNumber(cardArr[x][y1]->getNumber());
						cardArr[x][y1]->setNumber(0);
						//再扫描一次,确保所有结果正确
						y--;
						moved = true;
					}
					else if(cardArr[x][y]->getNumber() == cardArr[x][y1]->getNumber())
					{//当前位置不为空,而且同一行有数字,相同的就叠加,并清空原位置
						cardArr[x][y]->setNumber((cardArr[x][y1]->getNumber())*2);
						cardArr[x][y1]->setNumber(0);
						score += (cardArr[x][y]->getNumber());
						scoreLabel->setString(__String::createWithFormat("%i",score)->getCString());
						moved = true;
					}
					break;				
				}
			}
		}
	}
	return moved;

}

bool HelloWorld::isMoveDown()
{
	bool moved = false;
	for (int x = 0; x < 4; x++)
	{
		for (int y = 3; y >= 0; y--)
		{
			for(int y1 = y-1; y1 >= 0 ; y1--)
			{
				if(cardArr[x][y1]->getNumber() > 0)
				{   //当前位置为空,而同一行的有不为空的数字,就把它移到空的位置,接着把原位置清零
					if(cardArr[x][y]->getNumber() <= 0)
					{
						cardArr[x][y]->setNumber(cardArr[x][y1]->getNumber());
						cardArr[x][y1]->setNumber(0);
						//再扫描一次,确保所有结果正确
						y++;
						moved = true;
					}
					else if(cardArr[x][y]->getNumber() == cardArr[x][y1]->getNumber())
					{//当前位置不为空,而且同一行有数字,相同的就叠加,并清空原位置
						cardArr[x][y]->setNumber((cardArr[x][y1]->getNumber())*2);
						cardArr[x][y1]->setNumber(0);
						score += (cardArr[x][y]->getNumber());
						scoreLabel->setString(__String::createWithFormat("%i",score)->getCString());
						moved = true;
					}
					break;
				}
			}
		}
	}
	return moved;


}

void HelloWorld::createCard(Size size)
{
	//求出单元格的宽高
	int cardLen = (size.width-20)/4;

	//4*4单元格
	for (int i = 0; i < 4; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			Card *cards = Card::createCard(0,cardLen,cardLen,cardLen*i+12,cardLen*j+12+size.height/6); 
			addChild(cards);
			//把卡片存在一个二维数组里面
			cardArr[i][j] = cards;
		}
	}
}

void HelloWorld::autoCreateCard()
{
	//随机生成横坐标和纵坐标
	int row = CCRANDOM_0_1()*4;
	int col = CCRANDOM_0_1()*4;

	//判断位置是否已经存在数字
	if(cardArr[row][col]->getNumber() > 0)
	{
		autoCreateCard();
	}
	else
	{   //4出现的几率是%10
		cardArr[row][col]->setNumber(CCRANDOM_0_1()*10<1?4:2);
	}

}

void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
	MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
    return;
#endif

    Director::getInstance()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

void HelloWorld::checkGameOver()
{
	bool isGameOver = true;
	
	for (int y = 0; y < 4; y++)
	{
		for (int x = 0; x < 4; x++)
		{
			if(cardArr[x][y]->getNumber() == 0 ||
				(x>0 && (cardArr[x][y]->getNumber() == cardArr[x-1][y]->getNumber()))||
				(x<3 && (cardArr[x][y]->getNumber() == cardArr[x+1][y]->getNumber()))||
				(y>0 && (cardArr[x][y]->getNumber() == cardArr[x][y-1]->getNumber()))||
				(y<3 && (cardArr[x][y]->getNumber() == cardArr[x][y+1]->getNumber()))){
					isGameOver = false;//满足以上条件则游戏继续
			}
		}
	}

	if(isGameOver)
	{
		Director::getInstance()->replaceScene(TransitionFade::create(1,HelloWorld::createScene()));
	}
}
           

3.游戏卡片精灵类

Card.h

#include "cocos2d.h"

USING_NS_CC;

class  Card : public Sprite
{
public:
	//初始化框架三件套
	static Card* createCard(int num, int cardWeight, int cardHeight, float positionX, float positionY);
	virtual bool init();
	CREATE_FUNC(Card);

	//设置数字并显示的方法
	void setNumber(int num);
	
	//获取数字的方法
	int getNumber();

private:
	//卡片中的数字
	int number;
	void cardInit(int num, int cardWeight, int cardHeight, float positionX, float positionY);

	//用于显示数字的控件
	LabelTTF *cardLabel;

	//控件的背景颜色
	LayerColor *cardBgColour;

};

           

Card.cpp

#include "Card.h"

USING_NS_CC;

Card* Card::createCard(int num, int cardWeight, int cardHeight, float positionX, float positionY)
{
	Card* card = new Card();
	if(card && card->init())
	{
		card->autorelease();
		card->cardInit(num,cardWeight,cardHeight,positionX,positionY);
		return card;
	}
	CC_SAFE_DELETE(card);
	return NULL;
}

bool Card::init()
{
	if(!Sprite::init())
		return false;
	return true;
}

void Card::setNumber(int num)
{
	number = num;
	//设置字体的大小
	if(number >= 0 && number < 16)
	{
		cardLabel->setFontSize(50);

	}
	if(number >= 16 && number < 128)
	{
		cardLabel->setFontSize(40);

	}
	if(number >= 128 && number < 1024)
	{
		cardLabel->setFontSize(30);
	}
    if(number >= 1024)
	{
		cardLabel->setFontSize(20);	
	}

	//设置数字颜色
     if(number == 0){
		 cardBgColour->setColor(Color3B(200,190,180));
	 }
	if(number == 2){
		cardBgColour->setColor(Color3B(240,230,220));
	}
	if(number == 4){
		cardBgColour->setColor(Color3B(51,153,51));
	}
	if(number == 8){
		cardBgColour->setColor(Color3B(255,153,102));
	}
	if(number == 16){
		cardBgColour->setColor(Color3B(153,204,153));
	}
	if(number == 32){
		cardBgColour->setColor(Color3B(153,204,255));
	}
	if(number == 64){
		cardBgColour->setColor(Color3B(255,204,204));
	}
	if(number == 128){
		cardBgColour->setColor(Color3B(204,102,0));
	}
	if(number == 256){
		cardBgColour->setColor(Color3B(153,204,51));
	}
	if(number == 512){
		cardBgColour->setColor(Color3B(255,102,102));
	}
	if(number == 1024){
		cardBgColour->setColor(Color3B(204,204,255));
	}
	if(number == 2048){
		cardBgColour->setColor(Color3B(255,204,00));
	}

	//显示数字
	if(number > 0)
		cardLabel->setString(__String::createWithFormat("%d",number)->getCString());
	else
		cardLabel->setString("");
}

int Card::getNumber()
{
	return number;
}

void Card::cardInit(int num, int cardWeight, int cardHeight, float positionX, float positionY)
{
	number = num;

	//添加卡片背景颜色
	cardBgColour = LayerColor::create(Color4B(200,190,180,255),cardWeight-5,cardHeight-5);
	cardBgColour->setPosition(Point(positionX,positionY));

	//判断num是否大于0,是就显示,否则显示空
	if(num > 0)
	{
		//设置字体
		cardLabel = LabelTTF::create(__String::createWithFormat("%d",number)->getCString(),"Arial",50);
		cardLabel->setPosition(Point(cardBgColour->getContentSize().width/2,cardBgColour->getContentSize().height/2));
		cardBgColour->addChild(cardLabel);
	}
	else
	{
		cardLabel = LabelTTF::create("","Arial",50);
		cardLabel->setPosition(Point(cardBgColour->getContentSize().width/2,cardBgColour->getContentSize().height/2));
		cardBgColour->addChild(cardLabel);
	}

	this->addChild(cardBgColour);
}