Hi everyone,
I’ve been attempting to solve this problem for the past few days, tried a few approaches, but all unsuccessful.
So to start off describing my problem, let me first describe what I attempting to achieve.
This game i’m making involves objects colliding with each other and combining to form a new object. For example, when two different coloured rectangles collide, a new rectangle with the combined width of the two rectangles and a new colour is formed.
Thus this new rectangle needs to have physics properties, as well as the collision event listener attached to it as well. The two previous rectangles then fade into alpha = 0 using transition.to and onComplete, is removed. The code is as follow.
local function RectCollision ( self, event ) local phase = event.phase local other = event.other print( self.width, other.width ) local new\_width = self.width+other.width local forceModifier = 0.01 local function CombineRects () transition.to( self, { time = 400, transition = easing.inOutCubic, alpha = 0 } ) transition.to( other, { time = 400, transition = easing.inOutCubic, alpha = 0 } ) local CombinedRect = display.newRect( self.x, self.y, 10, self.height ) CombinedRect.fill = self.colour CombinedRect.colourname = self.colourname CombinedRect.type = 'rect' CombinedRect.alpha = 0 transition.to( CombinedRect, { time = 400, transition = easing.inOutCubic, alpha = 1, width = new\_width, onStart = function() display.remove(self) ; display.remove(other) end } ) timer.performWithDelay( 20, physics.addBody( CombinedRect, {density = 1.8, bounce = 0, friction = 10} ) ) CombinedRect:applyForce( forceModifier\*(halfW-CombinedRect.x), forceModifier\*(halfH-CombinedRect.y), CombinedRect.x, CombinedRect.y ) CombinedRect.touch = RectControl CombinedRect:addEventListener("touch") CombinedRect.collision = RectCollision CombinedRect:addEventListener("collision") mapGroup:insert(CombinedRect) if (phase == 'began') then print(phase, self.colourname, 'collided with', other.colourname, other.type) if other.type == 'rect' then ObjColourBehaviour( self, other ) timer.performWithDelay( 40, CombineRects ) elseif other.type == 'ObjCircle' then timer.performWithDelay( 40, reSize(other) ) --reSizeObj1 = true --timer.performWithDelay( 1000, physics.removeBody(other) ) --timer.performWithDelay( 1000, physics.addBody( other, 'static', {radius = other.path.radius, density = 1, bounce = 0.3, friction = 10} ) ) end elseif (phase == 'ended') then end return true end
This listener functions is found in the same file where the rectangles are created, i.e. classes.objects. Which is called during the scene:create function of the game itself, a separate scene called tutorial… I’ve tried calling it during the will and did phase of the scene:show as well but it doesn’t work.
The new rectangles spawn as working, but the the physics collision boundaries still follow the old rectangles.
On a related note, I have two circles, also physics bodies, which the player has to aim the combined rectangles at, if the rectangles do not have the same colour of the circle, this circle will increase in size via the transition.to method.I also use a similar method, timer.performWithDelay to update the physics.addBody but it doesn’t work as well. But I keep getting the error that says physics addBody cannot be called when the world is locked and in the middle of number crunching.
I have tried removing the previous physics body with physics.removeBody (via timer as well) before using timer to call physics.addBody, in an attempt to ‘reset’ the physics bodies. I have also varied the timers, from 20ms to 1000ms but it doesn’t work.
I’ve read the collision detection guide and understand the limitations, the guide suggested to use timer.performWithDelay, which is why I used it in my code above. I also tried to put the CombineRects function outside the collision listener function with it’s own parameters which the collision handler will pass when it calls it, but it doesn’t work.
This is from the tutorial scene file where it calls the objects
function scene:show( event ) local sceneGroup = self.view local phase = event.phase if phase == "will" then -- Called when the scene is still off screen and is about to move on screen physics.start() physics.setGravity ( 0, 0 ) elseif phase == "did" then -- Called when the scene is now on screen -- -- INSERT code here to make the scene come alive -- e.g. start timers, begin animation, play audio, etc -- load scripted tilemap from tutorialLvl.lua local map = {} map.level = require( "levels.tutorialLvl" ) local mapGroup = newObjects( tileSize, tileSize, map ) --sceneGroup:insert( mapGroup ) end end
All help to solve this problem will be much much appreciated.