Skip to content

Instantly share code, notes, and snippets.

@pepinganos
Last active August 29, 2015 14:17
Show Gist options
  • Save pepinganos/ae40757ab9969ddccc49 to your computer and use it in GitHub Desktop.
Save pepinganos/ae40757ab9969ddccc49 to your computer and use it in GitHub Desktop.
2048 in Codea
--# Interface
Interface = class()
local x=WIDTH/2
local w=300
local h=60
function Interface:init() -- Constructor
self.buttons = {}
self.labels = {}
end
function Interface:addButton(line, txt, id)
table.insert(self.buttons,Button(line, txt, id))
end
function Interface:addLabel(line, txt, size)
table.insert(self.labels,Label(line, txt, size))
end
function Interface:draw(backBox)
x=WIDTH/2
noStroke()
if backBox == true then
fill(150,150,150,200)
rect(WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
end
for i, button in ipairs(self.buttons) do
button:draw()
end
for i, label in ipairs(self.labels) do
label:draw()
end
end
function Interface:touched(touch)
local xb=touch.x
local yb=touch.y
ellipse(xb,yb,50,50)
for i, button in ipairs(self.buttons) do
if xb>x-w/2 and xb<x+w/2 and yb>HEIGHT-(button.line+.5)*h and yb<HEIGHT-(button.line-.5)*h then
sound(SOUND_BLIT, 33372)
return button.id
end
end
return "background"
end
----------------
Button = class()
function Button:init(line, txt, id) -- Constructor
self.line=line
self.txt=txt
self.id=id
end
function Button:draw()
strokeWidth(0)
fill(0, 0, 0, 95)
rect(WIDTH/2+8,HEIGHT-self.line*h-8,w,h)
strokeWidth(2)
fill(198, 177, 118, 255)
rect(WIDTH/2,HEIGHT-self.line*h,w,h)
font("Arial-BoldMT")
fill(79, 79, 70, 255)
fontSize(35)
textAlign(CENTER)
text(self.txt, x,HEIGHT-(self.line)*h)
end
----------------
Label = class()
function Label:init(line, txt, size) -- Constructor
self.line=line
self.txt=txt
self.size=size
end
function Label:draw()
fontSize(self.size)
textAlign(CENTER)
fill(2, 2, 2, 205)
text(self.txt, x+2,HEIGHT-(self.line)*h-3)
fill(255, 232, 0, 255)
text(self.txt, x,HEIGHT-(self.line)*h)
end
----------------
-- 2048 Game
--displayMode(FULLSCREEN)
mainSCR = Interface()
inGameSCR = Interface()
function setup()
print("Testing, 1, 2, 3")
textAlign(CENTER)
rectMode(CENTER)
stroke(255)
anim = {}
cell = {}
SHRINK = 1
FADEOUT = 2
cellSize = 100
padding = 20
sensitivity =40
highscore = 0
highscore = readLocalData("highscore", highscore)
pressedX=0
pressedY=0
piece = {}
piece[0] = color(109, 98, 98, 255)
piece[2] = color(230, 226, 226, 255)
piece[4] = color(219, 209, 171, 255)
piece[8] = color(229, 170, 95, 255)
piece[16] = color(245, 165, 24, 255)
piece[32] = color(223, 181, 163, 255)
piece[64] = color(253, 50, 3, 255)
piece[128] = color(224, 219, 136, 255)
piece[256] = color(226, 194, 111, 255)
piece[512] = color(255, 247, 0, 255)
piece[1024] = color(231, 221, 87, 255)
piece[2048] = color(177, 228, 101, 255)
piece[4096] = color(88, 201, 15, 255)
piece[8192] = color(148, 223, 165, 255)
piece[16384] = color(161, 219, 198, 255)
piece[32768] = color(147, 222, 223, 255)
piece[65536] = color(206, 147, 223, 255)
mainSCR:addLabel(3, "2048", 80)
mainSCR:addButton(5, "New Game", "start")
mainSCR:addButton(7, "Continue", "continue")
inGameSCR:addButton(1, "Menu", "menu")
state="MAIN_SCR"
resetGame()
playing = false
end
function resetGame()
for i = 1, 4 do
cell[i] = {0,0,0,0}
end
score = 0
end
function draw()
background(40, 40, 50)
strokeWidth(5)
local y
for y = 1, 4 do
for x = 1, 4 do
value=cell[x][y]
drawPiece(x,y,value,0,0)
end
end
for i, m in ipairs(anim) do
if m.counter <1 then
table.remove(anim, i) --remove finished animations
else
m:draw() --draw the animations
end
end
if state=="MAIN_SCR" then
mainSCR:draw(true)
elseif state=="GAME_SCR" then
inGameSCR:draw(false)
end
drawScore()
end
function drawScore()
font("Arial-BoldMT")
fill(79, 79, 70, 255)
fontSize(35)
textAlign(CENTER)
text("Score: "..score, WIDTH/4, HEIGHT/8)
text("Highscore: "..highscore, WIDTH/4*2.8, HEIGHT/8)
end
function drawPiece(col,row,value,size,transparency)
ox = (WIDTH-4*cellSize+3*padding)/2 + (cellSize+padding)* (col-1)
oy = (HEIGHT-4*cellSize+3*padding)/2 + (cellSize+padding)* (row-1)
if transparency == 0 then transparency = 255 end
fill(piece[value].r,piece[value].g,piece[value].b,transparency)
stroke(255, 255, 255, 255)
rect (ox, oy, cellSize+size, cellSize+size)
fill(0,0,0,transparency)
d = string.format("%d", value)
if string.len(d)<5 then fontSize(40) else fontSize(32) end
if value ~= 0 then
text (value, ox, oy)
end
end
function touched(touch)
if touch.state == BEGAN then
pressedX=touch.x
pressedY=touch.y
end
if touch.state == ENDED then
--Get "answer" from menus
local answer = ""
if state=="MAIN_SCR" then
answer = mainSCR:touched(touch)
elseif (state=="GAME_SCR") then
answer = inGameSCR:touched(touch)
playGame(touch)
end
--Treat "answer"
if answer=="continue" then
if playing ==true then state="GAME_SCR" end
elseif answer=="start" then
resetGame()
playing = true
populate()
state="GAME_SCR"
elseif answer=="menu" then
state="MAIN_SCR"
end
end
end
function playGame(touch)
mouvX=touch.x-pressedX
mouvY=touch.y-pressedY
if(math.abs(mouvX)>sensitivity or math.abs(mouvY)>sensitivity) then
if(math.abs(mouvX)-math.abs(mouvY)>0) then
a=math.abs(mouvX)/math.abs(mouvY)
else
a=math.abs(mouvY)/math.abs(mouvX)
end
if(a-1>.1) then
if(math.abs(mouvX)-math.abs(mouvY)>0) then --horizontal mouvement
if ((mouvX)>0) then
rot=1 --right
else
rot=3 --left
end
else --vertical mouvement
if ((mouvY)>0) then
rot=2 --up
else
rot=0 --down
end
end
moved=play(false)
if moved then
populate()
sound(SOUND_HIT, 33372)
end
playable=false
for i=0,3 do
playable = play(true) or playable
rotateRight(1)
end
if playable ~= true then
playing = false
state = "MAIN_SCR"
sound(SOUND_JUMP, 33374)
saveLocalData("highscore", highscore) --save only if ended
--print("END OF GAME")
end
end
end
end
function populate()
voidCellX = {}
voidCellY = {}
i = 0
for y = 1, 4 do
for x = 1, 4 do
if (cell[x][y] == 0) then
table.insert(voidCellX, x)
table.insert(voidCellY, y)
i = i + 1
end
end
end
if i>0 then
v = math.random(i)
if math.random(5) < 5 then p = 2 else p = 4 end
cell[voidCellX[v]][voidCellY[v]]=p
table.insert(anim, Anim(voidCellX[v],voidCellY[v],p,SHRINK,50))
end
end
function rotateRight(n)
if n==0 or n== 4 then return end
for i = 1, n do
rotatedCell = {}
for i = 1, 4 do
rotatedCell[i] = {0,0,0,0}
end
for y = 1, 4 do
for x = 1, 4 do
newX = y
newY = 5 - x
rotatedCell[newX][newY] = cell[x][y]
end
end
copyArray(rotatedCell,cell)
end
end
function rotateCoord(x,y,n)
n = math.fmod(n,4)
if n~= 0 then
for i = 1, n do
newX = y
newY = 5 - x
x=newX
y=newY
end
return newX, newY
else
return x, y
end
end
function copyArray(ori, dest) --copy array by value
for y = 1, 4 do
for x = 1, 4 do
dest[x][y] = ori[x][y]
end
end
end
function displayArray(a) --to debug only...
for i = 4, 1, -1 do
print(a[1][i], a[2][i], a[3][i], a[4][i])
end
print("----------------")
end
function play(testOnly)
possibleMove = false
rotateRight(rot)
backup = {}
for i = 1, 4 do
backup[i]={0,0,0,0}
end
copyArray(cell, backup)
alreadyAdded = {}
for i = 1, 4 do
alreadyAdded[i] = {false,false,false,false}
end
for y = 2, 4 do
for x = 1, 4 do
val=cell[x][y] --the piece we're gonna move
if(val ~= 0) then --does it exist?
for i = y-1, 1, -1 do
if(cell[x][i] ~= 0) then --case is OCCUPIED
if(val == cell[x][i] and alreadyAdded[x][i] == false) then --they're equal
cell[x][i] = cell[x][i] * 2
score = score + cell[x][i]
if score>highscore then highscore=score end
cell[x][y] = 0
alreadyAdded[x][i]=true
possibleMove = true
break
else
--they're different
if (i ~= y-1) then --...and not just a line below
cell[x][i+1] = cell[x][y]
cell[x][y] = 0
possibleMove = true
end
break
end
else --case is EMPTY
if testOnly == false then
nx, ny = rotateCoord(x,i+1,4-rot) --undo rotation
table.insert(anim, Anim(nx,ny,val,FADEOUT,100))
end
if i == 1 then --bottom line reached
cell[x][i] = cell[x][y]
cell[x][y] = 0
possibleMove = true
break
end
end
end
end
end
end
if(testOnly) then
copyArray(backup, cell) --undo move
end
rotateRight(4-rot) --undo rotation
return possibleMove
end
Anim = class()
function Anim:init(col,row,value,effect,counter)
self.col = col
self.row =row
self.value = value
self.effect = effect
self.counter = counter
end
function Anim:draw()
if self.effect==SHRINK then
drawPiece(self.col,self.row,self.value,self.counter,0)
self.counter = self.counter - 5
elseif self.effect==FADEOUT then
if cell[self.col][self.row] ~= 0 then
self.counter=0
else
drawPiece(self.col,self.row,self.value,0,self.counter)
self.counter = self.counter / 1.2
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment