Page 1 of 2

Need help with Bump.lua Filters

Posted: Wed Jul 31, 2024 10:15 pm
by dpkgluci
Ok I pretty much understand bump.lua completely, except filters. I'm trying to use the libraries STI and Bump.lua to work together and they do! but I want to add spikes to my tilemaps and I thought I add a custom property to the spike tiles like "isSpike" or something and if the player collides with it it would trigger another function

How do the <filter> in world:move

Code: Select all

local actualX, actualY, cols, len = world:move(item, goalX, goalY, <filter>)
and world:check

Code: Select all

local actualX, actualY, cols, len = world:check(item, goalX, goalY, <filter>)
works?

I tried putting "slide" and "cross" there but it gives me an error

Re: Need help with Bump.lua Filters

Posted: Thu Aug 01, 2024 12:25 am
by dpkgluci
update: I don't know how to set up the Type attribute of objects, and in the bump.lua docs it seems to need it for filters
do someone understand how to set up type? is it the same as Class in tiled?

Re: Need help with Bump.lua Filters

Posted: Thu Aug 01, 2024 5:10 pm
by cip
I've been recently using bump (which, like lots of LÖVE libraries, is very good!) and I think I can help you with this question:

From my understanding, in place of <filter> you can put a function there directly, as <filter> is already a function which returns one of the collision responses (from the tutorial, these are: cross, slide, touch, bounce).

If you set the spikes with a isSpike property to true (so self.isSpike = true when you initially create the spikes), you can iterate over the collisions like so,

Code: Select all

local actualX, actualY, cols, len = world:move(player, goalX, goalY, function(item, other) 
if other.isSpike == true then	
     return 'bounce'
  end	
end)
In this case, "other" is the sprite you are acting upon.

Also, you can iterate over the collisions,

Code: Select all

for i=1,len do
   local other = cols[i].other
   if other.isCoin then
      takeCoin(other)
   elseif other.isExit then
      changeLevel()
   elseif other.isSpring then
      highJump()
  end
end
If it helps, I am fairly certain that instead of checking against boolean properties of the objects (such as isCoin, isExit, etc) you can also use something like sprite.name == 'coin' or sprite.name == 'exit' (which, when querying for collisions using the code above would turn into other.name == 'coin' or other.name == 'exit'. So the Type attribute you are mentioning is an identifier which helps you and helps bump identify the sprites and their respective collision responses.

Please check out this thread as well,
viewtopic.php?t=87249

Re: Need help with Bump.lua Filters

Posted: Thu Aug 01, 2024 5:17 pm
by MrFariator
Ninja'd by cip, but posting my reply anyway.

Lets assume you have a player object like the following:

Code: Select all

local player = {
  x = 0,
  y = 0,
  w = 16,
  h = 16,
  isPlayer = true
}
-- insert the object into the world:
world:add (player, player.x, player.y, player.w, player.h)
Just a single table, as an example. As you see, we have "isPlayer" boolean in our player object, and that'll be used by our filters later.
Now, lets assume we create some bullet, perhaps with the following structure:

Code: Select all

local bullet = {
  x = 0,
  y = 0,
  w = 8,
  h = 8,
  isBullet = true,
}
-- insert again like before
world:add (bullet, bullet.x, bullet.y, bullet.w, bullet.h)
Now, when you want to update the bullet, and want to check it colliding against the player, you'd create a filter like the following:

Code: Select all

-- 'item' is the object we're currently updating, 'other' is the object we're colliding with
local function bulletFilter (item, other)
  if other.isPlayer then return 'touch' end
  -- add any other conditions here if desired, like checking for "isWall" or "isBullet"
end
You'd pass this function into world:move (or world:check) when updating your bullet object. If the bullet object collides with the player object, the collision will be returned, otherwise nothing happens.

Code: Select all

local newX, newY, cols, len = world:move (bullet, targetX, targetY, bulletFilter)

for i = 1, len do
  local other = cols[i].other
  if other.isPlayer then
    print("collided with player!")
  end
end
As such, to answer your question simply: the 'types' are just any arbitrary fields you might put into the objects you insert into the bump world. They could be numbers, booleans, strings or even tables. It's up to you what fields the filter functions might check.

Do note, that when using functions like world:queryRect, the filter functions use a simpler form:

Code: Select all

-- here, 'item' is whatever item in the world that the query'd area happened to touch
-- with these query filters, you simply need to return a truthy or falsy value
local function bulletQuery ( item )
  -- add others as desired
  return item.isPlayer
end

Re: Need help with Bump.lua Filters

Posted: Thu Aug 01, 2024 5:23 pm
by cip
MrFariator wrote: Thu Aug 01, 2024 5:17 pm Ninja'd by cip, but posting my reply anyway.

Lets assume you have a player object like the following:

Code: Select all

local player = {
  x = 0,
  y = 0,
  w = 16,
  h = 16,
  isPlayer = true
}
-- insert the object into the world:
world:add (player, player.x, player.y, player.w, player.h)
Just a single table, as an example. As you see, we have "isPlayer" boolean in our player object, and that'll be used by our filters later.
Now, lets assume we create some bullet, perhaps with the following structure:

Code: Select all

local bullet = {
  x = 0,
  y = 0,
  w = 8,
  h = 8,
  isBullet = true,
}
-- insert again like before
world:add (bullet, bullet.x, bullet.y, bullet.w, bullet.h)
Now, when you want to update the bullet, and want to check it colliding against the player, you'd create a filter like the following:

Code: Select all

-- 'item' is the object we're currently updating, 'other' is the object we're colliding with
local function bulletFilter (item, other)
  if other.isPlayer then return 'touch' end
  -- add any other conditions here if desired, like checking for "isWall" or "isBullet"
end
You'd pass this function into world:move (or world:check) when updating your bullet object. If the bullet object collides with the player object, the collision will be returned, otherwise nothing happens.

Code: Select all

local newX, newY, cols, len = world:move (bullet, targetX, targetY, bulletFilter)

for i = 1, len do
  local other = cols[i].other
  if other.isPlayer then
    print("collided with player!")
  end
end
As such, to answer your question simply: the 'types' are just any arbitrary fields you might put into the objects you insert into the bump world. They could be numbers, booleans, strings or even tables. It's up to you what fields the filter functions might check.

Do note, that when using functions like world:queryRect, the filter functions use a simpler form:

Code: Select all

-- here, 'item' is whatever item in the world that the query'd area happened to touch
-- with these query filters, you simply need to return a truthy or falsy value
local function bulletQuery ( item )
  -- add others as desired
  return item.isPlayer
end
@MrFariator, your answer is more comprehensive, and more replies is always better :D

Re: Need help with Bump.lua Filters

Posted: Thu Aug 01, 2024 6:29 pm
by dpkgluci
Hi! This seems pretty understandable, But I'm using STI to get the collisions, and I'm trying to make a filter that somehow returns slide on ground (or everything) and "cross" when player touches a spike

Code: Select all

local collidablefilter = function(_, other)
  if other.base == "ground" then
    return "slide"
  elseif other.base == "spike" then
    return "cross"
  else
    return "slide"
  end
end
It always returns slide, and apparently it is not because the last else but the first, it seems like the other.base is strangely defined

I am trying to set a custom property in the spike objects in tiled.
I created a new layer "spike" and inside, there are objects (that have collidable=true) and a "base" property (string) set to "spike" but the filter seems to not read it

Re: Need help with Bump.lua Filters

Posted: Thu Aug 01, 2024 7:29 pm
by MrFariator
If in doubt, try printing your object's 'base' field before inserting it into the bump world (ie. just print "myObj.base" and see what it prints). If it's undefined (nil) or a non-string value, your filter will return 'slide' in all cases. If it's undefined, you're not importing that information from your tiled maps.

Edit: also, in your case, check if there are any overlapping tiles that have 'base' set to 'ground. If such tiles lie atop/below your spikes, the 'ground' tiles will take priority due to the 'slide' result.

Re: Need help with Bump.lua Filters

Posted: Thu Aug 01, 2024 8:13 pm
by cip
Could it be that the spike is over a ground tile (which has a 'slide' response') and the player always collides first with the ground tile? I don't have experience with STI, so I'm not really sure what advice to give.

But I agree with MrFariator, printing the object's base property might get you closer to the answer.

EDIT: had to edit my answer, as I mixed the spike and ground tiles and their collision responses.

Re: Need help with Bump.lua Filters

Posted: Thu Aug 01, 2024 8:21 pm
by dpkgluci
I printed it but got nil, and the ground tile above the spike is impossible since the player is standing on top of a spike, it doesnt touch any ground tiles

But I resolved this! I used the type (class) property! it's not a custom property, but you can put strings on it, so I marked all my spike boxes with spike and all my ground ones with ground and now with this filter

Code: Select all

local collidablefilter = function(_, other)
  if other.type == "spike" then
    return "cross"
  elseif other.type == "ending" then
    return "slide"
  elseif other.type == "coin" then
    return "cross"
  else
    return "slide"
  end
end

Re: Need help with Bump.lua Filters

Posted: Thu Aug 01, 2024 8:31 pm
by MrFariator
If it printed nil, then perhaps you weren't reading the 'base' property from the tiled map, and setting it to your tile objects accordingly before inserting them to the bump world. I've never used STI, so I wouldn't know how that part should be done, but seems like your solution achieves much of the same result.