I've been experimenting with attractors in physics.js, rigging up a simple object in zero gravity, with an attractor at a point. This creates a great little 'gravity well' as can be seen here.
Where the simple square vector attracts towards a point, at 'x':200,'y':200, and then orbits around it. I'm looking for a way to turn this attractor into more of a gravity well, so that the objects attracted to it slow down over time and eventually settle static and stationary at the point of the attractor, until it was collided with or dragged with the mouse again. Is this a possibility?
Currently the object is created with:
var bodies = [Physics.body('convex-polygon', {
// place the center of the square at (0, 0)
x: 150,
treatment : 'dynamic',
cof: 0.01,
mass : 1,
y: 100,
vertices: [
{ x: 0, y: 0 },
{ x: 0, y: 200 },
{ x: 200, y: 200 },
{ x: 200, y: 0 }
]
})];
The attractor is created thusly:
var attractor = Physics.behavior('attractor', {
order: 0,
strength: 0.0005
}).applyTo(bodies);
attractor.position({'x':200,'y':200});
Affecting the strength of the attractor doesn't appear to help, it just changes the speed of the attraction and subsequent orbit.
I'm looking for a way, in effect, to add friction to the entire space, which I think will do the job in naturally slowing down the object so it ends up stationary at the attractor point. Not sure how to go about this with PhysicsJS.
There is the possibility to create your own Attractor-Behaviour: See this documentation.
If you don't want to that, you can set the option min of the attractor to the size of the polygon, so the forces stops, when the body is at the center of the attractor. Strength and order are optional options, so you don't need to specify them (According to the API). For example this should work for you:
world.add(Physics.behavior("attractor", {
min: 200,
pos: {"x": 200, "y": 200}
}));
Related
Is any option to add min and max value for X and Y position.
Method .to()
I need it for save timeline and angle, but object stop move when reached limit value.
Thank you for your help.
I tried to use snap, but I think its not for this case.
I tried calculate time and position when I need to stop it, but nothing succeeded.
I think better option to set min and max value.
https://codepen.io/GreenSock/embed/NWzzgKO?editors=0010?height=450&slug-hash=NWzzgKO%3Feditors%3D0010&user=GreenSock&tab-bar-color=%23222&name=cp_embed_2#result-box
gsap.set(".box", {x: 300, y: 300});
gsap.to(".box", {
x: 0,
y: 0,
duration: 3,
modifiers: {
x: gsap.utils.unitize(gsap.utils.clamp(100, 300))
}
})
In codepen example which helped to me.
Thanks to gsap developer for help.
I'm using Matter.js and I want two rectangles with a constraint to make them act if they where a single rigid object.
I am basically setting stiffness to 1, so the contraint acts like a rigid bar instead of a spring.
Also to prevent the object from rotating, I'm setting the intertia to Infinity.
// a 20x20 square with 0 friction and infinite inertia
let objectA = Bodies.rectangle(0, 0, 20, 20, {
frictionAir: 0,
inertia: 'Infinity'
});
let objectB = Bodies.rectangle(30, 0, 20, 20, {
frictionAir: 0,
inertia: 'Infinity'
});
let constraint = Constraint.create({
bodyA: objectB,
bodyB: objectB,
length: 30,
stiffness: 1);
This indeed creates 2 objects with a fixed distance and they do not rotate (both squares always have the same absolute orientation)
However the objects can rotate between them, the constrain acts as a linear constraint but not as an angular constraint.
This picture shows how the distance between objects is kept, how the absolute orientation of the objects has not changed but how the objects rotate around each other.
How can I get rid of this rotation and have the two objects act if they were a single object?
I use a different approach: building a Body from parts instead of using constraints. The result is a single rigid object. Matter handles the parts still separately, so you can e.g. drop a ball in the cart created with the code below.
let cart = bodyWithParts(200, 150, { isStatic: true, friction: 0.0 });
function bodyWithParts(x, y, options) {
options = options || {}
let w = 4;
options.parts = [];
options.parts.push(Matter.Bodies.rectangle(w, 20, 5, 20));
options.parts.push(Matter.Bodies.rectangle(40 - w, 20, 5, 20));
options.parts.push(Matter.Bodies.rectangle(20, 40 - w, 50, 5))
let body = Matter.Body.create(options)
Matter.Body.setPosition(body, { x: x, y: y });
return body;
}
Building a Body to of parts can be useful, however, the strength of the orientation "constraint" cannot be lowered. The orientation stays fixed in any situation.
Therefore, I've written the following TypeScript function which adds two constraints of zero length to two Body objects. Constraints allows us to set the stiffness parameter.
Note that removing one the constraints allows one of the bodies to rotate around its own position ("midpoint") but it cannot change its position relative the other body.
/**
* Adds constraints to `bodyA` and `bodyB` such that their current
* relative position and orientaion is preseved (depending on `stiffness`).
*
* #param bodyA the first body of the constraint
* #param bodyB the second body of the constraint
* #param stiffness the stiffness of the constraint connecting `bodyA` and `bodyB`
* #param offsetA the constraint offset on `bodyA` in its coordinate system
* #param offsetB the constraint offset on `bodyB` in its coordinate system
*/
function addRigidBodyConstraints(
bodyA: Body, bodyB: Body,
stiffness: number = 0.1,
offsetA: Vector = Vector.create(0, 0),
offsetB: Vector = Vector.create(0, 0)
) {
function makeConstraint(posA: Vector, posB: Vector): Constraint {
return Constraint.create({
bodyA: bodyA, bodyB: bodyB,
pointA: posA, pointB: posB,
// stiffness larger than 0.1 is sometimes unstable
stiffness: stiffness
})
}
// add constraints to world or compound body
World.add(world, [
makeConstraint(Vector.sub(bodyB.position, bodyA.position), offsetB),
makeConstraint(offsetA, Vector.sub(bodyA.position, bodyB.position))
])
}
I am developing an application to show a property and its elements such as walls, doors, etc. I need to control camera to zoom to specific objects on the scene. However, I need to move camera slowly between objects and not quick movement. I have an example here:
http://interactivebuildings.planning.nsw.gov.au/planning-residential
In this example, when you click an object from the list, camera flies to that object.
How can I do a fly in Three.js?
Thanks.
Its called tweening.
There are a few tweening libraries for JS.
My preferred tweening library is TweenLite or TweenMax by Greensock
To do what I think you want, you would just tween the properties of the camera in your scene.
This what I have used. Works very well using tween.js http://www.createjs.com/#!/TweenJS.
function test () {
var position = {X: 200, Y: 200, Z: 200, lookX: 0, lookY: 0, lookZ: 0};
tween = new TWEEN.Tween(position).to({X: 0, Y: 300, Z: 0, lookX: 0, lookY: 0, lookZ: 0}, 2000);
tween.easing(TWEEN.Easing.Circular.InOut);
tween.onUpdate(function(){
camera.position.set(position.X,position.Y,position.Z);
camera.lookAt( {x:position.lookX, y:position.lookY, z:position.lookZ } );
});
tween.start();
}
test();
animate();
TWEEN.update(time);
I'm trying to use Transform.multiply4x4() to move a surface modifier but it doesn't seem to work as expect. I am trying to rotate a surface almost flat and then send it off into the distance.
My code looks like this
myModifier.setTransform(
Transform.multiply4x4(
Transform.rotateX(1.4), //rotate at the same time by 1.4 radians on the x axis
Transform.scale(0, 0, 1) //send back into the distance
),
{duration: 600}
);
However the only thing that happens is that the surface that is attached to the modifier just gets pushed back into the distance there is no rotation on the X axis. Am I using the multiplyx4x method wrong ?
I am not trying to stagger the effects I am actually trying to do them at the same time.
You may want to chain your modifiers instead.
See this example jsBin
var myRotateModifier = new Modifier({
origin: [0.5, 0.5],
align: [0.5, 0.5],
});
myRotateModifier.setTransform(
Transform.rotateX(1.4),
{duration: 1000}
);
var myModifier = new Modifier();
myModifier.setTransform(
Transform.scale(0, 0, 1),
{duration: 2000}
);
mainContext.add(myRotateModifier).add(myModifier).add(surface);
Why not the multiply4x4 in this case
The multiply4x4 gives you a result matrix from multiplying the two transforms then applies that matrix transform. It results in what you are seeing in your code.
me again with a very specific question about Raphael.js . What I would like to do is, that rectangles push against each other. Lets say I have following situation that each rectangle is side by side example picture and I let the one in the middle transform big:
r.click(function() { r.animate({ width: 100, height: 100 }, 500); });
how can I handle it, that the other ones move correctly away like the transformation.
I've tried it by transforming every by hand, but the problem is, my markup isnt that simple.
Thanks in advance.
Its difficult to know a specific answer without seeing any code and knowing what the markup issues or or how you can tie some maths into calculating the figures, it will likely be more complicated, but you may be able to calculate the amount moved by the rects compared to the new width of the original rect. This shows an example of one way you could maybe approach it... jsfiddle here http://jsfiddle.net/R8avm/3/
Edit: There's an updated fiddle which has some basic maths which can sort of figure the end x,y if you know which direction the cubes will be in. http://jsfiddle.net/R8avm/4/ It will need more complex stuff for more rects moving at different angles if thats needed.
<div id="container"></div>
paper = Raphael( "container",400,400);
var rects = [ [ 100,50,50,50, 150,50 ], //x,y,w,h,newx,newy
[ 50,100,50,50, 50,150 ],
[ 50,0,50,50, 50, -50 ],
[ 0,50,50,50, -50,50 ],
];
var newRects = new Array(4);
var r = paper.rect(50,50,50,50).attr({ fill: '#123' });
for (var a=0; a<rects.length; a++) {
newRects[a] = paper.rect( rects[a][0], rects[a][1], rects[a][2], rects[a][3]);
};
r.click(function() {
r.animate({ width: 150, height: 150, x: 0, y: 0 }, 500);
for (var a=0; a<rects.length; a++) {
newRects[a].animate({ x: rects[a][4] , y: rects[a][5] }, 500);
};
});