attempt to call method 'insert' (a nil value) when i restart game - lua

I've added objects to the group so they get deleted and respawn when the game restarts but when the game restarts it gives the following error "attempt to call method 'insert' (a nil value)"
This is my object code:
local function spawnObject()
local objIdx = mRandom(#objects)
objName = objects[objIdx]
object = display.newImage( "images/fruit_" .. objName .. "_100.png" )
object.x = mRandom(screenLeft+30, screenRight-30)
object.y = screenTop
object.rotation = mRandom(-15, 15)
object.id = mRandom(-15,15)
group:insert( object )
if objIdx < 4 then
object.type = "food"
else
object.type = "other"
end
physics.addBody(object, "dynamic",{radius=45 , bounce = bt})
grassfront320w:toFront()
object.collision = objectCollision
object:addEventListener( "collision", object )
end
And for restarting I go to restart scene which I've created and from there I go back to my play scene.
Please help me solve the problem.

Don't add directly to the group view. Make a separate display group for the objects
local objectGroup = display.newGroup()
group:insert(objectGroup)
by doing it this way, you are not obligated to kill out the group when you change scene (if you are using composer or storyboard). It will clear it self in the memory when you change scene.

Related

how do i stop objects from spawning automatic

ok whenever i try to reload the scene the objects from the previous scene dont stop spawning
here is my code, I want to delete all the objects from screen before moving to another screen
local objects = {
"banana",
"grape",
"pineapple",
"bomb",
"watermelon",
}
local function spawnObject()
objIdx = mRandom(#objects)
objName = objects[objIdx]
object = display.newImage( "images/fruit_" .. objName .. "_100.png" )
object.x = mRandom(screenLeft+30, screenRight-30)
object.y = screenTop
object.rotation = mRandom(-15, 15)
object.id = mRandom(-15,15)
if objIdx < 4 then
object.type = "food"
else
object.type = "other"
end
end
Insert your object (from display.newImage) into the scene view / display group.
Then it will get deleted automatically if you change screen.
Other option is to store all objects in a table, and call removeSelf() on each object in the table when you want to delete them.

Corona Sdk - Is there a way to call and group:insert() an object from another lua file?

As stated in the title I would like to not only call an object from an external Lua file, but I would also like to group:insert() this object into my Menu page with the properties given to it in the external lua file. Is this possible and/or efficient? I would just really like to make sure data isn't repeated through out my project.
EDIT
Here's my code so far:
The group:insert() function is throwing me an error stating it was expecting a table and that I might have been trying to call a function in which case i should use ":" instead of "."
This is menu.lua:
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local widget = require "widget"
local m = require ("myData")
local menuFunction = require("menuFunction")
local menuSwipe
-- =======================
-- menuSwipe()
-- =======================
menuSwipe = function(self, event)
local phase = event.phase
local touchID = event.id
if(phase == "began") then
elseif(phase == "moved") then
elseif(phase == "ended" or phase == "cancelled") then
if(m.menuActivator > 0) then
menuDown(m.invisiBar, event)
else
--m.layerInfo = layers
transition.to( menuFunction.menuBar, { x = menuFunction.menuBar.x, y = 0, time = 200 } )
--transition.to( layers, { x = menuFunction.menuBar.x, y = h, time = 100 } )
m.invisiBar = display.newRect( 0,0,w,25,6)
m.invisiBar.alpha = 0
m.menuActivator = 1
end
end
end
-- ++++++++++++++++++++++
-- menuDown()
-- ++++++++++++++++++++++
function menuDown(self, event)
local phase = event.phase
local touchID = event.id
if(phase == "began") then
elseif(phase == "moved") then
elseif(phase == "ended" or phase == "cancelled") then
if(m.menuActivator == 1) then
transition.to( menuFunction.menuBar, { x = m.menuInfo.x, y = h*.964, time = 200 } )
--transition.to( group, { x = 0, y = 0, time = 10 } )
m.menuActivator = 0
end
end
end
function scene:createScene( event )
local group = self.view
group:insert( menuFunction.menuBar ) -- *** ERROR occurs here
end
function scene:enterScene( event )
local group = self.view
end
function scene:exitScene( event )
local group = self.view
end
function scene:destroyScene( event )
local group = self.view
end
scene:addEventListener( "createScene", scene )
scene:addEventListener( "enterScene", scene )
scene:addEventListener( "exitScene", scene )
scene:addEventListener( "destroyScene", scene )
return scene
This is menuFunction.lua:
local m = require("myData")
local menu = require ("menu")
local w = display.contentWidth
local h = display.contentHeight
local menuFunction = {}
--menuBar
menuFunction.menuBar = display.newImage( "images/menuBar1.png")
menuFunction.menuBar.x = w*(1/2)
menuFunction.menuBar.y = h*1.465
menuFunction.menuBar.height = h
menuFunction.menuBar:setReferencePoint(display.TopLeftReferencePoint)
menuFunction.menuBar.touch = menu.menuSwipe
menuFunction.menuBar:addEventListener("touch", menuFunction.menuBar)
return menuFunction
This is the exact error message:
ERROR: table expected. If this is a function call, you might have used '.' instead of ':'
message**
Does this happen every time this code is called, or does it by any chance work the first time and then crashes? In your case, code could work the first time you enter the scene, but the second time you do, it may crash [if you remove scenes in between].
When you do a 'require' of a file, its contents are executed and returned value is saved in the global packages table. When you require the same file again, the returned value is taken from the global packages table instead, the code is not executed again.
So if you by any chance require this file in one spot of your app, and then call :removeSelf() and nil the reference of the menuBar, the display object will be removed and its reference will cease to exist, and calling the require again, will not recreate the object. Fully removing a scene will also remove the display objects.
So what you wanted to achieve is very sensible [contrary to what #Schollii says], but your "module" should allow creation of multiple objects if you want to get rid of them during runtime.
I'm not going to correct your code, just a simple example of how you can achieve this:
-- menu.lua
local menuCreator = {}
menuCreator.newMenu = function(params)
local menu = display.newGroup()
-- create your menu here
return menu
end
return menuCreator
Now anytime you do:
local menuCreator = require("menu.lua")
you will be able to call:
local menu = menuCreator.newMenu(someParams)
and get yourself a nice new menu wherever you need.
If it's not shown all the time on screen, it may be better to create a new one whenever you need it, and then remove it from the memory.
There are several issues with this, and none of them seem related to your error but fixing them will either also fix the error or make the cause of the error more obvious. Please fix following and update:
Although Lua allows it, don't use circular includes, where A includes B which includes A. Instead have menu require menuFunction and then call a creation function in menuFuntion:
-- menuFunction.lua
local m = require("myData")
-- require("menu") -- BAD! :)
local w = display.contentWidth
local h = display.contentHeight
local menuBar = display.newImage( "images/menuBar1.png")
menuBar.x = w*(1/2)
menuBar.y = h*1.465
menuBar.height = h
menuBar:setReferencePoint(display.TopLeftReferencePoint)
local menuFunction = { menuBar = menuBar }
function createMenuBar(menuSwipe)
menuFunction.menuBar.touch = menuSwipe
menuFunction.menuBar:addEventListener("touch", menuFunction.menuBar)
return menuFunction
end
-- menu.lua
function createScene(event)
local mf = require('menuFunction')
mfFunction = mf.createMenuBar(menuSwipe)
group:insert(menuFunction.menuBar)
end
Secondly out of the four calls to group:insert() the first 3 refer to objects that are not shown in the code and don't see relevant to problem, they should be removed or if you think relevant, comment why their code now shown, or show their code.

Images doesn´t appear in storyboard Corona SDK

I am doing a game in corona SDK, but I have this little problem.
I have a menu with a button. If I press it, it sends me to the first level of my game.
When I pass the final level, the game return me to the menu. Bur, if I start playing the first again, my images doesn´t appear.
The images are balls, and to pass the level, you have to eliminate all the balls. To do this, I use:
ball:removeSlef()
ball = nil
But, I don´t think that this is the problem, because I eliminate this lines, and it doesn´t work.
The images are create in scene:createScene function, and insert in the Group.
I short the code of the first level to be understood.
local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local physics = require "physics"
physics.start(); physics.pause()
physics.setGravity( 0, 0 )
local cont = 0
local bur = {}
function eliminar1( event )
if (cont == 0) and (event.phase == "began") then
event.target:removeSelf()
bur[1] = nil
cont = cont + 1
end
end
function eliminar2( event )
if (cont == 1) and (event.phase == "began") then
bur[2]:removeSelf()
bur[2] = nil
cont = cont + 1
end
end
function eliminar3( event )
if (cont == 2) and (event.phase == "began") then
bur[3]:removeSelf()
bur[3] = nil
storyboard.gotoScene( "levels.1.level2" )
end
end
function scene:createScene ( event )
local screenGroup = self.view
for i = 1,3 do
bur[i] = display.newImage("irudiak/"..i..".png")
bur[i]:translate(math.random(0,280), math.random(0,400) )
physics.addBody( bur[i], {bounce = 0.3 } )
bur[i]:setLinearVelocity(math.random(-50,50), math.random(-50,50) )
screenGroup:insert(bur[i])
end
bur[1]:addEventListener("touch", eliminar1)
bur[2]:addEventListener("touch", eliminar2)
bur[3]:addEventListener("touch", eliminar3)
end
function scene:enterScene( event )
local screenGroup = self.view
physics.start()
end
function scene:exitScene( event )
local screenGroup = self.view
physics.stop()
end
function scene:destroyScene( event )
local screenGroup = self.view
package.loaded[physics] = nil
physics = nil
end
return scene
createScene is ran only first time when you gotoScene. Every next time only willEnterScene and enterScene are played. To play createScene again you have to remove it (storyboard.removeScene() I guess). Or you can move some stuff you need to willEnterScene. For more detailed info you can watch this: http://www.coronalabs.com/blog/2013/08/20/tutorial-reloading-storyboard-scenes/

Corona SDK 'nil value' issue

I am making a shooter game using the corona sdk...
My problem is that i am trying to delete an object(that is part of an array)when it leaves the screen.. when i do, i get an error that says 'trying to compare nil value to variable' which refers to a simple move function for every object in the array. Here is relevant parts of code:
function addAlien()
listeners('add')
end
function listeners(action)
if(action == 'add') then
Runtime:addEventListener('enterFrame',update)
enemyTimer = timer.performWithDelay(800,addEnemy,0)
else
Runtime:removeEventListener('enterFrame',update)
timer.cancel(enemyTimer)
end
end
function addEnemy(e)
enemy = display.newImage('drone.png')
enemy.x = 500
enemy.y = math.floor(math.random()*300)
enemy:scale(-0.1,0.1)
enemy.speed = math.random(2,6)
enemies.insert(enemies,enemy)
enemy.enterFrame = moveEnemy
Runtime:addEventListener('enterFrame',enemy)
end
function moveEnemy(self,event)
--if self.x < 100 then
---self:removeSelf()
--self = nil
--removeSelf()
--else
self.x = self.x-self.speed
--end
end
function update(e)
if(enemies.numChildren ~= 0)then
for i = 1,enemies.numChildren do
if(enemies[i] ~= nil)then
--enemies[i].x = enemies[i].x-3
if(enemies[i].x<100)then
--enemies:remove(enemies[i])
--display.remove(enemies[i])
--enemies[i] = nil
end
end
end
end
end
I have commented out the parts that give me errors.
Any help would be appreciated,
thanks
You might want to try and put the delete code in it's own function and then use a timer to remove it so that the function where you are currently deleting the object can return and you're not deleting yourself.
Another option would be to make it temporarily invisible and then loop through the table periodically and remove anything outside of the move handler.
You have a problem with the following code:
function listeners(action)
if(action == 'add') then
Runtime:addEventListener('enterFrame',update)
enemyTimer = timer.performWithDelay(800,addEnemy,0)
else
Runtime:removeEventListener('enterFrame',update)
timer.cancel(enemyTimer)
end
end
You only want to Runtime:addEventListener('enterFrame', update) once. If you do it everytime you add an enemy things will go wrong. The problem is your code runs again and again after the objects have been removed already.
hmmm. did you use the scene template? if so, you should only put the :removeself () and = nil values in the scene destroy section at the bottom. you also dont need the second removeself that is not attached to an object as that is probably the nil issue.
to summarize.
1-put all remove self () and = nil at the destroy section of scene template and use object.isVisible = false instead.
2-the nil error is most likely coming from the removeself() statement with no object. so change it to moveenemy:removeself ()
if my understanding is right this is how i would do it without using runtime
and using timer instead. ask away if you have question
local scrWidth = display.actualContentWidth
local scrHeight = display.actualContentHeight
local enemy = {} --this will hold your aliens
function addEnemy()
enemy[#enemy + 1] = display.newImage("drone.png")
enemy[#enemy].x = 500
enemy[#enemy].y = math.floor(math.random()*300)
enemy[#enemy]:scale(-0.1,0.1)
enemy[#enemy].speed = math.random(2,6)
end
local function update()
addEnemy()
--this will move the enemy to the left from right
for i=1,#enemy,1 do
enemy[i].x = enemy[i].x - enemy[i].speed
end
--the below codes will destroy each enemy that is out side the screen on the left
local function destroyWhenOutside()
for i=1,#enemy,1 do
if enemy[i].x < 0 - enemy[i].width then
enemy[i]:removeSelf()
enemy[i] = nil
elseif enemy[i].y < 0 - enemy[i].height then
enemy[i]:removeSelf()
enemy[i] = nil
end
end
end
destroyWhenOutside()
end
--this will loop the update every 1/1000 seconds
local timerUpdate = timer.performWithDelay(1,update,-1)
.

Delete object[i] from table or group in corona sdk

i have a problem (obviusly :P)
i'm create a mini game, and when i touch a Object-A , creates an Object-B.
If i touch N times, this create N Object-B.
(Object-B are Bubbles in my game)
so, i try when I touch the bubble (object-B), that disappears or perform any actions.
I try adding Object-B to Array
local t = {}
.
.
.
bur = display.newImage("burbuja.png")
table.insert(t,bur)
and where i have my eventListeners i wrote:
for i=1, #t do
bur[i]:addEventListener("tap",reventar(i))
end
and my function 'reventar'
local function reventar (event,id)
table.remove(t,id)
end
i'm lost, and only i want disappears the bubbles.
you're probably gonna want to do something like this:
local t = {}
bur = display.newImage("burbuja.png")
table.insert(t,bur)
-- declaring the function first so it can be used later in the for loop
local function reventar(event)
t[event.target.id] = nil -- We remove object from table
event.target:removeSelf() -- Also remember to remove from display
end
for i=1,#t do
t[i].id = i
t[i]:addEventListener("tap", reventar)
end
Hope this helps.
EDIT
I would do it this way, because it's better when you want to loop through the objects:
local t = {}
-- declaring the function first so it can be used later
local function reventar(event)
event.target.kill = true -- Mark the clicked object for later destruction
end
bur = display.newImage("burbuja.png")
bur:addEventListener("tap", reventar)
table.insert(t,bur)
local function loop(event)
for i = #t, 1, -1 do
local object = t[i]
-- Do stuff to object here, such as object.y = object.y + 1
if object.kill then -- Check if object is marked for destruction
local child = table.remove(t, i) -- Remove from table
if child ~= nil then
-- Remove from display and nil it
child:removeSelf()
child = nil
end
end
end
end
Runtime:addEventListener("enterFrame", loop) -- Remember to remove this when no longer needed

Resources