-
-
Save pepinganos/ae40757ab9969ddccc49 to your computer and use it in GitHub Desktop.
2048 in Codea
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# 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