jabbany / CommentCoreLibrary

Javascript Live Comment (Danmaku) Engine Implementation. JS弹幕模块核心,提供从基本骨架到高级弹幕的支持。
http://jabbany.github.io/CommentCoreLibrary/demo
MIT License
1.9k stars 304 forks source link

如何解决弹幕量大的情况下弹幕重叠的问题? #77

Closed djmax2010 closed 7 years ago

djmax2010 commented 7 years ago

看了文档似乎没找到相关的设定,在弹幕量大的时候,会出现弹幕重叠的问题,有什么办法可以解决么?

jabbany commented 7 years ago

这个有两种情况,一个是滚动排版问题,一个是弹幕太多没法不重叠。

第一种情况在这里 (#35) 有提到,目前的策略是:在检测两个弹幕是否重叠的时候,如果已有弹幕运行到结尾时的绝对时间比要添加的弹幕的大,则认为两个弹幕会发生重叠。这个不是最高效的办法而且如果新弹幕超过屏幕长度还是会重叠。默认版采用主要是因为和弹幕屏幕大小、弹幕字号无关(方便调试和测试),而且和老版播放器一致所以就一直在沿用。

这个可以通过改 https://github.com/jabbany/CommentCoreLibrary/blob/master/src/core/CommentSpaceAllocator.ts 里面willCollide 函数改变何时“判定撞击”,然后重新编译一下库就好了。引用的issue上有这么个公式。

第二种情况比较没办法,基于目前排版形式,当安排完所有无冲撞轨道之后如果还有弹幕,则会新开一个弹幕池从顶部开始排列新的弹幕,忽视下面那层。新的弹幕会从最低层开始找有空位置的层,找不到会开一层新的。

不过有几个降低重叠的方法(没法根本解决因为弹幕足够多的时候没有很好的排版方式):(1)服务器端可以在输出的时候去掉足够老的弹幕(2)限制同屏可以出现的弹幕

djmax2010 commented 7 years ago

恩,感谢作者,在弹幕多的情况下,原先碰撞的逻辑排版比较单一,导致弹幕有很明显的分割空隙,(一排一排的)所以,我改了碰撞算法,提高了弹幕的密集度,并确保老弹幕在消失前,新弹幕不会碰撞到。关于重叠问题,的确弹幕量非常大导致满屏的情况下,没办法避免。

CommentSpaceAllocator.prototype.willCollide = function (existing, check) {
        if(existing.ttl <= 0){
            return false;
        }
        if(Math.abs(existing.x) + existing.width > Math.abs(check.x)){
            return true;
        }
        var speed = (existing.right) / existing.dur; //计算速度
        var speed2 = (check.right) / check.dur;
        var ttl = existing.x / speed; //计算剩余时间,自带的ttl测试下来并不准
        var ttl2 = check.x / speed2;
        var px1 = -existing.width + speed * ttl;
        var px2 = -check.width + speed2 * ttl2;
        if (px1 + existing.width > px2) {
            return true;
        }else{
            return false;
        }
        // 以下是源码的逻辑
        // return existing.stime + existing.ttl >= check.stime + check.ttl / 2;
    };