28 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
Nguyễn Quốc Hưng
f691f9e75d Bump version number 2024-08-10 08:00:15 +07:00
Nguyễn Quốc Hưng
e7474aefeb Reset background color 2024-08-10 07:55:22 +07:00
Nguyễn Quốc Hưng
c0d061e254 Update README 2024-08-10 07:52:14 +07:00
Nguyễn Quốc Hưng
c24cfe1a8b Small changes 2024-08-10 06:35:52 +07:00
SweetSea
3827304fc5 Fix gamepad system on Android
(tụi này không dùng cảm biến trọng trường đâu!)
2024-08-10 06:28:15 +07:00
Nguyễn Quốc Hưng
91100883fe Add buttons to prevent soft-lock in keybind conf. 2024-08-09 23:40:07 +07:00
Nguyễn Quốc Hưng
1a99de7435 Using Lily to speed up assets loading 2024-08-09 19:47:04 +07:00
Nguyễn Quốc Hưng
0a5bc1476d Attempt to fix soft lock in stick conf. screen 2024-08-09 10:45:48 +07:00
Squishy (C6H12O6+NaCl+H2O)
52f0e5323f Fix various bugs
- Sometimes keyboard suddenly closed while a key is being pressed on mobile (TEST)
- Fix navigation issue in replay scene
- Fix Confirm key is not usable as Restart in 20G Training
2024-06-14 15:20:36 +07:00
Squishy (C6H12O6+NaCl+H2O)
a5b72ef286 Disable OSK when starting game 2024-06-13 11:41:45 +07:00
Squishy (C6H12O6+NaCl+H2O)
a0575bdfab Erase outdated screenshots 2024-06-13 11:39:47 +07:00
Squishy (C6H12O6+NaCl+H2O)
0a2fd20075 Update replay screen 2024-06-13 11:38:17 +07:00
27 changed files with 2030 additions and 185 deletions

View File

@@ -3,7 +3,7 @@ A old-fashioned but modern block-stacking game. Made with :heart: by [mycophobia
Ported to Android (mobile and TV) by SweetSea with on-screen control (with some necessary changes)
# How to play
> :warning: There is no Android build (aka APK file) right now. If you see any pre-built APK files on the internet. Please be aware
> :warning: There is no Android build (aka APK file) right now. If you see any pre-built APK files on the internet. Please be aware of viruses and malwares
## For mobile
### Install
1. In the [Releases tab](https://gitea.com/SweetSea-ButImNotSweet/tromi_mobile/releases) and click on ``Source code (zip)``
@@ -15,8 +15,8 @@ Ported to Android (mobile and TV) by SweetSea with on-screen control (with some
7. Now, press Home (or back to app launcher), you can see two icons: ``LÖVE for Android`` and ``LÖVE Launcher``. You should use the ``LÖVE Launcher`` to launch Tromi
### Launch
1. Launch ``LÖVE Launcher``, an file picker will appear
2. Navigate to where you put the game file, example ``tromi_mobile.love``
3. Pick the file and enjoy
2. Navigate to where you put the file and pick Tromi
3. Pick the file and enjoy.
## For TV
> :warning: Before I tell you how, I need to tell you something
@@ -28,7 +28,7 @@ Ported to Android (mobile and TV) by SweetSea with on-screen control (with some
2. Install this file manager on your TV: https://play.google.com/store/apps/details?id=com.alphainventor.filemanager. Once you installed, you should see [this icon](https://play-lh.googleusercontent.com/9PzlG2XGr5sQDf5925tlZhqluOreI2cwzp-FOZiuj545Kt1Gk5EE9J4IdGsD7e5xWw=w240-h480-rw)
3. Opening the application, click on ``Access from...`` (network/other devices/etc.)
4. Transfer 2 downloaded files to TV
5. Install LÖVE for Android application (see step 6 in ``Install for TV`` section)
5. Install LÖVE for Android application (see step 6 in ``Install for mobile`` section)
6. *(First time only)* Open the ``tromi_mobile.love``. When the file manager asks you to open the file as what. Select ``Other``, then select ``LÖVE for Android`` and select ``Always``
7. Once you are in the key configuration scene, type ``88663366``. An predefined keybind will be set automatically, but you can now make a different one if you'd like to
@@ -52,18 +52,19 @@ Navigate to where you put ``tromi_mobile.love`` in the File manager (the one you
* Update ``binser`` library, this fixes some weird bugs related to saving
* Add ``simple-button`` module, made by me (SweetSea)
* Replaced old Cambridge's ``config`` module with the new one inspired by "the sequel of Techmino"s ``SETTINGS`` module".
* Using `lily` to improve the loading speed of animated backgrounds and sounds.
# TODO
- [x] Add a way to export replay data for Android > 11
- [x] Add a way to export replay data for Android 11+
- [x] Revert ``bitser`` with ``binser`` (if and only if I can make it works)
- [x] Design a new on-screen buttons skin (the current one is come from [C₂₉H₂₅N₃O₅](https://github.com/C29H25N3O5), I am aware that it's not fit to Tromi's design language)
- [x] Updating on-screen control configuration screen
- [x] (Low priority) Design a new menu screen
- [x] Add shortcut to open replay converter at https://sweetsea-butimnotsweet.github.io/tromi_replay_converter
- [x] Redesign the replay selector screen
- [ ] Add user data management
- [ ] Redesign "the Control method selection" screen
- [ ] Redesign the replay screen
- [ ] Add shortcut to open replay converter at https://sweetsea-butimnotsweet.github.io/tromi_replay_converter
# License (GNU GPLv3)
Please read ``COPYING.txt`` for more information.<br>
@@ -82,7 +83,7 @@ A small note about the music:
# Don't forget to check
* [Original Tromi](https://mycophobia.org/tromi)
* [Leaderboard](https://mycophobia.org/)
* [Leaderboard](https://mycophobia.org/forums/viewtopic.php?t=29)
* [Cambridge](https://github.com/Cambridge-stacker/Cambridge)
* [Techmino](https://github.com/26F-Studio/Techmino)

View File

@@ -9,5 +9,5 @@ function love.conf(t)
t.window.height = 960
t.window.vsync = false
t.accelerometerjoystick = true
t.accelerometerjoystick = false
end

View File

@@ -11,10 +11,9 @@ local Randomizer = require 'game.randomizer'
local GameMode = Object:extend()
function GameMode:new(player_name, input_file, replay_grade)
-- VCTRL.toggle(MOBILE and not input_file and not SETTINGS.tvMode)
VCTRL.toggle(true)
VCTRL.toggle(MOBILE and not input_file and not SETTINGS.tvMode)
VCTRL.reset()
if player_name == nil then self.training = true else self.training = false end
if input_file ~= nil then
input_file = love.filesystem.read(REPLAY_DIR..input_file)
@@ -60,7 +59,7 @@ function GameMode:new(player_name, input_file, replay_grade)
self.did_grades = false
self.active_frames = 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 = {
"19k", "18k", "17k", "16k", "15k", "14k", "13k", "12k", "11k", "10k",
"9k", "8k", "7k", "6k", "5k", "4k", "3k", "2k", "1k",

View File

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

@@ -15,7 +15,6 @@ local function mDrawQ(obj,quad,x,y,a,k)
love.graphics.draw(obj,quad,x,y,a,k,nil,w*.5,h*.5)
end
ShowLoadingText('virtual key skin')
local empty_quad
-- A table containing quads used to draw icons for virtual control system.
-- local virtual_quad=setmetatable((function()
@@ -42,7 +41,7 @@ local virtual_quad=setmetatable((function()
empty_quad=gc_newQuad(0,0,1,1,5*w,2*w)
for i,name in next,{
'left','right','up','down','restart',
'rotate_right','rotate_left','rotate_right2','rotate_left2','',
'rotate_right','rotate_left','rotate_right2','rotate_left2'
} do if #name>0 then t[name]=gc_newQuad((i-1)%5*w,math.floor((i-1)/5)*w,w,w,5*w,2*w) end end
return t
end)(),{

1009
libs/lily.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -151,13 +151,13 @@ function button:press(x, y, touchID)
end
---Trigger release action, don't need ``self._hovering`` to ``true``
function button:release(x, y, touchID)
local valid = true
local valid
if touchID then
valid = touchID == self._touchID
else
valid = true
end
if valid then
self._pressed = false
self._touchID = false
@@ -187,7 +187,7 @@ function BUTTON.checkDataValidation(D, safe)
elseif type(D.text) ~= 'string' then
error("[text] must be a string or a function returns string, got "..type(D.text))
end
assert(type(D.x) == "number" , "[x] must be a integer")
assert(type(D.y) == "number" , "[y] must be a integer")
assert(type(D.w) == "number" and D.w > 0, "[w] must be a positive integer")

View File

@@ -60,22 +60,25 @@ BUTTON.setDefaultOption{
}
-- Graphics
ShowLoadingText('backgrounds')
local gc_newImage, gc_newVideo = love.graphics.newImage, love.graphics.newVideo
BACKGROUNDS = {
[0] = gc_newVideo("res/backgrounds/green_waterfall.ogv", {audio=false}),
gc_newVideo("res/backgrounds/water.ogv", {audio=false}),
gc_newVideo("res/backgrounds/green_streams.ogv", {audio=false}),
gc_newVideo("res/backgrounds/streams.ogv", {audio=false}),
gc_newVideo("res/backgrounds/red_forest_waterfall.ogv", {audio=false}),
gc_newVideo("res/backgrounds/flowers_rain.ogv", {audio=false}),
gc_newVideo("res/backgrounds/moonlight_tree.ogv", {audio=false}),
gc_newVideo("res/backgrounds/lisa_frank.ogv", {audio=false}),
gc_newVideo("res/backgrounds/snowy_trees.ogv", {audio=false}),
gc_newVideo("res/backgrounds/snowy_cabin.ogv", {audio=false}),
}
BACKGROUNDS = {}
LILY.loadMulti{
{'newVideo', "res/backgrounds/green_waterfall.ogv", {audio=false}},
{'newVideo', "res/backgrounds/water.ogv", {audio=false}},
{'newVideo', "res/backgrounds/green_streams.ogv", {audio=false}},
{'newVideo', "res/backgrounds/streams.ogv", {audio=false}},
{'newVideo', "res/backgrounds/red_forest_waterfall.ogv", {audio=false}},
{'newVideo', "res/backgrounds/flowers_rain.ogv", {audio=false}},
{'newVideo', "res/backgrounds/moonlight_tree.ogv", {audio=false}},
{'newVideo', "res/backgrounds/lisa_frank.ogv", {audio=false}},
{'newVideo', "res/backgrounds/snowy_trees.ogv", {audio=false}},
{'newVideo', "res/backgrounds/snowy_cabin.ogv", {audio=false}},
}:onComplete(
function(_, lilies)
for i = 0, 9 do BACKGROUNDS[i] = lilies[i + 1][1] end
LOADED_BACKGROUND = true;
end)
ShowLoadingText('blocks')
BLOCKS = {
["2tie"] = {
R = gc_newImage("res/img/r.png"),
@@ -112,21 +115,30 @@ COLOUR_SCHEMES = {
}
-- BGMs and SFXs
ShowLoadingText('BGMs & SFXs')
local audio_newSource = love.audio.newSource
SOUNDS = {
bottom = audio_newSource("res/se/bottom.wav", "static"),
lock = audio_newSource("res/se/lock.wav", "static"),
erase = audio_newSource("res/se/erase.wav", "static"),
fall = audio_newSource("res/se/fall.wav", "static"),
ready = audio_newSource("res/se/ready.wav", "static"),
promote = audio_newSource("res/se/promote.wav", "static"),
demote = audio_newSource("res/se/demote.wav", "static"),
autopromote = audio_newSource("res/se/autopromote.wav", "static"),
bgm_firsthalf = audio_newSource("res/bgm/firsthalf.flac", "static"),
bgm_secondhalf = audio_newSource("res/bgm/secondhalf.flac", "static"),
bgm_title = audio_newSource("res/bgm/title.flac", "static")
}
SOUNDS = {}
LILY.loadMulti{
{"newSource", "res/se/bottom.wav", "static"},
{"newSource", "res/se/lock.wav", "static"},
{"newSource", "res/se/erase.wav", "static"},
{"newSource", "res/se/fall.wav", "static"},
{"newSource", "res/se/ready.wav", "static"},
{"newSource", "res/se/promote.wav", "static"},
{"newSource", "res/se/demote.wav", "static"},
{"newSource", "res/se/autopromote.wav", "static"},
{"newSource", "res/bgm/firsthalf.flac", "static"},
{"newSource", "res/bgm/secondhalf.flac", "static"},
{"newSource", "res/bgm/title.flac", "static"},
}:onComplete(
function(_, lilies)
SOUNDS.bottom, SOUNDS.lock, SOUNDS.erase, SOUNDS.fall = unpack(lilies, 1, 4)
SOUNDS.ready, SOUNDS.promote, SOUNDS.demote, SOUNDS.autopromote = unpack(lilies, 5, 8)
SOUNDS.bgm_firsthalf, SOUNDS.bgm_secondhalf, SOUNDS.bgm_title = unpack(lilies, 9)
for k, v in pairs(SOUNDS) do SOUNDS[k] = v[1] end -- Again, to avoid userdata
LOADED_MUSIC = true;
end
)
function PlaySE(sound, subsound)
if sound ~= nil then

View File

@@ -12,26 +12,13 @@ if not love.filesystem.getInfo(REPLAY_DIR) then
love.filesystem.createDirectory(REPLAY_DIR)
end
BACKGROUND_COLOR = {32/255, 120/255, 88/255}
BACKGROUND_COLOR = {0, 0, 0}
-- BACKGROUND_COLOR = {32/255, 120/255, 88/255}
CURRENT_OS = love.system.getOS()
MOBILE = CURRENT_OS == "Android" or CURRENT_OS == "iOS"
LOADING_IMAGE_FILE = love.graphics.newImage('res/loading.png')
--- Show the loading text while we are loading resources<br>
--- **WARNING**: should only be used while loading the game!
function ShowLoadingText(thing)
love.resize(love.graphics.getDimensions())
love.graphics.replaceTransform(GLOBAL_TRANSFORM)
love.graphics.setFont(love.graphics.newFont(20))
love.graphics.clear()
love.graphics.draw(LOADING_IMAGE_FILE,0,0,0,0.5)
drawText("Loading ".. thing .. "...", 15, 455, 1e99, "left")
love.graphics.flushBatch()
love.graphics.present()
end
LILY = require "libs.lily"
function love.load()
require 'funcs'
@@ -53,17 +40,7 @@ function love.load()
require "game.vctrl" -- VCTRL
SCENE = LoadingScene()
-- VCTRL.new{ -- up down left right --- right left down up
-- -- {type='button',x= 100,y=320,key= 'up',r=35,iconSize=60,alpha=0.75},
-- -- {type='button',x= 100,y=440,key= 'down',r=35,iconSize=60,alpha=0.75},
-- -- {type='button',x= 40,y=380,key= 'left',r=35,iconSize=60,alpha=0.75},
-- -- {type='button',x= 160,y=380,key= 'right',r=35,iconSize=60,alpha=0.75},
-- -- {type='button',x=640- 40,y=380,key= 'rotate_left',r=35,iconSize=60,alpha=0.75},
-- -- {type='button',x=640-160,y=380,key= 'rotate_left2',r=35,iconSize=60,alpha=0.75},
-- -- {type='button',x=640-100,y=440,key= 'rotate_right',r=35,iconSize=60,alpha=0.75},
-- -- {type='button',x=640-100,y=320,key='rotate_right2',r=35,iconSize=60,alpha=0.75},
-- }
sceneStack = {SCENE}
VCTRL.new(SETTINGS.input.virtual)
end
@@ -148,7 +125,6 @@ function love.keypressed(key, scancode)
love.resize(love.graphics.getDimensions())
elseif scancode == "f2" and SCENE.title ~= "Input Config" and SCENE.title ~= "Game" then
SCENE = InputConfigScene()
elseif scancode == "f3" then SCENE = DataManagementScene()
elseif scancode == "f12" then LLDEBUGGER.requestBreak()
-- elseif scancode == "f11" then SETTINGS.firstTime = true
-- function keys are reserved
@@ -305,6 +281,10 @@ end
function love.focus(f) end
function love.quit()
LILY.quit()
end
local TARGET_FPS = 60
function love.run()
@@ -329,6 +309,7 @@ function love.run()
end
end
if SCENE and SCENE.update and love.timer then
SCENE:update()
@@ -433,7 +414,7 @@ function love.errorhandler(msg)
love.graphics.setColor(1, 1, 1)
love.graphics.draw(screenshot_canva, 0, 0, 0, screenshot_canva_scale)
if not showScreenshot then
love.graphics.setColor(0, 0, 0, 0.75)
love.graphics.rectangle("fill", 0, 0, 640, 480)
@@ -589,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
main_bg_cur_mino = 1
end
main_bg_placed = false
main_bg_draw_frame = main_bg_draw_frame + 1
end

View File

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

View File

@@ -26,7 +26,7 @@ local data_explaination = {
local NULL = function() end
local settings_func = {
function() love.system.openURL(love.filesystem.getSaveDirectory()) end,
NULL,
function() return UserManagementScene() end,
function() return EraseHighScoresScene() end,
function() return ResetAllScene() 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'
if PENTO_MODE then
ruleset = require 'game.rotation_pent'
ruleset = require 'game.rotation_big'
else
ruleset = require 'game.rotation'
end
self.retry_mode = game_mode
self.retry_ruleset = ruleset
-- self.secret_inputs = inputs

View File

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

View File

@@ -1,5 +1,6 @@
local KeyConfigScene = SCENE:extend()
KeyConfigScene.title = "Key Config"
local buttonList = {}
local configurable_inputs = {
"menu_decide",
@@ -13,7 +14,6 @@ local configurable_inputs = {
"rotate_right",
"rotate_right2",
}
local input_names = {
menu_decide='Confirm Selection',
menu_back = 'Go Back',
@@ -27,7 +27,6 @@ local input_names = {
rotate_right2='Rotate Clockwise (2)'
}
local function newSetInputs()
local set_inputs = {}
for i, input in ipairs(configurable_inputs) do
@@ -40,6 +39,31 @@ function KeyConfigScene:new()
self.input_state = 1
self.set_inputs = newSetInputs()
self.new_input = {}
self.axis_timer = 0
BUTTON.reset(buttonList)
buttonList = { -- Configuring
BUTTON.new{
text = CHAR.key.tab.."\nTab",
x = 40, y = 300, w = 100, h = 50,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "tab"} end
},
BUTTON.new{
text = CHAR.key.enter_or_return.."\nEnter/Return",
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
},
}
end
function KeyConfigScene:update()
@@ -47,6 +71,10 @@ end
function KeyConfigScene:render()
MainBackground()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 0, 0, 640, 480)
BUTTON.draw(buttonList)
for i, input in ipairs(configurable_inputs) do
drawText(input_names[input], 40, 60 + i * 20, 200, "left")
if self.set_inputs[input] then
@@ -54,15 +82,17 @@ function KeyConfigScene:render()
end
end
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
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
function KeyConfigScene:onInputPress(e)
if e.type == "key" then
if e.type == "mouse" or e.type == "touch" then
BUTTON.press(buttonList, e.x, e.y, e.id)
elseif e.type == "key" then
-- function keys, escape, and tab are reserved and can't be remapped
if e.scancode == "escape" or (self.input_state > #configurable_inputs and e.input == "menu_back") then
SCENE = InputConfigScene(SETTINGS.firstTime)
@@ -72,10 +102,7 @@ function KeyConfigScene:onInputPress(e)
SCENE = SETTINGS.firstTime and TitleScene() or InputConfigScene()
SETTINGS.firstTime = false
elseif e.scancode == "delete" or e.scancode == "backspace" then
-- retry
self.input_state = 1
self.set_inputs = newSetInputs()
self.new_input = {}
self:new() -- retry
end
elseif e.scancode == "tab" then
self.set_inputs[configurable_inputs[self.input_state]] = "skipped"
@@ -86,10 +113,22 @@ function KeyConfigScene:onInputPress(e)
self.new_input[e.scancode] = configurable_inputs[self.input_state]
self.input_state = self.input_state + 1
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.input_state = self.input_state + 1
end
end
function KeyConfigScene:onInputRelease(e)
if e.type == "mouse" or e.type == "touch" then
BUTTON.release(buttonList, e.x, e.y, e.id)
end
end
function KeyConfigScene:onInputMove(e)
if e.type == "mouse" then
BUTTON.checkHovering(buttonList, e.x, e.y)
end
end
return KeyConfigScene

View File

@@ -1,10 +1,21 @@
local LoadingScene = SCENE:extend()
local LoadingImageFile = love.graphics.newImage('res/loading.png')
function LoadingScene.update()
SCENE = SETTINGS.firstTime and InputConfigScene(true) or TitleScene()
if LOADED_BACKGROUND and LOADED_MUSIC then
SCENE = SETTINGS.firstTime and InputConfigScene(true) or TitleScene()
LILY.quit()
end
end
function LoadingScene.render()
love.graphics.draw(LOADING_IMAGE_FILE,0,0,0,0.5)
love.graphics.draw(LoadingImageFile,0,0,0,0.5)
drawText(
("Background: %s\nMusic & SFX: %s"):format(
LOADED_BACKGROUND and "loaded" or "...",
LOADED_MUSIC and "loaded" or "..."
),
15, 400, 1e99, "left"
)
end
return LoadingScene

View File

@@ -37,12 +37,12 @@ local Grid = require 'game.grid'
function NameEntryScene:new()
VCTRL.toggle(false)
self.chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890."
self.char_pos = 1
self.name_entry = {'A','A','A'}
self.entry_pos = 1
self.entry_chars = self.name_entry[1]..self.name_entry[2]..self.name_entry[3]
self.entry_chars = table.concat(self.name_entry, '', 1, 3)
self.grid = Grid(10, 20)
self.repeat_limit = 10
self.repeat_counter = self.repeat_limit-1
@@ -79,7 +79,7 @@ end
function NameEntryScene:render()
MainBackground()
BUTTON.draw(buttonList)
love.graphics.setColor(1, 1, 1, 1)
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))
@@ -130,7 +130,7 @@ function NameEntryScene:update()
end
self.repeat_counter = self.repeat_counter + 1
end
self.entry_chars = self.name_entry[1]..self.name_entry[2]..self.name_entry[3]
self.entry_chars = table.concat(self.name_entry, '', 1, 3)
end
function NameEntryScene:onInputMove(e)
@@ -146,38 +146,24 @@ function NameEntryScene:getPlayInfo(player_name)
self.wins = grade_history[2]
self.plays = grade_history[4]
else
self.grade, self.win, self.plays = 0, 0, 0
self.grade, self.wins, 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])
local name = string.lower(table.concat(self.name_entry, '', 1, 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 self:getPlayInfo(name)
elseif 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
self.entry_pos = self.entry_pos + 1
elseif e.input == "left" or e.scancode == "left" then
self.direction = "left"
elseif e.input == "right" or e.scancode == "right" then
@@ -193,12 +179,27 @@ function NameEntryScene:onInputPress(e)
self.entry_pos = self.entry_pos - 1
self.grade = 0
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
function NameEntryScene:onInputRelease(e)
if e.type == "mouse" or e.type == "touch" then
BUTTON.release(buttonList, e.x, e.y, e.id)
elseif (
MOBILE and not SETTINGS.tvMode and
self.entry_pos == 4
) then love.keyboard.setTextInput(false)
elseif e.input == "left" or e.scancode == "left" or e.input == "right" or e.scancode == "right" then
self.direction = nil
self.repeat_counter = self.repeat_limit-1

View File

@@ -4,38 +4,41 @@ ReplaySelectScene.title = "Replay"
local replay_list
local buttonList = {
BUTTON.new{
text = CHAR.key.up.."\nUP", font = FONT_big,
x = 425, y = 80, w = 80, h = 80,
codeWhenPressed = function() SCENE:onInputPress {input = "up"} end,
codeWhenReleased = function() SCENE:onInputRelease{input = "up"} end
x = 325, y = 375, w = 100, h = 30,
text = CHAR.key.up.." Page up",
codeWhenReleased = function() SCENE:onInputPress{input = "left"} end
},
BUTTON.new{
text = CHAR.key.down.."\nDOWN", font = FONT_big,
x = 425, y = 240, w = 80, h = 80,
codeWhenPressed = function() SCENE:onInputPress {input = "down"} end,
codeWhenReleased = function() SCENE:onInputRelease{input = "down"} end
x = 435, y = 375, w = 100, h = 30,
text = CHAR.key.down.." Page down",
codeWhenReleased = function() SCENE:onInputPress{input = "right"} end
},
BUTTON.new{
text = CHAR.icon.play.."\nPLAY", font = FONT_big,
x = 345, y = 160, w = 80, h = 80,
x = 105, y = 375, w = 100, h = 30,
text = CHAR.icon.play.." Play",
codeWhenPressed = function() SCENE:onInputPress {input = "menu_decide"} end,
codeWhenReleased = function() SCENE:onInputRelease{input = "menu_decide"} end
},
BUTTON.new{
text = CHAR.icon.home.."\nHOME", font = FONT_big,
x = 505, y = 160, w = 80, h = 80,
x = 105, y = 415, w = 100, h = 45,
text = CHAR.icon.home.." Home",
codeWhenPressed = function() SCENE:onInputPress {input = "menu_back"} end,
codeWhenReleased = function() SCENE:onInputRelease{input = "menu_back"} end
},
BUTTON.new{
text = CHAR.icon.export.."\nEXP.", font = FONT_big,
x = 345, y = 320, w = 80, h = 80,
x = 215, y = 415, w = 100, h = 45,
text = CHAR.icon.save.." Converter",
codeWhenReleased = function() love.system.openURL("https://sweetsea-butimnotsweet.github.io/tromi_replay_converter/") end
},
BUTTON.new{
x = 325, y = 415, w = 100, h = 45,
text = CHAR.icon.export.." Export\n(R.Left)",
codeWhenPressed = function() SCENE:onInputPress {input = "rotate_left"} end,
codeWhenReleased = function() SCENE:onInputRelease{input = "rotate_left"} end
},
BUTTON.new{
text = CHAR.icon.import.."\nIMP.", font = FONT_big,
x = 505, y = 320, w = 80, h = 80,
x = 435, y = 415, w = 100, h = 45,
text = CHAR.icon.import.." Import\n(R.Right)",
codeWhenPressed = function() SCENE:onInputPress {input = "rotate_right"} end,
codeWhenReleased = function() SCENE:onInputRelease{input = "rotate_right"} end
},
@@ -43,6 +46,8 @@ local buttonList = {
function ReplaySelectScene:new()
self:initList()
SCENE = self
BUTTON.reset(buttonList)
PENTO_MODE = false
end
@@ -51,7 +56,7 @@ function ReplaySelectScene:initList()
replay_list = love.filesystem.getDirectoryItems('saves/replays/')
table.sort(replay_list, function(a,b) return a > b end)
self.replay_text = {}
self.page_flip = 16
self.page_flip = 10
self.page = 1
local gradeNames = {
"19k", "18k", "17k", "16k", "15k", "14k", "13k", "12k", "11k",
@@ -81,29 +86,32 @@ end
function ReplaySelectScene:render()
MainBackground()
love.graphics.setColor(0.4, 1, 1, 0.5)
love.graphics.rectangle("fill", 0, 20 + 20 * self.replay_select, 640, 22)
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 0, 0, 640, 480)
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(string.format('Page %s/%s', self.page, math.floor(#self.replays / self.page_flip) + 1), 20, 440, 1000, "left")
drawText('Name - Grade - Score', 40, 20, 1000, "left")
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
while i <= #self.replay_text do
if j > self.page_flip then j = 1
elseif j < 1 then j = self.page_flip
local i, j = 1, 1
while i <= #self.replay_text do
if j > self.page_flip then j = 1
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
if i > (self.page-1) * self.page_flip and i <= self.page * self.page_flip then
drawText(self.replay_text[i], 40, 20 + 20 * j, 1000, "left")
end
j = j + 1
i = i + 1
end
if self.replays[1] == nil then
else
drawText('No replays yet!', 40, 40, 1000, "left")
end
BUTTON.draw(buttonList)
end
function ReplaySelectScene:update()
@@ -145,8 +153,19 @@ function ReplaySelectScene:onInputPress(e)
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)]
if e.type == "touch" or e.type == "mouse" then
BUTTON.press(buttonList, e.x, e.y, e.id)
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)
if (
selection >= 1 and
selection <= self.repeat_limit and
selection + ((self.page-1) * self.page_flip) <= #replay_list
) then
self.replay_select = selection
end
elseif e.input == "menu_decide" or e.scancode == "return" then
if self.replays[1] == nil then SCENE = TitleScene(); return
else
@@ -183,6 +202,22 @@ function ReplaySelectScene:onInputPress(e)
elseif e.input == "down" or e.scancode == "down" then
if self.replays[1] == nil then SCENE = TitleScene(); return end
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
SCENE = TitleScene()
end

View File

@@ -5,7 +5,6 @@ local error_message
local valid_data
local prev_scene
function ReplayTestScene:new(input_file)
prev_scene = SCENE
@@ -36,7 +35,7 @@ function ReplayTestScene:render()
if valid_data 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(error_message, 80, 100, 560)
else

View File

@@ -12,7 +12,7 @@ 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",
"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"
}

View File

@@ -1,5 +1,6 @@
local StickConfigScene = SCENE:extend()
StickConfigScene.title = "Controller Config"
local buttonList = {}
local configurable_inputs = {
"menu_decide",
@@ -13,7 +14,6 @@ local configurable_inputs = {
"rotate_right",
"rotate_right2",
}
local input_names = {
menu_decide='Confirm Selection',
menu_back = 'Go Back',
@@ -40,6 +40,30 @@ function StickConfigScene:new()
self.set_inputs = newSetInputs()
self.new_input = {}
self.axis_timer = 0
BUTTON.reset(buttonList)
buttonList = { -- Configuring
BUTTON.new{
text = CHAR.key.tab.."\nTab",
x = 40, y = 300, w = 100, h = 50,
codeWhenReleased = function() self:onInputPress{type = "key", scancode = "tab"} end
},
BUTTON.new{
text = CHAR.key.enter_or_return.."\nEnter/Return",
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
},
}
end
function StickConfigScene:update()
@@ -47,6 +71,10 @@ end
function StickConfigScene:render()
MainBackground()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 0, 0, 640, 480)
BUTTON.draw(buttonList)
for i, input in ipairs(configurable_inputs) do
drawText(input_names[input], 40, 60 + i * 20, 200, "left")
if self.set_inputs[input] then
@@ -54,7 +82,7 @@ function StickConfigScene:render()
end
end
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
drawText("Press joystick input for " .. input_names[configurable_inputs[self.input_state]] .. ", tab to skip, escape to cancel", 0, 0, 1000)
end
@@ -69,22 +97,19 @@ local function addJoystick(input, name)
end
function StickConfigScene:onInputPress(e)
if e.type == "key" then
if e.type == "mouse" or e.type == "touch" then
BUTTON.press(buttonList, e.x, e.y, e.id)
elseif e.type == "key" then
-- function keys, escape, and tab are reserved and can't be remapped
if e.scancode == "escape" or (self.input_state > #configurable_inputs and e.input == "menu_back") then
SCENE = InputConfigScene()
SCENE = InputConfigScene(SETTINGS.firstTime)
elseif self.input_state > #configurable_inputs then
if e.scancode == "return" or e.input == "" then
-- save new input, then load next scene
local had_config = SETTINGS.input ~= nil
if not SETTINGS.input then SETTINGS.input = {} end
if e.scancode == "return" or e.input == "menu_decide" then
SETTINGS.input.joysticks = self.new_input
SCENE = had_config and InputConfigScene() or TitleScene()
SCENE = SETTINGS.firstTime and TitleScene() or InputConfigScene()
SETTINGS.firstTime = false
elseif e.scancode == "delete" or e.scancode == "backspace" then
-- retry
self.input_state = 1
self.set_inputs = newSetInputs()
self.new_input = {}
self:new() -- retry
end
else -- Other keys - skip
self.set_inputs[configurable_inputs[self.input_state]] = "skipped"
@@ -149,4 +174,16 @@ function StickConfigScene:onInputPress(e)
end
end
function StickConfigScene:onInputRelease(e)
if e.type == "mouse" or e.type == "touch" then
BUTTON.release(buttonList, e.x, e.y, e.id)
end
end
function StickConfigScene:onInputMove(e)
if e.type == "mouse" then
BUTTON.checkHovering(buttonList, e.x, e.y)
end
end
return StickConfigScene

View File

@@ -25,7 +25,7 @@ local main_menu_scenes = {
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,
@@ -39,7 +39,7 @@ local main_menu_icons = {
CHAR.icon.export,
CHAR.icon.home,
CHAR.icon.info,
CHAR.icon.toDown,
CHAR.icon.globe,
CHAR.icon.settings,
@@ -52,7 +52,7 @@ function Title2Scene:new()
love.audio.stop()
end
self.main_menu_state = 1
PENTO_MODE = false
PENTO_MODE = true
input_code = {0,0,0,0,0,0,0,0}
end
@@ -63,13 +63,13 @@ 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("Mobile 1.4 - PC 2.3", 150, 78, 200, "left")
drawText("https://mycophobia.org\nhttps://github.com/SweetSea-ButImNotSweet/", 40, 100, 300, "left")
if PENTO_MODE then
@@ -109,7 +109,7 @@ local function checkCode(c)
if (
code_string == "-1,-1,-1,-1,1,1,1,1" or
code_string == "2,2,2,2,2,2,2,2"
) then
) then
PENTO_MODE = true
end
end

View File

@@ -13,7 +13,7 @@ function TrainingScene:new()
game_mode = require 'game.gamemode'
if PENTO_MODE then
ruleset = require 'game.rotation_pent'
ruleset = require 'game.rotation_big'
else
ruleset = require 'game.rotation'
end
@@ -54,7 +54,7 @@ end
function TrainingScene:onInputPress(e)
if e.type == "mouse" or (e.type == "touch" and not VCTRL.press(e.x, e.y, e.id)) then
menuKey:press(e.x, e.y, e.id)
elseif (self.game.game_over or self.game.completed) and (e.input == "menu_decide" or e.input == "menu_back" or e.input == "rotate_right") and self.game.game_over_frames > 50 then
elseif (self.game.game_over or self.game.completed) and (e.input == "menu_back" or e.input == "rotate_right") and self.game.game_over_frames > 50 then
SCENE = TitleScene()
elseif (e.input == "menu_back") then
SCENE = TitleScene()

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 514 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 KiB