Detecting near-by physic.bodys

Hi! As most of you know from my previous threads, will were trying to figure out a good solution to having tons of collisions on Codea. I fixed my issue of having to many images, but this seems to be its own battle. I’ve turned back to physic.body’s instead of my own physics engine because it wan’t working the way I wanted. I also thought the mask and categories function would help, by only allowing collisions between the player and the cube. Not the cubes vs cubes vs player. So that might of helped, as I can’t really see a difference. But then that got me thinking, I was trying to figure out how to find the nearest physic.bodies in a table to a player. I can’t find a good way to do this without doing a pairs or for loop in the entire table. Then after I looked around google to try finding one, all I could find is box2d solutions for javascript. Any ideas?

Thanks,

Prynok.

Loop through the table of bodies and calculate the distance from the player, then find the shortest. Ex:

local shortest, closest = math.huge, 1
for id, body in pairs(bodies) do
    local dist = player.pos:dist(body.pos)
    -- If closer than previous one, set this to shortest distance and this id to the closest
    if dist < shortest then
        shortest = dist
        closest = id
    end
end

This loop will end with the closest body’s id stored in the variable closest.

EDIT: Just re-read the question and you say no for loop… Why? But if this really won’t work, I suggest looking into raycasting

@JakAttack The reason I don’ t think I can loop is because if there are lets say, 6,000+ bodies inside the game, it would take forever to loop trough them in the draw function.

Well I think ray casting probably uses a loop somewhere, but @John would know best

I don’t think there’s any way to automagically determine which body is closest to the player

You might try adding an extra physics body for the player, and set the sensor property to true, which means it will trap collision events without making objects bounce. If you make this sensor body bigger than your player, then it will notify you of all objects within the radius of that body. Then you only have to loop through these few objects to see which is closest.

@Ignatz has the best solution — this is what sensors are for.

@Ignatz Thanks! Though, doesn’t that require the body’s to be active, which is part of the reason its so slow?

Not sure, why not try it

Using a sensor sounds like the best solution as @Ignatz said.

I’m working on some performance fixes when there is a large number of physics bodies. I’ll be posting a performance comparison once I’m done.

@Prynok I don’t know if this will work, but you can try it. What I’m trying to do here is put all the object in a table with “x” as the key, with it’s “y” value. Then as the green dot moves down the screen, I check the table for “x” values within -60 to +60 of the green dots “x” value. In that range, I then look for the smallest distance from the green dot to the other dots near it. I turn it “red” until another dot is closer. You’ll have to compare this with the “sensor” code.

EDIT: The blue dots are the ones being checked.


displayMode(FULLSCREEN)  
function setup()
    tx=math.random(50,WIDTH-50)
    ty=HEIGHT
    tab={}
    for z=1,1000 do
        x=math.random(WIDTH)
        y=math.random(HEIGHT)
        table.insert(tab,tostring(x),y)
    end
end

function draw()
    background(40,40,50)
    yy=100
    fill(255)
    for a,b in pairs(tab) do
        ellipse(a,b,5)
    end
    v1=vec2(tx,ty)
    for z=tx-60,tx+60 do
        ss=tab[z]
        if ss~=nil and ss>ty-60 and ss<ty+60 then
            fill(0,0,255)
            ellipse(z,tab[z],5)
            d=v1:dist(vec2(z,tab[z]))
            if d<yy then
                yy=d
                zz=z
            end
        end
    end
    if zz>0 then
        fill(255,0,0)
        ellipse(zz,tab[zz],5)
    end
    ty=ty-2
    if ty<0 then
        tx=math.random(WIDTH)
        ty=HEIGHT
    end
    fill(0,255,0)
    ellipse(tx,ty,12)
end

@dave1707 - that only works if the x values are integers (and the dots aren’t moving continuously)

@Ignatz The x values could be rounded down to integers. I don’t think a fraction of a pixel matters that much. The table would be created each time the objects are drawn. I don’t know if this is better or worse. I haven’t tried doing sensor code to see how fast that is.

if you’re going to create a table of rounded x values on each draw, it would be much quicker to just test the distance from the player x instead, I’m sure.

@Ignatz That’s kind of what I’m trying to do, I think. I’m just using a table in this example so I don’t have to create a bunch of code to move all of the dots around. It would be just a matter of comparing each x,y value of the objects as they’re being drawn to see if they’re within the bounds of a square. If they are, then calculate the distance from the main object and keep track of which one is the closest.

EDIT: I’m trying to use physics.bodies with a sensor, but with 1000 objects, the falling dot is going really slow. The FPS is only 3.