cambridge-modpack/tetris/modes/stacker.lua

165 lines
4.8 KiB
Lua

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 = math.random(1, 7 + self.block_width - 1)
self.direction = ({-1, 1})[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