I’m working on my next app, and I’m using a custom menu with my own menu, where there are 4 circles around a central circle and you drag one of the 4 circles to the center and release to trigger the action specified in the init section of the menu class. It is similar to the button class seen in the examples, but works with a deferent ui concept. The question I’m getting to is what would i set the action to in ~~~ menu:init ~~~ for a function located within menu? And is there a specific way to call it (in the button class i just use self.action() )
@Mr_Ninja - assuming the function you want to call is named A, and the menu instance is m, then you simply write m:A()
--# Main
-- Math circles
-- Use this function to perform your initial setup
function setup()
menu = Menu()
supportedOrientations (LANDSCAPE_ANY)
displayMode (FULLSCREEN)
reinit = true
end
-- This function gets called once every frame
function draw()
if reinit == true then
menu:init()
end
reinit = false
menu:draw()
end
function touched (touch)
plus:touched (touch)
minus:touched (touch)
division:touched (touch)
multiplication:touched (touch)
end
--# Menu
Menu = class()
function Menu:init()
plus = Button(true, "+" , 125, HEIGHT/2, HEIGHT/2 + 200, WIDTH/2, Menu:Game())
minus = Button(true, "-", 125, HEIGHT/2, HEIGHT/2 - 200, WIDTH/2)
division = Button(false, "/", 125, WIDTH/2, HEIGHT/2, WIDTH/2 - 200)
multiplication = Button(false, "x", 125, WIDTH/2, HEIGHT/2, WIDTH/2 +200)
gameadd = GameAdd()
end
function Menu:Game()
print ("received #yay")
background(0, 233, 255, 255)
text ("hi", WIDTH-20, HEIGHT-20)
end
function Menu:draw()
background(232, 12, 7, 255)
fill(0, 204, 255, 255)
ellipse (WIDTH/2, HEIGHT/2, 125)
fill(0, 0, 0, 255)
font("Copperplate-Light")
fontSize (30)
text("START", WIDTH/2, HEIGHT/2)
fill(62, 255, 0, 255)
fontSize(75)
text ("Math Circles", WIDTH/2, HEIGHT -50)
plus:draw()
plus.setpos = vec2 (WIDTH/2, HEIGHT/2 + 200)
minus:draw()
minus.setpos = vec2 (WIDTH/2, HEIGHT/2 -200)
division:draw()
division.setpos = vec2 (WIDTH/2 -200, HEIGHT/2)
multiplication:draw()
multiplication.setpos = vec2 (WIDTH/2 + 200, HEIGHT/2 )
end
function Menu:touched(touch)
-- Codea does not automatically call this method
end
--# Button
Button = class()
function Button:init(vertical, symbol, radius, trigger, defaulty, defaultx, action)
self.vertical = vertical
self.symbol = symbol
self.size = radius
self.trigger = trigger
self.setpos = vec2 (defaultx, defaulty)
self.position = vec2 (defaultx, defaulty)
self.action = action
end
function Button:draw()
self.touchpos = vec2 (CurrentTouch.x, CurrentTouch.y)
self.touchdist = self.touchpos:dist(self.position)
fill(50, 222, 10, 255)
ellipse (self.position.x, self.position.y, self.size)
fill(0, 0, 0, 255)
font("Copperplate-Light")
fontSize (50)
text (self.symbol, self.position.x, self.position.y)
if self.touch == true then
if self.vertical == true then
if self.touchdist < self.size/1.5 then
if self.trigger > self.setpos.y then
self.position.y =math.max (CurrentTouch.y, self.setpos.y)
self.position.y =math.min(self.trigger, self.position.y)
else
self.position.y =math.min (CurrentTouch.y, self.setpos.y)
self.position.y= math.max (self.trigger, self.position.y)
end
end
else
if self.touchdist < self.size/1.5 then
if self.trigger > self.setpos.x then
self.position.x =math.max ( CurrentTouch.x, self.setpos.x)
self.position.x = math.min(self.trigger, self.position.x)
else
self.position.x = math.min (CurrentTouch.x, self.setpos.x)
self.position.x = math.max(self.trigger, self.position.x)
end
end
end
end
if self.touch == false then
if self.position.y == self.trigger then
self.action()
else
self.position = self.setpos
end
end
end
function Button:touched(touch)
if touch.state == BEGAN then
self.touch = true
elseif touch.state == ENDED then
self.touch = false
end
end
--# GameAdd
GameAdd = class()
function GameAdd:init(x)
-- you can accept and set parameters here
self.x = x
end
function GameAdd:draw()
background(255, 158, 0, 255)
end
function GameAdd:touched(touch)
-- Codea does not automatically call this method
end
Here’s the code. Keep getting the error “self.action == nil”. I’m sure it’s going to be some stupid error on my part, but I’ve been looking through the code for 2 days and cant spot it.
Mr_Ninja - a tricky one.
First, when providing a callback function, don’t include brackets (they tell Codea to run the function straight away). If you want to include brackets, then you have to wrap the function in another function as shown below.
Second, you can’t include the colon in the callback function like that. Use a full stop, which I think works for you. So instead of Menu:game(), write either of these
function() Menu.Game() end
Menu.Game
…and don’t forget to include them for all four arithmetic signs!
PS if you really need to use a colon in the callback, (ie you are using a specific instance of Menu and need to access it’s self variables) there is a way, but I’ve forgotten it. Someone here will tell you how, if you need it.
@Mr_Ninja - I would recommend replacing this:
function touched (touch)
plus:touched (touch)
minus:touched (touch)
division:touched (touch)
multiplication:touched (touch)
end
with this:
function touched (touch)
menu:touched (touch)
end
and then replacing this:
function Menu:touched(touch)
-- Codea does not automatically call this method
end
with this:
function Menu:touched(touch)
plus:touched (touch)
minus:touched (touch)
division:touched (touch)
multiplication:touched (touch)
end
you might also want to look into making those buttons local to the class, and even putting them into a table, so you can easily add more buttons
Thanks again Ignatz and Jakattack
@Ignatz - if you need to access a certain instance can’t you just use:
Menu.game(instance,...)
or
instance:game(...)
@Coder You can’t pass the instance into a callback unless you do it like this:
tween(..., function()
instance:callback(...)
or type.callback(instance, ...)
end)
(Pseudo-code)
@JakAttack, how would I make the buttons local? I add local before i initialize every button, but then I get an error (button name here) = nil
@Mr_Ninja, I meant local to the class, not local to the function.
what you did is local to the function, so when you try to access them outside that function you get an error like the one you said.
local to the class is using self
like so:
function Menu:init()
self.plus = Button(true, "+" , 125, HEIGHT/2, HEIGHT/2 + 200, WIDTH/2, Menu:Game())
self.minus = Button(true, "-", 125, HEIGHT/2, HEIGHT/2 - 200, WIDTH/2)
self.division = Button(false, "/", 125, WIDTH/2, HEIGHT/2, WIDTH/2 - 200)
self.multiplication = Button(false, "x", 125, WIDTH/2, HEIGHT/2, WIDTH/2 +200)
self.gameadd = GameAdd()
end
if you also want to use a table like I suggested, try this:
function Menu:init()
self.buttons = {
Button(true, "+" , 125, HEIGHT/2, HEIGHT/2 + 200, WIDTH/2, Menu:Game()),
Button(true, "-", 125, HEIGHT/2, HEIGHT/2 - 200, WIDTH/2),
Button(false, "/", 125, WIDTH/2, HEIGHT/2, WIDTH/2 - 200),
Button(false, "x", 125, WIDTH/2, HEIGHT/2, WIDTH/2 +200),
}
self.gameadd = GameAdd()
end
then in draw:
for bi, button in ipairs(self.buttons) do
button:draw()
end
then in touched:
for bi, button in ipairs(self.buttons) do
button:touched(touch)
end
Hope this helps!
Thanks @JakAttack, that clears up a lot between local and self, and I will use the table for the buttons. Thanks!
No problem!
In another class, I am having an issue involving variables, whenever i call a self variable that had previously been initialized i get the error “attempt to call local self, a nil value”
EDIT: it seems to work if i use GameAdd.variable for setting and calling the variable.
(GameAdd is the class name)
DOUBLE EDIT: it seems for one of my instances i was using “.” Not “:” and that was my problem