Skip to content

Instantly share code, notes, and snippets.

@dermotbalson
Created November 9, 2013 08:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dermotbalson/7382993 to your computer and use it in GitHub Desktop.
Save dermotbalson/7382993 to your computer and use it in GitHub Desktop.
L game beta
--Project: L Game
--Version: Beta 1.0
--Comments:
--================ SETUP ===================
function setup()
--playing stages
NONE,MOVED_L,TOUCHED_DOT,MOVED_DOT=10,11,12,13
--setup the grid
size=400 --total size of grid
offset=vec2(WIDTH/2-size/2-50,HEIGHT/2-size/2+65) --position slightly left and above of centre
square=size/4 --size of each cell in the square
--make an image containing the board
board=image(size,size)
setContext(board)
background(137, 194, 208, 255)
pushStyle()
--draw grid
stroke(45, 125, 151, 50)
strokeWidth(2)
for i=0,4 do
line(square*i,1,square*i,square*4)
line(1,square*i,square*4,square*i)
end
pushStyle()
setContext()
StartGame()
end
--this runs each time the game restarts, it sets up the initial position
function StartGame()
--table holds touches, used for drawing L shape
touches={} for i=1,4 do touches[i]={} end
--tables to hold player data, pos = position of 4 squares of the L
player={}
player[1]={name="Blue",pos={vec2(2,1),vec2(2,2),vec2(2,3),vec2(3,1)},color=color(44, 155, 219, 255)}
player[2]={name="Red",pos={vec2(2,4),vec2(3,4),vec2(3,3),vec2(3,2)},color=color(209, 93, 113, 255)}
--and another table to hold a player's new move until it is submitted
playerN={pos={}}
--a table for the two dots
dot={pos={vec2(1,4),vec2(4,1)},color=color(84, 167, 84, 255)}
dot2={pos={}} --and one for the dot moved by the player (until it is submitted)
--control buttons
buttons={}
buttons.Restart={text="Restart",show=true,x=offset.x+square*4+90,y=offset.y+square*3}
buttons.Undo={text="Undo",show=false,x=offset.x+square*4+90,y=offset.y+square*3-75}
buttons.Done={text="Done",show=false,x=offset.x+square*4+90,y=offset.y+square*3-150}
stage=NONE
D_touched=nil
--choose a player to start with
play=math.random(1,2)
--start tween to vibrate current player colour, see use in DrawBoard
Alpha={a=255}
tween( 2, Alpha, { a=50 }, { easing = tween.easing.linear, loop = tween.loop.pingpong } )
end
--====== DRAW functions =================
function draw()
background(200)
DrawBoard()
--draw ellipse under finger if touching screen
if CurrentTouch.state~=ENDED and CurrentTouch.x>0 then
pushStyle()
fill(255,255,0,100)
ellipse(CurrentTouch.x,CurrentTouch.y,40,60)
popStyle()
end
if stage==NONE then --player must move L
DrawHelpText("It is "..player[play].name.." to move.\n"..
[[
Try to block your opponent from moving their L piece. Use your finger to draw your L piece at another position on the board (you can only draw on pale blue, unoccupied squares - including the squares your piece was on - but at least one square must be different).
You can draw it upside down and back to front, any way you want.
The new position will be shown as 4 square dots until you finish your move.]])
else --player has moved L, and can now move dot
DrawHelpText(
[[If you want, move ONE of the dots to a blank square to make it more difficult for your opponent.
To do this, touch a dot, then a blank square, and the dot should move.
Press the Done button when you're finished your move, or Undo to start your move again.]])
end
end
function DrawBoard()
pushStyle()
--draw heading
font("Papyrus") fontSize(48)
fill(100) text("The L Game",offset.x+square*2+3,offset.y+square*4+57)
fill(255,255,0) text("The L Game",offset.x+square*2,offset.y+square*4+60)
fill(0) font("ArialMT") fontSize(14) text("(c) Edward De Bono",offset.x+square*2+3,offset.y+square*4+30)
--draw board
spriteMode(CORNER)
sprite(board,offset.x,offset.y)
--draw dots
strokeWidth(0)
for i=1,2 do
if D_touched==i then fill(dot.color.r,dot.color.g,dot.color.b,Alpha.a) else fill(dot.color) end
local d=dot.pos[i]
if dot2.id==i then d=dot2.pos end
ellipse(offset.x+square*(d.x-.5),offset.y+square*(d.y-.5),square*.6)
end
--draw current player
local a=255
if playerN.pos[1] then a=75 else a=Alpha.a end
local pp=player[play]
fill(pp.color.r,pp.color.g,pp.color.b,a)
for i=1,4 do
rect(offset.x+square*(player[play].pos[i].x-1),offset.y+square*(player[play].pos[i].y-1),square,square)
end
if playerN.pos[1] then
fill(player[play].color)
for i=1,4 do
rect(offset.x+square*(playerN.pos[i].x-.75),offset.y+square*(playerN.pos[i].y-.75),square*.5,square*.5)
end
end
--draw other player's L
local p=3-play --other player's id
fill(player[p].color)
for i=1,4 do
rect(offset.x+square*(player[p].pos[i].x-1),offset.y+square*(player[p].pos[i].y-1),square,square)
end
--add buttons
DrawButtons()
popStyle()
end
function DrawButtons()
pushStyle()
fontSize(24)
font("ArialRoundedMTBold")
for i,b in pairs(buttons) do
if b.w==nil then b.w,b.h=textSize(b.text) end
if b.show then
stroke(186, 132, 185, 255)
strokeWidth(b.h)
line(b.x-b.w/2,b.y,b.x+b.w/2,b.y)
fill(255)
text(b.text,b.x,b.y)
end
end
popStyle()
end
function DrawHelpText(t)
pushStyle()
font("HelveticaNeue")
fill(0)
fontSize(16)
textWrapWidth(size+offset.x+20)
textMode(CORNER)
local sx,sy=textSize(t)
text(t,offset.x/2,offset.y-sy-25)
popStyle()
end
--===== TOUCH functions =======================
function touched(touch)
--get square that was touched as vec2
local p=GetSquare(touch.x,touch.y)
--if user is making a move, process touch
if touch.state~=ENDED and state==MOVE then
if stage==TOUCHED_DOT then --if user has previously touched a dot
if GetD(p) then --see if he's touched a blank square to move it to
dot2.id=D_touched
dot2.pos=vec2(p.x,p.y) --yes, so store new position
ChangeStage(MOVED_DOT) --and move to next stage
return
else --move was faulty, reset to position after L moved
ChangeStage(MOVED_L)
dot2={}
end
--if user has already moved the L, he has option to move a dot or finish the move
elseif stage==MOVED_L then
--check if either of the dots touched
if p==dot.pos[1] then D_touched=1
elseif p==dot.pos[2] then D_touched=2
end
if D_touched~=nil then --a dot was touched, wait for user to choose new square
ChangeStage(TOUCHED_DOT)
return
end
end
if stage<=MOVED_L and p then --check for a move of the L piece
if id~=touch.id then
id=touch.id
touches={}
nTouches=0
end
local v=GetSquare(touch.x,touch.y)
local u=v.x*10+v.y
if touches[u]==nil then nTouches=nTouches+1 end
touches[u]=v
if nTouches==4 then MoveL() end
end
--check the other game states
elseif touch.state==ENDED then
local b=GetButton(touch.x,touch.y)
if b then HandleButton(b) end
end
end
function HandleButton(b)
if b==buttons.Restart then
StartGame()
elseif b==buttons.Undo then
playerN.pos={}
dot2={}
D_touched=nil
ChangeStage(NONE)
elseif b==buttons.Done then --finish move
--TO DO - store move to allow move rollbacks
for i=1,4 do --store new position
player[play].pos[i]=playerN.pos[i]
end
playerN.pos={} --clear
--move dot if applicable
if dot2.id then dot.pos[dot2.id]=dot2.pos end
dot2.id=nil dot2.pos={} D_touched=nil
ChangeStage(NONE)
--switch player
play=3-play
end
end
--process L move
function MoveL()
playerN.pos={}
local n,tr,tc=0,{},{}
for i=1,4 do tr[i],tc[i]=0,0 end
local mr,mc=0,0
local r,c=0,0
local ar,ac=0,0
local p=3-play --opponent's id
for i,t in pairs(touches) do
--check for valid move first
for k=1,2 do if t==dot.pos[k] then ChangeStage(NONE) return end end
for k=1,4 do if t==player[p].pos[k] then ChangeStage(NONE) return end end
tr[t.x]=tr[t.x]+1
if tr[t.x]>mr then mr=tr[t.x] r=t.x end
ar=ar+t.x
tc[t.y]=tc[t.y]+1
if tc[t.y]>mc then mc=tc[t.y] c=t.y end
ac=ac+t.y
end
local moved=false
if (mr==3 and mc==2 and mc~=mr/3) or --L is lying down
(mr==2 and mc==3 and mr~=mc/3) then --L is upright
for i=1,4 do
local n=player[play].pos[i].x*10 + player[play].pos[i].y
if touches[n]==nil then moved=true end
end
local n=0
for i,t in pairs(touches) do
n=n+1
playerN.pos[n]=vec2(t.x,t.y)
end
end
if moved==true then
ChangeStage(MOVED_L)
else
playerN.pos={}
ChangeStage(NONE)
end
end
function ChangeStage(s)
stage=s
if s>=MOVED_L then
buttons.Undo.show=true
buttons.Done.show=true
else
buttons.Undo.show=false
buttons.Done.show=false
end
end
--====== UTILITY functions
--give an x,y position, return the grid position (1,1 is bottom left) or nil if outside grid
function GetSquare(x,y)
local x,y=math.floor((x-offset.x)/square+1),math.floor((y-offset.y)/square+1)
if x>0 and x<5 and y>0 and y<5 then return vec2(x,y) else return nil end
end
function GetButton(x,y)
for i,b in pairs(buttons) do
if math.abs(x-b.x)<b.w and math.abs(y-b.y-b.h/2)<b.h
and b.show==true then return b end
end
return nil
end
function GetD(p)
--check for valid move first
for k=1,2 do if p==dot.pos[k] then return false end end
for k=1,4 do if p==playerN.pos[k] then return false end end
for k=1,4 do if p==player[3-play].pos[k] then return false end end
return true
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment