Closed EskelCz closed 8 years ago
Hey, I am working with @EskelCz on the game. I think he didn't explained well what we need and some of the issues are already solved anyway.
Currently we have a rather simple problem. For a player body we use Bodies.circle
with these settings:
collisionBody.frictionAir = 0
collisionBody.inverseInertia = 0
When these two bodies meet, they bounce off each other. We simply need them to stop moving in the direction of a collision, but they can still move around each other. I am rather weak at physics too, isn't there some option that would allow us to do that?
From the sounds of it I think you should look at the Body Manipulation demo and check out the source code. This shows some techniques for precisely controlling bodies.
Id highly suggest you use impulses.
Onmousemove
On timestep
The reason this is better is setting positiom directly will cause bodies to overlap. Setting position will quite literally set position. And the collision resolver will not know how to handle it as the velocities that caused it are trchnically nonexistant. Set position is better for respawning/new level type situations where the dev is fully aware of what is and isnt around. You can also do a set position in a crowded space after finding an opponening but you will need to find an opening.
I dont know if this can be applied to matter js but i know its true for box2d and it seems as though matter may have taken heavy inspiration if not some of box2ds code itself
@formula1: That sounds really like a good thing to have. We are doing exactly that, using translate
to move onto coordinates where the collision happens. I tried debugging deeply, but didn't really found the way how to influence this bounce off effect.
https://github.com/liabru/matter-js/blob/master/examples/restitution.js
This is probably what your looking for. If you go to the restitution example of the demo you can essentially modify how much an object elastic/inelastic a collision is.
I assume when resitution should be 0
Yeah, I definitely tried that before, has no effect in this case. It's even set to 0 by default.
Hm... Looking at the resolver code
I see the only place that restitution is being used is
Im confident its being handled correctly, though i havent calculated use cases. Heres what we know though
This is likely a bug. I don't believe box2d has this issue so ill have to test it out. But this may be a deeper issue
Restitution and bouncing is not an issue, the problem was in friction and I've solved it some time ago. The topic of this thread is collision control and and value precision/resets and weight application.
In particular these two questions:
If you directly change position, no velocities will br applied. This will cause overlaps and make the collsion solver make innaccurate or messed up reaction forces.
By applying an impulse that subtracts the last velocity and adds the new velocity to the bodies center, you allow the collision solver to act the way it should
Ok so I tested using positionImpulse (directly, as I can't find any setter method) but it acts pretty much the same. It just goes faster, has a little inertia overshoot at the end of translation and some random rotation. That doesn't bother me but the velocity and speed values are still 0, before and after engine update.
Ill try to take a look tonight.
I understand now what you mean and honestly, its rather difficult to implement properly in Matter JS. Below was my code and I found that often the Body would end up at positions > +/- 5000 causing freezes in addition forces not working quite how I understand they should. I found that the closer I multiplied each of the Vectors by one, the more direct the velocity would be to the effect I think you desired. But to get to this, you need to increase the velocity iterations to the point where it will not blindly guess when presented a huge velocity change. I'll definitely say this was not my comfort zone though I thought it was as simple as I've done it in other areas. I was incorrect to tell you to "apply impulse" as there is no method for that from what I can tell from the docs. Hopefully this is a good example for you
<!doctype html>
<html>
<head>
<script src="https://raw.githubusercontent.com/liabru/matter-js/master/build/matter.min.js" ></script>
<script type="text/javascript" >
window.addEventListener('load', function(){
var World = Matter.World,
Bodies = Matter.Bodies,
Vector = Matter.Vector,
Body = Matter.Body,
Engine = Matter.Engine,
Events = Matter.Events,
Mouse = Matter.Mouse;
var engine = Matter.Engine.create(document.querySelectorAll('#canvas-container')[0], {
positionIterations: 10,
velocityIterations: 30,
enableSleeping: false,
metrics: { extended: true}
});
engine.timing.isFixed = true;
var runner = Engine.run(engine);
var movable = Bodies.circle(300, 300, 10, { frictionAir: 0.000, restitution: 0.0, density:1 });
var canvas = engine.render.canvas;
var mouse = Mouse.create(canvas);
Events.on(engine, 'tick', function(){
var toSub = Vector.sub({x:0,y:0}, movable.velocity);
toSub = Vector.mult(toSub, 3/4);
Body.applyForce(movable, movable.position, toSub);
var impulse = Vector.sub(mouse.position, movable.position)
console.log("before vel: ", 10/runner.delta);
impulse = Vector.mult(impulse, 3/4);
Body.applyForce(movable, movable.position, impulse);
});
engine.world.gravity.y = 0;
engine.world.gravity.x = 0;
engine.timing.timeScale = 1;
World.add(engine.world, [
movable,
Bodies.circle(250, 250, 20, { frictionAir: 0.000, restitution: 0.0, density: 1000 }),
]);
});
</script>
</head>
<body>
<div id="canvas-container"></div>
</body>
</html>
That's a perfect example, thanks a lot for looking into it, I'll try it out on our engine. One more thing, how would I go about making the obstacle almost unmovable? So it can be pushed but only by a very little. (a heavy crate for example) I've tried mass and density values to no avail. (that was with the position update method)
This should be able to handle density and weight as it uses forces rather than setting position directly. To make it actually immovable or something that wants to retain position http://brm.io/matter-js-docs/classes/Constraint.html
You want to specify a bodyA then specify pointB in world space (most likely body.position), with length of zero and the stiffness will be the how immovable it is
The simplest solution with forces I've found is this (each tick):
Body.applyForce body, body.position, {x: -body.velocity.x, y: -body.velocity.y} Body.applyForce body, body.position, {x: x, y: y}
Each tick? Do you mean something:
Matter.Events.on(engine, 'afterUpdate', function () {
Body.applyForce(body, body.position, {x: -body.velocity.x, y: -body.velocity.y});
Body.applyForce(body, body.position, {x: x, y: y});
});
@Aleksey-Danchin: Exactly, that was coffeescript, sorry. We have our own game loop but that afterUpdate event should work as well I guess.
I just found out that this is not precise when moving multiple bodies at the same time. No idea why but they move faster despite having the same x, y input. :( Reverting back to Body.translate
@EskelCz are they the same mass?
@liabru In regards to your initial response to this issue, I'm looking at the Body Manipulation Demo... but I'm not seeing how the example applies to moving bodies accurately for a top down multiplayer game.
I have successfully synchronized two instances of matterjs, but since one is the server and one is the client, they don't run at the same speeds. This causes the issue mentioned above (I think) where the host player moves slower than the client player despite having the same velocities. I'm struggling to find the right way to force all bodies velocities to be relative to actual time rather than the engine's tick interval (which I think is what's causing my problem? Correct me if I'm wrong). Do you have any guidance on this matter?
Hi, I can't find an example close to my use case and I have to admit I'm not very good at physics theory. The source code has so many interactions of similar (to me) properties that I kind of got lost.
I'd like to move a body based on mouse input, with no gravity and 'inertia' (nothing floating, it's all top-down moving characters and walls). When a body collides with another body, I need to know the length of the vector it actually moved until the collision (so I can send it to a server). Let's say I tried to move by x:100 and at distance 50 is a wall. I'd like to get a {x:50, y:0} vector. Also a reference to the colliding body would be really nice, for pushing things.
I tried 'setPosition' or 'translate' and looked at 'positionImpulse' value. The engine computes the behavior properly but the 'positionImpulse' doesn't reset to zero after the collision is cleared.
Also properties 'moving' and 'velocity' don't get updated, even though it I thought they should from the velocity description.
Maybe I'm using a wrong method altogether. Thanks for any guidance, I suspect more people might run into similar problems.