作者:G小麥NO1_238 | 来源:互联网 | 2023-06-10 11:06
相信这个特效你和你的朋友(或对象)一定玩过 当你发送一个便便的表情,对方如果扔一个炸弹表情,就会立刻将这个便便炸开,实现满屏粑粑的“酷炫”画面。可谓是“臭味十足”,隔着屏幕都能感受到来自微信爸爸的满满恶意。
不清楚大家对这个互动设计怎么看,反正一恩当时是喜欢的不行,拉着朋友们就开始“炸”得不亦乐乎。
同样被虏获芳心的设计小哥哥在玩到尽兴后,突然灵感大发,连夜绘制出了设计稿,第二天就拉上产品和研发开始脑暴。
“微信炸💩打动我的一点是他满屏的设计,能够将用户强烈的情绪抒发出来;同时他能够与上一条表情进行捆绑,加强双方的互动性。”设计小哥哥声情并茂道。
“所以,让我们的表情也‘互动’起来吧!” 这不,需求文档就来了:
改掉常见的emoji表情发送方式,替换为动态表情交互方式。即, 当用户发送或接收互动表情,表情会在屏幕上随机分布,展示一段时间后会消失。 用户可以频繁点击并不停发送表情,因此屏幕上的表情是可以非常多且重叠的,能够将用户感情强烈抒发。 (暂用微信的聊天界面进行解释说明,图1为原样式,图2是需求样式)
这需求一出,动态表情在屏幕上的分布方案便引起了研发内部热烈讨论:当用户点击表情时,到底应该将表情放置在屏幕哪个位置比较好呢?
最直接的做法就是完全随机方式:取0到屏幕宽度和高度中随机值,放置表情贴纸。但这么做的不确定因素太多,比如存在一定几率所有表情都集中在一个区域,布局边缘化以及最差的重叠问题。因此简单的随机算法对于用户的体验是无法接受的。
我们开始探索新的方案: 因为目前点的选择依赖于较多元素,比如与屏幕已有点的间距,与中心点距离以及屏幕已有点的数目。因此最终决定采用点权随机 的方案,根据上述元素决策出屏幕上可用点的优度,选取优度最高的插入表情。
基本思路 维护对应屏幕像素的二维数组,数组元素代指新增图形时,图形中心取该点的优度。 采用懒加载的方式,即每次每次新增图形后,仅记录现有方块的位置,当需要一个点的优度时再计算。
遍历所有方块的位置,将图形内部的点优度全部减去 A ,将图形外部的点按到图形的曼哈顿距离从 0 到 max (W,H),映射,减 0 到 A * K2。 每次决策插入位置时,随机取 K + n * K1 个点,取这些点中优度最高的点为插入中心 A, K, K1, K2 四个常数可调整
一次选择的复杂度是 n * randT,n 是场上方块数, randT 是本次决策需要随机取多少个点。 从效率和 badcase来说,这个方案目前最优。
代码展示 &#96;&#96;&#96;cpp# include # include using namespace std; const int screenW &#61; 600 ; const int screenH &#61; 800 ; const int kInnerCost &#61; 1e5 ; const double kOuterCof &#61; .1 ; const int kOutterCost &#61; kInnerCost * kOuterCof; class squareint x1; int x2; int y1; int y2; } ; int lineDist ( int x, int y, int p) { if ( p < x) { return x - p; } else if ( p > y) { return p - y; } else { return 0 ; } } int getVal ( const square & elm, int px, int py) { int dx &#61; lineDist ( elm. x1, elm. x2, px) ; int dy &#61; lineDist ( elm. y1, elm. y2, py) ; int dist &#61; dx &#43; dy; constexpr int maxDist &#61; screenW &#43; screenH; return dist ? ( ( maxDist - dist) * kOutterCost / maxDist ) : kInnerCost; } int getVal ( const vector< square> & elmArr, int px, int py) { int rtn &#61; 0 ; for ( auto elm: elmArr) { rtn &#43;&#61; getVal ( elm, px, py) ; } return rtn; } int main ( void ) { int n; cin >> n; vector< square> elmArr; for ( int i&#61; 0 ; i< n; i&#43;&#43; ) { square cur; cin >> cur. x1 >> cur. x2 >> cur. y1 >> cur. y2; elmArr. push_back ( cur) ; } for ( ; ; ) { int px, py; cin >> px >> py; cout << getVal ( elmArr, px, py) << endl; } }
优化点 该算法最优解偏向边缘。因此随着随机值设置越多&#xff0c;得出来的点越偏向边缘&#xff0c;因此随机值不能设置过多。 为了解决偏向边缘的问题&#xff0c;每一个点在计算优度getVal需要加上与屏幕中心的距离 * n * k3 效果演示 最后就是给大家演示一下最后的效果啦&#xff01; 圆满完成任务&#xff0c;收工&#xff0c;下班&#xff01;