浙江省建设厅继续教育网站,网站制作能赚多少钱,erp系统怎么自学,新建网站的价格前言在上篇文章中#xff0c;我们提到了如何使用 .NET连接斗鱼TV直播弹幕的基本操作。然而想要做得好#xff0c;做得容易扩展#xff0c;就需要做进一步的代码整理。本文将涉及以下内容#xff1a;介绍如何使用 ReactiveExtensions#xff08; Rx#xff09;#xff0c… 前言在上篇文章中我们提到了如何使用 .NET连接斗鱼TV直播弹幕的基本操作。然而想要做得好做得容易扩展就需要做进一步的代码整理。本文将涉及以下内容介绍如何使用 ReactiveExtensions Rx演示这一系列操作用起来就像写 HelloWorld一样简单用我自制的“准游戏引擎” FlysEngine只需少量代码即可实现桌面弹幕的效果最后提供一波“伸手党”福利文中所有可运行、完整代码将按原样奉上。Rx.NETRx是 ReactiveExtensions的缩写据说 Rx发明于 .NET2.0时代的微软。那时候还没有 async/await。后来也许由于 RX对编程语言要求不高如不要求内置 协程- coroutine RX反倒在 .NET之外的其它编程语言中大行其道。如 rx.js、 RxJava等等。C#从 .NET2.0就提供了 yield关键字然后 3.0提供了 LINQ 5.0提供了 async/await因此很多时候 RX的意义不大。但在某些情况下如这种情况就有意义了原因请见下图-单数据多数据同步TIEnumerableT异步TaskTObservableT/ IAsyncEnumerableTC#的 协程支持同步多数据异步单数据但不支持同步多数据 C# 8.0现在已经支持 IAsyncEnumerableT本文将使用 Rx来包装上一篇文章的斗鱼TV直播弹幕客户端。来先看一波老代码注意剪头所指的位置那是基础代码“出口”或者业务逻辑“入口”基础代码不能简单地 return打断因为它要不停地输出数据这时就需要像 协程等编程语言功能或者 Rx的支持。Rx-Hello World首先引入 NuGet包 System.Reactive一个简单的“异步多值返回”的 Rx示例代码如下Observable.Createint(async (o, cancellationToken)
{ for (var i 0; i 5; i) { await Task.Delay(1000); o.OnNext(i); } o.OnCompleted();
})麻雀虽小五脏俱全如代码所示几乎只需在正常代码外包一层 Rx即可享受 Rx的好处。使用 Rx使用起来就更简单了上篇展示的长达 252行代码的 demo现在只需一行代码即可无侵入式地调用DouyuBarrage.ChatMessageFromUrl(https://www.douyu.com/scboy)调用结果如下和昨天效果完全一样Rx的其它好处除了调用简单之外 Rx的扩展也非常非常简单比如完成以下操作以前可能非常麻烦需要改多处代码而使用 Rx只需像 LINQ一样加几个指令即可同时抓多个直播间的弹幕#load .\barrage.linq
DouyuBarrage.ChatMessageFromUrl(https://www.douyu.com/scboy) .Select(x new { Room scboy, Message x.Message })
.Merge(DouyuBarrage.ChatMessageFromUrl(https://www.douyu.com/topic/lscs?rid633019) .Select(x new { Room lalala, Message x.Message}))效果如下只需一个 Merge指令即可合并两个直播间的弹幕 ObservableT扩展简单比如只想提取特殊的弹幕或者数据之前想做一些转换可以使用 Where Select等数据过滤和转换操作符符合 LINQ的习惯非常好用。比如我正常弹幕的提取其实是从 JObjectFromUrl转换而来 JObjectFromUrl又是从 RawFromUrl转换而来这提高了扩展性又无需修改老代码正是所谓“对扩展开放对修改封闭”的开放-封闭原则public IObservableJToken JObjectFromUrl(string url) RawFromUrl(url).Select(MsgTool.DecodeStringToJObject);
public IObservableBarrage ChatMessageFromUrl(string url) JObjectFromUrl(url) .Where(x x[type].Valuestring() chatmsg) .Select(Barrage.FromJToken);又比如可能我只想提取彩色弹幕我只需 ChatMessageFromUrl().Where(xx.Color!0xffffff)即可非常方便。桌面弹幕这可能是另一个主题——实时渲染用到了我自己写的“准游戏引擎” FlysEngine因此需要安装 NuGet包FlysEngine.Desktop。桌面弹幕不同于 网页弹幕只能在网页中显示而 桌面弹幕可以直接显示在屏幕最上方。有些公司年会可能用到了 桌面弹幕这无疑增加了主持人与观众们的互动提高了群众参与的积极性。注意本文中所说 FlysEngine的实质是 Direct2D和 WindowsAPI- UpdateLayeredWindowIndirect函数。如果不想使用 FlysEngine完全可以使用其它方式代替。最简单的方式是使用 WPF然后设置 AllowsTransparencytrue但这样性能会差一些。本文介绍的方法 CPU使用率将保持在 0%左右桌面弹幕的要点渲染文字 DirectWrite文字移动 将文字从屏幕右边移动到左边检测是否离开屏幕 如果屏幕上不显示弹幕即可将弹幕删除初始位置确定 如果一行显示不下则将弹幕放在下一行。渲染文字渲染文字一般是通过 DirectWrite它性能很好功能也强大。FlysEngine将 DirectWrite封装了因此直接用便是。注意DirectWrite不仅渲染文字还提供了 .Metrics属性可以计算文字渲染之后的大小这会让事情变得容易很多。文字移动文字移动首先需要一个位置随着时间变化将该位置的 X坐标不段减少即可。这可以通过 FlysEngine中的 UpdateLogic事件实现它会定期调用传入一个 floatdt代码离上一次调用 UpdateLogic的时间间隔。因此可以利用这个 dt变量计算是弹幕的新位置public void MoveLeft(float dt, float speed)
{ Position.X - dt * speed;
}检测是否离开屏幕由于我们已知弹幕是矩形很显然屏幕也是矩形因此这个检测比较简单直接判断文字的 右边缘是否 大于0即可。也由于需要经常/频繁地删除在屏幕上的弹幕对象因此最好储存弹幕的数据结构别使用 O(n)的集合如最好别使用 ListT它是线性表。我这里使用的是 链表 .NET的链表实现是 LinkedListT很多人以为是 ListT。多说一句链接的遍历算法如下 while循环var node barrages.First;
while (node ! null)
{ var next node.Next; // do work here node next;
}之所以不使用 foreach来遍历因为这样遍历可以实现高性能的“边遍历、边删除”的实现。初始位置确定这一点思想需要多想想需要从第一行开始从后往前看看最后那一边弹幕是否大于屏幕右边。只要想清楚了代码很容易float GetNewY()
{ float y 0; while (barrages.Reverse().Where(x x.Position.Y y).Select(x x.Rect.Right).FirstOrDefault() form.Width) { y FontSize; } return y;
}有了这些就可以愉快地感受屏幕弹幕啦彩色 emoji表情Direct2D支持——但默认不显示弹幕 emoji表情要多加一个枚举让其支持target.DrawText(????????????, res.TextFormats[36], rectangle, res.GetColor(Color.Blue), Direct2D.DrawTextOptions.EnableColorFont); // 重点支持彩色 emoji表情后效果如下结最终效果昨天已经见过了如下本文包括上文所用的代码如下id链接老式代码https://github.com/sdcb/blog-data/blob/master/2019/20191013-douyu-barrage-with-dotnet-2/barrage_tranditional.linq新式代码https://github.com/sdcb/blog-data/blob/master/2019/20191013-douyu-barrage-with-dotnet-2/barrage.linq合并弹幕https://github.com/sdcb/blog-data/blob/master/2019/20191013-douyu-barrage-with-dotnet-2/barrage-combine.linq桌面弹幕https://github.com/sdcb/blog-data/blob/master/2019/20191013-douyu-barrage-with-dotnet-2/desktop-barrage.linq喜欢的朋友请“刷一波666???”并关注我的微信公众号【DotNet骚操作】