kikito / bump.lua

A collision detection library for Lua
MIT License
939 stars 86 forks source link

Precise synchronization of physical simulation problems #29

Closed ax-jason closed 7 years ago

ax-jason commented 7 years ago

First of all, what a wonderful lib!

As lua document mentioned about key / value pair table:

The order in which the indices are enumerated is not specified, even for numeric indices.

I see the source code has some operations on tables by using lua pairs method, which may lead to physical simulation is not accurate enough, such as the same physical starting conditions, the results of simulations may occur Subtle differences, so it would be a problem for those scenes who strictly require the same results of physical simulation.

To resolve this, can use arrary or some implementations which guarantees the order of the indices.

kikito commented 7 years ago

Hi there,

First of all, what a wonderful lib!

Thanks! :)

Precise synchronization of physical simulation problems

You might have missed an important bit near the beginning of the readme, where it says:

bump is not a good match for:

  • Games that require polygons for the collision detection
  • Games that require highly realistic simulations of physics

To begin with, you are right. bump.lua is not suitable for precise physics. But the reason for this is mainly the fact that objects move "one-at-a-time". This already makes certain scenarios behave differently than in a more "physically realistic" simulation, in which all objects "move at the same time". This is a design decision. There are other libraries out there which are a better fit for those scenarios. This is why I say bump.lua is for making gameistic games, not realistic ones.

To resolve this, can use arrary or some implementations which guarantees the order of the indices.

I can't stop using pairs on my code because a lot of the internal tables bump uses to store the state of the world are hash-like; the objects stored on them are keys, not values. This is for performance reasons. I guess I could store them in array-like structures, but it would be much less efficient to do certain things (if you think otherwise, feel free to send me a pull request ;))

That said, let me try to address your concern: the order in which things happen. You see, the main "list" that bump produces is the list of collisions generated by world:move. This method calls world:check, which in turn calls world:project.

world:project does this: Imagine the item moves "in a straight line" towards its goal, going through other objects, as if it was a ghost. world:project returns these objects. But crucially, it is sorts them out first first. The algorithm is:

When world:check gets this sorted list of collisions, it picks the first one (the one which usually happens "first"). Then it resolves it (potentially changing the actualX and Y in the process, as it would happen in a slide or a bounce), and then calls world:project again, who produces another sorted list of collisions. The first one is picked again, etc. And this is repeated again and again until there are no more objects available. There is a restriction in place so that the objects which have already produced a collision don't produce more on the same frame.

The result is that collisions happen in an "intuitive" (and almost deterministic) order. For example: let's imagine a Mario-like game in which Mario, in a single frame, touches both a star and some spikes. If the star is "closer" to Mario than the spikes, even by some fraction of a pixel, the star will always be activated first, and Mario will be invulnerable to the spikes. On the other hand, if the spikes are a bit closer than the star, they will be collided against first, and Mario will die. The "indeterminism" in this case would happen when the star and the spikes are exactly at the same distance (for example, if they are exactly on top of each other). If that case worries you, remember that you can sort the cols table however you want after you receive it from bump:move. You might want to resolve all the stars first. Or all the spikes first. Most of the time, it doesn't matter, because most of the time one will be closer than the other anyway.

This algorithm is good enough for games, and much more deterministic than "just using pairs". it is definitively not fit for accurate physics. But that was never the objective in the first place.

I think that writing all of the above in the readme would take lots of space and most bump users don't need such a detailed description. But now if anyone needs it, I can point them to this issue, so thanks :)

Let me close this issue. Feel free to reopen if you feel I haven't answered your questions.

ax-jason commented 7 years ago

Thank you for your quick and detailed answer! I do understand the whole thing now :)