iOS ZHBarrage - 游戏弹幕 CABasicAnimation动画、不卡扽弹幕动画

说明

1.大多数弹幕都采用时间来控制弹幕,能够很好的适配在播放器、或者是一些对除了弹幕动画外,其他动画很少的项目中运行。而当除了弹幕动画以外,还存在更多动画时,就会导致动画冲突,而使弹幕停留不前,内存消耗巨大。故结合实际,简单写下此弹幕

2.此动画采用CABasicAnimation动画,与大多数动画不同采用时间来控制弹幕的走向有所不同。但是目前无法控制弹幕的停留,实际我所接触的项目也没有这个需求。

3.存在问题点,或者说是可优化点在于创建时默认初始化多个弹幕通道,但可能程序运行中,有些通道并不能得到有效的利用,如何在利用到的时候在进行初始化,有时间我在提交一个版本。

弹幕展示

z9lb4-pte81.gif

处理弹幕消息

1.我的思路是在处理接受到弹幕到时候,从上往下依次判断所创建的通道是否畅通,若找到畅通的通道时,进行数据渲染,开始动画。当所创建的通道全部被占用时,默认将消息保存在内存中,并按时间0.2秒循环查找是否有畅通通道。当内存中没有未处理的消息时,将定时器释放,代码如下

- (void)sendMessage:(NSMutableAttributedString *)attributedString
     withSpseed:(int)spseed
      withImage:(NSString *)imagePath
     withInsets:(UIEdgeInsets)insets {
if (!_isaccording) {
    if (!_cacheInfoArr) {
        _cacheInfoArr = [[NSMutableArray alloc] init];
    }
    ZHModel *model = [[ZHModel alloc] init];
    model.attributedString = attributedString;
    model.imagePath = imagePath;
    model.spseed = spseed;
    model.textInsets = insets;
    [_cacheInfoArr addObject:model];
    return;
}
if (_cacheInfoArr && _cacheInfoArr.count > 0) {
    //别急,先处理当前缓存信息
    ZHModel *model = [[ZHModel alloc]init];
    model.attributedString = attributedString;
    model.spseed = spseed;
    model.imagePath = imagePath;
    model.textInsets = insets;
    [_cacheInfoArr addObject:model];
    return;
}
//是否查找到通道
for (int i = 0; i < _countChannel; i++) {
    ZHLabel *label = [self viewWithTag:ZH_Label_tag + I];
    NSLog(@"curr channel %d unblocked = %d",i,label.unblocked);
    if (label.unblocked == YES) {
        [label updateAttributed:attributedString
                     withSpseed:spseed
                      withImage:imagePath
                     withInsets:insets];
        return;
    }
}
//处理未找到通道时动作
NSLog(@"creat succeed");
if (!_cacheInfoArr) {
    _cacheInfoArr = [[NSMutableArray alloc] init];
}
ZHModel *model = [[ZHModel alloc] init];
model.attributedString = attributedString;
model.imagePath = imagePath;
model.spseed = spseed;
model.textInsets = insets;
[_cacheInfoArr addObject:model];
if (!caCcheTime) {
    caCcheTime = [NSTimer scheduledTimerWithTimeInterval:0.2
                                                  target:self
                                                selector:@selector(cacheTimeFunction)
                                                userInfo:nil
                                                 repeats:YES];
}
}
- (void)cacheTimeFunction{
ZHModel *model = [_cacheInfoArr firstObject];
for (int i = 0; i < _countChannel; i++) {
    ZHLabel *label = [self viewWithTag:ZH_Label_tag + I];
    if (label.unblocked == YES) {
        [label updateAttributed:model.attributedString
                     withSpseed:model.spseed
                      withImage:model.imagePath
                     withInsets:model.textInsets];
        [_cacheInfoArr removeObjectAtIndex:0];
        if (_cacheInfoArr.count == 0) {
            //清空集合,停止时间循环
            _cacheInfoArr = nil;
            [self stopCacheTime];
            NSLog(@"clean succeed");
        }
        return;
    }
}
}

2.动画采用CABasicAnimation动画,并监听动画是否完成

- (void)startAnimationandLabel:(ZHLabel *)label{
CGFloat customLabwith = label.frame.size.width;
int time = (ZH_ANIMATION_WIDTH + customLabwith*2 + 10)/self.spseed;
CGFloat left_P = - (customLabwith/2 - 10);
CGPoint center = CGPointMake(ZH_ANIMATION_WIDTH + customLabwith/2 + 5, label.center.y);
CGPoint finishPoint = CGPointMake(left_P, label.center.y);
CABasicAnimation *animationgo = [CABasicAnimation animationWithKeyPath:@"position"];
animationgo.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animationgo.duration = time;
animationgo.repeatCount = 1;
animationgo.delegate = self;
animationgo.removedOnCompletion = NO;
animationgo.beginTime = CACurrentMediaTime();
animationgo.fromValue = [NSValue valueWithCGPoint:center];
animationgo.toValue = [NSValue valueWithCGPoint:finishPoint];
[label.layer addAnimation:animationgo forKey:@"label"];
_label = label;
}
#pragma mark - CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if (anim == [_label.layer animationForKey:@"label"]) {
    [_label.layer removeAnimationForKey:@"label"];
    _label.unblocked = YES;
}
}

介绍

给我们项目打一个广告吧,欢迎去AppStore搜索下载"欢乐狼人杀",有什么想法,或者看法,也可能联系我,欢迎大神点评

wiscq-y36zs.gif

dome:
https://github.com/Zhangyunjiang123/ZHBarrage

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 9,588评论 1 27
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 7,176评论 6 28
  • 姓名:吴龙飞 公司:杭州简品食品股份有限公司 组别:利他一组 【日精进打卡...
    加了冰的咖啡阅读 43评论 0 0
  • 1. 定义 观察者模式也叫发布订阅模式/模型,在项目中常用:定义对象间一种一对多的依赖关系,使得每当一个对象改变状...
    小楠总阅读 386评论 0 1
  • 最近因为崔永元老师,冰冰又大火了可是这次火却是法律不允许的;因为是偷税漏税的大小合同。 1 最近手机2又开始开拍了...
    超越凡尘118阅读 772评论 4 15
  • 2017年11月9日 星期四 晴天 今天下午,我们几个人没放学,因为晚上家长要过来打扫卫生。男的只有我、宫...
    鑫隆妈妈阅读 101评论 0 0