local GameMode = require 'tetris.modes.gamemode' local Grid = require 'tetris.components.grid' local StackerGame = GameMode:extend() StackerGame.name = "Stacker" StackerGame.hash = "Stacker" StackerGame.tagline = "Hey, wait, I didn't mean this kind of block stacking!" local block = { skin = "2tie", colour = "C" } function StackerGame:new() self.super:new() self.grid = Grid(7, 19) self.next_queue_length = 0 self.ready_frames = 1 self.row = 19 self.block_width = 3 self.position = 0 self.direction = 0 self.ticks = 0 self.are = 30 self.map = {} block.colour = "C" self:updateGrid() end function StackerGame:getSpeed() return 20 ^ ((self.row - 4) / 15) end function StackerGame:getMaxBlockWidth() if self.row >= 17 then return 3 elseif self.row >= 11 then return 2 else return 1 end end function StackerGame:updateGrid() local width = math.min(self:getMaxBlockWidth(), self.block_width) self.grid:clear() self.grid:applyMap(self.map) for w = 0, width - 1 do self.grid.grid[self.row][self.position - w] = block end for y = 5, 19 do for x = 1, 7 do self.grid.grid_age[y][x] = 3 end end end function StackerGame:advanceOneFrame(inputs, ruleset) if self.game_over or self.completed then return true end if self.are > 0 then self.are = self.are - 1 return false elseif self.are == 0 then self.position = love.math.random(1, 7 + self.block_width - 1) self.direction = ({-1, 1})[love.math.random(2)] self.are = -1 end if not self.prev_inputs.up and inputs.up then self.prev_inputs = inputs local width = math.min(self:getMaxBlockWidth(), self.block_width) local new_width = 0 local row = {} for w = 0, width - 1 do if self.grid:isOccupied(self.position - w - 1, self.row) and self.position - w >= 1 and self.position - w <= 7 then new_width = new_width + 1 row[self.position - w] = block end end if new_width == 0 then self.game_over = true else playSE("lock") self.map[self.row] = row self.row = self.row - 1 if self.row <= 8 and self.row >= 5 then block.colour = "R" elseif self.row <= 4 then block.colour = "G" self.completed = true self:updateGrid() return false end self.ticks = 0 self.block_width = new_width self.position = 0 self.direction = 0 self.are = 30 self:updateGrid() end return false end self.ticks = self.ticks + 1 if self.ticks >= self:getSpeed() then self.ticks = self.ticks - self:getSpeed() if self.position >= 7 + math.min(self:getMaxBlockWidth(), self.block_width) - 1 then self.direction = -1 elseif self.position <= 1 then self.direction = 1 end self.position = self.position + self.direction self:updateGrid() end self.prev_inputs = inputs return false end local function noOutline(game, block, x, y, age) local x = 0.75 return x, x, x, 1, 0 end function StackerGame:onGameComplete() self.grid:clear() local win = { [6] = {nil, block, nil, nil, nil, block, nil}, [7] = {nil, block, nil, block, nil, block, nil}, [8] = {nil, block, block, nil, block, block, nil}, [9] = {nil, block, nil, nil, nil, block, nil}, [11] = {nil, nil, nil, block, nil, nil, nil}, [12] = {nil, nil, nil, block, nil, nil, nil}, [13] = {nil, nil, nil, block, nil, nil, nil}, [14] = {nil, nil, nil, block, nil, nil, nil}, [16] = {nil, block, nil, block, block, nil, nil}, [17] = {nil, block, block, nil, nil, block, nil}, [18] = {nil, block, nil, nil, nil, block, nil}, [19] = {nil, block, nil, nil, nil, block, nil}, } self.grid:applyMap(win) end function StackerGame:drawGrid() self.grid:drawCustom(noOutline, self) end function StackerGame:drawScoringInfo() love.graphics.setColor(1, 1, 1, 1) love.graphics.setFont(font_3x5_2) love.graphics.print("<-- MAJOR PRIZE", 190, 80) love.graphics.print("<-- MINOR PRIZE", 190, 144) love.graphics.print("ROWS STACKED", 64, 340) love.graphics.print("FRAMES PER MOVE", 64, 400) love.graphics.setFont(font_3x5_3) love.graphics.print(19 - self.row .. (self.row <= 4 and " - COMPLETE!" or ""), 64, 360) love.graphics.print( ( self.row > 4 and string.format("%.02f", self:getSpeed()) or "N/A" ), 64, 420 ) end function StackerGame:getHighscoreData() return { rows = 19 - self.row, } end return StackerGame