Friday, August 17, 2012

Interlude 11 - Classes in Lua and Codea

   

Interlude 11.1 What is a Class?


In Object Oriented Programming (OOP) a class is a coding construct used to define and create an object. Our original training was in the days of Procedural Programming, so we have some sympathy for those grappling with classes and other OOP paradigms for the first time. One way to think of a class is that it is the blueprint for an object.
  
When you create a new object using a class it is called an instance of that class. A class normally consists of data and functions which are associated with the object, this concept is called encapsulation. The class functions (sometimes called methods) act on the data variables to modify the behaviour of the object or provide information about its state. The purist approach is that only an objects functions can modify its variables. 

There are many benefits to using classes (code reuse, maintainability, modularity, inheritance etc.) but for us, the best thing about them is the mapping of a physical object or concept to a virtual object in your code. This makes it easier to conceptualise, write and understand complicated applications.
   
To be balanced we should point out that there is a camp of OOP haters (this rant by Linus Torvalds against C++ is quite amusing), it can make your code larger than necessary and arguably harder to maintain. Like most things in life moderation is the key. Abstraction for its own sake is pointless.
     

Interlude 11.2 Classes in Lua

   
As the comic at the start of the Interlude suggests, there is no class type in Lua. If that is the case then why the hell are we doing a tutorial on classes? Well it is possible to emulate a class in Lua using tables and because they are so useful the good folk at Two Lives Left have done it for you and it is included in Codea implementation of Lua. If you are really interested in how this is done then you can read the description on the Codea Wiki.
  

Interlude 11.2 Classes in Codea

    
The usual tutorial examples for classes are cars, employee data or animals. Whilst not wishing to anger the coding gods, we thought we would do something a bit more relevant to our next tutorial in the series (our interpretation of the classic SpaceWar! game). For this game we want to have a reusable ship class. The first step is to think about what sort of attributes a ship has which are relevant for us to model. Let's start with its position, speed and screen representation.
   
As mentioned above, Codea comes with a built-in global function called logically enough - class(). You can declare a class just about anywhere (with the usual caveat that if it refers to another class or function then this must have been defined before it in the tab order), but it is usually best to use the "+" tab at the top right of the screen when you are in a project to create your class. Tapping the "+" will bring up a popover with the "Create New Class" button at the top. Tapping this button allows you to enter the name of your new class and when "Done" is then tapped, Codea will create a new tab with your class template code. By convention class names start with a capital and class instances start with a lower case letter. This helps with the readability of your code, as you can immediately tell if you are referring to the class or its instance.
    

Interlude 11.3 The Ship Class

    
OK let's give it a go. Create a new project called SpaceWar! then tap the "+" tab and create a new class called Ship. You should end up with something that looks like Figure 1.
  
Figure 1. Default Class Template in Codea.
   
Codea automatically adds three functions to your class which you will usually need. The init(x) function is often called a constructor in OOP terminology. Whenever you create an instance of a new class this function will be called to set it up. Notice the x? When you create a new class you can pass in parameters to be used in the initialisation. The line self.x = x is assigning the parameter that you pass in (x) to the class variable (self.x). You don't have to do this, in which case your function would look like Ship:init() and you would also delete the line self.x = x in the body of the function. 

The draw() function you would be familiar with from earlier tutorials. Within a class we use it to handle the drawing of your object (if required). As the embedded comment says, Codea won't automatically call this function, you need to explicitly call it from the draw() function in Main. We will show you how to do this shortly.
    
Similarly, the touched() function looks after how your object handles touches. As for draw(), Codea won't call the class touch function automatically, so you need to do it in the Main touch() function. We won't be using touch until later.
   
So we have a ship class but it isn't much use at the moment. To keep track of our ship we want to use screen co-ordinates (x,y), assign a speed and allocate an image to represent the ship. The following code will achieve these objectives. 
      
Ship = class()
   
function Ship:init(x, y)
    -- you can accept and set parameters here
    self.x = x
    self.y = y
    self.speed = 5
    self.image = readImage("Tyrian Remastered:Boss D")
end
    
function Ship:draw()
    -- Codea does not automatically call this method
    -- Draw the ship
   
    sprite(self.image, self.x, self.y)
   
end
   
function Ship:touched(touch)
    -- Codea does not automatically call this method
end
        
We want to initialise our ship located in the middle of the screen so in the setup() function of your Main class you would have:
    
myShip = Ship(WIDTH/2, HEIGHT/2)
  
And then to draw you ship, in the Main draw() function, after the line background(40, 40, 50) add the line:
   
myShip:draw()
  
It is as simple as that. In subsequent tutorials we will look at the concept of inheritance and ways of moving your ship (the earlier Move Ship code in Tutorial 8 illustrates one method).

No comments:

Post a Comment