I am trying to use functions of another class in my main.lua. I wrote some code according to my research but it's not working properly. Can you help me out? Thanks.
fish.lua code:
function class()
local cls = {}
cls.__index = cls
return setmetatable(cls, {__call = function (c, ...)
instance = setmetatable({}, cls)
if cls.__init then
cls.__init(instance, ...)
end
return instance
end})
end
Fish= class()
function Fish:listen(event)
if phase =="began" then
print("hi")
end
end
function Fish:__init(image)
self.image=display.newImage(image,30,30)
self.image: addEventListener("touch",self.listen)
end
main.lua code:
require "fish"
originalImage="fish.small.red.png"
differentImage="fish.small.blue.png"
local fishImage=Fish(originalImage)
It displays the image but does not work(prints "hi" ) when it is touched.
A couple of problems:
Change function Fish:listen(event) to function Fish.listen(event)
and if phase =="began" then should be if event.phase =="began" then
Related
I am writing a new constructor and I have something like this:
function Map:new(path, world, debug)
local map = sti(path, { "box2d" })
return map
end
function Map:update(dt)
print('call this')
end
sti is some thirdparty library that constructs a class object.
What I am trying to do is make it so when I call:
map:update(dt)
it calls the functions I have declared. If not found, it calls the actual function that sti sets up on the object.
I've tried stuffing around with metatables but can't seem to get my functions to take priority over the third party library supplied functions....
Reading the source code for what I believe is the library you're using (Simple-Tiled-Implementation), I figured out it actually overrides your metatable with another one:
local function new(map, plugins, ox, oy)
local dir = ""
if type(map) == "table" then
map = setmetatable(map, Map) -- Here
else
-- Check for valid map type
local ext = map:sub(-4, -1)
assert(ext == ".lua", string.format(
"Invalid file type: %s. File must be of type: lua.",
ext
))
-- Get directory of map
dir = map:reverse():find("[/\\]") or ""
if dir ~= "" then
dir = map:sub(1, 1 + (#map - dir))
end
-- Load map
map = setmetatable(assert(love.filesystem.load(map))(), Map) -- Or here
end
map:init(dir, plugins, ox, oy)
return map
end
The function above is defined here
You'll need to pass a table argument as map instead of the path, there you can define update(), which will take precedence over the metatable provided by STI.
I believe you can copy the procedure STI does to load your map and provide it with a table containing the function you wish to define inside:
-- Check for valid map type
local ext = map:sub(-4, -1)
assert(ext == ".lua", string.format(
"Invalid file type: %s. File must be of type: lua.",
ext
))
-- Get directory of map
dir = map:reverse():find("[/\\]") or ""
if dir ~= "" then
dir = map:sub(1, 1 + (#map - dir))
end
-- Load map
local map = assert(love.filesystem.load(map))()
function map:update()
-- Do things
end
sti(map, { "box2d" })
unfortunately sti declares 'local dir' at the top of the function so copying the code did not work.
I found a solution how ever I have made myself some way to easily set a class as a proxy in lua:
-- forward a function call from oldSelf:fn(...) to newSelf:fn(...)
function utils.forwardFunc(fn, newSelf)
return function(oldSelf, ...)
local function __NULL__() end
return (fn or __NULL__)(newSelf, ...)
end
end
-- make a function fn(...) call newSelf:fn(...)
function utils.func(fn, newSelf)
return function(...)
local function __NULL__() end
return (fn or __NULL__)(newSelf, ...)
end
end
-- forward any undefined functions called on 'from' to 'to'
-- if 'to' is a function, it acts as a dynamic proxy, incase you are changing what class you are proxying to
-- on the fly. For example, a state machine proxies to the current state
function utils.proxyClass(from, to)
local mt = getmetatable(from)
setmetatable(from, {__index = function(_, func)
if mt and mt[func] then
return mt[func]
end
local forwardTo = to
if type(to) == 'function' then
forwardTo = to(from)
end
if type(forwardTo[func]) == 'function' then
return utils.forwardFunc(forwardTo[func], forwardTo)
else
return forwardTo[func]
end
end})
end
There is a variable called f, And this code is supposed to play random audio whenever it's clicked
local clickDetector = script.Parent.ClickDetector
f = math.random(1,3)
function onMouseClick()
script.Parent.f.TimePosition = 0
script.Parent.f.Playing = true
end
clickDetector.MouseClick:connect(onMouseClick)
How do I make it so it will thing it's not inside
assuming the parent exist, try
script.Parent[f]
In app designer I have two buttons one to declare the working folder:
function setSaveLocationButtonPushed(app, event)
app.path = uigetdir()
end
The other one to save an image
function saveButtonPushed(app, event)
pathSave = app.path;
[file, pathSave] = uiputfile([pathSave,'*.jpg']);
…
end
Why do I get in the save as type also the app.path? (as shown in image)
Your code [pathSave,'*.jpg'] concatenates the path and the filter and then passes the result as the only argument to the uiputfile function. This argument tells the function what file filter to use.
Instead of storing the chosen directory, make it change the current directory. The file selection UI always opens in the current directory.
function setSaveLocationButtonPushed(app, event)
p = uigetdir;
cd(p)
end
function saveButtonPushed(app, event)
[file, pathSave] = uiputfile('*.jpg');
…
end
If you don’t want to change the current directory for the whole application, you can change it just before calling the uiputfile function, and change it back afterward:
function saveButtonPushed(app, event)
p = cd(app.path);
[file, pathSave] = uiputfile('*.jpg');
cd(p);
…
end
I'm trying to create a class for my game and I got this error (shown in love2d): attempt to index upvalue 'World' (a boolean value)
This is my World file I made:
local World = {}
World.__index = World
function World:new(meter, gravity)
setmetatable({}, World)
-- Set physics parameters
love.physics.setMeter(meter)
self.world = love.physics.newWorld(0, gravity*meter, true)
-- Load background
self.background = love.graphics.newImage("imgs/background.png")
return self
end
function World:update(dt)
end
function World:draw()
love.graphics.draw(self.background)
end
function World:destroy()
-- Destroy the world
self.world:destroy()
end
And here I call the world:
local World = require("world")
function love.load()
-- Build the world
world = World:new(32, 9.81)
end
What is wrong? Anyway, what is the best way for make a class in Lua?
In the world.lua file, put a return World at the end:
.
.
.
function World:destroy()
-- Destroy the world
self.world:destroy()
end
-- Add line below
return World
Something like this:
##class(MyApp.MyClass).%HasProperty("SomeProperty").
I looked into doing something like this:
set classDefinition = ##class(%Dictionary.CompiledClass).%OpenId(%class.Name)
and then looping through the Properties, however, I need to be able to use any class, not just %class
For a simple OO approach, you can use the following API:
Set tPropExists = ##class(%Dictionary.CompiledProperty).IDKEYExists("SomeClass","SomeProperty")
This should have much less runtime cost than loading the class definition data and looping over its properties (and thus loading the data for those properties as well).
If you still want to create a %HasProperty() helper method for your application classes, you can use the following base method (assuming you are on Cache 2010.2 or higher - I believe the $this special variable and the $classname() function were added in 2010.2, but that may have been in 2010.1.):
ClassMethod %HasProperty(pPropName As %String = "") As %Boolean
{
Set tHasProp = 0
If (pPropName '= "") {
Set tHasProp = ##class(%Dictionary.CompiledProperty).IDKEYExists($classname($this),pPropName)
}
Quit tHasProp
}
You also might want to use a generator method (one of the really nice features in Cache objects) if run-time speed is important to you.
For example:
Method PropertyExists(Name) As %Boolean [ CodeMode = generator, ProcedureBlock = 1, ServerOnly = 1 ]
{
Set %code=0
S ClassDef=##class(%Dictionary.CompiledClass).%OpenId(%class)
i '$IsObject(ClassDef) $$$GENERATE(" Q 0") Q $$$OK
I '$IsObject(ClassDef.Properties) $$$GENERATE(" Q 0") Q $$$OK
S Key="" F S Key=ClassDef.Properties.Next(Key) Q:Key="" D
. S CompiledProperty=ClassDef.Properties.GetAt(Key)
. $$$GENERATE(" I Name="""_CompiledProperty.Name_""" Q 1" )
$$$GENERATE(" Q 0")
q $$$OK
}