[library] bump.lua v3.1.4 - Collision Detection

Showcase your libraries, tools and other projects that help your fellow love users.
pevzi
Prole
Posts: 27
Joined: Tue Apr 02, 2013 4:09 pm
Contact:

Re: [library] bump.lua v3.1.4 - Collision Detection

Post by pevzi »

Sorry for the lack of response from me and thanks for your suggestions.
I've considered something like pgimeno's solution but using querySegment instead of queryRect (didn't try it yet but it seems possible in my mind at least). I thought maybe I was missing some really simple and concise solution but apparently there's no way to evade that bunch of repetitive queries anyway. Thanks again for a comprehensive example, pgimeno.
The grid alignment is a curious approach but it doesn't look like it is the one that is used in The Minish Cap. The player's movement there feels free of any constraints.
User avatar
Jasoco
Inner party member
Posts: 3725
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: [library] bump.lua v3.1.4 - Collision Detection

Post by Jasoco »

What I was thinking is that when one rectangle hits another, it should first check how much of an overlap there is. If it's only a few pixels, then shift the character rectangle to the left or right so it lines up with the edge of what it's colliding with but preserve the momentum so as to not stop them short. Or instead of instantly shifting them, push them one pixel at a time but preserve the momentum anyway.

I should try and see if this actually works by implementing it into my own engine.
User avatar
pgimeno
Party member
Posts: 3548
Joined: Sun Oct 18, 2015 2:58 pm

Re: [library] bump.lua v3.1.4 - Collision Detection

Post by pgimeno »

pevzi wrote:I've considered something like pgimeno's solution but using querySegment instead of queryRect
I'm not sure but it seems to me that this would be slower, assuming you aim for the same strategy. Axis-aligned rectangles are very fast and easy to check; the segments in bump, however, are not constrained to be axis-aligned and need some extra math to be dealt with. I may be wrong, though.
User avatar
pgimeno
Party member
Posts: 3548
Joined: Sun Oct 18, 2015 2:58 pm

Skirting around corners demo

Post by pgimeno »

pgimeno wrote:I've made a proof of concept of what I meant. Sorry it took this long.

I thought bump would have support for moving multiple rectangles as a unit, but that doesn't seem to be the case, so I reworked the idea to use bump's queryRect. In total it requires checking at most three rectangles each pass. It can be made better by making it stick to the wall once it's around the corner, but that's not the focus of this demo.

Rather than using half the character width as a fixed margin, the margin is adjustable.
I've just realized that I forgot to bundle bump.lua in the .love file that I attached, and LÖVE didn't complain when I tested because it found it in the current directory. Sorry about that. Updated attachment:
Attachments
corners.love
(7.98 KiB) Downloaded 229 times
Tassilo
Prole
Posts: 14
Joined: Wed Jun 29, 2016 9:23 am
Contact:

Re: [library] bump.lua v3.1.4 - Collision Detection

Post by Tassilo »

Hey everybody.
First of all, let me thank you guys for these fantastic libraries. Definitely one of love's major advantages.
Alas, I am having a problem with bump right now (using it alongside STI for a tilebased top-down game).

This is -abbreviated - what I have:

Code: Select all

    world:add(layer.player, layer.player.x, layer.player.y, layer.player.w, layer.player.h)
    
    function layer:update(dt)
        if love.keyboard.isDown("w") or love.keyboard.isDown("up") then
            local actualX, actualY, cols, len = world:move(self.player, 0,-96)
            print("Player.x/.y: "..self.player.x.."x"..self.player.y)
            print("Returned from world:move: "..actualX.."x"..actualY)
        end
    
I would expect this to return (at least almost) identical values. Instead, what I get is this:
Player.x/.y: 1728x1536
Returned from world:move: 1641x1468


The first values are what is expected to be get from the tiled-data. But I have no clue where the divergent values from world:move are coming from. They actually stay the same no matter what I put into world:add and don't seem to be found anywhere in the project. Any idea what I might be doing wrong here?
Thanks a lot!
Tassilo
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: [library] bump.lua v3.1.4 - Collision Detection

Post by kikito »

The problem seems to be the 0, -96 parameters that you are passing to world:move. By doing so you are telling bump "on this frame, try to move the player from where it is to 0,96 (colliding with whatever it should along the way)".

Instead, you should pass it the point where the player "will try to move on the current frame". This is usually the position it had in the previous frame + (the velocity it is moving along the x or y axis) * dt. It is usually not a fixed point like 0,96.
When I write def I mean function.
Tassilo
Prole
Posts: 14
Joined: Wed Jun 29, 2016 9:23 am
Contact:

Re: [library] bump.lua v3.1.4 - Collision Detection

Post by Tassilo »

Oh stupid me, absolute, not relative! Thanks so much, that solved it.
meowman9000
Prole
Posts: 15
Joined: Thu Mar 10, 2016 3:47 pm

Re: [library] bump.lua v3.1.4 - Collision Detection

Post by meowman9000 »

I'm messing around with the love2d bunnymark, adding collision detection to it. According to debugging I did the latest Bunny is being correctly checked for collision, showing 0 when nothing is around, however their direction changes erratically as if they are colliding with something.

The collision is at the bottom of the update method. Any ideas?

Code: Select all

------------------------------------------------
-- Modules
------------------------------------------------
local bump = require 'bump'
------------------------------------------------
-- Base functions
------------------------------------------------
function love.load()
    world = bump.newWorld()
    
    
    bunnies = {}
    gravity = 0.98
    
    maxX = love.graphics.getWidth( )
    minX = 0
    maxY = love.graphics.getHeight( )
    minY = 0

   

    baseLitterSize = 1
    litterSizeIncrement = 1
    litterSize = baseLitterSize
    
    stdOutText = ""

    bunnyCount = 0

    bunnyImg = love.graphics.newImage("bunny2.png")

    spriteBatch = love.graphics.newSpriteBatch( bunnyImg, 50000 )
end

function love.draw()
    spriteBatch:clear()
    love.graphics.print(bunnyCount .. " Total Bunnies", 20, 10)
    
    love.graphics.print(litterSize .. " bunnies in each Litter", 20, 20)
    
    love.graphics.print("Current FPS: "..tostring(love.timer.getFPS( )), 20, 30)    
    
    for index,value in ipairs(bunnies) do
        local tempBunnyId = value[1]
        local tempBunnyPosX = value[2]
        local tempBunnyPosY = value[3]


	spriteBatch:add(tempBunnyPosX,tempBunnyPosY)
    end
    
    spriteBatch:flush()
        love.graphics.draw(spriteBatch, 0, 0)
    
    
end


function love.update(dt)
    
    left = love.mouse.isDown(1)
    if left == true then
        for variable = 1, litterSize, 1 do
            procreate(love.mouse.getX( ), love.mouse.getY( ))
	    end
    end
    
    
    
    for index,value in ipairs(bunnies) do
        local tempBunnyId = value[1]
        local tempBunnyPosX = value[2]
        local tempBunnyPosY = value[3]
        local tempBunnySpeedX = value[4]
        local tempBunnySpeedY = value[5]
        tempBunnyPosX = tempBunnyPosX + tempBunnySpeedX;    
        tempBunnyPosY = tempBunnyPosY + tempBunnySpeedY;

        tempBunnySpeedY = tempBunnySpeedY + gravity;
        tempBunnyPosX=tempBunnyPosX+math.random(-30,30);
        if (tempBunnyPosX > maxX) then
            tempBunnySpeedX = tempBunnySpeedX * -0.9;
            tempBunnyPosX = maxX;
        elseif (tempBunnyPosX < minX) then
            tempBunnySpeedX = tempBunnySpeedX * -0.9;
            tempBunnyPosX = minX;
        end
        
        if (tempBunnyPosY > maxY) then
            tempBunnySpeedY = tempBunnySpeedY * -0.9;
            tempBunnyPosY = maxY;
        elseif (tempBunnyPosY < minY) then
            tempBunnySpeedY = tempBunnySpeedY * -0.9;
            tempBunnyPosY = minY;
        end
        
        
	local len = 0;
	local actualX, actualY, cols, len = world:check(bunnies[index][1]);
	if len > 10 then
            tempBunnySpeedX = tempBunnySpeedX * math.random(-1.01,-1.10)
        end
	

       	world:update(tempBunnyId,tempBunnyPosX,tempBunnyPosY);
      
        -- push all values back in the tables
	bunnies[index][1] = tempBunnyId
	bunnies[index][2] = tempBunnyPosX
	bunnies[index][3] = tempBunnyPosY
	bunnies[index][4] = tempBunnySpeedX
	bunnies[index][5] = tempBunnySpeedY

    end
end
function love.quit()
    stdOutPrint("Quitting app!")
end
------------------------------------------------
-- Custom functions
------------------------------------------------

function procreate(x,y) -- this function creates a new bunny
    bunnyCount = bunnyCount + 1
    local bunnyId = bunnyCount
    local bunnyPosX = x
    local bunnyPosY = y
    local bunnySpeedX = (math.random() * 10) - 5  
    local bunnySpeedY = (math.random() * 10) - 5  
    local bunny = {bunnyId, bunnyPosX, bunnyPosY, bunnySpeedX, bunnySpeedY }
    
    
    table.insert(bunnies, bunny)
    world:add(bunnyId, bunnyPosX, bunnyPosY, 70, 100)
end

------------------------------------------------
-- Utils. Toolbelt stuff needed to run this app
------------------------------------------------

------------------------------------------------
-- Debug. Stuff here gets removed after debugging is done
------------------------------------------------

function stdOutPrint(text)
    stdOutText = text
    print(text)
end

function table.val_to_str ( v )
  if "string" == type( v ) then
    v = string.gsub( v, "\n", "\\n" )
    if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
      return "'" .. v .. "'"
    end
    return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
  else
    return "table" == type( v ) and table.tostring( v ) or
      tostring( v )
  end
end 

function table.key_to_str ( k )
  if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
    return k
  else
    return "[" .. table.val_to_str( k ) .. "]"
  end
end

function table.tostring( tbl )
  local result, done = {}, {}
  for k, v in ipairs( tbl ) do
    table.insert( result, table.val_to_str( v ) )
    done[ k ] = true
  end
  for k, v in pairs( tbl ) do
    if not done[ k ] then
      table.insert( result,
        table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
    end
  end
  return "{" .. table.concat( result, "," ) .. "}"
end
Attachments
love2d-bunnymark-patch-2.zip
(80.78 KiB) Downloaded 183 times
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: [library] bump.lua v3.1.4 - Collision Detection

Post by kikito »

It would be easier to help you if you described what you want to happen when the bunnies collide. Right now your code says "when a bunny is colliding with 10 other bunnies or more, change its x speed randomly" (there's a math.random there). Since you are not using dt to make this calculation I expect it to be quite severe. That's probably where your "erratic movement" comes from.

I must warn you that if your objective is to make all the bunnies "collide with each other", without never overlapping, bump is not particularly suited for that. This is by design - bump resolves collisions in order, and only moving one item each time. So collisions which require "moving a first object, which moves a second, wich moves a third, which then move the first one" are not provided out-of-the-box. You would have to code that yourself, and it is tricky.

On the other hand, if you make some ground or some scenery, and you want the bunnies to collide with it, without colliding with each other, that should work well with bump.
When I write def I mean function.
meowman9000
Prole
Posts: 15
Joined: Thu Mar 10, 2016 3:47 pm

Re: [library] bump.lua v3.1.4 - Collision Detection

Post by meowman9000 »

Okay I see now what I've done, thanks for the help. Sorry for cluttering up your post.

:cry:

I was simply trying to make it so a colliding bunny would change direction if it intersected, unfortunately I left an X movement in the code.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 31 guests