Cocos2dx制作2048(2.数字方块的创建)

我们今天来完成数字方块的创建以及把方块添加到主场景中,完成4行4列矩阵方块的添加


1.数字方块的创建

1.1新增方块精灵

我们在Classes目录上右键添加新建项,如下图

注意,点击浏览,统一把代码放到Classes目录下, 一次添加源文件

如图

1.2分析游戏,编写方块精灵头文件

第一步:首先我们的数字方块其实就是一个一个的精灵,总共是4X4=16个精灵,所以我们的SquareSprite类是继承与CCSprite的
#ifndef _SQUARE_SPRITE_H_
#define _SQUARE_SPRITE_H_
#include "cocos2d.h"
using namespace cocos2d;
class SquareSprite:public CCSprite
{
public:
	SquareSprite();
private:

};
#endif // !_SQUARE_SPRITE_H_
第二步:创建的方块需要多大?方块需要摆放在什么位置上?16个方块都是在不同位置的,然后,方块显示的数字是多少?
分析 得出,我们需要定义几个变量和方块创建的方法
变量:m_number(方块中的数字) m_lablenumber(显示数字的标签) m_layercolor(带颜色的层,用于显示方块)
形参:pointx(方块的X轴) pointy(方块的Y轴) width(方块的宽度) height(方块的高度)
方法:createSquareSprite(创建方块精灵的方法) initSquareSprite(初始化方块精灵的方法) getNumber(获得方块中数字)setNumber

#ifndef _SQUARE_SPRITE_H_
#define _SQUARE_SPRITE_H_
#include "cocos2d.h"
using namespace cocos2d;
class SquareSprite:public CCSprite
{
public:
	SquareSprite();
	static SquareSprite* createSquareSprite(int number,float pointx,float pointy,int width,int height);
	int getNumber();
	void setNumber(int number);
	CREATE_FUNC(SquareSprite);
private:
	int m_number;
	CCLabelTTF* m_lablenumber;
	CCLayerColor* m_layercolor;
	void initSquareSprite(int number,float pointx,float pointy,int width,int height);
};
#endif // !_SQUARE_SPRITE_H_

1.3编写方块精灵的实现

一个个来实现

第一:实现构造函数,初始化成员变量
#include "SquareSprite.h"
SquareSprite::SquareSprite()
	:m_number(0)
	,m_lablenumber(NULL)
	,m_layercolor(NULL)
{
}
第二 :实现创建方块精灵的函数(creteSquareSprite)

我们可以在基类CCSprite中找到create源码,复制一份,在改成如下:
SquareSprite* SquareSprite::createSquareSprite(int number,float pointx,float pointy,int width,int height)
{
	SquareSprite *pSprite = new SquareSprite();
    if (pSprite && pSprite->init())
    {
        pSprite->autorelease();
        return pSprite;
    }
    CC_SAFE_DELETE(pSprite);
    return NULL;
}
第三:实现getNumber和setNumber
int SquareSprite::getNumber()
{
	return m_number;
}
void SquareSprite::setNumber(int number)
{
	m_number=number;
	m_lablenumber->setString("");
	if (m_number>0)
	{
		m_lablenumber->setString(CCString::createWithFormat("%i",m_number)->getCString());
	}
}
第四 :实现initSquareSprite
void SquareSprite::initSquareSprite(int number,float pointx,float pointy,int width,int height)
{
	m_number=number;
	m_layercolor=CCLayerColor::create(ccc4(200,190,180,255),width,height);
	m_layercolor->setPosition(ccp(pointx,pointy));
	this->addChild(m_layercolor);
	//创建字体
	m_lablenumber=CCLabelTTF::create("","arial.ttf",50);
	m_lablenumber->setColor(ccc3(0,0,0));
	m_lablenumber->setPosition(ccp(m_layercolor->getContentSize().width/2,m_layercolor->getContentSize().height/2));
	m_layercolor->addChild(m_lablenumber);
	setNumber(number);
}

第五:修改createSquareSprite和HelloWorldScene中的init 测试创建的精灵
此时createSquareSprite代码如下:

SquareSprite* SquareSprite::createSquareSprite(int number,float pointx,float pointy,int width,int height)
{
	SquareSprite *pSprite = new SquareSprite();
	if (pSprite && pSprite->init())
	{
		pSprite->autorelease();
		pSprite->initSquareSprite( number, pointx, pointy, width, height);
		return pSprite;
	}
	CC_SAFE_DELETE(pSprite);
	return NULL;
}
HelloWorld:Scene.cpp中的init如下:
bool HelloWorld::init()
{
	//
	// 1. super init first
	if ( !CCLayer::init() )
	{
		return false;
	}

	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
	CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
	SquareSprite* pSquareSprite=SquareSprite::createSquareSprite(2,50,50,100,100);
	this->addChild(pSquareSprite);
	return true;
}
运行看看效果:


不错,呵呵

我们再来优化优化方块,不同的字体显示不同的颜色

第六:修改setNumber,优化方块颜色
void SquareSprite::setNumber(int number)
{
	m_number=number;
	m_lablenumber->setString("");
	m_layercolor->setColor(ccc3(200,190,180));
	if (m_number>0)
	{
		m_lablenumber->setString(CCString::createWithFormat("%i",m_number)->getCString());
		//设置卡片颜色
		switch (m_number)
		{
		case 2:
			m_layercolor->setColor(ccc3(255,245,238));
			break;
		case 32:
		case 4:
			m_layercolor->setColor(ccc3(255,0,0));
			break;
		case 8:
			m_layercolor->setColor(ccc3(244,164,96));
			break;
		case 16:
			m_layercolor->setColor(ccc3(255,69,0));
			break;
		case 64:
			m_layercolor->setColor(ccc3(250,128,114));
			break;
		case 128:
			m_layercolor->setColor(ccc3(255,228,181));
			break;
		case 256:
			m_layercolor->setColor(ccc3(240,230,140));
			break;
		case 512:
			m_layercolor->setColor(ccc3(255,250,205));
			break;
		case 1024:
			m_layercolor->setColor(ccc3(255,160,122));
			break;
		case 2048:
			m_layercolor->setColor(ccc3(250,240,230));
			break;
		case 4096:
			m_layercolor->setColor(ccc3(255,228,225));
			break;
		case 8192:
			m_layercolor->setColor(ccc3(188,143,143));
			break;
		case 16384:
			m_layercolor->setColor(ccc3(205,92,92));
			break;
		default:
			break;
		}
	}
}
现在我们改下number的值看看效果

,最终修改完成后,我们的方块代码头文件如下:
#ifndef _SQUARE_SPRITE_H_
#define _SQUARE_SPRITE_H_
#include "cocos2d.h"
using namespace cocos2d;
class SquareSprite:public CCSprite
{
public:
	SquareSprite();
	static SquareSprite* createSquareSprite(int number,float pointx,float pointy,int width,int height);
	int getNumber();
	void setNumber(int number);
	CREATE_FUNC(SquareSprite);
private:
	int m_number;
	CCLabelTTF* m_lablenumber;
	CCLayerColor* m_layercolor;
	void initSquareSprite(int number,float pointx,float pointy,int width,int height);
};
#endif // !_SQUARE_SPRITE_H_
源文件:
#include "SquareSprite.h"
SquareSprite::SquareSprite()
	:m_number(0)
	,m_lablenumber(NULL)
	,m_layercolor(NULL)
{
}
SquareSprite* SquareSprite::createSquareSprite(int number,float pointx,float pointy,int width,int height)
{
	SquareSprite *pSprite = new SquareSprite();
	if (pSprite && pSprite->init())
	{
		pSprite->autorelease();
		pSprite->initSquareSprite( number, pointx, pointy, width, height);
		return pSprite;
	}
	CC_SAFE_DELETE(pSprite);
	return NULL;
}
int SquareSprite::getNumber()
{
	return m_number;
}
void SquareSprite::setNumber(int number)
{
	m_number=number;
	m_lablenumber->setString("");
	m_layercolor->setColor(ccc3(200,190,180));
	if (m_number>0)
	{
		m_lablenumber->setString(CCString::createWithFormat("%i",m_number)->getCString());
		//设置卡片颜色
		switch (m_number)
		{
		case 2:
			m_layercolor->setColor(ccc3(255,245,238));
			break;
		case 32:
		case 4:
			m_layercolor->setColor(ccc3(255,0,0));
			break;
		case 8:
			m_layercolor->setColor(ccc3(244,164,96));
			break;
		case 16:
			m_layercolor->setColor(ccc3(255,69,0));
			break;
		case 64:
			m_layercolor->setColor(ccc3(250,128,114));
			break;
		case 128:
			m_layercolor->setColor(ccc3(255,228,181));
			break;
		case 256:
			m_layercolor->setColor(ccc3(240,230,140));
			break;
		case 512:
			m_layercolor->setColor(ccc3(255,250,205));
			break;
		case 1024:
			m_layercolor->setColor(ccc3(255,160,122));
			break;
		case 2048:
			m_layercolor->setColor(ccc3(250,240,230));
			break;
		case 4096:
			m_layercolor->setColor(ccc3(255,228,225));
			break;
		case 8192:
			m_layercolor->setColor(ccc3(188,143,143));
			break;
		case 16384:
			m_layercolor->setColor(ccc3(205,92,92));
			break;
		default:
			break;
		}
	}
}
void SquareSprite::initSquareSprite(int number,float pointx,float pointy,int width,int height)
{
	m_number=number;
	m_layercolor=CCLayerColor::create(ccc4(200,190,180,255),width,height);
	m_layercolor->setPosition(ccp(pointx,pointy));
	this->addChild(m_layercolor);
	//创建字体
	m_lablenumber=CCLabelTTF::create("","arial.ttf",50);
	m_lablenumber->setColor(ccc3(0,0,0));
	m_lablenumber->setPosition(ccp(m_layercolor->getContentSize().width/2,m_layercolor->getContentSize().height/2));
	m_layercolor->addChild(m_lablenumber);
	setNumber(number);
}

添加方块到主场景

2.1修改整个窗体的大小,让它更像手机竖屏

main.cpp中的这么一句
eglView->setFrameSize(320, 480);
设置FPS隐藏,AppDelagate.cpp中
 pDirector->setDisplayStats(false);

有点像了哼

2.2新增方法用来初始化4X4矩阵

首先我们根据下图来分析一下,因为我们的方块得根据手机屏幕来自适应的,所以不能像测试一样给定死咯

我们的窗体是320宽度,其中每个方块之间的间隔是10,故而,我们得出计算方块的算法是什么呢??

很简单:(窗体的宽度-5*间隔)/4
大小计算出来了,然后双重循环遍历,创建方块

在创建的时候,还记得我们有什么参数吗??

现在我们缺少的参数有,方块位置的起点

怎么破呢?? 这里需要注意,我们用了Layer作为精灵,CCLayer的锚点不是0.5了  而是0即左下角

起点X的算法: 空隙+方块的横向下标*方块的宽度+方块的横向下标*空隙

不理解??上图


起点Y的算法:这个其实和X是一样的,这里最下面一片的这个间隔可以自己调,这个不能居中,因为最后我们还得在顶部增加用了显示总分数的

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
	//
	// 1. super init first
	if ( !CCLayer::init() )
	{
		return false;
	}

	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
	CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
	initMatrix(visibleSize);
	return true;
}
void HelloWorld::initMatrix(CCSize size)
{
	//两个方块之间的空隙
	int space=10;
	int SquareSize=(size.width-space*5)/4;
	for (int x = 0; x < 4; x++)
	{
		for (int y = 0; y < 4; y++)
		{
			float pointx=space+x*SquareSize+x*space;
			float pointy=40+y*SquareSize+y*space;
			SquareSprite* pSquareSprite=SquareSprite::createSquareSprite(0,pointx,pointy,SquareSize,SquareSize);
			this->addChild(pSquareSprite);
		}
	}
}


当然,你如果觉得太挤了也可以改成这样:
void HelloWorld::initMatrix(CCSize size)
{
	//两个方块之间的空隙
	int space=10;
	//2*20	最左边和最右边的空隙
	int SquareSize=(size.width-space*3-2*20)/4;
	for (int x = 0; x < 4; x++)
	{
		for (int y = 0; y < 4; y++)
		{
			float pointx=20+x*SquareSize+x*space;
			float pointy=40+y*SquareSize+y*space;
			SquareSprite* pSquareSprite=SquareSprite::createSquareSprite(0,pointx,pointy,SquareSize,SquareSize);
			this->addChild(pSquareSprite);
		}
	}
}

2.3定义数组用了存储每个方块

//二维数组存储方块
	SquareSprite* m_squarearray[4][4];

void HelloWorld::initMatrix(CCSize size)
{
	//两个方块之间的空隙
	int space=10;
	int SquareSize=(size.width-space*5)/4;
	for (int x = 0; x < 4; x++)
	{
		for (int y = 0; y < 4; y++)
		{
			float pointx=space+x*SquareSize+x*space;
			float pointy=40+y*SquareSize+y*space;
			SquareSprite* pSquareSprite=SquareSprite::createSquareSprite(0,pointx,pointy,SquareSize,SquareSize);
			this->addChild(pSquareSprite);
			m_squarearray[x][y]=pSquareSprite;
		}
	}
}

2.4创建随机产生方块的方法 (其实就是随机产生数字而已)

void HelloWorld::initMatrix(CCSize size)
{
	//两个方块之间的空隙
	int space=10;
	int SquareSize=(size.width-space*5)/4;
	for (int x = 0; x < 4; x++)
	{
		for (int y = 0; y < 4; y++)
		{
			float pointx=space+x*SquareSize+x*space;
			float pointy=40+y*SquareSize+y*space;
			SquareSprite* pSquareSprite=SquareSprite::createSquareSprite(0,pointx,pointy,SquareSize,SquareSize);
			this->addChild(pSquareSprite);
			m_squarearray[x][y]=pSquareSprite;
		}
	}
	//刚开始游戏,创建两个方块
	autoSquare();
	autoSquare();
}
void HelloWorld::autoSquare()
{
	int x=CCRANDOM_0_1()*4;
	int y=CCRANDOM_0_1()*4;
	if (m_squarearray[x][y]->getNumber()>0)
	{
		autoSquare();
	}
	else
	{
		m_squarearray[x][y]->setNumber(2);
	}
}

2.5搞点背景色

//搞点背景
	CCLayerColor* layerColorBG= CCLayerColor::create(ccc4(180,170,160,255));
	this->addChild(layerColorBG,0);


最后代码就不传了,反正也没用到任何资源,就直接贴出来算了

SquareSprite.h
#ifndef _SQUARE_SPRITE_H_
#define _SQUARE_SPRITE_H_
#include "cocos2d.h"
using namespace cocos2d;
class SquareSprite:public CCSprite
{
public:
	SquareSprite();
	static SquareSprite* createSquareSprite(int number,float pointx,float pointy,int width,int height);
	int getNumber();
	void setNumber(int number);
	CREATE_FUNC(SquareSprite);
private:
	int m_number;
	CCLabelTTF* m_lablenumber;
	CCLayerColor* m_layercolor;
	void initSquareSprite(int number,float pointx,float pointy,int width,int height);
};
#endif // !_SQUARE_SPRITE_H_

SquareSprite.cpp

#include "SquareSprite.h"
SquareSprite::SquareSprite()
	:m_number(0)
	,m_lablenumber(NULL)
	,m_layercolor(NULL)
{
}
SquareSprite* SquareSprite::createSquareSprite(int number,float pointx,float pointy,int width,int height)
{
	SquareSprite *pSprite = new SquareSprite();
	if (pSprite && pSprite->init())
	{
		pSprite->autorelease();
		pSprite->initSquareSprite( number, pointx, pointy, width, height);
		return pSprite;
	}
	CC_SAFE_DELETE(pSprite);
	return NULL;
}
int SquareSprite::getNumber()
{
	return m_number;
}
void SquareSprite::setNumber(int number)
{
	m_number=number;
	m_lablenumber->setString("");
	m_layercolor->setColor(ccc3(200,190,180));
	if (m_number>0)
	{
		m_lablenumber->setString(CCString::createWithFormat("%i",m_number)->getCString());
		//设置卡片颜色
		switch (m_number)
		{
		case 2:
			m_layercolor->setColor(ccc3(255,245,238));
			break;
		case 32:
		case 4:
			m_layercolor->setColor(ccc3(255,0,0));
			break;
		case 8:
			m_layercolor->setColor(ccc3(244,164,96));
			break;
		case 16:
			m_layercolor->setColor(ccc3(255,69,0));
			break;
		case 64:
			m_layercolor->setColor(ccc3(250,128,114));
			break;
		case 128:
			m_layercolor->setColor(ccc3(255,228,181));
			break;
		case 256:
			m_layercolor->setColor(ccc3(240,230,140));
			break;
		case 512:
			m_layercolor->setColor(ccc3(255,250,205));
			break;
		case 1024:
			m_layercolor->setColor(ccc3(255,160,122));
			break;
		case 2048:
			m_layercolor->setColor(ccc3(250,240,230));
			break;
		case 4096:
			m_layercolor->setColor(ccc3(255,228,225));
			break;
		case 8192:
			m_layercolor->setColor(ccc3(188,143,143));
			break;
		case 16384:
			m_layercolor->setColor(ccc3(205,92,92));
			break;
		default:
			break;
		}
	}
}
void SquareSprite::initSquareSprite(int number,float pointx,float pointy,int width,int height)
{
	m_number=number;
	m_layercolor=CCLayerColor::create(ccc4(200,190,180,255),width,height);
	m_layercolor->setPosition(ccp(pointx,pointy));
	this->addChild(m_layercolor);
	//创建字体
	m_lablenumber=CCLabelTTF::create("","arial.ttf",30);
	m_lablenumber->setColor(ccc3(0,0,0));
	m_lablenumber->setPosition(ccp(m_layercolor->getContentSize().width/2,m_layercolor->getContentSize().height/2));
	m_layercolor->addChild(m_lablenumber);
	setNumber(number);
}

HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "SimpleAudioEngine.h"
#include "SquareSprite.h"
using namespace CocosDenshion;
using namespace cocos2d;
class HelloWorld : public cocos2d::CCLayer
{
public:
	HelloWorld();
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  

    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::CCScene* scene();
    
    // implement the "static node()" method manually
    CREATE_FUNC(HelloWorld);
public:
	virtual void onEnter();
	virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
	//上下左右滑动时调用
	bool doTop();
	bool doDown();
	bool doReight();
	bool doLeft();
	//初始化矩阵
	void initMatrix(CCSize size);
	//随机产生方块
	void autoSquare();
private:
	//启点的X坐标,Y坐标
	//起点到终点X的距离,Y的距离
	int m_StartX,m_StartY,m_RangeX,m_RangeY;
	//二维数组存储方块
	SquareSprite* m_squarearray[4][4];
};

#endif // __HELLOWORLD_SCENE_H__

HelloWorldScene.cpp

#include "HelloWorldScene.h"

USING_NS_CC;
HelloWorld::HelloWorld()
	:m_StartX(0)
	,m_StartY(0)
	,m_RangeX(0)
	,m_RangeY(0)
{
}
CCScene* HelloWorld::scene()
{
	// 'scene' is an autorelease object
	CCScene *scene = CCScene::create();

	// 'layer' is an autorelease object
	HelloWorld *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 ( !CCLayer::init() )
	{
		return false;
	}

	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
	CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
	initMatrix(visibleSize);
	//搞点背景
	CCLayerColor* layerColorBG= CCLayerColor::create(ccc4(180,170,160,255));
	this->addChild(layerColorBG,0);
	return true;
}
void HelloWorld::initMatrix(CCSize size)
{
	//两个方块之间的空隙
	int space=10;
	int SquareSize=(size.width-space*5)/4;
	for (int x = 0; x < 4; x++)
	{
		for (int y = 0; y < 4; y++)
		{
			float pointx=space+x*SquareSize+x*space;
			float pointy=40+y*SquareSize+y*space;
			SquareSprite* pSquareSprite=SquareSprite::createSquareSprite(0,pointx,pointy,SquareSize,SquareSize);
			this->addChild(pSquareSprite,1);
			m_squarearray[x][y]=pSquareSprite;
		}
	}
	//刚开始游戏,创建两个方块
	autoSquare();
	autoSquare();
}
void HelloWorld::autoSquare()
{
	int x=CCRANDOM_0_1()*4;
	int y=CCRANDOM_0_1()*4;
	if (m_squarearray[x][y]->getNumber()>0)
	{
		autoSquare();
	}
	else
	{
		m_squarearray[x][y]->setNumber(2);
	}
}
void HelloWorld::onEnter()
{
	CCLayer::onEnter();
	this->setTouchMode(kCCTouchesOneByOne);
	this->setTouchEnabled(true);
}
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
	m_StartX=pTouch->getLocation().x;
	m_StartY=pTouch->getLocation().y;
	return true;
}
void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
	CCPoint point=	pTouch->getLocation();
	m_RangeX=m_StartX-point.x;
	m_RangeY=m_StartY-point.y;

	if (abs(m_RangeX)>abs(m_RangeY))
	{
		//X大于Y	左右移动
		if (m_RangeX>5)
		{
			//正数	向左
			doLeft();
		}
		else  if(m_RangeX<-5)
		{
			//负数	向右
			doReight();
		}
	}
	else
	{
		//否则	上下移动
		if (m_RangeY>5)
		{
			//正数	向下
			doDown();
		}
		else  if(m_RangeY<-5)
		{
			//负数	向上
			doTop();
		}
	}
}
bool HelloWorld::doTop()
{
	CCLOG("doTop Runing");
	return true;
}
bool HelloWorld::doDown()
{
	CCLOG("doDown Runing");
	return true;
}
bool HelloWorld::doReight()
{
	CCLOG("doReight Runing");
	return true;
}
bool HelloWorld::doLeft()
{
	CCLOG("doLeft Runing");
	return true;
}

OK,今天先到这来,写的有点多,其实内容不多,说的比较细而已,


最起码,我认为,认真看完就完全能理解变为自己的东西,就算没有此博文,自己也能写出来代码,这才是硬道理

而不像其他的博文,看完还是不理解,云里雾里的,不看着博文写自己完全无从下手


下一篇就开始写游戏的逻辑了,反正偶觉得这个游戏逻辑不是一般的复杂啊,

上次写了两个下午,最后因为JNI问题,移植了2小时,往Android上一安装,测试一下,居然还有BUG

这次写这个系列的博客,也是为了把自己的思路理一理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值