91. Let’s play pool (2)
In this post, I want to get some pool balls bouncing around, for my first version of this project.
http://instagram.com/p/bqCZ8HhHWi/
Physics of pool
Not being a physicist, nor loving complex formulae, I am going to start by using the built in physics engine to manage all the bouncing around, collisions and friction.
I’ll also start with a top down view of a table with no pockets, using the full screen. That’s about as simple as I can make it.
Table edges
First, I’ll create the sides of the table, around the edge of the screen, with the code below. I’ve put this code in its own function, just to keep things neat. Note how the function name has P1 in front, so it is part of the P1 table, for the first version, which I will keep in a tab called P1.
function P1.CreateEdges() sides={} sides[1]=physics.body(EDGE,vec2(0,0),vec2(WIDTH,0)) sides[2]=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) sides[3]=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) sides[4]=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) for i=1,4 do sides[i].restitution=.8 end end
NB the “restitution” above is simply how bouncy the sides will be – in this case, pretty bouncy.
Drawing
I’ll show the draw function next. It assumes we have the details of the balls in a table called balls. It loops through all the balls, translating (moving the drawing centre to the x,y position of the ball), rotating the ball, and then drawing it.
function P1.draw() background(111, 181, 143, 255) for i,p in pairs(balls) do pushMatrix() translate(p.body.x,p.body.y) rotate(-p.body.angle) sprite(p.img,0,0) popMatrix() end end
The balls table has a property called body for each item, which has an x, y and angle property. You may guess this is a physics body, and you would be right. Codea is going to tell us what all these things are, and manage them as our objects run around and collide with each other.
I’ll show you the whole balls table below, but first I wanted to explain the need for translate and rotate. We need to rotate the balls because they will have numbers on top, and we want to show them spinning. And if you are going to rotate a ball, you need to move the drawing centre to the middle of the ball first.
Imagine you are going to draw a rotated ball on a sheet of paper. Instead of trying to draw it at an angle, you turn the paper so you can draw the ball normally, then turn it back again. The angle in the code above is negative because you need to turn the paper the opposite way before drawing, then turn it back (try it and see!).
And if you are going to turn the paper, an easy way to do this accurately is to move the paper so the centre of the ball is right under our pencil, press our pencil down to hold the centre steady, then rotate the paper, draw the ball, and rotate the paper back again. This ensures we rotate the paper around the centre of the ball. The same happens with Codea. So when we rotate, we always translate (ie move the rotation point) first. If this isn’t clear, I have covered rotation and translation in detail in some earlier posts. But I always find a real life example helps me figure out what is happening.
The balls
There’s a lot of code below, but do not fear. It’s not too difficult.
function P1.CreateBalls() local d,f=40,14 --diameter of ball, font size of number physics.gravity(0,0) --turn off gravity pushStyle() fontSize(f) font('GillSans-Bold') --define colours of balls 1-8 --(balls 9-15 have the same colours, repeated) local ballCols={color(255,255,0),color(0,0,255),color(255,0,0),color(146, 21, 226, 255), color(223, 99, 37, 255),color(0,255,0),color(95, 70, 49, 255),color(0)} balls={} for i=0,15 do balls[i]={} --the details of each ball are in its own table --each ball has its own physics object local p=physics.body(CIRCLE,d/2) --start in a random x,y position p.x,p.y=math.random(1,600),math.random(1,600) --they all have the same speed and direction, for now p.linearVelocity=vec2(200,250) --damping makes them slow down p.linearDamping=0.2 p.angularDamping=.2 p.restitution=.8 --bounciness off the sides balls[i].body=p --add ball to table --now create the correct image for this ball local img=image(d,d) --create a blank image setContext(img) --draw on the image stroke(130, 125, 125, 255) --outline around ball strokeWidth(1) if i==0 then fill(255) ellipse(d/2,d/2,d) elseif i<=8 then fill(ballCols[i]) ellipse(d/2,d/2,d) else fill(227, 227, 221, 255) ellipse(d/2,d/2,d) fill(ballCols[i-8]) local a=math.rad(30) local x,y=d/2*math.cos(a)-1,d/2*math.sin(a)-1 rect(d/2-x,d/2-y,x*2,y*2) end if i>0 then strokeWidth(0) fill(255) ellipse(d/2,d/2,d/2) fill(0) text(i,d/2,d/2) end setContext() --all done, add image to table of balls balls[i].img=img end popStyle() end
I have commented the code, but essentially, I have created a table containing 16 balls (ball 0 being white), with approximately the correct colours and stripes (the first 8 have solid colours, and remaining 7 have stripes). Each ball also has its own physics object.
When this code runs, the balls will be created in random positions, and draw will start putting them on the screen. If you go back to the draw code above, you’ll see the x and y position of each ball is based on the position of its physics body. So all we need to do is draw our ball image on top of the current position of that physics body (rotating it if the physics body is rotated).
The most complex part of the code so far, is creating the ball colour patterns. The other code really isn’t very difficult, if you know a little about how to use the physics engine.
The code so far is here.
Next, I want to find a way to aim and make a shot, using the built in accelerometer.
Maybe it’ll be better if we can shoot with our fingers rather than the accelerometer. I’m waiting to see how you’ll do it cause I have no idea about it.
Wait and see, I think it’s pretty cool
he Ignaz why dont you use a game template you wrote anice tutorial about that 😉
I can tell you it works and it is very easy. you have to think about the different scenes/parts of the game before you start coding and then you program the different scenes one by one. I will upload my first codea game after I ve cleanup the code a bit I have to translate the code from dutch to english . I used dutch variable names. 🙂
I didn’t use a game template because I’m writing different versions of the same thing, rather than game levels.