Detecting Multiple Collisions per Frame

So I did some more work on this and discovered that when colliding with a corner, it’s actually detecting the following tiles:

19:50:29.287 x=304, y=144

19:50:29.287 x=304, y=112

19:50:29.287 x=304, y=80

So basically if the following is a corner with the “O” being the player and each “[]” a tile with the arrow indicating the player’s direction:

        []

–>O []

    [] []

Only collisions with the three tiles on the right are detected, not the one underneath. So now I’m completely lost as to how I can even figure out that that tile is there before the player literally goes right through it.

If it helps here’s my new code with the queue system:

[lua]local function collisionEvent(event)
  local obj1 = event.object1;
  local obj2 = event.object2;

  local other;

  if obj1.type == “player” then
   other = obj2;
  else
   other = obj1;
  end

  if (event.phase == “began”) and (instance.isAligned) and (other.type == “wall”) then

   table.insert(collidingTiles, other);
  end
 end
 
 local function frameEvent(event)  
  if instance.direction > DIR_NONE then  
   for _, v in pairs(collidingTiles) do   
    if (v.x == instance.x) and (v.y <= instance.y) then
     instance.collides[DIR_UP] = true;
    end
    
    if (v.y == instance.y) and (v.x >= instance.x) then
     instance.collides[DIR_RIGHT] = true; 
    end
    
    if (v.x == instance.x) and (v.y >= instance.y) then
     instance.collides[DIR_DOWN] = true; 
    end
    
    if (v.y == instance.y) and (v.x <= instance.x) then
     instance.collides[DIR_LEFT] = true;
    end
   end
  
   if (instance.isAligned) and (not instance.collides[instance.desiredDirection]) then
    instance.direction = instance.desiredDirection;
   end
   
   if not instance.collides[instance.direction] then
    if (instance.direction == DIR_UP) then
     instance.y = instance.y - 2;
    elseif (instance.direction == DIR_RIGHT) then
     instance.x = instance.x + 2;
    elseif (instance.direction == DIR_DOWN) then
     instance.y = instance.y + 2;
    else
     instance.x = instance.x - 2;
    end

    collidingTiles = {};

   end
  end

  if ((instance.x - 16)%32 == 0) and ((instance.y - 16)%32 == 0) then
   instance.isAligned = true;
  else
   instance.isAligned = false;
  end
 end[/lua]

Hi @danielbeer1376,

I’m a bit confused: if your walls (tiles) are static physics objects, and your player is a dynamic physics object, the player simply won’t be allowed to “pass through” the walls… unless you made the player a sensor object, walls sensor objects, or something else (which I doubt that you did).

Do you want to use some kind of in-advance detection which prevents the player from even turning in a particular direction, if there’s a wall in that direction?

It would be great to have detection in advance if that’s possible. Basically I’m making a maze game and don’t want to the player to go through the walls. And yes, right now the walls are sensors :stuck_out_tongue: since the player was shaking back and forth between the walls earlier and I couldn’t get that to stop. I have a feeling there’s a better way but I couldn’t find one. And yes, the walls are static and the player is dynamic

Hmmm… player was “shaking”? Did you set the “bounce” level of both the player and wall objects to 0?

Yes I did. It still made the player vibrate back and forth and then get stuck about 2px into the walls that were in its path. That’s why I switched to sensors originally

Hmmm… I assume then the vibrate was because you continued putting physical velocity/force on the player even after he collided with a wall?

Does your player “turn” (as in the actual object turns/rotates) to face the direction it’s going?

Right now my player is a one frame circle with no gravity and only its x and y-values being modified (+2 per frame)

OK, if the player will eventually turn to face the direction it’s travelling, I suggest another solution. It’s a tiny bit more work, but it should improve this scenario considerably. Basically, create the player as a 2-element physics body: first element is the main body (circle) and the second element is a smaller “face sensor” which emerges just a few pixels beyond the physical bounds of the player (see attached image).

This guide explains how to properly create multi-element bodies:

https://docs.coronalabs.com/guide/physics/physicsBodies/index.html#multi-element-bodies

The main body can be a non-sensor, but the smaller emerging rect part should be a sensor.

From here, basically, you use per-element collision detection according to this guide:

https://docs.coronalabs.com/guide/physics/collisionDetection/index.html#multi-element-collisions

Now when dealing with sensors overlapping something, you should use the “began” phase of the collision (on just the “face sensor” element!) to detect that point in time when it overlaps or “enters” the object it’s overlapping. Conversely, you can use the “ended” phase of the collision to detect when the face sensor has exited the wall object it’s overlapping.

These two phase aspects are critical because, during the “began” one, you will need to explicity set the player’s linear velocity to 0,0 and code some method to prevent any further application of velocity or force upon the player in the direction of the wall it’s facing.

Now, if we imagine the player has contacted a wall to its right, but there is a clear path above, then you would allow the player to turn (face) upward or something like that. At that point, the “face sensor” has exited the wall to the right, triggering an “ended” phase, which means that you’re clear to apply velocity in the new direction (up).

This probably sounds more complicated than it really is. :slight_smile: Basically, the concept is that you’re using that extra sensor element, which always “leads” in front of the direction the player is going, to detect when it hits a wall. When it does, you know that the player can’t move any further in that direction, so you stop its linear velocity and prevent any further movement in that direction. Other directions are, of course, still allowed, until the sensor contacts another wall, and then you prevent further movement in that direction.

Hope this helps somewhat,

Brent

P.S. - applying a direct linear velocity might be better (smoother looking) than moving the player by 2 pixels in each direction. You’d have to experiment to find what suits your game best.

https://docs.coronalabs.com/api/type/Body/setLinearVelocity.html

Didn’t do that exactly but the suggestion definitely got me on the right track and this is now fixed. Thanks so much

Great to hear! As usual, there’s more than one way to solve almost any issue, and my suggestion was just one. Good to hear it helped you along the way. Any other issues, please just post.

Brent