----------------------------- -- Levak ©2014 -------------- -- http://levak.free.fr/ ---- -- levak92@gmail.com -------- ----------------------------- Grid = class() function Grid:init(x, y, s) self.x, self.y, self.s = x, y, s self.grid = {} self.dead = {} local i for i = 1, s do self.grid[i] = {} end self.null = Tile(1, 1, 0) self:addRandomTile() self:addRandomTile() end function Grid:getEmptySlots() local t = {} local grid = self.grid local i, j for i = 1, self.s do for j = 1, self.s do if grid[i][j] == nil then t[#t+1] = {x=i, y=j} end end end return t end function Grid:canMove() local i, j local s = self.s for i = 1, s do for j = 1, s do local tile = self.grid[i][j] local value = tile and tile.data.value or 0 if value == 0 then return true elseif i > 1 and self.grid[i-1][j] and self.grid[i-1][j].data.value == value then return true elseif j > 1 and self.grid[i][j-1] and self.grid[i][j-1].data.value == value then return true elseif i < s and self.grid[i+1][j] and self.grid[i+1][j].data.value == value then return true elseif j < s and self.grid[i][j+1] and self.grid[i][j+1].data.value == value then return true end end end return false end function Grid:addRandomTile(delay) local t = self:getEmptySlots() if #t > 0 then local coord = t[math.random(#t)] local value = math.random(10) == 1 and 4 or 2 local tile = Tile(coord.x, coord.y, value) self.grid[coord.x][coord.y] = tile tile.scale = 0 tile:Delay(delay or 0):Animate({scale=1}, TILE_ANIM) return tile end end function Grid:moveTile(tile, x, y) self.grid[x][y] = tile self.grid[tile.data.x][tile.data.y] = nil tile.data.x, tile.data.y = x, y end function Grid:killTile(tile) self.dead[#self.dead + 1] = tile self.grid[tile.data.x][tile.data.y] = nil end function Grid:buryTile(tile) local i for i = 1, #self.dead do if self.dead[i] == tile then table.remove(self.dead, i) break end end end function Grid:paint(gc) local x, y = self.x * ww, self.y * wh local m = 4/320 * ww gc:setColorRGB(187, 173, 160) fillRoundedRect(gc, x, y, self.s*TILE_SIZE + m, self.s*TILE_SIZE + m, m) x, y = x + m/2, y + m/2 local i, j local grid = self.grid for i = 1, self.s do for j = 1, self.s do self.null.x, self.null.y = (i-1)*TILE_SIZE/ww, (j-1)*TILE_SIZE/ww self.null:paint(gc, x, y) end end for i = 1, self.s do for j = 1, self.s do if grid[i][j] then grid[i][j]:paint(gc, x, y) end end end for i = 1, #self.dead do self.dead[i]:paint(gc, x, y) end end local dir2vect = { left = {x=-1, y=0}, right= {x=1, y=0}, down = {x=0, y=1}, up = {x=0, y=-1} } function Grid:getFarPos(tile, dir) local s = self.s local vect = dir2vect[dir] local x, y = tile.data.x + vect.x, tile.data.y + vect.y while x > 0 and x <= s and y > 0 and y <= s do if self.grid[x][y] then break end x = x + vect.x y = y + vect.y end return x - vect.x, y - vect.y end function Grid:doesMerge(tile, dir) local s = self.s local vect = dir2vect[dir] local x, y = tile.data.x - vect.x, tile.data.y - vect.y while x > 0 and x <= s and y > 0 and y <= s do local t = self.grid[x][y] if t then return t.data.value == tile.data.value and t or nil end x = x - vect.x y = y - vect.y end return nil end local dir2iter = { right= {i=-1, s=false}, left = {i=1, s=false}, up = {i=1, s=true}, down = {i=-1, s=true} } function Grid:getTiles(dir) local s = self.s local iter = dir2iter[dir] local i, j if iter.s then i, j = 1, iter.i > 0 and 1 or s else i, j = iter.i > 0 and 1 or s, 1 end local grid = self.grid if iter.s then return function() local ret = nil while not ret do if i < 1 or i > s then j, i = j + iter.i, 1 if j < 1 or j > s then break end end ret = grid[i][j] i = i + 1 end return ret end else return function() local ret = nil while not ret do if j < 1 or j > s then i, j = i + iter.i, 1 if i < 1 or i > s then break end end ret = grid[i][j] j = j + 1 end return ret end end end