V1 update (#1)

This commit is contained in:
Nguyễn Quốc Hưng
2024-06-06 16:01:24 +07:00
committed by Squishy (C6H12O6+NaCl+H2O)
parent 3343d8711b
commit 1d6643448e
30 changed files with 1000 additions and 228 deletions

139
scene/about.lua Normal file
View File

@@ -0,0 +1,139 @@
---@class SCENE
local AboutScene = SCENE:extend()
AboutScene.title = "About"
local current_page = 1
local maxPage = 2
local buttonList
local function changePage(rel)
current_page = (current_page + maxPage + rel - 1) % maxPage + 1
end
buttonList = {
BUTTON.new{
text = function()
if current_page < maxPage then
return ("%s Next (%s/%s)"):format(CHAR.key.right, current_page, maxPage)
else
return ("%s Back (%s/%s)"):format(CHAR.icon.toLeft, current_page, maxPage)
end
end,
textOrientation = "center",
x = 185, y = 440, w = 130, h = 30,
codeWhenReleased = function()
changePage(1)
BUTTON.reset(buttonList)
end
},
BUTTON.new{
text = CHAR.icon.home.." Title",
textOrientation = "center",
x = 325, y = 440, w = 130, h = 30,
codeWhenReleased = function() SCENE = TitleScene() end
}
}
function AboutScene:new()
current_page = 1
BUTTON.reset(buttonList)
end
function AboutScene:render()
MainBackground()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 0, 0, 640, 480)
BUTTON.draw(buttonList)
if current_page == 1 then
-- Design & programming - Mycophobia
drawText ("Design & programming" , 20, 10, 180, "center")
drawBigText("mycophobia" , 20, 25, 180, "center")
drawText ("https://mycophobia.org" , 20, 60, 180, "center")
-- Cambridge - Based on
drawText ("Based on" , 230, 10, 180, "center")
drawBigText("Cambridge" , 230, 25, 180, "center")
drawText ("Cambridge contributors\nhttps://t-sp.in/cambridge", 230, 60, 180, "center")
-- Port to TV & mobile - SweetSea
drawText ("Port to TV & mobile" , 450, 10, 180, "center")
drawBigText("SweetSea" , 450, 25, 180, "center")
drawText ("https://github.com/\nSweetSea-ButImNotSweet" , 450, 60, 180, "center")
-- Design & programming - Mycophobia
drawText ("RNG Consultant" , 20, 120, 180, "center")
drawBigText("colour_thief" , 20, 135, 180, "center")
-- Design & programming - Mycophobia
drawText ("Launcher for Mac" , 450, 120, 180, "center")
drawBigText("nightmareci" , 450, 135, 180, "center")
drawText ("http://iblock.red" , 450, 170, 180, "center")
local other_text_y = 200
--- Other credit text, small text's y on the right = big text's y + 13, on the left: big text's y + 30
-- Music - Jerry Martin
drawBigText("Music", 0, other_text_y, 250, "right")
drawText("all rights reserved", 0, other_text_y + 30, 250, "right")
drawText("Jerry Martin - https://jerrymartinmusic.com \nJuraj Stanik - https://www.jurajstanik.com", 300, other_text_y + 13, 400, "left")
-- Background - PixaBays
drawBigText("Background", 0, other_text_y + 60, 250, "right")
drawText("by people on PixaBays", 0, other_text_y + 90, 250, "right")
drawText(
"Joe_hackney VisualSkyFX\n"..
"yokim Favorisxp Any_Ann",
300, other_text_y + 73, 400, "left"
)
-- Special thanks
drawBigText("Testing and/or\nCool Features", 0, other_text_y + 120, 250, "right")
drawText(
"netdoll esquatre Kirby703\n"..
"switchpalacecorner lindtobias\n"..
"zaphod77 Arch Nemesis dtet_enjoyer\n"..
"woozy Zircean AgentBasey Eden GT",
300, other_text_y + 133, 400, "left"
)
elseif current_page == 2 then
-- Main font
drawBigText("Font", 0, 10, 250, "right")
drawText("all used font are licensed under\nthe SIL Open Font License, v.1.1", 0, 40, 250, "right")
drawText(
"Iosevka - Renzhi Li (aka. Bellve Invis),\n(for game's UI interface and\n on-screen buttons' texture)\n\n"..
"Exo 2 for Techmino - C₂₉H₂₅N₃O₅, (for game's UI)\n\n"..
"Cascadia Code - Microsoft, used with Iosevka\nfor on-screen buttons' texture",
300, 23, 340, "left"
)
-- VCTRL
drawBigText("On-screen buttons\nimplementation", 0, 180, 250, "right")
drawText("UI's buttons: using simple-button module\nwritten by SweetSea\n\nIn-game on-screen control module is based on MrZ's VCTRL module in his games\nTexture made by SweetSea", 300, 193, 340, "left")
drawBigText("Special thanks", 25, 310, 460, "left")
drawText(
"The Absolute Plus - theabsolute.plus FYAD/Imp Zone Collective\
MrZ - https://github.com/MrZ626 C₂₉H₂₅N₃O₅ - https://github.com/C29H25N3O5\n\
AND ALL VERSION 1 PLAYERS "
, 25, 350, 600, "left")
end
end
---@param e SCENE_onInput
function AboutScene:onInputPress(e)
local key = e.input or e.key
if e.type == "touch" or e.type == "mouse" then
BUTTON.press(buttonList, e.x, e.y, e.id)
elseif key == "left" or key == "up" then changePage(-1)
elseif key == "right" or key == "down" then changePage( 1)
elseif e.input == "menu_back" or e.scancode == "escape" then
SCENE = TitleScene()
end
end
function AboutScene:onInputRelease(e)
if e.type == "touch" or e.type == "mouse" then
BUTTON.release(buttonList, e.x, e.y, e.id)
end
end
function AboutScene:onInputMove(e)
if e.type == "mouse" then
BUTTON.checkHovering(buttonList, e.x, e.y)
end
end
return AboutScene

View File

@@ -0,0 +1,81 @@
local EraseHighScoresScene = SCENE:extend()
EraseHighScoresScene.title = "Erase all high scores"
local selection_title = {"No", "Yes"}
local selection_icon = {
CHAR.icon.crossMark,
CHAR.icon.checkMark,
}
local menu_tip = "Are you sure you want to erase all your high scores?\n\nCAUTION!\nThis action CANNOT BE UNDONE!"
local settings_func = {
function() return DataManagementScene() end,
function()
love.filesystem.remove(HIscoreFILE)
love.window.showMessageBox("Done", "All high scores are erased!")
return DataManagementScene()
end,
}
function EraseHighScoresScene:new()
self.settings_menu_state = 1
end
function EraseHighScoresScene:changeOption(rel)
local len = #selection_title
self.settings_menu_state = (self.settings_menu_state + len + rel - 1) % len + 1
end
function EraseHighScoresScene:render()
MainBackground()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 30, 60, 580, 85, 10, 10) -- Tromi
love.graphics.rectangle("fill", 30, 165, 580, 225, 10, 10) -- Menu
drawBigText(CHAR.icon.erase.." ERASE ALL HIGH SCORES?", 40, 85, 400, "left")
-- Selecting
love.graphics.setColor(0.4, 1, 1, 0.5)
love.graphics.rectangle("fill", 330, 135 + 40 * self.settings_menu_state, 270, 40)
-- Text
for i = 1, #selection_title do
drawText (selection_title[i], 365, 145 + 40 * i, 230, "left")
drawBigText(selection_icon [i], 335, 135 + 40 * i, 50, "left")
end
drawText(menu_tip, 45, 175, 610 - 15 - 330, "left")
end
---@param e SCENE_onInput
function EraseHighScoresScene:onInputPress(e)
if e.input == "menu_back" or e.scancode == "escape" then SCENE = TitleScene()
elseif e.input == "menu_decide" or e.key == "return" then
local s = settings_func[self.settings_menu_state]()
if s then SCENE = s end
elseif e.input == "down" or e.scancode == "down" then
self:changeOption(1)
elseif e.input == "up" or e.scancode == "up" then
self:changeOption(-1)
elseif e.type == "touch" or e.type == "mouse" then
local x, y = e.x, e.y
local testOption = function(sel)
if sel ~= self.settings_menu_state then
self.settings_menu_state = sel
else
self:onInputPress{input = "menu_decide"}
end
end
if (
x >= 330 and x <= 600 and
y >= 175 and y <= 375
) then
local sel = math.floor((y - 175) / 40) + 1
if sel <= #settings_func then
testOption(sel)
end
end
end
end
return EraseHighScoresScene

93
scene/data/reset_all.lua Normal file
View File

@@ -0,0 +1,93 @@
local ResetAllScene = SCENE:extend()
ResetAllScene.title = "Erase all high scores"
local selection_title = {"No", "Yes"}
local selection_icon = {
CHAR.icon.crossMark,
CHAR.icon.checkMark,
}
local menu_tip = "ARE YOU SURE you want to RESET ALL?\n\nCAUTION: This will reset everything: accounts, replays, high scores and your settings!\n\nGame will restart after resetting."
local function recursivelyDelete(item)
if love.filesystem.getInfo(item,"directory") then
for _, child in ipairs(love.filesystem.getDirectoryItems(item)) do
recursivelyDelete(item..'/'..child)
love.filesystem.remove(item..'/'..child)
end
elseif love.filesystem.getInfo(item) then
love.filesystem.remove(item)
end
love.filesystem.remove(item)
end
local settings_func = {
function() return DataManagementScene() end,
function()
recursivelyDelete('')
love.window.showMessageBox("Done", "All your data erased\nQuitting game... Game will restart now!")
love.event.quit()
end,
}
function ResetAllScene:new()
self.settings_menu_state = 1
end
function ResetAllScene:changeOption(rel)
local len = #selection_title
self.settings_menu_state = (self.settings_menu_state + len + rel - 1) % len + 1
end
function ResetAllScene:render()
MainBackground()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 30, 60, 580, 85, 10, 10) -- Tromi
love.graphics.rectangle("fill", 30, 165, 580, 225, 10, 10) -- Menu
drawBigText(CHAR.icon.erase.." RESET ALL?", 40, 85, 400, "left")
-- Selecting
love.graphics.setColor(0.4, 1, 1, 0.5)
love.graphics.rectangle("fill", 330, 135 + 40 * self.settings_menu_state, 270, 40)
-- Text
for i = 1, #selection_title do
drawText (selection_title[i], 365, 145 + 40 * i, 230, "left")
drawBigText(selection_icon [i], 335, 135 + 40 * i, 50, "left")
end
drawText(menu_tip, 45, 175, 610 - 15 - 330, "left")
end
---@param e SCENE_onInput
function ResetAllScene:onInputPress(e)
if e.input == "menu_back" or e.scancode == "escape" then SCENE = TitleScene()
elseif e.input == "menu_decide" or e.key == "return" then
local s = settings_func[self.settings_menu_state]()
if s then SCENE = s end
elseif e.input == "down" or e.scancode == "down" then
self:changeOption(1)
elseif e.input == "up" or e.scancode == "up" then
self:changeOption(-1)
elseif e.type == "touch" or e.type == "mouse" then
local x, y = e.x, e.y
local testOption = function(sel)
if sel ~= self.settings_menu_state then
self.settings_menu_state = sel
else
self:onInputPress{input = "menu_decide"}
end
end
if (
x >= 330 and x <= 600 and
y >= 175 and y <= 375
) then
local sel = math.floor((y - 175) / 40) + 1
if sel <= #settings_func then
testOption(sel)
end
end
end
end
return ResetAllScene

96
scene/data_management.lua Normal file
View File

@@ -0,0 +1,96 @@
local DataManagementScene = SCENE:extend()
DataManagementScene.title = "Data Management"
local data_title = {
"Open save folder",
"Manage accounts (WIP)",
"Erase all high scores",
"RESET ALL!",
"Back"
}
local data_icon = {
CHAR.key .windows,
CHAR.icon.menu,
CHAR.icon.erase,
CHAR.icon.erase,
CHAR.icon.home,
}
local data_explaination = {
"(Only for PC)\nOpen save folder in a new window",
"You can view and delete your accounts here.",
"Erase all your high scores\nThis will make high score table go back to default",
"Erase all accounts, replays and all high scores!",
"Back to main menu"
}
local NULL = function() end
local settings_func = {
function() love.system.openURL(love.filesystem.getSaveDirectory()) end,
NULL,
function() return EraseHighScoresScene() end,
function() return ResetAllScene() end,
function() return TitleScene() end,
}
function DataManagementScene:new()
self.data_menu_state = 1
end
function DataManagementScene:changeOption(rel)
local len = #data_title
self.data_menu_state = (self.data_menu_state + len + rel - 1) % len + 1
end
function DataManagementScene:render()
MainBackground()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 30, 60, 580, 85, 10, 10) -- Tromi
love.graphics.rectangle("fill", 30, 165, 580, 225, 10, 10) -- Menu
drawBigText(CHAR.icon.export.." DATA MANAGEMENT", 40, 85, 400, "left")
-- Selecting
love.graphics.setColor(0.4, 1, 1, 0.5)
love.graphics.rectangle("fill", 40, 135 + 40 * self.data_menu_state, 270, 40)
-- Text
for i = 1, #data_title do
drawText (data_title[i], 85, 145 + 40 * i, 230, "left")
drawBigText(data_icon [i], 45, 135 + 40 * i, 50, "left")
end
drawText(data_explaination[self.data_menu_state], 330, 175, 610 - 15 - 330, "left")
end
---@param e SCENE_onInput
function DataManagementScene:onInputPress(e)
if e.input == "menu_back" or e.scancode == "escape" then SCENE = TitleScene()
elseif e.input == "menu_decide" or e.key == "return" then
local s = settings_func[self.data_menu_state]()
if s then SCENE = s end
elseif e.input == "down" or e.scancode == "down" then
self:changeOption(1)
elseif e.input == "up" or e.scancode == "up" then
self:changeOption(-1)
elseif e.type == "touch" or e.type == "mouse" then
local x, y = e.x, e.y
local testOption = function(sel)
if sel ~= self.data_menu_state then
self.data_menu_state = sel
else
self:onInputPress{input = "menu_decide"}
end
end
if (
x >= 40 and x <= 310 and
y >= 175 and y <= 375
) then
local sel = math.floor((y - 175) / 40) + 1
if sel <= #settings_func then
testOption(sel)
end
end
end
end
return DataManagementScene

View File

@@ -8,14 +8,5 @@ function ExitScene:update()
love.event.quit()
end
function ExitScene:render()
end
function ExitScene:changeOption(rel)
end
function ExitScene:onInputPress(e)
end
return ExitScene

View File

@@ -3,7 +3,6 @@ GameScene.title = "Game"
local tas = false
-- 70 295
local buttonList = {
BUTTON.new{
text = "Rotate Left\n Pause/Frame Step",
@@ -45,17 +44,17 @@ local buttonList = {
local menuKey -- MENU key used to go main menu XD
function GameScene:new(player_name, replay_file, replay_grade)
VCTRL[9].show = false
menuKey = BUTTON.new{
text = "MENU",
x = 265, y = 0, w = 60, h = 25,
text = CHAR.icon.menu.." MENU",
x = 10, y = 10, w = 70, h = 30,
codeWhenReleased = function()
if self.game.input_playback or self.game.game_over or self.game.completed then
SCENE = TitleScene()
end
end
}
VCTRL[9].show = false
BUTTON.reset(buttonList)
game_mode = require 'game.gamemode'
if PENTO_MODE then
@@ -89,7 +88,7 @@ end
function GameScene:update(nosound, tas_update)
local inputs = {}
if tas then
if tas then
while self.game.are > 2 do
self.game:update(inputs, self.ruleset)
end

View File

@@ -48,16 +48,16 @@ end
function KeyConfigScene:render()
MainBackground()
for i, input in ipairs(configurable_inputs) do
drawText(input_names[input], 40, 50 + i * 20, 200, "left")
drawText(input_names[input], 40, 60 + i * 20, 200, "left")
if self.set_inputs[input] then
drawText(self.set_inputs[input], 240, 50 + i * 20, 300, "left")
drawText(self.set_inputs[input], 240, 60 + i * 20, 300, "left")
end
end
if self.input_state > #configurable_inputs then
drawText("Press Enter/Confirm Selection to confirm, delete/backspace to retry" .. (SETTINGS.input and ", escape/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
drawText("Press key input for " .. input_names[configurable_inputs[self.input_state]] .. ", tab to skip, escape to cancel",0,0,1000)
drawText("Press any key from other input than keyboard will also skip.\nFunction keys (F1, F2, etc.), escape, and tab can't be changed", 0, 20,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)
end
end

View File

@@ -1,21 +1,9 @@
local LinesToggleScene = SCENE:extend()
LinesToggleScene.title = "Show lines during game:"
function LinesToggleScene:new()
end
function LinesToggleScene:update()
SETTINGS["lines"] = not SETTINGS["lines"]
SCENE = TitleScene()
end
function LinesToggleScene:render()
end
function LinesToggleScene:changeOption(rel)
end
function LinesToggleScene:onInputPress(e)
end
return LinesToggleScene

10
scene/loading.lua Normal file
View File

@@ -0,0 +1,10 @@
local LoadingScene = SCENE:extend()
function LoadingScene.update()
SCENE = SETTINGS.firstTime and InputConfigScene(true) or TitleScene()
end
function LoadingScene.render()
love.graphics.draw(LOADING_IMAGE_FILE,0,0,0,0.5)
end
return LoadingScene

View File

@@ -1,21 +1,9 @@
local MusicToggleScene = SCENE:extend()
MusicToggleScene.title = "Play music during game:"
function MusicToggleScene:new()
end
function MusicToggleScene:update()
SETTINGS["music"] = not SETTINGS["music"]
SCENE = TitleScene()
end
function MusicToggleScene:render()
end
function MusicToggleScene:changeOption(rel)
end
function MusicToggleScene:onInputPress(e)
end
return MusicToggleScene
return MusicToggleScene

View File

@@ -3,33 +3,37 @@ NameEntryScene.title = "Game Start"
local buttonList = {
BUTTON.new{
text = "\nCHAR", font = FONT_big,
text = "\nCHAR", font = FONT_big,
x = 25, y = 120, w = 80, h = 80,
codeWhenPressed = function() SCENE:onInputPress {input = "left"} end,
codeWhenReleased = function() SCENE:onInputRelease{input = "left"} end,
},
BUTTON.new{
text = "\nCHAR", font = FONT_big,
text = "\nCHAR", font = FONT_big,
x = 115, y = 120, w = 80, h = 80,
codeWhenPressed = function() SCENE:onInputPress {input = "right"} end,
codeWhenReleased = function() SCENE:onInputRelease{input = "right"} end,
},
BUTTON.new{
text = "\nESC", font = FONT_big,
text = "\nESC", font = FONT_big,
x = 25, y = 210, w = 80, h = 80,
codeWhenPressed = function() SCENE:onInputPress {input = "menu_back"} end,
codeWhenReleased = function() SCENE:onInputRelease{input = "menu_back"} end,
},
BUTTON.new{
text = "\nENTER", font = FONT_big,
text = "\nENTER", font = FONT_big,
x = 115, y = 210, w = 80, h = 80,
codeWhenPressed = function() SCENE:onInputPress {input = "menu_decide"} end,
codeWhenReleased = function() SCENE:onInputRelease{input = "menu_decide"} end,
},
BUTTON.new{
text = CHAR.key.keyboard.." Open OSK", font = FONT_big,
x = 25, y = 300, w = 170, h = 40,
codeWhenReleased = function() love.keyboard.setTextInput(true, 215, 175, 160, 160) end
}
}
local Grid = require 'game.grid'
local bitser = require 'libs.bitser'
function NameEntryScene:new()
VCTRL.toggle(false)
@@ -61,7 +65,6 @@ function NameEntryScene:new()
self.hi_scores = {"TRO",0,"MIT",0,"ROM",0,"ITR",0,"OMI",0}
end
end
function NameEntryScene:drawGradeList(left, top)
love.graphics.setColor(0,0,0,0.5)
love.graphics.rectangle("fill", left+3, top+3, 200, 240, 10, 10)
@@ -97,10 +100,8 @@ function NameEntryScene:render()
love.graphics.setColor(0.05,0.05,0.05,1)
love.graphics.rectangle("fill", 397, 292, 130, 130, 10, 10)
drawText("Best scores:", 410, 297, 1000, "left")
i = 2
while i <= 10 do
for i = 2, 10, 2 do
drawText(self.hi_scores[i-1]..' - '..self.hi_scores[i], 410, 297+(i*10), 1000, "left")
i = i + 2
end
if self.entry_pos == 4 then
drawText('Press confirm\nto play', 255, 290, 1000)
@@ -138,28 +139,43 @@ function NameEntryScene:onInputMove(e)
end
end
function NameEntryScene:getPlayInfo(player_name)
if love.filesystem.getInfo((SAVE_DIR..player_name.."_grade_history.sav")) then
grade_history = FILE.read(SAVE_DIR..player_name.."_grade_history.sav")
self.grade = grade_history[1]
self.wins = grade_history[2]
self.plays = grade_history[4]
else
self.grade, self.win, self.plays = 0, 0, 0
end
return self.grade, self.win, self.plays
end
function NameEntryScene:onInputPress(e)
local name = string.lower(self.name_entry[1]..self.name_entry[2]..self.name_entry[3])
if e.type == "mouse" or e.type == "touch" then
BUTTON.press(buttonList, e.x, e.y, e.id)
elseif e.key and #e.key == 1 then
local pos = string.find("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.", 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
if self.entry_pos == 4 then
BUTTON.release(buttonList, e.x, e.y, e.id)
SETTINGS['last_entry'] = name:upper()
SCENE = GameScene(name:lower())
else
if self.entry_pos == 3 then
name = string.lower(self.name_entry[1]..self.name_entry[2]..self.name_entry[3])
if love.filesystem.getInfo((SAVE_DIR..name.."_grade_history.sav")) then
grade_history = FILE.read(SAVE_DIR..name.."_grade_history.sav")
self.grade = grade_history[1]
self.wins = grade_history[2]
self.plays = grade_history[4]
end
end
if self.entry_pos < 3 then
self.name_entry[self.entry_pos] = self.chars:sub(self.char_pos, self.char_pos)
self.name_entry[self.entry_pos+1] = self.chars:sub(self.char_pos, self.char_pos)
end
if self.entry_pos == 3 then self:getPlayInfo(name)
else
self.name_entry[self.entry_pos ] = self.chars:sub(self.char_pos, self.char_pos)
self.name_entry[self.entry_pos+1] = self.chars:sub(self.char_pos, self.char_pos)
end
self.entry_pos = self.entry_pos + 1
end
elseif e.input == "left" or e.scancode == "left" then

View File

@@ -160,10 +160,10 @@ function ReplaySelectScene:onInputPress(e)
end
elseif e.input == "rotate_left" then -- Export
local plain_replay_data = love.data.encode("string", "base64", love.filesystem.read(REPLAY_DIR..selected_replay))
love.system.setClipboardText(("BEGINNING_OF_TROMI_REPLAY|%s|%s|END_OF_TROMI_REPLAY"):format(selected_replay, plain_replay_data))
love.system.setClipboardText(("BEGIN_OF_TROMI_REPLAY|%s|%s|END_OF_TROMI_REPLAY"):format(selected_replay, plain_replay_data))
elseif e.input == "rotate_right" then -- Import
local input_data = love.system.getClipboardText()
if input_data:find("BEGINNING_OF_TROMI_REPLAY|", 1, true) == 1 and input_data:find("|END_OF_TROMI_REPLAY", 1, true) == #input_data - 19 then
if input_data:find("BEGIN_OF_TROMI_REPLAY|", 1, true) == 1 and input_data:find("|END_OF_TROMI_REPLAY", 1, true) == #input_data - 19 then
local data_part = input_data:sub(27, #input_data - 20)
local separator_pos = data_part:find("|", 1, true)
local replay_name = data_part:sub(1, separator_pos - 1)
@@ -171,8 +171,10 @@ function ReplaySelectScene:onInputPress(e)
local replay_data = love.data.decode("string", "base64", data_part:sub(separator_pos + 1))
love.filesystem.write(replay_path, replay_data)
BUTTON.reset(buttonList)
SCENE = ReplayTestScene(replay_name)
else
BUTTON.reset(buttonList)
SCENE = ReplayTestScene()
end
elseif e.input == "up" or e.scancode == "up" then

View File

@@ -3,9 +3,12 @@ local ReplayTestScene = SCENE:extend()
local GAME
local error_message
local valid_data
local prev_scene
function ReplayTestScene:new(input_file)
prev_scene = SCENE
if not input_file then
valid_data = false
return
@@ -27,7 +30,10 @@ function ReplayTestScene:new(input_file)
end
function ReplayTestScene:render()
MainBackground()
prev_scene:render()
love.graphics.setColor(0, 0, 0, 0.8)
love.graphics.rectangle("fill", 0, 0, 640, 480)
if valid_data then
if error_message then
drawText("Replay test failed! Data corrupted!", 80, 40, 1000)
@@ -39,7 +45,7 @@ function ReplayTestScene:render()
end
else
drawText("Replay test failed! Not Tromi's replay data", 80, 40, 1000)
drawText("Press any key to go back, and check your device's clipboard again!", 80, 100, 1000)
drawText("Press any key to go back, and check your device's clipboard again!", 80, 70, 1000)
end
end

95
scene/settings.lua Normal file
View File

@@ -0,0 +1,95 @@
local SettingsScene = SCENE:extend()
SettingsScene.title = "Settings"
local settings_title = {
"Music",
"Lines",
"Fullscreen (F4)",
"Input configuration (F2)",
"Back",
}
local settings_explaination = {
"Enable music?\nThis does not apply to sound effects.",
"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.",
"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",
"Back to main menu"
}
local settings_func = {
function()
SETTINGS["music"] = not SETTINGS["music"]
love.audio.stop()
end,
function() SETTINGS["lines"] = not SETTINGS["lines"] end,
function() love.keypressed("f4", "f4") end,
InputConfigScene,
function() return TitleScene() end,
}
function SettingsScene:new()
self.settings_menu_state = 1
end
function SettingsScene:changeOption(rel)
local len = #settings_title
self.settings_menu_state = (self.settings_menu_state + len + rel - 1) % len + 1
end
function SettingsScene:render()
MainBackground()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 30, 60, 580, 85, 10, 10) -- Tromi
love.graphics.rectangle("fill", 30, 165, 580, 225, 10, 10) -- Menu
drawBigText(CHAR.icon.settings.." SETTINGS", 40, 85, 200, "left")
-- Selecting
love.graphics.setColor(0.4, 1, 1, 0.5)
love.graphics.rectangle("fill", 40, 135 + 40 * self.settings_menu_state, 270, 40)
-- Text
for i = 1, #settings_title do
drawText(settings_title[i], 45, 145 + 40 * i, 230, "left")
end
drawBigText(SETTINGS["music"] and CHAR.icon.checkMark or CHAR.icon.crossMark, 260, 175, 50, "center")
drawBigText(SETTINGS["lines"] and CHAR.icon.checkMark or CHAR.icon.crossMark, 260, 215, 50, "center")
drawBigText(love.window.getFullscreen() and CHAR.icon.checkMark or CHAR.icon.crossMark, 260, 255, 50, "center")
drawBigText(CHAR.key.keyboard , 260, 295, 50, "center")
drawBigText(CHAR.icon.home , 260, 335, 50, "center")
drawText(settings_explaination[self.settings_menu_state], 330, 175, 610 - 15 - 330, "left")
end
---@param e SCENE_onInput
function SettingsScene:onInputPress(e)
if e.input == "menu_back" or e.scancode == "escape" then SCENE = TitleScene()
elseif e.input == "menu_decide" or e.key == "return" then
local s = settings_func[self.settings_menu_state]()
if s then SCENE = s end
elseif e.input == "down" or e.scancode == "down" then
self:changeOption(1)
elseif e.input == "up" or e.scancode == "up" then
self:changeOption(-1)
elseif e.type == "touch" or e.type == "mouse" then
local x, y = e.x, e.y
local testOption = function(sel)
if sel ~= self.settings_menu_state then
self.settings_menu_state = sel
else
self:onInputPress{input = "menu_decide"}
end
end
if (
x >= 40 and x <= 310 and
y >= 175 and y <= 375
) then
local sel = math.floor((y - 175) / 40) + 1
if sel <= #settings_func then
testOption(sel)
end
end
end
end
return SettingsScene

View File

@@ -48,13 +48,13 @@ end
function StickConfigScene:render()
MainBackground()
for i, input in ipairs(configurable_inputs) do
drawText(input_names[input], 40, 50 + i * 20, 200, "left")
drawText(input_names[input], 40, 60 + i * 20, 200, "left")
if self.set_inputs[input] then
drawText(self.set_inputs[input], 240, 50 + i * 20, 300, "left")
drawText(self.set_inputs[input], 240, 60 + i * 20, 300, "left")
end
end
if self.input_state > #configurable_inputs then
drawText("Press enter/Confirm Selection to confirm, delete/backspace to retry" .. (SETTINGS.input and ", escape/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
drawText("Press joystick input for " .. input_names[configurable_inputs[self.input_state]] .. ", tab to skip, escape to cancel", 0, 0, 1000)
end

View File

@@ -15,8 +15,6 @@ local main_menu_screens = {
}
function TitleScene:new()
VCTRL.clearAll() -- Reset the RESTART button state
VCTRL.new(SETTINGS.input.virtual)
if SOUNDS['bgm_firsthalf']:isPlaying() or SOUNDS['bgm_secondhalf']:isPlaying() or not SETTINGS["music"] then
love.audio.stop()
end
@@ -116,7 +114,6 @@ function TitleScene:onInputPress(e)
if self.main_menu_state ~= selecting then
self.main_menu_state = selecting
else
VCTRL.toggle(true)
SCENE = main_menu_screens[selecting]()
end
end

164
scene/title2.lua Normal file
View File

@@ -0,0 +1,164 @@
---@class SCENE
local Title2Scene = SCENE:extend()
Title2Scene.title = "Title"
local input_code = {}
local main_menu_title = {
"New game" ,
"Replay" ,
"Data management" ,
"Mobile port repository",
"About" ,
"Max gravity Training",
"Leaderboard" ,
"Settings" ,
"Official homepage" ,
"Exit game" ,
}
local half_pos = math.roundUnit(#main_menu_title / 2)
local main_menu_scenes = {
NameEntryScene,
ReplaySelectScene,
DataManagementScene,
function() love.system.openURL("https://gitea.com/SweetSea-ButImNotSweet/tromi_mobile") end,
AboutScene,
TrainingScene,
function() love.system.openURL("https://mycophobia.org/forums/viewtopic.php?t=29") end,
SettingsScene,
function() love.system.openURL("https://mycophobia.org/tromi") end,
ExitScene
}
local main_menu_icons = {
CHAR.icon.play,
CHAR.icon.rewind,
CHAR.icon.export,
CHAR.icon.home,
CHAR.icon.info,
CHAR.icon.toDown,
CHAR.icon.globe,
CHAR.icon.settings,
CHAR.icon.home,
CHAR.icon.back,
}
function Title2Scene:new()
if SOUNDS['bgm_firsthalf']:isPlaying() or SOUNDS['bgm_secondhalf']:isPlaying() or not SETTINGS["music"] then
love.audio.stop()
end
self.main_menu_state = 1
PENTO_MODE = false
input_code = {0,0,0,0,0,0,0,0}
end
function Title2Scene:changeOption(rel)
local len = #main_menu_title
self.main_menu_state = (self.main_menu_state + len + rel - 1) % len + 1
end
function Title2Scene:render()
MainBackground()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 30, 60, 580, 85, 10, 10) -- Tromi
love.graphics.rectangle("fill", 30, 165, 580, 225, 10, 10) -- Menu
drawBigText("Tromi", 40, 65, 100, "left")
drawText("Mobile 1.0 - PC 2.3", 150, 78, 200, "left")
drawText("https://mycophobia.org\nhttps://github.com/SweetSea-ButImNotSweet/", 40, 100, 300, "left")
if PENTO_MODE then
drawBigText("PENTO MODE", 400, 85, 200, "right")
end
love.graphics.setColor(1, 1, 1, 0.5)
love.graphics.setLineWidth(1)
love.graphics.line(320, 175, 320, 375)
-- Selecting
love.graphics.setColor(0.4, 1, 1, 0.5)
if self.main_menu_state > half_pos then
love.graphics.rectangle("fill", 330, 135 + 40 * (self.main_menu_state - half_pos), 270, 40)
else
love.graphics.rectangle("fill", 40, 135 + 40 * self.main_menu_state, 270, 40)
end
-- Text
for i = 1, half_pos do
drawText(main_menu_title[i] , 45, 145 + 40 * i, 230, "right")
drawText(main_menu_icons[i] or '', 285, 145 + 40 * i, 20, "center")
end
for i = half_pos + 1, #main_menu_title do
drawText(main_menu_title[i] , 365, 145 + 40 * (i - half_pos), 230, "left")
drawText(main_menu_icons[i] or '', 335, 145 + 40 * (i - half_pos), 20, "center")
end
end
local function checkCode(c)
if not PENTO_MODE then
table.insert(input_code, c)
if #input_code > 8 then
table.remove(input_code, 1)
end
local code_string = table.concat(input_code, ',')
if (
code_string == "-1,-1,-1,-1,1,1,1,1" or
code_string == "2,2,2,2,2,2,2,2"
) then
PENTO_MODE = true
end
end
end
---@param e SCENE_onInput
function Title2Scene:onInputPress(e)
if e.input == "menu_back" or e.scancode == "escape" then SCENE = TitleScene()
elseif e.input == "menu_decide" or e.key == "return" then
local s = main_menu_scenes[self.main_menu_state]()
if s then SCENE = s end
elseif e.input == "down" or e.scancode == "down" then
self:changeOption(1)
elseif e.input == "up" or e.scancode == "up" then
self:changeOption(-1)
elseif e.input == "left" or e.scancode == "left" then
self:changeOption(-half_pos)
checkCode(-1)
elseif e.input == "right" or e.scancode == "right" then
self:changeOption(half_pos)
checkCode(1)
elseif e.type == "touch" or e.type == "mouse" then
local x, y = e.x, e.y
local testOption = function(sel)
if sel ~= self.main_menu_state then
self.main_menu_state = sel
else
self:onInputPress{input = "menu_decide"}
end
end
-- 40 175 320 375 320 175 600 375
if y >= 175 and y <= 375 then
local sel = math.floor((y - 175) / 40) + 1
if x >= 40 and x <= 310 and sel <= half_pos then
testOption(sel)
elseif (
x >= 330 and x <= 600 and
sel >= 1 and sel + half_pos <= #main_menu_scenes
) then
testOption(sel + half_pos)
end
elseif (
x >= 460 and y >= 85 and
x <= 600 and y <= 125
) then
checkCode(2)
end
end
end
return Title2Scene

View File

@@ -5,13 +5,11 @@ TouchConfigScene.title = "Touchscreen config"
local Grid = require 'game.grid'
local buttonList
local sliderList
local sliderList = {}
---@class VCTRL.data
local focusingButton
---@type number
local snapUnit = 1
---@type boolean
local hasChanged
---@type function
local function exitSceneFunc(saved)
@@ -29,23 +27,23 @@ buttonList = {
showToggle = BUTTON.new{
text = function()
if focusingButton then
return focusingButton.show and "[SHOW]\nHide" or "Show\n[HIDE]"
return focusingButton.show and ">SHOW<\nhide" or "show\n>HIDE<"
else
return "Show\nHide"
return "show\nhide"
end
end,
x = 275, y = 5, w = 50, h = 75,
codeWhenReleased = function ()
x = 400, y = 110, w = 60, h = 40,
codeWhenReleased = function()
if focusingButton then
focusingButton.show = not focusingButton.show
hasChanged = true
VCTRL.hasChanged = true
end
end,
update = function(self) self.textColor = focusingButton and {1, 1, 1} or {0.5, 0.5, 0.5} end
},
previewToggle = BUTTON.new{
text = "Preview\nON",
x = 570, y = 35, w = 60, h = 40,
x = 570, y = 60, w = 60, h = 40,
codeWhenReleased = function()
VCTRL.release()
BUTTON.release(buttonList)
@@ -54,7 +52,7 @@ buttonList = {
},
resetAll = BUTTON.new{
text = "RESET\nALL",
x = 570, y = 80, w = 60, h = 40,
x = 500, y = 110, w = 60, h = 40,
codeWhenReleased = function()
local selection = love.window.showMessageBox(
"Save config?", "Are you really sure about RESETTING ALL touchscreen configuration?",
@@ -63,7 +61,7 @@ buttonList = {
)
if selection == 1 then
VCTRL.focus = nil; focusingButton = nil
hasChanged = false
VCTRL.hasChanged = false
VCTRL.clearAll()
VCTRL.new(SETTINGS.__default__.input.virtual)
SETTINGS.input.virtual = SETTINGS.__default__.input.virtual
@@ -72,9 +70,9 @@ buttonList = {
},
menuScreen = BUTTON.new{
text = "MENU",
x = 570, y = 5, w = 60, h = 25,
x = 570, y = 10, w = 60, h = 40,
codeWhenReleased = function()
if hasChanged or SETTINGS.firstTime then
if VCTRL.hasChanged or SETTINGS.firstTime then
local selection = love.window.showMessageBox(
"Save config?", "Do you want to save your changes before exiting?",
{"Save", "Discard", "Keep editing", escapebutton = 3, enterbutton = 1},
@@ -98,45 +96,59 @@ buttonList = {
end
}
}
sliderList = {}
sliderList.buttonSize = newSlider(
200, 30, 120, 0, 0, 120,
function(v)
if focusingButton then
v = math.roundUnit(v, 5)
if focusingButton.r ~= v then
focusingButton.r = v
VCTRL.hasChanged = true
end
sliderList.buttonSize.value = v / 120
end
end,
{width = 40}
)
sliderList.iconSize = newSlider(
480, 30, 120, 0, 0, 100,
function(v)
if focusingButton then
v = math.roundUnit(v, 5)
if focusingButton.iconSize ~= v then
focusingButton.iconSize = v
VCTRL.hasChanged = true
end
sliderList.iconSize.value = v / 100
end
end,
{width = 40}
)
sliderList.opacity = newSlider(
155, 20+5, 120, 100, 0, 100,
200, 80, 120, 0, 0, 1,
function()
local v
if focusingButton then
v = math.roundUnit(sliderList.opacity.value, 0.01)
if focusingButton.alpha~=v then
focusingButton.alpha = v
hasChanged = true
VCTRL.hasChanged = true
end
sliderList.opacity.value = v
end
end,
{width = 30}
)
sliderList.size = newSlider(
155, 60+2.5, 120, 45, 0, 120,
function(v)
if focusingButton then
local v = math.roundUnit(v, 5)
if focusingButton.r ~= v then
focusingButton.r = v
hasChanged = true
end
sliderList.size.value = v / 120
end
end,
{width = 30}
{width = 40}
)
local gridSizeTable = {1, 2, 5, 10, 20, 50, 100}
sliderList.gridSize = newSlider(
405, 50, 100, 1, 1, #gridSizeTable - 1,
480, 80, 120, 1, 1, #gridSizeTable - 1,
function()
local v = math.roundUnit(sliderList.gridSize.value, 1 / 6)
local f = #gridSizeTable - 1
local v = math.roundUnit(sliderList.gridSize.value, 1 / f)
sliderList.gridSize.value = v
snapUnit = gridSizeTable[math.roundUnit(v * (#gridSizeTable - 1) + 1)]
snapUnit = gridSizeTable[math.roundUnit(v * f + 1)]
end,
{width = 30}
{width = 40}
); sliderList.gridSize.forceLight = true
local function sliderList_draw()
@@ -177,13 +189,15 @@ function TouchConfigScene:update()
if VCTRL.focus~=focusingButton then
focusingButton = VCTRL.focus
sliderList.opacity.value = focusingButton.alpha
sliderList.size.value = focusingButton.r / 120
sliderList.buttonSize.value = focusingButton.r / 120
sliderList.iconSize.value = focusingButton.iconSize / 100
end
BUTTON.update(buttonList)
sliderList_update()
end
local string_format = string.format
function TouchConfigScene:render()
MainBackground()
@@ -206,19 +220,16 @@ function TouchConfigScene:render()
end
love.graphics.setColor(0, 0, 0, 0.7)
-- Opacity and Size
love.graphics.rectangle("fill", 10, 5, 267, 75)
-- Snap to grid
love.graphics.rectangle("fill", 330, 5, 150, 75)
love.graphics.rectangle("fill", 5, 5, 560, 100)
-- Button Size
drawText(string_format("Size (buttons)\n%14.1d", focusingButton and focusingButton.r or 0), 10, 13, 100, "left")
-- Icon size
drawText(string_format("Size (icons)\n%13.1d%%", focusingButton and focusingButton.iconSize or 0), 290, 13, 100, "left")
-- Opacity
drawText("Opacity", 20, 15, 100, "left")
drawText(string.format("%3.1d%%", focusingButton and focusingButton.alpha * 100 or 0), 225, 15, 40, "left")
-- Size
drawText("Size", 20, 55, 100, "left")
drawText(string.format("%3.1dpx", focusingButton and focusingButton.r or 0), 225, 55, 40, "left")
drawText(string_format("Opacity\n%13.1d%%", focusingButton and focusingButton.alpha * 100 or 0), 10, 63, 100, "left")
-- Snap to grid
drawText(string.format("Snap to grid: %3s", snapUnit), 345, 15, 140, "left")
drawText(string_format("Snap to grid\n%14.1d", snapUnit), 290, 63, 100, "left")
for _, v in ipairs(VCTRL) do
if v ~= focusingButton then
@@ -245,10 +256,8 @@ end
---@param e SCENE_onInput
function TouchConfigScene:onInputMove(e)
if e.type == "touch" or (e.type == "mouse" and love.mouse.isDown(1)) then
if VCTRL.drag(e.dx, e.dy, e.id or 1) then hasChanged = true end
end
if e.type == "mouse" then
if VCTRL.drag(e.dx, e.dy, e.id or 1) then VCTRL.hasChanged = true end
elseif e.type == "mouse" then
BUTTON.checkHovering(buttonList, e.x, e.y)
end
end
@@ -258,7 +267,8 @@ function TouchConfigScene:onInputPress(e)
if not (
VCTRL.press(e.x, e.y, e.id and e.id or 1, true) or
BUTTON.press(buttonList, e.x, e.y, e.id) or
(e.x >= 80 and e.x <= 230 and e.y >= 10 and e.y <= 77)
(e.x >= 120 and e.x <= 280 and e.y >= 10 and e.y <= 100) or
(e.x >= 400 and e.x <= 560 and e.y >= 10 and e.y <= 100)
) then
VCTRL.focus = nil
focusingButton = nil

View File

@@ -8,7 +8,7 @@ local buttonList
buttonList = {
previewToggle = BUTTON.new{
text = "Preview\nOFF",
x = 570, y = 35, w = 60, h = 40,
x = 570, y = 60, w = 60, h = 40,
codeWhenReleased = function()
VCTRL.release()
BUTTON.release(buttonList)
@@ -16,8 +16,6 @@ buttonList = {
end
},
}
local sliderList = {}
local secret_grade_grid = {}
do
local colour_names = {'R', 'O', 'Y', 'G', 'C', 'B', 'M'}
@@ -80,13 +78,17 @@ end
function TouchConfigPreviewScene:onInputPress(e)
if e.type ~= "virtual" and e.input == 'menu_back' then SCENE = InputConfigScene() end
if e.type == "mouse" or e.type == "touch" then
BUTTON.press(buttonList, e.x, e.y, e.id)
if not BUTTON.press(buttonList, e.x, e.y, e.id) then
VCTRL.press(e.x, e.y, e.id or 1)
end
end
end
---@param e SCENE_onInput
function TouchConfigPreviewScene:onInputRelease(e)
if e.type == "mouse" or e.type == "touch" then
BUTTON.release(buttonList, e.x, e.y, e.id)
if not BUTTON.release(buttonList, e.x, e.y, e.id) then
VCTRL.release(e.id or 1)
end
end
end

View File

@@ -1,14 +1,15 @@
local TrainingScene = SCENE:extend()
TrainingScene.title = "Max Gravity Training"
local menuKey
local menuKey = BUTTON.new{
text = CHAR.icon.menu.." MENU",
x = 10, y = 10, w = 70, h = 30,
codeWhenReleased = function() SCENE = TitleScene() end
}
function TrainingScene:new()
menuKey = BUTTON.new{
text = "MENU",
x = 265, y = 0, w = 60, h = 25,
codeWhenReleased = function() SCENE = TitleScene() end
}
BUTTON.reset{menuKey}
VCTRL[9].show = true
game_mode = require 'game.gamemode'
if PENTO_MODE then