Stucked at tutorial

Hi!

I am new and from Hungary.

My first question would be about the getting started tutorial, chapter 2.

There is part where we type the loaded image sheet parameters and i dont understand how the tutorial came up with those numbers on the Y axis and on width/width. How to even measure these things?

My second problem is that after finishing tutorial chapter 3, my game worked except the laser did not destroyed the asteroids. I tried to fix this by tweaking the collision function part of the code (209-228) without any succes.

Then i copy pasted the collision code part from the official tutorial code (downloaded from website) and the game now doesnt even work.

 if someone could spot and tell my mistake i would be happy

[spoiler]

----------------------------------------------------------------------------------------- -- -- main.lua -- ----------------------------------------------------------------------------------------- local physics = require ("physics") physics.start () physics.setGravity (0, 0) -- Seed the random number generator math.randomseed (os.time()) -- configure image sheet 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) -- Initialize variables local lives = 3 local score = 0 local died = false local asteroidsTable = {} local ship local gameLoopTimer local livesText local scoreText -- set up display groups local backGroup = display.newGroup () -- display group for the background image local mainGroup = display.newGroup () -- display group for the ship, asteroids, lasers, etc. local uiGroup = display.newGroup () -- display group for UI objects like the store -- load the background local background = display.newImageRect (backGroup, "background.png", 800, 1400) background.x = display.contentCenterX background.y = display.contentCenterY ship = display.newImageRect (mainGroup, objectSheet, 4, 98, 79) ship.x = display.contentCenterX ship.y = display.contentHeight -100 physics.addBody (ship, {radius = 30, isSensor = true}) 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) -- hide the status bar display.setStatusBar (display.HiddenStatusBar) 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 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 ship:addEventListener ("tap", fireLaser) local function dragShip (event) local ship = event.target local phase = event.phase if ("began" == phase) then --set touch 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 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 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 gameLoopTimer = timer.performWithDelay (500, gameLoop, 0) local function restoreShip () ship.isBodyactive = false ship.x = display.contentCenterX ship.y = display.contentHeight - 100 --fade in the ship (-1hp) transition.to (ship, {alpha = 1, time = 4000, onComplete = function () ship.isBodyactive = true died = false end }) 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) else ship.alpha = 0 timer.performWithDelay (1000, restoreShip) end end end end end Runtime:addEventListener ("collision", onCollison)

[/spoiler]

Let me answer the first question first?  Those measurements are determined by the original source image size.  Let’s say you have four squares that are 50 px on each edge and you want to put them into a single image. You can make a image that is 50px wide and 200px tall (4 images * 50px each). You would place the first square at the very top. It’s 0px from the left edge and 0px from the top edge. That would make it’s x and y, 0 and 0. It’s a 50x50 image so width = 50, height = 50. Now place the second image right below the first one. Now the left edge is still 0 px away from the left edge, but its top is 50 (the first one occupies pixels 0-49).  The third one would be a y of 100 and the final one would be 150.  All would have an x of 0 and a width, height of 50 and 50.

In StarExplorer, each image is a different size and the images have transparency around them. You can get the width and height from photoshop or by getting the properties from the operating system and then just make a note of where you put each image when you stitch the individual images together. Or you can use the height of the previous image.

For the second issue are you getting any errors or warnings in your console log window?

Rob

I am getting runtime error message in console and an error window stating:

addEventListener: listener cant be nil:nil

stack traceback:

[C]: in function ‘error’

?: in function ‘getOrCreateTable’

?: in function ‘addEventListener’ (this 3 times)

main.lua:255: in main chunk

thx

Hi @Ypulse,

Can you tell us what line 255 is? We can’t determine that from the code post here (since it has no line numbers).

Thanks,

Brent

Runtime:addEventListener (“collision”, onCollison)

You have a syntax error in the spelling. The function name is “onCollis i on” but you stated that the listener function on line 255 is “onCollison” (missing second “i”).

yes that spelling mistake was the problem…

I have a new problem in chapter 6: game cant save scores and “crashes” with error message upon death
 
 
My file for chapter 6

https://ufile.io/n7zyu

error message: error loading module highscores file from highscores.lua:

highscores.lua:100:’)’ expected near ‘native’.

stack trackback:

[C]: in function ‘error’

?: in function gotoScene

menu.lua:16:in function’?’

?: in function <?:182>

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()" -- ----------------------------------------------------------------------------------- --initialize variables local json = require ("json") local scoresTable = {} local filePath = system.pathForFile ("scores.json", system.DocumentsDirectory) local function loadScores () local file = io.open (filePath, "r") if file then local contents = file:read ("\*a") io.close (file) scoresTable = json.decode (contents) end if (scoresTable == nil or #scoresTable == 0) then scoresTable = {0,0,0,0,0,0,0,0,0,0} end end local function saveScores () for i = #scoreTable, 11, -1 do table.remove (scoreTable, i) end local file = io.open (filePath, "w") if file then file:write (json.encode (scoresTable)) io.close (file) end end local function gotoMenu () composer.gotoMenu ("menu", {time = 800, effect = "crossFade"}) 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 --load the previous scores loadScores () --insert the saved score from the last game into the table, then reset it table.insert (scoreTable, composer.getVariable ("finalScore")) composer.setVariable ("finalScore", 0) --sort the table entries from highest to lowest local function compare (a, b) return a \> b end table.sort (scoresTable, compare) --save the scores saveScores () local background = display.newImageRect (sceneGroup, "background.png", 800, 1400) background.x = display.contentCenterX background.y = display.contentCenterY local highScoresHeader = display.newText (sceneGroup, "High Scores", display.contentCenterX, 100, native.systemFont, 44) for i = 1, 10 do if ( scoreTable[i]) then local yPos = 150 + (i\*56) local rankNum = display.newText (sceneGroup, i .. ")", display.contentCenterX-50, yPos, native.systemFont, 36) rankNum:setFillColor (0.8) rankNum.anchorX = 1 local thisScore = display.newText (sceneGroup, scoresTable[i], display.contentCenterX-30, yPos, native.systemFont, 36) thisScore.anchorX = 0 end end local menuButton = display.newText (sceneGroup, "menu", display.contentCenterX, 810 native.systemFont, 44) menuButton:setFillColor (0.75, 0.78, 1) menuButton:addEventListener ("tap", gotoMenu) 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 composer.removeScene("highscores") 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

Hello @Ypulse

You are missing comma between 810 and native.systemFont.

When you are having errors like ‘something’ expected near ‘keyword’ it is mostly syntax error. 

yes, i also found other spelling errors i made. Still trying to find and fix all the typing errors i made. So far, all my problems came from simple bad typing/grammar mistakes.

finally its working now, i typed score instead of scores in lot of lines. also typed gotomenu instead of gotoscene

Let me answer the first question first?  Those measurements are determined by the original source image size.  Let’s say you have four squares that are 50 px on each edge and you want to put them into a single image. You can make a image that is 50px wide and 200px tall (4 images * 50px each). You would place the first square at the very top. It’s 0px from the left edge and 0px from the top edge. That would make it’s x and y, 0 and 0. It’s a 50x50 image so width = 50, height = 50. Now place the second image right below the first one. Now the left edge is still 0 px away from the left edge, but its top is 50 (the first one occupies pixels 0-49).  The third one would be a y of 100 and the final one would be 150.  All would have an x of 0 and a width, height of 50 and 50.

In StarExplorer, each image is a different size and the images have transparency around them. You can get the width and height from photoshop or by getting the properties from the operating system and then just make a note of where you put each image when you stitch the individual images together. Or you can use the height of the previous image.

For the second issue are you getting any errors or warnings in your console log window?

Rob

I am getting runtime error message in console and an error window stating:

addEventListener: listener cant be nil:nil

stack traceback:

[C]: in function ‘error’

?: in function ‘getOrCreateTable’

?: in function ‘addEventListener’ (this 3 times)

main.lua:255: in main chunk

thx

Hi @Ypulse,

Can you tell us what line 255 is? We can’t determine that from the code post here (since it has no line numbers).

Thanks,

Brent

Runtime:addEventListener (“collision”, onCollison)

You have a syntax error in the spelling. The function name is “onCollis i on” but you stated that the listener function on line 255 is “onCollison” (missing second “i”).

yes that spelling mistake was the problem…

I have a new problem in chapter 6: game cant save scores and “crashes” with error message upon death
 
 
My file for chapter 6

https://ufile.io/n7zyu

error message: error loading module highscores file from highscores.lua:

highscores.lua:100:’)’ expected near ‘native’.

stack trackback:

[C]: in function ‘error’

?: in function gotoScene

menu.lua:16:in function’?’

?: in function <?:182>

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()" -- ----------------------------------------------------------------------------------- --initialize variables local json = require ("json") local scoresTable = {} local filePath = system.pathForFile ("scores.json", system.DocumentsDirectory) local function loadScores () local file = io.open (filePath, "r") if file then local contents = file:read ("\*a") io.close (file) scoresTable = json.decode (contents) end if (scoresTable == nil or #scoresTable == 0) then scoresTable = {0,0,0,0,0,0,0,0,0,0} end end local function saveScores () for i = #scoreTable, 11, -1 do table.remove (scoreTable, i) end local file = io.open (filePath, "w") if file then file:write (json.encode (scoresTable)) io.close (file) end end local function gotoMenu () composer.gotoMenu ("menu", {time = 800, effect = "crossFade"}) 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 --load the previous scores loadScores () --insert the saved score from the last game into the table, then reset it table.insert (scoreTable, composer.getVariable ("finalScore")) composer.setVariable ("finalScore", 0) --sort the table entries from highest to lowest local function compare (a, b) return a \> b end table.sort (scoresTable, compare) --save the scores saveScores () local background = display.newImageRect (sceneGroup, "background.png", 800, 1400) background.x = display.contentCenterX background.y = display.contentCenterY local highScoresHeader = display.newText (sceneGroup, "High Scores", display.contentCenterX, 100, native.systemFont, 44) for i = 1, 10 do if ( scoreTable[i]) then local yPos = 150 + (i\*56) local rankNum = display.newText (sceneGroup, i .. ")", display.contentCenterX-50, yPos, native.systemFont, 36) rankNum:setFillColor (0.8) rankNum.anchorX = 1 local thisScore = display.newText (sceneGroup, scoresTable[i], display.contentCenterX-30, yPos, native.systemFont, 36) thisScore.anchorX = 0 end end local menuButton = display.newText (sceneGroup, "menu", display.contentCenterX, 810 native.systemFont, 44) menuButton:setFillColor (0.75, 0.78, 1) menuButton:addEventListener ("tap", gotoMenu) 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 composer.removeScene("highscores") 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

Hello @Ypulse

You are missing comma between 810 and native.systemFont.

When you are having errors like ‘something’ expected near ‘keyword’ it is mostly syntax error. 

yes, i also found other spelling errors i made. Still trying to find and fix all the typing errors i made. So far, all my problems came from simple bad typing/grammar mistakes.

finally its working now, i typed score instead of scores in lot of lines. also typed gotomenu instead of gotoscene