summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthe lemons <citrons@mondecitronne.com>2023-03-24 03:14:37 -0500
committerthe lemons <citrons@mondecitronne.com>2023-03-24 03:14:37 -0500
commit88e53b6f21d1183ec86f6234e2108ee331367920 (patch)
tree65cf189733a2aaff240a827d7718881e146f8126
L hell
-rw-r--r--conf.lua5
-rw-r--r--main.lua78
-rw-r--r--playfield.lua45
-rw-r--r--polyomino.lua96
-rw-r--r--tetrominoes.lua50
5 files changed, 274 insertions, 0 deletions
diff --git a/conf.lua b/conf.lua
new file mode 100644
index 0000000..c23b976
--- /dev/null
+++ b/conf.lua
@@ -0,0 +1,5 @@
+function love.conf(t)
+ t.identity = "polyflux"
+ t.window.title = "polyflux"
+ t.window.resizable = true
+end
diff --git a/main.lua b/main.lua
new file mode 100644
index 0000000..832678e
--- /dev/null
+++ b/main.lua
@@ -0,0 +1,78 @@
+local playfield = require "playfield"
+local tetrominoes = require "tetrominoes"
+
+local field
+local piece
+
+function love.load()
+ field = playfield.new(20, 10)
+end
+
+function love.draw()
+ local _, height = love.graphics.getDimensions()
+ local size = height / field.lines
+
+ love.graphics.setColor(0.1, 0.1, 0.1)
+ love.graphics.rectangle("fill",
+ 0, 0, size * field.columns, size * field.lines)
+ love.graphics.setColor(1, 1, 1)
+
+ local function draw_block(line, column)
+ local x = (column - 1) * size
+ local y = height - line * size
+ love.graphics.rectangle("fill", x, y, size, size)
+ end
+
+ for line = 1, field.lines do
+ for column = 1, field.columns do
+ if field.cells[line][column] then
+ draw_block(line, column)
+ end
+ end
+ end
+
+ if piece then
+ for line = 0, piece.poly.size - 1 do
+ for column = 0, piece.poly.size - 1 do
+ if piece:get_cell(line, column) then
+ draw_block(piece.line + line, piece.column + column)
+ end
+ end
+ end
+ end
+end
+
+local function gravity()
+ if not piece then
+ piece = tetrominoes.l:drop(field)
+ assert(piece, "you lose.")
+ else
+ if not piece:move(-1, 0) then
+ piece:place()
+ piece = nil
+ end
+ end
+end
+
+local interval = 0.5
+local ellapsed = 0
+
+function love.update(dt)
+ ellapsed = ellapsed + dt
+ while ellapsed >= interval do
+ gravity()
+ ellapsed = ellapsed - interval
+ end
+end
+
+function love.keypressed(key)
+ if piece then
+ if key == "left" then
+ piece:move(0, -1)
+ elseif key == "right" then
+ piece:move(0, 1)
+ elseif key == "down" then
+ piece:move(-1, 0)
+ end
+ end
+end
diff --git a/playfield.lua b/playfield.lua
new file mode 100644
index 0000000..22a32cb
--- /dev/null
+++ b/playfield.lua
@@ -0,0 +1,45 @@
+local M = {}
+M.__index = M
+
+local function line_index(cells, k)
+ if type(k) == 'number' and math.floor(k) == k then
+ cells[k] = {}
+ return cells[k]
+ end
+end
+
+function M.new(lines, columns)
+ local new = setmetatable({}, M)
+ new.lines, new.columns = lines, columns
+ new.cells = setmetatable({}, {__index = line_index})
+ return new
+end
+
+function M:cell_full(line, column)
+ if line >= 1 and column >= 1 and column <= self.columns then
+ return self.cells[line][column] or false
+ else
+ return true
+ end
+end
+
+function M:line_full(line)
+ for column = 1, w do
+ if self.cells[line][column] then
+ return true
+ end
+ end
+ return false
+end
+
+
+function M:shift_down(line)
+end
+
+function M:shift_up(line)
+end
+
+function M:clear_full()
+end
+
+return M
diff --git a/polyomino.lua b/polyomino.lua
new file mode 100644
index 0000000..00f20bc
--- /dev/null
+++ b/polyomino.lua
@@ -0,0 +1,96 @@
+local M = {}
+M.__index = M
+
+function M.def(name, shape)
+ local new = setmetatable({name = name}, M)
+
+ new.cells = {}
+ for l in shape:gmatch "[^%s]+" do
+ local line = {}
+ new.size = #l
+ for i = 1, #l do
+ local c = l:sub(i, i)
+ if c ~= "." then
+ if c == "#" then
+ line[i] = new.name
+ else
+ line[i] = new.name .. "." .. c
+ end
+ end
+ end
+ table.insert(new.cells, 1, line)
+ end
+
+ for line = 1, new.size do
+ for column = 1, new.size do
+ if new.cells[line][column] then
+ new.bottom = line
+ end
+ end
+ if new.bottom then
+ break
+ end
+ end
+
+ return new
+end
+
+local piece = {}
+piece.__index = piece
+
+function M:drop(field)
+ local new = setmetatable({poly = self}, piece)
+ new.field = field
+ new.line = field.lines - (self.bottom - 1)
+ new.column = math.floor(field.columns / 2 - self.size / 2 + 0.5)
+ new.rotation = 1
+ if not new:can_occupy() then
+ return
+ end
+ return new
+end
+
+function piece:get_cell(line, column, rotation)
+ return self.poly.cells[line + 1][column + 1]
+end
+
+function piece:can_occupy(line, column, rotation)
+ line = line or self.line
+ column = column or self.column
+ for l = 0, self.poly.size - 1 do
+ for c = 0, self.poly.size - 1 do
+ if self:get_cell(l, c)
+ and self.field:cell_full(line + l, column + c) then
+ return false
+ end
+ end
+ end
+ return true
+end
+
+function piece:place()
+ for line = 0, self.poly.size - 1 do
+ for column = 0, self.poly.size - 1 do
+ local cell = self:get_cell(line, column)
+ if cell then
+ self.field.cells[self.line + line][self.column + column] = cell
+ end
+ end
+ end
+end
+
+function piece:rotate(ccw)
+ return rotated
+end
+
+function piece:move(lines, columns)
+ local line, column = self.line + lines, self.column + columns
+ if self:can_occupy(line, column) then
+ self.line = line
+ self.column = column
+ return true
+ end
+ return false
+end
+
+return M
diff --git a/tetrominoes.lua b/tetrominoes.lua
new file mode 100644
index 0000000..fcab6c7
--- /dev/null
+++ b/tetrominoes.lua
@@ -0,0 +1,50 @@
+local poly = require "polyomino"
+
+local M = {}
+M.__index = M
+
+M.i = poly.def("tetr.I", [[
+ ....
+ ####
+ ....
+ ....
+]])
+
+M.j = poly.def("tetr.J", [[
+ #..
+ ###
+ ...
+]])
+
+M.l = poly.def("tetr.L", [[
+ ..#
+ ###
+ ...
+]])
+
+M.o = poly.def("tetr.O", [[
+ ....
+ .##.
+ .##.
+ ....
+]])
+
+M.s = poly.def("tetr.S", [[
+ .##
+ ##.
+ ...
+]])
+
+M.z = poly.def("tetr.Z", [[
+ ##.
+ .##
+ ...
+]])
+
+M.t = poly.def("tetr.T", [[
+ .#.
+ ###
+ ...
+]])
+
+return M