图片来源公众号“住在疯人院”,链接:https://mp.weixin.qq.com/s?__biz=MzUxOTg4ODI4NA==&mid=2247487501&idx=1&sn=aea4f6f06e3115689bbeef039b6af7ea&chksm=f9f39cfece8415e8be76c5483ec1a826a49c75d0316b6418a81e831746de8323ea3c46b711e5&mpshare=1&scene=23&srcid=#rd
言归正传,下面要介绍的是一个名为“神秘力量”的动画交互系统,系统使用processing开发,旨在为用户提供细腻生动的交互体验。
//系统界面截图
正如上述漫画所言,我们的生活似乎总是被一种“神秘力量”控制着,“神秘力量”支配着我们拿起手机,并悄悄偷走我们的时间。而本文要介绍的《神秘力量》讲述了这样一个故事:故事的主角“蛋蛋”总是在人们面前晃来晃去的,不管对它做什么,它最终都会回到属于它自己的状态,游离在大家面前。自然界的一切真实力量都无法控制它,任何人都无法摆脱它的存在。似乎有一种神秘的力量,把它拴在每一个人面前,任何人都摆脱不了。
故事中“蛋蛋”的生性顽固与神秘的力量,暗喻现实生活中人们意志力薄弱,不是对“神秘力量”束手无策,而是在诱惑面前束手就擒。
本应用共分为三个章节,分别模拟三种物理系统,用户通过鼠标操作控制主角“蛋蛋”在物理系统中运动,但“蛋蛋”最终都会回到它原本的运动状态(随机游走)。
应用具有隐喻生活中的诱惑的现实意义,通过简单而又逼真的物理系统模拟让用户获得细腻的交互体验,同时引发对现实的思考。
第一章以一根橡皮绳为道具,模拟橡皮绳对物体的拉力作用。用户点击屏幕即可用橡皮绳牵动“蛋蛋”,拖拽鼠标可以通过橡皮绳控制其移动。“蛋蛋”碰到地面及左右墙壁都会反弹,最终在重力和阻力作用下停止跳动,回到自由游走的状态。
第二章的道具为一个跷跷板,模拟木板以不同速度上升时对物体的弹力作用。跷跷板初始状态为平衡状态,用户点击鼠标后“蛋蛋”移动到跷跷板的左端,此时用户长按鼠标可以给跷跷板右端加力,使“蛋蛋”被弹飞。用户按鼠标持续时间越长,跷跷板右端的力越大,“蛋蛋”就会被弹得越远。此章节中“蛋蛋”碰到地面及左右墙壁同时会被施加弹力,同时受到重力及空气阻力,最终回到自由游走状态。
第三章的道具为一座滑梯,模拟物体从不同粗糙程度的滑梯上滑下的过程。用户点击鼠标可使“蛋蛋”移动到滑梯上端,此时长按鼠标可增加滑梯与“蛋蛋”之间的摩擦力,释放鼠标后“蛋蛋”滑下。用户按鼠标的时间越长,滑梯与“蛋蛋”之间的摩擦力就会越大,“蛋蛋”就会下滑得越慢。最终“蛋蛋”同样会在空气阻力的作用下回归自由游走状态。
此外,用户点击左右按钮进行三个场景之间的切换。三个场景之间无缝连接,场景的转换不会改变“蛋蛋”当前的运动状态。
本应用的创意点主要体现在以下几个方面:
本应用的故事背景看似无厘头,却是对现实生活中某个真实存在的一个侧面(很多人经受不住生活中的小诱惑)加以修饰与包装而成的。背景故事以奇特的切入点吸引用户兴趣,而整个故事又很好的融入进整个应用系统中,让玩家在获得交互体验的同时获得对生活的思考。
本应用的三个章节分别模拟橡皮绳、跷跷板、滑梯三个物理系统,虽然简单,却力求达到最真实的模拟效果,给用户以最真实而又细腻的交互体验。
本应用的三个章节总共只出现了主角“蛋蛋”、跷跷板和滑梯三个物体,且都由2D形状组合而成,结构简洁,画风简单明了。应用中的所有操作都可由鼠标完成,用户只需点击鼠标、长按鼠标、拖动鼠标便可获得细腻的交互体验和轻松的娱乐体验。
系统中角色在开始和用户操作结束后总是保持自由游走状态。其中“蛋蛋”游走的方向和在同一方向上持续的时间(路程)都是随机的,为了产生比较平滑的随机效果,这里用了Perlin噪声。首先设置了一个时间变量(t),每次“蛋蛋”位置改变后更新t的值,根据processing的库函数noise(t)获得一个随机量tempx,然后将tempx在整个屏幕上做位置映射,更新“蛋蛋”的位置。
具体代码如下:
float t;
void walk(){//随机游走
float n = noise(t);
float tempx=map(n,0,1,0,width);
if(pos.x-tempx>=2)//防止瞬移
pos.x--;
if(tempx-pos.x>=2)
pos.x++;
if(mousePressed == false&&pos.y==height - 70*scale-landh&&abs(speed.y)<0.5&&abs(pos.x-tempx)<2){
pos.x = tempx;
t+=0.004;
}
}//walk();
其中代码第4-7行是为了防止用户操作后“蛋蛋”回归自由游走状态时发生瞬移。
本应用针对大哥物理系统做力的模拟,主要涉及重力、弹力、拉力、摩擦力、空气阻力。下面将分别介绍三个物理系统中物理模拟的实现。
在此系统中“蛋蛋”撞到墙壁和地面会反弹,用到了弹力,同时被反弹后会逐渐停下来,是因为模拟了重力和空气阻力,“蛋蛋”在重力和空气阻力的作用下回渐渐停下来。在用户交互时模拟橡皮绳拉力。
变量声明(包含所有章节)如下:
PVector pos;//位置
float scale;//大小(0-1)
float t;
float grav;//重力
float bounce;//弹力
PVector speed=new PVector(0,0);//速度,向上为正
PVector power1=new PVector(0,0);//板的弹力
float friction;//阻力
PVector fric;//摩擦力
PVector deta;
PVector ff;//滑梯上重力和支持力的合力
PVector m,mid,v;
PVector v0;//抛物线初速度
橡皮绳的拉力根据鼠标位置与“蛋蛋”位置的距离计算,距离越大,拉力越大。在这里设置了当鼠标与“蛋蛋”距离大于50时才会产生拉力,并且随着距离变大,拉力会变大,以此模拟弹簧绳的效果。
具体代码如下:
void toss(){//绳拉动
speed.y += grav;
pos.y += speed.y;
speed.x *= friction;
pos.x += speed.x;
detect();
if (mousePressed ) {
if(!clickButton()){
translate(pos.x, pos.y);
m = new PVector(mouseX - pos.x, mouseY - pos.y);
translate(-pos.x, -pos.y);
stroke(150);
float lineX = pos.x + sin(-radians(int(nf(degrees(vAtan2cent360(mid, m, v)),2,2)))- radians(45)) * 70*scale;//vAtan2cent360() define in chapt0
float lineY = pos.y + cos(-radians(int(nf(degrees(vAtan2cent360(mid, m, v)),2,2)) - radians(45))) *70*scale;
line(lineX, lineY, mouseX, mouseY);
if (dist(mouseX, mouseY, pos.x, pos.y) > 50) {
speed.x -= (mouseX - pos.x) * -0.01;//绳的拉力作用
speed.y -= (mouseY - pos.y) * -0.01;
speed.x *= friction;
speed.y *= friction;
}
}
}
}//toss()
跷跷板系统主要在第一章的基础上加了木板的弹力。根据经验,物体被抛出应该会产生一条抛物线,所以直接根据抛物线的相关知识模拟了抛物线运动。主要步骤为:为“蛋蛋”设置初速度v0;检测到鼠标为按下状态时不断增加初速度大小;鼠标被释放时根据速度更新“蛋蛋”的位置pos,并在过程中根据“蛋蛋”所受力(只受重力grav,忽略空气阻力)不断更新速度speed。
此外还有一点设计是在跷跷板停止转动之前,“蛋蛋”一直跟随跷跷板做相对跷跷板静止的运动,当跷跷板停下时“蛋蛋”才被弹出并做抛物线运动。这样的运动更符合现实情况。
具体代码如下:
iphone.v0=new PVector(20,3);
seesaw.rotatespeed=0.05;
void raise(){//跷跷板弹出,抛物线
if(seesaw.leftdrop==true){
pos.x=seesaw.pos.x-130+10;
pos.y=height-landh-10-40-10;
}
if(seesaw.leftdrop==true&&mousePressed){
v0.x+=0.3;
v0.y+=0.01;
seesaw.rotatespeed+=0.001;
}
if(seesaw.rightdrop==true&&seesaw.angle<PI/9){
pos.y-=130*sin(0.05);
pos.x+=130-130*cos(0.05);
speed=new PVector(v0.x*(130-130*cos(0.05)),-v0.y*130*sin(0.05));
}
if(seesaw.angle>=PI/9){
speed.y += grav;
pos.add(speed);
speed.x *= friction;
pos.x += speed.x;
}
}//raise()
滑梯系统在前面的基础上增加了摩擦力。根据受力分析,“蛋蛋”在倾斜的滑梯上时受到三个力:重力、摩擦力、木板的支持力。但经过分析便可以发现,“蛋蛋”在垂直于滑梯方向的受力,即重力在垂直于滑梯方向的分力和支持力可以相互抵消。因此简化了整个系统,只保留了沿滑梯向下的力(ff)即重力和支持力的合力和沿滑梯向上的力即摩擦力(fric)进行模拟。当鼠标按下时,fric增大,以此产生鼠标按的时间越长摩擦力越大(即速度越小)的效果。
在力的模拟之前同样初始化一个沿着滑梯方向的初速度。初始化代码如下:
void slideinit(){
iphone.pos.y=slidpos.y-48;
iphone.pos.x=slidpos.x;
iphone.speed=new PVector(-1,1*slide.tansita);
iphone.fric=iphone.speed.get();
iphone.fric.normalize();
iphone.fric.mult(-1);//方向
iphone.fric.mult(0.01);//乘上大小
iphone.deta=iphone.speed.get();
iphone.deta.normalize();
iphone.deta.mult(-0.005);//乘上大小
}
摩擦力的模拟具体代码如下:
void slip(){//滑下
if(slide.ready==true){
if(mousePressed==true){
fric.add(deta);
fric.limit(1.1);
}
}
if(slide.sliding==true){
speed.add(ff);
speed.add(fric);
pos.add(speed);
}
}//slip()
在整个力的模拟系统中,物体所受到的力、物体的位置、速度都采用了向量的形式。遵循力的模拟系统中的统一模式:
speed.add(force);
pos.add(speed);
应用中星空背景的绘制涉及粒子系统。
[1]代码本色.Deniel Shiffman
[2]https://www.openprocessing.org/sketch/683345
链接:https://blog.csdn.net/wangyouxu24/article/details/89554177
效果图:
评价:应用界面仅用黑白两色,简洁美观,游戏机制完备,操作说明详细且易懂,游戏本身简单好玩,容易上手又不乏挑战性。
链接:https://zhuanlan.zhihu.com/p/64726213
效果图:
评价:“生态瓶”创意新颖,应用界面简洁美观,系统图标简单而又符合大众认知,系统功能完备,整个生态瓶的模拟新颖有趣,较为贴近真实生态系统。
链接:https://blog.csdn.net/qq_38406696/article/details/89811430
效果图:
评价:赋予颜色像素重量这一想法新颖独特,而“颜色的重量感”符合大部分人的认知,易产生共鸣。整个系统给人将课堂知识与生活脑洞完美结合,有趣而又逼真。