Collision bug (live app at the app stores)

Hi guys, 

I am an indie game maker, and I have made 2 mobile games using corona SDK (Pixelpartyapps.com)

The guy who wrote the code for me, is no longer available for helping with it, so I wonder if someone here can help me as it seem like a small issue to solve

The game is an endless run & jumper.

The character runs through the platforms, the left side of the screen is the jump button, and the right is the hit button which is used to neutralize enemies.

My main problem is that once in a while, when I use jump and hit together, the jump button stop reacting.

It can happen when I press them simultaneously, or just one after another.

For those who are interested in downloading the game to get a better feel, here are the links to both stores:

Android: https://play.google.com/store/apps/details?id=com.gmail.asafgibor.Asaf_Runner

iPhone: https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=1102182242&mt=8

It might take couple of tries to experience it, but (unfortunately) it happens, pretty random, but happens…

Here is the collision part of the code:

 function character:collision(event) if event.phase == "began" then if event.other.id == "block" then if self.contentBounds.xMax \<= event.other.contentBounds.xMin then self.isJumpPossible = 0; self.isJumpPressed = false; elseif self.contentBounds.yMax \<= event.other.contentBounds.yMin then self.isJumpPossible = 1+canSecondJump; self.firstJump = true; if self.sequence ~= "run" and not self.isHitting then self:setSequence("run"); self:play(); end end elseif event.other.id == "coin" then --audio.play(powerUpSFX, {channel = audio.findFreeChannel()}); event.other.hasTouchedCharacter = true; elseif event.other.id == "heart" then audio.play(powerUpSFX, {channel = audio.findFreeChannel()}); event.other.hasTouchedCharacter = true; elseif event.other.id == "invincibility" then audio.play(powerUpSFX, {channel = audio.findFreeChannel()}); event.other.hasTouchedCharacter = true; self.isDamaged = invincibilityTime; elseif event.other.id == "enemy" then if not self.isHitting then if (self.contentBounds.yMax) \<= (event.other.contentBounds.yMin+6) then audio.play(jumpEnemySFX, {channel = audio.findFreeChannel()}); if event.other.name == "purpleEnemy" then event.other:setLinearVelocity(0, 200); end if self.isJumpPressed then audio.play(jumpSFX, { channel = audio.findFreeChannel() }); self:setLinearVelocity(gameSpeed, -jumpPower); self.activateJump = true; self.maxJump = character.y-maxJumpOffset; if not self.isHitting then self:setSequence("jump"); self:play(); end self.isJumpPressed = true; else self:setLinearVelocity(gameSpeed, -jumpPower); end else if self.isDamaged \<= 0 then audio.play(hitByEnemySFX, {channel = audio.findFreeChannel()}); currentLifes = mMax(0, currentLifes-event.other.damage); self.isDamaged = 120; end end else event.other.isDamaged = 120; end end elseif event.phase == "ended" then if event.other.id == "block" then --self.firstJump = nil; --self.isJumpPossible = self.isJumpPossible-1; end end end

I’d appreciate any help, and if there is any other info needed, let me know, and I will post.

Thanks!

Asaf

It think people are going to need to see your Jump and Hit button handling code.

Rob

jumpButton = display.newGroup(); scene.view:insert(jumpButton); local jumpOn = display.newImageRect(jumpButton, "IMG/gameScene/jumpButtonOn.png", 80, 80); local jumpOff = display.newImageRect(jumpButton, "IMG/gameScene/jumpButtonOff.png", 80, 80); jumpOn.isVisible = false; jumpButton.x, jumpButton.y = leftSide+60, bottomSide-60; jumpButton.alpha = 0.7; hitButton = display.newGroup(); scene.view:insert(hitButton); local hitOn = display.newImageRect(hitButton, "IMG/gameScene/hitButtonOn.png", 80, 80); local hitOff = display.newImageRect(hitButton, "IMG/gameScene/hitButtonOff.png", 80, 80); hitOn.isVisible = false; hitButton.x, hitButton.y = rightSide-60, bottomSide-60; hitButton.alpha = 0.7; local jumpTab = {nil, 1}; local hitTab = {nil, 2}; local background = backgroundLayer[1]; function background:touch(event) --we put the touch on our biggest object, the background that covers the whole screen if #touches \>= 2 then local pass; for i = 1, #touches do if touches[i][1] == event.id then pass = true; break; end end if not pass then return; end end if event.phase == "began" then if event.x \< centerX then jumpTab[1] = event.id; touches[#touches+1] = jumpTab; if (character.isJumpPossible or 0) \> 0 then -- if not character.firstJump then character.isJumpPossible = character.isJumpPossible-1; -- end audio.play(jumpSFX, { channel = audio.findFreeChannel }); display.getCurrentStage():setFocus(self); character:setLinearVelocity(gameSpeed, -jumpPower); character.activateJump = true; if character.isJumpPossible \<= 0 and canSecondJump \> 0 then character.maxJump = character.y-secondJumpOffset; else character.maxJump = character.y-maxJumpOffset; end if not character.isHitting then character:setSequence("jump"); character:play(); end character.isJumpPressed = true; else character.isJumpPressed = true; end self.isFocus = true; jumpButton[1].isVisible = true; jumpButton[2].isVisible = false; else self.isFocus = true; hitTab[1] = event.id; touches[#touches+1] = hitTab; if timeTillNextHit \<= 0 then audio.play(attackSFX, { channel = audio.findFreeChannel }); hitButton[1].isVisible = true; hitButton[2].isVisible = false; timeTillNextHit = 60\*2; character.isHitting = true; if not (character.sequence == "hit") then character:setSequence("hit"); character:play(); end end end elseif event.phase == "ended" and self.isFocus then display.getCurrentStage():setFocus(nil); if touches[1] and (touches[1][1] or "") == event.id then if touches[1][2] == 1 then character.activateJump = nil; character.isJumpPressed = nil; jumpButton[1].isVisible = false; jumpButton[2].isVisible = true; elseif touches[1][2] == 2 then if timeTillNextHit \<= 0 then hitButton[1].isVisible = false; hitButton[2].isVisible = true; end end table.remove(touches, 1); elseif touches[2] and(touches[2][1] or "") == event.id then if touches[2][2] == 1 then character.activateJump = nil; character.isJumpPressed = nil; jumpButton[1].isVisible = false; jumpButton[2].isVisible = true; elseif touches[2][2] == 2 then if timeTillNextHit \<= 0 then hitButton[1].isVisible = false; hitButton[2].isVisible = true; end end table.remove(touches, 2); end end end background:addEventListener("touch", background); end

Thanks for notifying, here is the jump & hit button part.

Anything else needed?

Honestly it’s really hard to track what’s going on with the different flags, button states, multi-touch hits etc.

What I would suggest is to not put this on the background but use two separate images (well four since you’re changing the button while it’s being pressed) and have a dedicated jump function and a dedicated hit function. This will let you clean your code up.

There is a trick though. It seems you want a bigger touch area than the graphic which is why you’re testing to see if your touch came in on the left half or right half of the screen. To do something similar, make your button graphics have a larger transparent area.

+--------+ | | | | |O | +--------+

Where the O is your actual button graphic and the box is invisible padding around it. Then put a touch handler on the graphic.

I think this will help you in the long run.

Rob

Hi Rob,

Thanks for you answer!
Since I do not know how to program- I had no success executing the recommended change, but in one way or another, it did help me to get a deeper insight of what is causing the problem.

More specific explanation about the bug-

The character is jumping from the ground and can add one more jump in mid-air, total of 2 jumps.

Tapping the jump button after 2 jumps won’t do anything.

When he touches the ground, that resets that count, and give the character the ability to jump again.

As it looks like, the hit frames are the ones causing the problem, I’m guessing that they are not assigned as part of the character’s body, therefore, when he touches the ground while hitting, it does not reset the jump count, and do not give the character the ability to add one more jump (to a total of 2 jumps).

Knowing that I tried to change couple of lines at the code but pretty much got lost.

Is there any other info needed beside the lines provided above?

It think people are going to need to see your Jump and Hit button handling code.

Rob

jumpButton = display.newGroup(); scene.view:insert(jumpButton); local jumpOn = display.newImageRect(jumpButton, "IMG/gameScene/jumpButtonOn.png", 80, 80); local jumpOff = display.newImageRect(jumpButton, "IMG/gameScene/jumpButtonOff.png", 80, 80); jumpOn.isVisible = false; jumpButton.x, jumpButton.y = leftSide+60, bottomSide-60; jumpButton.alpha = 0.7; hitButton = display.newGroup(); scene.view:insert(hitButton); local hitOn = display.newImageRect(hitButton, "IMG/gameScene/hitButtonOn.png", 80, 80); local hitOff = display.newImageRect(hitButton, "IMG/gameScene/hitButtonOff.png", 80, 80); hitOn.isVisible = false; hitButton.x, hitButton.y = rightSide-60, bottomSide-60; hitButton.alpha = 0.7; local jumpTab = {nil, 1}; local hitTab = {nil, 2}; local background = backgroundLayer[1]; function background:touch(event) --we put the touch on our biggest object, the background that covers the whole screen if #touches \>= 2 then local pass; for i = 1, #touches do if touches[i][1] == event.id then pass = true; break; end end if not pass then return; end end if event.phase == "began" then if event.x \< centerX then jumpTab[1] = event.id; touches[#touches+1] = jumpTab; if (character.isJumpPossible or 0) \> 0 then -- if not character.firstJump then character.isJumpPossible = character.isJumpPossible-1; -- end audio.play(jumpSFX, { channel = audio.findFreeChannel }); display.getCurrentStage():setFocus(self); character:setLinearVelocity(gameSpeed, -jumpPower); character.activateJump = true; if character.isJumpPossible \<= 0 and canSecondJump \> 0 then character.maxJump = character.y-secondJumpOffset; else character.maxJump = character.y-maxJumpOffset; end if not character.isHitting then character:setSequence("jump"); character:play(); end character.isJumpPressed = true; else character.isJumpPressed = true; end self.isFocus = true; jumpButton[1].isVisible = true; jumpButton[2].isVisible = false; else self.isFocus = true; hitTab[1] = event.id; touches[#touches+1] = hitTab; if timeTillNextHit \<= 0 then audio.play(attackSFX, { channel = audio.findFreeChannel }); hitButton[1].isVisible = true; hitButton[2].isVisible = false; timeTillNextHit = 60\*2; character.isHitting = true; if not (character.sequence == "hit") then character:setSequence("hit"); character:play(); end end end elseif event.phase == "ended" and self.isFocus then display.getCurrentStage():setFocus(nil); if touches[1] and (touches[1][1] or "") == event.id then if touches[1][2] == 1 then character.activateJump = nil; character.isJumpPressed = nil; jumpButton[1].isVisible = false; jumpButton[2].isVisible = true; elseif touches[1][2] == 2 then if timeTillNextHit \<= 0 then hitButton[1].isVisible = false; hitButton[2].isVisible = true; end end table.remove(touches, 1); elseif touches[2] and(touches[2][1] or "") == event.id then if touches[2][2] == 1 then character.activateJump = nil; character.isJumpPressed = nil; jumpButton[1].isVisible = false; jumpButton[2].isVisible = true; elseif touches[2][2] == 2 then if timeTillNextHit \<= 0 then hitButton[1].isVisible = false; hitButton[2].isVisible = true; end end table.remove(touches, 2); end end end background:addEventListener("touch", background); end

Thanks for notifying, here is the jump & hit button part.

Anything else needed?

Honestly it’s really hard to track what’s going on with the different flags, button states, multi-touch hits etc.

What I would suggest is to not put this on the background but use two separate images (well four since you’re changing the button while it’s being pressed) and have a dedicated jump function and a dedicated hit function. This will let you clean your code up.

There is a trick though. It seems you want a bigger touch area than the graphic which is why you’re testing to see if your touch came in on the left half or right half of the screen. To do something similar, make your button graphics have a larger transparent area.

+--------+ | | | | |O | +--------+

Where the O is your actual button graphic and the box is invisible padding around it. Then put a touch handler on the graphic.

I think this will help you in the long run.

Rob

Hi Rob,

Thanks for you answer!
Since I do not know how to program- I had no success executing the recommended change, but in one way or another, it did help me to get a deeper insight of what is causing the problem.

More specific explanation about the bug-

The character is jumping from the ground and can add one more jump in mid-air, total of 2 jumps.

Tapping the jump button after 2 jumps won’t do anything.

When he touches the ground, that resets that count, and give the character the ability to jump again.

As it looks like, the hit frames are the ones causing the problem, I’m guessing that they are not assigned as part of the character’s body, therefore, when he touches the ground while hitting, it does not reset the jump count, and do not give the character the ability to add one more jump (to a total of 2 jumps).

Knowing that I tried to change couple of lines at the code but pretty much got lost.

Is there any other info needed beside the lines provided above?