So - after a lot of hair pulling and gnashing of teeth - i've come to the conclusion that the physics implementation in Corona is not very strong...
I am trying to get a character / sprite to move (I don't want to make this reference, but it's the best way to describe it) like a doodle-jump character. Collision between the character and platform works probably 70% of the time. I've tried manipulating the "setPosition" and "SetVelocity" iteration methods and it doesn't seem to improve accuracy. Basically the sprite will occasionally vanish (with the x/y coords being reported as NaN), or it will pass through the top of the object. The object is not moving that fast...
Do I seriously have to roll my own collision system to get this to work??
This is a somewhat hacked together example of the problem. The cube can be moved by selecting the character and dragging down. Please note - this isn't very robust yet.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | -- Setup the game -- Turn off the status bar display.setStatusBar(display.HiddenStatusBar); -- Setup graphics local physics = require("physics"); physics.start(); physics.setDrawMode("hybrid"); physics.setGravity(0, 9.8); physics.setPositionIterations(16); physics.setVelocityIterations(6); -- Setup the background group local gameGroup = display.newGroup(); gameGroup.x = 0; -- Ground object local ground = display.newRect(450, 0, 320, 5); ground.x = 160; ground.y = 440; ground.objectType = "ground" groundPhysics = { -160, 0, 160, 0, 160, 10, -160, 10 }; physics.addBody(ground, "static", { density=1.0, friction=0.0, bounce=0.0, shape=groundPhysics }); gameGroup:insert(ground); -- Setup a sprite for the player playerInstance = display.newRect(100, 400, 32, 32); playerInstance.x = 100; playerInstance.y = 400; playerInstance.rotation = 0; gameGroup:insert(playerInstance); physics.addBody(playerInstance, "dynamic", { density=0.25, friction=0.15, bounce=0.0 }); playerInstance.isFixedRotation = true; playerInstance.objectType = "player"; -- Setup some vars on the playerInstance playerInstance.isFalling = false; playerInstance.xVel = 0; playerInstance.yVel = 0; -- Test jump platform local jumpPlatform = display.newRect(80, 200, 100, 50); jumpPlatform.objectType = "jumpPlatform" gameGroup:insert(jumpPlatform); physics.addBody(jumpPlatform, "static", { friction=0.3, isSensor=true} ); -- The main loop function onEnterFrame(event) -- Move the game world to keep the player onscreen if playerInstance.y <= 200 then gameGroup.y = -playerInstance.y + 200; end end -- When the player makes a tap event function onTouch(event) local t = event.target; local phase = event.phase; if phase == "began" then -- Make the object the topmost object local parent = t.parent; parent:insert(t); display:getCurrentStage():setFocus(t); -- Prevents spurious messages being sent t.isFocus = true; -- Store the initial position t.x0 = event.x - t.x; t.y0 = event.y - t.y; elseif t.isFocus == true then if phase == "moved" then elseif phase == "ended" or phase == "cancelled" then local xForce = (-1 * (event.x - playerInstance.x)) * 2.75; local yForce = (-1 * (event.y - playerInstance.y)) * 2.75; playerInstance:applyForce( 0, yForce, playerInstance.x, playerInstance.y); display.getCurrentStage():setFocus(nil); t.isFocus = false; end end end local function onCollision(self, event) local other = event.other.objectType; xVel, yVel = playerInstance:getLinearVelocity(); --debugTextField1.text = "collision between: " .. self.objectType .. " and " .. other; if event.phase == "began" then if (yVel > 0) then event.other.isSensor = false; end elseif event.phase == "ended" then event.other.isSensor = true; end end -- Setup the event listeners playerInstance.collision = onCollision; playerInstance:addEventListener("collision", playerInstance); Runtime:addEventListener("enterFrame", onEnterFrame); playerInstance:addEventListener("touch", onTouch); |
How often are you getting this result? I just tried about 40 times and couldn't replicate it unless I moused down and out of the simulator which obviously isn't an issue on device.
Were you getting it 70% with this code, or in your actual project?
This code - on the simulator. Very frequently. Just got it first time I tried, with that exact code. I just selected the square, dragged down (within the simulator window) and released. The square went just above the platform, landed on the platform - and vanished. I'm assuming it didn't actually vanish, but was ejected very quickly (linear velocity goes through the roof when this happens).
Just tried this on the device - and I get the same behavior.
try to set fps to 60, for a similar problem it worked for me.
Thanks for the suggestion - it appears to improve matters. But definitely doesn't solve it. I still get the "player" disappearing occasionally. There is something truly whacky going on.