cocos2dx-3.10 C++实现滚动数字

本文实例为大家分享了cocos2dx-3.10 C++实现滚动数字的具体代码,供大家参考,具体内容如下

NumberScroller.h

#ifndef _NUMBERSCROLLER_H_
#define _NUMBERSCROLLER_H_

#include "cocos2d.h"
USING_NS_CC;

/*
  这是一个数字滚动切换控件
  更新方向:
  1.在规定时间运动完,速度在变化
  2.能指定字体表
  3.增加新的更新算法,确保运动到指定数时候可以及时完成
  4.添加能够指定宽和高以及数字之间的间隔
*/
class NumberColumn : public Node{
private:
  NumberColumn();
public:
  static NumberColumn* create(int fontHight);
  void setNumber(int number,bool direction=true);
  void setTime(float time);
private:
  bool init(int fontHight);
  void update(float delta);
private:
  Node* m_numbers;    //当前显示节点
  int m_cur_num;     //当前显示数字
  int m_target_num;    //目标显示数组
  int m_fontHight;    //当个字体高度

  float m_time;      //切换总时间

  float update_moveSum; //几率在两个数字更新期间移动的距离
  float update_speed;  //刷新一次的时间
};



class NumberScroller : public Node{
private:
  NumberScroller();
public:
  static NumberScroller* create(int length,int fontWidth,int fontHeight,int fontSpacing);
  void setTime(float time);
  void setNumber(int number);
  int getNumber();
private:
  bool init(int length, int fontWidth, int fontHeight, int fontSpacing);
private:
  Vector m_columns;  //存储一共的列数
  int m_cur_num;           //当前显示数字
  int m_length;            //列数
  int m_time;             //切换总时间
  int m_fontWidth;          //字体宽度
  int m_fontHeight;          //字体高度
  int m_fontSpacing;         //字体间隔
  Node* m_visibleNode;        //当前可视节点
};
#endif

NumberScroller.cpp

#include "NumberScroller.h"

NumberColumn::NumberColumn():
  m_cur_num(0),
  m_target_num(0),
  m_time(1.0f),
  update_moveSum(0),
  update_speed(0)
{

}

NumberColumn* NumberColumn::create(int fontHight){
  NumberColumn* ret = new NumberColumn();
  if (ret && ret->init(fontHight)){
    ret->autorelease();
    return ret;
  }
  CC_SAFE_DELETE(ret);
  return nullptr;
}

bool NumberColumn::init(int fontHight){
  if(!Node::init())  return false;
  m_numbers = Node::create();
  this->addChild(m_numbers);
  m_fontHight = fontHight;

  this->scheduleUpdate();

  //初始化一列0-9 共十个数字
  for(int i=0;i<10;i++){
    char str[2];
    str[0] = i + '0';
    str[1] = '\0';

    auto temp = Label::createWithBMFont("fonts/test.fnt", str);
    temp->setAnchorPoint(Point(0,0));
    temp->setPosition(Point(0, i * fontHight));
    m_numbers->addChild(temp);
  }
  //为了兼容不同方向的偏转
  char str[2];
  str[0]='0';
  str[1]='\0';  //添加字符串结束符
  Label* temp = Label::createWithBMFont("fonts/test.fnt", str);
  temp->setAnchorPoint(Point(0,0));
  temp->setPosition(Point(0, 10 * fontHight));
  m_numbers->addChild(temp);

  return true;
}
void NumberColumn::setNumber(int number,bool direction){
  m_target_num = number;
  int delta = m_target_num - m_cur_num;      //计算数字间隔
  update_speed = (delta * m_fontHight / m_time);  //v = s / t
}

void NumberColumn::setTime(float time){
  m_time = time;
}

void NumberColumn::update(float d){
  if(m_cur_num != m_target_num){ //如果当前显示的数字不等于目标数字,即要开始滚动
    float dis = update_speed * d; //每次调用update函数需要滚动的距离等于update_speed 乘以 d (update_speed在setNumber函数中已经算出) 
    m_numbers->setPositionY(m_numbers->getPositionY() - dis);//每次使整条向下移动dis距离
    update_moveSum += dis;//update_moveSum 用于保存现在到底移动了多少距离
    if (update_moveSum >= m_fontHight){ //如果现在已经移动了一个字大小的距离
      //每移动一次累加1
      m_cur_num++;
      //对10求余是为了在每次达到10后从新开始新循环
      m_numbers->setPositionY(- (m_cur_num % 10) * m_fontHight); //负数表示向下移,标准对齐位置
      update_moveSum = 0; 
    }
  }
}

/*
********************************************************************************************************************************************
********************************************************************************************************************************************
*/

NumberScroller::NumberScroller():
  m_cur_num(0),
  m_length(0),
  m_time(1.0f)
{

}

NumberScroller* NumberScroller::create(int length, int fontWidth, int fontHeight, int fontSpacing){
  NumberScroller* ret = new NumberScroller();
  if (ret && ret->init(length, fontWidth, fontHeight,fontSpacing)){
    ret->autorelease();
    return ret;
  }
  CC_SAFE_DELETE(ret);
  return nullptr;
}

bool NumberScroller::init(int length, int fontWidth, int fontHeight, int fontSpacing){
  if(!Node::init())  return false;
  m_length = length;
  m_fontWidth = fontWidth;
  m_fontHeight = fontHeight;
  m_fontSpacing = fontSpacing;
  m_visibleNode = Node::create();

  //排好length行数字
  //该demo下为左对齐
  for(int i=0;isetAnchorPoint(Point(0,0));   //锚点设置为0是为了后面设置遮罩层
    column->setPosition(i * (fontWidth + fontSpacing), 0);
    column->setTime(m_time);    //设置默认运动时间1S
    m_visibleNode->addChild(column);
  }
  /*设置遮罩层*/
  ClippingNode* cliper = ClippingNode::create();
  //创建模板
  DrawNode* drawNode = DrawNode::create();
  Point points[] = {
    Point(getPosition()),
    Point(getPositionX(),getPositionY() + m_fontHeight),
    Point(getPositionX() + m_length * m_fontHeight, getPositionY() + m_fontHeight), 
    Point(getPositionX() + m_length * m_fontHeight, getPositionY()) 
  };
  drawNode->drawPolygon(points,4,Color4F(0,0,0,1),0,Color4F(0,0,0,1));
  //设置模板
  cliper->setStencil(drawNode);
  cliper->addChild(m_visibleNode);
  this->addChild(cliper);
  //不添加遮罩层的方法
  //this->addChild(m_visibleNode);
}

void NumberScroller::setNumber(int number){
  if(number > m_cur_num){
    m_cur_num = number;

    for(int i=0;isetNumber(number);
      number /= 10;
    }    
  }
}

int NumberScroller::getNumber(){
  return m_cur_num;
}

//对外开放设置时间的接口
void NumberScroller::setTime(float time){
  m_time = time;
  for(int i=0;isetTime(time);
  }  
}

使用方法

auto numberScroller = NumberScroller::create(1,15,33,10);//这个字体宽度根据fnt 文件表的相关参数计算
  numberScroller->setPosition(Director::getInstance()->getVisibleSize().width / 2, Director::getInstance()->getVisibleSize().height / 2);

  this->addChild(numberScroller);
  scheduleUpdate();
  Director::getInstance()->getScheduler()->schedule([=](float){
      CountNum = CountNum + 1;
      numberScroller->setNumber(CountNum);
  }, this, 1.0f, false, "countDown");

实现效果:

cocos2dx-3.10 C++实现滚动数字_第1张图片

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

你可能感兴趣的:(cocos2dx-3.10 C++实现滚动数字)