mirror of
https://gitea.com/SweetSea-ButImNotSweet/tromi_mobile.git
synced 2025-01-08 17:33:09 +08:00
288 lines
9.2 KiB
Lua
288 lines
9.2 KiB
Lua
local Object = require 'libs.classic'
|
|
local Piece = require 'game.piece'
|
|
|
|
local Rotation = Object:extend()
|
|
|
|
Rotation.spawn_positions = {
|
|
I = { x=3, y= -2 },
|
|
J = { x=3, y= -2 },
|
|
L = { x=3, y= -2 },
|
|
O = { x=3, y= -2 },
|
|
S = { x=3, y= -2 },
|
|
T = { x=3, y= -2 },
|
|
Z = { x=3, y= -2 },
|
|
}
|
|
|
|
Rotation.colourscheme = {
|
|
I = "R",
|
|
L = "O",
|
|
J = "B",
|
|
S = "M",
|
|
Z = "G",
|
|
O = "Y",
|
|
T = "C",
|
|
}
|
|
|
|
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=2, y=0}, {x=2, y=1}, {x=2, y=2}, {x=2, y=3}, {x=2, y=4} },
|
|
{ {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2}, {x=4, y=2} },
|
|
{ {x=2, y=0}, {x=2, y=1}, {x=2, y=2}, {x=2, y=3}, {x=2, y=4} },
|
|
},
|
|
J={
|
|
{ {x=0, y=2}, {x=1, y=2}, {x=2, y=2}, {x=2, y=3}, {x=3, y=2} },
|
|
{ {x=1, y=0}, {x=1, y=1}, {x=1, y=2}, {x=0, y=2}, {x=1, y=3} },
|
|
{ {x=1, y=2}, {x=1, y=3}, {x=2, y=3}, {x=3, y=3}, {x=0, y=3} },
|
|
{ {x=1, y=1}, {x=2, y=1}, {x=1, y=2}, {x=1, y=3}, {x=1, y=0} },
|
|
},
|
|
L={
|
|
{ {x=0, y=2}, {x=0, y=3}, {x=1, y=2}, {x=2, y=2}, {x=3, y=2} },
|
|
{ {x=0, y=0}, {x=1, y=0}, {x=1, y=1}, {x=1, y=2}, {x=1, y=3} },
|
|
{ {x=1, y=3}, {x=2, y=3}, {x=3, y=2}, {x=3, y=3}, {x=0, y=3} },
|
|
{ {x=1, y=1}, {x=1, y=2}, {x=1, y=3}, {x=2, y=3}, {x=1, y=0} },
|
|
},
|
|
O={
|
|
{ {x=0, y=2}, {x=0, y=3}, {x=1, y=2}, {x=2, y=2}, {x=1, y=3} },
|
|
{ {x=0, y=1}, {x=1, y=1}, {x=1, y=2}, {x=1, y=3}, {x=0, y=2} },
|
|
{ {x=0, y=3}, {x=1, y=3}, {x=2, y=2}, {x=2, y=3}, {x=1, y=2} },
|
|
{ {x=1, y=1}, {x=1, y=2}, {x=1, y=3}, {x=2, y=3}, {x=2, y=2} },
|
|
},
|
|
S={
|
|
{ {x=1, y=2}, {x=2, y=2}, {x=0, y=3}, {x=1, y=3}, {x=3, y=2} },
|
|
{ {x=0, y=0}, {x=0, y=1}, {x=1, y=1}, {x=1, y=2}, {x=1, y=3} },
|
|
{ {x=2, y=2}, {x=3, y=2}, {x=1, y=3}, {x=2, y=3}, {x=0, y=3} },
|
|
{ {x=1, y=1}, {x=1, y=2}, {x=2, y=2}, {x=2, y=3}, {x=1, y=0} },
|
|
},
|
|
T={
|
|
{ {x=0, y=2}, {x=1, y=2}, {x=1, y=3}, {x=2, y=2}, {x=3, y=2} },
|
|
{ {x=0, y=1}, {x=1, y=0}, {x=1, y=1}, {x=1, y=2}, {x=1, y=3} },
|
|
{ {x=1, y=3}, {x=2, y=2}, {x=2, y=3}, {x=3, y=3}, {x=0, y=3} },
|
|
{ {x=2, y=1}, {x=2, y=2}, {x=3, y=2}, {x=2, y=3}, {x=2, y=0} },
|
|
},
|
|
Z={
|
|
{ {x=0, y=2}, {x=1, y=2}, {x=1, y=3}, {x=2, y=3}, {x=2, y=2} },
|
|
{ {x=1, y=1}, {x=0, y=2}, {x=1, y=2}, {x=0, y=3}, {x=1, y=3} },
|
|
{ {x=0, y=2}, {x=1, y=2}, {x=1, y=3}, {x=2, y=3}, {x=0, y=3} },
|
|
{ {x=2, y=1}, {x=1, y=2}, {x=2, y=2}, {x=1, y=3}, {x=1, y=1} },
|
|
}
|
|
}
|
|
|
|
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)
|
|
-- 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 grid:isOccupied(x,y) then
|
|
if offset.y <= 1 then sides.top = true end
|
|
if offset.y == 4 then sides.bottom = true end
|
|
if offset.x <= 1 then sides.lleft = true end
|
|
if offset.x >= 2 then sides.lright = true end
|
|
end
|
|
end
|
|
|
|
if sides.top then kick = {x=0,y=1}
|
|
elseif sides.bottom then kick = {x=0,y=-1}
|
|
elseif (sides.lleft or sides.uleft) then kick = {x=1,y=0}
|
|
elseif (sides.lright or sides.uright) then kick = {x=-1,y=0}
|
|
end
|
|
|
|
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({x=kick.x*2,y=kick.y*2})) then
|
|
self:onPieceRotate(piece, grid)
|
|
piece:setRelativeRotation(rot_dir):setOffset({x=kick.x*2,y=kick.y*2})
|
|
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
|