Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Problem with detecting collision between circle and line.
Started by universalenglishinchina Feb 19 2015 01:00 AM

- - - - -
32 replies to this topic

[TOPIC CONTROLS]
Page 1 of 2 1 2
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

I have

 

local line = display.newLine( sceneGroup, 0,_H-1, _W, _H-1)
    line:setStrokeColor(1,0,0,1)
    line.strokeWidth=8
    line.myName="Floor"
    sceneGroup:insert(line)
    physics.addBody(line, "static", {isSensor = True}) -- I was reading add body and I thought that would help.

 

I copied this function from Nick Sherman (thanks Nick!)

function touchCircle(event)
    local obj = event.target
    local cid = obj.id
    local objective = obj.objective
    
    if event.phase == "began" then
        print ("Circle number " .. cid .. " was clicked!")
        print ("objective is " .. objective)
    end
    

I called that function with

c:addEventListener("touch", touchCircle)

So, right after c:addEventListener("touch", touchCircle)

I added

c:addEventListener("collision", CollisionWithLine)

Then I tried to add function just like he did but using the info from your documentation

 

function CollisionWithLine(event)
    local obj = event.target   -- I will worry about these later.
    local cid = obj.id    -- I will worry about these later.
    local objective = obj.objective  -- I will worry about these later.
    

--I found out I had to put this in here because as soon as I created the circles this function was being called.  I assume collision with background??? but it was nil for object1.  No idea why.  But the problem is that when the circle touches the line I still get nothing in object1.  But then it does some strange things on my screen.  Likes stops but the text in the circle move backwards.  VERY strange.

    if (event.object1 == nil) then 
        print("nothing in object1")
        return false
    end
    if (event.object2 == nil) then
        print("nothing in object2")
        return false
    end
    
    if event.phase == "began" then
        print ("Circle number " .. cid .. " collided with line!")
        print ("obj1 is " .. event.object1.myName .. " obj2 is " .. event.object2.myName)
        print ("objective is " .. objective)
    end
    
end
 

 

Any ideas what I am doing wrong?

Thanks!

 



[TOPIC: post.html]
#2

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,814 posts
  • Corona SDK

I don't think you can add a physics body to a line object. Instead try creating a long, thin rectangle.



[TOPIC: post.html]
#3

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

Thanks for your reply Nick. I read this in the documentation. "You should not add a physics body to a line object created with display.newLine(), unless the body type is "static"." I did make it static. Anyway I changed it. local floor = display.newImageRect(sceneGroup,"images/floor.png",_W,2) floor.x=_W/2 floor.y=_H-1 floor.myName="Floor" --didn't know what to put here floor.id="Floor" -- didn't really need this but I put it anyway. physics.addBody(floor, "static") and I still get the SAME strange behavior.

[TOPIC: post.html]
#4

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,814 posts
  • Corona SDK

Are both the circle and the rect inserted into the same display group?



[TOPIC: post.html]
#5

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

Yes. I see it getting triggered. Just null is used. Here is my code - some stuff taken out. local floor = display.newImageRect(sceneGroup,"images/floor.png",_W,2) -- sceneGroup:insert(floor) ( I don't think I need this, I tried both ways - with and without) physics.addBody(floor, "static") level1b( sceneGroup, composer.objective, composer.gravity, composer.points) function level1b( group, objective, speed, points) ... createCircle(group, 60*i+30,-60*j, 28, created, speed, objective) ... end function createCircle(group, xCenter, yCenter, radius, created, speed, objective) local c = display.newCircle(group, xCenter, yCenter, radius) local choice="Hello" local text = display.newText(group,choice,xCenter,yCenter,Helvetica, 12) physics.addBody(c, {density = 0.01, radius = radius, bounce = 0.0}) physics.addBody(text, {density = 0.01, radius = radius, bounce = 0.0}) c:setLinearVelocity(0,speed) text:setLinearVelocity(0,speed) c:addEventListener("touch", touchCircle) -- to make it touchable c:addEventListener("collision", CollisionWithLine) -- to make it check if collided. c.id = choice text.id = choice c.objective = objective c.myName = choice end function touchCircle(event) local obj = event.target local cid = obj.id local objective = obj.objective if event.phase == "began" then print ("Circle number " .. cid .. " was clicked!") print ("objective is " .. objective) end end function CollisionWithLine(event) local obj = event.target -- will worry about this later local cid = obj.id -- will worry about this later local objective = obj.objective -- will worry about this later if (event.object1 == nil) then print("nothing in object1") -- All I get back is this!!! return false end if (event.object2 == nil) then print("nothing in object2") return false end if event.phase == "began" then print ("Circle number " .. cid .. " collided with floor!") print ("obj1 is " .. event.object1.myName .. " obj2 is " .. event.object2.myName) print ("objective is " .. objective) end end As soon as I create the circles, I get a Bunch of "nothing in object1" Then when the balls hit the bottom line I get "nothing in object1" Sorry for taking so much of your time. I am probably doing something stupid. :( It just gets frustrating.

[TOPIC: post.html]
#6

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

what is with the formatting?  It looked great when I typed it!!!!  UGH!



[TOPIC: post.html]
#7

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,814 posts
  • Corona SDK

You need to wrap code in lua tags.

 

Put [*lua*] (excluding the asterisks) before the code and [*/lua*] after the code.



[TOPIC: post.html]
#8

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

Ok, trying to type it again. 

 

Yes. I see it getting triggered. Just null is used. Here is my code - some stuff taken out.

 

local floor = display.newImageRect(sceneGroup,"images/floor.png",_W,2)

-- sceneGroup:insert(floor) ( I don't think I need this, I tried both ways - with and without)

physics.addBody(floor, "static")

 

level1b( sceneGroup, composer.objective, composer.gravity, composer.points)

 

function level1b( group, objective, speed, points)

...

createCircle(group, 60*i+30,-60*j, 28, created, speed, objective)

...

end

 

function createCircle(group, xCenter, yCenter, radius, created, speed, objective)

local c = display.newCircle(group, xCenter, yCenter, radius)

local choice="Hello"

local text = display.newText(group,choice,xCenter,yCenter,Helvetica, 12)

physics.addBody(c, {density = 0.01, radius = radius, bounce = 0.0})

physics.addBody(text, {density = 0.01, radius = radius, bounce = 0.0})

c:setLinearVelocity(0,speed)

text:setLinearVelocity(0,speed)

c:addEventListener("touch", touchCircle) -- to make it touchable

c:addEventListener("collision", CollisionWithLine) -- to make it check if collided.

c.id = choice

text.id = choice

c.objective = objective

c.myName = choice

end

 

function touchCircle(event)

local obj = event.target

local cid = obj.id

local objective = obj.objective

if event.phase == "began" then

print ("Circle number " .. cid .. " was clicked!")

print ("objective is " .. objective)

end

end

 

function CollisionWithLine(event)

local obj = event.target -- will worry about this later

local cid = obj.id -- will worry about this later local

objective = obj.objective -- will worry about this later

 

if (event.object1 == nil) then

print("nothing in object1") -- All I get back is this!!!

return false

end

 

if (event.object2 == nil) then

print("nothing in object2")

return false

end

if event.phase == "began" then

print ("Circle number " .. cid .. " collided with floor!")

print ("obj1 is " .. event.object1.myName .. " obj2 is " .. event.object2.myName)

print ("objective is " .. objective)

end

end

 

As soon as I create the circles, I get a Bunch of "nothing in object1" Then when the balls hit the bottom line I get "nothing in object1" Sorry for taking so much of your time. I am probably doing something stupid. :( It just gets frustrating.



[TOPIC: post.html]
#9

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

ahhhh formatting problem because they use google tools.  I am in China behind the great wall of china and when I posted the previous post I was connected to VPN (not working at time).  This post was after VPN was working.  So, they must use googleapis.com or something for formatting that did not get called when I wrote the previous post without using VPN.  So, sorry for the previous mess.



[TOPIC: post.html]
#10

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

I just tried adding this line

floor:addEventListener("collision", CollisionWithLine)

 

Still no help.

 

I guess it doesn't matter which one we listen to.  It will just depend which one we want to be object1, right?



[TOPIC: post.html]
#11

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,814 posts
  • Corona SDK

event.object1 and event.object2 are only for use with runtime collision listeners. Local collision listeners, which you are using here, use event.target for the object that was hit (i.e. the object that had a collision listener applied to it), and event.other for the object that collided with it.



[TOPIC: post.html]
#12

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

Thank you SOOO much!  That worked perfectly! 

 

I read in there -

When the event is detected with a table listener within an object, certain properties are replaced:

  • object1 → target
  • object2 → other
  • element1 → selfElement
  • element2 → otherElement

But, can you explain what a runtime listener is? 

Thank you once again!



[TOPIC: post.html]
#13

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,814 posts
  • Corona SDK

A runtime listener runs across all objects, waiting for a collision between any two objects. Using a local collision listener allows you to be more targeted in terms of what collisions you do and don't want to track.

 

An example would be the rings in Sonic The Hedgehog. When he gets hit and they fly all over the place, you wouldn't want a listener to be running every time the rings collided with each other or platforms, enemies etc. It would just slow everything down.

 

So you'd put a local listener on Sonic and say 'If sonic gets hit by a ring, collect the ring'.



[TOPIC: post.html]
#14

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

Thank you!

 

Two more questions if I may bother you.

 

I am trying to learn destroy method, but having trouble getting it to work.  So, for right now, I just made the object invisible.

 

However, the BIGGER problem I am having is the text inside the circle.

I figured out the immediate collisions were caused by the text being inside the circle.

Which is fine.  I fixed it by checking if the id's were the same I ignored the collisions.

 

The problem is this...

physics.addBody(c, {density = 0.01, radius = radius, bounce = 0.0})

physics.addBody(text, {density = 0.01, radius = radius, bounce = 0.0})

 

When the circle hits the bottom it disappears.  Great.  However, the text has stopped moving because the circle stopped moving (so it won't hit the floor).  I am not able to try to reference the text by its .id

Example I tried using id from c to make text.id invisible but couldn't do it from inside the listener.

 

Is there a way to make those 2 things a NEW GROUP.  Example: Something like this...

smallGroup:insert©

smallGroup:insert(text)

Then do physics.addBody(smallGroup, ...)

 

I already tried it - didn't work, but that would be ideal, then I can make the smallGroup invisible and then delete it.

 

Thanks!



[TOPIC: post.html]
#15

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

This is the code I tried to destroy the obj

I put this inside function CollisionWithLine(event)

 

 

local function removeObject()
        display.remove(event.obj)
    end

timer.performWithDelay(1, removeObjects, 1)



[TOPIC: post.html]
#16

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,814 posts
  • Corona SDK

Yes, you want to make your circle object and text a group, and then make that a physics object. Create your circle and text objects then:

 

 
local g = display.newGroup()
 
g:insert(c)
g:insert(text)
 
physics.addBody(g, {density = 0.01, radius = radius, bounce = 0.0})
g:addEventListener("collision",collisionWithLine)
 
g.id = choice
g.objective = objective
g.myName = choice
 
group:insert(g)
 
 
 
 

 

In your removal code, you called the function removeObject then called it using removeObjects.

 

That corrected, the object removal code should work (I think), maybe put a longer delay, say 50ms? And remember to make event.obj = nil.



[TOPIC: post.html]
#17

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

  VPN not working so let's see if I can format this response or not.
 
I am about to pull my hair out!  I am trying to learn from what you wrote and run with it.  It worked great with the touch event (making the circle and text into g).  If I touch one circle that one circle disappears (circle and text)- GREAT!  but, for the other event if collision with line then they ALL disappear instantly.
According to messages I print.  It appears as though, as soon as the first circle touches the line, then all circles touch the line!  So, it is as if g is being done for ALL circles for the collision event instead of different g.  Yet, it worked fine for the touch event.
 
Any ideas?  I am not going to post my code, because a) almost identical to above and b) VPN not working so I don't know if this will format well.
 



[TOPIC: post.html]
#18

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,814 posts
  • Corona SDK

Put the code in the lua tags as I mentioned above, and paste in from your code editor. That will help with the formatting.



[TOPIC: post.html]
#19

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

function CollisionWithLine(event)
	local obj = event.target
	local cid = obj.id
	local objective = obj.objective
	local targ = event.other
	
	if ( obj == nil) then
		print("nothing in obj")
		return false
	end
	
	if ( targ == nil) then
		print("nothing in targ")
		return false
	end
	
	if targ.myName == obj.myName then
		print("Ignore - circle and text hitting each other")  -- should no longer happen but did twice out of 100.
		return false
	end
	
	if event.phase == "began" then
		if targ.myName == "Floor" then
			print ("Circle number " .. cid .. " collided with floor!")
			print ("obj1 is " .. targ.myName .. " obj2 is " .. obj.myName)
			print ("objective is " .. objective)
			
			-- then remove the object after 1 cycle
			local function removeObject()
				obj.isVisible = false
				display.remove(obj)
				obj = nil
			end
			timer.performWithDelay(50, removeObject, 1)
		end
	end

function touchCircle(event)
	local obj = event.target
	local cid = obj.id
	local objective = obj.objective
	
	if event.phase == "began" then
		print ("Circle number " .. cid .. " was clicked!")
		print ("objective is " .. objective)
		obj.isVisible = false
	end
	
end

then inside my create circle function

        g:insert(c)
	text:setTextColor(0,0,1,255)
	g:insert(text)
	
	physics.addBody(g, {density = 0.01, radius = radius, bounce = 0.0})
	g:setLinearVelocity(0,speed)
	g:addEventListener("touch", touchCircle)  -- to make it touchable
	g:addEventListener("collision", CollisionWithLine)  -- to make it check if collided.
	g.id = choice
	g.objective = objective
	g.myName = choice

So, as you can see, the 2 listeners were setup with the same call (using g). Thanks for your help!

[TOPIC: post.html]
#20

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

well, I thought I would be smart and make an array of g, but even that didn't matter! SOMETHING crazy is going on. As soon as touched the line all the circles disappeared. Yet, it worked with touch. I can understand if they BOTH didn't work, but for one to work and the other not?

[TOPIC: post.html]
#21

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,814 posts
  • Corona SDK

You need to create a fresh 'local g' display group for every circle&text object you create. Otherwise you have one big display group called 'g' which contains all the circles and text, so when any element of 'g' hits the line, the whole display group is removed.



[TOPIC: post.html]
#22

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

I think I am doing that. In my createCircle function I have local g = display.newGroup() isn't that what you are talking about? Plus why would it make the whole display group disappear when it touches a line and not when I click on a circle? It "seems" (in MHO) that it should do both the same way. Thanks!

[TOPIC: post.html]
#23

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,814 posts
  • Corona SDK

Can you post all the code?



[TOPIC: post.html]
#24

universalenglishinchina

[GLOBAL: userInfoPane.html]
universalenglishinchina
  • Contributor

  • 103 posts
  • Corona SDK

I made a short project that has everything main.lua
local composer = require "composer"

local scene = composer.scene

local physics = require("physics")
physics.start()

composer.isDebug = true

display.setStatusBar(display.HiddenStatusBar)  

_W = display.contentWidth
_H = display.contentHeight

local physics = require "physics"
physics.setGravity( 0, 0 )

local function main()
	composer.gotoScene( "ifc.startPlay" )
end
timer.performWithDelay(200,main)
StartPlay.lua
local composer = require( "composer" )

local scene = composer.newScene()

-- -----------------------------------------------------------------------------------------------------------------
-- All code outside of the listener functions will only be executed ONCE unless "composer.removeScene()" is called.
-- -----------------------------------------------------------------------------------------------------------------

--local circleGroup = display.newGroup()

local circles = {}
local texts = {}

-- "scene:create()"
function scene:create( event )

    local sceneGroup = self.view
	print("_W and _H is " .. _W .. _H )

    local floor = display.newImageRect(sceneGroup,"images/floor.png",_W,2)
	floor.x=_W/2
	floor.y=_H-1
	floor.myName="Floor"
	floor.id="Floor"
	sceneGroup:insert(floor)
	--physics.addBody(floor, "static", {isSensor = True})
	physics.addBody(floor, "static")

	level1b( sceneGroup, 20, 30, 40)
	math.randomseed( os.time() )
	 
end

function level1b( group, objective, speed, points)
	local created=0
	local loop_counter=0
	local i=0
	local j=0
	-- worry about points later	
	repeat
		loop_counter=loop_counter+1
		j=math.floor(loop_counter/5)
		i=loop_counter-j*5
		created = created+1
		createCircle(group, 60*i+30,-70*j, 28, created, speed, objective)
	until (created == 100)
end

function createCircle(group, xCenter, yCenter, radius, created, speed, objective)
-- I noticed I am not really using this group - is that a problem?
	local c =  display.newCircle(group, xCenter, yCenter, radius)
	local choice=math.random(1,100000)
	local text = display.newText(group,choice,xCenter,yCenter,Helvetica, 12)
	local g = display.newGroup()
	g:insert(c)
	text:setTextColor(0,0,1,255)
	g:insert(text)
	
	physics.addBody(g, {density = 0.01, radius = radius, bounce = 0.0})
	g:setLinearVelocity(0,speed)
	g:addEventListener("touch", touchCircle)  -- to make it touchable
	g:addEventListener("collision", CollisionWithLine)  -- to make it check if collided.
	g.id = choice
	g.myName = choice
	circles[created]=c
	texts[created]=text

end

function touchCircle(event)
	local obj = event.target
	local cid = obj.id
	
	if event.phase == "began" then
		print ("Circle number " .. cid .. " was clicked!")
		obj.isVisible = false
	end
end

function CollisionWithLine(event)
	local obj = event.target
	local cid = obj.id
	local targ = event.other
	
	if event.phase == "began" then
		if targ.myName == "Floor" then
			print ("Circle number " .. cid .. " collided with floor!")
			print ("obj1 is " .. targ.myName .. " obj2 is " .. obj.myName)
			obj.isVisible = false
			-- then remove the object after 50 cycles
--			local function removeObject()        -- took this out to show objects going invisible enough for this demo.
--				obj.isVisible = false
--				display.remove(obj)
--				obj = nil
--			end
--			timer.performWithDelay(50, removeObject, 1)
		end
	end
end

-- "scene:show()"
function scene:show( event )

    local sceneGroup = self.view
    local phase = event.phase

    if ( phase == "will" ) then
        -- Called when the scene is still off screen (but is about to come on screen).
    elseif ( phase == "did" ) then
        -- Called when the scene is now on screen.
        -- Insert code here to make the scene come alive.
        -- Example: start timers, begin animation, play audio, etc.
    end
end

-- "scene:hide()"
function scene:hide( event )

    local sceneGroup = self.view
    local phase = event.phase

    if ( phase == "will" ) then
        -- Called when the scene is on screen (but is about to go off screen).
        -- Insert code here to "pause" the scene.
        -- Example: stop timers, stop animation, stop audio, etc.
    elseif ( phase == "did" ) then
        -- Called immediately after scene goes off screen.
    end
end

-- "scene:destroy()"
function scene:destroy( event )

    local sceneGroup = self.view

    -- Called prior to the removal of scene's view ("sceneGroup").
    -- Insert code here to clean up the scene.
    -- Example: remove display objects, save state, etc.
end

-- Listener setup
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )

return scene


[TOPIC: post.html]
#25

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,814 posts
  • Corona SDK

Try adding sceneGroup:insert(g) at the bottom of createCircle.




[topic_controls]
Page 1 of 2 1 2
 
[/topic_controls]