To make this more interesting, I want to add more balls, and I’ll make them random sizes, colors etc. Then we’ll get them bouncing about, and extend our class(es).

I’ll get the Ball class to do this like so

```function Ball:init(x,y,d,c)
self.x=x or math.random(0,WIDTH)
self.y=y or math.random(0,HEIGHT)
self.diameter=d or math.random(50,200)
self.colr=c or color(math.random(0,255),math.random(0,255),math.random(0,255))
end```

This uses a neat Lua coding trick. When I say

`self.x = x or math.random(0,WIDTH)`

Then Codea will use any x value I provide, but if it’s nil, it will use the “or” option, a random value, instead. So I don’t have to specify any measurements at all, unless I want to.

Now I can create a whole lot of random balls like this in my main setup function.

```function setup()
b={}
for i=1,15 do
b[i]=Ball()
end
end```

And when I run my code, I get something like this

So if you aren’t used to classes, I hope you can see just how simple and clean the Main tab is becoming, as we move all the ball stuff into the Ball class.

Movement

So let’s make the balls move about, and bounce off each other and the walls. We’ll need some physics to help us, and I think the neatest way to do this is to put all of that in a class of its own, which I will call Physics.

So I want to add a line to Ball:init() like so

`self.p=Physics(CIRCLE,{self.diameter/2},self.x,self.y)`

which passes through the physics type, diameter, and x,y position, and returns a physics object called self.p, that will tell us where to draw our ball.

In Ball:draw() we’ll add these lines to replace the ellipse line

```pushMatrix()
local x,y,a=self.p:currentPosition()
translate(x,y)
rotate(a)
ellipse(0,0,self.diameter)
popMatrix()```

First, I’m going to write a function in Physics, called currentPosition, that will give me x,y and angle. Once I know those, then I rotate the screen, move (“translate”) to the x,y position, and draw my circle at that point. (I explained all this a couple of posts ago, if you need to refresh your memory).

So you can see that my Ball class didn’t need much code to handle physics. And it shouldn’t have to, because it should be just about the ball itself.

But I still have to write my physics class. Here it is

```Physics = class()

--type=CIRCLE
--data is a table. For circles it is one value, the radius
--(why a table for one point? I was thinking ahead, you'll see later)
--x,y is the initial position of the centre
--a is the initial angle
--g is the gravity value, 0=tabletop, 1=normal (things fall down)
--r is the restitution, ie springiness
--f is friction
--lv is linear velocity
--i is any info you want to store to identify this object, eg a name
function Physics:init(type,data,x,y,a,g,r,f,lv,i)
self.body=physics.body(CIRCLE,data[1])
self.body.x=x
self.body.y=y
self.body.angle=a or 0
if g then self.body.gravityScale=1 else self.body.gravityScale=0 end
self.body.restitution=r or 1
self.body.friction=f or 0.1
if lv==nil then lv=vec2(100+math.random(400),100+math.random(400)) end
self.body.linearVelocity=lv
self.body.info=i
end

function Physics:currentPosition()
return self.body.x, self.body.y,self.body.angle
end```

This is fairly straightforward. Once again, I’ve calculated some random values where nothing is provided by the user. The currentPosition function returns the current x,y and angle.

If you’re curious about how it looks when it runs, here it is.

I’m not going to share the full code just yet, because I want to show you one more thing first.

Suppose we now decide we’d like to add some rectangles. It’s surprisingly easy, because we are using classes. We will need a rectangle class, and we’ll need to get Physics to handle rectangles, and finally we’ll need to create some rectangles on the screen in Main.

Here is the Rectangle class, most of the code copied from Ball

```Rect = class()

function Rect:init(x,y,w,h,c)
self.x=x or math.random(0,WIDTH)
self.y=y or math.random(0,HEIGHT)
self.width=w or math.random(60,150)
self.height=h or math.random(30,100)
self.colr=c or color(math.random(0,255),math.random(0,255),math.random(0,255))
local data={}
table.insert(data,vec2(-self.width/2,-self.height/2))
table.insert(data,vec2(-self.width/2,self.height/2))
table.insert(data,vec2(self.width/2,self.height/2))
table.insert(data,vec2(self.width/2,-self.height/2))
self.p=Physics(POLYGON,data,self.x,self.y)
end

function Rect:draw()
pushStyle() -- store style settings
fill(self.colr) --set color
pushMatrix()
local x,y,a=self.p:currentPosition()
translate(x,y)
rotate(a)
rect(-self.width/2,-self.height/2,self.width,self.height)
popMatrix()
popStyle() -- put back style settings
end```

Note how we set width and height rather than diameter, and we pass through a set of four x,y points, or vectors, to Physics. These are the corner points, relative to the centre of the rectangle – so the lower left point has an x value of – 1/2 the width, and y is -1/2 the height, for example.(Now you can see why I used an array to pass the ball diameter, because I want to use the same Physics class for both).

In draw, the only difference is that I draw a rectangle. Note that because we’ve “transformed” the screen so that 0,0 is sitting right over where the centre of the rectangle is to go, our bottom left point is – 1/2 the width, and y is -1/2 the height.

And there is only one change to the physics class. We need to test whether we are getting a circle or rectangle (POLYGON, to Codea). If it is a rectangle, then the “unpack” function will put all our points into the physics object.

```if type==CIRCLE then
self.body=physics.body(CIRCLE,data[1])
elseif type==POLYGON then
self.body=physics.body(POLYGON,unpack(data))
end
```

Finally, our Main class needs to create and draw some rectangles. This is dead easy.

```function setup()
b={}
for i=1,5 do
b[i]=Ball()
end
r={}
for i=1,0 do
r[i]=Rect()
end
CreateWalls()
end

function draw()
background(195, 195, 201, 255)
for i=1,#b do
b[i]:draw()
end
for i=1,#r do
r[i]:draw()
end
end```

And this is how the whole thing looks….

And the code is here or here.

I suspect you will be surprised how little code there is, in the end.

I’m sorry if I’ve gone a bit fast above, because I am consciously trying to take things slowly. Let me know if the pace is wrong.

From → Programming

1. Wow! Thanks for creating these tutorials – I am new to Lua and Codea and this information is essential, clear and easy to understand – and just what I needed! The pace is good and I really hope you continue sharing your knowledge this way.
regards, J

Very useful. Thanks again.

I didn’t understand one thing
What does the ‘return’ thing in the physics class, function currentPosition mean?

• Functions in Codea can either just “do stuff” for you, or they can give you back information, using the return command.

So if you wrote a function to convert degrees to radians, it might look like this
return d*math.pi/180
end
And you would use it like this

In the example you quoted, the function returns several items
returns self.body.x, self.body.y,self.body.angle
so you would use it like this
current.x, current.y,current.angle=currentPosition()
ie providing one variable for each item being returned

There are lots of examples in my other posts, because most functions return values like this.

Thanks a lot!!

• That’s ok, hope you have lots of fun with Codea. It gets much easier once you understand the basics.

I wrote this code after seeing this tutorial

function setup()
b = {}
for i = 1,10 do
b[i] = Ball()
dx = 1
end
end

function draw()
background(255, 255, 255, 255)
for i = 1,#b do
pushStyle()
fill(b[i].colr)
ellipse(b[i].x, b[i].y, b[i].diameter)
popStyle()
b[1].x = b[1].x + b[2].x/5000
b[2].x = b[2].x – dx
end
end

Ball = class()

Ball = class()

function Ball:init(x)
self.y = y or math.random(0,HEIGHT)
self.x = x or math.random(0,WIDTH)
self.diameter = d or math.random(50,200)
self.colr = c or color(math.random(255), math.random(255), math.random(255), math.random(100,255))
end

And it even works perfectly but when I change the number of balls from 10 to 2 the speed of b2 decreases and when I increase the number of balls the speed of b2 increases.
Do you know why?

Sorry wrote Pasted Ball class() twice

• I can’t see an obvious reason. Keep playing around and I’m sure you’ll solve it.

function setup()
b = {}
for i = 1,10 do
b[i] = Ball()
dx = 1
end
end

function draw()
background(255, 255, 255, 255)
for i = 1,#b do
pushStyle()
fill(b[i].colr)
ellipse(b[i].x, b[i].y, b[i].diameter)
popStyle()
b[1].x = b[1].x + b[2].x/5000
b[2].x = b[2].x – dx
end
end

Ball = class()

function Ball:init(d, x, y, c)
self.x = x or math.random(0,WIDTH)
self.diameter = d or math.random(100,300)
self.y = y or math.random(0,HEIGHT)
self.colr = c or color(math.random(255), math.random(255), math.random(255), math.random(100,255))
end

This is the code

• Thanks so much for the tutorials. I am 13 and I have understood everything up to here, but then I just found then ‘self.’ Stuff quite hard to actually use when I have so many other things going on.
I’m sure that I will figure it out, it just needs practice.

Cheers for the tutorials

• Don’t worry. I am much older and have experience with several languages, and I didn’t understand self either!

Just keep working at it, and it will become clearer. Feeling stupid is quite normal when learning programming.

self.p=Physics(CIRCLE,{self.diameter},self.x,self.y) is self.p=Physics(CIRCLE,{self.diameter/2},self.x,self.y) its right in the code on pasteBin but not here in the explaination.

Amazing tutorials man, i’m loving em all btw!

for some reason when i do the very first section all i get is black and no circles btw i also put the function setup in the main with all the stuff ahead, and the Ball:init in the Ball class on a different tab

btw here is my code
BALL TAB

Ball = class()

function Ball:init(x,y,d,c)
— you can accept and set parameters here
self.x = x or math.random(0, WIDTH)
self.y = y or math.random(0, HEIGHT)
self.diameter = d or math.random(5, 100)
self.colr=c or color(255, 0, 0, 255)

end
MAIN TAB
function setup()

b = {}
for i=1,15 do
b[i]=Ball

end

end