- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
纯文字很难描述,所以我录了一个GIF来演示。
https://public.lightpic.info/image/2B1F_582465841.gif
我目前正在做一个需要这种效果的项目。到目前为止,我已经用 SpriteKit 在 iOS 上完成了类似的效果,但不幸的是,结果并不令人满意。
这是我的作品:在我的项目中有一个不规则形状的物体,在物体重心以下某处施加恒定的力,其方向向下。我规定了物体的坐标不能被力改变,这样物体就不会被力往下拉。当物体倾斜时,它的惯性和力产生角动量,使物体直立。详情:
并且在操纵物体时,作用点高于重心。由于物体的惯性和力的结合,角动量使物体倾斜。
然而,没有什么能证明我是对的,因为我从 SpriteKit 的物理引擎得到的结果是,该对象原来是一个简单的钟摆。但是直觉告诉我我没有看错,实际上我并没有把物体的重心固定在背景上,我真正做的是每次模拟物理时把物体放回原来的位置。但是结果真的狠狠地打了我的脸:(。所以,钟摆摆啊摆啊,最后的物理效果简直糟透了。
然后我想出了一个临时解决方案:每次模拟物理时将角速度乘以0.95。这个方案显然不是最理想的方案,因为当旋转角度趋于水平时,角速度不够大,慢慢直立起来。不过有一个进步:至少物体终于能够停止摆动了。
我进一步的解决方案是,施加在物体上的力会随着倾斜程度的变化而变化。物体趋于水平时,力趋于大,物体趋于垂直时,力趋于小。一个简单的函数可以很好地描述它:F=1000N×|sin[旋转度数]|。这很有帮助,但不幸的是,结果效果似乎根本不是物理的。
总结:经过多日的研究,未能实现GIF中展示的效果,深感惭愧。我真的希望有能力的人能帮助我。感谢您阅读我的长篇描述,非常感谢您的耐心等待。
添加:
有一个屏幕截图显示了我实现此效果的方法。
补充 2:
我已经上传了我的实现,这是一个 Swift Playground 文件。下载地址:http://www.mediafire.com/file/qrct5sty2cyvwsy/Swing.playground.zip
附言。由于我的母语不是英语,请原谅我糟糕的语法。
最佳答案
您需要的是连接到 Spring 的摆臂和在小车上移动的阻尼器。
Spring 施加力使摆臂返回直立位置。
阻尼(在演示中它作为摩擦应用于旋转关节,例如在生锈的关节中发现的)只是为了阻止它永远振荡。
移动鼠标会在摆臂顶部施加一个相反方向的力。
摆V摆臂
摆锤和 Spring 摆臂之间的一个区别是摆动频率会根据角动量的大小、 Spring 上的最小张力和摆臂的位置而变化。
交互式插图
插图显示了摆臂的 Action ,但摆臂的特性取决于许多因素;摆臂的高度、 Spring 的强度、阻尼、摆臂的质量,其中 Spring 安装在摆臂上并固定在移动小车上。我添加了一些 slider ,让您看到不同的行为。
插图不是答案,它只是为了说明概念,您必须在您使用的任何软件或库中实现解决方案。
Spring 非常简单, Spring 长度和力之间存在线性关系。 Lookup Hook 定律。
示例中的阻尼只是一个应用于增量旋转的标量。 dr *= 1-阻尼
力作为加速度和力(以像素 BS 为单位的牛顿)施加到摆臂的某个位置。枢轴是固定的,因此任何线性加速度都会丢失。
更新。第一篇文章中有一些错误。我将 Spring 力作为加速度而不是力来施加, Spring 无法张紧,鼠标的移动被错误地转换为加速度。差异很微妙但很重要。所有固定🤞享受😀
var canvas = document.createElement("canvas");
canvas.width = innerWidth - 40;
canvas.height = innerHeight - 40;
canvas.style.border = "1px solid black";
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
var sliderChanged = true;
function createSlider(name,val,min,max){
var div = document.createElement("div");
div.textContent = name;
var slider = document.createElement("input");
var valSpan = document.createElement("span");
slider.type = "range";
slider.min = min;
slider.max = max;
slider.step = (max-min)/Math.floor(canvas.width * 0.7);
slider.value = val;
valSpan.textContent = val;
slider.addEventListener("mousemove",function(){
if(slider.value !== slider.lastValue){
slider.lastValue = slider.value;
valSpan.textContent = Number(slider.value).toFixed(3);
sliderChanged = true;
}
});
div.appendChild(slider);
div.appendChild(valSpan);
document.body.appendChild(div);
return slider;
}
var springTension = createSlider("Spring tension :",0.5,0,1);
var springStrength = createSlider("Spring strength :",5,0.1,20);
var damping = createSlider("Damping :",0.1,0.01,1.0);
var armMass = createSlider("Swing arm mass:",200,1,1000);
var armHeight = createSlider("Swing arm height:",Math.floor(canvas.height * 0.6),Math.floor(canvas.height * 0.1),Math.floor(canvas.height * 0.8));
var mouse = (function () {
function preventDefault(e) {
e.preventDefault();
}
var mouse = {
x : 0,
y : 0,
bounds : null,
mouseEvents : "mousemove".split(",")
};
var m = mouse;
function mouseMove(e) {
var t = e.type;
m.bounds = m.element.getBoundingClientRect();
m.x = e.pageX - m.bounds.left;
m.y = e.pageY - m.bounds.top;
}
m.updateBounds = function () {
}
m.start = function (element) {
m.element = element === undefined ? document : element;
m.mouseEvents.forEach(n => {
m.element.addEventListener(n, mouseMove);
});
m.updateBounds();
}
return mouse;
})();
mouse.start(canvas);
//=====================================================================================================================
// Answer start here
const springCof = 0.3; // characteristic of the spring see Hooks law
const dampingC = 0.05; // amount of damping as a factor of rotational speed.
const springTensionC = 0.5; // min tension on the spring ( 1 subtract the amount the spring is stretched from relaxed length)
// details of the swing arm
var pole = {};
pole.mass = 200;
pole.dr = 0;
pole.rot = 0;
pole.piviotRadius = canvas.height * 0.01;
pole.topWidth = canvas.height * 0.02
pole.centerWidth = canvas.height * 0.04
pole.baseWidth = canvas.height * 0.02
pole.x = canvas.width / 2;
pole.y = canvas.height * 0.7;
pole.height = canvas.height * 0.6; // from rotation point to top
pole.baseHeight = canvas.height * 0.1;
pole.spring = {};
pole.spring.y = canvas.height * 0.1;
pole.spring.x = 0;
pole.spring.baseY = canvas.height * 0.2;
pole.spring.baseX = 0;
pole.spring.relaxLength = Math.hypot(pole.spring.x -pole.spring.baseX, pole.spring.y - pole.spring.baseY);
pole.spring.relaxLength *= springTensionC;
pole.spring.cof = springCof; // characteristic of the spring see Hooks law
pole.spring.damp = dampingC; // amount of damping as a factor of rotational speed.
// Basicly the pivot is rusty and provides the damping.
function setPoleValues(pole){
pole.height = Number(armHeight.value);
pole.mass = Number(armMass.value);
var lookRight = Math.pow(pole.mass,1/3)/Math.pow(1000,1/3);
pole.topWidth = canvas.height * (0.001 + 0.02 * lookRight);
pole.centerWidth = canvas.height * (0.004 + 0.04 * lookRight)
pole.baseWidth = canvas.height * (0.004 + 0.02 * lookRight)
pole.spring.relaxLength = Math.hypot(pole.spring.x -pole.spring.baseX, pole.spring.y - pole.spring.baseY);
pole.spring.relaxLength *= 1-Number(springTension.value);
pole.spring.cof = Number(springStrength.value);
pole.spring.damp = Number(damping.value);
}
// draws a spring
function drawSpring(x1,y1,x2,y2,width){
var x = x2 - x1;
var y = y2 - y1;
var dist = Math.sqrt(x * x + y * y);
var nx = x / dist;
var ny = y / dist;
ctx.beginPath();
ctx.lineWidth = 1;
ctx.moveTo(x1,y1);
var step = 0.1;
for(var i = step; i < 1-step; i += step){
for(var j = 0; j < 1; j += 0.1){
var xx = x1 + x * (i + j * step);
var yy = y1 + y * (i + j * step);
xx -= Math.sin(j * Math.PI * 2) * ny * width;
yy += Math.sin(j * Math.PI * 2) * nx * width;
ctx.lineTo(xx,yy);
}
}
ctx.lineTo(x2,y2);
ctx.stroke();
return dist;
}
// draws the pole and also calculates the position of the pole top
// and details about the spring
function drawPole(pole){
ctx.fillStyle = "red";
ctx.strokeStyle = "black";
ctx.lineWidth = 4;
ctx.lineJoin = "round";
ctx.setTransform(1,0,0,1,pole.x,pole.y)
ctx.rotate(pole.rot)
ctx.beginPath();
ctx.moveTo( - pole.topWidth,- pole.height);
ctx.lineTo(pole.topWidth,- pole.height);
ctx.lineTo(pole.centerWidth,0);
ctx.lineTo(pole.baseWidth, pole.baseHeight);
ctx.lineTo( - pole.baseWidth, pole.baseHeight);
ctx.lineTo( - pole.centerWidth,0);
ctx.closePath();
ctx.stroke();
ctx.fill();
ctx.fillStyle = "yellow";
ctx.beginPath();
ctx.arc( pole.spring.x,pole.spring.y,pole.piviotRadius * 0.5,0,Math.PI*2);
ctx.stroke();
ctx.fill();
ctx.setTransform(1,0,0,1,0,0)
ctx.fillStyle = "blue";
ctx.beginPath();
ctx.arc(pole.x,pole.y,pole.piviotRadius,0,Math.PI*2);
ctx.stroke();
ctx.fill();
ctx.fillStyle = "yellow";
ctx.beginPath();
ctx.arc(pole.x + pole.spring.baseX,pole.y + pole.spring.baseY,pole.piviotRadius * 0.5,0,Math.PI*2);
ctx.stroke();
ctx.fill();
var xdx = Math.cos(pole.rot);
var xdy = Math.sin(pole.rot);
var xx = pole.spring.realX = xdx * pole.spring.x - xdy * pole.spring.y;
var yy = pole.spring.realY = xdy * pole.spring.x + xdx * pole.spring.y;
pole.spring.length = Math.hypot(pole.x + xx -(pole.x + pole.spring.baseX), pole.y + yy- (pole.y + pole.spring.baseY));
pole.spring.direction = Math.atan2(pole.y + pole.spring.baseY - (pole.y + yy),pole.x + pole.spring.baseX-(pole.x + xx ))
pole.topX = pole.x + xdy * pole.height; // at 90 deg
pole.topY = pole.y - xdx * pole.height;
drawSpring(pole.x + xx,pole.y + yy,pole.x + pole.spring.baseX,pole.y + pole.spring.baseY,3);
}
// applies a force.
// As the the swing arm rotation point is fixed this only extracts the
// angular acceleration from the force
function applyAccel(pole,x,y,ax, ay){ // x,y where the force is applied,
// ax,ay the acceleration of the force
var direction = Math.atan2(ay,ax);
var toCenter = Math.atan2(pole.y - y, pole.x - x);
var pheta = toCenter - direction;
var dist = Math.hypot(x-pole.x,y-pole.y);
var force = Math.hypot(ax,ay) * pole.mass;
var Fa = Math.sin(pheta) * force;
Fa = Fa / (pole.mass * dist);
pole.dr += Fa;// now add that to the box delta r
}
function applyForce(pole, x, y, fx, fy){ // x,y where the force is applied,
// fx,fy the force
var direction = Math.atan2(fy,fx);
var toCenter = Math.atan2(pole.y - y, pole.x - x);
var pheta = toCenter - direction;
var dist = Math.hypot(x-pole.x,y-pole.y);
var force = Math.hypot(fx,fy) ;
var Fa = Math.sin(pheta) * force;
Fa = Fa / (pole.mass * dist);
pole.dr += Fa;// now add that to the box delta r
}
// for calculating the acceleration of the mouse
var lastX = 0;
var speed = {};
speed.x = 0;
speed.y = 0;
speed.lx = 0;
speed.ly = 0;
function update2(timer){
globalTime = timer;
ctx.setTransform(1,0,0,1,0,0); // reset transform
ctx.globalAlpha = 1; // reset alpha
ctx.clearRect(0,0,canvas.width,canvas.height);
if(sliderChanged){
setPoleValues(pole);
sliderChanged;
}
if(lastX == undefined){
lastX = mouse.x;
getPoleDetails(pole);
}
drawPole(pole);
// move the pole
pole.x = mouse.x;
// get the acceleration of the mouse movement
speed.x = (lastX - mouse.x);
speed.y = 0;
// apply the mouse movement acceleration to the top of the pole
// Accel is the change in mouse speed
applyAccel(pole,pole.topX,pole.topY,speed.x - speed.lx, speed.y - speed.ly);
// apply the springs force (note the spring is never compressed)
applyForce(
pole,
pole.x + pole.spring.realX,
pole.y + pole.spring.realY,
Math.cos(pole.spring.direction) * (pole.spring.length - pole.spring.relaxLength) * pole.spring.cof,
Math.sin(pole.spring.direction) * (pole.spring.length - pole.spring.relaxLength) * pole.spring.cof
)
// add the change in rotation
pole.rot += pole.dr;
// dampen the rotation
pole.dr *= 1-pole.spring.damp;
lastX = mouse.x
speed.lx = speed.x;
speed.ly = speed.y
if((mouse.buttonRaw & 4)!== 4){
requestAnimationFrame(update2);
}else{
log("done");
}
}
requestAnimationFrame(update2);
关于ios - 如何在SimCity 5中实现建筑物移动时摇摆的物理效果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40548921/
我可以使用 javascript 和其他所有东西,但在重新发明轮子之前,我想知道是否已经有一个类似的 jquery 插件,因为我想使用那个框架而不是 mootools。 我没有钱的问题,特别是 5 欧
我正在 React 应用程序中处理动画。我需要动画在悬停 后开始工作。我尝试了 :hover:after css 但不起作用。将鼠标悬停在图像上后动画可以工作,但我需要在悬停后开始。将鼠标悬停在图像上
我正在使用 jQuery 在按钮单击时实现 slider 效果。我的代码是: $(document).ready(function() { $("#mybutton").click(functio
我需要一个div标签在屏幕右侧滑出,如何使用jQuery获得这种效果?我一直在看这里:http://api.jquery.com/category/effects/sliding/而且这似乎不是我要找
我正在使用此代码实现页面 curl 效果......它在模拟器和设备中工作正常......但它不是(setType:@“pageCurl”)苹果记录的api,这导致它被iPhone拒绝App Stor
我见过各种关于 WPF 效果的引用,但它们似乎是针对位图的,而不是针对文本的。是否可以将除模糊或投影以外的效果应用于XAML中的TextBlock对象? 我想要做的示例可能是轮廓笔划,或斜角/浮雕效果
我见过各种关于 WPF 效果的引用,但它们似乎是针对位图的,而不是针对文本的。是否可以将除模糊或投影以外的效果应用于XAML中的TextBlock对象? 我想要做的示例可能是轮廓笔划,或斜角/浮雕效果
我正在尝试模拟这种效果:http://meyerweb.com/eric/css/edge/complexspiral/demo.html在我的博客上:http://segment6.blogspot
我尝试将样式应用到 Accordion Pane ,但遇到了问题。 这行不通。 accordion.setEffect(new DropShadow(BlurType.ONE_PASS_BOX, Co
关于 Datatables website 的教程足够清楚了: 在我告诉 Datatables 我正在谈论哪一列后,我只需将切换按钮放入: column.visible( ! column.visib
我正在寻找 scratchOut 效果,随便叫它什么。 这是从前景中删除图像的效果,因此背景图像变得可见。 我曾尝试使用 jquery 插件重新创建此效果,但它并不像我希望的那样流畅。 有没有人有这种
本文实例讲述了android实现文字和图片混排(文字环绕图片)效果。分享给大家供大家参考,具体如下: 在平时我们做项目中,或许有要对一张图片或者某一个东西进行文字和图片说明,这时候要求排版美观,所
本文实例讲述了Javafx简单实现【我的电脑资源管理器】效果。分享给大家供大家参考。具体如下: 1. java代码: ?
我是 ngrx 的新手,正在尝试让我的 ngrx 商店的 @Effect 函数正常工作。下面的代码显示了如果我没有使用 ngrx 商店,服务是如何工作的。我首先调用 http.get 来获取列表,然后
基本上我搜索了很多,解决方案建议应用一些 PNG 掩码或不提供所需的解决方案。 我发现了什么。 ffmpeg -i main.mkv -i facecloseup.mkv -filter_compl
有关使用从商店中选择的状态的效果的 Ngrx 文档状态(没有双关语意) Note: For performance reasons, use a flattening operator like co
我有一个数据网格控件,我在其中使用名为 FastShadow 的自定义效果,它就像一个光晕。 我希望效果在其边界之外发光,这样很好,但是当我在顶部绘制另一个形状时,我不希望这个形状受到影响。在本例中,
除了子 div.exception 中的所有内容,我想将 div.main 中的所有文本设为灰色。 div.exception 应该看起来好像类 main 从未添加到父 div。 这可能吗?如果是这样
我有一个 PDF 文件,我想重现此包页面中的页面 curl 效果: https://pub.flutter-io.cn/packages/page_turn 我试过用这个 page_turn插件,它需
我想测试一个效果如下: 如果调度了 LoadEntriesSucces 操作,则效果开始 等待 5 秒 5 秒后发送 http 请求 当响应到达时,将分派(dispatch)新的操作(取决于响应是成功
我是一名优秀的程序员,十分优秀!