# Playing with balls

This is the first project I have worked on in Codea. It’s a simple project that shows balls and stuff. :>

``````
--# Main
-- Ball Test 3 (complete)

function setup()

parameter.boolean("stat",true)  -- Makes a newly made ball move
parameter.boolean("pchange",true)   -- Set to false if you don't want to change the ball you want to move
parameter.boolean("psize",false)    -- Set to true if you want to change the size your ball
parameter.integer("pspeed",0,10,1)  -- The amount of force exerted on your ball is multiplied by this value + 1
parameter.integer("size",1,100,30)  -- Sets the size of a newly made ball or your ball
parameter.action("Stop Player Movement", function() -- Stops the movement of your ball
for k,v in pairs(b) do
if v.player then
v.linearVelocity = vec2(0,0)
end
end
end)
parameter.action("Stop all ball movement", function() -- Stops the movement of all balls
for k,v in pairs(b) do
v.linearVelocity = vec2(0,0)
end
end)

b = {}  -- Store all the bodies here

-- Walls
local floor = physics.body( EDGE, vec2(0, 0), vec2(WIDTH, 0))
floor.restitution = 1.1

local left = physics.body( EDGE, vec2(0, 0), vec2(0, HEIGHT))
left.restitution =  1.1

local right = physics.body( EDGE, vec2(WIDTH, 0), vec2(WIDTH, HEIGHT))
right.restitution = 1.1

local ceiling = physics.body( EDGE, vec2(0, HEIGHT), vec2(WIDTH, HEIGHT))
ceiling.restitution = 1.1

physics.gravity(0,0)    -- Tabletop physics
physics.continuous = true   -- Balls don't pass through walls if they get too fast

table.insert(b,floor)
table.insert(b,left)
table.insert(b,right)
table.insert(b,ceiling)
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(2)

for k,v in pairs(b) do  -- Draws the balls
drawBodies(v)
if v.player and psize then  -- Changes the size of your ball if psize
end
end

if explode then -- Shows the last contact / Nice effects
sprite("Space Art:Red Explosion", exp.x, exp.y, exps, exps) -- exps is the energy of the impact
end
end

function touched(touch)
t = vec2(touch.x, touch.y)
if touch.state == BEGAN then
makeCirc(t.x,t.y)
else
for k,v in pairs(b) do
if v.shapeType == CIRCLE and not pcheck(v) and v.player then
v:applyForce((t-v.position)*(pspeed+1)) -- Applies force
end
end
end
end
end

function collide(contact)
if contact.state == BEGAN then
exp = contact.position
exps = contact.normalImpulse
explode = true
tween.delay(0.1, function()
explode = false
end)
sound(DATA, "ZgNAFQBJQEBAQEBAAAAAAAAAAAC5ZIg+AABAf0BAQEBAQHJx")
end
end

function makeCirc(x,y)
local a = physics.body(CIRCLE,size)
a.x, a.y = x, y
a.restitution = 1
a.interpolate = true
a.player = false
if not stat then
a:applyForce(vec2(math.random(-1000,1000),math.random(-1000,1000)))
end
table.insert(b, a)
end

function drawBodies(obj)
pushStyle()
fill(255, 0, 0, 0)
stroke(25, 255, 0, 165)
if obj.shapeType == EDGE then
line(obj.points[1][1],obj.points[1][2],
obj.points[2][1],obj.points[2][2])
elseif obj.shapeType == CIRCLE and obj.player then
pushStyle()
noStroke()
fill(0, 255, 180, 255)
popStyle()
elseif obj.shapeType == CIRCLE then
end
popStyle()
end

function pcheck(obj)    -- Checks if a tap is inside a ball
for k,v in pairs(b) do
v.player = false
end
obj.player = true
return true
else
return false
end
end

``````

Please show ways to make it better.

Nice work for a first project

``````--instead of
if tx >= obj.x - obj.radius and tx <= obj.x + obj.radius
and ty >= obj.y - obj.radius and ty <= obj.y + obj.radius
and pchange == true then

--try this
--dist is the distance between two vectors (points)
``````

It’s actually the 3rd version of the project. The first project only has the creation of balls and the second one is just a fancier version of the first.

I don’t understand the code you just posted.
By the way, your ebook helped me a lot

Edit:
I understood it but it gives me an error.

Edit2:
Eureka! Apparently, it doesn’t work when you just put obj inside.

``````    if pchange and vec2(tx,ty):dist( vec2(obj.x, obj.y) )<=obj.radius then
``````

Just updated the code.

ah, yes, I overlooked that obj wasn’t a vec2

it’s worth looking at the other vector functions in Codea, they can be very helpful. If you make your position variables vec2’s, then it makes using those functions a little easier (and your code a little tidier)

``````--if your position is t [=vec2(x,y)], instead of tx,ty
--and both of those are vec2, then you have
if pchange and t:dist(obj.pos) )<=obj.radius then
``````

``````v:applyForce(vec2((tx-v.x)*(pspeed+1), (ty-v.y)*(pspeed+1)))
--can be written as
v:applyForce((t-v)*(pspeed+1))
``````

(PS thanks for the kind words about the ebook).

Actually

``````if tx >= obj.x - obj.radius and tx <= obj.x + obj.radius
and ty >= obj.y - obj.radius and ty <= obj.y + obj.radius
and pchange == true then
``````

and

``````if pchange and vec2(tx,ty):dist(obj)<=obj.radius then
``````

are not equivalent. (But the second is probably what you want anyway.)

Thanks @Ignatz, I looked at the touched function and noticed that I could shorten the if statements into one if statement. I also made tx and ty into a vec2 in order to shorten other parts of my code.

@LoopSpace I don’t understand why they are not equivalent, could you please explain why

They are not equivalent because my code assumes your objects are circular, whereas your original code worked for squares.

But I thought you probably wanted circles (and even if you have squares, it is close enough, since we have fat fingers that don’t touch accurately).

Thanks, I get it now. (Fat fingers :)))

I also noticed that instead of putting “== true”, you could just write the variable/function. It also works with “== false” by putting “not” before the variable/function.

``````if var == true then

-- Just write
if var then

if var == false then

-- Just write
if not var then
``````

That’s right.

A very good trick is using `or` to set defaults for variables, eg in a function like this

``````function ABC(a,b)
--if a is nil or not provided, use 10
a = a or 10
--if b is nil or not provided, use 0.15
b = b or 0.15
return a,b
end

--then
ABC() --> returns 10, 0.15
ABC(3) --> returns 3, 0.15
ABC(nil,2) --> returns 10, 2
``````

@Ignatz Thanks for the info
I also thank you very much for your ebooks, I started reading the lua ebook before I even knew about Codea and it helped me a ton.