我的2048

首先先感谢Legendof1991的博客让我想到做一个2048

http://blog.csdn.net/Legendof1991/article/category/2194455


游戏界面比较挫,还望海涵。



cocos2d-x版本为cocos2d-x-3.2alpha0 使用vs2012进行开发


首先使用cocos new 一个项目


HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class HelloWorld : public cocos2d::Layer
{
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();

    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  
    
    // a selector callback
    void menuCloseCallback(cocos2d::Ref* pSender);
    
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
private:

	void initCardTable();

	cocos2d::Vec2 _startPosition;

	void CreateInitCardNumber();

	void onLeft();
	void onRight();
	void onUp();
	void onDown();

	void checkEnd();

	void initScore();
	void updateScore(int score);
	void ReStartGame();
	cocos2d::Label* _labelScore;
	cocos2d::Label* _labelBestScore;

	int _score;
	int _bestScore;
	bool _isReStart;


};

#endif // __HELLOWORLD_SCENE_H__

HelloWorldScene.cpp

#include "HelloWorldScene.h"
#include "CardSprite.h"
USING_NS_CC;

Size visibleSize;
Vec2 origin;

CardSprite* cardTable[4][4];
Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();
    
    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

	
    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
     visibleSize = Director::getInstance()->getVisibleSize();
	 origin = Director::getInstance()->getVisibleOrigin();
    
	
	//初始化表格
	initCardTable();

	//编写事件监听
	auto listen=EventListenerTouchOneByOne::create();
	listen->onTouchBegan=[this](Touch* myTouch, Event* myEvent)->bool 
	{
		if(_isReStart)
			return false;
		this->_startPosition=	myTouch->getLocation();
		return true;
	};
	listen->onTouchEnded=[this](Touch* myTouch, Event* myEvent)
	{
		//得到方向向量
		Vec2 dir=myTouch->getLocation()-_startPosition;
		//得到弧度数
		float radians= ccpToAngle(dir);
		//得到角度数
		float angel=CC_RADIANS_TO_DEGREES(radians);
		//log("%f",dir.length());
		if(dir.length()<10)
		{

		}
		else
		{
			
			//log("%f",angel);
			//CreateInitCardNumber();

			//注意角度是-180到180
			if(angel>=-45&&angel<45)
			{
				//log("right");
				onRight();
			}
			else if(angel>=45&&angel<135)
			{
				//log("up");
				onUp();
			}
			else if((angel>=135&&angel<=180)||(angel<-135))
			{
			//	log("left");
				onLeft();
			}
			else 
			{
			//	log("down");
				onDown();
			}
			checkEnd();
		}
		
	};

	//注册事件监听
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listen,this);

	//分值
	this->_labelScore=Label::create("","Arial",visibleSize.width/24);
	this->_labelBestScore=Label::create("","Arial",visibleSize.width/24);
	this->addChild(_labelScore);
	this->addChild(_labelBestScore);
    initScore();
    return true;
}


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
}

//初始化全为0
void HelloWorld::initCardTable()
{
	for(int i=0;i<4;i++)
		for(int j=0;j<4;j++)
		{
			if(cardTable[i][j]==NULL)
			{
			//if(cardTable[i][j]!=NULL)
			//{
		//		delete cardTable[i][j];
		//	}
			CardSprite *myCard=CardSprite::createWithArgs(0,i,j,visibleSize.width/5,visibleSize.height/6);
			cardTable[i][j]=myCard;
			//log("%f %f",myCard->getPositionX(),myCard->getPositionY());
			this->addChild(myCard);
			}
		else
			{
				cardTable[i][j]->setCardNumber(0);
			}
		}

		//生成两个不为0的
		CreateInitCardNumber();
		CreateInitCardNumber();
		_isReStart=false;
}

//初始化的卡片数字
void HelloWorld::CreateInitCardNumber()
{
	std::srand(time(NULL));
	int x=std::rand()%4;
	int y=std::rand()%4;
	while(cardTable[x][y]->getCardNumber()!=0)
	{
		x=std::rand()%4;
		y=std::rand()%4;
	}

	//2或4
	cardTable[x][y]->setCardNumber(rand()%4==0?4:2);
}

//往左滑动 下面三个类似
void HelloWorld::onLeft()
{
	//是否造成移动
	bool isMove=false;
	
	//关心的是每一横行
	for(int y=0;y<4;y++)
	{
		//最左侧开始计算
		for(int x=0;x<4;x++)
		{
			
			for(int x1=x+1;x1<4;x1++)
			{
				//当当前格为0 右面不为0 右边赋值给左面  右面为0  
				if(cardTable[x][y]->getCardNumber()==0&&cardTable[x1][y]->getCardNumber()!=0)
				{
					cardTable[x][y]->setCardNumber(cardTable[x1][y]->getCardNumber());
					cardTable[x1][y]->setCardNumber(0);
					isMove=true;

				}
				//当左右相等且不为0 左值加倍 右值为0
				else if(cardTable[x][y]->getCardNumber()==cardTable[x1][y]->getCardNumber()&&cardTable[x][y]->getCardNumber()!=0)
				{
					updateScore(cardTable[x][y]->getCardNumber());
					cardTable[x][y]->doubleNumber();
					cardTable[x1][y]->setCardNumber(0);
					isMove=true;
					//当前格不再计算
					break;
				}
				//当左右格不等   右格不为0   当前格不再计算
				else if(cardTable[x][y]->getCardNumber()!=cardTable[x1][y]->getCardNumber()&&cardTable[x1][y]->getCardNumber()!=0)
				{
					break;
				}
				
			}
		}
	}
	//发生移动时添加新的一个初始格子
	if(isMove)
		this->CreateInitCardNumber();
}
void HelloWorld::onRight()
{
	bool isMove=false;
	

	for(int y=0;y<4;y++)
	{
		for(int x=3;x>=0;x--)
		{
			
			for(int x1=x-1;x1>=0;x1--)
			{
				if(cardTable[x][y]->getCardNumber()==0&&cardTable[x1][y]->getCardNumber()!=0)
				{
					cardTable[x][y]->setCardNumber(cardTable[x1][y]->getCardNumber());
					cardTable[x1][y]->setCardNumber(0);
					isMove=true;

				}
				else if(cardTable[x][y]->getCardNumber()==cardTable[x1][y]->getCardNumber()&&cardTable[x][y]->getCardNumber()!=0)
				{
					updateScore(cardTable[x][y]->getCardNumber());
					cardTable[x][y]->doubleNumber();
					cardTable[x1][y]->setCardNumber(0);
					isMove=true;
					break;
				}
				else if(cardTable[x][y]->getCardNumber()!=cardTable[x1][y]->getCardNumber()&&cardTable[x1][y]->getCardNumber()!=0)
				{
					break;
				}
				
			}
		}
	}

	if(isMove)
		this->CreateInitCardNumber();
}
void HelloWorld::onUp()
{
		
	bool isMove=false;
	

	for(int x=0;x<4;x++)
	{
		for(int y=3;y>=0;y--)
		{
			
			for(int y1=y-1;y1>=0;y1--)
			{
				if(cardTable[x][y]->getCardNumber()==0&&cardTable[x][y1]->getCardNumber()!=0)
				{
					cardTable[x][y]->setCardNumber(cardTable[x][y1]->getCardNumber());
					cardTable[x][y1]->setCardNumber(0);
					isMove=true;

				}
				else if(cardTable[x][y]->getCardNumber()==cardTable[x][y1]->getCardNumber()&&cardTable[x][y]->getCardNumber()!=0)
				{
					updateScore(cardTable[x][y]->getCardNumber());
					cardTable[x][y]->doubleNumber();
					cardTable[x][y1]->setCardNumber(0);
					isMove=true;
					break;
				}
				else if(cardTable[x][y]->getCardNumber()!=cardTable[x][y1]->getCardNumber()&&cardTable[x][y1]->getCardNumber()!=0)
				{
					break;
				}
			}
		}
	}

	if(isMove)
		this->CreateInitCardNumber();
}
void HelloWorld::onDown()
{
	
	bool isMove=false;
	

	for(int x=0;x<4;x++)
	{
		for(int y=0;y<4;y++)
		{
			
			for(int y1=y+1;y1<4;y1++)
			{
				if(cardTable[x][y]->getCardNumber()==0&&cardTable[x][y1]->getCardNumber()!=0)
				{
					cardTable[x][y]->setCardNumber(cardTable[x][y1]->getCardNumber());
					cardTable[x][y1]->setCardNumber(0);
					isMove=true;

				}
				else if(cardTable[x][y]->getCardNumber()==cardTable[x][y1]->getCardNumber()&&cardTable[x][y]->getCardNumber()!=0)
				{
					updateScore(cardTable[x][y]->getCardNumber());
					cardTable[x][y]->doubleNumber();
					cardTable[x][y1]->setCardNumber(0);
					isMove=true;
					break;
				}
				else if(cardTable[x][y]->getCardNumber()!=cardTable[x][y1]->getCardNumber()&&cardTable[x][y1]->getCardNumber()!=0)
				{
					break;
				}
			}
		}
	}

	if(isMove)
		this->CreateInitCardNumber();
}

//检测是否可消除
void HelloWorld::checkEnd()
{
	int count=0;
	bool isEnd=true;
	for(int i=0;i<4;i++)
		for(int j=0;j<4;j++)
		{
			if(cardTable[i][j]->getCardNumber()!=0)
				count++;
			//下面是判断是否有可消除的格子 只要有便不结束游戏
			if(j!=3&&i!=3)
			{
				if(cardTable[i][j]->getCardNumber()==cardTable[i+1][j]->getCardNumber()||cardTable[i][j]->getCardNumber()==cardTable[i][j+1]->getCardNumber())
					isEnd=false;
			}
			else if(i==3&&j==3)
			{
				
			}
			else if(i==3)
			{
				if(cardTable[i][j]->getCardNumber()==cardTable[i][j+1]->getCardNumber())
					isEnd=false;
			}
			else if(j==3)
			{
				if(cardTable[i][j]->getCardNumber()==cardTable[i+1][j]->getCardNumber())
					isEnd=false;
			}
		}

	//没有填满 可以继续
	if(count<16)
	{
		//log("no");
		return;
	}

	if(isEnd)
	{
		log("Yes");
		//重置游戏
		_isReStart=true;
		ReStartGame();
		return;
	}


}

//初始化分数
void HelloWorld::initScore()
{
	_score=0;
	//this->_labelScore=Label::create("Score: 0","Arial",20);
	this->_labelScore->setString(String::createWithFormat("Score: %d",_score)->getCString());
	this->_labelScore->setPosition(visibleSize.width/2,visibleSize.height-visibleSize.height/12);
	

	//读取分数
	_bestScore= UserDefault::getInstance()->getIntegerForKey("BestScore",0);
	//this->_labelBestScore=Label::create(String::createWithFormat("Best Score: %d",_bestScore)->getCString(),"Arial",20);
	this->_labelBestScore->setString(String::createWithFormat("Score: %d",_bestScore)->getCString());
	this->_labelBestScore->setPosition(visibleSize.width*0.8,visibleSize.height-visibleSize.height/12);
	this->_labelBestScore->setColor(Color3B::YELLOW);
	
}

//更新分数
void HelloWorld::updateScore(int score)
{
	_score+=score;
	this->_labelScore->setString(String::createWithFormat("Score: %d",_score)->getCString());
	if(_score>_bestScore)
		this->_labelBestScore->setString(String::createWithFormat("Score: %d",_score)->getCString());
}

//重置游戏
void HelloWorld::ReStartGame()
{
	if(_score>_bestScore)
		UserDefault::getInstance()->setIntegerForKey("BestScore",_score);
	//Director::getInstance()->replaceScene(HelloWorld::createScene());
	initScore();
	initCardTable();
}


CardSprite.h

#ifndef __CardSprite__
#define __CardSprite__ 
#include"cocos2d.h"

class CardSprite:public cocos2d::Sprite
{
public:
	static CardSprite* cardTable[4][4];
	
	static CardSprite* createWithArgs(int number,int posX,int posY,float weight,float Height);
	int getCardNumber();
	void setCardNumber(int number);
	void doubleNumber();
	cocos2d::Label* getLabel()
	{
		return labelNumber;
	}
private:
	int _cardNumber;
	bool initWithArgs(int number,int posX,int posY,float weight,float Height);
	cocos2d::Label* labelNumber;
	cocos2d::LayerColor* layerBgColor;
	
	CREATE_FUNC(CardSprite);
};
#endif

CardSprite.cpp


#include"CardSprite.h"
USING_NS_CC;
using namespace std;
//设置数值
void CardSprite::setCardNumber(int number)
{
	
	if(number>0)
	{
		//设置颜色
		switch (number)
		{
		case 2:
			labelNumber->setColor(Color3B::WHITE);
			break;
		case 4:
			labelNumber->setColor(Color3B(0xcc,0x99,0x00));
			break;
		case 8:
			labelNumber->setColor(Color3B::BLUE);
			break;
		case 16:
			labelNumber->setColor(Color3B::YELLOW);
			break;
		case 32:
			labelNumber->setColor(Color3B::GREEN);
			break;
		case 64:
			labelNumber->setColor(Color3B::BLACK);
			break;
		case 128:
			labelNumber->setColor(Color3B(0xff,0x00,0x33));
			break;
		case 256:
			labelNumber->setColor(Color3B(0x33,0xcc,0xff));
			break;
		case 512:
			labelNumber->setColor(Color3B(0xff,0x99,0xcc));
			break;
		case 1024:
			labelNumber->setColor(Color3B(0x77,0x00,0x00));
			break;
		case 2048:
			labelNumber->setColor(Color3B(0xff,0xff,0x66));
			break;
			
		default:
			labelNumber->setColor(Color3B(0x00,0x88,0x00));
			break;
		}

		//设置大小 应该根据屏幕设置
		labelNumber->setSystemFontSize(50);
		if(number>10)
			labelNumber->setSystemFontSize(48);
		if(number>100)
			labelNumber->setSystemFontSize(45);
		if(number>1000)
			labelNumber->setSystemFontSize(42);
		
		if(_cardNumber==0)
		{
			//原值为0直接淡入
			FadeIn *fadeIn=FadeIn::create(0.2);
			Sequence *sequence=Sequence::create(CallFunc::create([this,number]()->void{this->labelNumber->setString(String::createWithFormat("%d",number)->getCString());}),fadeIn,NULL);
			labelNumber->runAction(sequence);
		}
		else
		{
			//原值不为0 先淡出 更新数值 淡入加旋转
			FadeOut *fadeout=FadeOut::create(0.1);
			FadeIn *fadeIn=FadeIn::create(0.2);
			RotateBy *rotateBy=RotateBy::create(0.2,Vec3(0,0,360));
			Spawn *spawn=Spawn::create(fadeIn,rotateBy,NULL);
			Sequence *sequence=Sequence::create(fadeout, CallFunc::create([this,number]()->void{this->labelNumber->setString(String::createWithFormat("%d",number)->getCString());}),spawn,NULL);
		//labelNumber->setString(String::createWithFormat("%d",number)->getCString());
		
		
		

			labelNumber->runAction(sequence);
		}
		
		//auto fadeIn=fadeout->reverse();
		
		
	}
	else
	{
		//淡出
		labelNumber->setString("");
		FadeOut *fadeout=FadeOut::create(0.1);
		labelNumber->runAction(fadeout);
	}
	_cardNumber=number;
}

//。。。不想说
int CardSprite::getCardNumber()
{
	return _cardNumber;
}

//仿得Sprite写的  不要问我为什么
CardSprite* CardSprite::createWithArgs(int number,int posX,int posY,float weight,float Height)
{
	CardSprite* cs=new CardSprite();
	if(cs&&cs->initWithArgs(number,posX, posY,weight,Height))
	{
		cs->autorelease();
		return cs;
	}
	CC_SAFE_DELETE(cs);
	return NULL;
}

//真正的初始化
bool CardSprite::initWithArgs(int number,int posX,int posY,float weight,float Height)
{
	if(Sprite::init())
	{
		//设置背景
		layerBgColor=LayerColor::create(Color4B::GRAY,weight*0.9,Height*0.9);
		//还是左下角比较舒服  下面的是忽视锚点  不过习惯设为0
		layerBgColor->setAnchorPoint(ccp(0,0));
		layerBgColor->ignoreAnchorPointForPosition(true);
		layerBgColor->setPosition(0.05*weight,0.05*Height);
		this->addChild(layerBgColor);
		
		labelNumber=Label::create("", "Arial",50);
		labelNumber->setPosition(0.5*weight,0.5*Height);
		this->setCardNumber(number);
		this->addChild(labelNumber);

		this->setAnchorPoint(ccp(0,0));
		this->setPosition(posX*weight+weight*0.5,posY*Height+Height*0.5);
		//log("%f %f",posX*weight,posY*Height);

		//设置大小
		this->setContentSize(CCSizeMake(weight,Height));
		
		return true;
	}
	else
	{
		return false;
	}

}

//。。。不想说
void CardSprite::doubleNumber()
{
	setCardNumber(_cardNumber*2);
}


AppDelegate.h


#ifndef  _APP_DELEGATE_H_
#define  _APP_DELEGATE_H_

#include "cocos2d.h"

/**
@brief    The cocos2d Application.

The reason for implement as private inheritance is to hide some interface call by Director.
*/
class  AppDelegate : private cocos2d::Application
{
public:
    AppDelegate();
    virtual ~AppDelegate();

    /**
    @brief    Implement Director and Scene init code here.
    @return true    Initialize success, app continue.
    @return false   Initialize failed, app terminate.
    */
    virtual bool applicationDidFinishLaunching();

    /**
    @brief  The function be called when the application enter background
    @param  the pointer of the application
    */
    virtual void applicationDidEnterBackground();

    /**
    @brief  The function be called when the application enter foreground
    @param  the pointer of the application
    */
    virtual void applicationWillEnterForeground();
};

#endif // _APP_DELEGATE_H_

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::create("My Game");
		//设置分辨率
		glview->setFrameSize(480,320);
        director->setOpenGLView(glview);
    }

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

    // 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 = HelloWorld::createScene();

    // run
    director->runWithScene(scene);

    return true;
}

// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground() {
    Director::getInstance()->stopAnimation();

    // if you use SimpleAudioEngine, it must be pause
    // SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
}

// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground() {
    Director::getInstance()->startAnimation();

    // if you use SimpleAudioEngine, it must resume here
    // SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
}


逻辑很简单 触摸开始记录一个位置 在结束时计算出一个向量,求出角度,判断滑动方向,调用相应方法。初始化一个卡片时,判断游戏是否可以继续进行,不可以的条件为16个格子全不为0且相邻的格子数值都不相等。  代码全发出来了,想用直接拿走。


发布android时在AndroidManifest.xml文件中,设置screenOrientation="landscape" 为横屏, screenOrientation="portrait"为竖屏。


前段时间在看Unity3D,c#的lamda用的很舒服,现在cocos2d-x的c++中也开始使用lamda了,比原来的函数指针用的舒服很多。


[capture](parameters)->return_type {body}

 

[捕获参数列表](参数列表)->返回类型{函数体}


[] 不截取任何变量 

[&截取外部作用域中所有变量,并作为引用在函数体中使用 

[=截取外部作用域中所有变量,并拷贝一份在函数体中使用 

[=, &foo] 截取外部作用域中所有变量,并拷贝一份在函数体中使用,但是对foo变量使用引用 [bar] 截取bar变量并且拷贝一份在函数体重使用,同时不截取其他变量 

[this截取当前类中的this指针。如果已经使用了&或者=就默认添加此选项。截取this的目的是可以在lamda中使用当前类的成员函数和成员变量。


如果不爱复制粘贴

http://download.csdn.net/detail/qw6194425/7576511  自己去


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值