cambridge/tetris/components/piece.lua
Oshisaure 05230ac046 Game settings screen, and minor fix on discordRPC
- Uses BG previously from the input config screen, which has gotten a new BG
- Minor tweak on the input config screen to display all inputs names regardless of if they are bound or not
- Added Mod1 function to `funcs.lua`, may be useful again sometime
- Added game settings
  * Manual locking (per gamemode, per ruleset, on harddrop or on softdrop)
  * Piece colours (per ruleset, TTC or Arika)
  * World Reverse toggle
- Moved the discordRPC `libs/` directory, as it's a third party library
- Edited the `discordRPC.lua` file to look for the dll at the right place regardless of how you run the game (until we fuse it that is)

This should have probably been done in several commits, sorry about that
2020-10-11 00:42:56 +01:00

167 lines
4.2 KiB
Lua

local Object = require 'libs.classic'
local Piece = Object:extend()
function Piece:new(shape, rotation, position, block_offsets, gravity, lock_delay, skin, colour, big)
self.shape = shape
self.rotation = rotation
self.position = position
self.block_offsets = block_offsets
self.gravity = gravity
self.lock_delay = lock_delay
self.skin = skin
self.colour = colour
self.ghost = false
self.locked = false
self.big = big
end
-- Functions that return a new piece to test in rotation systems.
function Piece:withOffset(offset)
return Piece(
self.shape, self.rotation,
{x = self.position.x + offset.x, y = self.position.y + offset.y},
self.block_offsets, self.gravity, self.lock_delay, self.skin, self.colour, self.big
)
end
function Piece:withRelativeRotation(rot)
local new_rot = self.rotation + rot
while new_rot < 0 do new_rot = new_rot + 4 end
while new_rot >= 4 do new_rot = new_rot - 4 end
return Piece(
self.shape, new_rot, self.position,
self.block_offsets, self.gravity, self.lock_delay, self.skin, self.colour, self.big
)
end
-- Functions that return predicates relative to a grid.
function Piece:getBlockOffsets()
return self.block_offsets[self.shape][self.rotation + 1]
end
function Piece:occupiesSquare(x, y)
local offsets = self:getBlockOffsets()
for index, offset in pairs(offsets) do
local new_offset = {x = self.position.x + offset.x, y = self.position.y + offset.y}
if new_offset.x == x and new_offset.y == y then
return true
end
end
return false
end
function Piece:isMoveBlocked(grid, offset)
local moved_piece = self:withOffset(offset)
return not grid:canPlacePiece(moved_piece)
end
function Piece:isDropBlocked(grid)
return self:isMoveBlocked(grid, { x=0, y=1 })
end
-- Procedures to actually do stuff to pieces.
function Piece:setOffset(offset)
self.position.x = self.position.x + offset.x
self.position.y = self.position.y + offset.y
return self
end
function Piece:setRelativeRotation(rot)
new_rot = self.rotation + rot
while new_rot < 0 do new_rot = new_rot + 4 end
while new_rot >= 4 do new_rot = new_rot - 4 end
self.rotation = new_rot
return self
end
function Piece:moveInGrid(step, squares, grid)
local moved = false
for x = 1, squares do
if grid:canPlacePiece(self:withOffset(step)) then
moved = true
self:setOffset(step)
else
break
end
end
if moved and step.y == 0 then playSE("move") end
return self
end
function Piece:dropSquares(dropped_squares, grid)
self:moveInGrid({ x = 0, y = 1 }, dropped_squares, grid)
end
function Piece:dropToBottom(grid)
local piece_y = self.position.y
self:dropSquares(24, grid)
self.gravity = 0
if self.position.y > piece_y then
-- if it got dropped any, also reset lock delay
if self.ghost == false then playSE("bottom") end
self.lock_delay = 0
end
return self
end
function Piece:lockIfBottomed(grid)
if self:isDropBlocked(grid) then
self.locked = true
end
return self
end
function Piece:addGravity(gravity, grid)
local new_gravity = self.gravity + gravity
if self:isDropBlocked(grid) then
self.gravity = math.min(1, new_gravity)
self.lock_delay = self.lock_delay + 1
else
local dropped_squares = math.floor(new_gravity)
local new_frac_gravity = new_gravity - dropped_squares
self.gravity = new_frac_gravity
self:dropSquares(dropped_squares, grid)
if self:isDropBlocked(grid) then
playSE("bottom")
end
end
return self
end
-- Procedures for drawing.
function Piece:draw(opacity, brightness, grid, partial_das)
if opacity == nil then opacity = 1 end
if brightness == nil then brightness = 1 end
love.graphics.setColor(brightness, brightness, brightness, opacity)
local offsets = self:getBlockOffsets()
local gravity_offset = 0
--if grid ~= nil and not self:isDropBlocked(grid) then
-- gravity_offset = self.gravity * 16
--end
if partial_das == nil then partial_das = 0 end
for index, offset in pairs(offsets) do
local x = self.position.x + offset.x
local y = self.position.y + offset.y
if self.big then
love.graphics.draw(
blocks[self.skin][self.colour],
64+x*32+partial_das*2, 16+y*32+gravity_offset*2,
0, 2, 2
)
else
love.graphics.draw(
blocks[self.skin][self.colour],
64+x*16+partial_das, 16+y*16+gravity_offset
)
end
end
return false
end
return Piece