资源:http://download.csdn.net/detail/hezeping888/5734051
在游戏中数值显示是一个常用部件,本节将实现对积分的累加,在积分榜上滚动显示。
将积分榜进行分解:将数字分解为一个的位,个位 ,十位等, 每个位的对象都只需要管理自己这个位上的数字滚动显示,然后有一个对每个位进行管理的调度对象,将这些位相互之间的数学关系维护起来。
数字位对象:RollNum
管理数字位对象:RollNumGroup
先讲解上述两个对象的实现,让后再将它们怎样融入到主游戏界面GameLayer的。
下面是RollNum及RollNumGroup的头文件
#ifndef __FishingJoyStep1__RollNum__
#define __FishingJoyStep1__RollNum__
#include "cocos2d.h"
class GameLayer;
/**
数字的每个位,主要控制这个位上得数字的滚动
*/
class RollNum : public cocos2d::CCSprite
{
public:
RollNum();
virtual ~RollNum();
CREATE_FUNC(RollNum);
//设置要滚动到得数字,以及滚动的方向
void setNumber(int var, bool bUp);
int getNumber();
private:
bool init();
CC_SYNTHESIZE(bool, m_bUp, UpDirection);
int m_nNumber; //当前显示的数字
int m_nCurTexH;//当前显示数字纹理的位置
int m_nEndTexH;//数字纹理的高度
bool m_bRolling;//标记当前这个数字是否在滚动
cocos2d::CCTexture2D *m_pTexture;//数字纹理
//不断更新数字纹理显示的位置,达到滚动数字的效果
void updateNumber(cocos2d::CCTime dt);
};
/**
管理数字的每个位,包括控制每个位的位置,及解析数字的每个位,调度RollNum进行显示
*/
class RollNumGroup : public cocos2d::CCObject
{
public:
RollNumGroup();
virtual ~RollNumGroup();
//nDigit 指定积分榜是几位数
static RollNumGroup *createWithGameLayer(GameLayer *pGameLayer, int nDigit);
//设置显示的数字,内部会将数字分解成单个数,然后逐个调用对应的setNumber方法
void setValue(int nValue);
//初始化各个数字的位置,参数指定最右边的那个数字的位子
void setPosition(cocos2d::CCPoint pt);
private:
CC_SYNTHESIZE(cocos2d::CCSpriteBatchNode *, m_pBatchNode, BatchNode);
CC_SYNTHESIZE(GameLayer *, m_pGameLayer, GameLayer);
//存储数字的每个位
CC_SYNTHESIZE_RETAIN(cocos2d::CCArray *, m_pRollNumArray, RollNumArray);
cocos2d::CCPoint m_ptPosition;
int m_nDigit;//展示数字的位数
int m_nValue;//被展示的数字
bool initWithGameLayer(GameLayer *pGameLayer, int nDigit);
};
#endif /* defined(__FishingJoyStep1__RollNum__) */
//
RollNum.cpp的实现代码如下
//
#include "RollNum.h"
#include "cocos2d.h"
#include "GameLayer.h"
using namespace cocos2d;
#define NUMBERHEIGHT 16
#define NUMBERWIDTH 12
#define TEXTUREHEIGHT 196
RollNum::RollNum():m_nNumber(0), m_bUp(true), m_nCurTexH(0), m_nEndTexH(0), m_bRolling(false), m_pTexture(NULL){}
RollNum::~RollNum()
{
this->unscheduleAllSelectors();
}
bool RollNum::init()
{
m_pTexture = CCTextureCache::sharedTextureCache()->textureForKey("number.png");
//初始默认截取数字0的位置进行显示
CCSpriteFrame *pFrame = CCSpriteFrame::createWithTexture(m_pTexture, CCRectMake(0, 0, NUMBERWIDTH, NUMBERHEIGHT));
this->initWithSpriteFrame(pFrame);
this->setScale(1.0f);
return true;
}
//不断更新数字纹理显示的位置,达到滚动数字的效果
void RollNum::updateNumber(cocos2d::CCTime dt)
{
if(m_bRolling && m_nCurTexH == m_nEndTexH)
{
//标记为数字滚动中,且滚动数字纹理到指定位置m_nEndTexH,注销updateNumber,停止滚动
this->unschedule(schedule_selector(RollNum::updateNumber));
m_bRolling = false;
return;
}
//每次向上或向下滚动4px,在数字纹理中,每两两数字的上下间隔为4px,数字本身高度为16px
if(m_bUp)
{
m_nCurTexH += 4;
if(m_nCurTexH >= TEXTUREHEIGHT)
//数字往增大方向滚动到纹理末尾,就从头开始,形成循环
m_nCurTexH = 0;
}
else
{
m_nCurTexH -= 4;
if(m_nCurTexH < 0)
//数字往减小方向滚动到纹理末尾,就从尾部开始,形成循环
m_nCurTexH = TEXTUREHEIGHT;
}
int h = m_nCurTexH;
if(m_nCurTexH >= 180)
//如果进入最后一个数字的高度范围,则从最后一个数字的位置开始
h = 180;
//截取指定范围的数字纹理
CCSpriteFrame *pFrame = CCSpriteFrame::createWithTexture(m_pTexture, CCRectMake(0, h, NUMBERWIDTH, NUMBERHEIGHT));
//更新自己负责的位的展现的数字纹理
this->setDisplayFrame(pFrame);
m_bRolling = true;
}
void RollNum::setNumber(int var, bool bUp)
{
m_nNumber = var;
m_bUp = bUp;
//计算当前位的数字纹理滚动到位置
m_nEndTexH = m_nNumber * (NUMBERHEIGHT + 4);
//周期更新数字纹理的位置,形成滚动效果
this->schedule(schedule_selector(RollNum::updateNumber), 0.01f);
}
int RollNum::getNumber()
{
return m_nNumber;
}
RollNumGroup.cpp 实现如下
RollNumGroup *RollNumGroup::createWithGameLayer(GameLayer *pGameLayer, int nDigit)
{
RollNumGroup *pRollNumGroup = new RollNumGroup();
if(pRollNumGroup && pRollNumGroup->initWithGameLayer(pGameLayer, nDigit))
{
//将自己设置为内存自动管理的对象
pRollNumGroup->autorelease();
return pRollNumGroup;
}
else
{
CC_SAFE_DELETE(pRollNumGroup);
return NULL;
}
}
RollNumGroup::RollNumGroup():m_pRollNumArray(NULL), m_nValue(0){}
RollNumGroup::~RollNumGroup()
{
CC_SAFE_RELEASE(m_pRollNumArray);
}
bool RollNumGroup::initWithGameLayer(GameLayer *pGameLayer, int nDigit)
{
m_pGameLayer = pGameLayer;
//装载数字纹理
CCTexture2D *pTex = CCTextureCache::sharedTextureCache()->addImage("number.png");
m_pBatchNode = CCSpriteBatchNode::createWithTexture(pTex);
//将积分榜添加到主游戏界面上
m_pGameLayer->addChild(m_pBatchNode, 100);
this->setRollNumArray(CCArray::createWithCapacity(nDigit));
for(int i = 0; i < nDigit; i++)
{
//创建积分榜中的每一个数字位
RollNum *pRollNum = RollNum::create();
m_pRollNumArray->addObject(pRollNum);
//将数字位显示到主游戏界面上
m_pBatchNode->addChild(pRollNum);
}
return true;
}
void RollNumGroup::setPosition(cocos2d::CCPoint pt)
{
m_ptPosition = pt;//积分榜的个位的位置坐标
for(int i = 0; i < m_pRollNumArray->count(); ++i)
{
RollNum *pRollNum = (RollNum *)m_pRollNumArray->objectAtIndex(i);
pRollNum->setPosition(pt);
//每个位的 坐标从右往左移动,间隔20.7px
pt.x -= 20.7f;
}
}
void RollNumGroup::setValue(int nValue)
{
//设置的数字与显示的一直时,直接返回
if(m_nValue == nValue)
return;
//设置积分榜中得数字滚动的方向
bool bUp = m_nValue < nValue;
m_nValue = nValue;
//解析每个位上的数,循环调度对应位上的数的滚动显示
for(int i = 0; i < m_pRollNumArray->count(); ++i)
{
RollNum *pRollNum = (RollNum *)m_pRollNumArray->objectAtIndex(i);
int num = nValue % 10;//取得与显示的积分榜中的末位上的数
//将m_pRollNumArray 中的第一个RollNum定义为个位,第二位为十位,依次类推
if(pRollNum->getNumber() != num)
//调度相应位上数字滚动
pRollNum->setNumber(num, bUp);
//去掉预显示的积分数的末位,进入下一位数字显示调度
nValue = nValue / 10;
}
}
//
下面来看看主游戏界面是怎么使用它们的。
在GameLayer.h 中添加 RollNum.h的头文件
添加定义:
public:
CC_SYNTHESIZE_RETAIN(RollNumGroup *, m_pRollNumGroup, RollNumGroup);//定义积分榜
在GameLayer.cpp中进行初始,调用,和释放
在 GameLayer::~GameLayer()方法中添加释放代码:
CC_SAFE_RELEASE(m_pRollNumGroup);
在void GameLayer::initBackground()添加初始化代码:
this->setRollNumGroup(RollNumGroup::createWithGameLayer(this, 6));
m_pRollNumGroup->setPosition(ccp(353, 21));
在 void GameLayer::updateGame(cocos2d::CCTime dt)中,将上一节两句代码注释放开:
m_nScore += 125;//此处简单处理,让每一种鱼的积分都是125分
//更新积分榜
m_pRollNumGroup->setValue(m_nScore);
OK,到现在积分榜就可以正常使用了。赶紧运行起来感受一下自己的捕鱼达人吧。