用Qt实现一个桌面弹幕程序(三)--实现一个弹幕③



  • 不同种类弹幕的实现

    在上一篇文章中,杰洛君带大家实现了从屏幕右方飞行到左方的弹幕。\(^o^)/

    但是弹幕并不止这一种,有很多很多不同的弹幕种类,包括但不限于:

    • 顶部弹幕 -- -- 弹幕悬停于屏幕顶部中央一段时间
    • 底部弹幕 -- -- 弹幕悬停在屏幕底部中央一段时间
    • 逆向弹幕 -- -- 弹幕从屏幕的右方飞行到屏幕左方

    实现起来也是非常简单的~

    继续使用QPropertyAnimation作为弹幕的动画实现方式

    顶部和底部弹幕:

    开始位置和结束位置设置为屏幕中间即可
    设置停留时间
    动画结束时销毁自身

    代码实现:

    QPropertyAnimation * anim2=new QPropertyAnimation(this, "pos");
    anim2->setDuration(7000);
    anim2->setEasingCurve(QEasingCurve::Linear);
    this->setWindowOpacity(this->getTransparency());
            connect(anim2,SIGNAL(finished()),this,SLOT(deleteLater()));
    

    问题又来了,顶部弹幕和底部弹幕的坐标如何确定呢?

    这两种弹幕的显示是位于屏幕中央,所以很自然可以想到 用 屏幕的宽度 - 弹幕的宽度除以2 得到弹幕的横坐标位置。

    但是纵坐标呢?

    纵坐标位置应该和上一个弹幕位置相关,也就是说,纵坐标的位置应该为字体高度的整数倍,这样这两种弹幕的文字才能不重叠。

    所以记得用两个变量来记录顶部弹幕数量和底部弹幕数量哦~

    至于逆向弹幕的话就更简单了,把正向弹幕的起始位置和结束位置互换就可以了~这里就不用代码写出了~

    杰洛君 怒偷一懒233O(∩_∩)O哈哈~

    (p.s. Qt的动画效果有很多,感兴趣的同学可以了解一下 QEasingCurve 类 , 恩恩,就是上面代码中经常出现的 QEasingCurve::Linear 部分,在这里是用了线性,你可以切换不同的类型来体验体验他们的动画效果哦~O(∩_∩)O嗯! )

    来试试动画弹幕吧~

    杰洛君的弹幕是继承QLabel实现的~

    而QLabel是可以播放GIF的哦~

    于是乎,杰洛君 脑洞大开地想到了一个很好玩的东西~

    不如让一个GIF动画飞过屏幕吧~

    好吧,那就决定是你了,上吧!!! 小doge!!!

    doge

    杰洛君创建了一个Doge类

    基本设置和弹幕类似,但是不需要重载 paintEvent函数了~

    Doge类用到了QMovie

    在Doge类中杰洛君添加了一个 QMovie * movie 这个私有变量。

    令他的构造函数看起来是这样子的

    Doge(
    QWidget *parent, 
    QMovie * movie2,
    QRect rect,
    int type = 4,
    double Transparency = 1.00,
    int runTime=15000
    );
    

    初始化后

    调用QLabel的 QLabel::setMovie(QMovie * movie); 函数就可以在Label上显示GIF了~

    所以在这里movie2的创建是在Doge类外部的。

    在构造函数中movie2的值会赋值给私有变量movie,自然在析构函数中要加上delete这个movie指针的代码,不然就内存泄露了。

    QMovie 类用法

    QMovie * movie = new QMovie(":/project/rundoge");
    movie->start(); //启动动画
    movie->setPaused(true); //暂停动画
    movie->stop(); //停止动画

    那上面代码中的":/project/rundoge" 是什么呢?

    这个是Qt中用资源文件进行管理文件时 文件的引用方式

    右键点击项目可以新建资源文件,在里面可以添加项目要用到的资源文件

    比如 杰洛君的项目中

    0_1457010603276_20160217221427169.jpg

    我给这个gif文件 定义了前缀为 /project 别名为 rundoge

    所以访问这个文件就是用 ":/project/rundoge" 进行访问啦~

    还不清楚的话,可以用搜索引擎搜索一下 Qt 资源文件 学习更加详细的用法~

    来试试图片弹幕吧~

    除了GIF 有时一些好玩的图片也是你希望能够放上屏幕让它飞过的,比如一些图片表情(手动滑稽)

    这时就可以用 QPixmap来加载图片了,与上文中的 QMovie类似,QPixmap在构造函数中传入图片资源即可。

    初始化后再用 QLabel中的setPixmap(const QPixmap & )函数即可

    为了让图片显示完全,设置弹幕窗体大小和图片大小一致即可,如果需要缩放 QPixmap 也有提供scaled 函数给你使用。这个函数参数比较多,快快选中它 按下F1 进行学习吧~

    小 D : 感觉从上到下 说明越来越水了。。。(#‵′)凸

    杰洛君 : 冤枉冤枉!重点在下面呢~

    来试试图片弹幕吧~(重点)

    制作一个南小鸟动画~

    相信看过LoveLive的同学都知道一个非常经典的表情

    0_1457010642644_LLleft.png

    它一般从画面的左下角缓慢/快速探出头,停留在左下角一段时间,再缓慢/快速收回去

    这个如何实现呢?

    没错,还是用Qt 的动画类

    只不过这次不同,这里应该有三个动画 探出 停留 收回

    而且这三个动画是顺序执行的,于是这里 杰洛君 就用了

    QSequentialAnimationGroup类

    这个类名中我们看到了Sequential 说明动画组中 动画的执行顺序是线性的,也就是有顺序,和加入组中的顺序有关,只要动画顺序加入这个组就可以了~

            group = new QSequentialAnimationGroup(this);
      
            anim1=new QPropertyAnimation(this, "pos");
            anim1->setDuration(100);
            anim1->setStartValue(QPoint(this->getPosX(),this->getPosY()));
            anim1->setEndValue(QPoint(this->getPosX(),this->getPosY()));
            anim1->setEasingCurve(QEasingCurve::Linear);
      
            anim2=new QPropertyAnimation(this, "pos");
            anim2->setDuration(200);
            anim2->setStartValue(QPoint(this->getPosX(),this->getPosY()));
            anim2->setEndValue(QPoint(0, rect.height()-pic.size().rheight()));
            anim2->setEasingCurve(QEasingCurve::Linear);
      
            anim3=new QPropertyAnimation(this, "pos");
            anim3->setDuration(500);
            anim3->setStartValue(QPoint(0, rect.height()-pic.size().rheight()));
            anim3->setEndValue(QPoint(0, rect.height()-pic.size().rheight()));
            anim3->setEasingCurve(QEasingCurve::Linear);
      
            anim4=new QPropertyAnimation(this, "pos");
            anim4->setDuration(200);
            anim4->setEndValue(QPoint(this->getPosX(),this->getPosY()));
            anim4->setStartValue(QPoint(0, rect.height()-pic.size().rheight()));
            anim4->setEasingCurve(QEasingCurve::Linear);
      
            group->addAnimation(anim1);
            group->addAnimation(anim2);
            group->addAnimation(anim3);
            group->addAnimation(anim4);
    

    上面的代码也是非常耿直的~

    (p.s. 既然有SequentialGroup 自然也会有 QParallelAnimationGroup ,感兴趣的小伙伴可以了解一下哦~)

    后续

    今天带大家实现了各种各样奇葩弹幕呢~

    那么弹幕的介绍大概就到这里,接下来会讲解主窗体的建立和设置。

    看到未来道阻且长,杰洛君不禁一声长叹~(╯3╰) 哎~

    不过我不会就这样轻易地狗带的!加油,记录自己做过的每一个程序~


  • 网站研运

    @杰洛飞 谢谢分享!你的博客让我找到了如何在论坛中播放gif的方法!真是帮助太大了。


  • 网站研运

    @杰洛飞 说:

    QPropertyAnimation

    这个是以前用过的类,我以前还用它来制作角色移动的二维动画呢。
    链接在这里



  • @jcy 嗯嗯,我发现直接发gif是不能播放的,只能用外链的形式~谢谢你给的链接分享啦~


 

最近的回复

关注我们

微博
QQ群











召唤伊斯特瓦尔