16 Commits

Author SHA1 Message Date
SweetSea
d3b63569dc Fix rotation kicks and hope it works 2024-10-27 14:45:27 +07:00
SweetSea
af659a69fe Fix basic rotation and add attempt to do 2nd wallkick before failed 2024-10-27 06:05:19 +07:00
SweetSea
7eb445e2c6 Merge commit '0e8d3ceacc6b68c11498dd6f6d9ee204d2699a05' into big_experimental 2024-10-27 06:01:01 +07:00
SweetSea
0e8d3ceacc Merge https://gitea.com/SweetSea-ButImNotSweet/tromi_mobile 2024-10-27 05:58:03 +07:00
SweetSea
b73c82c765 Fix scene stack and bump ver 2024-10-27 05:56:40 +07:00
SweetSea
c8665d06f0 First commit 2024-10-26 23:29:10 +07:00
SweetSea-ButImNotSweet
d7d9f77127 Fix buttons in replay scene broken
Signed-off-by: SweetSea-ButImNotSweet <sweetsea-butimnotsweet@noreply.gitea.com>
2024-10-06 12:17:44 +00:00
Nguyễn Quốc Hưng
c0089fc4a5 Multiple changes
- Fix softlock in Name entry
- Wrong page count in Replay scene
- Last key can't be ignored by other controllers
- Small B.T.S changes
2024-10-06 16:57:49 +07:00
Nguyễn Quốc Hưng
1f5a21fec4 Cleaning stuffs 2024-08-17 16:11:42 +07:00
Nguyễn Quốc Hưng
628cf22110 Add user management scene 2024-08-17 16:10:52 +07:00
Nguyễn Quốc Hưng
0647babc90 Fix player's info is not updated correctly when changing name 2024-08-16 09:06:43 +07:00
Nguyễn Quốc Hưng
c29b97cece Fix wrong saving bind place 2024-08-11 10:12:57 +07:00
Nguyễn Quốc Hưng
78501f368c Update both key and stick configuration scenes 2024-08-10 17:13:43 +07:00
Nguyễn Quốc Hưng
e6388c79bc Attempt to fix, one again 2024-08-10 16:53:49 +07:00
Nguyễn Quốc Hưng
e4e43ec61e Fix dumb error 2024-08-10 14:45:22 +07:00
Nguyễn Quốc Hưng
0eb274436e Attempt to fix broken button 2024-08-10 14:34:08 +07:00
17 changed files with 862 additions and 151 deletions

View File

@@ -13,7 +13,7 @@ local GameMode = Object:extend()
function GameMode:new(player_name, input_file, replay_grade) function GameMode:new(player_name, input_file, replay_grade)
VCTRL.toggle(MOBILE and not input_file and not SETTINGS.tvMode) VCTRL.toggle(MOBILE and not input_file and not SETTINGS.tvMode)
VCTRL.reset() VCTRL.reset()
if player_name == nil then self.training = true else self.training = false end if player_name == nil then self.training = true else self.training = false end
if input_file ~= nil then if input_file ~= nil then
input_file = love.filesystem.read(REPLAY_DIR..input_file) input_file = love.filesystem.read(REPLAY_DIR..input_file)
@@ -59,7 +59,7 @@ function GameMode:new(player_name, input_file, replay_grade)
self.did_grades = false self.did_grades = false
self.active_frames = 0 self.active_frames = 0
self.total_lines = 0 self.total_lines = 0
self.lineClearPoints = {[0]=0, 0, 1667, 3750, 6668, 8335} self.lineClearPoints = {[0]=0, 0, 1667, 3750, 6668, 8335, 10418, 13336, 15003, 17086}
self.gradeNames = { self.gradeNames = {
"19k", "18k", "17k", "16k", "15k", "14k", "13k", "12k", "11k", "10k", "19k", "18k", "17k", "16k", "15k", "14k", "13k", "12k", "11k", "10k",
"9k", "8k", "7k", "6k", "5k", "4k", "3k", "2k", "1k", "9k", "8k", "7k", "6k", "5k", "4k", "3k", "2k", "1k",

View File

@@ -81,6 +81,7 @@ function Grid:getClearedRowCount()
table.insert(cleared_row_table, row) table.insert(cleared_row_table, row)
end end
end end
if BIG_MODE or PENTO_MODE then count = count * 0.5 end
return count, cleared_row_table return count, cleared_row_table
end end

481
game/rotation_big.lua Normal file
View File

@@ -0,0 +1,481 @@
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

View File

@@ -40,6 +40,7 @@ function love.load()
require "game.vctrl" -- VCTRL require "game.vctrl" -- VCTRL
SCENE = LoadingScene() SCENE = LoadingScene()
sceneStack = {SCENE}
VCTRL.new(SETTINGS.input.virtual) VCTRL.new(SETTINGS.input.virtual)
end end
@@ -124,7 +125,6 @@ function love.keypressed(key, scancode)
love.resize(love.graphics.getDimensions()) love.resize(love.graphics.getDimensions())
elseif scancode == "f2" and SCENE.title ~= "Input Config" and SCENE.title ~= "Game" then elseif scancode == "f2" and SCENE.title ~= "Input Config" and SCENE.title ~= "Game" then
SCENE = InputConfigScene() SCENE = InputConfigScene()
elseif scancode == "f3" then SCENE = UserManagementScene()
elseif scancode == "f12" then LLDEBUGGER.requestBreak() elseif scancode == "f12" then LLDEBUGGER.requestBreak()
-- elseif scancode == "f11" then SETTINGS.firstTime = true -- elseif scancode == "f11" then SETTINGS.firstTime = true
-- function keys are reserved -- function keys are reserved
@@ -309,6 +309,7 @@ function love.run()
end end
end end
if SCENE and SCENE.update and love.timer then if SCENE and SCENE.update and love.timer then
SCENE:update() SCENE:update()
@@ -413,7 +414,7 @@ function love.errorhandler(msg)
love.graphics.setColor(1, 1, 1) love.graphics.setColor(1, 1, 1)
love.graphics.draw(screenshot_canva, 0, 0, 0, screenshot_canva_scale) love.graphics.draw(screenshot_canva, 0, 0, 0, screenshot_canva_scale)
if not showScreenshot then if not showScreenshot then
love.graphics.setColor(0, 0, 0, 0.75) love.graphics.setColor(0, 0, 0, 0.75)
love.graphics.rectangle("fill", 0, 0, 640, 480) love.graphics.rectangle("fill", 0, 0, 640, 480)
@@ -569,6 +570,5 @@ function MainBackground()
while main_bg_cur_color == main_bg_last_color do main_bg_cur_color = minos[love.math.random(1,7)] end while main_bg_cur_color == main_bg_last_color do main_bg_cur_color = minos[love.math.random(1,7)] end
main_bg_cur_mino = 1 main_bg_cur_mino = 1
end end
main_bg_placed = false
main_bg_draw_frame = main_bg_draw_frame + 1 main_bg_draw_frame = main_bg_draw_frame + 1
end end

View File

@@ -76,6 +76,7 @@ SettingsScene = require "scene.settings"
EraseHighScoresScene = require "scene.data.erase_high_scores" EraseHighScoresScene = require "scene.data.erase_high_scores"
ResetAllScene = require "scene.data.reset_all" ResetAllScene = require "scene.data.reset_all"
DataManagementScene = require "scene.data_management" DataManagementScene = require "scene.data_management"
UserManagementScene = require "scene.user_management"
ReplaySelectScene = require "scene.replay" ReplaySelectScene = require "scene.replay"
ReplayTestScene = require"scene.replay_test" ReplayTestScene = require"scene.replay_test"

View File

@@ -26,7 +26,7 @@ local data_explaination = {
local NULL = function() end local NULL = function() end
local settings_func = { local settings_func = {
function() love.system.openURL(love.filesystem.getSaveDirectory()) end, function() love.system.openURL(love.filesystem.getSaveDirectory()) end,
NULL, function() return UserManagementScene() end,
function() return EraseHighScoresScene() end, function() return EraseHighScoresScene() end,
function() return ResetAllScene() end, function() return ResetAllScene() end,
function() return TitleScene() end, function() return TitleScene() end,

View File

@@ -58,11 +58,11 @@ function GameScene:new(player_name, replay_file, replay_grade)
game_mode = require 'game.gamemode' game_mode = require 'game.gamemode'
if PENTO_MODE then if PENTO_MODE then
ruleset = require 'game.rotation_pent' ruleset = require 'game.rotation_big'
else else
ruleset = require 'game.rotation' ruleset = require 'game.rotation'
end end
self.retry_mode = game_mode self.retry_mode = game_mode
self.retry_ruleset = ruleset self.retry_ruleset = ruleset
-- self.secret_inputs = inputs -- self.secret_inputs = inputs

View File

@@ -71,7 +71,7 @@ function ConfigScene:new(first_time)
secret_code_used = false secret_code_used = false
secret_code_input = {} -- When it matches 88663366 then we will automatically set the special keybind secret_code_input = {} -- When it matches 88663366 then we will automatically set the special keybind
self.menu_state = 1 self.menu_state = 1
if first_time then if first_time then
self.first_time = true self.first_time = true
@@ -84,15 +84,18 @@ function ConfigScene:update() end
function ConfigScene:render() function ConfigScene:render()
MainBackground() MainBackground()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 0, 0, 640, 480)
if secret_code_used then if secret_code_used then
if SETTINGS.tvMode then if SETTINGS.tvMode then
drawText("TV mode is ON now! Check keybind below", 80, 40, 1000) drawText("TV mode is ON now! Check keybind below", 80, 40, 1000)
drawText("Which controls do you want to configure?", 80, 70, 1000) drawText("Which controls do you want to configure?", 80, 70, 1000)
drawText( drawText(
"2 - Up 1 - Rotate left 5 - Confirm selection\n".. "2 - Up 1 - Rotate left 5 - Confirm selection\n"..
"8 - Right 3 - Rotate right 0 - Back\n".. "8 - Down 3 - Rotate right 0 - Back\n"..
"4 - Left 7 - Rotate left 2\n".. "4 - Left 7 - Rotate left 2\n"..
"6 - Down 9 - Rotate right 2", 80, 350, 1000 "6 - Right 9 - Rotate right 2", 80, 350, 1000
) )
else else
drawText("TV mode is OFF now!", 80, 40, 1000) drawText("TV mode is OFF now!", 80, 40, 1000)
@@ -132,7 +135,7 @@ local function checkSecretCodeInput(key)
if secret_code_used then return end if secret_code_used then return end
if key:sub(1, 2) == "kp" then if key:sub(1, 2) == "kp" then
table.insert(secret_code_input, key:sub(3,3)) table.insert(secret_code_input, key:sub(3,3))
elseif key:find("[0-9.]") == 1 then elseif key:find("[0-9]") == 1 then
table.insert(secret_code_input, key) table.insert(secret_code_input, key)
else else
secret_code_input = {} -- Reset secret_code_input = {} -- Reset
@@ -146,14 +149,14 @@ local function checkSecretCodeInput(key)
if current_code == "88663366" then --TVMODEON if current_code == "88663366" then --TVMODEON
-- Set keybind -- Set keybind
SETTINGS.input.keys = { SETTINGS.input.keys = {
["2"] = "up", ["kp2"] = "up", ["2"] = "up", ["kp8"] = "up",
["8"] = "down", ["kp8"] = "down", ["8"] = "down", ["kp2"] = "down",
["4"] = "left", ["kp4"] = "left", ["4"] = "left", ["kp4"] = "left",
["6"] = "right", ["kp6"] = "right", ["6"] = "right", ["kp6"] = "right",
["1"] = "rotate_left", ["kp1"] = "rotate_left", ["1"] = "rotate_left", ["kp7"] = "rotate_left",
["3"] = "rotate_right", ["kp3"] = "rotate_right", ["3"] = "rotate_right", ["kp9"] = "rotate_right",
["7"] = "rotate_left2", ["kp7"] = "rotate_left2", ["7"] = "rotate_left2", ["kp1"] = "rotate_left2",
["9"] = "rotate_right2", ["kp9"] = "rotate_right2", ["9"] = "rotate_right2", ["kp3"] = "rotate_right2",
["5"] = "menu_decide", ["kp5"] = "menu_decide", ["5"] = "menu_decide", ["kp5"] = "menu_decide",
["0"] = "menu_back", ["kp0"] = "menu_back", ["0"] = "menu_back", ["kp0"] = "menu_back",
} }
@@ -161,7 +164,7 @@ local function checkSecretCodeInput(key)
SETTINGS.tvMode = true SETTINGS.tvMode = true
secret_code_used = true secret_code_used = true
updateButtonList(SCENE) updateButtonList(SCENE)
elseif current_code == "........" then elseif current_code == "11111111" then
SETTINGS.input.keys = {} SETTINGS.input.keys = {}
SETTINGS.tvMode = false SETTINGS.tvMode = false
secret_code_used = true secret_code_used = true

View File

@@ -27,7 +27,6 @@ local input_names = {
rotate_right2='Rotate Clockwise (2)' rotate_right2='Rotate Clockwise (2)'
} }
local function newSetInputs() local function newSetInputs()
local set_inputs = {} local set_inputs = {}
for i, input in ipairs(configurable_inputs) do for i, input in ipairs(configurable_inputs) do
@@ -40,47 +39,40 @@ function KeyConfigScene:new()
self.input_state = 1 self.input_state = 1
self.set_inputs = newSetInputs() self.set_inputs = newSetInputs()
self.new_input = {} self.new_input = {}
self.axis_timer = 0
BUTTON.reset(buttonList) BUTTON.reset(buttonList)
buttonList = { -- Configuring buttonList = { -- Configuring
BUTTON.new{ BUTTON.new{
text = CHAR.icon.fastForward.." SKIP", text = CHAR.key.tab.."\nTab",
x = 40, y = 300, w = 100, h = 30, x = 40, y = 300, w = 100, h = 50,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "tab"} end codeWhenReleased = function() self:onInputPress{type = "key", scancode = "tab"} end
}, },
BUTTON.new{ BUTTON.new{
text = CHAR.icon.cross_thick.." Cancel", text = CHAR.key.enter_or_return.."\nEnter/Return",
x = 150, y = 300, w = 100, h = 30, x = 150, y = 300, w = 100, h = 50,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "return"} end
},
BUTTON.new{
text = CHAR.key.del.."\nDelete",
x = 260, y = 300, w = 100, h = 50,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "delete"} end
},
BUTTON.new{
text = CHAR.key.esc.."\nEscape",
x = 370, y = 300, w = 100, h = 50,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "escape"} end codeWhenReleased = function() self:onInputPress{type = "key", scancode = "escape"} end
}, },
} }
end end
function KeyConfigScene:update() function KeyConfigScene:update()
if self.input_state > #configurable_inputs then
BUTTON.reset(buttonList)
buttonList = { -- Confirming
BUTTON.new{
text = CHAR.icon.checkMark.." CONFIRM",
x = 40, y = 300, w = 100, h = 30,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "return"} end
},
BUTTON.new{
text = CHAR.icon.retry_spin.." Restart",
x = 150, y = 300, w = 100, h = 30,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "delete"} end
},
BUTTON.new{
text = CHAR.icon.cross_thick.." Cancel",
x = 260, y = 300, w = 100, h = 30,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "escape"} end
}
}
end
end end
function KeyConfigScene:render() function KeyConfigScene:render()
MainBackground() MainBackground()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 0, 0, 640, 480)
BUTTON.draw(buttonList) BUTTON.draw(buttonList)
for i, input in ipairs(configurable_inputs) do for i, input in ipairs(configurable_inputs) do
@@ -90,10 +82,10 @@ function KeyConfigScene:render()
end end
end end
if self.input_state > #configurable_inputs then if self.input_state > #configurable_inputs then
drawText("Press Enter/Confirm Selection to confirm, delete/backspace to retry" .. (SETTINGS.input.keys and ", esc/Go Back to cancel" or ""),0,0,1000) drawText("Press Enter/Confirm Selection to confirm, Delete/Backspace to retry" .. (SETTINGS.input.keys and ", Esc/Go Back to cancel" or ""), 0, 0, 1000)
else else
drawText("Press key input for " .. input_names[configurable_inputs[self.input_state]] .. ", escape to cancel\nPress tab on keyboard, or any key from other inputs, to skip",0,0,1000) drawText("Press key input for " .. input_names[configurable_inputs[self.input_state]] .. ", escape to cancel\nPress tab on keyboard, or any key from other inputs, to skip",0,0,1000)
drawText("Function keys (F1, F2, etc.), escape, and tab can't be changed", 0, 35,1000) drawText("Function keys (F1, F2, etc.), Escape, and Tab can't be changed", 0, 35,1000)
end end
end end
@@ -121,7 +113,7 @@ function KeyConfigScene:onInputPress(e)
self.new_input[e.scancode] = configurable_inputs[self.input_state] self.new_input[e.scancode] = configurable_inputs[self.input_state]
self.input_state = self.input_state + 1 self.input_state = self.input_state + 1
end end
elseif self.input_state < #configurable_inputs then elseif self.input_state <= #configurable_inputs then
self.set_inputs[configurable_inputs[self.input_state]] = "skipped" self.set_inputs[configurable_inputs[self.input_state]] = "skipped"
self.input_state = self.input_state + 1 self.input_state = self.input_state + 1
end end

View File

@@ -37,7 +37,7 @@ local Grid = require 'game.grid'
function NameEntryScene:new() function NameEntryScene:new()
VCTRL.toggle(false) VCTRL.toggle(false)
self.chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890." self.chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890."
self.char_pos = 1 self.char_pos = 1
self.name_entry = {'A','A','A'} self.name_entry = {'A','A','A'}
@@ -79,7 +79,7 @@ end
function NameEntryScene:render() function NameEntryScene:render()
MainBackground() MainBackground()
BUTTON.draw(buttonList) BUTTON.draw(buttonList)
love.graphics.setColor(1, 1, 1, 1) love.graphics.setColor(1, 1, 1, 1)
love.graphics.line(216,80,216,80+(16*self.grid.height)) love.graphics.line(216,80,216,80+(16*self.grid.height))
love.graphics.line(216+(16*self.grid.width),80,216+(16*self.grid.width),80+(16*self.grid.height)) love.graphics.line(216+(16*self.grid.width),80,216+(16*self.grid.width),80+(16*self.grid.height))
@@ -153,17 +153,6 @@ function NameEntryScene:onInputPress(e)
local name = string.lower(table.concat(self.name_entry, '', 1, 3)) local name = string.lower(table.concat(self.name_entry, '', 1, 3))
if e.type == "mouse" or e.type == "touch" then if e.type == "mouse" or e.type == "touch" then
BUTTON.press(buttonList, e.x, e.y, e.id) BUTTON.press(buttonList, e.x, e.y, e.id)
elseif e.key and #e.key == 1 then
local pos = string.find(self.chars, string.upper(e.key), 1, true)
if pos then
if self.entry_pos <= 3 then
self.char_pos = pos
self.name_entry[self.entry_pos] = string.upper(e.key)
self.name_entry[self.entry_pos + 1] = string.upper(e.key)
end
if self.entry_pos == 3 then self:getPlayInfo(name) end
self.entry_pos = math.min(self.entry_pos + 1, 4)
end
elseif e.input == "menu_decide" or e.input == "rotate_left" or e.scancode == "return" then elseif e.input == "menu_decide" or e.input == "rotate_left" or e.scancode == "return" then
if self.entry_pos == 4 then if self.entry_pos == 4 then
BUTTON.release(buttonList, e.x, e.y, e.id) BUTTON.release(buttonList, e.x, e.y, e.id)
@@ -190,6 +179,17 @@ function NameEntryScene:onInputPress(e)
self.entry_pos = self.entry_pos - 1 self.entry_pos = self.entry_pos - 1
self.grade = 0 self.grade = 0
end end
elseif e.key and #e.key == 1 then
local pos = string.find(self.chars, string.upper(e.key), 1, true)
if pos then
if self.entry_pos <= 3 then
self.char_pos = pos
self.name_entry[self.entry_pos] = string.upper(e.key)
self.name_entry[self.entry_pos + 1] = string.upper(e.key)
end
self.entry_pos = math.min(self.entry_pos + 1, 4)
if self.entry_pos == 4 then self:getPlayInfo(string.lower(table.concat(self.name_entry, '', 1, 3))) end
end
end end
end end

View File

@@ -1,67 +1,52 @@
local ReplaySelectScene = SCENE:extend() local ReplaySelectScene = SCENE:extend()
ReplaySelectScene.title = "Replay" ReplaySelectScene.title = "Replay"
local scene_self
local replay_list local replay_list
local buttonList = { local buttonList = {
BUTTON.new{ BUTTON.new{
x = 325, y = 385, w = 100, h = 30, x = 325, y = 375, w = 100, h = 30,
text = CHAR.key.up.." Page up", text = CHAR.key.up.." Page up",
codeWhenReleased = function() codeWhenReleased = function() SCENE:onInputPress{input = "left"} end
if scene_self.page == 1 then
scene_self.page = 1 + math.floor(#scene_self.replays / scene_self.page_flip)
else
scene_self.page = scene_self.page - 1
end
scene_self.replay_select = 1;
end
}, },
BUTTON.new{ BUTTON.new{
x = 435, y = 385, w = 100, h = 30, x = 435, y = 375, w = 100, h = 30,
text = CHAR.key.down.." Page down", text = CHAR.key.down.." Page down",
codeWhenReleased = function() codeWhenReleased = function() SCENE:onInputPress{input = "right"} end
if scene_self.page < 1 + math.floor(#scene_self.replays / scene_self.page_flip) then
scene_self.page = scene_self.page + 1
else
scene_self.page = 1
end
scene_self.replay_select = 1;
end
}, },
BUTTON.new{ BUTTON.new{
x = 105, y = 385, w = 100, h = 30, x = 105, y = 375, w = 100, h = 30,
text = CHAR.icon.play.." Play", text = CHAR.icon.play.." Play",
codeWhenPressed = function() scene_self:onInputPress {input = "menu_decide"} end, codeWhenPressed = function() SCENE:onInputPress {input = "menu_decide"} end,
codeWhenReleased = function() scene_self:onInputRelease{input = "menu_decide"} end codeWhenReleased = function() SCENE:onInputRelease{input = "menu_decide"} end
}, },
BUTTON.new{ BUTTON.new{
x = 105, y = 425, w = 100, h = 30, x = 105, y = 415, w = 100, h = 45,
text = CHAR.icon.home.." Home", text = CHAR.icon.home.." Home",
codeWhenPressed = function() scene_self:onInputPress {input = "menu_back"} end, codeWhenPressed = function() SCENE:onInputPress {input = "menu_back"} end,
codeWhenReleased = function() scene_self:onInputRelease{input = "menu_back"} end codeWhenReleased = function() SCENE:onInputRelease{input = "menu_back"} end
}, },
BUTTON.new{ BUTTON.new{
x = 215, y = 425, w = 100, h = 30, x = 215, y = 415, w = 100, h = 45,
text = CHAR.icon.save.." Converter", text = CHAR.icon.save.." Converter",
codeWhenReleased = function() love.system.openURL("https://sweetsea-butimnotsweet.github.io/tromi_replay_converter/") end codeWhenReleased = function() love.system.openURL("https://sweetsea-butimnotsweet.github.io/tromi_replay_converter/") end
}, },
BUTTON.new{ BUTTON.new{
x = 325, y = 425, w = 100, h = 30, x = 325, y = 415, w = 100, h = 45,
text = CHAR.icon.export.." Export", text = CHAR.icon.export.." Export\n(R.Left)",
codeWhenPressed = function() scene_self:onInputPress {input = "rotate_left"} end, codeWhenPressed = function() SCENE:onInputPress {input = "rotate_left"} end,
codeWhenReleased = function() scene_self:onInputRelease{input = "rotate_left"} end codeWhenReleased = function() SCENE:onInputRelease{input = "rotate_left"} end
}, },
BUTTON.new{ BUTTON.new{
x = 435, y = 425, w = 100, h = 30, x = 435, y = 415, w = 100, h = 45,
text = CHAR.icon.import.." Import", text = CHAR.icon.import.." Import\n(R.Right)",
codeWhenPressed = function() scene_self:onInputPress {input = "rotate_right"} end, codeWhenPressed = function() SCENE:onInputPress {input = "rotate_right"} end,
codeWhenReleased = function() scene_self:onInputRelease{input = "rotate_right"} end codeWhenReleased = function() SCENE:onInputRelease{input = "rotate_right"} end
}, },
} }
function ReplaySelectScene:new() function ReplaySelectScene:new()
self:initList() self:initList()
scene_self = self SCENE = self
BUTTON.reset(buttonList) BUTTON.reset(buttonList)
PENTO_MODE = false PENTO_MODE = false
end end
@@ -103,29 +88,30 @@ function ReplaySelectScene:render()
love.graphics.setColor(0, 0, 0, 0.7) love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 0, 0, 640, 480) love.graphics.rectangle("fill", 0, 0, 640, 480)
love.graphics.setColor(0.4, 1, 1, 0.5)
love.graphics.rectangle("fill", 0, 15 + 30 * self.replay_select, 640, 27)
BUTTON.draw(buttonList) if #self.replays > 0 then
love.graphics.setColor(0.4, 1, 1, 0.5)
love.graphics.rectangle("fill", 0, 15 + 30 * self.replay_select, 640, 27)
drawText('Name - Grade - Score', 40, 20, 1000, "left") drawText('Name - Grade - Score', 40, 20, 1000, "left")
drawText(string.format('Page %s/%s', self.page, math.floor(#self.replays / self.page_flip) + 1), 215, 390, 100, "center") drawText(string.format('Page %s/%s', self.page, 1 + math.floor((#self.replays - 1) / self.page_flip)), 215, 380, 100, "center")
local i, j = 1, 1 local i, j = 1, 1
while i <= #self.replay_text do while i <= #self.replay_text do
if j > self.page_flip then j = 1 if j > self.page_flip then j = 1
elseif j < 1 then j = self.page_flip elseif j < 1 then j = self.page_flip
end
if i > (self.page-1) * self.page_flip and i <= self.page * self.page_flip then
drawText(self.replay_text[i], 40, 20 + 30 * j, 1000, "left")
end
j = j + 1
i = i + 1
end end
if i > (self.page-1) * self.page_flip and i <= self.page * self.page_flip then else
drawText(self.replay_text[i], 40, 20 + 30 * j, 1000, "left")
end
j = j + 1
i = i + 1
end
if self.replays[1] == nil then
drawText('No replays yet!', 40, 40, 1000, "left") drawText('No replays yet!', 40, 40, 1000, "left")
end end
BUTTON.draw(buttonList)
end end
function ReplaySelectScene:update() function ReplaySelectScene:update()
@@ -167,7 +153,11 @@ function ReplaySelectScene:onInputPress(e)
local selected_replay = self.replays[self.replay_select + ((self.page-1) * self.page_flip)] local selected_replay = self.replays[self.replay_select + ((self.page-1) * self.page_flip)]
local selected_replay_text = self.replay_text[self.replay_select + ((self.page-1) * self.page_flip)] local selected_replay_text = self.replay_text[self.replay_select + ((self.page-1) * self.page_flip)]
if (e.type == "touch" or e.type == "mouse") and not BUTTON.press(buttonList, e.x, e.y, e.id) then if (
(e.type == "touch" or e.type == "mouse") and
not BUTTON.press(buttonList, e.x, e.y, e.id) and
#self.replays > 0
) then
local selection = math.floor((e.y - 15) / 30) local selection = math.floor((e.y - 15) / 30)
if ( if (
selection >= 1 and selection >= 1 and
@@ -212,6 +202,22 @@ function ReplaySelectScene:onInputPress(e)
elseif e.input == "down" or e.scancode == "down" then elseif e.input == "down" or e.scancode == "down" then
if self.replays[1] == nil then SCENE = TitleScene(); return end if self.replays[1] == nil then SCENE = TitleScene(); return end
self.direction = 'down' self.direction = 'down'
elseif e.input == "left" or e.scancode == "left" then
if self.replays[1] == nil then SCENE = TitleScene(); return end
if self.page == 1 then
self.page = math.floor((#self.replays - 1) / self.page_flip)
else
self.page = self.page - 1
end
self.replay_select = 1;
elseif e.input == "right" or e.scancode == "right" then
if self.replays[1] == nil then SCENE = TitleScene(); return end
if self.page < 1 + math.floor((#self.replays - 1) / self.page_flip) then
self.page = self.page + 1
else
self.page = 1
end
self.replay_select = 1;
elseif e.input == "menu_back" or e.scancode == "backspace" or e.scancode == "delete" then elseif e.input == "menu_back" or e.scancode == "backspace" or e.scancode == "delete" then
SCENE = TitleScene() SCENE = TitleScene()
end end

View File

@@ -5,7 +5,6 @@ local error_message
local valid_data local valid_data
local prev_scene local prev_scene
function ReplayTestScene:new(input_file) function ReplayTestScene:new(input_file)
prev_scene = SCENE prev_scene = SCENE
@@ -36,7 +35,7 @@ function ReplayTestScene:render()
if valid_data then if valid_data then
if error_message then if error_message then
drawText("Replay test failed! Data corrupted!", 80, 40, 1000) drawText("Replay test failed!", 80, 40, 1000)
drawText("Press any key to go back. Anyway here is the error info:", 80, 70, 1000) drawText("Press any key to go back. Anyway here is the error info:", 80, 70, 1000)
drawText(error_message, 80, 100, 560) drawText(error_message, 80, 100, 560)
else else

View File

@@ -12,7 +12,7 @@ local settings_explaination = {
"Enable music?\nThis does not apply to sound effects.", "Enable music?\nThis does not apply to sound effects.",
"Show level and lines counter?\nThis setting is ignored when replaying.", "Show level and lines counter?\nThis setting is ignored when replaying.",
"Enter or leave fullscreen\nYou can press F4 key at any screen to do this quick.", "Enter or leave fullscreen\nYou can press F4 key at any screen to do this quick.",
"This is where you can re-configure your keybinds.\nYou can press F2 on the keyboard to open this quick\n\nTip for TV:\n\t88663366: enable TV mode.\n\t........: disable TV mode", "This is where you can re-configure your keybinds.\nYou can press F2 on the keyboard to open this quick\n\nTip for TV:\n\t88663366: enable TV mode.\n\t11111111 disable TV mode",
"Back to main menu" "Back to main menu"
} }

View File

@@ -44,43 +44,35 @@ function StickConfigScene:new()
BUTTON.reset(buttonList) BUTTON.reset(buttonList)
buttonList = { -- Configuring buttonList = { -- Configuring
BUTTON.new{ BUTTON.new{
text = CHAR.icon.fastForward.." SKIP", text = CHAR.key.tab.."\nTab",
x = 40, y = 300, w = 100, h = 30, x = 40, y = 300, w = 100, h = 50,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "tab"} end codeWhenReleased = function() self:onInputPress{type = "key", scancode = "tab"} end
}, },
BUTTON.new{ BUTTON.new{
text = CHAR.icon.cross_thick.." Cancel", text = CHAR.key.enter_or_return.."\nEnter/Return",
x = 150, y = 300, w = 100, h = 30, x = 150, y = 300, w = 100, h = 50,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "return"} end
},
BUTTON.new{
text = CHAR.key.del.."\nDelete",
x = 260, y = 300, w = 100, h = 50,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "delete"} end
},
BUTTON.new{
text = CHAR.key.esc.."\nEscape",
x = 370, y = 300, w = 100, h = 50,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "escape"} end codeWhenReleased = function() self:onInputPress{type = "key", scancode = "escape"} end
}, },
} }
end end
function StickConfigScene:update() function StickConfigScene:update()
if self.input_state > #configurable_inputs then
BUTTON.reset(buttonList)
buttonList = { -- Confirming
BUTTON.new{
text = CHAR.icon.checkMark.." CONFIRM",
x = 40, y = 300, w = 100, h = 30,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "return"} end
},
BUTTON.new{
text = CHAR.icon.retry_spin.." Restart",
x = 150, y = 300, w = 100, h = 30,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "delete"} end
},
BUTTON.new{
text = CHAR.icon.cross_thick.." Cancel",
x = 260, y = 300, w = 100, h = 30,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "escape"} end
}
}
end
end end
function StickConfigScene:render() function StickConfigScene:render()
MainBackground() MainBackground()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 0, 0, 640, 480)
BUTTON.draw(buttonList) BUTTON.draw(buttonList)
for i, input in ipairs(configurable_inputs) do for i, input in ipairs(configurable_inputs) do
@@ -90,7 +82,7 @@ function StickConfigScene:render()
end end
end end
if self.input_state > #configurable_inputs then if self.input_state > #configurable_inputs then
drawText("Press enter/Confirm Selection to confirm, delete/backspace to retry" .. (SETTINGS.input.joysticks and ", esc/Go Back to cancel" or ""), 0, 0, 1000) drawText("Press Enter/Confirm Selection to confirm, Delete/Backspace to retry" .. (SETTINGS.input.joysticks and ", Esc/Go Back to cancel" or ""), 0, 0, 1000)
else else
drawText("Press joystick input for " .. input_names[configurable_inputs[self.input_state]] .. ", tab to skip, escape to cancel", 0, 0, 1000) drawText("Press joystick input for " .. input_names[configurable_inputs[self.input_state]] .. ", tab to skip, escape to cancel", 0, 0, 1000)
end end
@@ -104,7 +96,6 @@ local function addJoystick(input, name)
end end
end end
---@param e SCENE_onInput
function StickConfigScene:onInputPress(e) function StickConfigScene:onInputPress(e)
if e.type == "mouse" or e.type == "touch" then if e.type == "mouse" or e.type == "touch" then
BUTTON.press(buttonList, e.x, e.y, e.id) BUTTON.press(buttonList, e.x, e.y, e.id)
@@ -114,7 +105,7 @@ function StickConfigScene:onInputPress(e)
SCENE = InputConfigScene(SETTINGS.firstTime) SCENE = InputConfigScene(SETTINGS.firstTime)
elseif self.input_state > #configurable_inputs then elseif self.input_state > #configurable_inputs then
if e.scancode == "return" or e.input == "menu_decide" then if e.scancode == "return" or e.input == "menu_decide" then
SETTINGS.input.keys = self.new_input SETTINGS.input.joysticks = self.new_input
SCENE = SETTINGS.firstTime and TitleScene() or InputConfigScene() SCENE = SETTINGS.firstTime and TitleScene() or InputConfigScene()
SETTINGS.firstTime = false SETTINGS.firstTime = false
elseif e.scancode == "delete" or e.scancode == "backspace" then elseif e.scancode == "delete" or e.scancode == "backspace" then

View File

@@ -25,7 +25,7 @@ local main_menu_scenes = {
DataManagementScene, DataManagementScene,
function() love.system.openURL("https://gitea.com/SweetSea-ButImNotSweet/tromi_mobile") end, function() love.system.openURL("https://gitea.com/SweetSea-ButImNotSweet/tromi_mobile") end,
AboutScene, AboutScene,
TrainingScene, TrainingScene,
function() love.system.openURL("https://mycophobia.org/forums/viewtopic.php?t=29") end, function() love.system.openURL("https://mycophobia.org/forums/viewtopic.php?t=29") end,
SettingsScene, SettingsScene,
@@ -39,7 +39,7 @@ local main_menu_icons = {
CHAR.icon.export, CHAR.icon.export,
CHAR.icon.home, CHAR.icon.home,
CHAR.icon.info, CHAR.icon.info,
CHAR.icon.toDown, CHAR.icon.toDown,
CHAR.icon.globe, CHAR.icon.globe,
CHAR.icon.settings, CHAR.icon.settings,
@@ -52,7 +52,7 @@ function Title2Scene:new()
love.audio.stop() love.audio.stop()
end end
self.main_menu_state = 1 self.main_menu_state = 1
PENTO_MODE = false PENTO_MODE = true
input_code = {0,0,0,0,0,0,0,0} input_code = {0,0,0,0,0,0,0,0}
end end
@@ -63,13 +63,13 @@ end
function Title2Scene:render() function Title2Scene:render()
MainBackground() MainBackground()
love.graphics.setColor(0, 0, 0, 0.7) love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 30, 60, 580, 85, 10, 10) -- Tromi love.graphics.rectangle("fill", 30, 60, 580, 85, 10, 10) -- Tromi
love.graphics.rectangle("fill", 30, 165, 580, 225, 10, 10) -- Menu love.graphics.rectangle("fill", 30, 165, 580, 225, 10, 10) -- Menu
drawBigText("Tromi", 40, 65, 100, "left") drawBigText("Tromi", 40, 65, 100, "left")
drawText("Mobile 1.1 - PC 2.3", 150, 78, 200, "left") drawText("Mobile 1.4 - PC 2.3", 150, 78, 200, "left")
drawText("https://mycophobia.org\nhttps://github.com/SweetSea-ButImNotSweet/", 40, 100, 300, "left") drawText("https://mycophobia.org\nhttps://github.com/SweetSea-ButImNotSweet/", 40, 100, 300, "left")
if PENTO_MODE then if PENTO_MODE then
@@ -109,7 +109,7 @@ local function checkCode(c)
if ( if (
code_string == "-1,-1,-1,-1,1,1,1,1" or code_string == "-1,-1,-1,-1,1,1,1,1" or
code_string == "2,2,2,2,2,2,2,2" code_string == "2,2,2,2,2,2,2,2"
) then ) then
PENTO_MODE = true PENTO_MODE = true
end end
end end

View File

@@ -13,7 +13,7 @@ function TrainingScene:new()
game_mode = require 'game.gamemode' game_mode = require 'game.gamemode'
if PENTO_MODE then if PENTO_MODE then
ruleset = require 'game.rotation_pent' ruleset = require 'game.rotation_big'
else else
ruleset = require 'game.rotation' ruleset = require 'game.rotation'
end end

237
scene/user_management.lua Normal file
View File

@@ -0,0 +1,237 @@
local UserManagementScene = SCENE:extend()
local max_items_per_page = 10
local gradeNames = {
"19k", "18k", "17k", "16k", "15k", "14k", "13k", "12k", "11k",
"10k", " 9k", " 8k", " 7k", " 6k", " 5k", " 4k", " 3k", " 2k", " 1k",
" 1D", " 2D", " 3D", " 4D", " 5D", " 6D", " 7D", " 8D", " 9D"
}
local user_list
local buttonList = {
BUTTON.new{
text = CHAR.icon.home.." Home\nEsc/Go back",
x = 510, y = 45, w = 120, h = 55,
codeWhenPressed = function() SCENE = TitleScene() end
},
BUTTON.new{
text = CHAR.icon.trash.." Delete\nDel/Rotate right",
x = 510, y = 105, w = 120, h = 55,
codeWhenPressed = function() SCENE:onInputPress{key = "delete"} end
},
BUTTON.new{
text = CHAR.key.up.." Page up\nLeft",
x = 510, y = 165, w = 120, h = 55,
},
BUTTON.new{
text = CHAR.key.down.." Page down\nRight",
x = 510, y = 225, w = 120, h = 55,
}
}
function UserManagementScene:new()
user_list = {}
self.current_page = 1
self.direction = nil
self.selecting = 1
self.repeat_counter = max_items_per_page - 1
for _, f in pairs(love.filesystem.getDirectoryItems(SAVE_DIR)) do
local file = SAVE_DIR .. f
local info = love.filesystem.getInfo(file)
if info and info.type == "file" and string.sub(f, 4, -1) == "_grade_history.sav" then
local name = string.sub(f, 1, 3)
table.insert(user_list, {
name = name,
valid = false, -- Data is not broken?
grade = 1, -- Player's grade
promo = 2, -- Promotion Meter
games = 0, -- Games played
})
local okay, _ = pcall(function()
local data = FILE.read(file)
if not data then error() end
user_list[#user_list].grade = data[1]
user_list[#user_list].promo = data[2]
user_list[#user_list].games = data[4]
end)
if okay then
user_list[#user_list].valid = true
end
end
end
end
local function getPromotionText(grade, promotion)
local points_text
if grade == 1 then
points_text = ({
[2] = " |..",
[3] = " .|.",
[4] = " ..|",
})[promotion]
else
points_text = ({
[0] = "|....",
[1] = ".|...",
[2] = "..|..",
[3] = "...|.",
[4] = "....|",
})[promotion]
end
return (grade > 1 and "-" or " ")..points_text..(grade < 29 and "+" or "")
end
function UserManagementScene:changeOption(rel)
local len = #user_list
self.selecting = self.selecting + rel
if self.selecting + ((self.current_page-1) * max_items_per_page) > len then
self.current_page = 1
self.selecting = 1
elseif self.selecting < 1 and self.current_page == 1 then
self.current_page = 1 + (math.floor(len / max_items_per_page))
self.selecting = len - ((self.current_page - 1) * max_items_per_page)
end
if self.selecting > max_items_per_page then
self.current_page = self.current_page + 1
self.selecting = 1
elseif self.selecting < 1 then
self.current_page = self.current_page - 1
self.selecting = max_items_per_page
end
end
function UserManagementScene:deleteCurrentReplay()
local name = user_list[max_items_per_page * (self.current_page - 1) + self.selecting].name
if love.window.showMessageBox(
"Delete the selected profile?",
"Are you sure you want to delete " .. string.upper(name) .. "'s profile?",
{
"Delete", ">>>CANCEL<<<",
escapebutton = 2
},
"warning"
) == 1 then
if love.window.showMessageBox(
"Are you really sure???",
"You really want to erase " .. string.upper(name) .. "'s profile?????\nYou may REGRET your action. This is NOT INVERSIBLE!",
{
">>>CANCEL<<<", "Delete",
escapebutton = 1
},
"warning"
) == 2 then
love.filesystem.remove(SAVE_DIR .. name .. "_grade_history.sav")
self:new()
end
end
end
function UserManagementScene:render()
MainBackground()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 0, 0, 640, 480)
love.graphics.setColor(0.4, 1, 1, 0.5)
love.graphics.rectangle("fill", 0, 15 + 30 * self.selecting, 500, 27)
BUTTON.draw(buttonList)
drawText('Name - Grade - Pro.Meter - Games', 40, 20, 1000, "left")
-- SEA 19k -..|..+ 12345
for i = (self.current_page - 1) * max_items_per_page + 1, math.min((self.current_page) * max_items_per_page, #user_list) do
if user_list[i].valid then
local name = user_list[i].name
local games = string.format("%5d", user_list[i].games)
local grade = gradeNames[user_list[i].grade]
local promo = getPromotionText(user_list[i].grade, user_list[i].promo)
drawText(
" " ..
name .. " " ..
grade .. " " ..
promo .. " " ..
games,
40, 20 + 30 * (i - (self.current_page - 1) * max_items_per_page), 1000, "left"
)
else
drawText(
" " .. user_list[i].name.." ??? -?????+ ?????",
40, 20 + 30 * (i - (self.current_page - 1) * max_items_per_page), 1000, "left"
)
end
end
drawText(string.format('Page %s/%s', self.current_page, math.floor(#user_list / max_items_per_page) + 1), 15, 440, 100,
"center")
end
function UserManagementScene:update()
if self.direction == "up" then
if self.repeat_counter >= max_items_per_page then
self:changeOption(-1)
self.repeat_counter = 0
end
self.repeat_counter = self.repeat_counter + 1
elseif self.direction == "down" then
if self.repeat_counter >= max_items_per_page then
self:changeOption(1)
self.repeat_counter = 0
end
self.repeat_counter = self.repeat_counter + 1
end
end
---@param e SCENE_onInput
function UserManagementScene:onInputPress(e)
if e.type == "mouse" or e.type == "touch" then
if not BUTTON.press(buttonList, e.x, e.y, e.id) then
local selection = math.floor((e.y - 45) / 30) + 1
love.window.showMessageBox("", selection)
if (
selection >= 1 and
selection <= self.repeat_counter and
selection + ((self.current_page-1) * max_items_per_page) <= #user_list
) then
self.selecting = selection
end
end
elseif e.input == "menu_back" then SCENE = TitleScene()
elseif e.input == "up" or e.key == "up" then self.direction = "up"
elseif e.input == "down" or e.key == "down" then self.direction = "down"
elseif e.input == "left" or e.key == "left" then
if self.current_page == 1 then
self.current_page = 1 + math.floor(#user_list / max_items_per_page)
else
self.current_page = self.current_page - 1
end
self.selecting = 1
elseif e.input == "right" or e.key == "right" then
if self.current_page < 1 + math.floor(#user_list / max_items_per_page) then
self.current_page = self.current_page + 1
else
self.current_page = 1
end
self.selecting = 1
elseif e.input == "rotate_right" or e.key == "delete" then self:deleteCurrentReplay()
end
end
function UserManagementScene:onInputRelease(e)
if e.type == "mouse" or e.type == "touch" then
BUTTON.release(buttonList, e.x, e.y, e.id)
elseif e.input == "up" or e.scancode == "up" or e.input == "down" or e.scancode == "down" then
self.direction = nil
self.repeat_counter = max_items_per_page - 1
end
end
function UserManagementScene:onInputMove(e)
if e.type == "mouse" then
BUTTON.checkHovering(buttonList, e.x, e.y)
end
end
return UserManagementScene