Last active
October 19, 2021 07:39
-
-
Save Adrodoc/9a9f6005d252846ce7bd91dcef363c07 to your computer and use it in GitHub Desktop.
tetris.lua
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
require 'mickkay.wol.Spell' | |
tetris = {} | |
tetris.delay = 10 | |
tetris.origin = Vec3(453985, 80, -888253) | |
tetris.width = 10 | |
tetris.height = 20 | |
tetris.rotationCenter = Vec3(0,-1,0) | |
local upperCenter = tetris.origin + Vec3(tetris.width//2 + 1, tetris.height-1, 0) | |
function tetris:setup() | |
spell.pos = self.origin | |
spell:execute('fill ~ ~ ~ ~%s ~%s ~ sandstone', self.width + 1, self.height + 1) | |
spell:execute('fill ~1 ~1 ~ ~%s ~%s ~ air', self.width, self.height) | |
end | |
function tetris:start() | |
spell:singleton('tetris') | |
self:setup() | |
self.brick = nil | |
self.queue = Events.connect( | |
'tetris-down', | |
'tetris-left', | |
'tetris-right', | |
'tetris-rotate-clockwise', | |
'tetris-rotate-counter-clockwise' | |
) | |
while true do | |
if self.brick == nil or not self.brick:canMoveRelative(Vec3(0, -1, 0)) then | |
if self.brick ~= nil then | |
tetris:clearFullRows() | |
end | |
self.brick = Brick.new(upperCenter) | |
if not self.brick:canBePlaced() then | |
spell:execute('tellraw @a[r=50] {"text":"[tetris] Game Over!","color":"gold"}') | |
return | |
end | |
self.brick:place() | |
else | |
self.brick:moveRelative(Vec3(0, -1, 0)) | |
end | |
tetris:handleUserInputUntil(Time.gametime + self.delay) | |
end | |
end | |
function tetris:clearFullRows() | |
for y=1,self.height do | |
while true do | |
for x=1,self.width do | |
spell.pos = self.origin + Vec3(x,y,0) | |
if spell.block.name == 'air' then | |
goto label | |
end | |
end | |
spell.pos = self.origin | |
spell:execute('clone ~1 ~%s ~ ~%s ~%s ~ ~1 ~%s ~ replace move', y + 1, self.width, self.height, y) | |
end | |
::label:: | |
end | |
end | |
function tetris:handleUserInputUntil(time) | |
while true do | |
local event = self.queue:next(time - Time.gametime) | |
if event == nil then | |
break | |
elseif event.name == 'tetris-down' then | |
while self.brick:canMoveRelative(Vec3(0, -1, 0)) do | |
self.brick:moveRelative(Vec3(0, -1, 0)) | |
end | |
elseif event.name == 'tetris-left' then | |
local relative = Vec3(-1, 0, 0) | |
if self.brick:canMoveRelative(relative) then | |
self.brick:moveRelative(relative) | |
end | |
elseif event.name == 'tetris-right' then | |
local relative = Vec3(1, 0, 0) | |
if self.brick:canMoveRelative(relative) then | |
self.brick:moveRelative(relative) | |
end | |
elseif event.name == 'tetris-rotate-clockwise' then | |
self.brick:maybeRotateClockwise() | |
elseif event.name == 'tetris-rotate-counter-clockwise' then | |
self.brick:maybeRotateCounterClockwise() | |
end | |
end | |
end | |
declare('Brick') | |
local templates = { | |
{Vec3(0,0,0),Vec3(0,-1,0),Vec3(0,-2,0),Vec3(0,-3,0)}, | |
{Vec3(0,0,0),Vec3(0,-1,0),Vec3(0,-2,0),Vec3(-1,-2,0)}, | |
{Vec3(0,-2,0),Vec3(-1,0,0),Vec3(-1,-1,0),Vec3(-1,-2,0)}, | |
{Vec3(0,0,0),Vec3(0,-1,0),Vec3(-1,-1,0),Vec3(-1,-2,0)}, | |
{Vec3(0,-1,0),Vec3(0,-2,0),Vec3(-1,0,0),Vec3(-1,-1,0)}, | |
{Vec3(0,0,0),Vec3(0,-1,0),Vec3(0,-2,0),Vec3(-1,-1,0),}, | |
{Vec3(0,0,0),Vec3(0,-1,0),Vec3(-1,0,0),Vec3(-1,-1,0)} | |
} | |
local colors = { | |
'light_blue', | |
'blue', | |
'orange', | |
'red', | |
'lime', | |
'magenta', | |
'yellow' | |
} | |
function Brick.new(pos) | |
local i = math.random(#templates) | |
local result = { | |
pos = pos, | |
blocks = templates[i], | |
color = colors[i] | |
} | |
setmetatable(result, Brick) | |
return result | |
end | |
function Brick:canBePlaced() | |
for k,blockPos in pairs(self.blocks) do | |
spell.pos = self.pos + blockPos | |
if spell.block.name ~= 'air' then | |
return false | |
end | |
end | |
return true | |
end | |
function Brick:place() | |
self:setBlocks(Blocks.get('wool'):withData({color=self.color})) | |
end | |
function Brick:breakMe() | |
self:setBlocks(Blocks.get('air')) | |
end | |
function Brick:setBlocks(block) | |
for k,blockPos in pairs(self.blocks) do | |
spell.pos = self.pos + blockPos | |
spell.block = block | |
end | |
end | |
function Brick:canMoveRelative(vec) | |
return self:canMoveTo(self.pos + vec) | |
end | |
function Brick:canMoveTo(pos) | |
for k,blockPos in pairs(self.blocks) do | |
local blockPos = pos + blockPos | |
if not self:contains(blockPos) then | |
spell.pos = blockPos | |
if spell.block.name ~= 'air' then | |
return false | |
end | |
end | |
end | |
return true | |
end | |
function Brick:contains(pos) | |
for k,blockPos in pairs(self.blocks) do | |
if pos == self.pos + blockPos then | |
return true | |
end | |
end | |
return false | |
end | |
function Brick:moveRelative(vec) | |
self:moveTo(self.pos + vec) | |
end | |
function Brick:moveTo(pos) | |
self:breakMe() | |
self.pos = pos | |
self:place() | |
end | |
function Brick:maybeRotateClockwise() | |
local blocks = {} | |
for k,blockPos in pairs(self.blocks) do | |
local relative = blockPos - tetris.rotationCenter | |
local result = tetris.rotationCenter + Vec3(relative.y, -relative.x, 0) | |
table.insert(blocks, result) | |
end | |
self:maybeTransformInto(blocks) | |
end | |
function Brick:maybeRotateCounterClockwise() | |
local blocks = {} | |
for k,blockPos in pairs(self.blocks) do | |
local relative = blockPos - tetris.rotationCenter | |
local result = tetris.rotationCenter + Vec3(-relative.y, relative.x, 0) | |
table.insert(blocks, result) | |
end | |
self:maybeTransformInto(blocks) | |
end | |
function Brick:maybeTransformInto(blocks) | |
if self:canTransformInto(blocks) then | |
self:breakMe() | |
self.blocks = blocks | |
self:place() | |
end | |
end | |
function Brick:canTransformInto(blocks) | |
for k,blockPos in pairs(blocks) do | |
blockPos = self.pos + blockPos | |
if not self:contains(blockPos) then | |
spell.pos = blockPos | |
if spell.block.name ~= 'air' then | |
return false | |
end | |
end | |
end | |
return true | |
end | |
return tetris |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment