Because shapes are really just Lua tables, you can add any custom information to them. This can be used to build an arbitrarily complex collision dispatching system atop of the callbacks. See for example my GPN11 gamejam entry (beware of the old api though). Relevant bits and pieces:
Collision callbacks
collidable.lua - collidable mixins
bomb.lua - catchall ("*") collision response
scrap.lua - individual response depending on other shape type
Creating and removing shapes from HardOnCollider on the fly
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Re: Creating and removing shapes from HardOnCollider on the
Cool, I'll have a look. Thank you!
EDIT: I fixed the problem explained below by making Spiral enter the wall 1 pixel. I don't know why it's neccessary but now it works, so I'll assume it's a Hardon "feature" (lol).
By the way, vldr, I'd appreciate a lot if you could bring some light to my current problem. I'm detecting collisions with floor, ceiling and walls with this function (the most optimized I've been able to do so far), but you can skip it for now (I copied it just in case you want to check if it's wrong):
Thus, when none of the negihbours belong to the group I'm checking, I return false. This works like a charm except for the walls collision, that gets walls at left side of the player perfectly but not always at its right side. The function I'm using for detecting walls is (you can skip this one as well and just have a look to the next chunk):
The insteresting part is just this (don't skip this one now, hehe):
Sometimes it detects the wall at right correctly, but sometimes not, so I put those two prints to get the values to try to debug the problem. Surprisingly, the values I get should get the colision and not print anything, but they don't. You can see it in the attachment. Explanation:
SPX1, SPX2 = Spiral (player) bounding box x1 and x2.
SHX1, SHX2 = the shape's bounding box x1 and x2. It's a wall shape (otherwise the message wouldn' be printed).
In the game window you can see "WALLS: false". This prints "left" or "right" if a wall is detected.
As you can see in the picture, the player's bounding box is next to the right wall, spX2 == shX1 (=1024) and spX1 < shX1. With these values, it should enter the "if", not the "else", so I wonder what's wrong.
I've tried with many alternatives (getting collisions with ALL shapes from the "walls" group, for instance), but the result is the same :S
I've attached the project if you need to have a look at the code.
EDIT: I fixed the problem explained below by making Spiral enter the wall 1 pixel. I don't know why it's neccessary but now it works, so I'll assume it's a Hardon "feature" (lol).
By the way, vldr, I'd appreciate a lot if you could bring some light to my current problem. I'm detecting collisions with floor, ceiling and walls with this function (the most optimized I've been able to do so far), but you can skip it for now (I copied it just in case you want to check if it's wrong):
Code: Select all
--********************************************************
-- spiral:collidingWith
--********************************************************
function spiral:collidingWith(what) -- what can be "floor", "ceiling" and "walls"
local neighbors = spiral.bbox:_getNeighbors()
for _,shape in pairs(neighbors) do
for group, _ in pairs(shape._groups) do
if (group == what) then
if (what == "floor" and spiral:collidingWithFloor(shape)) then
return true
end
if (what == "ceiling" and spiral:collidingWithCeiling(shape)) then
return true
end
if (what == "walls") then
local wall = spiral:collidingWithWalls(shape)
if (wall) then return wall end
end
end
end
end
return false
end
Code: Select all
--********************************************************
-- spiral:collidingWithWalls
--********************************************************
function spiral:collidingWithWalls(shape)
local spCX,spCY = spiral.bbox:center()
local spX1,spY1, spX2,spY2 = spiral.bbox:bbox()
local shCX,shCY = shape:center()
local shX1,shY1, shX2,shY2 = shape:bbox()
if (spiral.y + 20 < shY2 -- past ceiling
and spiral.y + spiral.height - 20 > shY1 -- past floor
) then
--print ("in vertical range")
if (spX1 <= shX2 and spX2 > shX2) then
spiral.x = shX2 - 10
if (spiral.velX < 0) then spiral.velX = 0 end
return "left"
end
if (spX2 >= shX1 and spX1 < shX1) then
spiral.x = shX1 - spiral.width + 10
if (spiral.velX > 0) then spiral.velX = 0 end
return "right"
else -- if right wasn't reached, I want to know how the player's and the shape's coordinates
print ("SPX1 ".. spX1.."\tSPX2 ".. spX2)
print ("SHX1 ".. shX1.."\tSHX2 ".. shX2)
end
end
end
The insteresting part is just this (don't skip this one now, hehe):
Code: Select all
if (spX2 >= shX1 and spX1 < shX1) then
spiral.x = shX1 - spiral.width + 10
if (spiral.velX > 0) then spiral.velX = 0 end
return "right"
else -- if right wasn't reached, I want to know how the player's and the shape's coordinates
print ("SPX1 ".. spX1.."\tSPX2 ".. spX2)
print ("SHX1 ".. shX1.."\tSHX2 ".. shX2)
end
SPX1, SPX2 = Spiral (player) bounding box x1 and x2.
SHX1, SHX2 = the shape's bounding box x1 and x2. It's a wall shape (otherwise the message wouldn' be printed).
In the game window you can see "WALLS: false". This prints "left" or "right" if a wall is detected.
As you can see in the picture, the player's bounding box is next to the right wall, spX2 == shX1 (=1024) and spX1 < shX1. With these values, it should enter the "if", not the "else", so I wonder what's wrong.
I've tried with many alternatives (getting collisions with ALL shapes from the "walls" group, for instance), but the result is the same :S
I've attached the project if you need to have a look at the code.
Re: Creating and removing shapes from HardOnCollider on the
It appears that you haven't attached the file. From the screenshot it's clear that the bug cannot be caused by the code segment you've shown, so it would be interesting to examine other places where the detection could go wrong. I also wonder why you are rolling your own collision detection but asking questions as if you are using the one provided by HC.
Re: Creating and removing shapes from HardOnCollider on the
Sorry, I already fixed the problem (I edited the post so nobody lost time on it, and also I removed the .love file to save space in the server). For some reason, in shapes' bottom and right edges, collision is not perfectly detected unless those edges enter another shape by at least one pixel. Not sure why that happened, but I figured out a workaround that works.
By the way, I'm using your HOC. Not the main collide callbacks, but some of its functions and variables (shape:collidesWith(), shape._neighbors, shape:bbox() and shape:center, and of course the HC:update(dt)). The main "on_collide" callback didn't suit my needs as I couldn't detect whether I was colliding any shape in a group or not (I need it to update my variables player.onGround, player.onWall, and player.onCeiling), so I had to write my own functions, based on your useful library. Actually I just expecting you to tell me something like "HOC does not detect bottom and right edged until you enter them by 1 pixel at least", but I assumed that was what was happening and I moved on.
Anyway, sorry for wasting your time, vrld. Believe me I spent a lot of hours before coming here to ask, but I found out how to fix it a little while after that... one more time >_<
By the way, I'm using your HOC. Not the main collide callbacks, but some of its functions and variables (shape:collidesWith(), shape._neighbors, shape:bbox() and shape:center, and of course the HC:update(dt)). The main "on_collide" callback didn't suit my needs as I couldn't detect whether I was colliding any shape in a group or not (I need it to update my variables player.onGround, player.onWall, and player.onCeiling), so I had to write my own functions, based on your useful library. Actually I just expecting you to tell me something like "HOC does not detect bottom and right edged until you enter them by 1 pixel at least", but I assumed that was what was happening and I moved on.
Anyway, sorry for wasting your time, vrld. Believe me I spent a lot of hours before coming here to ask, but I found out how to fix it a little while after that... one more time >_<
Re: Creating and removing shapes from HardOnCollider on the
The only purpose of HC:update(dt) is to check for collisions and call the callbacks accordingly, so you should skip it too.molul wrote:Not the main collide callbacks, but some of its functions and variables (shape:collidesWith(), shape._neighbors, shape:bbox() and shape:center, and of course the HC:update(dt)).
As said before, you can add any information to the shapes which you can query in the callbacks. A simple example might be this:molul wrote:The main "on_collide" callback didn't suit my needs as I couldn't detect whether I was colliding any shape in a group or not (I need it to update my variables player.onGround, player.onWall, and player.onCeiling), so I had to write my own functions, based on your useful library.
Code: Select all
-- on creation
wall = HC:addRectangle(0,0,20,100)
wall.type = 'wall'
-- the callback
function on_collide(dt, a,b, dx,dy)
-- determine the player/obstacle shape
local player, obstacle = a,b
if player.type == 'wall' then
player, obstacle = obstacle, player
dx,dy = -dx,-dy
end
if player.type ~= 'player' then return end -- none of the shapes was the player
if obstacle.type == 'wall' then
-- stop player and move shape out of the wall
player.parent.speed = 0
player:move(dx,dy)
end
end
It detects whether to geometric shapes intersect and calculates the direction you need to move one of the shapes so that they don't intersect anymore. There is no such thing as pixelsmolul wrote:Actually I just expecting you to tell me something like "HOC does not detect bottom and right edged until you enter them by 1 pixel at least", but I assumed that was what was happening and I moved on.
Re: Creating and removing shapes from HardOnCollider on the
Good to know, thanks! However, I'm using the HOC to get collisions with items and enemies, so I can keep itvrld wrote:The only purpose of HC:update(dt) is to check for collisions and call the callbacks accordingly, so you should skip it too.
In fact I tried something like that. If a == player and b.type == "ground", then player.onGround = true. But then I couldn't figure out how to get if player.onGround wasn't true anymore. Using a tiled map to create collision shapes, when using the "collide_stop" callback, I could get if the player wasn't colliding with a ground type shape that was colliding with last frame, but the "on_collide" could be detecting another floor tile, so I was getting a blinking "true"/"false" value when walking from one tile to another. That's why I ended up writing my own functions.vrld wrote:As said before, you can add any information to the shapes which you can query in the callbacks. A simple example might be this:Code: Select all
{code}
I'm sure there must be a way to do it using the main HC functionality, but I couldn't figure out how to do it.
- TechnoCat
- Inner party member
- Posts: 1612
- Joined: Thu Jul 30, 2009 12:31 am
- Location: Milwaukee, WI
- Contact:
Re: Creating and removing shapes from HardOnCollider on the
To make this more clear: If the vertex of one shape is on the line of another shape, that isn't a collision (intersection).vrld wrote:It detects whether to geometric shapes intersect and calculates the direction you need to move one of the shapes so that they don't intersect anymore. There is no such thing as pixelsmolul wrote:Actually I just expecting you to tell me something like "HOC does not detect bottom and right edged until you enter them by 1 pixel at least", but I assumed that was what was happening and I moved on.
Who is online
Users browsing this forum: Amazon [Bot] and 3 guests