cocoscreator实现 跑马灯 / 滚动公告

几乎所有的游戏中 都会有这么一个功能。 来告诉玩家 有啥新鲜事发生了,有啥活动出台了等等 ,这个功能就是跑马灯。也就是 一个 滚动的公告功能

需求

实现一个 滚动的消息 ,从右往左循环展示。

实现思路

  1. 首先要让消息是移动的。肯定需要两个点。起始点和终点,当消息体位置到达终点时。重置消息题的 位置为起点位置,如此循环
  2. 其次消息不能滚动到设定显示的范围外。所以需要一个遮罩 当 消息体某部分 到达终点位置时 隐藏该部分消息。可以用cocoscreator自带的 Mask组件实现

实操

1.界面结构如下图

Mask组件 用于规定子节点可渲染的范围,带有 Mask 组件的节点会使用该节点的约束框,也就是 属性检查器 中 Node 组件的 Size 规定的范围。创建一个渲染遮罩,该节点的所有子节点都会依据这个遮罩进行裁剪,遮罩范围外的将不会渲染。

Mask组件添加:创建一个node,选择添加渲染组件 找到mask组件添加

然后把Label的锚点设置为(0,0.5),最好是将锚点X设置为0,这样的话,Label节点的水平位置会以节点的左边界为基准,最左边的位置 就是 label的当前位置。便于后面的位置计算。或者不改变锚点用 x位置*锚点也可以。

tips:

label建议用富文本 richtext. 因为richtext可以用BBCode(标签格式)让滚动消息突出重点部分 区分内容等

RichText 组件参考链接

2.代码如下

  start () {
       let str = "<color=#00ff00>关注公众号  </c><color=#0fffff>亮亮同学TT</color>   获取更多精彩内容"
       this.noticeLabel.string = str;
       let contentSize = this.noticeLabel.node.getBoundingBox();
       this.startx =  this.mask.width * this.mask.anchorX;
       this.endx =  -this.mask.width * this.mask.anchorX - contentSize.size.width;
       this.noticeLabel.node.x = this.startx;
    }

    setSpeed(speed:number){
        this.speed = speed;
    }

    update (dt) {
        //移动循环展示消息的位置
        if (this.noticeLabel.node.x <= this.endx ) { 
            this.noticeLabel.node.x = this.startx;
        }
        this.noticeLabel.node.x -= this.speed * dt;

    }

2020,10.29更新版本

const {ccclass, property} = cc._decorator;

@ccclass
export default class Notice extends cc.Component {

    /**Mask组件 */
    @property(cc.Node)
    mask:cc.Node = null;
    
    /**公告label*/
    @property(cc.RichText)
    noticeLabel:cc.RichText = null;
    
    /**公告数组
    *notices 公告数组每个元素结构是{content,priority,times} content:string,     priority:number,times:number  文本内容,优先级,重复次数
    */
    
    private notices:object[] = [];

    private speed:number = 100;

    private index:number = 0;


    onLoad () {}

    start () {
       
    }
    
    init(){
        this.noticeLabel.string = "";
        this.index = 0;
    }

     /**更新广播 */
    pushOne(content:string,priority:number,times:number){
        let notice = {content,priority,times}
        if(this.notices.length > 100){
            this.clearAll();
        }
        this.notices.push(notice)
        this.notices.sort((a,b)=>b["priority"]-a["priority"])
        this.index = 0;

    }

    nextOne(){
       if(this.notices.length == 0){
           return ;
       }

       this.noticeLabel.node.x = this.mask.width / 2
       if(this.index >= this.notices.length ){
        this.index = 0;
       }

       this.noticeLabel.string = this.notices[this.index]["content"] ;
       this.index++;
     
    }



    clearAll(){
        this.index = 0;
        this.notices = [];
    }


    update (dt) {
        
        this.noticeLabel.node.x -= this.speed * dt;
        if (this.noticeLabel.node.x <=  -this.mask.width / 2 - this.noticeLabel.node.getBoundingBox().size.width  ) { 
            this.nextOne();
        }
    }
}

另外

代码中除了在update中实现 消息的移动 外还可以用cocoscreator缓动系统 cc.tween去实现。

关注微信公众号 亮亮同学TT 发送 跑马灯 获取完整代码工程及资源

关注微信公众号:亮亮同学TT 获取更多技术知识

6赞

再深入写点。服务器一次性发过来n条数据的话, 做个队列,一条一条显示。

嗯嗯 ,再进行一次改进

这是我自己写的= =

:grinning:

mark一下.

巧了,我也有一个~

https://gitee.com/ifaswind/eazax-ccc/blob/master/components/Marquee.ts

1赞

皮皮 这个比较全 哈哈

巧了,我也有一个

测试可用,只是3.x中的处理节点坐标和获取label width api发生了变化,调整之后效果可以的。
this.node.x => this.node.position.x
this.mask.width =>this.noticeMask.getComponent(UITransform).width

嗯嗯,是的呢。

大佬威武。

不错,愿意出教程的都是好样的