# Bull Puckey

After a name change and a graphic overhaul, this is starting to turn into something fun.

Original version below…

Fiddling with the little touch example I wrote yesterday, I expanded it into a simple game. Flick the “cue puck” toward the others and try to knock them into a hole in the designated number of shots.

I’m going to rework a little to make the energy transfer more accurate, and add a few graphical touches, but it was fun to scribble this up in just a little code.

``````

--# Circle
Circle = class()

function Circle:init(n, x, y)
-- you can accept and set parameters here
self.n = n
self.x = x
self.y = y
self.lifted = false
self.dx = 0
self.dy = 0
self.sx = x
self.sy = y
self.color = color(122, 122, 122, 255)
end

function Circle:draw()
fill(self.color)
ellipse(self.x, self.y, 50)
fill(0, 0, 0, 255)
if self.n > 0 then
text(self.n, self.x, self.y)
end
end

function Circle:move()
if (self.x + self.dx > WIDTH) or (self.x + self.dx < 0) then
self.dx = self.dx * -1
end
if (self.y + self.dy > HEIGHT) or (self.y + self.dy < 0) then
self.dy = self.dy * -1
end
self.x = self.x + self.dx
self.y = self.y + self.dy

self.dx = self.dx - (self.dx / 10)
self.dy = self.dy - (self.dy / 10)
end

function Circle:bounce(c)
if self:collide(c) then

self.x = self.x - self.dx
self.y = self.y - self.dy
c.dx = c.dx + (self.dx * 0.9)
c.dy = c.dy + (self.dy * 0.9)
self.dx = self.dx / 10
self.dy = self.dy / 10
end
end

function Circle:collide(c)
if (math.abs(self.x - c.x) < 50) and
(math.abs(self.y - c.y) < 50) then
return true
end
return false
end

function Circle:speed()
return math.abs(self.dx) + math.abs(self.dy)
end

function Circle:touched(touch)
if touch.state == BEGAN then
if math.abs(touch.x - self.x) < 30 and
math.abs(touch.y - self.y) < 30 then
self.lifted = true
self.sx = self.x
self.sy = self.y
return true
end
end
if touch.state == MOVING and self.lifted then
self.x = touch.x
self.y = touch.y
self.dx = touch.deltaX
self.dy = touch.deltaY
if math.abs(self.x - self.sx) > 150 or
math.abs(self.y - self.sy) > 150 then
self.lifted = false
end

end
if touch.state == ENDED and self.lifted then
self.lifted = false
end
return false
end

--# Main
-- PoolPuckey

displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT_ANY)

function setup()
pucks = {}
holes = {}
c = color(246, 246, 246, 255)
for i = 1, 16 do pucks[i] = Circle(i-1, -111, 50) end
pucks[1].color = color(253, 253, 253, 255)
pucks[2].color = color(255, 236, 0, 255)
pucks[3].color = color(65, 73, 236, 255)
pucks[4].color = color(240, 47, 47, 255)
pucks[5].color = color(175, 35, 156, 255)
pucks[6].color = color(236, 91, 7, 255)
pucks[7].color = color(45, 193, 21, 255)
holes[1] = Circle(0,0,0)
holes[2] = Circle(0,WIDTH,0)
holes[3] = Circle(0,0,HEIGHT)
holes[4] = Circle(0,WIDTH,HEIGHT)
holes[5] = Circle(0,0,HEIGHT/2)
holes[6] = Circle(0,WIDTH,HEIGHT/2)
for i = 1,6 do holes[i].color = color(0, 0, 0, 255) end
round = 1
shotStarted = false
setUpRound()
font("Arial-BoldMT")
end

function setUpRound()
for i = 1, 16 do
pucks[i].x = -111
pucks[i].dx = 0
pucks[i].dy = 0
end
pucks[1].x = WIDTH / 2
pucks[1].y = 100
scratch = false
if round == 1 then
count = 1
shots = 2
pucks[2].x = 60
pucks[2].y = HEIGHT - 60
end
if round == 2 then
count = 2
shots = 3
pucks[2].x = 60
pucks[2].y = HEIGHT - 60
pucks[3].x = 60
pucks[3].y = HEIGHT / 2
end
if round == 3 then
count = 2
shots = 3
pucks[2].x = 60
pucks[2].y = HEIGHT - 60
pucks[3].x = WIDTH - 60
pucks[3].y = HEIGHT - 60
end
if round == 4 then
count = 2
shots = 3
pucks[2].x = 60
pucks[2].y = HEIGHT - 60
pucks[3].x = WIDTH - 60
pucks[3].y = 60
end
if round == 5 then
count = 3
shots = 3
pucks[2].x = 60
pucks[2].y = HEIGHT - 60
pucks[3].x = WIDTH - 60
pucks[3].y = 60
pucks[4].x = WIDTH - 60
pucks[4].y = HEIGHT - 60
end
end

function totalSpeed()
s = 0
for i, p in ipairs(pucks) do
s = s + math.abs(p.dx)
s = s + math.abs(p.dy)
end
return s
end

function draw()
background(42, 90, 35, 255)
stroke(5, 116, 238, 255)
strokeWidth(2)
fontSize(111)
fill(145, 145, 145, 76)
text("Pool Puckey", WIDTH / 2, HEIGHT / 2)
fontSize(48)
text("Round: " .. round, WIDTH / 2, 35)
if shots > 0 then
text("Shots Remaining: " .. shots, WIDTH / 2, HEIGHT - 35)
elseif totalSpeed() < 1 then
fontSize(96)
fill(190, 75, 75, 255)
if scratch then text("Scratch", WIDTH / 2, 800) end
text("Game Over", WIDTH / 2, 700)
fill(125, 210, 13, 105)
text("Try Again", WIDTH / 2, 150)
end
if shotStarted then
stroke(29, 130, 122, 119)
if math.abs(startX - pucks[1].x) > 75 or
math.abs(startY - pucks[1].y) > 75 then
stroke(216, 92, 79, 109)
end
noFill()
ellipse(startX, startY, 300)
end
fontSize(18)
stroke(187, 181, 181, 255)
for i, circle in ipairs(pucks) do
circle:move()
circle:draw()
for k, p in ipairs(pucks) do
if i ~= k then
if circle:collide(p) then circle:bounce(p) end
end
end
end
strokeWidth(4)
stroke(26, 46, 25, 255)
for i, hole in ipairs(holes) do
hole:draw()
for k, p in ipairs(pucks) do
if hole:collide(p) and p:speed() < 4 then
p.x = -111
p.dx = 0
if k > 1 then
count = count - 1
sound(SOUND_BLIT, 27470)
if count == 0 then
round = round + 1
setUpRound()
end
else
scratch = true
shots = -1
end
end
end
end
end

function touched(touch)
if shots > 0 then
if pucks[1]:touched(touch) and touch.state == BEGAN then
shotStarted = true
startX = pucks[1].x
startY = pucks[1].y
end
end
if shotStarted and touch.state == ENDED then
shots = shots - 1
shotStarted = false
end
if shots <= 0 and touch.y < 300 and touch.state == BEGAN then
round = 1
setUpRound()
end

end
``````

Nice! Yet a bit too difficult…

A couple of screen shots to show the game as it’s developing. I like this one. If you’re interested in beta testing, let me know. With some fine tuning, I think this could really work.

.@Mark that looks fantastic. Have you thought about using the “Small World:Grass Patch” and “Small World:Dirt Patch” overlays to add some texture to the grass and dirt? They might be ideal for your level designs.

It’s actually designed to be used on solid coloured circles, like you have (although a different shade of green). So you draw all the circles, then for each circle, use the grass patch overlay. This lets each circular patch blend into the adjacent patches.

You could vary the opacity and tint to get a colour that’s more in line with your characters, too.

Here’s a screenshot:

Interesting, @Simeon. I fooled around with different tints and kind of like it this way.

Looks good!

Wow - it’s a small change, but it really makes a big difference.

much, much better . Now it shows a 3d effect.

@Simeon, what’s the code look like that generated that screen? Did it get rendered back to front? I’m trying to figure out how the “circles” would be able to be placed so that things aren’t overwritten.

Updated images from latest. Got the z order sort going and took the opportunity for a big refactor of everything from graphics to collisions (I’m not using physics, because I’m just that stupid).

Anyway, pretty darn happy with how it’s coming together. I’m going to grab @Fred’s ABC Music player, and try to get some sound into this thing.

Trying again…

.@aciolino that screen is actually from Daniel Cook’s preview image on how to use his art assets. To render such a thing in Codea you would need to draw it back-to-front (as @Mark is now doing).

.@Mark that’s looking great. Glad you got the z-sort working.

Now with 100% more sheep, beavers, and owls.

Closing in on the App Store. Seemed like a good time for a little teaser.

You video says it is Private when I try to play it.

Sorry about that. Give it another try. I couldn’t get the mobile version of Youtube to let me change it and had to wait till I got to a PC.

Looks great. Is the music on the video generated with @Fred’s ABC music player? If so, how easy was it to implement? Also have you got an ETA for getting it in the App Store?

Sorry to be deceptive. The music in the video is just one of apple’s canned iMovie tunes. For the in-game music, I’m trying old folk tunes and tweaking instrument sounds toward what I hope approximates “funky banjo.”

I’m finishing up the menu, design of the last 9 (of 36 stages) and still have some intermission screens and music to do, but I’m hoping to have it all cleaned up and submitted by Mar 1.

Looks nice!

Apple has rejected BullPuckey, saying that BullPuckey is an inappropriate name.

Sheesh.

@Mark wow. I really can’t see how they reached that conclusion.

What other names are you considering?