Search code examples
fluttercollision-detectionflame

Precision in onCollisionStart in flame with flutter


I'm attempting to write a bouncing ball game using flame in flutter. To detect collisions the onCollision and onCollisionStart methods are provided. What I had hoped is that onCollisionStart would give a precise location when two objects first hit each other. However, instead it gives a list of positions indicating where the two objects overlap after the first game-tick when this happens (i.e. onCollisionStart is called at the same time as onCollision, but is not called a second time if the same two objects are still colliding on the next tick).

An example of a collision issue

This is illustrated in the attached picture. The collision points are marked with red dots. If the ball were moving downwards, then the ball would have hit the top of the rectangle and so should bounce upwards. However, if the ball were moving horizontally, then its first point of contact would have been the top left corner of the box, and the ball would bounce upwards and to the left.

If I want to work out correct angle that the ball should fly off, then I would need to do some clever calculations to work out the point that the ball first started hitting the other object (those calculations would depend on the precise shape of the other object). Is there some way to work out the point at which the two objects first started colliding? Thanks


Solution

  • What you usually need for this is the normal of the collision, but unfortunately we don't have that for the collision detection system yet. We do have it in the raytracing system though, so what you could do is send out a ray and see how it will bounce and then just bounce the ball in the same way.

    If you don't want to use raytracing I suggest that you calculate the direction of the ball, which you might already have, but if you don't you can just store the last position and subtract it from the current position.

    After that you need to find the normals of the edges where the intersection points are.

    Let's say the ball direction vector is v, and the two normal vectors are n1 and n2.

    Calculate the dot product (this is build in to the vector_math library) of the ball direction vector and each of the normal vectors:

    dot1 = v.dot(n1)
    dot2 = v.dot(n2)
    

    Compare the results of the dot products:

    If dot1 > 0, n1 is facing the ball.
    If dot2 > 0, n2 is facing the ball.
    

    After that you can use v.reflect(nx) to get the direction where your ball should be going (where nx is the normal facing the ball).

    Hopefully we'll have this built-in to Flame soon!