I'm getting the following error:
Attempt to index global "a" (a nil value)
local gfx = love.graphics
return{
new = function( Image, Animation, Time)
return{
current_frame = 1,
current_anim = 1,
image = Image,
a = Animation,
play = false,
time = Time or 0,2,
counter = 0,
update = function(dt)
if play then
counter = counter + dt
if counter >= time then
counter = 0
current_frame = current_frame + 1
end
if current_frame > #a[current_anim] then
current_frame = 1
end
else
end
end,
play = function()
play = true
end,
stop = function()
play = false
end,
set_animation = function(anim)
if anim > #a then error("there is no animation ", anim) return end
current_anim = anim
end,
draw = function(data)
gfx.draw(image, a[current_anim][current_frame], data[1], data[2])
end
}
end
}
it seems to me, that I do give "a" a value - a table, containing a set of images, which I assign through second parameter.
-----
local quad = love.graphics.newQuad
local anim_data = {
quad(0,0, 32, 48, 192, 256),
quad(32,0, 32, 48, 192, 256),
quad(64,0, 32, 48, 192, 256),
quad(96,0, 32, 48, 192, 256),
quad(129,0, 32, 48, 192, 256),
quad(162,0, 32, 48, 192, 256)
}
local image = love.graphics.newImage("images/player_animation.png")
image:setFilter("nearest","nearest")
Here I supposedly give 'a' a value
animation = require("animations"):new(
image,
{
{ -- idle
anim_data[1]
},
{ -- walk
anim_data[2],
anim_data[3],
anim_data[4],
anim_data[5],
anim_data[6]
},
},
0.2
)
animation.play()
The a you are looking for is part of the table you are returning from the new function. It is not visible from the scope of those functions.
The easiest solution is to move the values you've placed in the table up in the scope of the new function, encapsulating them. However, this removes them from the table, so they won't be visible outside of the new, .play, .pause, .draw, .update, or .set_animation functions.
A better solution is to employ a more typical OOP solution, so I would suggest reading chapter 16 of Programming in Lua: Object-oriented Programming. Once you've read that chapter, go read every other just to be safe (particularly 5, 6, and 11).
local gfx = love.graphics
return {
new = function (Image, Animation, Time)
local current_frame = 1
local current_anim = 1
local image = Image
local a = Animation
local play = false
local time = Time or 0,2
local counter = 0
return {
update = function (dt)
if play then
counter = counter + dt
if counter >= time then
counter = 0
current_frame = current_frame + 1
end
if current_frame > #a[current_anim] then
current_frame = 1
end
end
end,
play = function ()
play = true
end,
stop = function ()
play = false
end,
set_animation = function (anim)
if anim > #a then
error("there is no animation ", anim)
return
end
current_anim = anim
end,
draw = function (data)
gfx.draw(image, a[current_anim][current_frame], data[1], data[2])
end
}
end
}
Related
I was playing around with Lua and neural networks, and I stumbled across a weird bug in my code, where Lua appears to be treating a table as a number. I have the following code...
function CreateEmptyNeuron()
local neuron = {
val = 0,
forward = { },
backward = { },
}
return neuron;
end
--layerSize is an integer representing the size of the layer we're creating.
function CreateLayer(layerSize)
local layer = {}
for i = 1, layerSize, 1 do
local n = CreateEmptyNeuron();
table.insert(layer, n)
end
return layer;
end
--layerSize is actually an array of integers representing the array sizes of
--each individual layer (first layer is the input layer, last layer is output layer)
function CreateLayers(numLayers, layerSize)
local layers = {}
for i = 1, numLayers, 1 do
local layer = CreateLayer(layerSize[i]);
table.insert(layers, layer)
end
return layers;
end
--This function initializes the "val" variable in each table, and
--forward connects each neuron to every node in the next layer...
function ForwardConnectLayers(network)
for i = 1, #network, 1 do
local layer = network[i]
local next_layer = nil
if (i+1) < #network then
next_layer = network[i+1]
else
print("We have reached the output layer...")
next_layer = nil
end
for j = 1, #layer, 1 do
local neuron = layer[j]
neuron.val = (math.random() + math.random(0, 100))/100;
if next_layer ~= nil then
for x = 1, #next_layer, 1 do
neuron.forward[x] = math.random(1, 100)/100
print("Found forward layer...")
end
else
print("We cannot forward connect the output layer...\n")
end
end
end
end
function BackwardConnectLayers(network)
for i = 1, #network, 1 do
local layer = network[i]
local prev_layer = nil
if (i-1) > 1 then
prev_layer = network[i-1]
else
print("We have reached the input layer...")
prev_layer = nil
end
for j = #layer, 1, -1 do
local neuron = layer[j]
--neuron.val = (math.random() + math.random(0, 100))/100;
if prev_layer ~= nil then
for x = 1, #prev_layer, 1 do
table.insert(neuron.backward, prev_layer[x])
print("Found input layer...")
end
else
print("We cannot backward connect the input layer...\n")
end
end
end
end
function CreateBrain()
local LAYER_SIZES = {
10, 20, 20, 5
}
local brain = CreateLayers(4, LAYER_SIZES)
ForwardConnectLayers(brain)
BackwardConnectLayers(brain)
return brain;
end
AI = CreateBrain();
AI.Run = function(inputs, expectedOutputs)
local input_layer = AI[1]
local output_layer = AI[#AI]
for i = 0, #inputs, 1 do
input_layer[i] = inputs[i]
end
--For each layer in the network...
for l = 1, #AI, 1 do
--Get the next layer and this layer...
local this_layer = AI[l]
local next_layer = AI[l+1]
--And for each neuron in the next layer...
--Multiply the value of the neuron in this layer by
--the value of the modifier, and set the value of the next
--Neuron to be nextneuron.val + sum(<x>.val*<x>[k])
if next_layer ~= nil then
for m = 1, #next_layer, 1 do
local prev_layer_sum = 0
for n = 1, #this_layer, 1 do
local neuron = this_layer[n]
print(neuron)
end
end
end
end
end
ai_inputs = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }
expected_outputs = { 8, 8, 8, 8, 8 }
AI.Run(ai_inputs, expected_outputs)
When I run the code as shown, it, as expected, prints a list of addresses to memory for Lua tables:
But then, if I alter AI.Run to the following:
AI.Run = function(inputs, expectedOutputs)
local input_layer = AI[1]
local output_layer = AI[#AI]
for i = 0, #inputs, 1 do
input_layer[i] = inputs[i]
end
--For each layer in the network...
for l = 1, #AI, 1 do
--Get the next layer and this layer...
local this_layer = AI[l]
local next_layer = AI[l+1]
--And for each neuron in the next layer...
--Multiply the value of the neuron in this layer by
--the value of the modifier, and set the value of the next
--Neuron to be nextneuron.val + sum(<x>.val*<x>[k])
if next_layer ~= nil then
for m = 1, #next_layer, 1 do
local prev_layer_sum = 0
for n = 1, #this_layer, 1 do
local neuron = this_layer[n]
for k, v in pairs(neuron) do
print(k .. ", " .. v)
end
end
end
end
end
end
I get the following error message:
Indicating that Lua thinks the table is a number... which is, suffice to say, confusing. There's probably some language technicality defining this behavior, but I can't find good documentation surrounding this (in part because I don't even know what term to search; I'm not usually a Lua programmer).
EDIT:
So, it appears, somewhere in the code, numbers are getting inserted into the layers...
(Link to online Lua compiler where you can run the code: http://tpcg.io/_WPRPQV)
Your AI.Run function does
local input_layer = AI[1]
for i = 0, #inputs, 1 do
input_layer[i] = inputs[i]
end
where inputs is a table of numbers, i.e. the first layer of your network is replaced by just numbers.
You probably want to replace the val of the neuron in that layer instead:
local input_layer = AI[1]
for i = 0, #inputs, 1 do
input_layer[i].val = inputs[i]
end
Related to a previous topic, helpfully answered by Piglet who directed me to documentation in this question: Using a table in Lua to display text isn't working?... for reference.
Because of how long the project has taken me, I decided to rework a good chunk of the program in order to meet my deadline. I used the documentation's help to properly fix the .text display. However, I should have had a functional changing "vnText" object that I could adjust the text of. However... it only works when I use Runtime event listener, and not the object itself.
While I am perfectly happy using the Runtime event listener to complete my project by the deadline, I would like to know why object:addEventListener didn't work as usual. Is there something I am missing in my code, something that Runtime accomplished that clicking on "textRect" won't?
The line in particular is
Runtime:addEventListener("tap", changePage)
It works perfectly now when I run it. The values are drawn from the table, the command print("change text") is displayed.
The object I tried to use in its place was textRect, which is defined earlier on in the program, a couple tables above. That didn't work to draw the text out and put it in the text. But Runtime did and I, for the life of me, cannot understand why.
HOWEVER, an interesting fact is that when I used textRect, "change text" was printed. But the function didn't change vnText.text...? Which is the whole reason I wrote up the program.
I have scoured documentation and other threads hoping to find an answer to this. The code, however, is much more complicated than my own level, since I'm just a high school student learning from class powerpoints ; right now I'm just searching for an answer as to why Runtime works? And if there is anything I can do to make the object work instead.
Thanks for your help, members of Stack Overflow! You all have helped me to learn tons in the past month.
local store = require( "plugin.google.iap.v3" )
local composer = require("composer")
local scene = composer.newScene()
display.setStatusBar( display.HiddenStatusBar ) -- Removes status bar
coins = 5 --[[variable that defines the number of coins player has in the game. It will be different
in a stand alone game, but as a small app meant to demonstrate function, it's necessary to start off
with a small, defined number in the beginning.]]
local logo = display.newImage("/Images/logo.png", 155, 275) --code for my personal logo, drawn by me.
--Not actually showcased in the video because of time limit.
logo.alpha = 0
local function makeTitleTrue() --this function makes the title true once the logo has been shown and faded out
logo:removeSelf() -- removes logo from screen
print("menu should be TRUE")
titleScreen() -- calls function titleScreen (which is thetitle menu)
end
local function fadeOut()
transition.to(logo, {time = 1000, alpha = 0, onComplete = makeTitleTrue})
end
transition.to(logo, {time = 1000, alpha = 1, onComplete = fadeOut}) -- end of logo code
function titleScreen() -- beginning of title code, which is not managed as a separate scene
title = true
titleImg = display.newImage("/Images/vn_bg.png", 155, 275)
--titleWords = display.newImage("/Images/TitleWords.png", 155, 275)
--particles that flow across the screen as a cool effect. fix to flow towards the upper right corner.
local flare = display.newImage("/Images/flare2.png", 40, 30)
flare.xScale = .5
flare.yScale = .5
local flare2 = display.newImage("/Images/flare2.png", 400, 70)
flare2.xScale = .6
flare2.yScale = .6
local flare3 = display.newImage("/Images/flare2.png", -30, 100)
flare3.xScale = .4
flare3.yScale = .4
local flare4 = display.newImage("/Images/flare2.png", 100, 400)
flare4.xScale = .4
flare4.yScale = .4
local flare5 = display.newImage("/Images/flare2.png", 400, 400)
flare5.xScale = .3
flare5.yScale = .3
local flare6 = display.newImage("/Images/flare2.png", 250, 200)
flare6.xScale = .3
flare6.yScale = .3
local function moveFlare1()
transition.to(flare, {time=2000, x = math.random(-100, 450), y = math.random(-100, 700), onComplete = moveFlare1})
end
local function moveFlare2()
transition.to(flare2, {time=2000, x = math.random(-100, 450), y = math.random(-100, 700), onComplete = moveFlare2})
end
local function moveFlare3()
transition.to(flare3, {time=2000, x = math.random(-100, 450), y = math.random(-100, 700), onComplete = moveFlare3})
end
local function moveFlare4()
transition.to(flare4, {time=2000, x = math.random(-100, 450), y = math.random(-100, 700), onComplete = moveFlare4})
end
local function moveFlare5()
transition.to(flare5, {time=2000, x = math.random(-100, 450), y = math.random(-100, 700), onComplete = moveFlare5})
end
local function moveFlare6()
transition.to(flare6, {time=2000, x = math.random(-100, 450), y = math.random(-100, 700), onComplete = moveFlare6})
end
transition.to(flare, {time=2000, x = math.random(-100, 450), y = math.random(-100, 700), onComplete = moveFlare1})
transition.to(flare2, {time=2500, x = math.random(-100, 450), y = math.random(-100, 700), onComplete = moveFlare2})
transition.to(flare3, {time=2000, x = math.random(-100, 450), y = math.random(-100, 700), onComplete = moveFlare3})
transition.to(flare4, {time=2000, x = math.random(-100, 450), y = math.random(-100, 700), onComplete = moveFlare4})
transition.to(flare5, {time=2000, x = math.random(-100, 450), y = math.random(-100, 700), onComplete = moveFlare5})
transition.to(flare6, {time=2000, x = math.random(-100, 450), y = math.random(-100, 700), onComplete = moveFlare6})
--add options that can when the screen is tapped, tap on an option twice to select
--local newGame_op = display.newImage("", )
--local cont_op = display.newImage("", )
--local coin_op = display.newImage("",)
--local end_op = display.newImage("",)
-- start story
-- continue story
-- coin gambling
-- end game
if (title == true) then
Runtime:addEventListener("tap", sceneVN)
end
--coin_op:addEventListener("tap", coinShop)
end
function forceQuit()
function quit()
os.exit()
end
timer.performWithDelay(1000,quit)
end
function sceneVNChapter2()
return
end
function sceneVN() -- the actual visual novel code itself
display.remove(titleImg)
display.remove(flare)
display.remove(flare2)
display.remove(flare3)
display.remove(flare4)
display.remove(flare5)
display.remove(flare6)
title = false
Runtime:removeEventListener()
page = 0
local coinSheetData =
{
width = 32,
height = 32,
numFrames = 8,
}
local coinimageSheet = graphics.newImageSheet( "/Images/spinning_coin.png", coinSheetData )
local sequenceData =
{
name= "spinning_coin",
start = 1,
count = 8,
time = 1000,
loopCount = 0
}
--the properties of the name plate that can be changed ingame by using ".text" property
local nameOptions =
{
text = "Frankenstein",
x = 165,
y = 450,
width = 310,
font = "Charlesworth.ttf",
fontSize = 22,
align = "left"
}
local bg = display.newImage("/Images/bg4.jpg", 155, 275)
local bust_display = display.newImage( "/Images/f_bust1.png", 155, 223 )
textRect = display.newRect(155, 525, 325, 200)
textRect:setFillColor(.02, .02, .02)
textRect.alpha = .9
local frames = display.newImage("/Images/windowframes_gold.png", 155, 275)
display.newText(nameOptions)
local scriptIntro =
{
[1] = "\"I see. So I\'m supposed to pretend I am\na character in a multi-chapter phone\napp that you\'ve been reading...\"",
[2] = "\"So the purpose of this game is to flirt\nwith me until the meter fills up, and\nyou earn enough coins for a date?\"",
[3] = "\"Then let's see how far you get. Charm\nme by picking the right compliments\nto praise me, my lady.\"",
[4] = "\"When the meter is full, you'll be able\nto ask me on a date to progress the\ngame.\"",
[5] = "\"Let's start the game, then... Can you\ncharm me, the butler of the Raizel\nhousehold?\""
}
vnText = display.newText("\"Good evening. This is a demonstration\nof a visual novel and minigame...\"", 160, 500, "Goudy Old Style Regular.ttf", 17)
vnText.x = 20 ; vnText.y = 495
vnText:setFillColor( 1, 1, 1 )
vnText.anchorX = 0
local function changePage()
page = page + 1
print("change text")
vnText.text = scriptIntro[page]
end
Runtime:addEventListener("tap", changePage)
function choiceGame()
local c_Complimented = {
[1] = "\"Aha... thank you so much. I do my best.\"",
[2] = "\"Ah, please, you flatter me too much! I\ncannot even begin to compare with\nyour praises.\"",
[3] = "\"You're making me blush, my lady. Where\ndid you learn such charm?\"",
[4] = "\"I really don't know what to say... how\nsweet.\""
}
local c_Insulted = {
[1] = "\"Is that really your best attempt at a\nflirt? Pathetic...\"",
[2] = "\"A butler of the Raizel household can\'t\n even begin to contemplate the idea\n of dating you.\"",
[3] = "\"Haha... what a wonderful choice... NOT.\nTry again, darling.\"",
[4] = "\"Such insults are below even your calibre,\n my lady.\""
}
local function optionChosen()
if (compliment == true) then
displayStatus.text = c_Complimented[math.random(1,4)]
else
displayStatus.text = c_Insulted[math.random(1,4)]
end
end
displayStatus = display.newText("Haha... I look forward to your attempts\nat flirting with me.", 160, 500, "Goudy Old Style Regular.ttf", 17)
Runtime:addEventListener("tap", optionChosen)
end -- end of choice game
local function flirtComplete()
local scriptComplete =
{
[1] = "\"Then, seeing as this is a simulation of\n a visual novel dating sim, I have no\n choice but to ask you...\"",
[2] = "\"My lady, would you go on a date with me?\nFrankenstein... butler of the finest noble,\nCadis Etrama di Raizel?\"",
[3] = "\"So, have you made a decision about whether\nyou would like to date yet?\""
}
end
if (coins < 10) then
coinsDigits = 2
else
if (coins > 9) and (coins < 100) then
coinsDigits = 3
else
if (coins > 99) and (coins < 1000) then
coinsDigits = 4
else
if (coins > 999) and (coins < 10000) then
coinsDigits = 5
else
if (coins > 9999) and (coins < 100000) then
coinsDigits = 6
end
end
end
end
end
cooin = display.newSprite(coinimageSheet, sequenceData)
cooin.x = 25
cooin.y = 30
cooin:play()
coinText = display.newText("1", 57 + 4 * coinsDigits, 32, "VCR_OSD_MONO_1.001.ttf", 25)
coinText.text = coins
coinTimer = timer.performWithDelay(2000, cooin, 1)
end
function choiceMade( event ) --the scenes where all the choices are made
if (event.action == "clicked") then
local i = event.index
if (i == 1) then
Runtime:removeEventListener()
titleScreen()
else
if (i == 2) then
system.openURL( "https://www.paypal.com/us/home" )
else
if (i == 3) then
return
end
end
end
end
end -- end of choice scenes
function Outofcoins()
--native alert lack of zero coins
local alertMessage = "Uh oh, looks like you've run out of coins! Would you like to keep flirting, or buy more?"
native.showAlert( "Out of coins!", alertMessage, {"Continue flirting", "Purchase coins", "Exit to Menu"}, choiceMade)
end
function sceneGambleStart()
function earntCoins()
numberEarnt = 0
local coinsGot = display.newImage("/Images/coins_gold.png", 155, 275)
coinsGot.alpha = 0
local function fadeOutCoinsEart()
transition.to(logo, {time = 2000, alpha = 0})
display.remove(coinsGot)
end
local transitionFade = transition.to(logo, {time = 2000, alpha = 1, onComplete = fadeOutCoinsEarnt})
timer.performWithDelay(2000, transitionFade, 1)
coinText.text = coins + numberEarnt
end
end
As your code is, textRect and vnText are both global in scope but scriptIntro is local and declared after textRect. So if you tried to add a tap listener to textRect in which you refer to scriptIntro, it wouldn't work. In fact, all of these variables could be local; just declare them in the right order:
local scriptIntro = ... -- an array of strings
local vnText = display.newText(...
vnText.text = scriptIntro[1]
local n = 1
local textRect = display.newRect(...
function textRect:tap( event )
n = n + 1
if n > #scriptIntro then
n = 1
end
vnText.text = scriptIntro[n]
return true
end
textRect:addEventListener( "tap", textRect )
I am creating a game in which liquid will come out. I am using the particle systems of the physics engine of Corona. For the parameter of particle group, i get it from a method. When i run the program i get an error message saying that the parameter is a nil value.
Code:
-- Will randomly drop water stream at random locations and with random colors
--Delcare class variables
local physics = (require"physics")
physics.start()
local w = display.contentWidth
local h = display.contentHeight
local particleSystem = physics.newParticleSystem({
filename = "particle.png",
colorMixingStrength = 0.1,
radius = 3,
imageRadius = 6
})
--function to start the water stream
local function start()
end
--fucntion to end the water stream
local function stop()
end
--a function to create particle paramerters
-- flag to determine if the particle parameter should have random colors
-- WILL have RANDOM location
local function createParticleParameter(flag, x, y, color)
local param = {
flags = flags,
x = x,
y = y,
color = color,
radius = 10,
linearVelocityX = 0,
linearVelocityY = 10,
lifetime = 10
}
return param
end
local function onTimer()
local parmas = createParticleParameter("water", math.random(0, display.contentWidth), 0, {0, 1, 0})
particleSystem:createGroup(params)
end
timer.performWithDelay( 1000, onTimer, 0 )
The error message:
---------------------------
Corona Runtime Error
---------------------------
attempt to index a nil value
stack traceback:
[C]: in function 'createGroup'
main.lua:47: in function '_listener'
?: in function <?:167>
?: in function <?:221>
I checked if the parameter was right, and it was because when i ran this program it worked for some reason:
-- Will randomly drop water stream at random locations and with random colors
--Delcare class variables
local physics = (require"physics")
physics.start()
local w = display.contentWidth
local h = display.contentHeight
local particleSystem = physics.newParticleSystem({
filename = "particle.png",
colorMixingStrength = 0.1,
radius = 3,
imageRadius = 6
})
--function to start the water stream
local function start()
end
--fucntion to end the water stream
local function stop()
end
--a function to create particle paramerters
-- flag to determine if the particle parameter should have random colors
-- WILL have RANDOM location
local function createParticleParameter(flag, x, y, color)
local param = {
flags = flags,
x = x,
y = y,
color = color,
radius = 10,
linearVelocityX = 0,
linearVelocityY = 10,
lifetime = 10
}
return param
end
local function onTimer()
local parmas = createParticleParameter("water", math.random(0, display.contentWidth), 0, { 0,1,0})
particleSystem:createGroup({
flags = "water",
x = math.random(0, display.contentWidth),
y = 0,
color = {0, 1,0 },
radius = 10,
linearVelocityX = 0,
linearVelocityY = 10,
lifetime = 10
})
end
timer.performWithDelay( 1000, onTimer, 0 )
With the only major difference is that I manually placed the parameters.
Why is this happening?
You spelled params wrong
local parmas = createParticleParameter("water", math.random(0, display.contentWidth), 0, {0, 1, 0})
The restart game function doesn't seem to work and I don't know why. The balloons, scores resets but the game doesn't resets, i can't shoot the balloons again. (plus the askUser, yesBtn and noBtn doesn't go invisible either)
function createBalloons(a, b)
for i = 1, a do
for j = 1, b do
local balloon = display.newImage ('balloon_fat_red.png', 270+ (i * 30), 80 + (j * 50))
balloonText = display.newText(hiragana_array[x+1], 300, 125)
balloonTextt = display.newText(hiragana_array[x+2], 300, 175)
balloonTexttt = display.newText(hiragana_array[x+3], 300, 225)
balloonText:setFillColor( 1,1, 0 )
balloonTextt:setFillColor( 1,1, 0 )
balloonTexttt:setFillColor( 1,1, 0 )
balloon.name = 'balloon'
physics.addBody(balloon)
balloon.bodyType = 'static'
table.insert(balloons, balloon)
end
end
target.text = #balloons
end
function restartLvl()
for i = 1, #balloons do
display.remove(balloons[i])
print ("restart level")
end
score.text = '0'
ballRemain.text = '3'
balloons = {}
createBalloons(1, 3)
askUser.isVisible = false
yesBtn.isVisible = false
noBtn.isVisible = false
print("time from start: ", (system.getTimer()-gameTime))
print('send mail')
sendMail()
end
This is what it shows in the simulator.
I'm not seeing any problem with that code, my guess is the problem is elsewhere. You're going to have to dig a little more, maybe put some more print statements. For example maybe isVisible is being reset to true by another function, after the restartLvl, like in an enterFrame handler.
I'm pretty new to lua as you can probably tell by the code, i'm trying to remove an object that says "Stop!" when the time runs out by using an event listener on a button object that's also created when the time runs out. This returns the error attempt to index global 'stopit' (a nil value). I declared it as a local var in the class that adds it to the screen so i'm not sure whats going on. I have organized and tried this several different ways and I can't get it to loop continually without randomly crashing either immediately or after one or two rounds of the game.
Here is the code:
display.setStatusBar(display.HiddenStatusBar)
local centerX = display.contentCenterX
local centerY = display.contentCenterY
local score = 0
local dextime;
local stopit;
local button3;
function newTarget(event)
timer.performWithDelay(100, function() display.remove(target) end)
transition.to(target, {time=99, xScale=.4, yScale=.4})
timer.performWithDelay(101, dexit)
score = score + 10
scoreTxt.text = ("Score:" .. score)
end
function dexit()
stopit = display.newImage("stop.png")
stopit.x = 300
stopit.y = 600
stopit.isVisible = false
button3 = display.newImage("button3.png")
button3:addEventListener("tap", removeitems)
button3.x = centerX
button3.y = centerY
button3.isVisible = false
target = display.newImage("target.png")
target.xScale = .25
target.yScale = .25
target.x = math.random(50, 550)
target.y = math.random(50, 750)
target:addEventListener("tap", newTarget)
local function removeitems(event)
stopit:removeSelf()
button3:removeSelf()
scoreTxt:removeSelf()
timerTxt:removeSelf()
timer.performWithDelay(500, setup)
dextime = 15
score = 0
end
timer.performWithDelay(15000, function() display.remove(target) end)
timer.performWithDelay( 15000, function() button3.isVisible = true end)
timer.performWithDelay(15000, function() stopit.isVisible = true end)
end
local function dexgo()
timer.performWithDelay(1000, function() dextime = dextime - 1 end, 15)
timer.performWithDelay(1001, function() timerTxt.text = ("Time:" .. dextime) end, 15)
dexit()
end
local function one2()
local one = display.newImage("1.png")
one.x = centerX
one.y = centerY
one.alpha = 0
transition.to(one, {time=1000, alpha =1, onComplete=dexgo})
timer.performWithDelay( 1000, function()
display.remove(one)
end, 1)
end
local function two2()
local two = display.newImage("2.png")
two.x = centerX
two.y = centerY
two.alpha = 0
transition.to(two, {time=1000, alpha =1, onComplete=one2})
timer.performWithDelay( 1000, function()
display.remove(two)
end, 1)
end
local function dexMode()
local three = display.newImage("3.png")
three.x = centerX
three.y = centerY
three.alpha = 0
timerTxt = display.newText("Time:" .. dextime,-1, centerX - 440, "Helvetica", 40)
scoreTxt = display.newText( "Score:" .. score, 440, -140, "Helvetica", 40)
display.remove(mode1)
display.remove(mode2)
display.remove(title)
transition.to(three, {time=1000, alpha =1, onComplete=two2})
timer.performWithDelay( 1000, function()
display.remove(three)
end, 1)
bg = nil
title = nil
mode1 = nil
mode2 = nil
end
function listener(event)
simpleMode()
end
function listener2(event)
dexMode()
end
function startGame()
transition.to( title, { time=2000, y=0, alpha=.9, onComplete=showTitle})
transition.to(bg, { time=2000, y=centerY, alpha=1})
transition.to(mode1, { time=2000, x=centerX, alpha=.9})
transition.to(mode2, { time=2000, x=centerX, alpha=.9})
end
function setup()
dextime = 15;
bg = display.newImage("background.png")
bg.yScale = 1.4
bg.alpha = 0
title = display.newImage("title.png")
title.x = centerX
title.y = -200
title.alpha = 0
mode1 = display.newImage("button1.png")
mode1.xScale = 1.23
mode1.yScale = 1.23
mode1.x = 800
mode1.y = 500
mode1.alpha = 0
mode2 = display.newImage("button2.png")
mode2.xScale = 1.23
mode2.yScale = 1.23
mode2.x = -200
mode2.y = 625
mode2.alpha = 0
mode1:addEventListener( "touch", listener )
mode2:addEventListener( "touch", listener2 )
startGame()
end
setup()
The usage of in stopit button3, scoreTxt and timerTxt in function removeitems(event) are globally scoped. When removeitems gets called in dexit it cannot see the local variables you declared in dexit.
The easiest solution is to make removeitems a closure by moving it into dexit:
function dexit()
local stopit = display.newImage("stop.png")
local button3 = display.newImage("button3.png")
local function removeitems(event)
stopit:removeSelf()
button3:removeSelf()
scoreTxt:removeSelf()
timerTxt:removeSelf()
timer.performWithDelay(500, setup)
end
-- ...
end
Try this:
if(stopit~=nil)then
stopit:removeSelf()
end
You are getting this error due to timer and transition. When you are removing an object without canceling timer or transition, it's calling in loop and getting nil value after removing once.
First of all you need to store all the timer and transition in array and release array while stoping game or changing scene. Then Reinitialize array again.
Ex: local timerId = {}
local TransitionID = {}
timerId[#timerId+1] = timer.performWithDelay(15000, function() display.remove(target) end)
TransitionID[#TransitionID+1] = transition.to(two, {time=1000, alpha =1, onComplete=one2})
When removing all the object remove timer and transition first.
for i = 1, #timerId do
timer.cancel(timerId[i])
timerId[i] = nil
timerId = {} //Initializing array
end
for j = 1, #transitionID do
transition.cancel(transitionID[j])
transitionID[j] = nil
transitionID = {}
end