w0rm/elm-physics

Collision detection between a block and a sphere fails sometimes

JarnoLeConte opened this issue · 5 comments

First of all I would like to say that you did an amazing job creating this elm package. It's a well documented package and friendly starting point for learning Elm, while playing with the physics and WebGL.

But it feels like the engine start missing to detect collisions when the velocity of objects become slightly higher. Even though when I use larger objects and a fixed frame rate (1/60 seconds). In my opinion the velocity is not even that high in the first place. So I'm wondering if there is something wrong in the collision detection? Isn't Elm not suitable for this? Or is it me doing something wrong?

Below you see the basic setup for a pinball game I'm creating. Of course this GIF is running with a lower frame rate than the real game, which runs almost exactly 60 frames per seconds. There are two problems:

  1. Sometimes the paddle misses the ball.
  2. Sometimes the paddle is going through the wall.

I can prevent these issues from happening by either:

  1. Lowering the frame rate (e.g. 30 frames per second)
  2. Lowering the velocity of the objects.
    But that is not a real solution.

ezgif-2-8d135354276e

Hopefully you can help me to find the source of the problem.

Kind regards,
Jarno Le Conté

w0rm commented

Hey @JarnoLeConte it seems that this is tunnelling due to high velocity. Basically bodies should not travel more than a half of their size per simulation step.

I’ve had the same issue when trying to build a pool game:

collision

More sophisticated physics engines have continuous collision detection. To partially address the issue, I've added a safeguard that caps the movement, but that doesn't take into account relative velocity between two moving bodies.

I actually wonder if this is because of the way you model the paddles. Can you tell more about how these paddles are implemented?

One option could be simulating twice per frame:

{ model
    | world =
        -- Simulate at shorter interval to prevent tunneling
        model.world
            |> World.simulate (seconds (1 / 120))
            |> World.simulate (seconds (1 / 120))
}

Thank you for responding.

I couldn't imagine that the ball was traveling half of it size each frame, because the animation was too smooth (and relative low velocity). But maybe you are right, if both objects move towards each other it will probably go too fast.

You asked me how the paddle is implemented:

  1. It's a block with a Hinge constraint onto the ground
  2. As long the arrow key is pressed, an upward force is added to the paddle each simulation step.

I uploaded the source code here:
https://github.com/JarnoLeConte/elm-pinball-experiment/blob/master/src/Main.elm

Your suggestion to call multiple simulation steps each frame seems like to work. Actually I need at least 3 simulation steps. For now that is working, but I'm worried that this will slow down the game once more objects become added.

I have to note that I have only a little experience in programming games. So my setup can be improved a lot, probably. I had also a bit of trouble adding the constraints. Sometime de paddle collapse away in the ground, or it suddenly start to rotate along another axis as well. I suppose that are issues unrelated with this package, but just common 3D scene knowledge I don't have yet.

w0rm commented

Just checked the game, seems to work fine for me! Curious about the issues you had with constraints, could as well be a bug. If it happens again, I would like to check the source code that reproduces it.

By the way, constraints do not have to be set on each frame (unless you dynamically add more bodies), you can do it once for the initial world.

Performance hopefully shouldn't be a big problem, especially if you plan a bunch of static bodies, as collisions with a sphere are relatively easy. The slowest part is the solver, that depends on the number of constraints and collision points. Static bodies are not collided with each other.

I'm not super experienced in making games either, thanks for trying out the engine! Let me know if you run into any issues.

Thanks for helping.

Now I run multiple simulation steps everything seems to work fine and stable. So this issue can be closed. If I run into problems with the constraints again, I will let you know.

I appreciate your suggestion to setup the constraints only once. I will make that improvement. To be honest, I copied most implementation details from the Car example, which probably does the same thing 😉

Good to know that performance wouldn't be a problem. Actually I'm surprised about how Elm is performing quit good on this subject. I wasn't expecting that from a pure functional language. It makes it cool. I really start liking it :)

w0rm commented

The car example sets the steering position of the wheels by rotating the hinges, so I just found it easier to do it in the animation frame. But e.g. the drag example only sets the constraint when you click an object.

For seeing the performance limits, I set up the following example: https://unsoundscapes.com/elm-physics/examples/boxes/ that runs close to 60fps (I haven't released a version with the recent improvements yet). I think your game will need less than that even if you simulate three times.

If you have any more questions feel free to open more issues, or join #gamedev channel on Elm Slack, I am unsoundscapes there!