数字滚动由两个类实现,数字类UINumber和数字滚动类UIRollNum,都是继承的CCSprite,都是精灵。数字类实现单个数字的上下滚动,数字滚动类实现了界面分数数字的位置设置,分数变化时把分数拆解成单个数字,然后调用数字类赋值,由数字类判断滚动方向,并连续改变精灵帧坐标,实现数字滚动效果。

数字类详解

数字类成员变量:

NumStyle m_style;       //滚动样式
    int m_num;                   //显示的数字
    int m_nPosCur;          //当前的位置
    int m_nPosEnd;          //结束的位置
    int m_nMoveLen;         //每次移动的位置
    CCTexture2D *m_texture; //数字的texture

数字类的实现方法:

-(id) initWithStyle:(NumStyle) style;//按照格式初始化
-(void) setNumber:(int) num;//设置分数数字,为一位数字
-(void) onRollDown:(ccTime) dt;//数字向上帧向下滚动
-(void) onRollUP:(ccTime) dt;//数字向下帧向上滚动
-(void) setup;//获取数字图片生成精灵帧

数字类初始化首先设置数字成员都为0,贴图为NULL,然后-(void) setup获取贴图,过程如下:

UIImage *image = [UIImage imageNamed:@"number.png"];
//    用UIImage加载图像的方法很多,最常用的是下面两种:
//    1、用imageNamed函数
//    [UIImage imageNamed:ImageName];
//    2、用imageWithContentFile的方式加载,例如:
//    1. NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:extension];
//    2. UIImage *image = [UIImage imageWithContentOfFile:filePath]; 
//    由于第一种方式要写的代码比较少,可能比较多人利用imageNamed的方式加载图像。其实这两种加载方式都有各自的特点。   
//    1)用imageNamed的方式加载时,系统会把图像Cache到内存。如果图像比较大,或者图像比较多,用这种方式会消耗很大的内存,而且释放图像的内存是一件相对来说比较麻烦的事情。例如:如果利用imageNamed的方式加载图像到一个动态数组NSMutableArray,然后将将数组赋予一个UIView的对象的animationImages进行逐帧动画,那么这将会很有可能造成内存泄露。并且释放图像所占据的内存也不会那么简单。但是利用imageNamed加载图像也有自己的优势。对于同一个图像系统只会把它Cache到内存一次,这对于图像的重复利用是非常有优势的。例如:你需要在一个TableView里重复加载同样一个图标,那么用imageNamed加载图像,系统会把那个图标Cache到内存,在Table里每次利用那个图像的时候,只会把图片指针指向同一块内存。这种情况使用imageNamed加载图像就会变得非常有效。  
//    2)利用NSData方式加载时,图像会被系统以数据方式加载到程序。当你不需要重用该图像,或者你需要将图像以数据方式存储到数据库,又或者你要通过网络下载一个很大的图像时,请尽量使用imageWithData的方式加载图像。无论用哪种方式加载图像,图像使用结束后,一定要记得显示释放内存。
//    + (UIImage *)imageNamed:(NSString *)name导致的内存问题
//    这种方法在application bundle的顶层文件夹寻找名字的图象 , 如果找到图片, 系统缓存图象。图片内容被加载到系统内存中,使用时直接引用到系统内存。
//    所以当图片比较大时,程序使用的内存会迅速上升导致内存警告并退出。  
//    特别在使用Interface Builder建立界面时,如果直接拖动UIImageView 并设置image的图片名称。InterfaceBuilder 正是通过UIImage 类的imageName方法加载图片。图片被缓存,导致内存使用较大。且无法释放,即使release掉 UIImageView也无济于事。
    m_texture = [[CCTexture2D alloc]initWithImage:image]; //CCTexture2D表示精灵包含的图片,范围是整张图片
    CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:m_texture rect:CGRectMake(0, 0, NUM_WIDTH, NUM_HEIGHT)];
//    CCSPriteFrame是帧,它是组成动画的一部 分,CCSPriteFrame的成员变量中有一个Texture,用帧创建精灵,其实就是用帧的Texture创建精灵,当精灵切换帧 时,Texture也会随之更换,精灵就会呈现不同的形态,以次达到动画的效果。这里大家可以理解为,Texture和Frame都可以构成一个精灵对象。

  然后用setNumber 设置显示的数字

m_nPosCur = NUM_HEIGHT * m_num;//当前显示单个数字的位置为数值乘以高度
    m_nPosEnd = NUM_HEIGHT * num;//需要更换的单个数字的位置为数值乘以高度
    if (NumStyleNormal == m_style) {//根据格式判断移动速度。
        m_nMoveLen = 4;//数字图片精灵每次移动距离,数值越大移动速度越快。
    }

if (m_num > num) {//如果当前数字大于更换数字就向上滚动,例如当前数字5,更换为数字1,按图片的滚动方向为向下滚动,那怎么理解呢?图片向下滚动是通过帧向上移动实现的。
        [self schedule:@selector(onRollUP:) interval:0.03];  //每0.03秒执行一次onRollUP方法
//        Schedule是cocos2d中的一个很重要的机制,它的功能和CCAction有相似的地方,都是执行一种行为;不同之处在于,schedule是通过调用方法来执行逻辑的,而且他它内部还有个计时器,可以每隔一定的时间调用一次,反复循环,直到手动将其停止或者节点被删除(暂停)。这里的参数selector就是执行的方法,interval是间隔时间(秒),
//        cocos2d中的schedule有两种作用
//        1)定时执行方法,例如每隔3秒钟执行一次方法fire
//        看例子:
//        - (id) init{
//            if((self = [super init])){
//                [game addChild:self]
//                [self schedule:@selector(fire) interval:3];
//            }
//            return self;
//        }
//        - (void) fire{
//            NSLog(@"fire");
//        }    
//        2)延时执行方法,例如5秒种后执行方法destory
//        看例子:
//        - (id) init{
//            if((self = [super init])){
//                [game addChild:self]
//                [self schedule:@selector(destory) interval:5];
//            } 
//            return self; 
//        } 
//        - (void) destory{ 
//            NSLog(@"destory"); 
//            [self unschedule:@selector(destory)];//解除调度 
//            [self.parent removeChild:self cleanup:YES]; 
//        }
    }
    else {
        [self schedule:@selector(onRollDown:) interval:0.03];//每0.03秒执行一次onRollDown方法
//        @selector是什么
//        一种类型 SEL
//        代表你要发送的消息(方法), 跟字符串有点像, 也可以互转.
//        是能让Objective-C动态调用方法的玩意.      
//        可以理解为类似函数指针的东西     
//        其实就是消息响应函数
//        选一个消息响应的函数地址给你的action 
//        @selector(function_name) 即取得一个function的id
//        函数指针 本质上讲, 是 object-c 的动态后绑定技术 可以通过字符串 访问的函数指针
//        @selector(xxxx)的作用是找到名字为xxxx的方法。
//        一般用于[a performSelector:@selector(b)];就是说去调用a对象的b方法,和[a b];的意思一样,但是这样更加动态一些。
//        返回的类型是SEL,看方法说明的时候如果参数类型是SEL,那么就是要接受@selector(xxxx)返回的值的那种了。
//        可以理解 @selector()就是取类方法的编号,他的行为基本可以等同C语言的中函数指针,只不过C语言中,可以把函数名直接赋给一个函数指针,而Object-C的类不能直接应用函数指针,这样只能做一个@selector语法来取.

onRollDown 帧向下滚动图片向上滚动
    m_nPosCur += m_nMoveLen;//当前y坐标加每次移动长度
    if (m_nPosCur >= m_nPosEnd) {//如果移动到新位置就结束
        m_nPosCur = m_nPosEnd;//更改当前位置为新位置
        [self unschedule:@selector(onRollDown:)];//解除选择器方法
    CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:m_texture rect:CGRectMake(0, m_nPosCur, NUM_WIDTH, NUM_HEIGHT)];//使帧坐标下移则图片上移
//    精灵在创建之后,它的contentSize便不会再发生变化。CCAnimate的实现通过setDisplayFrame来实现,setDisplayFrame通过setTexture来实现的, 仅仅是添加了修改rect的相应操作。所以,通过CCAnimate和setDisplayFrame可以修改精灵的contentSize,通过setTexture不能修改对应的contentSize
}
onRollUP 帧向上滚动图片向下滚动

    m_nPosCur -= m_nMoveLen;//当前y坐标减每次移动长度
    if (m_nPosCur <= m_nPosEnd) {//如果移动到新位置就结束
        m_nPosCur = m_nPosEnd;//更改当前位置为新位置
        [self unschedule:@selector(onRollUP:)];
    CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:m_texture rect:CGRectMake(0, m_nPosCur, NUM_WIDTH, NUM_HEIGHT)];

数字滚动类主要实现数字在界面的位置布局,及改变总分数的数值。

成员变量:

int m_nNumber;              //显示的数字
    int m_maxCol;               //最大显示位数
//    NSMutableArray可变对象数组
//    [NSMutableArray arrayWithCapacity:6] :初始化可变数组对象的长度,如果后面代码继续添加数组超过长度6以后NSMutableArray的长度会自动扩充,6是自己可以设置的颗粒度。
//    [array addObject:...] : 向可变数组尾部添加数据对象。
//    [array addObjectsFromArray:..] :向可变数组尾部添加一个数组对象。
//    NSArray 不可变数组
//    [array count] : 数组的长度。
//    [array objectAtIndex 0]: 传入数组脚标的id 得到数据对象。
//    [arrayWithObjects; ...] :向数组对象初始化赋值。这里可以写任意对象的指针,结尾必须使用nil。
    NSMutableArray *numArray;   //存放每个数字的数组
    CGPoint m_point;            //坐标
    bool  zeroFill;             //是否开启0填充
    NumStyle style;             //滚动样式

实现方法如下:

-(void) rebuildEffect;//更新分数数字
-(void) clearEffect;//初始化分数数字,全部为0
-(int) getNumber;//获得当前显示分数数字
-(void) setNumber:(int)num;//设置新分数数字

rebuildEffect 重新设置每位数字

//    while语句的原型是while(表达式)语句,当表达式为非0值时,执行while语句中的嵌套语句。       
//    那么while(1)其中1代表一个常量表达式,他永远不会等于0。所以,循环会一直执行下去。除非你设置break等类似的跳出循环语句循环才会中止
    while (1) {
        if (num<=0) {//如果现实的数字是0
            if(m_maxCol<=i && zeroFill)//判断是否是最后数字,如果是就退出while()循环
            break;
        }
        int showNum = num%10;//num%10则取出当前十进制位数的值,如9987,则获取的数字为7.
        UINumber* pNumber = [numArray objectAtIndex:i];
        [pNumber setNumber:showNum];//设置数字产生滚动
        i++;
        num = num/10;//当前数字除以10,把已经设置完毕的数字去掉,继续循环设置下一位数字。

clearEffect初始化每位数字

[self removeChild:pNumber cleanup:YES];//如果有精灵,就循环全部删除

[numArray removeAllObjects];//把精灵数组清空

for (int i=0; i< m_maxCol; i++) {//生成6个图片精灵
        UINumber* pNumber = [[UINumber alloc]initWithStyle:style];
        [numArray addObject:pNumber];
        [pNumber setNumber:0];
        [pNumber setPosition:CGPointMake(m_point.x-i*NUM_WIDTH, m_point.y)];//依次向左边显示
        [pNumber setAnchorPoint:CGPointMake(1, 0.5)];//图片setPosition时的点在图片上所处的位置.取值范围0-1,0,0表示左下角,1,1表示右上角,0.5,0.5表示中心点.
        [self addChild:pNumber z:100];//z:是指添加的ZOrder值,ZOrder是指该成员的层级(也可以说深度),z值大的成员在z值小的成员的上面;

}

cocos2D捕鱼达人源代码初学者详解4数字滚动相关推荐

  1. cocos2D捕鱼达人源代码初学者详解3AppDelegate

    AppDelegate.m 代码------------------------------------------------------------------------------------ ...

  2. 详解央行数字货币和数字票据交易平台架构(多图)

    独家披露:详解央行数字货币和数字票据交易平台架构(多图) 暴走时评:央行推动的基于区块链的数字票据交易平台已测试成功,由央行发行的法定数字货币已在该平台试运行.作为一种创新的货币和全新的支付体系架构, ...

  3. python3 绝对值_Python3 abs() 函数详解 获取数字的绝对值

    Python3 abs() 函数详解 获取数字的绝对值 abs函数是Python的内置函数,在python文件中直接可以使用. 它的主要用途是获取数字的绝对值. 语法 abs(n) 参数 n - 数值 ...

  4. css鼠标拖拉卡顿_详解overflow-scrolling解决滚动卡顿问题

    前言 如果你对某个div或模块使用了overflow: scroll属性,在iOS系统的手机上浏览时,则会出现明显的卡顿现象.但是在android系统的手机上则不会出现该问题. 解决方法 以下代码可解 ...

  5. pyquery获取不到网页完整源代码_PyQuery 详解

    在之前写的爬虫入门里,PyQuery一笔带过,这次详细地讲一下. 为什么选择PyQuery? Python爬虫解析库,主流的有 PyQuery Beautifulsoup Scrapy Selecto ...

  6. java语音播报源代码_详解Android 语音播报实现方案(无SDK)

    本文介绍了详解Android 语音播报实现方案(无SDK),分享给大家,具体如下: 功能描述 类似支付宝收款时候的语音播报功能:当别人扫描你的收款码,你收到钱之后,就会听到"支付宝到账12. ...

  7. android源代码目录详解

    Android 2.1 |-- Makefile |-- bionic                        (bionic C库) |-- bootable                ( ...

  8. 博客网站源代码_详解SEO布词以及网站排名优化技巧

    首先,谈谈新手以及老手在认知上容易出现的SEO误区,我认为有以下几点因素,不容忽视. 1.SEO优化就是为了排名.就是发外链 不少人认为做SEO就是为了排名,完全不考虑网站文章的质量.可读性以及用户体 ...

  9. 跨平台异步IO库 libuv 源代码接口详解

    Table of Contents 简介 谁这本书是为 背景 代码 libuv的基础知识 事件循环 helloworld 默认循环 错误处理 把手和要求 空转 存储方面 文件系统 读/写文件 文件系统 ...

最新文章

  1. 通俗易懂讲解梯度下降法!
  2. 「AI不惑境」学习率和batchsize如何影响模型的性能?
  3. 自定义状态栏notification布局
  4. android 炫酷背景,炫酷-背景图垂直循环滚动登录页,Android RecyclerView实现
  5. android xml组建圆角背景设置
  6. 移动硬盘函数不正确要如何寻回资料
  7. SQL Server:统计数据库中每张表的大小
  8. 根据业务单生成时将描扫记录触发到临时表(SQL触发)
  9. Blue Prism如何成为RPA领域魔力象限领袖
  10. Power BI(十九)power pivot之常用筛选器函数
  11. 如何下载macOS Ventura、Monterey、Big Sur、Catalina Mojave完整安装程序
  12. 采云端采云链:从订单协同到采购供应链,让采购供应链互联互通
  13. 计算机中h是几进制,16进制后面用H表示,其他进制的用什么表示
  14. [POI2008]KUP
  15. 从人工智能角度考虑生命的本质和意义
  16. 网页实现从数据库读取数据并简单分页
  17. matlab中portcons,Matlab在马柯维茨均值-方差模型的简单应用.ppt
  18. 设计模式 之 中介者
  19. 计算机二级c++考试
  20. antd table合并行或者列(动态添加合并行、列)

热门文章

  1. Zabbix与ELK整合实现对安全日志数据的实时监控告警
  2. 迟到的情人节祝福 Sierpinski Valentine
  3. 【近日状况】7月1日-7月7日
  4. iMobile for ReactNative入门使用介绍
  5. java设计博客_JAVA课程设计——团队博客
  6. 计算机不能取代老师的英语作文,电脑是否会取代老师
  7. fastjson android 版本,Fastjson Android版本
  8. Fastjson AutoType
  9. Docker世界 -- 基础篇(入门)
  10. 李嘉诚留住人才的秘诀