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.
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! 
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 
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 
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 “:” 
Hello, guys! I´ve been working in the code…im actually at chapter 5, but i got stucked one more time! 
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
, 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