Collision of a Table of Bullets

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
fparedesg
Prole
Posts: 13
Joined: Thu Dec 15, 2011 8:47 am

Collision of a Table of Bullets

Post 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!
Attachments
Asteroids.love
(36.7 KiB) Downloaded 144 times
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Collision of a Table of Bullets

Post 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
Help us help you: attach a .love.
fparedesg
Prole
Posts: 13
Joined: Thu Dec 15, 2011 8:47 am

Re: Collision of a Table of Bullets

Post by fparedesg »

Thank you very much (again). :)
Evil_Bartek
Prole
Posts: 43
Joined: Sun Dec 25, 2011 5:13 pm

Re: Collision of a Table of Bullets

Post by Evil_Bartek »

I don't see a problem,

OFF TOPIC:

Add a conf file, it looks ugly
fparedesg
Prole
Posts: 13
Joined: Thu Dec 15, 2011 8:47 am

Re: Collision of a Table of Bullets

Post 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?
Attachments
Test.love
(1.08 KiB) Downloaded 159 times
MP6767
Prole
Posts: 16
Joined: Wed Dec 21, 2011 12:18 am

Re: Collision of a Table of Bullets

Post 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.
User avatar
tentus
Inner party member
Posts: 1060
Joined: Sun Oct 31, 2010 7:56 pm
Location: Appalachia
Contact:

Re: Collision of a Table of Bullets

Post 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.)
Kurosuke needs beta testers
fparedesg
Prole
Posts: 13
Joined: Thu Dec 15, 2011 8:47 am

Re: Collision of a Table of Bullets

Post 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
fparedesg
Prole
Posts: 13
Joined: Thu Dec 15, 2011 8:47 am

Re: Collision of a Table of Bullets

Post 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
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 3 guests