Attempt to index field '?' a nil value error (a different one)

I see you can create polygons, but I am very bad with coordinates…

You have to… Thats the only way…

When you said the player only loses one life, did you try it multiple times?

yes i tried it multiple times

Since lives 3 and 2 are lost at the same time and changing the physics bodies to a single simple shape seems to address this, it sounds like perhaps you’re creating the multiple physics bodies so that they are separate physics bodies and not just one body. Are you using Physics Editor to generate the physics bodies?

If so, you might want to consider using it to generate simple polygons. When I let it auto trace the ships in my game, it was creating shapes that were causing errors. If you delete the auto-generated shape and click on the polygon button it will give you a triangle in the bottom right. you can drag each of the 3 points to logical places on the object. You can right-click (CTRL-Click on a Mac) to add additional points until you get your shape. See one of my pieces below:

You end up with a better fitting shape with out the complexities through you give up some perfection like around the wings on the backside of the ship.

Rob

This is actually exactly what I did to generate each of my shapes, I did not use auto-trace, I drew the polygons myself, it was giving me problems before. Should I use coordinates with Corona’s physics body maker?

No, the physics editor shapes should work just fine.

Can you set the physics draw mode to hybrid and give us a screen shot if your objects that are colliding?

Is playerHit() your collision handling function?

Another function onCollision handles collision and uses playerHit(): 

function onCollision(event) local function removeOnPlayerHit(obj1, obj2) if((obj ~= nil ) and ((obj.id == "enemy") or (obj.id == "enemy2") or (obj.id == "enemy3") or (obj.id == "enemy4"))) then display.remove(obj) end end local function showPlayerHit() local tmr\_onPlayerHit = timer.performWithDelay(1, playerHit, 1) end if event.phase == "began" then if((event.object1.id == "enemy" or event.object1.id == "enemy2" or event.object1.id == "enemy3" or event.object1.id == "enemy4") and event.object2.id == "character") then showPlayerHit() removeOnPlayerHit(event.object1, nil) elseif(event.object1.id == "character" and (event.object2.id == "enemy" or event.object2.id == "enemy2" or event.object2.id == "enemy3" or event.object2.id == "enemy4")) then showPlayerHit() removeOnPlayerHit(nil, event.object2) end end end

https://www.youtube.com/watch?v=s23FbFKniTY&feature=youtu.be

It looks like your enemies are still made up of multiple bodies instead of simple polygons. I’m not sure this is the cause. What I would suggest doing to verify what’s happening is put more print statements in your code.

For instance in your collision function print out the names of the two bodies that are colliding:

function onCollision(event)     print( "Object 1", event.object1.id, "Object 2", event.object2.id, event.phase )     ...

This will tell you the two objects that are colliding, more on that in a bit, but it will also tell you if the collision handler is being entered twice. Now you will get multiple prints since there are multiple phases, so you’re looking to see if you’re getting two “began”'s in a row.

I’ve not seen where you’re creating the object or adding the bodies. Are you by any chance adding the bodies in scene:show()? Can you post your scene:show() function if that’s the case?

All bodies are added in scene:create. There is a physics.pause in scene:hide, could that be the cause?

This is what was printed on the console on a collision:

Object 1 character Object 2 enemy3 began Object 1 character Object 2 enemy3 began Object 1 character Object 2 enemy3 began Object 1 character Object 2 enemy3 ended

On your scene that you go to when you run into an enemy… the one with the black screen and a blue button. Can you post the code for that scene?

Thanks

Rob

local composer = require( "composer" ) local scene = composer.newScene() local widget = require "widget" widget.setTheme("widget\_theme\_ios7") -- ----------------------------------------------------------------------------------- -- Code outside of the scene event functions below will only be executed ONCE unless -- the scene is removed entirely (not recycled) via "composer.removeScene()" -- ----------------------------------------------------------------------------------- local background local button -- ----------------------------------------------------------------------------------- -- Scene event functions -- ----------------------------------------------------------------------------------- local function resumeGame(event) if ( "ended" == event.phase ) then composer.gotoScene("level1") end end -- create() function scene:create( event ) local sceneGroup = self.view background = display.newRect(\_CX, \_CY, \_CW, \_CH) background:setFillColor(0) button = widget.newButton( { x = \_CX, y = \_CY, id = "button", label = "Try Again", onRelease = resumeGame } ) sceneGroup:insert(background) sceneGroup:insert(button) end -- show() function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Code here runs when the scene is still off screen (but is about to come on screen) elseif ( phase == "did" ) then -- Code here runs when the scene is entirely on screen end end -- hide() function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Code here runs when the scene is on screen (but is about to go off screen) elseif ( phase == "did" ) then -- Code here runs immediately after the scene goes entirely off screen end end -- destroy() function scene:destroy( event ) local sceneGroup = self.view -- Code here runs prior to the removal of scene's view end -- ----------------------------------------------------------------------------------- -- Scene event function listeners -- ----------------------------------------------------------------------------------- scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) -- ----------------------------------------------------------------------------------- return scene

_CX, _CY, _CW, and _CH are some globals I intend to remove.

Is it your intent that when they die and go to this scene that the level start over or resume? If you want it to start over then you should:

local function resumeGame(event) if ( "ended" == event.phase ) then composer.removeScene( "level1" ) --\<----- added this line composer.gotoScene("level1") end end

You are going back to level 1 in an in-between state. The main reason to have a cut scene like this is to give you a chance to remove the scene. This is the fastest/easiest way to reset a scene. If you wanted to do something more complex like move them back to a save point, not loose all their progress, not reset scores and such, then you have to take more effort to reset the scene yourself.

Rob

I want them to resume their progress just with one less life. Is there a “better” alternative to do this?

What is the purpose of the black screen? Do you have further plans for it?

In the sci-fi shooter I’m building in my spare time, when I take enough hits to die, I simply subtract one from my lives, hide a heart and let the game keep going. When my lives run out, then I jump to a game over scene.

I removed the black screen but the problem still occurs. 

It seems to happen when the player simultaneously hits two edges on an enemy.

Are you still getting the multiple “began” phases?