Attempt to perform arithmetic on file 'x' (a nil value) - lua corona sdk

Good morning,
I’m having trouble with the game I’m developing with the LUA programming code.
Gives the message when the scene is reloaded on line 254 --> self.x=self.x - self.speed
Here there are the complete lines



– game.lua


– caricamento composer library
local composer = require( “composer” )

– definizione di una nuova scena
local scene = composer.newScene()

– caricamento e inizializzazione fisica
local physics = require(“physics”)
–partenza del sistema fisico
physics.start()

– creazione scene ()
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

–tabella per la gestione degli ostacoli attivi
local obstacles={}

–tabella per la gestione degli animali attivi
local animals={}

–impostazione background

local bosco1 = display.newImageRect(sceneGroup, “img/back1.jpg”,display.contentWidth,display.contentHeight)
bosco1.x=display.contentCenterX
bosco1.y = display.contentCenterY

local bosco2 = display.newImageRect(sceneGroup, “img/back2.jpg”,display.contentWidth,display.contentHeight)
bosco2.x=display.contentCenterX+display.contentWidth
bosco2.y = display.contentCenterY

– impostazione terreno

local terreno1 = display.newImageRect(sceneGroup, “img/ground.png”,1920,105)
terreno1.x = display.contentCenterX
terreno1.y = display.contentHeight-52
terreno1.name=“ground”

local terreno2 = display.newImageRect(sceneGroup, “img/ground.png”,1920,105)
terreno2.x = display.contentCenterX+display.contentWidth
terreno2.y = display.contentHeight-52
terreno2.name=“ground”

–impostazione boy

local opt={width =93, height= 150, numFrames = 60}
local boySheet=graphics.newImageSheet(“img/boy.png”,opt)
local runningBoy={

		 {
		   name = "runRight",
		   start = 31,
		   count = 30,
		   time = 300,
		   loopCount = 0,
		   loopDirection ="forward"
		 }
                 
		 }

local boy=display.newSprite(boySheet, runningBoy)
boy.x=50
boy.y=display.contentHeight-232
boy:setSequence(“runRight”)
boy:play()
boy.action=“run”
boy.name=“boy”

– INIZIO GENERAZIONE MONDO FISICO

– trasformazione terreno1 e terreno2
– in corpi fisici statici con elevato attrito e nessun rimbalzo
physics.addBody(terreno1,“static”,{friction=1.0,bounce=0.0,density=1.8})
physics.addBody(terreno2,“static”,{friction=1.0,bounce=0.0,density=1.8})

– aggiunta corpo fisico dinamico a boy, con attrito elevato e rimbalzo 0
physics.addBody(boy,“dynamic”,{friction=1.0,bounce=0.0,density=1.3})
boy.isFixedRotation = true

–velocità di scrolling
bosco1.speed = 2
bosco2.speed = 2
terreno1.speed = 2
terreno2.speed = 2

– FINE GENERAZIONE MONDO FISICO

– INIZIO IMPLEMENTAZIONE PER FAR SALTARE BOY

– boyJump è un listener di tocchi associato a boy.
– Quando viene toccato boy l’ascoltatore viene richiamato per
– farlo saltare.

local function boyJump(self, event)
–se boy non sta saltando…
if boy.action ~= “jump” then
–da commentare
boy:applyLinearImpulse(0,-220,boy.x,boy.y)
boy.action = “run”

end  

end

–listener di tocco su boy
–quando boy viene toccato salta
boy:addEventListener(“tap”,boyJump)

local function onCollision(self,event)
– self rappresenta l’oggetto badGuy
– event.other rappresenta l’altro ogetto
– coinvolto nell’urto
if event.phase==“began” then
if event.other.name==“ground” and event.contact.isTouching==true then
self.action=“run”
end
end
return true
end
– attivare il listener di tocco su boy
boy.collision = onCollision
boy:addEventListener(“collision”,boy)

– FINE IMPLEMENTAZIONE DI BOYJUMP

– IMPLEMENTAZIONE DELLO SCORRIMENTO ORIZZONTALE DEL TERRENO E DELLO SFONDO
– mentre l’oggetto boy continua a stare nella stessa posizione

function scrolling(self,event)
– self è l’oggetto da muovere verso sinistra
if self.x<-(display.contentCenterX-self.speed*2) then
self.x = display.contentWidth+display.contentCenterX
else
self.x =self.x - self.speed
end
return true
end

–lo scrolling viene associato agli oggetti bosco1,bosco2, terreno1 e terreno2
–iniziando lo scorrimento orizzontale
bosco1.enterFrame = scrolling
Runtime:addEventListener( “enterFrame”, bosco1)
bosco2.enterFrame = scrolling
Runtime:addEventListener( “enterFrame”, bosco2 )
terreno1.enterFrame=scrolling
Runtime:addEventListener(“enterFrame”,terreno1)
terreno2.enterFrame=scrolling
Runtime:addEventListener(“enterFrame”,terreno2)
– FINE IMPLEMENTAZIONE SCORRIMENTO ORIZZONTALE

–funzione per creare nuovi oggetti obstacles
local function createObstacle(event)
local obstacle=display.newImageRect(sceneGroup, “img/flame.png”, 70,70)
–il nuovo ostacolo viene posizionato alla coordinata 1080
–la coordinata x dell’ostacolo viene generata casualmente per avere ostacoli diversi
obstacle.x=1080+math.random(4)
–posizionamento coordinata y
obstacle.y=display.contentHeight-150

–velocità randomica
obstacle.speed=math.random(2,4)

–il nuovo ostacolo viene aggiunto alla tabella degli ostacoli attivi
table.insert(obstacles, obstacle)

–obstacle:toBack()
– aggiunta corpo fisico dinamico a obstacle, con attrito elevato e rimbalzo 0
physics.addBody(obstacle,“dynamic”,{friction=1.0,bounce=0.0,density=1.3})
obstacle.name=“obstacle”
–obstacle.isFixedRotation = true
return obstacle
end

–questa funzione è un listener di tabelle che implementa
–lo scorrimento orizzontale di ogni ostacolo attivo
local function obstacleScroll(self, event)
self.x=self.x - self.speed
end

– funzione che elimina gli ostacoli non attivi e ne crea di nuovi
– e viene chiamato ogni secondo per mezzo di
– timer.performWithDelay

local function gameLoop()
– creazione nuovo ostacolo fuori dal display
local obstacle=createObstacle()
– attivazione dello scorrimento orizzontale degli ostacoli
– per farli entrare nel display
obstacle.enterFrame = obstacleScroll
Runtime:addEventListener(“enterFrame”,obstacle)

-- analizza la tabella degli ostacoli attivi alla ricerca di
-- ostacoli attivi che si trovano nel margine sinistro del display
-- gli ostacoli e gli ascoltatori vengono rimossi insieme 
-- all'entrata degli ostacoli nella tabella 

for i,thisObstacle in ipairs(obstacles) do
	if thisObstacle.x < -80 then
		Runtime:removeEventListener("enterFrame",thisObstacle)
		display.remove(thisObstacle)
		table.remove(obstacles,i)
	end
end		

end

–variabile locale che contiene il timer del loop del gioco
–viene richiamato gameLoop ogni secondo
local gameLoopTimer = timer.performWithDelay(1000,gameLoop,0)

–funzione per creare nuovi oggetti obstacles
local function createAnimal(event)
local animal=display.newImageRect(sceneGroup, “img/rabbit.png”, 70,70)
–il nuovo ostacolo viene posizionato alla coordinata 1080
–la coordinata x dell’ostacolo viene generata casualmente per avere ostacoli diversi
animal.x=1250+math.random(3)
–posizionamento coordinata y
animal.y=display.contentHeight-150

–velocità randomica
animal.speed=math.random(2,4)

–il nuovo ostacolo viene aggiunto alla tabella degli ostacoli attivi
table.insert(animals, animal)

–obstacle:toBack()
– aggiunta corpo fisico dinamico a obstacle, con attrito elevato e rimbalzo 0
physics.addBody(animal,“dynamic”,{friction=1.0,bounce=0.0,density=1.3})
animal.name=“animal”
–obstacle.isFixedRotation = true
return animal
end

–questa funzione è un listener di tabelle che implementa
–lo scorrimento orizzontale di ogni ostacolo attivo
local function animalScroll(self, event)
self.x=self.x - self.speed
end

– funzione che elimina gli ostacoli non attivi e ne crea di nuovi
– e viene chiamato ogni secondo per mezzo di
– timer.performWithDelay

local function animalLoop()
– creazione nuovo ostacolo fuori dal display
local animal=createAnimal()
– attivazione dello scorrimento orizzontale degli ostacoli
– per farli entrare nel display
animal.enterFrame = animalScroll
Runtime:addEventListener(“enterFrame”,animal)

-- analizza la tabella degli ostacoli attivi alla ricerca di
-- ostacoli attivi che si trovano nel margine sinistro del display
-- gli ostacoli e gli ascoltatori vengono rimossi insieme 
-- all'entrata degli ostacoli nella tabella 

for i,thisAnimal in ipairs(animals) do
	if thisAnimal.x < -80 then
		Runtime:removeEventListener("enterFrame",thisAnimal)
		display.remove(thisAnimal)
		table.remove(animals,i)
	end
end		

end

–variabile locale che contiene il timer del loop del gioco
–viene richiamato gameLoop ogni secondo
local animalLoopTimer = timer.performWithDelay(1000,animalLoop,0)
–funzione che viene invocata quando boy collide con un ostacolo
local function restartGame(event)
– se l’oggetto boy esiste …
if boy~=nil then
– cancella il timer gameLoopTimer
timer.cancel(gameLoopTimer)
–elimina l’oggetto boy
display.remove(boy)
boy = nil

		--elimina gli ascoltatori per lo scrollling del terreno e del soffito
		Runtime:removeEventListener("enterFrame",back1)
		Runtime:removeEventListener("enterFrame",back2)
		Runtime:removeEventListener("enterFrame",terreno1)
		Runtime:removeEventListener("enterFrame",terreno2)	
		
		 -- scorri l'array obstacles dall'ultimo al primo elemento ed
		-- elimina tutti gli ascoltatori per lo scrolling degli ostacoli
		-- attivi
	    for i=#obstacles,1,-1 do
	      local thisObstacle=obstacles[i]
		  Runtime:removeEventListener("enterFrame",thisObstacle)
          
		  		  
	    end
		
		 for i=#animals,1,-1 do
	      local thisAnimal=animals[i]
		  Runtime:removeEventListener("enterFrame",thisAnimal)
          
		  		  
	    end

–eliminazone scena restart per non farla ricomparire
composer.removeScene(“restart”)
–vai alla scena di restart
composer.gotoScene(“restart”,{ time=800, effect=“crossFade” } )
end
end

–funzione che viene richiamata quando l’oggetto boy collide con un ostacolo
local function obstacleCollision(self,event)
if event.phase==“began” then
if event.other.name==“obstacle” and event.contact.isTouching==true then
–attivazione funzione restartGame()
restartGame()
end
end
end

–associa a boy un ascoltatore locale per l’evento collision
–l’ascoltatore deve essere un table listener che richiama la funzione
–obstacleCollision
boy.collision=obstacleCollision
boy:addEventListener(“collision”, boy )

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

scene:addEventListener(“show”)

– 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)
	physics.pause()
elseif ( phase == "did" ) then
	-- Code here runs immediately after the scene goes entirely off screen
	end

end

– destroy()
function scene:destroy( event )

local sceneGroup = self.view
-- Code here runs prior to the removal of scene's view

end


– Scene event function listeners


scene:addEventListener( “create”, scene )
scene:addEventListener( “show”, scene )
scene:addEventListener( “hide”, scene )
scene:addEventListener( “destroy”, scene )


return scene

Can someone help me?
I need it for a university exam

Thank you

Hi @s1507,

Better use only one enterFrame listener to iterate over all animals.

Try this (should work)

  1. Replace
    local animalLoopTimer = timer.performWithDelay(1000,animalLoop,0)
    with
    local animalLoopTimer = timer.performWithDelay(1000,createAnimal,0)

  2. Replace

    local function animalScroll(self, event)
       self.x=self.x - self.speed
    end
    

    with

    local function animalScroll(event)
      -- You need interate table in reverse way
      for i=#animals, 1, -1 do
        local thisAnimal = animals[i]
        if thisAnimal.x < -80 then 
          display.remove(table.remove(animals,i))
        else
          thisAnimal.x=thisAnimal.x - thisAnimal.speed
        end
       end	
     end
    
  3. You need add and remove enterFrame listener in your code
    Runtime:removeEventListener("enterFrame",animalScroll)
    Runtime:addEventListener("enterFrame",animalScroll)

EDIT:
You don’t cancel animalLoopTimer timer. Probably you should.

Have a nice day:)
ldurniat

1 Like

Good morning, thank you for the advice! I tried but it doesn’t word, because instead of moving forward, animals go back

They should move closer left edge of screen with every frame, is it right?