How come I get a attempt to call method 'insert' (a nil value) error on the line containing insert?
Changing it to instance.sprites = bg does make it work, but I want to return all sprites in a separate table (sprites).
local writingTool = {}
local _W, _H = display.contentWidth, display.contentHeight
function writingTool:new()
local instance = {}
instance.index = writingTool
setmetatable(instance, self)
instance.sprites = {}
local bg = display.newImage("images/backgrounds/wooden_bg.png")
bg.x = _W/2
bg.y = _H/2
instance.sprites:insert(bg)
return instance
end
return writingTool
Edit: Trying instance.sprites.bg = bg does not work either. Give this error:
bad argument #-2 to 'insert' (Proxy expected, got nil)
instance.index = writingTool
Should be
instance.__index = writingTool
Though I would remove the above line and implement it in the one below like so:
setmetatable(instance,{__index=writingTool})
Also, t:insert() or t.insert() aren't defined by default, to insert elements into a table you use the table.insert function as defined below:
table.insert (table, [pos,] value)
so you should have table.insert(instance.sprites,bg). So with these modifications your function should look like:
function writingTool:new()
local instance = { sprites = {} }
setmetatable(instance, {__index = wirtingTool})
local bg = display.newImage("images/backgrounds/wooden_bg.png")
bg.x = _W/2
bg.y = _H/2
table.insert(instance.sprites,bg)
return instance
end
Related
I wanna call GameScene setSpecificSquare function in Square, it will occur 'attempt to index field 'squares' error.
In my understanding, require("GameScene") in onTouchEnded(touch event) do not get the last variable of GameScene, it has not been constructed, so it does not have squares attribute.
How to call GameScene static function setSpecificSquare in Square? Or in other word, how to get the last GameScene so I can set self.squares table?
Thanks in advanced!! :)
Square.lua
require "Cocos2d"
require "Cocos2dConstants"
local Square = class("Square",function()
return cc.Node:create()
end)
function Square.create()
local square = Square.new()
return square
end
function Square:ctor()
self.bg = cc.Sprite:create("square_bg.png")
self:addChild(self.bg)
self.isHighlight = true
local function onTouchEnded(touch,event)
--occur error here
require("GameScene"):setSpecificSquare()
end
end
return Square
GameScene.lua
require "Cocos2d"
require "Cocos2dConstants"
local GameScene = class("GameScene",function()
return cc.Scene:create()
end)
function GameScene.create()
local scene = GameScene.new()
return scene
end
function GameScene:ctor()
self.visibleSize = cc.Director:getInstance():getVisibleSize()
self.x = cc.Director:getInstance():getVisibleOrigin().x
self.y = cc.Director:getInstance():getVisibleOrigin().y
self.squares = {}
for i=0, 5 do
self.squares[i] = {} -- create a new row
for j=0, 5 do
self.squares[i][j] = nil
end
end
--add layer
self.bombLayer = cc.Layer:create()
self:addChild(self.bombLayer)
--add squares
self:addSquares()
end
function GameScene:addSquares()
for i=0,5 do
for j=0,5 do
local square = require("src/Square"):create()
square:setPosition(0+j*70,0+i*70)
self.bombLayer:addChild(square)
self.squares[i][j] = square
end
end
end
function GameScene:setSpecificSquare()
--can not access self.square here, occur attempt to index field 'squares' error
self.square[0][0].isHighLight
end
return GameScene
Move self.squares = {} out of ctor function, or call ctor function before calling addSquares, or you can just call this function inside addsquares.
The recommended method is moving it out of function and creating it on creation of your GameScene object:
require "Cocos2d"
require "Cocos2dConstants"
local GameScene = class("GameScene",function()
return cc.Scene:create()
end)
function GameScene.create()
local scene = GameScene.new()
return scene
end
GameScene.squares = {}
...
OK my first question was too vague so I'm going to start simple here. I am trying to get a random word from a table in another lua file (content.lua). I have gotten the code to run without errors but cannot get a word to display on the screen or via print in the command console. What am I missing?
game.lua
--lua for game
--Loading the local variables
--creates the storyboard variable and calls the storyboard api
local storyboard = require ("storyboard")
--calls the mydata.lua module
local myData = require( "mydata" )
--calls the sfx.lua where sounds are stored
local sfx = require( "sfx" )
--calls the operations.lua
local operations = require("operations")
local content = require("content")
local playOrder
local wordGraphic
local currQuestion = 1
local homeButton
--tells storyboard to create a new scene
local scene = storyboard.newScene()
function scene:createScene(event)
local gameScreen = self.view
--creates a transparent background image centered on the display
local gameBackground = display.newImage("images/graphics/jungle1.jpg")
gameBackground.x = display.contentWidth/2
gameBackground.y = display.contentHeight/2
gameScreen:insert(gameBackground)
homeButton = display.newImage("images/buttons/home.png")
homeButton.alpha = .8
homeButton.y = 70
gameScreen:insert(homeButton)
playOrder = operations.getRandomOrder(#content)
end
local function onHomeTouch(event)
if event.phase == "began" then
storyboard.gotoScene("start")
end
end
function scene:enterScene(event)
homeButton:addEventListener("touch", onHomeTouch)
audio.play(sfx.Bkgd)
--uses the operations.lua to get words in a random order from the content.lua
--shows a random word from the content.lua table
function showWord()
local word = content[playOrder[currQuestion]].word
print(word)
wordGraphic = self.view
wordGraphic:insert(word)
wordGraphic.x = display.contentWidth/2
wordGraphic.y = display.contentHeight/2
end
end
--next question function which clears the screen and loads a new random word
function scene:exitScene(event)
homeButton:removeEventListener("touch", onHomeTouch)
end
function scene:destroyScene(event)
end
--the actual event listeners that make the functions work
scene:addEventListener("createScene", scene)
scene:addEventListener("enterScene", scene)
scene:addEventListener("exitScene", scene)
scene:addEventListener("destroyScene", scene)
return scene
Here is the operations.lua that gets the random order function
--operations.lua
module(..., package.seeall)
--function to get a random piece of data
function getRandomOrder(amount)
local order ={}
local i
local temp
local temp1
for n = 1,amount do
order[n] = n
end
for i=0,9 do
for temp = 1,amount do
n = math.random(1, amount)
temp1 = order[temp]
order[temp] = order[n]
order[n] = temp1
end
end
return order
end
This is where the words I am attempting to display are stored. I did not include all of them.
--content.lua
return {
{
id = "after",
word = "after"
},
{
id = "again",
word = "again"
},
{
id = "an",
word = "an"
},
{
id = "any",
word = "any"
},
{
id = "ask",
word = "ask"
},
{
id = "as",
word = "as"
},
{
id = "by",
word = "by"
}
}
You're not calling showWord in any of the code that you've shown so far. This is probably why it isn't even printing to the console. The function is just contained within scene:enterScene and exits to the outer scope, defining itself as a global variable when enterScene is called.
New to Corona (coming from Actionscript) and trying to work through some OOP tutorials to create reusable modules for my app. Currently working on a number picker, which seems to be working, but also throwing an error when I press the buttons. Here's the code for the 'numberPicker.lua':
local numberPicker = {}
local numberPicker_mt = { __index = numberPicker } -- metatable
widget = require "widget"
-------------------------------------------------
-- PUBLIC FUNCTIONS
-------------------------------------------------
function numberPicker.new() -- constructor
local newNP = display.newGroup()
local value = 0
local function dec()
print("dec")
if value > 0 then
value = value - 1
valueText.text = value
end
end
local function inc()
print("inc")
if value < 100 then
value = value + 1
valueText.text = value
end
end
decrement = widget.newButton{
default="gfx/dec_normal.png",
over="gfx/dec_press.png",
width=58, height=58,
onRelease = dec
}
valueText = display.newText(value, 70, 10, native.systemFont, 40)
valueText:setTextColor(0, 0, 0)
increment = widget.newButton{
default="gfx/inc_normal.png",
over="gfx/inc_press.png",
width=58, height=58,
onRelease = inc
}
increment.x = 140
newNP:insert(decrement.view)
newNP:insert(valueText)
newNP:insert(increment.view)
return setmetatable( newNP, numberPicker_mt )
end
return numberPicker
usage:
local numberPicker = require( "numberPicker" )
local lengthPicker = numberPicker.new()
scrollView:insert(lengthPicker)
When I press either button, I get the following error printing out twice:
Runtime error
attempt to call a nil value
stack traceback:
[C]: ?
Any clues anyone?
Thanks,
Emma.
"scrollView" variable was not initialized.
A very strange error, showing an object is nil.
the code in subject is
while pbs:HasNext() do
local char = self.DecodeCharacter(pbs)
...
One would think, that if pbs:HasNext() is true, it means that, pbs is not nil, whatsoever.
However, the print(pbs) - the first line of HTMLEntityCodec:DecodeCharacter prints nil
function HTMLEntityCodec:DecodeCharacter(pbs)
print(pbs)
...
The entire file dumped below, it was stripped from 1800+ lines to 110 so it can be clear for SO users to get he context. But that stripping took away all logic from the code, so do not get confused by that.
#!/usr/bin/env lua
function Inherits( baseClass )
local new_class = {}
local class_mt = { __index = new_class }
function new_class:create()
local newinst = {}
setmetatable( newinst, class_mt )
return newinst
end
if baseClass then
setmetatable( new_class, { __index = baseClass } )
end
return new_class
end
-------------------------------------------
-- PushbackString
-------------------------------------------
PushbackString = Inherits({})
function PushbackString:Init(input)
self.input = input
self.pushback = nil
self.temp = nil
self.index = 0
self.mark = 0
end
-- Mark the current index, so the client can reset() to it if need be.
function PushbackString:HasNext()
return true
end
function PushbackString:Mark ()
self.temp = self.pushback
self.mark = self.index
end
BaseCodec = Inherits({})
function BaseCodec:Decode(input)
local buff = ''
local pbs = PushbackString:create()
pbs:Init(input)
while pbs:HasNext() do
local char = self.DecodeCharacter(pbs)
if char ~= nil then
buff = buff .. char
else
buff = buff .. pbs:Next()
end
end
return buff
end
HTMLEntityCodec = Inherits(BaseCodec)
-- HTMLEntityCodec.classname = ('HTMLEntityCodec')
function HTMLEntityCodec:DecodeCharacter(pbs)
print(pbs)
pbs:Mark()
end
DefaultEncoder = Inherits({})
function DefaultEncoder:Init(codecs)
self.html_codec = HTMLEntityCodec:create()
end
function DefaultEncoder:TestInput(input , strict)
print ("\n----------------8<----------------8<----------------\n")
print ("Input:\t" .. input)
-- default value
if strict == nil then strict = true end
-- nothing to do
if input == nil then return nil end
local working = input
local codecs_found = {}
local found_count = 0
local clean = false
while not clean do
clean = true
old = working
working = self.html_codec:Decode( working )
if old ~= working then
print ("Warning:\tINTRUSION DETECTED")
end
end
print ("Output:\t".. working)
return working
end
local default_encoder = DefaultEncoder:create()
default_encoder:Init()
default_encoder:TestInput("%25", true)
----------8<-----------8<--------------8<----------------
END OF FILE
Console Output:
tzury#1005:~/devel/lua$ lua problem.lua
----------------8<----------------8<----------------
Input: %25
nil
lua: problem.lua:70: attempt to index local 'pbs' (a nil value)
stack traceback:
problem.lua:70: in function 'DecodeCharacter'
problem.lua:54: in function 'Decode'
problem.lua:96: in function 'TestInput'
problem.lua:109: in main chunk
[C]: ?
In your code, the crash happens on this line:
local char = self.DecodeCharacter(pbs)
The problem is that you are calling DecodeCharacter with incorrect number of arguments.
Solution: call it like this (notice the colon):
local char = self:DecodeCharacter(pbs)
Explanation:
When you define functions in Lua using the colon (:), you are using a syntax sugar which hides an implicit first argument named self. Definitions like:
function HTMLEntityCodec:DecodeCharacter(pbs) ... end
Are actually 'translated' to this:
HTMLEntityCodec.DecodeCharacter = function (self, pbs) ... end
When you call the function, you either need to pass the self argument yourself, or use the colon call to supply it automatically. In your code (self.DecodeCharacter(pbs)), you are passing pbs which ends up as self in HTMLEntityCodec.DecodeCharacter, and pbs ends up being nil. Both following calls are equivalent and should solve the issue:
local char = self.DecodeCharacter(self, pbs)
local char = self:DecodeCharacter(pbs)
I have implemented OOP in my lua environment but it doesnt seem to be working.
I think it has something to do with how i am handling the __index and my improper use of require and module but I'm not 100% sure.
Here is the code:
Class = function( prototype )
local derived = {}
local derivedMT = {
--When indexing into a derived class, check the base class as well
__index = prototype,
--When invoking a class, return an instance
__call = function( proto, ... )
local instance = {}
local instanceMT = {
--When indexing into an instance, check the class hierarchy as well.
__index = derived,
--Calling instances is a no-no!
__call = function()
print( "WARNING! Attempt to invoke an instance of a class!" )
print( debug.traceback() )
return instance
end,
}
setmetatable( instance, instanceMT )
if ( instance.__constructor ) then
instance:__constructor( ... )
end
return instance
end,
}
setmetatable( derived, derivedMT )
return derived
end
And here is how I use it, the nil reference is a call to a base class function, that is the error/problem im having is it seems like the base class isn't being referenced.
require "Core.Camera.FreeCamera"
local T = Core.Camera.FreeCamera.FreeCamera(0,0,-35)
c = T:getObjectType() -- nil reference
print(c .." --Type" )
and here is Camera.lua the base class
local _G = _G
module(...)
local M = _G.Class()
Camera = M
function M:__constructor(x,y,z) --This never gets called.
--self.Active = false
--self.x = x
--self.y = y
--self.z = z
--self.ID = EngineManager:getCamera()
print("InCameraInstance_-_-_-_-_-__-_--_-__-_-_-_--_-_-_-_-_--_-_-_--_--__-_---_--_---__-")
end
function M:getObjectType()
return "camera"
end
And Finally Free Camera which attempts to inherit Camera.
local require = require
local _G = _G
module(...)
require "Core.Camera.Camera"
local M = _G.Class( _G.Core.Camera.Camera ) --Gross, lame might be the culprit
FreeCamera = M
function M:__constructor(x,y,z) ---WHOOPS, this does get called... the other one doesnt
self.Active = false
self.x = x
self.y = y
self.z = z
self.ID = _G.EngineManager:getCamera()
--_G.print("got Id of:" .. self.ID)
self:setCameraPosition(x, y, z, self.ID)
_G.print("<<<Camera in lua>>>")
end
I'm running out of ideas. any help would be appreciated.
Instead of:
local M = _G.Class( _G.Core.Camera.Camera )
you need to have:
local M = _G.Class( _G.Core.Camera.Camera.Camera )
First Camera is the directory name, second is the module name, third is the class name.
Edit: You can clean it up a bit like this:
local CameraModule = require "Core.Camera.Camera"
local M = _G.Class( CameraModule.Camera )