Page 1 of 1

Collision of a Table of Bullets

Posted: Sun Dec 25, 2011 4:59 am
by fparedesg
Hey everyone! I'm starting off with the physics module, so I decided to be original and write my own Asteroids game. I only have one question regarding collision detection with the ship's bullets.

In order to store the bullets' data, I created a variable which holds all the bullets and another which records how many bullets are active:

Code: Select all

bullets = {}
bulletNo = 0
Every time the spacebar is pressed, a new bullet is created, like so:

Code: Select all

if key == ' ' then
	bulletNo = bulletNo + 1
	table.insert(bullets, {})
	bullets[bulletNo].body = love.physics.newBody(world, player.body:getX()+32*math.cos(player.angle), player.body:getY()+32*math.sin(player.angle), 1, 0)
	bullets[bulletNo].shape = love.physics.newCircleShape(bullets[bulletNo].body, 0, 0, 2)
	bullets[bulletNo].body:applyImpulse(10*math.cos(player.angle)+3*player.force.x, 10*math.sin(player.angle)+3*player.force.y)
	bullets[bulletNo].lifespan = 0
	bullets[bulletNo].shape:setCategory(2)
	bullets[bulletNo].shape:setData("Bullet")
end
The way I understand it (but please correct me if I'm wrong) is that upon setting callbacks to the world, once a collision is detected, the data set in shape:setData() is passed onto the collision function, like so:

Code: Select all

function add(a, b, collision)
	--If a collision is detected between *something* and a bullet, then either a or b would be "Bullet".
end
Since only the string "Bullet" is being passed, how can I know which bullet collided with said *something*? I was thinking on modifying the setData() part and changing it to

Code: Select all

bullets[bulletNo].shape:setData("Bullet" .. bulletNo)
so that once a collision is detected, I can get the characters after "Bullet" to obtain which bullet collided, but I don't know if I'm over-complicating myself. Is there another way I can do it?

Thanks! And happy holidays to everyone!

Re: Collision of a Table of Bullets

Posted: Sun Dec 25, 2011 9:02 am
by Robin
I think you are overcomplicating things, in more than one way. Here's my suggestion, see if you like it:

Code: Select all

bullets = {}

Code: Select all

if key == ' ' then
	local newbullet = {}
	newbullet.body = love.physics.newBody(world, player.body:getX()+32*math.cos(player.angle), player.body:getY()+32*math.sin(player.angle), 1, 0)
	newbullet.shape = love.physics.newCircleShape(newbullet.body, 0, 0, 2)
	newbullet.body:applyImpulse(10*math.cos(player.angle)+3*player.force.x, 10*math.sin(player.angle)+3*player.force.y)
	newbullet.lifespan = 0
	newbullet.shape:setCategory(2)
	newbullet.shape:setData({type = "Bullet", bullet = newbullet)
	bullets[#bullets+1] = newbullet
end
You can look at a.type and b.type to see if they are a bullet, and a.bullet or b.bullet to extract the bullet object. You could store the index in the bullets table instead, but that gets all messed up when you want to remove bullets because they collided with something (the indices of bullets fired later are then wrong). How you would remove a bullet in this way:

Code: Select all

if a.type == "Bullet" or b.type == "Bullet then
    local bullet = a.bullet or b.bullet
    for i, v in ipairs(bullets) do
       if v == bullet then
           table.remove(bullets, i)
           break
       end
    end
end

Re: Collision of a Table of Bullets

Posted: Sun Dec 25, 2011 6:20 pm
by fparedesg
Thank you very much (again). :)

Re: Collision of a Table of Bullets

Posted: Sun Dec 25, 2011 10:55 pm
by Evil_Bartek
I don't see a problem,

OFF TOPIC:

Add a conf file, it looks ugly

Re: Collision of a Table of Bullets

Posted: Tue Dec 27, 2011 5:55 am
by fparedesg
I am still having problems with the removal of the bodies. Once I remove the bullets and asteroids using the method you described, they are no longer drawn, but they are still present, as I've noticed that other bullet objects keep bouncing off that now-blank-space.

To simulate this, I created the following test program that causes round 'drops' to fall down and bounce off the 'ground'. Once the user presses space, the ground is removed (using your previously described method), but the drops keep bouncing off. Why does this happen?

EDIT: Besides removing the value from the table, I am also calling Body:destroy(). Shouldn't this completely remove the body?

Re: Collision of a Table of Bullets

Posted: Tue Dec 27, 2011 6:41 am
by MP6767
fparedesg wrote:I am still having problems with the removal of the bodies. Once I remove the bullets and asteroids using the method you described, they are no longer drawn, but they are still present, as I've noticed that other bullet objects keep bouncing off that now-blank-space.

To simulate this, I created the following test program that causes round 'drops' to fall down and bounce off the 'ground'. Once the user presses space, the ground is removed (using your previously described method), but the drops keep bouncing off. Why does this happen?

EDIT: Besides removing the value from the table, I am also calling Body:destroy(). Shouldn't this completely remove the body?

The file you posted crashes. Error on line 60. I can't really help since I'm scrub at Lua, but if it's any help, half the screen turns orange and when you press space twice, it crashes.

Re: Collision of a Table of Bullets

Posted: Tue Dec 27, 2011 7:28 am
by tentus
fparedesg wrote:I am still having problems with the removal of the bodies. Once I remove the bullets and asteroids using the method you described, they are no longer drawn, but they are still present, as I've noticed that other bullet objects keep bouncing off that now-blank-space.

To simulate this, I created the following test program that causes round 'drops' to fall down and bounce off the 'ground'. Once the user presses space, the ground is removed (using your previously described method), but the drops keep bouncing off. Why does this happen?

EDIT: Besides removing the value from the table, I am also calling Body:destroy(). Shouldn't this completely remove the body?
Body:destroy() had some... issues in Love 0.7. https://bitbucket.org/rude/love/issue/1 ... -not-crash They should be fixed in Love 0.8.0.

To fix the bug mentioned above, change

Code: Select all

if key == ' ' then
to

Code: Select all

if key == ' ' and floor[1] then
. (You have to make sure there's a floor to destroy before you destroy it.)

Re: Collision of a Table of Bullets

Posted: Tue Dec 27, 2011 11:54 pm
by fparedesg
MP6767 wrote:The file you posted crashes. Error on line 60.
That happens because the floor is already removed from the table 'floor', and pressing space for a second time runs:

Code: Select all

table.remove(floor, 1)
again, and there's nothing to remove.

That bug isn't present in the original Asteroids.love file I attached in my first post. I just quickly wrote this Test.love to emulate the problem in Asteroids.love, which is that even though the object is removed, other bodies still bounce off it. Is there any way I can fix this? Or should I just do:

Code: Select all

Body:setPosition(-100, -100)
--To place the removed body outside the world

Re: Collision of a Table of Bullets

Posted: Wed Dec 28, 2011 7:23 am
by fparedesg
Well, I took the easy way out, but I don't know if there's a better way of doing it. Instead of destroying bodies/shapes, I simply remove the object from the table and set a mask, so as to avoid any unneeded collisions with the 'removed' objects.

Code: Select all

if a.type == "Bullet" or b.type == "Bullet then
    local bullet = a.bullet or b.bullet
    for i, v in ipairs(bullets) do
       if v == bullet then
           v.shape:setMask(1, 2, 3) --1 = player, 2 = bullets, 3 = enemies
           table.remove(bullets, i)
           break
       end
    end
end