Collision and destroy problems

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.
User avatar
Nexion
Prole
Posts: 46
Joined: Fri Sep 05, 2008 1:40 pm

Collision and destroy problems

Post by Nexion »

For whatever reason, my collision function will not detect ANY collisions.

Code: Select all

function collision(a,b,c)
	local f, r = c:getFriction(), c:getRestitution() 
    local s = c:getSeparation() 
    local px, py = c:getPosition() 
    local vx, vy = c:getVelocity() 
    local nx, ny = c:getNormal() 
	for k, v in pairs(bulletShapes) do
		if a == v or b == v then
			if b == mobShape or a == mobShape then
				mobDamage = mobDamage + 2
			end
			bulletIndex = k
			a:destroy()
			b:destroy()
			bullets[k]:destroy()
		end
	end
end
I'm just trying to detect if any of the bullets fired (all the bodies are stored in the "bullets" table, and the shapes are also stored exclusively in the "bulletShapes" table) so I can add some damage to the mob.
The weird thing is, I can't even get any callbacks from collision, even with just a simple text display; so it's probably not my code that's wrong.
Did the callback change in 0.5.0?

Also - whenever I CAN get to a point to use :destroy() to get rid of the bullets (I cheated and tried doing it in the update function checking distance, but that's hacky and I want the actual collision function to do it because my mob is a diamond, so the collisions wouldn't be right) LOVE errors and says "attempt to call method 'destroy' (a nil value)". I know you have to delete the shapes first, but it's just erroring.

Code: Select all

	for k, v in pairs(bullets) do
		for j, n in pairs(bullets) do
			if dist(v.b:getX(), v.b:getY(), n.b:getX(), n.b:getY()) <= 2 then
				n.s:destroy() --shape member of the bullets table
				v.s:destroy() --same as above
				n.b:destroy() --body member of the bullets table
				v.b:destroy() --same as above
			end
		end
	end
User avatar
rude
Administrator
Posts: 1052
Joined: Mon Feb 04, 2008 3:58 pm
Location: Oslo, Norway

Re: Collision and destroy problems

Post by rude »

Love.physics has hardly been touched since initial release, and callbacks seem to work fine (see "Mini Physics Callbacks" in the example browser).

As for your problems: what did you pass to Shape:setData? Your second problem is very weird. What does the entries in the bullets-table look like?

Clarification: you do not need to destroy stuff in a specific order, but if you destroy a body before an attatched shape, that body will not really be destroyed until the attatched shape is destroyed too.
User avatar
Nexion
Prole
Posts: 46
Joined: Fri Sep 05, 2008 1:40 pm

Re: Collision and destroy problems

Post by Nexion »

Here, I'll just post the entire code (some changes made since last post)

Code: Select all

local phys = love.physics
local graph = love.graphics
local time = love.timer
local aud = love.audio

local bullets = {}
function load() 
	world = phys.newWorld(1024, 768)
	world:setGravity(0, 15)
	graph.setBackgroundColor(100,100,255)
	LCannonBody = phys.newBody(world, 256, 768, 0)
	LCannonShape = phys.newCircleShape(LCannonBody, 15)
	LCannonShape:setData("LeftCannon");
	LBarrelBody = phys.newBody(world, 256, 758, 0)
	LBarrelShape = phys.newRectangleShape(LBarrelBody, 45, 5)
	LBarrelShape:setData("LeftBarrel")
	LBarrelBody:setAngle(0)
	
	MCannonBody = phys.newBody(world, 512,768,0)
	MCannonShape = phys.newCircleShape(MCannonBody, 15)
	MCannonShape:setData("MidCannon");
	MBarrelBody = phys.newBody(world, 512, 758,0)
	MBarrelShape = phys.newRectangleShape(MBarrelBody, 45, 5)
	MBarrelShape:setData("MidBarrel")
	MBarrelBody:setAngle(0)
	
	RCannonBody = phys.newBody(world, 768,768,0)
	RCannonShape = phys.newCircleShape(RCannonBody, 15)
	RCannonShape:setData("RightCannon");
	RBarrelBody = phys.newBody(world, 768, 758,0)
	RBarrelShape = phys.newRectangleShape(RBarrelBody, 45, 5)
	RBarrelShape:setData("RightBarrel")
	RBarrelBody:setAngle(0)
	
	local f = love.graphics.newFont(love.default_font, 14)
    	love.graphics.setFont(f)
		
	mob = phys.newBody(world, math.random(50,984), 0)
	mobDamage = 0
	mob:setMass(0,0,200,0)
	mobShape = phys.newCircleShape(mob, 5)
	mobShape:setData("Mob")
	nextDamage = 0
	
	mob:applyImpulse(math.random(-15000,15000),75)

	cannonFire = aud.newSound("sounds/cannon.wav")
end

function update(dt)
	world:update(dt)
	CurTime = love.timer.getTime()
	mPosX, mPosY = love.mouse.getPosition()
	
	lbPosX, lbPosY = LBarrelBody:getPosition()
	mbPosX, mbPosY = MBarrelBody:getPosition()
	rbPosX, rbPosY = RBarrelBody:getPosition()
	
	LBarrelBody:setAngle(math.deg(math.atan2(lbPosY-mPosY,lbPosX-mPosX)))
	MBarrelBody:setAngle(math.deg(math.atan2(mbPosY-mPosY,mbPosX-mPosX)))
	RBarrelBody:setAngle(math.deg(math.atan2(rbPosY-mPosY,rbPosX-mPosX)))

	for k, v in pairs(bullets) do
		if v.b:getX() > 1024 or v.b:getX() < 0 or v.b:getY() < 0 then
			table.remove(bullets, k)
		end
	end
end

function dist(x1,y1,x2,y2) 
	return ((x1^2+y1^2)^.5) - ((x2^2+y2^2)^.5)
end


text = ""
function draw() 

	graph.draw(text, 50, 50)
	graph.setColor(200, 200, 200);
		
	graph.polygon(love.draw_line, LBarrelShape:getPoints())
	graph.polygon(love.draw_line, MBarrelShape:getPoints())
	graph.polygon(love.draw_line, RBarrelShape:getPoints())
	graph.circle(0,LCannonBody:getX(), LCannonBody:getY(), 15, 360)
	graph.circle(0,MCannonBody:getX(), MCannonBody:getY(), 15, 360)
	graph.circle(0,RCannonBody:getX(), RCannonBody:getY(), 15, 360)
	for k,v in ipairs(bullets) do
		graph.circle(2, v.b:getX(), v.b:getY(), 2, 360)
	end
	
	graph.setColor(255,100,100)
	graph.circle(0, mob:getX(), mob:getY(), 10, 4)
	graph.setColor(255,255,255)
	graph.rectangle(0, mob:getX() - 13.5, mob:getY() - 19, 27, 7)
	graph.setColor(255,50,50)
	mobHealth = (25 - mobDamage)
	graph.rectangle(0, mob:getX() - 12.5, mob:getY() - 18, mobHealth, 5)
	
	graph.draw(mobDamage, 100, 100) 
end 

function keypressed(k) 
	if k == love.key_r then
		love.system.restart()
	end
end 

lastclick = 0
function mousepressed(x1, y1, button) 
	if button == love.mouse_left and lastclick + 0.1 <= love.timer.getTime() then--or button == love.mouse_wheeldown or button == love.mouse_wheelup then --
		lastclick = love.timer.getTime()
		
		local spawner
		if x1 < 384 then spawner = LBarrelBody elseif x1 < 640 then spawner = MBarrelBody else spawner = RBarrelBody end
		local x2, y2 = spawner:getPosition()
		local sPosX, sPosY = 512, 768
		local sAngle = spawner:getAngle()

		sPosX = x2 + math.cos(math.rad(sAngle-180)) * 30
		sPosY = y2 + math.sin(math.rad(sAngle-180)) * 30

		t = {}
		bulletShapes = {}
		t.b = phys.newBody(world, sPosX, sPosY, 1)
		t.s = phys.newCircleShape(t.b, 3)
		table.insert(bulletShapes, t.s)
		--t.b:setBullet(true)
		t.s:setData("Bullet")
		table.insert(bullets, t)
		t.b:setVelocity(math.cos(math.rad(sAngle-180)) * 5000000,math.sin(math.rad(sAngle-180)) * 5000000)
		
		aud.play(cannonFire)
	end 
end 

function collision(a,b,c)
	local f, r = c:getFriction(), c:getRestitution() 
    local s = c:getSeparation() 
    local px, py = c:getPosition() 
    local vx, vy = c:getVelocity() 
    local nx, ny = c:getNormal() 
	--for k, v in pairs(bulletShapes) do
		if a == "Bullet" or b == "Bullet" then
			if b == "Mob" or a == "Mob" then
				mobDamage = mobDamage + 2
			end
			bulletIndex = k
			a:destroy()
			b:destroy()
			bullets[k]:destroy()
		end
	--end
end
I wasn't sure if you could reference the shapes directly in the collision function or if you had to pass them with their setData value. Either way it still didn't work.
And I know you have to destroy them in the right order, and I believe I am doing it correctly, that's not what i'm saying. :destroy() is simply throwing an error saying it doesnt exist whenever i try to use it.
User avatar
rude
Administrator
Posts: 1052
Joined: Mon Feb 04, 2008 3:58 pm
Location: Oslo, Norway

Re: Collision and destroy problems

Post by rude »

Nexion wrote:And I know you have to destroy them in the right order
No you don't, see my post:
rude wrote:Clarification: you do not need to destroy stuff in a specific order, but if you destroy a body before an attatched shape, that body will not really be destroyed until the attatched shape is destroyed too.
As far as I can tell, you're setting the data of the bullets as strings:

Code: Select all

t.s:setData("Bullet")
In your collision callback, this string will be passed as one of the parameters:

Code: Select all

function collision(a,b,c)
-- ...
-- a and b are strings, and do obviously not
-- have a destroy() method.
a:destroy()
b:destroy()
-- ...
end
I made an example which demonstates how to remove bodies/shapes in different ways. It may not be the best example ever, but hopefully it can help you a little.
User avatar
Nexion
Prole
Posts: 46
Joined: Fri Sep 05, 2008 1:40 pm

Re: Collision and destroy problems

Post by Nexion »

oh ok, i misread what you had posted.

And if a and b are strings, then the docs are wrong, because the docs say that collision passes the shapes, not their data strings
User avatar
rude
Administrator
Posts: 1052
Joined: Mon Feb 04, 2008 3:58 pm
Location: Oslo, Norway

Re: Collision and destroy problems

Post by rude »

Do you know which page? I would like to correct it if it really says that.
User avatar
Nexion
Prole
Posts: 46
Joined: Fri Sep 05, 2008 1:40 pm

Re: Collision and destroy problems

Post by Nexion »

http://love2d.org/docs/Contact.html
It doesn't REALLY say that, but from looking at it that was the impression I got from it.

And I put
text = a .. ", " .. b
in the collision function then drew text with the draw function, and no matter what hits where, it never shows ANYTHING
User avatar
Nexion
Prole
Posts: 46
Joined: Fri Sep 05, 2008 1:40 pm

Re: Collision and destroy problems

Post by Nexion »

*sigh* nevermind I'm an idiot, I forgot to set the callback to the world...
User avatar
rude
Administrator
Posts: 1052
Joined: Mon Feb 04, 2008 3:58 pm
Location: Oslo, Norway

Re: Collision and destroy problems

Post by rude »

Ah, I just noticed that myself! :D

Silly me, I should have paid more attention to your code. On the plus side, all this love.physics-investigating has been been very useful. I found at least one weakness I didn't consider.

This code will create a cyclic dependency, and the shape/body can never be garbage collected.

Code: Select all

local b = love.physics.newBody()
local s = love.physics.newShape(b)
local t = { b = b, s = s }
s:setData(t)
I suppose weak tables or something would be a solution to this.
User avatar
Nexion
Prole
Posts: 46
Joined: Fri Sep 05, 2008 1:40 pm

Re: Collision and destroy problems

Post by Nexion »

I'm trying to implement your code into mine, and I think I have everything right, but LOVE is still complaining about destroy() being a nil value, even though its being called on entities.b and .s

Do you have MSN or GTalk or something so we don't have to take up forum space and for faster responses?
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot] and 7 guests