Omnimaga

Calculator Community => TI Calculators => Lua => Topic started by: pianoman on July 29, 2011, 12:03:10 pm

Title: Lua Classes
Post 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!
Title: Re: Lua Classes
Post by: Jim Bauwens on July 29, 2011, 12:55:58 pm
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:
Code: [Select]
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:
Code: [Select]
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.
Title: Re: Lua Classes
Post by: pianoman on July 29, 2011, 12:59:42 pm
Oh, I think I get it. Thanks!
Title: Re: Lua Classes
Post by: pianoman on August 17, 2011, 12:18:00 pm
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!
Title: Re: Lua Classes
Post by: Jim Bauwens on August 17, 2011, 03:18:57 pm
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:
Code: [Select]
--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:
Code: [Select]
--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!)
Title: Re: Lua Classes
Post by: pianoman on August 17, 2011, 11:20:17 pm
I actually understood you :)
Thank you once again, jim and adriweb! :D
Title: Re: Lua Classes
Post by: Jim Bauwens on August 18, 2011, 05:33:07 am
I'm glad I could be of help :)
Title: Re: Lua Classes
Post by: Levak on August 18, 2011, 05:51:41 am
Jim, we really have to translate this tutorial for inspired-lua :D
Title: Re: Lua Classes
Post by: Jim Bauwens on August 18, 2011, 05:53:08 am
Adriweb was planning to do it when he had some time.
I could do it, but I don't have much time either :p
Title: Re: Lua Classes
Post by: flyingfisch on January 04, 2012, 02:21:16 pm
Sorry to necro-post, but cant you do this instead of using classes?

Code: [Select]
car = {car1 = {TopSpeed=50,Weight=10},car2 = {TopSpeed=60,Weight=11}...}

function PrintTopSpeed
graydraw.print(car.car1.TopSpeed)
end
Title: Re: Lua Classes
Post by: Nick on January 04, 2012, 02:24:18 pm
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?
Title: Re: Lua Classes
Post by: Jim Bauwens on January 04, 2012, 03:02:34 pm
Sorry to necro-post, but cant you do this instead of using classes?

Code: [Select]
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).
Title: Re: Lua Classes
Post by: flyingfisch on January 04, 2012, 03:36:11 pm
How do you do this with LuaForWindows? (I dont think they have a class function)
Title: Re: Lua Classes
Post by: Jim Bauwens on January 04, 2012, 03:41:22 pm
No, TI added the class() function.
However, its very easy to add that function on the pc since its a simple function :)
Title: Re: Lua Classes
Post by: Nick on January 04, 2012, 03:42:39 pm
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?
Title: Re: Lua Classes
Post by: Adriweb on January 04, 2012, 03:43:35 pm
Here's the source code of the class() function, that TI uses :


(not tested)
Code: [Select]
-- 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 :)
Title: Re: Lua Classes
Post by: Jim Bauwens on January 04, 2012, 03:44:52 pm
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 :)
Title: Re: Lua Classes
Post by: Nick on January 04, 2012, 03:49:52 pm
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?
Title: Re: Lua Classes
Post by: Jim Bauwens on January 04, 2012, 03:51:46 pm
You just make a loop were you call certain functions when certain stuff are true :)
Visual basic has nothing to do with Lua :P
Title: Re: Lua Classes
Post by: flyingfisch on January 04, 2012, 03:57:33 pm
Here's the source code of the class() function, that TI uses :


(not tested)
Code: [Select]
-- 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?
Title: Re: Lua Classes
Post by: Jim Bauwens on January 04, 2012, 03:57:57 pm
Yes, it will :)
Title: Re: Lua Classes
Post by: flyingfisch on January 05, 2012, 09:43:12 am
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 :)
Title: Re: Lua Classes
Post by: Adriweb on January 05, 2012, 10:08:57 am
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.
Title: Re: Lua Classes
Post by: Levak on January 05, 2012, 10:12:12 am
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..
Title: Re: Lua Classes
Post by: flyingfisch on January 05, 2012, 10:19:12 am
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
Title: Re: Lua Classes
Post by: Nick on January 05, 2012, 10:22:54 am
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 Ö
Title: Re: Lua Classes
Post by: Levak on January 05, 2012, 10:24:20 am
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/
Title: Re: Lua Classes
Post by: Jim Bauwens on January 05, 2012, 10:25:41 am
Or check EEPro.

Also Levak, I was before you. /me runs
Title: Re: Lua Classes
Post by: Levak on January 05, 2012, 10:29:46 am
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)
Title: Re: Lua Classes
Post by: Adriweb on January 05, 2012, 10:31:57 am
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)
Title: Re: Lua Classes
Post by: Nick on January 05, 2012, 10:43:17 am
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 :)