Hardon Collider problem on restart

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
Ulydev
Party member
Posts: 445
Joined: Mon Nov 10, 2014 10:46 pm
Location: Paris
Contact:

Hardon Collider problem on restart

Post by Ulydev »

Hello, everyone !

I'm actually trying to create a simple platformer using HardonCollider.

Basically, I'd need to get the collision sides for the function I'm implementing. This said, I was thinking about doing some comparison between the mtv_x et mtv_y values that are passed in the collision callback. Unfortunately, this vector is not displayed properly at all. I was not expecting empty values, is this a bug or me doing something wrong ?



https://www.dropbox.com/s/glsd6xwzcag7u ... .love?dl=1

Thanks in advance for your answers, and have a nice evening.
Last edited by Ulydev on Tue Jul 14, 2015 12:44 pm, edited 1 time in total.
User avatar
Ulydev
Party member
Posts: 445
Joined: Mon Nov 10, 2014 10:46 pm
Location: Paris
Contact:

Re: Hardon Collider "resolve vector" behaving strangely

Post by Ulydev »

I found a simple temporary "fix", using Minkowski's algorithm.

Here's the Lua implementation

Code: Select all

function getCollisionSide(A, B)
  local side = 1 --1 down - 2 left - 3 up - 4 right
  local x1, y1 = A:center()
  local x2, y2 = B:center()
  local w = 0.5 * (A.width + B.width);
  local h = 0.5 * (A.height + B.height);
  local dx = x1 - x2;
  local dy = y1 - y2;

  local wy = w * dy
  local hx = h * dx

  if (wy > hx) then
    if (wy > -hx) then
      side = 3
    else
      side = 2
    end
  else
    if (wy > -hx) then
      side = 4
    else
      side = 1
    end
  end
  return side
end
If someone got a cleaner workaround, though, please share it !
User avatar
Ulydev
Party member
Posts: 445
Joined: Mon Nov 10, 2014 10:46 pm
Location: Paris
Contact:

Re: Hardon Collider "resolve vector" behaving strangely

Post by Ulydev »

Hi, it's me again ! I've got another problem / question that I prefer to ask here rather than opening a new thread.

I have two players (with their own collider) that can jump on each other's head. But there's always a "victim" which is not allowed to jump on the other's head and pushes it instead. Just like in this gif :

Image

The "victim" always changes when I restart the game. Here's my collision manager :

Code: Select all

function touchGround(obj)
  obj.ref.isGrounded = true
  obj.ref.isJumping = false
end

function stopTouchingGround(obj)
  obj.ref.isGrounded = false
end

function getCollisionSide(A, B, mtv_x, mtv_y)
  local side = 1 --1 down - 2 left - 3 up - 4 right
  local x1, y1 = A:center()
  if mtv_x then x1, y1 = x1 + mtv_x, y1 + mtv_y end
  local x2, y2 = B:center()
  local w = 0.5 * (A.width + B.width);
  local h = 0.5 * (A.height + B.height);
  local dx = x1 - x2;
  local dy = y1 - y2;

  local wy = w * dy
  local hx = h * dx

  if (wy > hx) then
    if (wy > -hx) then
      side = 3
    else
      side = 2
    end
  else
    if (wy > -hx) then
      side = 4
    else
      side = 1
    end
  end
  return side
end

function onCollide(dt, obj1, obj2, mtv_x, mtv_y)
  if obj1.name == "player" or obj2.name == "player" then

    --player is always refered as "obj1"
    if obj2.name == "player" then local tObj = obj1; obj1 = obj2; obj2 = tObj; mtv_y = -mtv_y+0.001; mtv_x = -mtv_x end

    local collisionSide = Gravity:convertCollisionSide(getCollisionSide(
        obj1,
        obj2,
        mtv_x,
        mtv_y), obj1.ref.gravity) --1 down - 2 left - 3 up - 4 right

    mtv_x = mtv_x - math.sign(mtv_x)*0.005
    mtv_y = mtv_y - math.sign(mtv_y)*0.005
    
    local x1, y1 = obj1:center()
    local x2, y2 = obj2:center()
    
    
    print(collisionSide)
    
    if collisionSide == 1 then
      if obj2.name == "player" then
        obj1.ref:jump("bump") 
      else
        obj1:move(mtv_x, mtv_y)
        touchGround(obj1)
      end
    elseif collisionSide == 2 or collisionSide == 4 then
      obj1:move(mtv_x, mtv_y)
      if Gravity:getAxis(obj1.ref.gravity) == "y" then obj1.ref.velocity.x = 0 else obj1.ref.velocity.y = 0 end
    elseif collisionSide == 3 then
      obj1:move(mtv_x, mtv_y)
      if Gravity:getAxis(obj1.ref.gravity) == "y" then obj1.ref.velocity.y = 0 else obj1.ref.velocity.x = 0 end
    end

  end
end

function onStopCollide(dt, obj1, obj2)
  if obj1.name == "player" or obj2.name == "player" then
    
    if obj2.name == "player" then local tObj = obj1; obj1 = obj2; obj2 = tObj end
    
    local collisionSide = Gravity:convertCollisionSide(getCollisionSide(obj1, obj2), obj1.ref.gravity) --1 down - 2 left - 3 up - 4 right
    
    print("end collision side : "..collisionSide)
    
    --if collisionSide == 1 then
      stopTouchingGround(obj1)
    --end
    
  end
end
I really don't understand what happens here... Thank you in advance for your help ;)
User avatar
DaedalusYoung
Party member
Posts: 407
Joined: Sun Jul 14, 2013 8:04 pm

Re: Hardon Collider "resolve vector" behaving strangely

Post by DaedalusYoung »

I didn't really look at your code, so I don't know what's causing your issue, but I just wanted to point out that this:
Ulydev wrote:

Code: Select all

    local tObj = obj1; obj1 = obj2; obj2 = tObj;
can be written easier like this:

Code: Select all

    obj1, obj2 = obj2, obj1 -- swaps obj1 and obj2
User avatar
Ulydev
Party member
Posts: 445
Joined: Mon Nov 10, 2014 10:46 pm
Location: Paris
Contact:

Re: Hardon Collider "resolve vector" behaving strangely

Post by Ulydev »

can be written easier like this:

Code: Select all

    obj1, obj2 = obj2, obj1 -- swaps obj1 and obj2
Thanks, that's appreciated ;)
User avatar
Positive07
Party member
Posts: 1014
Joined: Sun Aug 12, 2012 4:34 pm
Location: Argentina

Re: Hardon Collider problem on restart

Post by Positive07 »

First: Can you upload a .love file? that would be appreciated since it will make the problem clearer, I cant know what obj1 and obj2 are if I cant take a look at other parts of the code

Any way I have some ideas of what could be happening my first option is that both obj1 and obj2 are "player" so obj2 is the only one that can handle the collisions, my second option is pretty similar, basically you are not handling what happens if what you suppose is the "victim" is actually the "perpetrator" (that is, the one jumping on top of the other is the "victim") so the perpetrator which is not suppose to suffer a collision from the top just slides to the other side like if it was being moved

NOTE: The "victim" changes every time you start up the game because the order in which pairs traverses a table is not defined)
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
User avatar
Ulydev
Party member
Posts: 445
Joined: Mon Nov 10, 2014 10:46 pm
Location: Paris
Contact:

Re: Hardon Collider problem on restart

Post by Ulydev »

Thanks for your answer, Positive07.

You were right, I was able to fix the problem by handling the collision twice for each player. It's pretty ugly, but it works for now :nyu:
User avatar
Positive07
Party member
Posts: 1014
Joined: Sun Aug 12, 2012 4:34 pm
Location: Argentina

Re: Hardon Collider problem on restart

Post by Positive07 »

Cool! Could you show us the fix? Would be nice for future users that may stumble with the same issue
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
User avatar
Ulydev
Party member
Posts: 445
Joined: Mon Nov 10, 2014 10:46 pm
Location: Paris
Contact:

Re: Hardon Collider problem on restart

Post by Ulydev »

Indeed !

Code: Select all

if obj2.name == "player" then --both objects are players
      local collisionSide2 = Gravity:convertCollisionSide(getCollisionSide(
        obj2, obj1,
        -mtv_x,
        -mtv_y), obj2.ref.gravity) --get object 2 side (we already got object 1 side earlier)
      if collisionSide == 1 then
        if collisionSide2 == 1 then
          obj1:move(mtv_x*.5, mtv_y*.5)
          obj2:move(-mtv_x*.5, -mtv_y*.5)
        else
          obj1.ref:jump("bump") 
          obj2.ref:kill()
          obj1:move(0, mtv_y*.5)
          if not obj2.ref.isGrounded then
            obj2:move(0, -mtv_y*.5)
          end
        end
        --obj1:move(0, mtv_y)
        --obj2:move(0, -mtv_y)
      elseif collisionSide == 2 or collisionSide == 4 then
        if collisionSide2 == 1 then
          obj2.ref:jump("bump")
          obj1.ref:kill()
        elseif collisionSide2 == 3 then
          obj1:move(mtv_x*.5, mtv_y*.5)
          obj2:move(-mtv_x*.5, -mtv_y*.5)
        else
          obj1:move(mtv_x*.5, mtv_y*.5)
          obj2:move(-mtv_x*.5, -mtv_y*.5)
        end
        --obj1.ref:jump("bump")
        --obj2.ref:kill()
        --local tempDir = boolInt(collisionSide == 2)*2-1
        --obj1:move(mtv_x, 0)--mtv_y)
        --obj2:move(-mtv_x, 0)--mtv_y)
      elseif collisionSide == 3 then
        --obj1:move(0, mtv_y)
        --obj2:move(0, -mtv_y)
        if collisionSide2 == 1 then
          obj2.ref:jump("bump")
          obj1.ref:kill()
          obj2:move(0, -mtv_y*.5)
          if not obj1.ref.isGrounded then
            obj1:move(0, mtv_y*.5)
          end
        else
          obj1:move(mtv_x*.5, mtv_y*.5)
          obj2:move(-mtv_x*.5, -mtv_y*.5)
        end
      end
    else --handle normal collision between player and object
Basically, every time you check collision between, say, side A and side B, you also have to check collision between side B and side A.
User avatar
Positive07
Party member
Posts: 1014
Joined: Sun Aug 12, 2012 4:34 pm
Location: Argentina

Re: Hardon Collider problem on restart

Post by Positive07 »

Does this work? It should be the same, just a little bit cleaner

Code: Select all

function kill (killer, victim, move)
    killer.ref:jump("bump")
    victim.ref:kill()
    if move then
        killer:move(0, move * mtv_y*.5)
        if not victim.ref.isGrounded then
            victim:move(0, move * -mtv_y*.5)
        end
    end
end

function move (obj1, obj2)
    obj1:move(mtv_x*.5, mtv_y*.5)
    obj2:move(-mtv_x*.5, -mtv_y*.5)
end

if obj2.name == "player" then --both objects are players
    local collisionSide2 = Gravity:convertCollisionSide(getCollisionSide(
    obj2, obj1,
    -mtv_x,
    -mtv_y), obj2.ref.gravity) --get object 2 side (we already got object 1 side earlier)
    if collisionSide == 1 then
        if collisionSide2 == 1 then
            move(obj1, obj2)
        else
            kill(obj1, obj2, 1)
        end
    elseif collisionSide == 2 or collisionSide == 4 then
        if collisionSide2 == 1 then
            kill(obj2, obj1)
        elseif collisionSide2 == 3 then
            move(obj1, obj2)
        end
    elseif collisionSide == 3 then
        if collisionSide2 == 1 then
            kill(obj2, obj1, -1)
        else
            move(obj1, obj2)
        end
    end
else --handle normal collision between player and object
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 134 guests