打包好的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
效果:
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);
}