最近很火的那个电视剧里李峋的爱心代码怎么弄啊?

您所在的位置:网站首页 爱心代码编程R语言 最近很火的那个电视剧里李峋的爱心代码怎么弄啊?

最近很火的那个电视剧里李峋的爱心代码怎么弄啊?

2023-03-17 19:51| 来源: 网络整理| 查看: 265

UPD.20221122

终于在宿舍放大假啦(大雾),稍微调整了一下编译过程。

总之在换了一下编译器版本之后,VirScan的报毒率直线下降(至少WD不会拦着我了)

然后顺便的话,修订了一下PE和pdf互相嵌入的这么个格式问题()

嘛嘛嘛,虽然说把整个PDF都放DOS stub里面也(应该)问题不大,但是我们试着只在stub里面放一小段pdf头,把接下来的大段数据标记成PDF内嵌的二进制流;然后再在后面加上一个section放PDF的正文…

至于DOS Header…我就直接在默认的dos header基础上做了一点修改…不过编译这玩意需要nasm,有兴趣的话也可以看一看(?)

heartbeat_all.pdf99.4K · 百度网盘

周中听室友给对象打电话一直在说这个玩意——于是趁着周末火速写一个。

啊,当然如果用贴图的话,问题就变得平凡了:所以我们试图搞一个不依赖贴图,而且尽量减少第三方依赖的版本。(其实就是在看GL相关的玩意,迫不及待想写点小玩具)

首先的话,先确定我们要用到的心形形状:

这里的话我用了一个比较简单的形式,即下面公式表示的形状的边界:

(|x|-0.5)^3 + (|x|-0.5)-0.625\leqslant y

然后呢,我们试图引入“跳动”这个特效:就是单纯地对图片进行缩放。

总之我们构造了一个“在0.03秒内从1收缩到0.5;在0.03-0.13秒舒张到1.3,再用0.87秒徐徐回到1。”的函数来表示心跳(毫无疑问,这也是口胡的。)

那么我们把输入的坐标的名称改成vPos_nobeat,再通过这样的式子计算vPos:

vPos = vPos_nobeat * 1.3 / heartbeat(timestamp);有一说一,是不是直接正弦比较好啊。一抽一抽地跳的话,总有一种要打高塔之心之类的boss的感觉

最后我们直接把LearnOpenGL的Shader那段的教程代码套上去,改一下顶点让它渲染一个全窗口的四边形,就得到了一个能运行的程序。

除此之外,在找资料的过程中我还试着写了另一种玩意(就是附近一堆散点在闪的那种)…

啊,这玩意我做了一个特别简单的实现,不过效果不怎么好看就是了(大雾)。先把屏幕划分成非常非常小的点,然后检查点到它所在的区间中心的距离…给这些点生成(看起来)随机的id,再按照这个距离决定抽点的密度。

感觉调一调密度分布可能能好一点…但是直觉上感觉会很麻烦,就不管了!

(发出了根本调不出来好看玩意的声音)

总之我们有了两组预设的玩意,所以就引入一个uniform来控制用哪种,然后在glfw的消息处理里,见到tab键就切换一下。

同理,我们也可以处理F12(或者随便什么快捷键),让我们的程序变成透明背景的:在C++程序里的glClear当然要改,glfw也可以通过GLFW_DECORATED和GLFW_FLOATING把窗口设置成“前端显示、不要标题栏”…而我们在GLSL里面也可以根据算出来的颜色强度来给opacity通道赋值。

啊——既然去掉标题栏和背景色,那很显然我们是希望能够让它挂在那里不影响我们正常工作的。

那么我们可以通过SetWindowLong给窗口设置上WS_EX_LAYERED | WS_EX_TRANSPARENT属性,从而阻止窗口阻挡鼠标;通过SetWindowDisplayAffinity设置WDA_MONITOR,让窗口不在腾讯会议之类的屏幕捕获中出现;还可以把窗口的owner设置成GetDesktopWindow(),从而让窗口不在任务栏上显示。

(当然,因此关不掉窗口只能taskkill不关我的事,毕竟注册热键还要考虑热键冲突什么的。)

当然当然,只是这样的话根本根本就不好玩(大声)

所以我们继续口胡,用上midifile和rtmidi这两个库给程序加上点背景音。

首先我们先找一个mid音频,把它转换一下嵌入到我们的代码里。(比如hxtools里面的bin2c工具)

啊,然后我们可以围绕着生成的这个数组包装成一个istringstream,就可以喂给MidiFile库了。

std::string str(reinterpret_cast(&bin2c_some_music_mid[0]), sizeof(bin2c_some_music_mid)); std::istringstream iss(str, std::ios::binary); smf::MidiFile midifile; midifile.readSmf(iss); midifile.doTimeAnalysis();

我们进行如下的声明用来存midi消息

std::vector messages;

用double来存MidiFile库换算过的时间,而vector则是MidiFile库给出的midi消息,然后做一下排序。

(当然其实我们可以直接用MidiFile对象joinTracks()之后拿来用…但是反正转储到vector时可以顺便把Meta消息丢掉嘛!)

总之总之我们得到了这么一个vector,之后我们试图(利用RtMidi库)打开一个midi的输出接口

RtMidiOut midiout; if (0 == midiout.getPortCount())return; midiout.openPort(0);

然后剩下的事情就是轮询检查有没有需要输出的消息了:

while (1) { unsigned long long begin_time = GetTickCount64(); size_t pos = 0; while (pos = messages[pos].first) { midiout.sendMessage(messages[pos].second.data(), messages[pos].second.size()); pos++; } else { if (messages[pos].first - note_ts > 20)Sleep(messages[pos].first - note_ts - 3); } } } timeEndPeriod(1);

最后我们把这一堆“播放音频”的玩意封在一个线程里面,在程序启动时运行…

啊好了,我们现在得到了一个看起来能用的“带着BGM显示心形”的代码了;

虽然用的第三方库看起来还有些跨平台支持,但是不幸的是,我们的代码本身不怎么跨平台——先不说SetWindowLong这一类东西,我们播放midi时用的GetTickCount当然可以换成clock(),但是Windows下clock的实现是和posix不怎么一致的(指几十天后溢出时并不回卷,而是返回固定的-1)

而且怎么说呢…诚然我们可以去掉那些平台相关的代码,再分情况决定用什么计时函数,但是……不会吧不会吧不会有人做这玩意还要考虑跨平台吧

另一个问题就是,这玩意实在是太大了,静态链接第三方库,动态CRT的情况下,它大概有500多K的大小。

上面说的全都当成“为了方便展示”……总之在进行下一步之前,我们先默认这样一个事实:通过用各种各样不怎么跨平台而且功能性可能没那么强的实现,替代掉glfw,glew,rtmidi这些第三方库,以及一些比较无聊的优化参数或者技巧,我们得到了一个相对小一点的可执行文件。(啊,midifile我没敢动,毕竟自己改的玩意万一换了个midi就不好使了,那也太尴尬了)

然后下一步,我们拿出我们精(随)心(手)准(摘)备(抄)的情书,把它转换成pdf格式。我们试图把它跟我们的程序合成一个polyglot。

嘛嘛嘛,毕竟是脑袋一热想做的玩意,果然折腾了好久才弄好。

总的来说的话,PDF格式是允许在开头出现一小段其它信息的(如果我对标准理解的没问题的话,似乎是不超过512字节?)

那么我们直接把PDF贴在exe后面肯定是不行的了…看起来更合理的做法是在exe靠前的位置开一个section塞进去…

很不幸的是MSVC Linker并没有什么靠谱的稳定的接口让用户实现这个功能…

所以我们稍微搞点事,把PDF作为DOS Stub塞到程序里面去,也就是本来默认应该是输出那个众所周知的“This Program Cannot Be Run in DOS Mode”的那段程序。

link在传进去的时候会检查给的程序是不是一个可执行文件——好在它只检查文件的开头是不是"MZ"。

所以故事就简单了,我们把这个pdf头上加上MZ再作为stub传进去;这样我们这个exe也就同时能被(至少我见到的大多数)PDF Reader识别出来了。

最后的最后,我们再试图把远程仓库的地址(实际上是一个把内容都删掉,只留下pull需要的信息的'.git'目录)、以及一部分关键代码打包附在程序后面——如果我没记错的话,zip和rar应该都允许“不从头开始”(当然,这也是为了方便实现“自解压程序”)

然而很不幸的是…天知道为什么,如果我把zip附在exe后面保存在一个zip文件,7z就是解析不出来;但是如果扩展名不是zip,它就识别的好好的(大雾)感觉就像是把“检测偏移量”这部分代码写在了某种扩展名匹配不上的回退里面的样子…

这个问题是如此的生草,再加上各种奇奇怪怪的原因,以至于我折腾了一个晚上加小半个下午才总算发现是扩展名的问题,室友都开始怀疑我老板开始压榨学生了。(不是,谁能想到把扩展名改成.114514都能正常打开的一个玩意,竟然会因为扩展名跟文件格式匹配而不行啊)

嘛嘛嘛,总而言之我们得到了一个相对不太大的PDF…至少我这边编译出来的结果大概在100K左右。

不过目前的话,exe如果用了奇妙的stub的话似乎报毒率很高…

UPD:大晚上来公司想着调一调代码,结果发现,哪怕我把HelloWorld后缀名改成pdf传到网上再下载下来,它也一样报毒(大雾)

啥玩意啊咋回事啊这可咋整啊

不过总之的话,polyglot当然只是为了自己觉得好玩啊,给别人发的时候还是最好别这么干了(

123.pdf125.9K · 百度网盘

啊,为了避免下载时的WD扫描,我把刚才说的PDF+ZIP+EXE外面又套了一层有密码的zip…如果习惯于从各种资源站下载奇奇怪怪的盗版游戏的话应该能按照提示解压成功…吧…

不过当然,如果图省事的话,QML里我记得是有现成的粒子系统的,拿那玩意做这个我觉得是特别合适了。(啊当然,前提是我们在说exe而不是网页)

怎么说呢怎么说呢,毕竟您拿个优盘开开心心去表白,不管是安装依赖装半天才能运行,还是跟我这茬似的Windows Defender连续弹窗,好像都不怎么合适是吧…

用Qt的话好歹windeployqt一下基本上就没什么好操心的了,而且看起来兼容性也不错(至少赶大作业的时候,某个大佬还有被pyinstaller背刺的时候呢,我这边deploy一下顶多塞个vcredist进去好像就没出过什么大岔子,实在不行还能/MT呢对吧)。

您上个QML,不用自己抠shader也犯不上自己算粒子运动,反正这玩意也不吃性能您直接用软件GL总出不了大问题是吧;从音频到视频从文本到语音都有现成的库可以用,资源需求和启动速度什么的跟native的可能比不了但至少比CEF强多了是吧

(啊…总感觉好像忘记了什么…就先这样吧…好困…)



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3