Getting Error: "attempt to perform arithmetic on upvalue 'score' (a table value)"

Hi

I am on Chapter 5 of the ‘Getting Started’ Corona tutorial, here, and I am at a loss now with this issue.

The error:

“attempt to perform arithmetic on upvalue ‘score’ (a table value)”

This error is the same with the variable ‘lives’ depending on which is changed first in the game.

What I’ve tried:

  • I have made sure the variables are declared and assigned to at the top of the file.
  • I copy-pasted the source provided by the tutorial and continue to get the same error, which confirms for me that I had indeed followed along correctly, which I was pretty certain of just from combing through it.
  • There doesn’t appear to be anything in outside of this file ‘game.lua’ that would cause this problem. (other files are ‘main.lua’ and ‘menu.lua’)

The code:

I have shortened the code for readability. I am pretty sure the below snippets are what’s relevant. However, I will paste the full source at the bottom of this post just in case, it’s relatively short for the beginner tutorial.

I inserted *** HERE *** comments on the right at the points where the variables are declared and the arithmetic in question is performed. 

Edited code:

local composer = require( "composer" ) local scene = composer.newScene() -- MORE CODE HERE -- Initialise variables local lives = 3 -- \*\*\* HERE \*\*\* local score = 0 local died = false -- VARIOUS FUNCTIONS HERE -- collision handler/listener function local function onCollision( event )     if ( event.phase == "began" ) then         -- get references to the objects         local obj1 = event.object1         local obj2 = event.object2         -- laser/asteroid collision         if ( ( obj1.myName == "laser" and obj2.myName == "asteroid" ) or             ( obj1.myName == "asteroid" and obj2.myName == "laser" ) )         then             -- remove both laser and asteroid             display.remove( obj1 )             display.remove( obj2 )             -- remove the asteroid from asteroidsTable             for i = #asteroidsTable, 1, -1 do                 if ( asteroidsTable[i] == obj1 or asteroidsTable[i] == obj2 ) then                     table.remove( asteroidsTable, i )                     break -- no need to keep searching                 end             end             -- increase score for hitting the roid             score = score + 100 -- \*\*\* HERE \*\*\*             scoreText.text = "Score: " .. score         -- ship/asteroid collision         elseif ( ( obj1.myName == "asteroid" and obj2.myName == "ship" ) or                 ( obj1.myName == "ship" and obj2.myName == "asteroid" ) )         then             -- are we dead now??             if ( died == false ) then                 died = true                 -- take a life                 lives = lives - 1 -- \*\*\* HERE \*\*\*                 livesText.text = "Lives: " .. lives                 -- check for Game Over                 if ( lives == 0 ) then                     display.remove( ship ) -- \*\*\* GAME OVER \*\*\*                 else                       -- else respawn                     ship.alpha = 0                     timer.performWithDelay( 1000, respawnShip )                 end             end         end     end end -- ----------------------------------------------------------------------------------- -- Scene event functions -- -----------------------------------------------------------------------------------

Full source:

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()" -- ----------------------------------------------------------------------------------- -- start da physics local physics = require("physics") physics.start() physics.setGravity(0, 0) -- Image sheet instructions local sheetOptions = { &nbsp; &nbsp; frames = &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; -- 1) asteroid 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = 0, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y = 0, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width = 102, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height = 85 &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; -- 2) asteroid 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = 0, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y = 85, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width = 90, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height = 83 &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; -- 3) asteroid 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = 0, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y = 168, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width = 100, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height = 97 &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; -- 4) ship &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = 0, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y = 265, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width = 98, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height = 79 &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; -- 5) laser &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x = 98, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y = 265, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width = 14, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height = 40 &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; } } -- initialise a sprite/image sheet local objectSheet = graphics.newImageSheet( "gameObjects.png", sheetOptions ) -- Initialise variables local lives = 3 -- \*\*\*HERE \*\*\* local score = 0 local died = false local asteroidsTable = {} local ship local gameLoopTimer local livesText local scoreText -- main game display groups local backGroup local mainGroup local uiGroup -- update HUD function local function updateHUD() &nbsp; &nbsp; livesText.text = "Lives: " .. lives &nbsp; &nbsp; scoreText.text = "Score: " .. score end -- function to create asteroid local function createAsteroid() &nbsp; &nbsp; local asteroid = display.newImageRect(mainGroup, objectSheet, 1, 102, 85) &nbsp; &nbsp; table.insert(asteroidsTable, asteroid) &nbsp; &nbsp; physics.addBody( asteroid, { radius=40, bounce=0.8 } ) &nbsp; &nbsp; asteroid.myName = "asteroid" &nbsp; &nbsp; -- set entry point of asteroid &nbsp; &nbsp; local entryPoint = math.random(3) -- top, left, right &nbsp; &nbsp; if ( entryPoint == 1 ) then -- from the left &nbsp; &nbsp; &nbsp; &nbsp; asteroid.x = -60 &nbsp; &nbsp; &nbsp; &nbsp; asteroid.y = math.random(500) &nbsp; &nbsp; &nbsp; &nbsp; asteroid:setLinearVelocity( math.random(40, 120), math.random(20, 60) ) &nbsp; &nbsp; elseif ( entryPoint == 2) then -- from the top &nbsp; &nbsp; &nbsp; &nbsp; asteroid.x = math.random( display.contentWidth ) &nbsp; &nbsp; &nbsp; &nbsp; asteroid.y = -60 &nbsp; &nbsp; &nbsp; &nbsp; asteroid:setLinearVelocity( math.random(-40, 40), math.random(40, 120)) &nbsp; &nbsp; elseif (entryPoint == 3) then -- from right &nbsp; &nbsp; &nbsp; &nbsp; asteroid.x = display.contentWidth + 60 &nbsp; &nbsp; &nbsp; &nbsp; asteroid.y = math.random(500) &nbsp; &nbsp; &nbsp; &nbsp; asteroid:setLinearVelocity( math.random(-120, -40), math.random(20, 60)) &nbsp; &nbsp; end &nbsp; &nbsp; -- give asteroid rotation &nbsp; &nbsp; asteroid:applyTorque( math.random(-6, 6) ) end -- function to load laser local function fireLaser() &nbsp; &nbsp; local laser = display.newImageRect( mainGroup, objectSheet, 5, 14, 40 ) &nbsp; &nbsp; laser.x = ship.x &nbsp; &nbsp; laser.y = ship.y &nbsp; &nbsp; physics.addBody( laser, "dynamic", { isSensor=true }) &nbsp; &nbsp; laser.myName = "laser" &nbsp; &nbsp; laser:toBack() -- send to bottom layer of mainGroup &nbsp; &nbsp; -- fire laser &nbsp; &nbsp; transition.to(laser, { &nbsp; &nbsp; &nbsp; &nbsp; y=-40, &nbsp; &nbsp; &nbsp; &nbsp; time=500, &nbsp; &nbsp; &nbsp; &nbsp; onComplete = function() display.remove( laser ) end &nbsp; &nbsp; }) end -- function to add ship movement via touch/drag local function dragShip(event) &nbsp; &nbsp; local ship = event.target -- the ship &nbsp; &nbsp; local phase = event.phase -- which phase of touch &nbsp; &nbsp; if ( phase == "began" ) then &nbsp; &nbsp; &nbsp; &nbsp; -- set focus on the ship &nbsp; &nbsp; &nbsp; &nbsp; display.currentStage:setFocus( ship ) &nbsp; &nbsp; &nbsp; &nbsp; ship.touchOffsetX = event.x - ship.x -- retain offset &nbsp; &nbsp; elseif ( phase == "moved" ) then &nbsp; &nbsp; &nbsp; &nbsp; -- move the ship to new position &nbsp; &nbsp; &nbsp; &nbsp; -- calculate new position &nbsp; &nbsp; &nbsp; &nbsp; local newPosition = event.x - ship.touchOffsetX &nbsp; &nbsp; &nbsp; &nbsp; -- keep the ship fully on-screen &nbsp; &nbsp; &nbsp; &nbsp; if ( newPosition \>= display.contentWidth - 150 ) then -- check the right &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ship.x = display.contentWidth - 150 &nbsp; &nbsp; &nbsp; &nbsp; elseif ( newPosition \<= 150 ) then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-- check the left &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ship.x = 150 &nbsp; &nbsp; &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ship.x = newPosition &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-- go ahead &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp; &nbsp; elseif ( phase == "ended" or phase == "cancelled" ) then &nbsp; &nbsp; &nbsp; &nbsp; -- release touch focus on the hip &nbsp; &nbsp; &nbsp; &nbsp; display.currentStage:setFocus( nil ) &nbsp; &nbsp; end &nbsp; &nbsp; return true -- prevent touch event from affecting other objects end -- implement a game loop local function gameLoop() &nbsp; &nbsp; -- create an asteroid &nbsp; &nbsp; createAsteroid() &nbsp; &nbsp; -- garbage collect spent asteroids &nbsp; &nbsp; -- iterate through asteroidTable &nbsp; &nbsp; for i = #asteroidsTable, 1, -1 do &nbsp; &nbsp; &nbsp; &nbsp; local thisAsteroid = asteroidsTable[i] &nbsp; &nbsp; &nbsp; &nbsp; -- bounds check for spent asteroids &nbsp; &nbsp; &nbsp; &nbsp; if ( thisAsteroid.x \< -100 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-- check left &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; or thisAsteroid.x \> display.contentWidth + 100 &nbsp; &nbsp; &nbsp;-- check right &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; or thisAsteroid.y \> display.contentHeight + 100 &nbsp; &nbsp; -- check bottom &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; or thisAsteroid.y \< -100 ) then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- check top &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; display.remove( thisAsteroid ) &nbsp; &nbsp; &nbsp;-- clean up spent asteroid &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; table.remove( asteroidsTable, i ) &nbsp; -- remove asteroid from table &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp; &nbsp; end end -- function to respawn the ship after death (live allowing) local function respawnShip() &nbsp; &nbsp; ship.isBodyActive = false &nbsp; &nbsp; ship:setLinearVelocity( 0, 0 ) &nbsp; &nbsp; ship.x = display.contentCenterX &nbsp; &nbsp; ship.y = display.contentHeight - 100 &nbsp; &nbsp; -- fade the ship in &nbsp; &nbsp; transition.to( ship, { alpha=1, time=4000, &nbsp; &nbsp; &nbsp; &nbsp; onComplete = function() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ship.isBodyActive = true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; died = false &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp; &nbsp; }) end -- collision handler/listener function local function onCollision( event ) &nbsp; &nbsp; if ( event.phase == "began" ) then &nbsp; &nbsp; &nbsp; &nbsp; -- get references to the objects &nbsp; &nbsp; &nbsp; &nbsp; local obj1 = event.object1 &nbsp; &nbsp; &nbsp; &nbsp; local obj2 = event.object2 &nbsp; &nbsp; &nbsp; &nbsp; -- laser/asteroid collision &nbsp; &nbsp; &nbsp; &nbsp; if ( ( obj1.myName == "laser" and obj2.myName == "asteroid" ) or &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ( obj1.myName == "asteroid" and obj2.myName == "laser" ) ) &nbsp; &nbsp; &nbsp; &nbsp; then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- remove both laser and asteroid &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; display.remove( obj1 ) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; display.remove( obj2 ) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- remove the asteroid from asteroidsTable &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for i = #asteroidsTable, 1, -1 do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ( asteroidsTable[i] == obj1 or asteroidsTable[i] == obj2 ) then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; table.remove( asteroidsTable, i ) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break -- no need to keep searching &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- increase score for hitting the roid &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; score = score + 100 -- \*\*\* HERE \*\*\* &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scoreText.text = "Score: " .. score &nbsp; &nbsp; &nbsp; &nbsp; -- ship/asteroid collision &nbsp; &nbsp; &nbsp; &nbsp; elseif ( ( obj1.myName == "asteroid" and obj2.myName == "ship" ) or &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ( obj1.myName == "ship" and obj2.myName == "asteroid" ) ) &nbsp; &nbsp; &nbsp; &nbsp; then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- are we dead now?? &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ( died == false ) then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; died = true &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- take a life &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lives = lives - 1 -- \*\*\* HERE \*\*\* &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; livesText.text = "Lives: " .. lives &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- check for Game Over &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ( lives == 0 ) then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; display.remove( ship ) -- \*\*\* GAME OVER \*\*\* &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -- else respawn &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ship.alpha = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; timer.performWithDelay( 1000, respawnShip ) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp; &nbsp; &nbsp; &nbsp; end &nbsp; &nbsp; 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 -- Pause so that placed objects don't start moving until games starts physics.pause() -- insert the display groups into the scene backGroup = display.newGroup() sceneGroup:insert( backGroup ) mainGroup = display.newGroup() sceneGroup:insert( mainGroup ) uiGroup = display.newGroup() sceneGroup:insert( uiGroup ) -- load the background local background = display.newImageRect( backGroup, "background.png", 800, 1400 ) background.x = display.contentCenterX background.y = display.contentCenterY -- load the ship ship = display.newImageRect( mainGroup, objectSheet, 4, 98, 79 ) ship.x = display.contentCenterX ship.y = display.contentHeight - 100 &nbsp; &nbsp; physics.addBody( ship, { radius=30, isSensor=true }) &nbsp; &nbsp; ship.myName = "ship" -- load the score/lives text lives = display.newText( uiGroup, "Lives: " .. lives, 200, 80, native.systemFont, 36 ) score = display.newText( uiGroup, "Score: " .. score, 560, 80, native.systemFont, 36 ) -- add ship's event listeners ship:addEventListener( "tap", fireLaser ) ship:addEventListener( "touch", dragShip ) 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 &nbsp; &nbsp; &nbsp; &nbsp; -- start physics engine again &nbsp; &nbsp; &nbsp; &nbsp; physics.start() &nbsp; &nbsp; &nbsp; &nbsp; Runtime:addEventListener( "collision", onCollision ) &nbsp; &nbsp; &nbsp; &nbsp; gameLoopTimer = timer.performWithDelay( 500, gameLoop, 0 ) end end -- hide() function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Code here runs when the scene is on screen (but is about to go off screen) elseif ( phase == "did" ) then -- Code here runs immediately after the scene goes entirely off screen end end -- destroy() function scene:destroy( event ) local sceneGroup = self.view -- Code here runs prior to the removal of scene's view end -- ----------------------------------------------------------------------------------- -- Scene event function listeners -- ----------------------------------------------------------------------------------- scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) -- ----------------------------------------------------------------------------------- return scene

Try (probably line 324 in your code)

livesText = display.newText( uiGroup, "Lives: " .. lives, 200, 80, native.systemFont, 36 ) scoreText = display.newText( uiGroup, "Score: " .. score, 560, 80, native.systemFont, 36 )

instead of 

lives = display.newText( uiGroup, "Lives: " .. lives, 200, 80, native.systemFont, 36 ) score = display.newText( uiGroup, "Score: " .. score, 560, 80, native.systemFont, 36 )

Should work now:)

Doh! Thank you :slight_smile:

Try (probably line 324 in your code)

livesText = display.newText( uiGroup, "Lives: " .. lives, 200, 80, native.systemFont, 36 ) scoreText = display.newText( uiGroup, "Score: " .. score, 560, 80, native.systemFont, 36 )

instead of 

lives = display.newText( uiGroup, "Lives: " .. lives, 200, 80, native.systemFont, 36 ) score = display.newText( uiGroup, "Score: " .. score, 560, 80, native.systemFont, 36 )

Should work now:)

Doh! Thank you :slight_smile: