Files
tromi_mobile/game/rotation_big.lua
2024-10-27 14:45:27 +07:00

482 lines
19 KiB
Lua

local Object = require 'libs.classic'
local Piece = require 'game.piece'
local Rotation = Object:extend()
Rotation.spawn_positions = {
I = { x=2, y= -2 },
J = { x=2, y= 0 },
L = { x=2, y= 0 },
O = { x=2, y= 0 },
S = { x=2, y= 0 },
T = { x=2, y= 0 },
Z = { x=2, y= 0 },
}
Rotation.colourscheme = {
I = "R",
L = "O",
J = "B",
S = "M",
Z = "G",
O = "Y",
T = "C",
}
-- local a = {
-- {x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0}, {x=6, y=0}, {x=7, y=0},
-- {x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1}, {x=6, y=1}, {x=7, y=1},
-- {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, {x=6, y=2}, {x=7, y=2},
-- {x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, {x=6, y=3}, {x=7, y=3},
-- {x=0, y=4}, {x=1, y=4}, {x=2, y=4}, {x=3, y=4}, {x=4, y=4}, {x=5, y=4}, {x=6, y=4}, {x=7, y=4},
-- {x=0, y=5}, {x=1, y=5}, {x=2, y=5}, {x=3, y=5}, {x=4, y=5}, {x=5, y=5}, {x=6, y=5}, {x=7, y=5},
-- {x=0, y=6}, {x=1, y=6}, {x=2, y=6}, {x=3, y=6}, {x=4, y=6}, {x=5, y=6}, {x=6, y=6}, {x=7, y=6},
-- {x=0, y=7}, {x=1, y=7}, {x=2, y=7}, {x=3, y=7}, {x=4, y=7}, {x=5, y=7}, {x=6, y=7}, {x=7, y=7},
-- }
Rotation.block_offsets = {
I={
{
{x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, {x=6, y=2}, {x=7, y=2},
{x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, {x=6, y=3}, {x=7, y=3},
},
{
{x=4, y=0}, {x=5, y=0},
{x=4, y=1}, {x=5, y=1},
{x=4, y=2}, {x=5, y=2},
{x=4, y=3}, {x=5, y=3},
{x=4, y=4}, {x=5, y=4},
{x=4, y=5}, {x=5, y=5},
{x=4, y=6}, {x=5, y=6},
{x=4, y=7}, {x=5, y=7},
},
{
{x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2}, {x=6, y=2}, {x=7, y=2},
{x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3}, {x=6, y=3}, {x=7, y=3},
},
{
{x=4, y=0}, {x=5, y=0},
{x=4, y=1}, {x=5, y=1},
{x=4, y=2}, {x=5, y=2},
{x=4, y=3}, {x=5, y=3},
{x=4, y=4}, {x=5, y=4},
{x=4, y=5}, {x=5, y=5},
{x=4, y=6}, {x=5, y=6},
{x=4, y=7}, {x=5, y=7},
},
},
J={
{
{x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0},
{x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1},
{x=4, y=2}, {x=5, y=2},
{x=4, y=3}, {x=5, y=3},
},
{
{x=2, y=0}, {x=3, y=0},
{x=2, y=1}, {x=3, y=1},
{x=2, y=2}, {x=3, y=2},
{x=2, y=3}, {x=3, y=3},
{x=0, y=4}, {x=1, y=4}, {x=2, y=4}, {x=3, y=4},
{x=0, y=5}, {x=1, y=5}, {x=2, y=5}, {x=3, y=5},
},
{
{x=0, y=0}, {x=1, y=0},
{x=0, y=1}, {x=1, y=1},
{x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2},
{x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3},
},
{
{x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0},
{x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1},
{x=2, y=2}, {x=3, y=2},
{x=2, y=3}, {x=3, y=3},
{x=2, y=4}, {x=3, y=4},
{x=2, y=5}, {x=3, y=5},
},
},
L={
{
{x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0},
{x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1},
{x=0, y=2}, {x=1, y=2},
{x=0, y=3}, {x=1, y=3},
},
{
{x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0},
{x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1},
{x=2, y=2}, {x=3, y=2},
{x=2, y=3}, {x=3, y=3},
{x=2, y=4}, {x=3, y=4},
{x=2, y=5}, {x=3, y=5},
},
{
{x=4, y=0}, {x=5, y=0},
{x=4, y=1}, {x=5, y=1},
{x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2},
{x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3},
},
{
{x=2, y=0}, {x=3, y=0},
{x=2, y=1}, {x=3, y=1},
{x=2, y=2}, {x=3, y=2},
{x=2, y=3}, {x=3, y=3},
{x=2, y=4}, {x=3, y=4}, {x=4, y=4}, {x=5, y=4},
{x=2, y=5}, {x=3, y=5}, {x=4, y=5}, {x=5, y=5},
},
},
O={
{
{x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0},
{x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1},
{x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2},
{x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3},
},
{
{x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0},
{x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1},
{x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2},
{x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3},
},
{
{x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0},
{x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1},
{x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2},
{x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3},
},
{
{x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0},
{x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1},
{x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2},
{x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3},
},
},
S={
{
{x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0},
{x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1},
{x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2},
{x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3},
},
{
{x=0, y=0}, {x=1, y=0},
{x=0, y=1}, {x=1, y=1},
{x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2},
{x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3},
{x=2, y=4}, {x=3, y=4},
{x=2, y=5}, {x=3, y=5},
},
{
{x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0},
{x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1},
{x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2},
{x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3},
},
{
{x=0, y=0}, {x=1, y=0},
{x=0, y=1}, {x=1, y=1},
{x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2},
{x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3},
{x=2, y=4}, {x=3, y=4},
{x=2, y=5}, {x=3, y=5},
},
},
T={
{
{x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0}, {x=4, y=0}, {x=5, y=0},
{x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1}, {x=4, y=1}, {x=5, y=1},
{x=2, y=2}, {x=3, y=2},
{x=2, y=3}, {x=3, y=3},
},
{
{x=2, y=0}, {x=3, y=0},
{x=2, y=1}, {x=3, y=1},
{x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2},
{x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3},
{x=2, y=4}, {x=3, y=4},
{x=2, y=5}, {x=3, y=5},
},
{
{x=2, y=0}, {x=3, y=0},
{x=2, y=1}, {x=3, y=1},
{x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2},
{x=0, y=3}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3},
},
{
{x=2, y=0}, {x=3, y=0},
{x=2, y=1}, {x=3, y=1},
{x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2},
{x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3},
{x=2, y=4}, {x=3, y=4},
{x=2, y=5}, {x=3, y=5},
},
},
Z={
{
{x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0},
{x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1},
{x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2},
{x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3},
},
{
{x=4, y=0}, {x=5, y=0},
{x=4, y=1}, {x=5, y=1},
{x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2},
{x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3},
{x=2, y=4}, {x=3, y=4},
{x=2, y=5}, {x=3, y=5},
},
{
{x=0, y=0}, {x=1, y=0}, {x=2, y=0}, {x=3, y=0},
{x=0, y=1}, {x=1, y=1}, {x=2, y=1}, {x=3, y=1},
{x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2},
{x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3},
},
{
{x=4, y=0}, {x=5, y=0},
{x=4, y=1}, {x=5, y=1},
{x=2, y=2}, {x=3, y=2}, {x=4, y=2}, {x=5, y=2},
{x=2, y=3}, {x=3, y=3}, {x=4, y=3}, {x=5, y=3},
{x=2, y=4}, {x=3, y=4},
{x=2, y=5}, {x=3, y=5},
},
}
}
Rotation.pieces = 7
-- Component functions.
function Rotation:new(game_mode)
self.game = require 'game.gamemode'
end
function Rotation:rotatePiece(inputs, piece, grid, prev_inputs, initial, lastdir)
local new_inputs = {}
for input, value in pairs(inputs) do
if value and not prev_inputs[input] then
new_inputs[input] = true
end
end
local was_drop_blocked = piece:isDropBlocked(grid)
if self:canPieceRotate(piece, grid) then
-- if not self.held_rotate then
-- self:attemptRotate(inputs, piece, grid, initial)
-- self.held_rotate = true
-- else
self:attemptRotate(new_inputs, piece, grid, initial, lastdir)
-- end
end
if not initial and not was_drop_blocked and piece:isDropBlocked(grid) then
PlaySE("bottom")
end
-- prev_inputs becomes the previous inputs
for input, value in pairs(inputs) do
prev_inputs[input] = inputs[input]
end
end
function Rotation:attemptRotate(new_inputs, piece, grid, initial, lastdir)
local rot_dir = 0
if (new_inputs["rotate_left"] or new_inputs["rotate_left2"]) then
rot_dir = 3
if lastdir == 0 then lastdir = -1 end
elseif (new_inputs["rotate_right"] or new_inputs["rotate_right2"]) then
rot_dir = 1
if lastdir == 0 then lastdir = 1 end
end
if rot_dir == 0 then return end
local new_piece = piece:withRelativeRotation(rot_dir)
self:attemptWallkicks(piece, new_piece, rot_dir, grid, lastdir)
end
function Rotation:attemptWallkicks(piece, new_piece, rot_dir, grid, lastdir)
-- wallkick routine designed to maximize flexibility while minimizing teleports
-- O doesn't kick
if (piece.shape == "O") then return end
-- assess precisely what rows/columns would be blocked given the desired rotation
local sides = {top=false,uright=false,lright=false,uleft=false,lleft=false,center=false,bottom=false}
local left_exists = false
local right_exists = false
local kick = {x=0,y=0}
for _,offset in pairs(new_piece:getBlockOffsets()) do
local x = piece.position.x + offset.x
local y = piece.position.y + offset.y
if offset.x == 0 then left_exists = true end
if offset.x >= 4 and offset.x <= 7 then right_exists = true end
-- Read rotation.lua line 141 for original implementation
-- As where everything here are double-sized so the position is shifted
if grid:isOccupied(x,y) then
if (offset.y == 0 or offset.y == 1) then sides.top = true end
if (offset.y == 6 or offset.y == 7) then sides.bottom = true end
if (offset.y == 2 or offset.y == 3) and (offset.x == 0 or offset.x == 1) then sides.uleft = true end
if (offset.y == 4 or offset.y == 5) and (offset.x == 0 or offset.x == 1) then sides.lleft = true end
if (offset.y == 2 or offset.y == 3) and (offset.x >= 4 and offset.x <= 7) then sides.uright = true end
if (offset.y == 4 or offset.y == 5) and (offset.x >= 4 and offset.x <= 7) then sides.lright = true end
if (offset.x == 2 or offset.x == 3) then sides.center = true end
end
end
if sides.top then kick = {x=0,y=2}
elseif (sides.uleft and sides.lright) or (sides.uright and sides.lleft) or (sides.uright and sides.uleft) then kick = {x=0,y=2}
elseif (sides.lleft and sides.lright) then kick = {x=0,y=-2}
elseif (sides.lleft or sides.uleft) then kick = {x=2,y=0}
elseif (sides.lright or sides.uright) then kick = {x=-2,y=0}
elseif sides.center and left_exists then kick = {x=2,y=0}
elseif sides.center and right_exists then kick = {x=-2,y=0}
elseif sides.bottom then kick = {x=0,y=-2}
end
-- Attempt to push the piece 2 blocks away since it is in double size
local kick_double = {x=kick.x*2, y=kick.y*2}
if grid:canPlacePiece(new_piece:withOffset({x=0,y=0})) then
self:onPieceRotate(piece, grid)
piece:setRelativeRotation(rot_dir):setOffset({x=0,y=0})
elseif grid:canPlacePiece(new_piece:withOffset(kick)) then
self:onPieceRotate(piece, grid)
piece:setRelativeRotation(rot_dir):setOffset(kick)
elseif grid:canPlacePiece(new_piece:withOffset(kick_double)) then
-- self:onPieceRotate(piece, grid)
-- piece:setRelativeRotation(rot_dir):setOffset(kick_double)
end
end
function Rotation:movePiece(piece, grid, move, instant)
local was_drop_blocked = piece:isDropBlocked(grid)
local offset = ({x=0, y=0})
local moves = 0
local y = piece.position.y
if move == "left" then
offset.x = -1
moves = 1
elseif move == "right" then
offset.x = 1
moves = 1
elseif move == "speedleft" then
offset.x = -1
moves = grid.width
elseif move == "speedright" then
offset.x = 1
moves = grid.width
end
if not self:canPieceMove(piece, grid) then return end
for i = 1, moves do
local x = piece.position.x
if moves ~= 1 then
piece:moveInGrid(offset, 1, grid, instant)
else
piece:moveInGrid(offset, 1, grid, false)
end
if piece.position.x ~= x then
self:onPieceMove(piece, grid)
if piece.locked then break end
end
end
if not was_drop_blocked and piece:isDropBlocked(grid) then
PlaySE("bottom")
end
end
function Rotation:dropPiece(
inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked,
hard_drop_enabled, additive_gravity, classic_lock
)
local y = piece.position.y
if inputs["down"] == true and drop_locked == false then
piece:addGravity(math.max(gravity, drop_speed), grid, classic_lock)
else
piece:addGravity(gravity, grid, classic_lock)
end
if piece.position.y ~= y then
self:onPieceDrop(piece, grid)
end
end
function Rotation:lockPiece(piece, grid, lock_delay, classic_lock)
if piece:isDropBlocked(grid) and piece.lock_delay >= lock_delay then
piece.locked = true
end
end
function Rotation:get180RotationValue() return 3 end
function Rotation:getDefaultOrientation() return 1 end
function Rotation:getDrawOffset(shape, orientation) return { x=0, y=0 } end
function Rotation:getAboveFieldOffset(shape, orientation)
if shape == "I" then
return 1
else
return 2
end
end
function Rotation:initializePiece(
inputs, data, grid, gravity, prev_inputs,
move, lock_delay, drop_speed,
drop_locked, hard_drop_locked, big, irs, lastdir
)
local spawn_positions
spawn_positions = self.spawn_positions
local colours
colours = self.colourscheme
self.last_dir = 0
self.held_rotate = false
if inputs['left'] then self.last_dir = -1
elseif inputs['right'] then self.last_dir = 1 end
local spawn_x = math.floor(spawn_positions[data.shape].x / 10 * grid.width)
local spawn_dy
spawn_dy = 0
local piece = Piece(data.shape, data.orientation - 1, {
x = spawn_x or spawn_positions[data.shape].x,
y = spawn_positions[data.shape].y - spawn_dy
}, self.block_offsets, 0, 0, data.skin, colours[data.shape], big)
self:onPieceCreate(piece)
if irs then
self:rotatePiece(inputs, piece, grid, {}, true, lastdir)
end
return piece
end
function Rotation:onPieceCreate(piece) end
function Rotation:processPiece(
inputs, piece, grid, gravity, prev_inputs,
move, lock_delay, drop_speed,
drop_locked, hard_drop_locked,
hard_drop_enabled, additive_gravity, classic_lock, lastdir
)
self:rotatePiece(inputs, piece, grid, prev_inputs, false, lastdir)
self:movePiece(piece, grid, move, gravity >= grid.height)
self:dropPiece(
inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked,
hard_drop_enabled, additive_gravity, classic_lock
)
self:lockPiece(piece, grid, lock_delay, classic_lock)
end
function Rotation:canPieceMove(piece, grid) return true end
function Rotation:canPieceRotate(piece, grid) return true end
function Rotation:onPieceMove(piece) end
function Rotation:onPieceRotate(piece) end
function Rotation:onPieceDrop(piece)
if piece.position.y > piece.lowest_point then
piece.lock_delay = 0
piece.lowest_point = piece.position.y
end
end
return Rotation