Experiment 1

So today let's start with Lua and see what is possible using Codea and it's various libraries. The project will end up with a little square "floating" in a body of "water", you should be able to flick around, and I want to work out how to get the viewport to follow the square...

What is Lua

Apart from being Portuguese for 'moon' Lua is also a lightweight and fairly extensible programming language that is primarily designed as a scripting language. What that means is that it reads rather well, so should make sense to the beginner, and doesn't come with lots of baggage or boilerplate code that you have to memorise. This lightweight nature does have drawbacks though, as you will find when trying to debug your application, but it is quick to set up, and in my opinion massively fun.

Making Friends With Codea

So far I have found that Codea does roughly what you expect it to, I will point out anywhere I have fallen down. So hit the "Add New Project" button and give it a title of your choosing. Your project will then be created and it will take you directly to the editor for it, which should look like this:

Imgur

There are four basic buttons on the editor. * The back button in the top left, this will take you back to the main menu, or if you have the reference pane open it will close that. * The close button in the bottom left, this will also take you back to the main menu. * The add button in the top right, this will add a new file to the project. Projects can be made up of as many files as you need, and each file can contain any code necessary. * The run button in the bottom right, this will compile and run your code.

There is also the tab bar, which will currently only show you the 'Main' file that has been created for you, until you add more of course. The 'Main' file is the entry point to the application and should be the root to everything that it does, though this is just a convention not an absolute but don't be difficult!

The Starter Code

In your newly created project you will have been given some sample code, and two really useful entries into the world of Lua, and specifically how Codea works with Lua. It should look like this:

-- WaterBob

-- Use this function to perform your initial setup
function setup()
    print("Hello World!")
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)

    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here
    
end

So you have two functions that will be the main structure to all of your apps. Setup is run at the very start of your applications life, so this is where you would initialise any state that would be used in the application. Draw is then run every few milliseconds and should be responsible for updating the logic as the application progresses and drawing out the graphics that make up your application to screen. The function print is internal and will simply print out whatever you feed it to the output panel that you can see on the left hand of the scren when Codea runs your application. If you run your application now you should get:

Codea Screen

There are three main areas to the running screen on Codea. You have the parameters box in the top left hand corner and this is where any defined parameters will appear (more on these at a later date). You then have the output in the bottom left, and this shows anything that goes through the print command, as well as any errors that occur during the running of your application. Finally you have the main application area on the right (currenty just a grey area) which is where your graphics will be drawn should they exist!

So let's get physics on the go! You first need to get hold of the PhysicsDebugDraw class that is bundled into Codea's examples using physics. You can either copy it from the gist or you can use Codea's ingenious 'Dependancies' function. If you click on the 'Add' button back on the code editor you will see that as well as being able to add your own files you can also pull in dependancies from other projects, even your own. This allows you to reuse code from other projects, even creating smaller projects that contribute to a bigger one. The PhysicsDebugDraw can be added as a dependancy by selecting the 'Physics Lab' project from the list.

If you also create a new file called Water (it doesn't matter if it is a class or a blank file as you are going to replace the content) and paste in the code from the gist. You should have a good read through this class, as it is going to represent a body of water that has buoyancy on any object that is in it. Essentially this will initialise with a body that represents the waters area:

function Water:init(body)
    -- you can accept and set parameters here
    self.body = body
    self.body.sensor = true
    self.body.type = STATIC
    self.bodies = {}
end

It then sets the body to be a sensor so that it doesn't stop other bodies passing through it (like water yes!), and then makes it STATIC so it doesn't fall under gravity. It also initialises a table (a table is like an array, or an object full of values) which will stores our bodies. It will then wait for an object to collide with it using the collide function and check whether the collision is BEGAN or ENDED i.e. has the object entered the water or has it left it. When it enters it runs the function self:add(body) which takes the body that has collided and adds it to the bodies table:

function Water:add(body)
    table.insert(self.bodies, body)
    body.linearDamping = 3
    body.angularDamping = 5
end

We use the table bodies to keep track of all of the objects that are in the water, we also add some linearDamping and angularDamping that slows the object down, as it was really in water! When the body leaves the water we will then call self:remove(body):

function Water:remove(body)
    for k, b in ipairs(self.bodies) do
        if b == body then
            table.remove(self.bodies, k)
            break
        end
    end
    body.linearDamping = 0
    body.angularDamping = 0
end

Which finds the body in the bodies table and then removes it, and resets the linearDamping and angularDamping back to their normal settings. The body is then free to return to normal physical conditions within the simulation. The final set is the draw function for Water which looks like this:

function Water:draw()
    -- Codea does not automatically call this method
    for k,body in ipairs(self.bodies) do
        body:applyForce(vec2(0,20))
    end
end

Which loops through all of the body items in the bodies table and uses the applyForce function (part of Codea's physics library). The applyForce accepts a vec2 type object which is basically a 'x' and 'y' coord pair which in this case represent the force that you want to act on the body. In this case we are not changing anything in the 'x' but are adding 20 to the 'y' which will push the object look (very crude water simulation indeed!).

Finally we then need to set up the Main file, which will have an instance of our Water class which you can take from the gist. With this there are a few functions that have been taken from the examples - createCircle, createBox, createGround and createRandPoly all create physical bodies (of different shapes). The setup and draw for the Main file:

local water
local box
 
function setup()
    print("alright let's do this!")
    debugDraw = PhysicsDebugDraw()
    
    createGround()
    box = createBox(WIDTH/2, 100, 30, 30)
    water = Water(createBox(WIDTH/2, 50, WIDTH, 100))
    camera = 0
end
 
-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)
 
    -- Do your drawing here
    pushMatrix() 
    
    camera = -box.x + WIDTH*0.5
    translate(camera, 0)
    
    water:draw()
    debugDraw:draw()
    
    popMatrix()
    
end

So first we define two local variables water, which will be our body of water, and box which will be the thing we are chucking into the water. The setup function then initialises the PhysicsDebugDraw class, which is quite complicated to get into today (but essentially draws the shapes on screen for us so we don't have to), creates our box using the createBox function, creates our water using our Water class which will be represented by another box. It also sets the camera to equal 0, as we will be moving the camera around to follow the box. The draw function will then use pushMatrix which tell the graphics processing to store all settings from this point, and then popMatrix which tells the graphics processing that you are finished with that session. Between those two lines we then set the camera to be at the same point as the box, though only in the 'x' plane' and translate the whole graphics buffer which simulates the idea of a camera following the box. We then call the draw functions for both the water class and the debugDraw class. It is worth pointing out that draw functions are only called by the system on the Main file, it is up to the coder to then call the draw function for any subsequent classes. If you run you should get this amazing thing:

Codea Floating

Be warned, there are bugs, and a poorly implemented touch thing that I am too ashamed to even document! We will review this later, together!

comments powered by Disqus