Bigger touch detection area for display object

Hi everyone!,

I am having the same problem as a previous archived problem:

https://forums.coronalabs.com/topic/59614-bigger-touch-detection-area/

The only problem I am having is that the two awnsers that were given can’t be used in my example because:

  1. I don’t use image’s for objects just display.newpolygon

  2. I can’t use weld joints because my game doesn’t have physics.

I tried the following:

-- spawning function spawnShapes = function ( event ) local startX = mathRandom(50, w-50) local randomInt = mathRandom(difficultyTotal) print( randomInt ) local shape if(randomInt \<= (difficulty[1])) then shape = shapes[mathRandom(3)] elseif (randomInt \<= (difficulty[1]+difficulty[2])) then shape = shapes[4] else shape = shapes[5] end local color = colors[mathRandom(#colors)] local object if(shape == "circle") then object = display.newCircle( startX, -100, circleRad ) elseif(shape == "star") then --for beter touchable area object = display.newPolygon( startX, -100, vertices["star"] ) local touchObject = display.newRect( startX, -100, 100, 100 ) --object to be touched touchObject:setFillColor(0,0,0,1) touchObject.id = "star" touchObject.isHitTestable = true touchObject.connect = object object.connect = touchObject touchObject.touch = objectTouched transition.moveBy( touchObject, { y=h+300, time=difficulty[4], transition=easing.linear }) --move object down touchObject:addEventListener("touch", touchObject) sceneGroup:insert(touchObject) else object = display.newPolygon( startX, -100, vertices[shape] ) end object:setFillColor( colorsStat[color][1],colorsStat[color][2],colorsStat[color][3] ) object.enterFrame = offScreen object.touch = objectTouched object.strokeWidth = strokeThick object.stroke = strokeColors[color] object.id = shape Runtime:addEventListener( "enterFrame", object ) object:addEventListener( "touch", object ) transition.moveBy( object, { y=h+300, time=difficulty[4], transition=easing.linear }) --move object down sceneGroup:insert(object) end

I have touch object behind the first object but i don’t know how to delete it:

local function objectTouched(self, event) if (event.phase == "began") then --remove adjacent object if self.connect == not nil then --delete object print( "connected" ) Runtime:removeEventListener("enterFrame", self.connect) self.connect:removeSelf() end scoreLabel.text = score --delete object Runtime:removeEventListener("enterFrame", self) self:removeSelf() end end

Hi @Cing2,

One option for you is to place both the star and “touchObject” into a display group (display.newGroup()) and then detect touches on the entire group, not on either object individually.

Probably a good idea to use children anchoring on the group as well:

https://docs.coronalabs.com/api/type/GroupObject/anchorChildren.html

Hope this helps,

Brent

Thanks for the help.

I have three questions:

  1. How can I also add the objects to the sceneGroup because a object can only have 1 parent?

  2. How do I know if a object is a starObject because i have other display objects that don’t need a additional object?

  3. And how do i delete both objects of the starGroup?

Hi @Cing2,

  1. Basically, you’d insert the group (containing the two objects) into the sceneGroup.

  2. I suppose you could assign a property to the group like “.isStarObject = true” and then detect it later using that.

  3. If you delete the group, both of its children (star and touch-able part) will be destroyed with it.

Hope this helps,

Brent

Really thanks for the help @Brent Sorrentino.

Btw i made a seperate group for the objects and I don’t put them in the sceneGroup

I have 1 more question: How does the table of the group look like after I add the starGroup, like what is the parent of a object in the starGroup.

I get an error on the line specified below after I remove the objectsGroup what previous was my scenegroup.

local function offScreen(self, event) if(self.y == nil) then return elseif(self.y \> (h+100)) then if(self.id == "star" or self.id == "gold") then --death print( "Missed object" ) death() end Runtime:removeEventListener("enterFrame", self) if(self.isStarObject) then self.parent:removeSelf() -- on this line I get an error else self:removeSelf() end end end

This is how the function is called;

touchObject.enterFrame = offScreen touchObject:addEventListener("touch", touchObject)

GameOverFunction:

local function GameOver() if running then running = false timer.cancel( spawnTmr ) spawnTmr = nil for i=1, objectsGroup.numChildren do if objectsGroup[i] ~= nil then Runtime:removeEventListener("enterFrame", objectsGroup[i]) transition.cancel(objectsGroup[i]) end end objectsGroup:removeSelf() objectsGroup = display.newGroup() composer.gotoScene( "GameoverScene", { effect="fade", time=500, params={ points = score, mod=mode } } ) end end

Hi @Cing2,

This section of the Display Objects guide might explain it better:

https://docs.coronalabs.com/guide/media/displayObjects/index.html#hierarchy

Basically, the “stage” is the master display group of all… nothing has higher priority than that (except “native” objects, but that’s sort of a separate issue not related to what you’re doing).

Next in line, within Composer, every scene has a “view”… that is fundamental to how Composer works, and that’s the group you’re accessing with references like “sceneGroup”.

Once you insert a new display group, i.e. “display.newGroup()”, into “sceneGroup”, it becomes a child of “sceneGroup”. Then, once you insert display objects into that new group you created, that group becomes the parent of those objects… and the parent of that group is “sceneGroup”.

Hope that makes sense,

Brent

Yes that exactly did make sense and it solved the problem!

Thanks you very much @Brent Sorrentino

Here is the code that solved the problem:

local function GameOver() print("gameover") if running then running = false timer.cancel( spawnTmr ) spawnTmr = nil for i=1, objectsGroup.numChildren do if objectsGroup[i] ~= nil then if objectsGroup[i][1] ~= nil and objectsGroup[i][1].isStarObject then Runtime:removeEventListener("enterFrame", objectsGroup[i][1]) transition.cancel(objectsGroup[i][1]) transition.cancel(objectsGroup[i][2]) else Runtime:removeEventListener("enterFrame", objectsGroup[i]) transition.cancel(objectsGroup[i]) end end end objectsGroup:removeSelf() objectsGroup = display.newGroup() composer.gotoScene( "GameoverScene", { effect="fade", time=500, params={ points = score, mod=mode } } ) end end

Hi @Cing2,

One option for you is to place both the star and “touchObject” into a display group (display.newGroup()) and then detect touches on the entire group, not on either object individually.

Probably a good idea to use children anchoring on the group as well:

https://docs.coronalabs.com/api/type/GroupObject/anchorChildren.html

Hope this helps,

Brent

Thanks for the help.

I have three questions:

  1. How can I also add the objects to the sceneGroup because a object can only have 1 parent?

  2. How do I know if a object is a starObject because i have other display objects that don’t need a additional object?

  3. And how do i delete both objects of the starGroup?

Hi @Cing2,

  1. Basically, you’d insert the group (containing the two objects) into the sceneGroup.

  2. I suppose you could assign a property to the group like “.isStarObject = true” and then detect it later using that.

  3. If you delete the group, both of its children (star and touch-able part) will be destroyed with it.

Hope this helps,

Brent

Really thanks for the help @Brent Sorrentino.

Btw i made a seperate group for the objects and I don’t put them in the sceneGroup

I have 1 more question: How does the table of the group look like after I add the starGroup, like what is the parent of a object in the starGroup.

I get an error on the line specified below after I remove the objectsGroup what previous was my scenegroup.

local function offScreen(self, event) if(self.y == nil) then return elseif(self.y \> (h+100)) then if(self.id == "star" or self.id == "gold") then --death print( "Missed object" ) death() end Runtime:removeEventListener("enterFrame", self) if(self.isStarObject) then self.parent:removeSelf() -- on this line I get an error else self:removeSelf() end end end

This is how the function is called;

touchObject.enterFrame = offScreen touchObject:addEventListener("touch", touchObject)

GameOverFunction:

local function GameOver() if running then running = false timer.cancel( spawnTmr ) spawnTmr = nil for i=1, objectsGroup.numChildren do if objectsGroup[i] ~= nil then Runtime:removeEventListener("enterFrame", objectsGroup[i]) transition.cancel(objectsGroup[i]) end end objectsGroup:removeSelf() objectsGroup = display.newGroup() composer.gotoScene( "GameoverScene", { effect="fade", time=500, params={ points = score, mod=mode } } ) end end

Hi @Cing2,

This section of the Display Objects guide might explain it better:

https://docs.coronalabs.com/guide/media/displayObjects/index.html#hierarchy

Basically, the “stage” is the master display group of all… nothing has higher priority than that (except “native” objects, but that’s sort of a separate issue not related to what you’re doing).

Next in line, within Composer, every scene has a “view”… that is fundamental to how Composer works, and that’s the group you’re accessing with references like “sceneGroup”.

Once you insert a new display group, i.e. “display.newGroup()”, into “sceneGroup”, it becomes a child of “sceneGroup”. Then, once you insert display objects into that new group you created, that group becomes the parent of those objects… and the parent of that group is “sceneGroup”.

Hope that makes sense,

Brent

Yes that exactly did make sense and it solved the problem!

Thanks you very much @Brent Sorrentino

Here is the code that solved the problem:

local function GameOver() print("gameover") if running then running = false timer.cancel( spawnTmr ) spawnTmr = nil for i=1, objectsGroup.numChildren do if objectsGroup[i] ~= nil then if objectsGroup[i][1] ~= nil and objectsGroup[i][1].isStarObject then Runtime:removeEventListener("enterFrame", objectsGroup[i][1]) transition.cancel(objectsGroup[i][1]) transition.cancel(objectsGroup[i][2]) else Runtime:removeEventListener("enterFrame", objectsGroup[i]) transition.cancel(objectsGroup[i]) end end end objectsGroup:removeSelf() objectsGroup = display.newGroup() composer.gotoScene( "GameoverScene", { effect="fade", time=500, params={ points = score, mod=mode } } ) end end