Aweptimum / Strike

2D Collision Detection for Lua using the Separating-Axis Theorem

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

A callback function would be handy

togfoxy opened this issue · comments

commented

Similar to box2d begin_collision etc.

I'd make a PR if I had the skills.

commented

Could you give me an example of when you would want to use it? I ask because Strike is very plain in comparison to box2d. It's only concerned with collision, while box2d is a fleshed out physics simulation. It needs to give you hooks into it to influence it since it's doing resolution for you.

I think S.ettle could use a callback though if you're referring to that. I meant to add something to make resolution friendlier.

commented

Apologies for briefness. I wasn't convinced this library was maintained. :)

My project has multiple objects with one collider each (simple rectangle sprites with simple rectangle collider). On every game loop, during love.update(), do I need to check if every collider has touched any other collider?

The code seems convoluted. If there were a callback that describes the two colliders that have touched then I would not need this code.

Here you can see I check if any submarine has collided with anything, then I check if any torpedo has collided with anything, then I check if any destroyer has collided with anything. What you see below gets invoked three times (elsewhere):

local obj = fun.targetHit(sub) 
local obj = fun.targetHit(torp) 
local obj = fun.targetHit(destroyer) 

Is there a better way? Thanks.



function functions.targetHit(obj)
    -- checks colliders and returns nil or the object that was hit. Does NOT return the collider or shape or anything else
    for k, v in pairs(SUBMARINE) do
        local result = S.triking(obj.collider, v.collider)
        if result ~= false then
            return v
        end
    end

    for k, v in pairs(TORPEDO) do
        local result = S.triking(obj.collider, v.collider)
        if result ~= false then
            return v
        end
    end

    for k, v in pairs(DESTROYER) do
        local result = S.triking(obj.collider, v.collider)
        if result ~= false then
            return v
        end
    end
    return nil
end

commented

do I need to check if every collider has touched any other collider?

Afraid so

The module just gives you the tools for collision detection; it doesn't keep track of what shapes you've instantiated. The reason for that is the lack of spatial partitioning built-in like in bump or HC. This is something I've worked on and would like to integrate at some point. I had way more free time when I was activley working on this library than I do now :( which is why it seems abandoned.

The abridged way of doing checking yourself would be a double loop like this:

-- Let's say you have the following
local myObjs = {} -- contains all your game objects with collision geometry

-- We collect objects that are colliding
local collisions = {}

-- By looping through each potential collision pair
for i = 1, #myObjs do
    local collides = myObjs[i]
    for j = i, #myObjs do
        local against = myObjs[j]
        -- Checking if they should collide
        if shouldCollide(collides, against) then
            local mtv = S.triking(collides.collider, against.collider))
            -- and, if they do collide, storing it for later
            if mtv then
                -- the mtv will push `against` out of `collides`
                local collision = {collides = collides, against = against, mtv = mtv}
                table.insert(collisions, collision)
            end
        end
    end
end

-- Resolve - Loop over collisions, resolving them according to your game logic
-- You would probably loop over the collisions table in two passes.
-- First, you would remove stuff that is destroyed, 
-- and then on the second you can resolve the stuff left over that shouldn't be phasing through each other.

The double loop is nice because you can check everything all in one place and it ensures a pair is only checked once. But you can fill the collisions array any way you want.

There are other concepts to mix in to make this process easier/more performant:

  1. Collision groups/filtering (maybe torpedoes don't collide with other torpedoes)
  2. Spatial partitioning (you only do this process inside partitions, so a torpedo 1000 pixels away from a ship isn't checked for collision)

If you don't want to do this kind of stuff manually, that's understandable. But that's how Strike is built currently.

I am wanting to get back into working on it. I've just moved and gone remote with my job, so I have an extra 2 hours a day of free time now.

commented

I see. In the absence of a callback then your loop is an improvement - if only for performance reasons. I'll re-engineer my code. Thanks!