Omnimaga
Calculator Community => TI Calculators => Lua => Topic started by: pianoman on July 29, 2011, 12:03:10 pm
-
I tried reading the thing on inspired-lua.org, but google translate sucks, so I couldn't understand much.
Basically, what I'm asking boils down to three things: what are classes, how do you use them, and is there anything special you can do with them?
Thanks!
-
Well, I'll try my best to explain them.
Imagine you have a game were you can have many different cars. All the cars have different things like engine power, but still share much stuff. This is were classes come in.
With classes you can make a basic structure of an object, and create new objects based on the first one. Nspire Lua has the class() function that saves us lots of work.
Example:
car = class()
function car: init(power, type, lights, etc)
self.power = power
self.type = type
self.lights = lights*2
self.options = etc
end
function car: drive(speed)
return self.power * speed -- this doesn't make much sense, but its just an example
end
Now, once we made our basic car class, we can define cars using this class:
volvo = car(10, "2x2", 4, {air-conditioning = True})
jeep = car(60, "4x4", 12, {air-conditioning = False, trailer-hook = True})
jeep:drive(10) -- returns 600
volvo:drive(20) -- returns 200
if jeep.options.trailer-hook then
print("The jeep can have a trailer")
else
print("No trailer for you :(")
end
This is just a basic example, and it written here without testing, so it can have some bugs.
-
Oh, I think I get it. Thanks!
-
Sorry, I'm still just a bit confused.
Let's say you created a class for a button. How would you initialize it so that you could actually draw it and do stuff with it?
Or let's say that you want to be able to create something on a keypress. How could you set it up so that, theoretically, you could continue generating objects infinitely?
I kinda tried to read the inspired-lua.org explanation, but Google Translate still sucks :P
Thank you very much!
-
Well, it really depends how you want to do it :)
First create the class and its init script. The init script for a button would set for example it label and size. Then you need to add an paint function to it, were you draw it.
Also, you should keep a table with references to all the buttons, so that you can link event to it.
Something like this:
--The table we keep all references to created buttons in
ButtonTable = {}
--Create the class
button = class()
--Create and init the button
function button:init(label, x, y, action)
self.label = label
self.x = x
self.y = y
self.action = action
self.labelWidth = 0
self.width = 0
self.height = 20
table.insert(ButtonTable, self)
end
--Draw the button
function button:paint(gc)
self.labelWidth = gc:getStringWidth(self.label)
self.width = self.labelWidth + 4
gc:setColorRGB(0,0,0)
gc:setFont("serif", "b", 12)
gc:drawRect(self.x, self.y, self.width, self.height)
gc:drawString(self.label, self.x+1, self.y+2, "top")
end
Well, but now you will wonder how to make it clickable and all.
Look at this full code:
--The table we keep all references to created buttons in
ButtonTable = {}
--Create the class
button = class()
--Create and init the button
function button:init(label, x, y, action)
self.label = label
self.x = x
self.y = y
self.action = action
self.labelWidth = 0
self.width = 0
self.height = 20
table.insert(ButtonTable, self)
end
--Draw the button
function button:paint(gc)
self.labelWidth = gc:getStringWidth(self.label)
self.width = self.labelWidth + 4
gc:setColorRGB(0,0,0)
gc:setFont("serif", "b", 12)
gc:drawRect(self.x, self.y, self.width, self.height)
gc:drawString(self.label, self.x+1, self.y+2, "top")
end
--What happens if you click the button
function button:click()
self.action()
end
--Check if clicked, and if clicked call its click method
function button:checkClick(x, y)
if y >= self.y and y <= self.y + self.height and x >= self.x and x <= self.x + self.width then
self:click()
end
end
--Check ButtonTable, and draw all the button in it
function drawButtons(gc)
for _, selectedButton in pairs(ButtonTable) do
selectedButton:paint(gc)
end
end
----------------------
--The on.create even. Here we create a sample button, and make that it will call testFunction when clicked
function on.create()
button1 = button("Test!", 100, 50, testFunction)
end
--TestFunction
function testFunction()
bclicked = true
platform.window:invalidate()
end
--The paint event
function on.paint(gc)
if bclicked then
gc:drawString("The button was clicked", 10, 10, "top")
end
drawButtons(gc)
end
--Link the click event to the buttons
function on.mouseDown(x, y)
for _, selectedButton in pairs(ButtonTable) do
selectedButton:checkClick(x, y)
end
end
This should explain most of it :)
Note that I didn't try this, so there might be some errors.
I strongly recommend you too look at the source of Adriweb's contest entry here: https://github.com/adriweb/Nspire-BreakOut .
Its a very good example of what you want to do, and should be easy to understand :)
EDIT:
Ok, tested it and fixed some bugs :) (Thanks Adriweb!)
-
I actually understood you :)
Thank you once again, jim and adriweb! :D
-
I'm glad I could be of help :)
-
Jim, we really have to translate this tutorial for inspired-lua :D
-
Adriweb was planning to do it when he had some time.
I could do it, but I don't have much time either :p
-
Sorry to necro-post, but cant you do this instead of using classes?
car = {car1 = {TopSpeed=50,Weight=10},car2 = {TopSpeed=60,Weight=11}...}
function PrintTopSpeed
graydraw.print(car.car1.TopSpeed)
end
-
euh, why would you do that? you have the ease of use to play with classes..
they're really easy to handle, what's the reason you want to do it this way?
-
Sorry to necro-post, but cant you do this instead of using classes?
car = {car1 = {TopSpeed=50,Weight=10},car2 = {TopSpeed=60,Weight=11}...}
function PrintTopSpeed
graydraw.print(car.car1.TopSpeed)
end
You can, but for certain stuff classes is much better.
It allows you to do very nice stuff which are not possible (like, each car has its own subroutines).
-
How do you do this with LuaForWindows? (I dont think they have a class function)
-
No, TI added the class() function.
However, its very easy to add that function on the pc since its a simple function :)
-
i had some questions about that lua for windows
can you create a full program with it, with windows (real ones, not the OS) and stuff?
-
Here's the source code of the class() function, that TI uses :
(not tested)
-- Class definition system
class = function(prototype)
local derived = {}
local derivedMT = {
__index = prototype,
__call = function(proto, ...)
local instance = {}
local instanceMT = {
__index = derived,
__call = function()
return nil, "attempt to invoke an instance of a class"
end,
}
setmetatable(instance, instanceMT)
if instance.init then
instance:init(...)
end
return instance
end,
}
setmetatable(derived, derivedMT)
return derived
end
Paste that and use blablabla=class() now :)
-
You can, but it works in a different way then the calculator way.
1. Its not event based (but you can make it like that)
2. It has no gc like we now on the calculator
3. Standard is only console, but you can add gui support by installing modules (or rocks).
Edit, thanks Adriweb :)
-
well yeah, i found this one: http://www.tecgraf.puc-rio.br/iup/
i'll study it..
and how can you make it event-based?
i know some visual basic, will that help?
-
You just make a loop were you call certain functions when certain stuff are true :)
Visual basic has nothing to do with Lua :P
-
Here's the source code of the class() function, that TI uses :
(not tested)
-- Class definition system
class = function(prototype)
local derived = {}
local derivedMT = {
__index = prototype,
__call = function(proto, ...)
local instance = {}
local instanceMT = {
__index = derived,
__call = function()
return nil, "attempt to invoke an instance of a class"
end,
}
setmetatable(instance, instanceMT)
if instance.init then
instance:init(...)
end
return instance
end,
}
setmetatable(derived, derivedMT)
return derived
end
Paste that and use blablabla=class() now :)
So this should work in luaFX also?
-
Yes, it will :)
-
OK, so now my question is, what is so special about classes and how can I take advantage of them?
And thanks for answering all my stupid questions jimbauwens :)
-
https://github.com/adriweb/Nspire-BreakOut/blob/master/BreakOut.lua (https://github.com/adriweb/Nspire-BreakOut/blob/master/BreakOut.lua)
take a look at this code (I made it so it can be helpful for beginners and people who want to learn class-oriented lua programming on the Nspire) and try to understand a way I could have had as many balls, blocks etc. as I wished without using classses and without having to write everything for each object.
Have fun :D
(btw, it's almost impossible)
That's what classes are for : creating once and for all, a "definition" of objects, and creating as many objects as you want of that class, so they will inherit the class properties.
Google "object oriented programming" and you'll see in detail what I mean.
-
The principle of classes / objects is simple : you can make copies of it, you can duplicate much much time and reach a certain amount of variables that you can't manage without (or with arrays but ... well you get it).
An object represents a bunch of preperties and a bunch of methods ALL related to this "kind" of object.
That way you won't have troubles to find other function names for this, this or that. Here is an example : "vector1_toString", "vector2_toString" etc... this is bad and painful, just define it once and call the object "vector" and the method name "toString", then, make bunch of that object.
This is a general approach. Now, I'm giving you a _real_ example : Imagine a bunch of aliens sprites and a spaceship (space invaders thus). How are you going to store each aliens positions ?
You can make two arrays, one for x, one for y. Ok. But then you have to manage somthing else : the spaceship position. Another varname x and another y. You reached 2 arrays and 2 vars.
Now let's see with classes : An array of "SpaceShipSprite" objects (aliens), and another "SpaceShipSprite" object for the space ship.
Each position is object.x and object.y (for example) and you only have to manage 1 array and 1 object.
You see now ?
Secondly, classes makes your code looking clever, sperated in multiple files, each file is related for one object and co..
-
The principle of classes / objects is simple : you can make copies of it, you can duplicate much much time and reach a certain amount of variables that you can't manage without (or with arrays but ... well you get it).
An object represents a bunch of preperties and a bunch of methods ALL related to this "kind" of object.
That way you won't have troubles to find other function names for this, this or that. Here is an example : "vector1_toString", "vector2_toString" etc... this is bad and painful, just define it once and call the object "vector" and the method name "toString", then, make bunch of that object.
This is a general approach. Now, I'm giving you a _real_ example : Imagine a bunch of aliens sprites and a spaceship (space invaders thus). How are you going to store each aliens positions ?
You can make two arrays, one for x, one for y. Ok. But then you have to manage somthing else : the spaceship position. Another varname x and another y. You reached 2 arrays and 2 vars.
Now let's see with classes : An array of "SpaceShipSprite" objects (aliens), and another "SpaceShipSprite" object for the space ship.
Each position is object.x and object.y (for example) and you only have to manage 1 array and 1 object.
You see now ?
Secondly, classes makes your code looking clever, sperated in multiple files, each file is related for one object and co..
Oh, wow, I've been wondering how to do this for a while! Now I understand what classes are for! THX!!!! :D
-
Secondly, classes makes your code looking clever, sperated in multiple files, each file is related for one object and co..
how can you do this? i mean, writing every method/class in a seperate file would be sooo useful Ö
-
Secondly, classes makes your code looking clever, sperated in multiple files, each file is related for one object and co..
how can you do this? i mean, writing every method/class in a seperate file would be sooo useful Ö
For a while here (like 6 months now :D) :
http://levak.free.fr/ftp/nspire/Make3D/
-
Or check EEPro.
Also Levak, I was before you. /me runs
-
Or check EEPro.
Also Levak, I was before you. /me runs
Never said I was first Ö
Basicly, it's Makefile based (or bash like me), you have to concatenate each files in a single Lua file (or xml for the Library version of Make3D)
-
Secondly, classes makes your code looking clever, sperated in multiple files, each file is related for one object and co..
how can you do this? i mean, writing every method/class in a seperate file would be sooo useful Ö
Example for EEPro (https://github.com/adriweb/EEPro-for-Nspire), indeed :
(http://i.imgur.com/Gos0Q.jpg)
-
that's indeed a lot of files O.o well, i saw the build file from eepro, but i didn't really get it, i'll check it again :)