attempt to index local 'newAstroid' (a nil value)

Hi All

I got my game running…with the exception of: When my laser fire hits an asteroid, the game crashes. The crash message mentioned “listener”  I saw briefly something about it recently in this post.

 Hey @beyond2k, I will try to help you. Check my code. It, sure, has to be with collision.

local function onCollision( event )

if ( event.phase == “began” ) then

  local obj1 = event.object1

  local obj2 = event.object2

  if ( ( obj1.myName == “laser” and obj2.myName == “asteroid” ) or

    ( obj1.myName == “asteroid” and obj2.myName == “laser” ) )

  then

   – Remove both the laser and asteroid

   display.remove( obj1 )

            display.remove( obj2 )

   for i = #asteroidsTable, 1, -1 do

    if ( asteroidsTable[i] == obj1 or asteroidsTable[i] == obj2 ) then

     table.remove( asteroidsTable, i )

     break

    end

   end

   – Increase score

   score = score + 100

   scoreText.text = "Score: " … score

  elseif ( ( obj1.myName == “ship” and obj2.myName == “asteroid” ) or

     ( obj1.myName == “asteroid” and obj2.myName == “ship” ) )

  then

   if ( died == false ) then

    died = true

    – Update lives

    lives = lives - 1

    livesText.text = "Lives: " … lives

    if ( lives == 0 ) then

     display.remove( ship )

    else

     ship.alpha = 0

     timer.performWithDelay( 1000, restoreShip )

    end

   end

  end

end

end

Runtime:addEventListener( “collision”, onCollision )       

It really helps if you look in the console log that we open behind the simulator. The full message will be recorded there with it’s full stack trace. There is so much useful information there. Everyone new to Corona should read our Debugging Guide after they get to a point of getting errors in their code:

http://docs.coronalabs.com/guide/basics/debugging/index.html

And as far as asking for help, very rarely can we speculate as to an error if all you say is “I have an error”. Use the line # information in the error (and module) to find the code around the error. Share the error and the code near the error with us and that will go a long way to helping get you quicker answers.

Rob

Hi All

Still getting random crashes.  Here is my console output:

10:05:26.154  ERROR: Runtime error
10:05:26.154  C:\Users\Andy\Documents\Corona Projects\StarExplorer\main.lua:179: attempt to compare nil with number
10:05:26.154  stack traceback:
10:05:26.154      C:\Users\Andy\Documents\Corona Projects\StarExplorer\main.lua:179: in function ‘_listener’
10:05:26.154      ?: in function <?:167>
10:05:26.154      ?: in function <?:169>
 

Here is my code:

ship:addEventListener( “touch”, dragShip )    

local function gameLoop()

    – Create new asteroid
    createAsteroid()
    
    – Remove asteroids which have drifted off screen
    for i = #asteroidsTable, 1, -1 do
        local thisAsteroid = asteroidsTable[i]
        
        if ( thisAsteroid.x < -100 or – LINE 179
             thisAsteroid.x > display.contentWidth + 100 or
             thisAsteroid.y < -100 or
             thisAsteroid.y > display.contentHeight + 100 )
        then
            display.remove( thisAsteroid )
            table.remove( asteroidsTable, i )
        end
    end
end  

I have compared my code to the tutorial, the tutorial “complete project code” and I have compared my code to arellano.marco’s code and do not see what the problem is!  :frowning:

I believe you have found a bug in the tutorial code. We never saw this while testing it, but this appears to be what’s known as a “race condition bug”. The game loop fires twice per second spawning new asteroids, but it also tries and remove any that have moved off screen. If you happen to shoot and miss any on screen asteroids and that bullet travels off screen and strikes an asteroid and the collision event is removing it and at the same time the game loop wants to remove it, the are racing to do the same job. One wins, the other tries to remove something that’s not there.

Now to fix this, you would do something like:

if ( thisAsteroid and thisAsteroid.x and thisAsteroid.x \< -100 or -- LINE 179 thisAsteroid.x \> display.contentWidth + 100 or thisAsteroid.y \< -100 or thisAsteroid.y \> display.contentHeight + 100 ) then

What this does is a) makes sure thisAsteroid exists and b ) there is an object there (it has a .x value) which creates a safety net. I’ll talk with Brent about this and see if we can find a way to avoid the race condition without the game getting overly complex.

Now if you an reproduce this with regularity, we may want to have you put some print statements in there and try to get some intel as to what’s going on.

Rob

Hi Rob

I tried this fix and now it crashes here:

11:49:11.098  ERROR: Runtime error
11:49:11.098  C:\Users\Andy\Documents\Corona Projects\StarExplorer\main.lua:181: attempt to compare number with nil
11:49:11.098  stack traceback:
11:49:11.098      C:\Users\Andy\Documents\Corona Projects\StarExplorer\main.lua:181: in function ‘_listener’
11:49:11.098      ?: in function <?:167>
11:49:11.098      ?: in function <?:169>
 

I downloaded the Tutorial main.lua from herehttps://github.com/coronalabs/GettingStarted03/archive/master.zip And it worked flawlessly.  I am going to compare my main and the tute mail once more at lunch time :slight_smile:

I’m seeing some typos on my part, folks.  If there is any finger pointing, it should be directed toward me!  Fixin’ code…

Ok!  :-)  It’s fixed and running.  Not really any deviation from the tutorial code.  The tutorial actual told me when to test, so I jumped the gun with that.  Little typos.  Check this out if you want to see the code:

https://github.com/coronalabs/GettingStarted03/archive/master.zip

I am sorry if I put you guys through too much Trouble (Rob).  I will now hack the code to make my own spin on the game :slight_smile:

No trouble at all. Encountering errors and learning how to fix them is a very important skill for a programmer. If you don’t make mistakes you won’t get that experience. Learning to read error messages is a skill that has to be groomed. Experimenting and failing is a part of this too. Thomas Edison, inventor of the light bulb has a great quote:  “I have not failed. I’ve just found 10,000 ways that won’t work.”.

Rob

Thanks Rob and to all who helped!  What did I learn? :

This forum is helpful with great people

The Tutorial had testing points; I was in too much of a hurry to see results.

The compiler finds errors.  There is a difference between a “.”  and a “:”  :slight_smile:

error.png

Hello, guys! I´ve been working in the code…im actually at chapter 5, but i got stucked one more time! :frowning:

I dont know, this time, I took my time and make my search and debugging, but,nothing, I didnt find my mistake! pls someone help me! hehe I upload and image of my error. If I understood, the error derivates in other errors… but the first line? is 0??? What??? im so confused… :wacko:  :blink:

16:40:30.358  ERROR: Runtime error

16:40:30.358  ?:0: attempt to index a nil value

16:40:30.358  stack traceback:

16:40:30.358   ?: in function ‘cancel’

16:40:30.358   C:\Users\usuario\Documents\Corona Projects\Asteroids Games\game.lua:357: in function <C:\Users\usuario\Documents\Corona Projects\Asteroids Games\game.lua:348>

16:40:30.358   ?: in function ‘dispatchEvent’

16:40:30.358   ?: in function ‘gotoScene’

16:40:30.358   C:\Users\usuario\Documents\Corona Projects\Asteroids Games\menu.lua:20: in function <C:\Users\usuario\Documents\Corona Projects\Asteroids Games\menu.lua:12>

16:40:30.358   ?: in function <?:169>

Is the variable gameLoopTimer defined in a way that it can be scene in that function? The error is saying gameLoopTimer is nil at that point.  In scene:show() just above it you should have the line:

gameLoopTimer = timer.performWithDelay( 500, gameLoop, 0 )

Do you have a “local” on the front of that?  If you do, take it off. There should be near the top a line that reads:

local gameLoopTimer

You’re declaring the variable at the top, outside of any function so any functions in that module can see it. You initialize it in scene:show, but if you put “local” on it there, then only scene:show() can see it (more specifically only code in that part of the if-then-else statement.) This is called scope.

When an object needs to be seen in more than one function you define it near the top, outside of any function so that it’s visible to everything below it.

Rob

Thank you so much, Rob! It work, but throw me another error…I believe It have to be something with creating the asteroids and a listener…I remember that we have to to “call” the asteroids with this " timer.performWithDelay(1000,function()createAsteroid()end,0)"

It was a solution in previous post, so I tried to move this in order to make work the code. But, nothing, mmm I thought, then, It was something with display groups…But nothing really works of all that mods that I made to my code, so I leave it just like It was. And this is what it appears:

18:17:44.696  Loading project from:   C:\Users\usuario\Documents\Corona Projects\Asteroids Games

18:17:44.696  Project sandbox folder: C:\Users\usuario\AppData\Local\Corona Labs\Corona Simulator\Sandbox\asteroids games-CA34EDD33CE707BFD7C5375F9D425709\Documents

18:17:46.253  ERROR: Runtime error

18:17:46.253  C:\Users\usuario\Documents\Corona Projects\Asteroids Games\game.lua:90: bad argument #-1 to ‘newImageRect’ (Proxy expected, got nil)

18:17:46.253  stack traceback:

18:17:46.253   [C]: in function ‘newImageRect’

18:17:46.253   C:\Users\usuario\Documents\Corona Projects\Asteroids Games\game.lua:90: in function ‘createAsteroid’

18:17:46.253   C:\Users\usuario\Documents\Corona Projects\Asteroids Games\game.lua:168: in function ‘_listener’

18:17:46.253   ?: in function <?:167>

18:17:46.253   ?: in function <?:169>

18:18:27.385  

And, yeah, I dont understand that “bad argument…”, I thought, like I already wrote, It was something with display groups :S. I already checked the code. I´m still in chapter 5, I managed to access to scene from menu, I can see “lives,score, background, ship” and then that error appears! Pls, Im a rlly noob with lua, Its making me crazy hahaha and it looks so easy and friendly…but i liked it anyway…

The first parameter to display.newImageRect() has to either be a display.newGroup() or a string that’s a name to a file, or a valid imageSheet.

One of those is bad.

Rob

But I have string that is a name for a file :S This is the line 90:

local newAsteroid = display.newImageRect(mainGroup, objectSheet, 1, 102, 85 )

This is the error, again:

18:17:46.253  ERROR: Runtime error

18:17:46.253  C:\Users\usuario\Documents\Corona Projects\Asteroids Games\game.lua:90: bad argument #-1 to ‘newImageRect’ (Proxy expected, got nil)

18:17:46.253  stack traceback:

18:17:46.253   [C]: in function ‘newImageRect’

18:17:46.253   C:\Users\usuario\Documents\Corona Projects\Asteroids Games\game.lua:90: in function ‘createAsteroid’

18:17:46.253   C:\Users\usuario\Documents\Corona Projects\Asteroids Games\game.lua:168: in function ‘_listener’

18:17:46.253   ?: in function <?:167>

18:17:46.253   ?: in function <?:169>

18:18:27.385  

And here is my code :frowning: , thanks for your help. Rob! And sorry, I have my notes in the code heheh


local composer = require( “composer” )

local scene = composer.newScene()


– Code outside of the scene event functions below will only be executed ONCE unless

– the scene is removed entirely (not recycled) via “composer.removeScene()”


–Reacomodo para game.lua de main.lua, primero la physics

–ya que se siguen usando.etc

local physics = require ( “physics” )

physics.start()

physics.setGravity(0,0)

–Luego la imagesheet que luego se asocian  las imagenes con la variabel sheetOptions

– mdiante el uso del comando graphics

local sheetOptions =

{

    frames =

    {

        {   – 1) asteroid 1

            x = 0,

            y = 0,

            width = 102,

            height = 85

        },

        {   – 2) asteroid 2

            x = 0,

            y = 85,

            width = 90,

            height = 83

        },

        {   – 3) asteroid 3

            x = 0,

            y = 168,

            width = 100,

            height = 97

        },

        {   – 4) ship

            x = 0,

            y = 265,

            width = 98,

            height = 79

        },

        {   – 5) laser

            x = 98,

            y = 265,

            width = 14,

            height = 40

        },

    }

}

local objectSheet = graphics.newImageSheet( “gameObjects.png”, sheetOptions )

–Luego se colocan las variables que se inician

local lives = 3

local score = 0

local died = false

local asteroidsTable = {}

local ship

local gameLoopTimer

local livesText

local scoreText

–Se añaden los displays groups, pero como estamos usando “COMPOSER” para mamejar el juego por escenas

–deben llevar algunas modificaciones. Los display groups se pueden asociar a otros display groups!

– en este caso las tres se pueden asociar a scene.view que es el display de composer en gral. por el momento

– se dejan solo declaradas

local backGroup

local mainGroup  

local uiGroup

–Se introduce gamefunction asi como variabellocal function updateText()

local function updateText()

    livesText.text = "Lives: " … lives

    scoreText.text = "Score: " … score

end

local function createAsteroid()

    local newAsteroid = display.newImageRect(mainGroup, objectSheet, 1, 102, 85 ) ----LINE 90

    table.insert( asteroidsTable, newAsteroid )

    physics.addBody( newAsteroid, “dynamic”, { radius=40, bounce=0.8 } )

    newAsteroid.myName = “asteroid”

    local whereFrom = math.random( 3 )

    if ( whereFrom == 1 ) then

        – From the left

        newAsteroid.x = -60

        newAsteroid.y = math.random( 500 )

        newAsteroid:setLinearVelocity( math.random( 40,120 ), math.random( 20,60 ) )

    elseif ( whereFrom == 2 ) then

        – From the top

        newAsteroid.x = math.random( display.contentWidth )

        newAsteroid.y = -60

        newAsteroid:setLinearVelocity( math.random( -40,40 ), math.random( 40,120 ) )

    elseif ( whereFrom == 3 ) then

        – From the right

        newAsteroid.x = display.contentWidth + 60

        newAsteroid.y = math.random( 500 )

        newAsteroid:setLinearVelocity( math.random( -120,-40 ), math.random( 20,60 ) )

    end

   

    newAsteroid:applyTorque( math.random( -6,6 ) )

end

– Hay que dejar algunas cosas afuera en laser, porque muchos de los objetso no han sido creados

– y marcaran erro, mas aadelante se dice cque, es decir, en si son los listener de ship que no ha sido

– creado asi como el spawn y el gameloopTimer, asi como el listener de colision, vaya, todos lo listener…

– y el timer…el codio sin ello queda asi

local function fireLaser()

    local newLaser = display.newImageRect( mainGroup, objectSheet, 5, 14, 40 )

    physics.addBody( newLaser, “dynamic”, { isSensor=true } )

    newLaser.isBullet = true

    newLaser.myName = “laser”

    newLaser.x = ship.x

    newLaser.y = ship.y

    newLaser:toBack()

    transition.to( newLaser, { y=-40, time=500,

        onComplete = function() display.remove( newLaser ) end

    } )

end

local function dragShip( event )

    local ship = event.target

    local phase = event.phase

    if ( “began” == phase ) then

        – Set touch focus on the ship

        display.currentStage:setFocus( ship )

        – Store initial offset position

        ship.touchOffsetX = event.x - ship.x

    elseif ( “moved” == phase ) then

        – Move the ship to the new touch position

        ship.x = event.x - ship.touchOffsetX

    elseif ( “ended” == phase or “cancelled” == phase ) then

        – Release touch focus on the ship

        display.currentStage:setFocus( nil )

    end

    return true  – Prevents touch propagation to underlying objects

end

local function gameLoop()

    – Create new asteroid

    createAsteroid()                                                                                         ------------------------------LINE 169

    – Remove asteroids which have drifted off screen

    for i = #asteroidsTable, 1, -1 do

        local thisAsteroid = asteroidsTable[i]

        if ( thisAsteroid.x < -100 or

             thisAsteroid.x > display.contentWidth + 100 or

             thisAsteroid.y < -100 or

             thisAsteroid.y > display.contentHeight + 100 )

        then

            display.remove( thisAsteroid )

            table.remove( asteroidsTable, i )

        end

    end

end

local function restoreShip()

    ship.isBodyActive = false

    ship:setLinearVelocity( 0, 0 )

    ship.x = display.contentCenterX

    ship.y = display.contentHeight - 100

    – Fade in the ship

    transition.to( ship, { alpha=1, time=4000,

        onComplete = function()

            ship.isBodyActive = true

            died = false

        end

    } )

end

– CUANDO EL JUEGO SE ACABE SE LLLAMARA  A ESTA FUNCION CON CROSSFADE 800 MILISEGS,

– ENTONCCES ENTRARA EN FUNCION SCENE HIDE!!!

local function endGame()

    composer.gotoScene( “menu”, { time=800, effect=“crossFade” } )

end

local function onCollision( event )

    if ( event.phase == “began” ) then

        local obj1 = event.object1

        local obj2 = event.object2

        if ( ( obj1.myName == “laser” and obj2.myName == “asteroid” ) or

             ( obj1.myName == “asteroid” and obj2.myName == “laser” ) )

        then

            – Remove both the laser and asteroid

            display.remove( obj1 )

            display.remove( obj2 )

            for i = #asteroidsTable, 1, -1 do

                if ( asteroidsTable[i] == obj1 or asteroidsTable[i] == obj2 ) then

                    table.remove( asteroidsTable, i )

                    break

                end

            end

            – Increase score

            score = score + 100

            scoreText.text = "Score: " … score

        elseif ( ( obj1.myName == “ship” and obj2.myName == “asteroid” ) or

                 ( obj1.myName == “asteroid” and obj2.myName == “ship” ) )

        then

            if ( died == false ) then

                died = true

                – Update lives

                lives = lives - 1

                livesText.text = "Lives: " … lives

                if ( lives == 0 ) then

                    display.remove( ship )

     timer.performWithDelay( 2000, endGame ) – importante

     --IMPORTANTE ESTA FUNCION HACE QUE DESPUES DE 2 SEGS LLAME A LA FUNCION endGame

     --PARA QUE PUEDA A VER LA TRANSICION HIDE

                else

                    ship.alpha = 0

                    timer.performWithDelay( 1000, restoreShip )

                end

            end

        end

    end

end


– Scene event functions


– create()

function scene:create( event )

local sceneGroup = self.view

– Code here runs when the scene is first created but has not yet appeared on screen

physics.pause()  – Temporarily pause the physics engine

–el proposito de este comando en el ciclo de vida d euna scene, e sprimero, recuerda que la escena aun no

– se esta viendo en pantalla en este punto, no queremos que el juego empiece aun, asi que paramos el

– sistema de physics. Esto nos permite crear objetos, asignar cuerpo fisico, su posicion, y no

– seran afectados hasta que reiniciemos el engine de physics.

–Ahora hay que crear los tres display groups qie previamente en capitulos anteriores ya, habiamos definido.

   – Set up display groups (creamos los grupos ena dicion con el comando inster los metemos a scenegroup)

   – asi es como mantenemos nuestros grupos originales y lso metemos en la escena

    backGroup = display.newGroup()  – Display group for the background image

    sceneGroup:insert( backGroup )  – Insert into the scene’s view group

    mainGroup = display.newGroup()  – Display group for the ship, asteroids, lasers, etc.

    sceneGroup:insert( mainGroup )  – Insert into the scene’s view group

    uiGroup = display.newGroup()    – Display group for UI objects like the score

    sceneGroup:insert( uiGroup )    – Insert into the scene’s view group

– Load the background (no se declaro arriba… porque una vez insertada en grupo scene.view no se evuelve a usar

– , asi que solo creamos “local”" dentro de scene:creater)

    local background = display.newImageRect( backGroup, “background.png”, 800, 1400 )

    background.x = display.contentCenterX

    background.y = display.contentCenterY

– NO sepone local antes de ship, porque ya fue previamente declarada en el inico de las variables

ship = display.newImageRect( mainGroup, objectSheet, 4, 98, 79 )

    ship.x = display.contentCenterX

    ship.y = display.contentHeight - 100

    physics.addBody( ship, { radius=30 } )

    ship.myName = “ship”

    -----

    – Display lives and score

    livesText = display.newText( uiGroup, "Lives: " … lives, 200, 80, native.systemFont, 36 )

    scoreText = display.newText( uiGroup, "Score: " … score, 400, 80, native.systemFont, 36 )

–RECORDAR QUE ANTES SE HABIA QUITADO los listeners de ship porque no existian, pero ahora existen

–y por eso deben de meterse

  ship:addEventListener( “tap”, fireLaser )

    ship:addEventListener( “touch”, dragShip )

   

   

end

– SCENE SHOW, no hemos puesto deteccion de la colision, ni reiniciado el engine de physics, o empezado

–el gameloop para spawnear los asteroides pero aqui en sceneshow se ahce

– show()

gameLoopTimer = timer.performWithDelay( 500, gameLoop, 0 )

function scene:show( event )

local sceneGroup = self.view

local phase = event.phase

   

–Es importante saber que composer.gotoScene ayuda a especificar efectos de transiciones, como fading in,

–cross fading, zoom in, zoom out y mas. Naturalmente hay un tiempo de duraciona asociadop con el

– principio y final de dichas transiciones y aqui es donde dos lalamdas entran en juego. EL primero

– ocurre antes de que la transicion comience y el segundo cuando la transicion termina.

– Necesitamos saber cuando ocurre los llamados. Esto puede ser checado con event.phase, una propiedad

–asociada con el parametro “evento” pasado a scene:show().

– El primero llamado a event.phase por parte de scene:show(), sera “will” que significa que la escena

– y la transición de efecto apenas se mostrará.

– El segundo llamado a event.phase por parte de scene:show(), sera “did” que significa que la escena

– y la transicion de efecto han terminado

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

  – SE HAN REINICIADO LAS PHYSICS, EMPIEZAN LAS DETECCIONES D COLISION, Y SE ACTIVA EL TIMER

  --GAMELOOPTIMER DE SPAWN  DE ASTEROIDES

  physics.start()

        Runtime:addEventListener( “collision”, onCollision )

        gameLoopTimer = timer.performWithDelay( 500, gameLoop, 0 )

        timer.performWithDelay(1000,function()createAsteroid()end,0)

end

end

– hide()

–SCENE.HIDE…cuando se acaban las vidas, los asteroides se siguen construyendo y no hay manera

– de hacer restart al juego, esto significa que debemos adaptar el codigo de game.lua para cuando

– el jugador se quede sin vidas, COMPOSER acceda a la escena de highscores, pero como la

– escena de highscores.lua no existe haremos que simplemente regrese a menu.lua

– scene hide funciona igual, en cuanto event.phase, como scene show

function scene:hide( event )

local sceneGroup = self.view

local phase = event.phase

if ( phase == “will” ) then

  – Detiene el spawn de asteroides

  timer.cancel( gameLoopTimer )

elseif ( phase == “did” ) then

  Runtime:removeEventListener( “collision”, onCollision )-- quita el listener de colision

        physics.pause()-- pausa las physics

– Observa que intencionalmente se uso el pimer comando antes de que la escena se escondiera

– ya que no necesitamos generar nuevos asteroides cuando el juego se acaba. Para los otros dos comandos

– se dejan hasta que la esta totalmente oscura “offscreen” porque no queremos que los asteroides

– dejen de moverse de repente cuando la tranisicion apenas esta comenzando, etonces es cuando ya paso. 

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

When you post code to the forums, you really need to use some technique for formatting the code to make it easy to read. One way is to type in the “lua” tag and paste your code in and then close the tag like:

[lua] paste your code here [/lua]

Or you can simply hit the blue <> button in the row with Bold, Italics etc. and paste your code into the window that pops up.

Your comments are a good thing. It helps you and people following you to know what’s going on. I don’t see a problem immediately, but its hard to read with the unformatted code.

Hi, Rob! My apologies, now here is my code, again hehe. I hope you can help me with this, im still in the same error. It starting to driving me crazy! cheers

[lua]

local composer = require( “composer” )

local scene = composer.newScene()


– Code outside of the scene event functions below will only be executed ONCE unless

– the scene is removed entirely (not recycled) via “composer.removeScene()”


–Reacomodo para game.lua de main.lua, primero la physics

–ya que se siguen usando.etc

local physics = require ( “physics” )

physics.start()

physics.setGravity(0,0)

–Luego la imagesheet que luego se asocian  las imagenes con la variabel sheetOptions

– mdiante el uso del comando graphics

local sheetOptions =

{

    frames =

    {

        {   – 1) asteroid 1

            x = 0,

            y = 0,

            width = 102,

            height = 85

        },

        {   – 2) asteroid 2

            x = 0,

            y = 85,

            width = 90,

            height = 83

        },

        {   – 3) asteroid 3

            x = 0,

            y = 168,

            width = 100,

            height = 97

        },

        {   – 4) ship

            x = 0,

            y = 265,

            width = 98,

            height = 79

        },

        {   – 5) laser

            x = 98,

            y = 265,

            width = 14,

            height = 40

        },

    }

}

local objectSheet = graphics.newImageSheet( “gameObjects.png”, sheetOptions )

–Luego se colocan las variables que se inician

local lives = 3

local score = 0

local died = false

local asteroidsTable = {}

local ship

local gameLoopTimer

local livesText

local scoreText

–Se añaden los displays groups, pero como estamos usando “COMPOSER” para mamejar el juego por escenas

–deben llevar algunas modificaciones. Los display groups se pueden asociar a otros display groups!

– en este caso las tres se pueden asociar a scene.view que es el display de composer en gral. por el momento

– se dejan solo declaradas

local backGroup 

local mainGroup   

local uiGroup 

–Se introduce gamefunction asi como variabellocal function updateText()

local function updateText()

    livesText.text = "Lives: " … lives

    scoreText.text = "Score: " … score

end

local function createAsteroid()

    local newAsteroid = display.newImageRect(mainGroup, objectSheet, 1, 102, 85 )

    table.insert( asteroidsTable, newAsteroid )

    physics.addBody( newAsteroid, “dynamic”, { radius=40, bounce=0.8 } )

    newAsteroid.myName = “asteroid”

    local whereFrom = math.random( 3 )

    if ( whereFrom == 1 ) then

        – From the left

        newAsteroid.x = -60

        newAsteroid.y = math.random( 500 )

        newAsteroid:setLinearVelocity( math.random( 40,120 ), math.random( 20,60 ) )

    elseif ( whereFrom == 2 ) then

        – From the top

        newAsteroid.x = math.random( display.contentWidth )

        newAsteroid.y = -60

        newAsteroid:setLinearVelocity( math.random( -40,40 ), math.random( 40,120 ) )

    elseif ( whereFrom == 3 ) then

        – From the right

        newAsteroid.x = display.contentWidth + 60

        newAsteroid.y = math.random( 500 )

        newAsteroid:setLinearVelocity( math.random( -120,-40 ), math.random( 20,60 ) )

    end

    

    newAsteroid:applyTorque( math.random( -6,6 ) )

end

– Hay que dejar algunas cosas afuera en laser, porque muchos de los objetso no han sido creados

– y marcaran erro, mas aadelante se dice cque, es decir, en si son los listener de ship que no ha sido

– creado asi como el spawn y el gameloopTimer, asi como el listener de colision, vaya, todos lo listener…

– y el timer…el codio sin ello queda asi

local function fireLaser()

    local newLaser = display.newImageRect( mainGroup, objectSheet, 5, 14, 40 )

    physics.addBody( newLaser, “dynamic”, { isSensor=true } )

    newLaser.isBullet = true

    newLaser.myName = “laser”

    newLaser.x = ship.x

    newLaser.y = ship.y

    newLaser:toBack()

    transition.to( newLaser, { y=-40, time=500,

        onComplete = function() display.remove( newLaser ) end

    } )

end

local function dragShip( event )

    local ship = event.target

    local phase = event.phase

    if ( “began” == phase ) then

        – Set touch focus on the ship

        display.currentStage:setFocus( ship )

        – Store initial offset position

        ship.touchOffsetX = event.x - ship.x

    elseif ( “moved” == phase ) then

        – Move the ship to the new touch position

        ship.x = event.x - ship.touchOffsetX

    elseif ( “ended” == phase or “cancelled” == phase ) then

        – Release touch focus on the ship

        display.currentStage:setFocus( nil )

    end

    return true  – Prevents touch propagation to underlying objects

end

local function gameLoop()

    – Create new asteroid

    createAsteroid()

    – Remove asteroids which have drifted off screen

    for i = #asteroidsTable, 1, -1 do

        local thisAsteroid = asteroidsTable[i]

        if ( thisAsteroid.x < -100 or

             thisAsteroid.x > display.contentWidth + 100 or

             thisAsteroid.y < -100 or

             thisAsteroid.y > display.contentHeight + 100 )

        then

            display.remove( thisAsteroid )

            table.remove( asteroidsTable, i )

        end

    end

end

local function restoreShip()

    ship.isBodyActive = false

    ship:setLinearVelocity( 0, 0 )

    ship.x = display.contentCenterX

    ship.y = display.contentHeight - 100

    – Fade in the ship

    transition.to( ship, { alpha=1, time=4000,

        onComplete = function()

            ship.isBodyActive = true

            died = false

        end

    } )

end

– CUANDO EL JUEGO SE ACABE SE LLLAMARA  A ESTA FUNCION CON CROSSFADE 800 MILISEGS,

– ENTONCCES ENTRARA EN FUNCION SCENE HIDE!!!

local function endGame()

    composer.gotoScene( “menu”, { time=800, effect=“crossFade” } )

end

local function onCollision( event )

    if ( event.phase == “began” ) then

        local obj1 = event.object1

        local obj2 = event.object2

        if ( ( obj1.myName == “laser” and obj2.myName == “asteroid” ) or

             ( obj1.myName == “asteroid” and obj2.myName == “laser” ) )

        then

            – Remove both the laser and asteroid

            display.remove( obj1 )

            display.remove( obj2 )

            for i = #asteroidsTable, 1, -1 do

                if ( asteroidsTable[i] == obj1 or asteroidsTable[i] == obj2 ) then

                    table.remove( asteroidsTable, i )

                    break

                end

            end

            – Increase score

            score = score + 100

            scoreText.text = "Score: " … score

        elseif ( ( obj1.myName == “ship” and obj2.myName == “asteroid” ) or

                 ( obj1.myName == “asteroid” and obj2.myName == “ship” ) )

        then

            if ( died == false ) then

                died = true

                – Update lives

                lives = lives - 1

                livesText.text = "Lives: " … lives

                if ( lives == 0 ) then

                    display.remove( ship )

timer.performWithDelay( 2000, endGame ) – importante

–IMPORTANTE ESTA FUNCION HACE QUE DESPUES DE 2 SEGS LLAME A LA FUNCION endGame

–PARA QUE PUEDA A VER LA TRANSICION HIDE

                else

                    ship.alpha = 0

                    timer.performWithDelay( 1000, restoreShip )

                end

            end

        end

    end

end


– Scene event functions


– create()

function scene:create( event )

local sceneGroup = self.view

– Code here runs when the scene is first created but has not yet appeared on screen

physics.pause()  – Temporarily pause the physics engine

–el proposito de este comando en el ciclo de vida d euna scene, e sprimero, recuerda que la escena aun no

– se esta viendo en pantalla en este punto, no queremos que el juego empiece aun, asi que paramos el 

– sistema de physics. Esto nos permite crear objetos, asignar cuerpo fisico, su posicion, y no

– seran afectados hasta que reiniciemos el engine de physics.

–Ahora hay que crear los tres display groups qie previamente en capitulos anteriores ya, habiamos definido.

   – Set up display groups (creamos los grupos ena dicion con el comando inster los metemos a scenegroup)

   – asi es como mantenemos nuestros grupos originales y lso metemos en la escena

    backGroup = display.newGroup()  – Display group for the background image

    sceneGroup:insert( backGroup )  – Insert into the scene’s view group

    mainGroup = display.newGroup()  – Display group for the ship, asteroids, lasers, etc.

    sceneGroup:insert( mainGroup )  – Insert into the scene’s view group

    uiGroup = display.newGroup()    – Display group for UI objects like the score

    sceneGroup:insert( uiGroup )    – Insert into the scene’s view group

 – Load the background (no se declaro arriba… porque una vez insertada en grupo scene.view no se evuelve a usar

 – , asi que solo creamos “local”" dentro de scene:creater)

    local background = display.newImageRect( backGroup, “background.png”, 800, 1400 )

    background.x = display.contentCenterX

    background.y = display.contentCenterY

– NO sepone local antes de ship, porque ya fue previamente declarada en el inico de las variables

 ship = display.newImageRect( mainGroup, objectSheet, 4, 98, 79 )

    ship.x = display.contentCenterX

    ship.y = display.contentHeight - 100

    physics.addBody( ship, { radius=30 } )

    ship.myName = “ship”

    -----

    – Display lives and score

    livesText = display.newText( uiGroup, "Lives: " … lives, 200, 80, native.systemFont, 36 )

    scoreText = display.newText( uiGroup, "Score: " … score, 400, 80, native.systemFont, 36 )

–RECORDAR QUE ANTES SE HABIA QUITADO los listeners de ship porque no existian, pero ahora existen

–y por eso deben de meterse

ship:addEventListener( “tap”, fireLaser )

    ship:addEventListener( “touch”, dragShip )

    

    

end

– SCENE SHOW, no hemos puesto deteccion de la colision, ni reiniciado el engine de physics, o empezado

–el gameloop para spawnear los asteroides pero aqui en sceneshow se ahce

– show()

gameLoopTimer = timer.performWithDelay( 500, gameLoop, 0 )

function scene:show( event )

local sceneGroup = self.view

local phase = event.phase

    

–Es importante saber que composer.gotoScene ayuda a especificar efectos de transiciones, como fading in, 

–cross fading, zoom in, zoom out y mas. Naturalmente hay un tiempo de duraciona asociadop con el

– principio y final de dichas transiciones y aqui es donde dos lalamdas entran en juego. EL primero

– ocurre antes de que la transicion comience y el segundo cuando la transicion termina.

– Necesitamos saber cuando ocurre los llamados. Esto puede ser checado con event.phase, una propiedad

–asociada con el parametro “evento” pasado a scene:show(). 

– El primero llamado a event.phase por parte de scene:show(), sera “will” que significa que la escena 

– y la transición de efecto apenas se mostrará.

– El segundo llamado a event.phase por parte de scene:show(), sera “did” que significa que la escena

– y la transicion de efecto han terminado

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

– SE HAN REINICIADO LAS PHYSICS, EMPIEZAN LAS DETECCIONES D COLISION, Y SE ACTIVA EL TIMER

–GAMELOOPTIMER DE SPAWN  DE ASTEROIDES

physics.start()

        Runtime:addEventListener( “collision”, onCollision )

        gameLoopTimer = timer.performWithDelay( 500, gameLoop, 0 )

        timer.performWithDelay(1000,function()createAsteroid()end,0)

end

end

– hide()

–SCENE.HIDE…cuando se acaban las vidas, los asteroides se siguen construyendo y no hay manera

– de hacer restart al juego, esto significa que debemos adaptar el codigo de game.lua para cuando

– el jugador se quede sin vidas, COMPOSER acceda a la escena de highscores, pero como la 

– escena de highscores.lua no existe haremos que simplemente regrese a menu.lua

– scene hide funciona igual, en cuanto event.phase, como scene show

function scene:hide( event )

local sceneGroup = self.view

local phase = event.phase

if ( phase == “will” ) then

– Detiene el spawn de asteroides

timer.cancel( gameLoopTimer )

elseif ( phase == “did” ) then

Runtime:removeEventListener( “collision”, onCollision )-- quita el listener de colision

        physics.pause()-- pausa las physics

– Observa que intencionalmente se uso el pimer comando antes de que la escena se escondiera

– ya que no necesitamos generar nuevos asteroides cuando el juego se acaba. Para los otros dos comandos

– se dejan hasta que la esta totalmente oscura “offscreen” porque no queremos que los asteroides

– dejen de moverse de repente cuando la tranisicion apenas esta comenzando, etonces es cuando ya paso.

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

[/lua]

Can you paste your entire console log?  That is start Corona, load your app and hit the play button. In the console window that should be showing up behind the simulator, select all (CTRL-A) copy (CTRL-C) then come here to the forum post and paste in (CTRL-V) the whole log.

Thanks

Rob

Hi, Rob, Is this? Thank you,

11:55:16.825  

11:55:16.825  Windows simulator build date: Jun 21 2016 @ 17:14:06

11:55:16.825  

11:57:00.114  

11:57:00.114  Copyright © 2009-2016  C o r o n a   L a b s   I n c .

11:57:00.114   Version: 3.0.0

11:57:00.114   Build: 2016.2906

11:57:00.124  Platform: SM-G900S / x64 / 6.1 / AMD M880G with ATI Mobility Radeon HD 4250 / 3.3.10179 Compatibility Profile Context / 2016.2906 / es_MX | MX | es_MX | es

11:57:00.124  Loading project from:   C:\Users\usuario\Documents\Corona Projects\Asteroids Games

11:57:00.124  Project sandbox folder: C:\Users\usuario\AppData\Local\Corona Labs\Corona Simulator\Sandbox\asteroids games-CA34EDD33CE707BFD7C5375F9D425709\Documents

11:57:10.509  ERROR: Runtime error

11:57:10.509  C:\Users\usuario\Documents\Corona Projects\Asteroids Games\game.lua:90: bad argument #-1 to ‘newImageRect’ (Proxy expected, got nil)

11:57:10.509  stack traceback:

11:57:10.509   [C]: in function ‘newImageRect’

11:57:10.509   C:\Users\usuario\Documents\Corona Projects\Asteroids Games\game.lua:90: in function ‘createAsteroid’

11:57:10.509   C:\Users\usuario\Documents\Corona Projects\Asteroids Games\game.lua:169: in function ‘_listener’

11:57:10.509   ?: in function <?:167>

11:57:10.509   ?: in function <?:169>

This is very odd. I copied your code above into my copy of the project and totally replaced my game.lua with your game.lua and I didn’t get any error.

Does this happen right away, during play, after your ship gets hit?

Thanks

Rob