mirror of
https://github.com/SashLilac/cambridge.git
synced 2025-05-13 20:21:25 -05:00
Compare commits
32 Commits
v0.3-beta5
...
v0.3-beta6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fbfbd5cda | ||
|
|
c5c4c4d95c | ||
|
|
53c51c2062 | ||
|
|
e4eb9972e6 | ||
|
|
7dbfe23059 | ||
|
|
61d5410f22 | ||
|
|
2cb0416548 | ||
| 83f3e297ce | |||
|
|
8fb01dc9a8 | ||
|
|
61de3c6dbf | ||
|
|
3c718c38e4 | ||
|
|
d18c3e298d | ||
|
|
33934bfb53 | ||
|
|
3e2d107687 | ||
|
|
312b95728d | ||
|
|
5013443302 | ||
|
|
a8ac8f5966 | ||
|
|
a5032386e6 | ||
|
|
264255290d | ||
|
|
a5839bede2 | ||
|
|
4ebf24316a | ||
|
|
f2acab4496 | ||
| 929069c1b6 | |||
|
|
3f2b38f7b3 | ||
|
|
56fb5aebea | ||
|
|
6c201596b0 | ||
|
|
50466c5902 | ||
| ae1231c47a | |||
|
|
366ac1d552 | ||
| 302353f716 | |||
|
|
7f550b629f | ||
|
|
6b2252e6d9 |
51
README.md
51
README.md
@@ -5,24 +5,12 @@ Cambridge
|
|||||||
|
|
||||||
Welcome to Cambridge, the next open-source falling-block game engine!
|
Welcome to Cambridge, the next open-source falling-block game engine!
|
||||||
|
|
||||||
The project is written and maintained exclusively by [SashLilac](https://github.com/SashLilac), [joezeng](https://github.com/joezeng) and [Oshisaure](https://github.com/oshisaure)!
|
The project is written and maintained exclusively by [Milla](https://github.com/MillaBasset), [joezeng](https://github.com/joezeng) and [Oshisaure](https://github.com/oshisaure)!
|
||||||
|
|
||||||
The Discord server has been reopened! https://discord.gg/AADZUmgsph
|
The Discord server has been reopened! https://discord.gg/AADZUmgsph
|
||||||
|
|
||||||
The game also has a website now with more detail than seen on this README: https://t-sp.in/cambridge
|
The game also has a website now with more detail than seen on this README: https://t-sp.in/cambridge
|
||||||
|
|
||||||
Credits
|
|
||||||
-------
|
|
||||||
|
|
||||||
- [Lilla Oshisaure](https://www.youtube.com/user/LeSpyroshisaure) for being my co-dev!
|
|
||||||
- [joezeng](https://github.com/joezeng) for the original project, and for offering to help with the expansion!
|
|
||||||
- [The Tetra Legends Discord](http://discord.com/invite/7hMx5r2) for supporting me and playtesting!
|
|
||||||
- [The Absolute Plus](https://discord.gg/6Gf2awJ) for being another source of motivation!
|
|
||||||
|
|
||||||
More special thanks can be found in-game, under the "Credits" menu.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Playing the game
|
Playing the game
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
@@ -32,13 +20,13 @@ You do not need LÖVE on Windows, as it comes bundled with the program.
|
|||||||
|
|
||||||
#### Stable release
|
#### Stable release
|
||||||
|
|
||||||
To get the stable release, simply download either `cambridge-win32.zip` (32-bit) or `cambridge-windows.zip` (64-bit) in the [latest release](https://github.com/sashlilac/cambridge/releases/latest).
|
To get the stable release, simply download either `cambridge-win32.zip` (32-bit) or `cambridge-windows.zip` (64-bit) in the [latest release](https://github.com/MillaBasset/cambridge/releases/latest).
|
||||||
|
|
||||||
All assets needed are bundled with the executable.
|
All assets needed are bundled with the executable.
|
||||||
|
|
||||||
#### Bleeding edge
|
#### Bleeding edge
|
||||||
|
|
||||||
If you want the bleeding edge version, download [this](https://github.com/SashLilac/cambridge/archive/master.zip).
|
If you want the bleeding edge version, download [this](https://github.com/MillaBasset/cambridge/archive/master.zip).
|
||||||
|
|
||||||
Extract the ZIP, open a Command Prompt at the folder you extracted Cambridge to, then run this command:
|
Extract the ZIP, open a Command Prompt at the folder you extracted Cambridge to, then run this command:
|
||||||
|
|
||||||
@@ -66,7 +54,7 @@ You can download the .love file in the latest release, and run it with:
|
|||||||
|
|
||||||
Clone the repository in git:
|
Clone the repository in git:
|
||||||
|
|
||||||
git clone https://github.com/SashLilac/cambridge
|
git clone https://github.com/MillaBasset/cambridge
|
||||||
|
|
||||||
Alternatively, download the source code ZIP in the latest release.
|
Alternatively, download the source code ZIP in the latest release.
|
||||||
|
|
||||||
@@ -78,7 +66,7 @@ It should run automatically!
|
|||||||
|
|
||||||
## Installing modpacks
|
## Installing modpacks
|
||||||
|
|
||||||
For instructions on how to install modpacks, go to [this](https://github.com/SashLilac/cambridge-modpack) mod pack to get a taste of the mod potential.
|
For instructions on how to install modpacks, go to [this](https://github.com/MillaBasset/cambridge-modpack) mod pack to get a taste of the mod potential.
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
@@ -90,3 +78,32 @@ community, as well as borrowed from other places, either with licensing
|
|||||||
or as placeholders until suitable material can be found that is properly
|
or as placeholders until suitable material can be found that is properly
|
||||||
licensed. Their original sources, and copyright notices if applicable, are
|
licensed. Their original sources, and copyright notices if applicable, are
|
||||||
listed in the file SOURCES.
|
listed in the file SOURCES.
|
||||||
|
|
||||||
|
Credits
|
||||||
|
-------
|
||||||
|
|
||||||
|
- [Lilla Oshisaure](https://www.youtube.com/user/LeSpyroshisaure) for being my co-dev!
|
||||||
|
- [joezeng](https://github.com/joezeng) for the original project, and for offering to help with the expansion!
|
||||||
|
- [The Tetra Legends Discord](http://discord.com/invite/7hMx5r2) for supporting me and playtesting!
|
||||||
|
- [The Absolute Plus](https://discord.gg/6Gf2awJ) for being another source of motivation!
|
||||||
|
|
||||||
|
More special thanks can be found in-game, under the "Credits" menu.
|
||||||
|
|
||||||
|
Other Notable Games
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
- [TGMsim](https://github.com/2Tie/TGMsim) by 2Tie
|
||||||
|
- [Multimino](https://gamejolt.com/games/multimino/556683) by Axel Fox
|
||||||
|
- [Tetra Legends](https://tetralegends.app) by Dr Ocelot
|
||||||
|
- [ZTrix](https://discord.gg/MGhqCBDGNH) by Electra
|
||||||
|
- [Shiromino](https://github.com/shiromino/shiromino) by Felicity/nightmareci/kdex
|
||||||
|
- [Cursed Blocks](https://github.com/Manabender/Cursed-Blocks) by Manabender
|
||||||
|
- Picoris 1/2 by MarkGamed
|
||||||
|
- [Tetra Online](https://github.com/Juan-Cartes/Tetra-Offline) by Mine
|
||||||
|
- [Techmino](https://discord.gg/6Yuww44tq8) by MrZ
|
||||||
|
- [TETR.IO](https://tetr.io) by osk
|
||||||
|
- [Master of Blocks](https://discord.gg/72FZ49mjWh) by Phoenix Flare
|
||||||
|
- [Spirit Drop](https://rayblastgames.com/spiritdrop.php) by RayRay26
|
||||||
|
- [stackfuse](https://github.com/sinefuse/stackfuse) by sinefuse
|
||||||
|
|
||||||
|

|
||||||
|
|||||||
@@ -12,8 +12,8 @@ local mt = {
|
|||||||
__add = function(lhs, rhs)
|
__add = function(lhs, rhs)
|
||||||
return bigint.add(lhs, rhs)
|
return bigint.add(lhs, rhs)
|
||||||
end,
|
end,
|
||||||
__unm = function()
|
__unm = function(arg)
|
||||||
return bigint.negate(self)
|
return bigint.negate(arg)
|
||||||
end,
|
end,
|
||||||
__sub = function(lhs, rhs)
|
__sub = function(lhs, rhs)
|
||||||
return bigint.subtract(lhs, rhs)
|
return bigint.subtract(lhs, rhs)
|
||||||
@@ -30,8 +30,8 @@ local mt = {
|
|||||||
__pow = function(lhs, rhs)
|
__pow = function(lhs, rhs)
|
||||||
return bigint.exponentiate(lhs, rhs)
|
return bigint.exponentiate(lhs, rhs)
|
||||||
end,
|
end,
|
||||||
__tostring = function()
|
__tostring = function(arg)
|
||||||
return bigint.unserialize(self, "s")
|
return bigint.unserialize(arg, "s")
|
||||||
end,
|
end,
|
||||||
__eq = function(lhs, rhs)
|
__eq = function(lhs, rhs)
|
||||||
return bigint.compare(lhs, rhs, "==")
|
return bigint.compare(lhs, rhs, "==")
|
||||||
|
|||||||
25
load/bgm.lua
25
load/bgm.lua
@@ -9,31 +9,38 @@ local current_bgm = nil
|
|||||||
local bgm_locked = false
|
local bgm_locked = false
|
||||||
|
|
||||||
function switchBGM(sound, subsound)
|
function switchBGM(sound, subsound)
|
||||||
if bgm_locked then return end
|
|
||||||
if current_bgm ~= nil then
|
if current_bgm ~= nil then
|
||||||
current_bgm:stop()
|
current_bgm:stop()
|
||||||
end
|
end
|
||||||
if subsound ~= nil then
|
if bgm_locked or config.bgm_volume <= 0 then
|
||||||
current_bgm = bgm[sound][subsound]
|
current_bgm = nil
|
||||||
resetBGMFadeout()
|
|
||||||
elseif sound ~= nil then
|
elseif sound ~= nil then
|
||||||
current_bgm = bgm[sound]
|
if subsound ~= nil then
|
||||||
resetBGMFadeout()
|
current_bgm = bgm[sound][subsound]
|
||||||
|
else
|
||||||
|
current_bgm = bgm[sound]
|
||||||
|
end
|
||||||
else
|
else
|
||||||
current_bgm = nil
|
current_bgm = nil
|
||||||
end
|
end
|
||||||
|
if current_bgm ~= nil then
|
||||||
|
resetBGMFadeout()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function switchBGMLoop(sound, subsound)
|
function switchBGMLoop(sound, subsound)
|
||||||
if bgm_locked then return end
|
|
||||||
switchBGM(sound, subsound)
|
switchBGM(sound, subsound)
|
||||||
current_bgm:setLooping(true)
|
if current_bgm then current_bgm:setLooping(true) end
|
||||||
end
|
end
|
||||||
|
|
||||||
function lockBGM()
|
function lockBGM()
|
||||||
bgm_locked = true
|
bgm_locked = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function unlockBGM()
|
||||||
|
bgm_locked = false
|
||||||
|
end
|
||||||
|
|
||||||
local fading_bgm = false
|
local fading_bgm = false
|
||||||
local fadeout_time = 0
|
local fadeout_time = 0
|
||||||
local total_fadeout_time = 0
|
local total_fadeout_time = 0
|
||||||
@@ -53,7 +60,7 @@ function resetBGMFadeout(time)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function processBGMFadeout(dt)
|
function processBGMFadeout(dt)
|
||||||
if fading_bgm then
|
if current_bgm and fading_bgm then
|
||||||
fadeout_time = fadeout_time - dt
|
fadeout_time = fadeout_time - dt
|
||||||
if fadeout_time < 0 then
|
if fadeout_time < 0 then
|
||||||
fadeout_time = 0
|
fadeout_time = 0
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
local binser = require 'libs.binser'
|
local binser = require 'libs.binser'
|
||||||
|
|
||||||
function loadSave()
|
function loadSave()
|
||||||
local info = love.filesystem.getInfo(love.filesystem.getSaveDirectory())
|
local info = love.filesystem.getInfo(
|
||||||
if not info or info.type ~= "directory" then
|
love.filesystem.getSaveDirectory(), "directory"
|
||||||
|
)
|
||||||
|
if not info then
|
||||||
love.filesystem.remove(love.filesystem.getSaveDirectory())
|
love.filesystem.remove(love.filesystem.getSaveDirectory())
|
||||||
love.filesystem.createDirectory(love.filesystem.getSaveDirectory())
|
love.filesystem.createDirectory(love.filesystem.getSaveDirectory())
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,33 +27,37 @@ sounds = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function playSE(sound, subsound)
|
function playSE(sound, subsound)
|
||||||
if subsound == nil then
|
if sound ~= nil then
|
||||||
sounds[sound]:setVolume(config.sfx_volume)
|
if subsound ~= nil then
|
||||||
if sounds[sound]:isPlaying() then
|
sounds[sound][subsound]:setVolume(config.sfx_volume)
|
||||||
sounds[sound]:stop()
|
if sounds[sound][subsound]:isPlaying() then
|
||||||
|
sounds[sound][subsound]:stop()
|
||||||
|
end
|
||||||
|
sounds[sound][subsound]:play()
|
||||||
|
else
|
||||||
|
sounds[sound]:setVolume(config.sfx_volume)
|
||||||
|
if sounds[sound]:isPlaying() then
|
||||||
|
sounds[sound]:stop()
|
||||||
|
end
|
||||||
|
sounds[sound]:play()
|
||||||
end
|
end
|
||||||
sounds[sound]:play()
|
|
||||||
else
|
|
||||||
sounds[sound][subsound]:setVolume(config.sfx_volume)
|
|
||||||
if sounds[sound][subsound]:isPlaying() then
|
|
||||||
sounds[sound][subsound]:stop()
|
|
||||||
end
|
|
||||||
sounds[sound][subsound]:play()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function playSEOnce(sound, subsound)
|
function playSEOnce(sound, subsound)
|
||||||
if subsound == nil then
|
if sound ~= nil then
|
||||||
sounds[sound]:setVolume(config.sfx_volume)
|
if subsound ~= nil then
|
||||||
if sounds[sound]:isPlaying() then
|
sounds[sound][subsound]:setVolume(config.sfx_volume)
|
||||||
return
|
if sounds[sound][subsound]:isPlaying() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
sounds[sound][subsound]:play()
|
||||||
|
else
|
||||||
|
sounds[sound]:setVolume(config.sfx_volume)
|
||||||
|
if sounds[sound]:isPlaying() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
sounds[sound]:play()
|
||||||
end
|
end
|
||||||
sounds[sound]:play()
|
|
||||||
else
|
|
||||||
sounds[sound][subsound]:setVolume(config.sfx_volume)
|
|
||||||
if sounds[sound][subsound]:isPlaying() then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
sounds[sound][subsound]:play()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1 +1 @@
|
|||||||
version = "v0.3-beta5.2"
|
version = "v0.3-beta6"
|
||||||
135
main.lua
135
main.lua
@@ -18,9 +18,9 @@ function love.load()
|
|||||||
--config["fullscreen"] = false
|
--config["fullscreen"] = false
|
||||||
|
|
||||||
love.window.setMode(love.graphics.getWidth(), love.graphics.getHeight(), {resizable = true});
|
love.window.setMode(love.graphics.getWidth(), love.graphics.getHeight(), {resizable = true});
|
||||||
|
|
||||||
-- used for screenshots
|
-- used for screenshots
|
||||||
GLOBAL_CANVAS = love.graphics.newCanvas()
|
GLOBAL_CANVAS = love.graphics.newCanvas()
|
||||||
|
|
||||||
-- init config
|
-- init config
|
||||||
initConfig()
|
initConfig()
|
||||||
@@ -55,49 +55,11 @@ function initModules()
|
|||||||
return tostring(a.name):gsub("%d+",padnum) < tostring(b.name):gsub("%d+",padnum) end)
|
return tostring(a.name):gsub("%d+",padnum) < tostring(b.name):gsub("%d+",padnum) end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local TARGET_FPS = 60
|
|
||||||
local SAMPLE_SIZE = 60
|
|
||||||
|
|
||||||
local rolling_samples = {}
|
|
||||||
local rolling_total = 0
|
|
||||||
local average_n = 0
|
|
||||||
local frame = 0
|
|
||||||
|
|
||||||
function getSmoothedDt(dt)
|
|
||||||
rolling_total = rolling_total + dt
|
|
||||||
frame = frame + 1
|
|
||||||
if frame > SAMPLE_SIZE then frame = frame - SAMPLE_SIZE end
|
|
||||||
if average_n == SAMPLE_SIZE then
|
|
||||||
rolling_total = rolling_total - rolling_samples[frame]
|
|
||||||
else
|
|
||||||
average_n = average_n + 1
|
|
||||||
end
|
|
||||||
rolling_samples[frame] = dt
|
|
||||||
return rolling_total / average_n
|
|
||||||
end
|
|
||||||
|
|
||||||
local update_time = 0.52
|
|
||||||
|
|
||||||
function love.update(dt)
|
|
||||||
processBGMFadeout(dt)
|
|
||||||
local old_update_time = update_time
|
|
||||||
update_time = update_time + getSmoothedDt(dt) * TARGET_FPS
|
|
||||||
updates = 0
|
|
||||||
while (update_time >= 1.02) do
|
|
||||||
scene:update()
|
|
||||||
updates = updates + 1
|
|
||||||
update_time = update_time - 1
|
|
||||||
end
|
|
||||||
if math.abs(update_time - old_update_time) < 0.02 then
|
|
||||||
update_time = old_update_time
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.draw()
|
function love.draw()
|
||||||
love.graphics.setCanvas(GLOBAL_CANVAS)
|
love.graphics.setCanvas(GLOBAL_CANVAS)
|
||||||
love.graphics.clear()
|
love.graphics.clear()
|
||||||
|
|
||||||
love.graphics.push()
|
love.graphics.push()
|
||||||
|
|
||||||
-- get offset matrix
|
-- get offset matrix
|
||||||
love.graphics.setDefaultFilter("linear", "nearest")
|
love.graphics.setDefaultFilter("linear", "nearest")
|
||||||
@@ -109,13 +71,13 @@ function love.draw()
|
|||||||
(height - scale_factor * 480) / 2
|
(height - scale_factor * 480) / 2
|
||||||
)
|
)
|
||||||
love.graphics.scale(scale_factor)
|
love.graphics.scale(scale_factor)
|
||||||
|
|
||||||
scene:render()
|
scene:render()
|
||||||
love.graphics.pop()
|
love.graphics.pop()
|
||||||
|
|
||||||
love.graphics.setCanvas()
|
love.graphics.setCanvas()
|
||||||
love.graphics.setColor(1,1,1,1)
|
love.graphics.setColor(1,1,1,1)
|
||||||
love.graphics.draw(GLOBAL_CANVAS)
|
love.graphics.draw(GLOBAL_CANVAS)
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.keypressed(key, scancode)
|
function love.keypressed(key, scancode)
|
||||||
@@ -134,16 +96,16 @@ function love.keypressed(key, scancode)
|
|||||||
scene.restart_message = true
|
scene.restart_message = true
|
||||||
if config.secret then playSE("mode_decide")
|
if config.secret then playSE("mode_decide")
|
||||||
else playSE("erase") end
|
else playSE("erase") end
|
||||||
-- f12 is reserved for saving screenshots
|
-- f12 is reserved for saving screenshots
|
||||||
elseif scancode == "f12" then
|
elseif scancode == "f12" then
|
||||||
local ss_name = os.date("ss/%Y-%m-%d_%H-%M-%S.png")
|
local ss_name = os.date("ss/%Y-%m-%d_%H-%M-%S.png")
|
||||||
local info = love.filesystem.getInfo("ss")
|
local info = love.filesystem.getInfo("ss", "directory")
|
||||||
if not info or info.type ~= "directory" then
|
if not info then
|
||||||
love.filesystem.remove("ss")
|
love.filesystem.remove("ss")
|
||||||
love.filesystem.createDirectory("ss")
|
love.filesystem.createDirectory("ss")
|
||||||
end
|
end
|
||||||
print("Saving screenshot as "..ss_name)
|
print("Saving screenshot as "..ss_name)
|
||||||
GLOBAL_CANVAS:newImageData():encode("png", ss_name)
|
GLOBAL_CANVAS:newImageData():encode("png", ss_name)
|
||||||
-- function keys are reserved
|
-- function keys are reserved
|
||||||
elseif string.match(scancode, "^f[1-9]$") or string.match(scancode, "^f[1-9][0-9]+$") then
|
elseif string.match(scancode, "^f[1-9]$") or string.match(scancode, "^f[1-9][0-9]+$") then
|
||||||
return
|
return
|
||||||
@@ -305,6 +267,59 @@ function love.focus(f)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function love.resize(w, h)
|
function love.resize(w, h)
|
||||||
GLOBAL_CANVAS:release()
|
GLOBAL_CANVAS:release()
|
||||||
GLOBAL_CANVAS = love.graphics.newCanvas(w, h)
|
GLOBAL_CANVAS = love.graphics.newCanvas(w, h)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local TARGET_FPS = 60
|
||||||
|
|
||||||
|
function love.run()
|
||||||
|
if love.load then love.load(love.arg.parseGameArguments(arg), arg) end
|
||||||
|
|
||||||
|
if love.timer then love.timer.step() end
|
||||||
|
|
||||||
|
local dt = 0
|
||||||
|
|
||||||
|
local last_time = love.timer.getTime()
|
||||||
|
local time_accumulator = 0
|
||||||
|
return function()
|
||||||
|
if love.event then
|
||||||
|
love.event.pump()
|
||||||
|
for name, a,b,c,d,e,f in love.event.poll() do
|
||||||
|
if name == "quit" then
|
||||||
|
if not love.quit or not love.quit() then
|
||||||
|
return a or 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
love.handlers[name](a,b,c,d,e,f)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if love.timer then
|
||||||
|
processBGMFadeout(love.timer.step())
|
||||||
|
end
|
||||||
|
|
||||||
|
if scene and scene.update and love.timer then
|
||||||
|
scene:update()
|
||||||
|
|
||||||
|
local frame_duration = 1.0 / TARGET_FPS
|
||||||
|
if time_accumulator < frame_duration then
|
||||||
|
if love.graphics and love.graphics.isActive() and love.draw then
|
||||||
|
love.graphics.origin()
|
||||||
|
love.graphics.clear(love.graphics.getBackgroundColor())
|
||||||
|
love.draw()
|
||||||
|
love.graphics.present()
|
||||||
|
end
|
||||||
|
local end_time = last_time + frame_duration
|
||||||
|
local time = love.timer.getTime()
|
||||||
|
while time < end_time do
|
||||||
|
love.timer.sleep(0.001)
|
||||||
|
time = love.timer.getTime()
|
||||||
|
end
|
||||||
|
time_accumulator = time_accumulator + time - last_time
|
||||||
|
end
|
||||||
|
time_accumulator = time_accumulator - frame_duration
|
||||||
|
end
|
||||||
|
last_time = love.timer.getTime()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ CreditsScene.title = "Credits"
|
|||||||
|
|
||||||
function CreditsScene:new()
|
function CreditsScene:new()
|
||||||
self.frames = 0
|
self.frames = 0
|
||||||
|
-- higher = slower
|
||||||
|
self.scroll_speed = 1.9
|
||||||
switchBGM("credit_roll", "gm3")
|
switchBGM("credit_roll", "gm3")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -11,16 +13,18 @@ function CreditsScene:update()
|
|||||||
if love.window.hasFocus() then
|
if love.window.hasFocus() then
|
||||||
self.frames = self.frames + 1
|
self.frames = self.frames + 1
|
||||||
end
|
end
|
||||||
if self.frames >= 4200 then
|
if self.frames >= 2100 * self.scroll_speed then
|
||||||
playSE("mode_decide")
|
playSE("mode_decide")
|
||||||
scene = TitleScene()
|
scene = TitleScene()
|
||||||
switchBGM(nil)
|
switchBGM(nil)
|
||||||
elseif self.frames == 3600 then
|
elseif self.frames == math.floor(1950 * self.scroll_speed) then
|
||||||
fadeoutBGM(2)
|
fadeoutBGM(2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function CreditsScene:render()
|
function CreditsScene:render()
|
||||||
|
local offset = self.frames / self.scroll_speed
|
||||||
|
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
love.graphics.draw(
|
love.graphics.draw(
|
||||||
backgrounds[19],
|
backgrounds[19],
|
||||||
@@ -29,36 +33,43 @@ function CreditsScene:render()
|
|||||||
)
|
)
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_4)
|
love.graphics.setFont(font_3x5_4)
|
||||||
love.graphics.print("Cambridge Credits", 320, 500 - self.frames / 2)
|
love.graphics.print("Cambridge Credits", 320, 500 - offset)
|
||||||
love.graphics.print("THANK YOU\nFOR PLAYING!", 320, math.max(1770 - self.frames / 2, 240))
|
love.graphics.print("THANK YOU\nFOR PLAYING!", 320, math.max(2010 - offset, 240))
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_3)
|
love.graphics.setFont(font_3x5_3)
|
||||||
love.graphics.print("Game Developers", 320, 550 - self.frames / 2)
|
love.graphics.print("Game Developers", 320, 550 - offset)
|
||||||
love.graphics.print("Project Heads", 320, 640 - self.frames / 2)
|
love.graphics.print("Project Heads", 320, 640 - offset)
|
||||||
love.graphics.print("Other Game Developers", 320, 730 - self.frames / 2)
|
love.graphics.print("Notable Game Developers", 320, 730 - offset)
|
||||||
love.graphics.print("Special Thanks", 320, 950 - self.frames / 2)
|
love.graphics.print("Special Thanks", 320, 980 - offset)
|
||||||
love.graphics.print("- SashLilac / TS3 / Milla", 320, math.max(1850 - self.frames / 2, 320))
|
love.graphics.print("- Milla", 320, math.max(2090 - offset, 320))
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_2)
|
love.graphics.setFont(font_3x5_2)
|
||||||
love.graphics.print("Oshisaure\nJoe Zeng", 320, 590 - self.frames / 2)
|
love.graphics.print("Oshisaure\nJoe Zeng", 320, 590 - offset)
|
||||||
love.graphics.print("Mizu\nHailey", 320, 680 - self.frames / 2)
|
love.graphics.print("Mizu\nMarkGamed", 320, 680 - offset)
|
||||||
love.graphics.print(
|
love.graphics.print(
|
||||||
"Axel Fox - Multimino\nMine - Tetra Online\nDr Ocelot - Tetra Legends\n" ..
|
"2Tie - TGMsim\nAxel Fox - Multimino\nDr Ocelot - Tetra Legends\n" ..
|
||||||
"Felicity / nightmareci - Shiromino\n2Tie - TGMsim\nPhoenix Flare - Master of Blocks\n" ..
|
"Electra - ZTrix\nFelicity/nightmareci/kdex - Shiromino\n" ..
|
||||||
"RayRay26 - Spirit Drop\nosk - TETR.IO\nMarkGamed7794 - Picoris 2",
|
"Mine - Tetra Online\nMrZ - Techmino\nosk - TETR.IO\n" ..
|
||||||
320, 770 - self.frames / 2
|
"Phoenix Flare - Master of Blocks\nRayRay26 - Spirit Drop\n" ..
|
||||||
|
"sinefuse - stackfuse",
|
||||||
|
320, 770 - offset
|
||||||
)
|
)
|
||||||
love.graphics.print(
|
love.graphics.print(
|
||||||
"RocketLanterns\nCylinderKnot\nHammrTime\nKirby703\nMattMayuga\nMyPasswordIsWeak\n" ..
|
"321MrHaatz\nAdventium\nAgentBasey\nArchina\nAurora\n" ..
|
||||||
"Nikki Karissa\noffwo\nsinefuse\nTetro48\nTimmSkiller\nuser74003\nAgentBasey\n" ..
|
"Caithness\nCheez\ncolour_thief\nCommando\nCublex\n" ..
|
||||||
"CheeZed_Fish\neightsixfivezero\nEricICX\ngizmo4487\nM1ssing0\n" ..
|
"CylinderKnot\neightsixfivezero\nEricICX\nGesomaru\n" ..
|
||||||
"pokemonfan1937\nSimon\nstratus\nZaptorZap\nArchina\nOliver\ncolour_thief\n" ..
|
"gizmo4487\nJBroms\nKirby703\nKitaru\n" ..
|
||||||
"Caithness\nkdex\nzid\nsaphie\nSuper302\nAurora\nswitchpalacecorner\nKitaru\n" ..
|
"M1ssing0\nMattMayuga\nMyPasswordIsWeak\n" ..
|
||||||
"JBroms\nMany more I definitely missed!\n" ..
|
"Nikki Karissa\noffwo\nOliver\nPineapple\npokemonfan1937\n" ..
|
||||||
"The Absolute PLUS Discord\nTetra Legends Discord\nTetra Online Discord\n" ..
|
"Pyra Neoxi\nRDST64\nRocketLanterns\nRustyFoxxo\n" ..
|
||||||
"Multimino Discord\nHard Drop Discord\nCambridge Discord\n" ..
|
"saphie\nShelleloch\nSimon\nstratus\nSuper302\n" ..
|
||||||
|
"switchpalacecorner\nterpyderp\nTetrian22\nTetro48\nThatCookie\n" ..
|
||||||
|
"TimmSkiller\nTrixciel\nuser74003\nZaptorZap\nZircean\n" ..
|
||||||
|
"All other contributors and friends!\nThe Absolute PLUS Discord\n" ..
|
||||||
|
"Tetra Legends Discord\nTetra Online Discord\nMultimino Discord\n" ..
|
||||||
|
"Hard Drop Discord\nRusty's Systemspace\nCambridge Discord\n" ..
|
||||||
"And to you, the player!",
|
"And to you, the player!",
|
||||||
320, 990 - self.frames / 2
|
320, 1020 - offset
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -42,79 +42,17 @@ function GameScene:update()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function GameScene:render()
|
function GameScene:render()
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
self.game:draw(self.paused)
|
||||||
love.graphics.draw(
|
|
||||||
backgrounds[self.game:getBackground()],
|
|
||||||
0, 0, 0,
|
|
||||||
0.5, 0.5
|
|
||||||
)
|
|
||||||
|
|
||||||
-- game frame
|
|
||||||
if self.game.grid.width == 10 and self.game.grid.height == 24 then
|
|
||||||
love.graphics.draw(misc_graphics["frame"], 48, 64)
|
|
||||||
end
|
|
||||||
|
|
||||||
love.graphics.setColor(0, 0, 0, 200)
|
|
||||||
love.graphics.rectangle(
|
|
||||||
"fill", 64, 80,
|
|
||||||
16 * self.game.grid.width, 16 * (self.game.grid.height - 4)
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.game.grid.width ~= 10 or self.game.grid.height ~= 24 then
|
|
||||||
love.graphics.setColor(174/255, 83/255, 76/255, 1)
|
|
||||||
love.graphics.setLineWidth(8)
|
|
||||||
love.graphics.line(
|
|
||||||
60,76,
|
|
||||||
68+16*self.game.grid.width,76,
|
|
||||||
68+16*self.game.grid.width,84+16*(self.game.grid.height-4),
|
|
||||||
60,84+16*(self.game.grid.height-4),
|
|
||||||
60,76
|
|
||||||
)
|
|
||||||
love.graphics.setColor(203/255, 137/255, 111/255, 1)
|
|
||||||
love.graphics.setLineWidth(4)
|
|
||||||
love.graphics.line(
|
|
||||||
60,76,
|
|
||||||
68+16*self.game.grid.width,76,
|
|
||||||
68+16*self.game.grid.width,84+16*(self.game.grid.height-4),
|
|
||||||
60,84+16*(self.game.grid.height-4),
|
|
||||||
60,76
|
|
||||||
)
|
|
||||||
love.graphics.setLineWidth(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.game:drawGrid()
|
|
||||||
if self.game.lcd > 0 then self.game:drawLineClearAnimation() end
|
|
||||||
self.game:drawPiece()
|
|
||||||
self.game:drawNextQueue(self.ruleset)
|
|
||||||
self.game:drawScoringInfo()
|
|
||||||
|
|
||||||
-- ready/go graphics
|
|
||||||
|
|
||||||
if self.game.ready_frames <= 100 and self.game.ready_frames > 52 then
|
|
||||||
love.graphics.draw(misc_graphics["ready"], 144 - 50, 240 - 14)
|
|
||||||
elseif self.game.ready_frames <= 50 and self.game.ready_frames > 2 then
|
|
||||||
love.graphics.draw(misc_graphics["go"], 144 - 27, 240 - 14)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.game:drawCustom()
|
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_2)
|
|
||||||
if config.gamesettings.display_gamemode == 1 then
|
|
||||||
love.graphics.printf(self.game.name .. " - " .. self.ruleset.name, 0, 460, 640, "left")
|
|
||||||
end
|
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_3)
|
|
||||||
if self.paused then love.graphics.print("PAUSED!", 80, 100) end
|
|
||||||
|
|
||||||
if self.game.completed then
|
|
||||||
self.game:onGameComplete()
|
|
||||||
elseif self.game.game_over then
|
|
||||||
self.game:onGameOver()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function GameScene:onInputPress(e)
|
function GameScene:onInputPress(e)
|
||||||
if (self.game.game_over or self.game.completed) and (e.input == "menu_decide" or e.input == "menu_back" or e.input == "retry") then
|
if (
|
||||||
|
self.game.game_over or self.game.completed
|
||||||
|
) and (
|
||||||
|
e.input == "menu_decide" or
|
||||||
|
e.input == "menu_back" or
|
||||||
|
e.input == "retry"
|
||||||
|
) then
|
||||||
highscore_entry = self.game:getHighscoreData()
|
highscore_entry = self.game:getHighscoreData()
|
||||||
highscore_hash = self.game.hash .. "-" .. self.ruleset.hash
|
highscore_hash = self.game.hash .. "-" .. self.ruleset.hash
|
||||||
submitHighscore(highscore_hash, highscore_entry)
|
submitHighscore(highscore_hash, highscore_entry)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ ConfigScene.options = {
|
|||||||
{"smooth_movement", "Smooth Piece Drop", false, {"On", "Off"}},
|
{"smooth_movement", "Smooth Piece Drop", false, {"On", "Off"}},
|
||||||
{"synchroes_allowed", "Synchroes", false, {"Per ruleset", "On", "Off"}},
|
{"synchroes_allowed", "Synchroes", false, {"Per ruleset", "On", "Off"}},
|
||||||
{"diagonal_input", "Diagonal Input", false, {"On", "Off"}},
|
{"diagonal_input", "Diagonal Input", false, {"On", "Off"}},
|
||||||
{"buffer_lock", "Buffer Lock Inputs", false, {"On", "Off"}},
|
{"buffer_lock", "Buffer Drop Type", false, {"Off", "Hold", "Tap"}},
|
||||||
{"sfx_volume", "SFX", true, "sfxSlider"},
|
{"sfx_volume", "SFX", true, "sfxSlider"},
|
||||||
{"bgm_volume", "BGM", true, "bgmSlider"},
|
{"bgm_volume", "BGM", true, "bgmSlider"},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ function KeyConfigScene:onInputPress(e)
|
|||||||
elseif e.scancode == "tab" then
|
elseif e.scancode == "tab" then
|
||||||
self.set_inputs[configurable_inputs[self.input_state]] = "skipped"
|
self.set_inputs[configurable_inputs[self.input_state]] = "skipped"
|
||||||
self.input_state = self.input_state + 1
|
self.input_state = self.input_state + 1
|
||||||
elseif e.scancode ~= "escape" then
|
elseif e.scancode ~= "escape" and not self.new_input[e.scancode] then
|
||||||
-- all other keys can be configured
|
-- all other keys can be configured
|
||||||
self.set_inputs[configurable_inputs[self.input_state]] = "key " .. love.keyboard.getKeyFromScancode(e.scancode) .. " (" .. e.scancode .. ")"
|
self.set_inputs[configurable_inputs[self.input_state]] = "key " .. love.keyboard.getKeyFromScancode(e.scancode) .. " (" .. e.scancode .. ")"
|
||||||
self.new_input[e.scancode] = configurable_inputs[self.input_state]
|
self.new_input[e.scancode] = configurable_inputs[self.input_state]
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ function StickConfigScene:onInputPress(e)
|
|||||||
if not self.new_input[e.name].buttons then
|
if not self.new_input[e.name].buttons then
|
||||||
self.new_input[e.name].buttons = {}
|
self.new_input[e.name].buttons = {}
|
||||||
end
|
end
|
||||||
|
if self.new_input[e.name].buttons[e.button] then return end
|
||||||
self.set_inputs[configurable_inputs[self.input_state]] =
|
self.set_inputs[configurable_inputs[self.input_state]] =
|
||||||
"jbtn " ..
|
"jbtn " ..
|
||||||
e.button ..
|
e.button ..
|
||||||
@@ -119,6 +120,9 @@ function StickConfigScene:onInputPress(e)
|
|||||||
if not self.new_input[e.name].axes[e.axis] then
|
if not self.new_input[e.name].axes[e.axis] then
|
||||||
self.new_input[e.name].axes[e.axis] = {}
|
self.new_input[e.name].axes[e.axis] = {}
|
||||||
end
|
end
|
||||||
|
if (
|
||||||
|
self.new_input[e.name].axes[e.axis][e.value >= 1 and "positive" or "negative"]
|
||||||
|
) then return end
|
||||||
self.set_inputs[configurable_inputs[self.input_state]] =
|
self.set_inputs[configurable_inputs[self.input_state]] =
|
||||||
"jaxis " ..
|
"jaxis " ..
|
||||||
(e.value >= 1 and "+" or "-") .. e.axis ..
|
(e.value >= 1 and "+" or "-") .. e.axis ..
|
||||||
@@ -137,6 +141,9 @@ function StickConfigScene:onInputPress(e)
|
|||||||
if not self.new_input[e.name].hats[e.hat] then
|
if not self.new_input[e.name].hats[e.hat] then
|
||||||
self.new_input[e.name].hats[e.hat] = {}
|
self.new_input[e.name].hats[e.hat] = {}
|
||||||
end
|
end
|
||||||
|
if self.new_input[e.name].hats[e.hat][e.direction] then
|
||||||
|
return
|
||||||
|
end
|
||||||
self.set_inputs[configurable_inputs[self.input_state]] =
|
self.set_inputs[configurable_inputs[self.input_state]] =
|
||||||
"jhat " ..
|
"jhat " ..
|
||||||
e.hat .. " " .. e.direction ..
|
e.hat .. " " .. e.direction ..
|
||||||
|
|||||||
@@ -118,10 +118,11 @@ function Piece:lockIfBottomed(grid)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Piece:addGravity(gravity, grid, classic_lock)
|
function Piece:addGravity(gravity, grid, classic_lock)
|
||||||
|
gravity = gravity / (self.big and 2 or 1)
|
||||||
local new_gravity = self.gravity + gravity
|
local new_gravity = self.gravity + gravity
|
||||||
if self:isDropBlocked(grid) then
|
if self:isDropBlocked(grid) then
|
||||||
if classic_lock then
|
if classic_lock then
|
||||||
self.gravity = math.min(1, new_gravity)
|
self.gravity = new_gravity
|
||||||
else
|
else
|
||||||
self.gravity = 0
|
self.gravity = 0
|
||||||
self.lock_delay = self.lock_delay + 1
|
self.lock_delay = self.lock_delay + 1
|
||||||
|
|||||||
@@ -85,10 +85,11 @@ function GameMode:getDasCutDelay() return 0 end
|
|||||||
function GameMode:getGravity() return 1/64 end
|
function GameMode:getGravity() return 1/64 end
|
||||||
|
|
||||||
function GameMode:getNextPiece(ruleset)
|
function GameMode:getNextPiece(ruleset)
|
||||||
|
local shape = self.used_randomizer:nextPiece()
|
||||||
return {
|
return {
|
||||||
skin = self:getSkin(),
|
skin = self:getSkin(),
|
||||||
shape = self.used_randomizer:nextPiece(),
|
shape = shape,
|
||||||
orientation = ruleset:getDefaultOrientation(),
|
orientation = ruleset:getDefaultOrientation(shape),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -156,9 +157,6 @@ function GameMode:update(inputs, ruleset)
|
|||||||
if self.enable_hold and inputs["hold"] == true and self.held == false and self.prev_inputs["hold"] == false then
|
if self.enable_hold and inputs["hold"] == true and self.held == false and self.prev_inputs["hold"] == false then
|
||||||
self:hold(inputs, ruleset)
|
self:hold(inputs, ruleset)
|
||||||
self.prev_inputs = inputs
|
self.prev_inputs = inputs
|
||||||
if not self.grid:canPlacePiece(self.piece) then
|
|
||||||
self.game_over = true
|
|
||||||
end
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -181,7 +179,10 @@ function GameMode:update(inputs, ruleset)
|
|||||||
|
|
||||||
ruleset:processPiece(
|
ruleset:processPiece(
|
||||||
inputs, self.piece, self.grid, self:getGravity(), self.prev_inputs,
|
inputs, self.piece, self.grid, self:getGravity(), self.prev_inputs,
|
||||||
self.move, self:getLockDelay(), self:getDropSpeed(),
|
(
|
||||||
|
inputs.up and self.lock_on_hard_drop and not self.hard_drop_locked
|
||||||
|
) and "none" or self.move,
|
||||||
|
self:getLockDelay(), self:getDropSpeed(),
|
||||||
self.drop_locked, self.hard_drop_locked,
|
self.drop_locked, self.hard_drop_locked,
|
||||||
self.enable_hard_drop, self.additive_gravity, self.classic_lock
|
self.enable_hard_drop, self.additive_gravity, self.classic_lock
|
||||||
)
|
)
|
||||||
@@ -237,6 +238,7 @@ function GameMode:update(inputs, ruleset)
|
|||||||
self.lock_on_soft_drop
|
self.lock_on_soft_drop
|
||||||
then
|
then
|
||||||
self.piece.locked = true
|
self.piece.locked = true
|
||||||
|
self.piece_soft_locked = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -324,11 +326,13 @@ function GameMode:onPieceEnter() end
|
|||||||
function GameMode:onHold() end
|
function GameMode:onHold() end
|
||||||
|
|
||||||
function GameMode:onSoftDrop(dropped_row_count)
|
function GameMode:onSoftDrop(dropped_row_count)
|
||||||
self.drop_bonus = self.drop_bonus + 1 * dropped_row_count
|
self.drop_bonus = self.drop_bonus + (
|
||||||
|
(self.piece.big and 2 or 1) * dropped_row_count
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GameMode:onHardDrop(dropped_row_count)
|
function GameMode:onHardDrop(dropped_row_count)
|
||||||
self.drop_bonus = self.drop_bonus + 2 * dropped_row_count
|
self:onSoftDrop(dropped_row_count * 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GameMode:onGameOver()
|
function GameMode:onGameOver()
|
||||||
@@ -417,26 +421,38 @@ function GameMode:dasCut()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function GameMode:areCancel(inputs, ruleset)
|
function GameMode:areCancel(inputs, ruleset)
|
||||||
if ruleset.are_cancel and self.piece_hard_dropped and
|
if ruleset.are_cancel and strTrueValues(inputs) ~= "" and
|
||||||
not self.prev_inputs.up and
|
not self.prev_inputs.up and
|
||||||
strTrueValues(inputs) ~= "" then
|
(self.piece_hard_dropped or
|
||||||
|
(self.piece_soft_locked and not self.prev_inputs.down)) then
|
||||||
self.lcd = 0
|
self.lcd = 0
|
||||||
self.are = 0
|
self.are = 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function GameMode:checkBufferedInputs(inputs)
|
||||||
|
if (
|
||||||
|
config.gamesettings.buffer_lock ~= 1 and
|
||||||
|
not self.prev_inputs["up"] and inputs["up"] and
|
||||||
|
self.enable_hard_drop
|
||||||
|
) then
|
||||||
|
self.buffer_hard_drop = true
|
||||||
|
end
|
||||||
|
if (
|
||||||
|
config.gamesettings.buffer_lock ~= 1 and
|
||||||
|
not self.prev_inputs["down"] and inputs["down"]
|
||||||
|
) then
|
||||||
|
self.buffer_soft_drop = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function GameMode:processDelays(inputs, ruleset, drop_speed)
|
function GameMode:processDelays(inputs, ruleset, drop_speed)
|
||||||
if self.ready_frames == 100 then
|
if self.ready_frames == 100 then
|
||||||
playedReadySE = false
|
playedReadySE = false
|
||||||
playedGoSE = false
|
playedGoSE = false
|
||||||
end
|
end
|
||||||
if self.ready_frames > 0 then
|
if self.ready_frames > 0 then
|
||||||
if not self.prev_inputs["up"] and inputs["up"] and self.enable_hard_drop then
|
self:checkBufferedInputs(inputs)
|
||||||
self.buffer_hard_drop = true
|
|
||||||
end
|
|
||||||
if not self.prev_inputs["down"] and inputs["down"] then
|
|
||||||
self.buffer_soft_drop = true
|
|
||||||
end
|
|
||||||
if not playedReadySE then
|
if not playedReadySE then
|
||||||
playedReadySE = true
|
playedReadySE = true
|
||||||
playSEOnce("ready")
|
playSEOnce("ready")
|
||||||
@@ -450,12 +466,7 @@ function GameMode:processDelays(inputs, ruleset, drop_speed)
|
|||||||
self:initializeOrHold(inputs, ruleset)
|
self:initializeOrHold(inputs, ruleset)
|
||||||
end
|
end
|
||||||
elseif self.lcd > 0 then
|
elseif self.lcd > 0 then
|
||||||
if not self.prev_inputs["up"] and inputs["up"] and self.enable_hard_drop then
|
self:checkBufferedInputs(inputs)
|
||||||
self.buffer_hard_drop = true
|
|
||||||
end
|
|
||||||
if not self.prev_inputs["down"] and inputs["down"] then
|
|
||||||
self.buffer_soft_drop = true
|
|
||||||
end
|
|
||||||
self.lcd = self.lcd - 1
|
self.lcd = self.lcd - 1
|
||||||
self:areCancel(inputs, ruleset)
|
self:areCancel(inputs, ruleset)
|
||||||
if self.lcd == 0 then
|
if self.lcd == 0 then
|
||||||
@@ -468,12 +479,7 @@ function GameMode:processDelays(inputs, ruleset, drop_speed)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif self.are > 0 then
|
elseif self.are > 0 then
|
||||||
if not self.prev_inputs["up"] and inputs["up"] and self.enable_hard_drop then
|
self:checkBufferedInputs(inputs)
|
||||||
self.buffer_hard_drop = true
|
|
||||||
end
|
|
||||||
if not self.prev_inputs["down"] and inputs["down"] then
|
|
||||||
self.buffer_soft_drop = true
|
|
||||||
end
|
|
||||||
self.are = self.are - 1
|
self.are = self.are - 1
|
||||||
self:areCancel(inputs, ruleset)
|
self:areCancel(inputs, ruleset)
|
||||||
if self.are == 0 then
|
if self.are == 0 then
|
||||||
@@ -494,6 +500,10 @@ function GameMode:initializeOrHold(inputs, ruleset)
|
|||||||
if not self.grid:canPlacePiece(self.piece) then
|
if not self.grid:canPlacePiece(self.piece) then
|
||||||
self.game_over = true
|
self.game_over = true
|
||||||
end
|
end
|
||||||
|
ruleset:dropPiece(
|
||||||
|
inputs, self.piece, self.grid, self:getGravity(),
|
||||||
|
self:getDropSpeed(), self.drop_locked, self.hard_drop_locked
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GameMode:hold(inputs, ruleset, ihs)
|
function GameMode:hold(inputs, ruleset, ihs)
|
||||||
@@ -518,64 +528,55 @@ function GameMode:hold(inputs, ruleset, ihs)
|
|||||||
if ihs then playSE("ihs")
|
if ihs then playSE("ihs")
|
||||||
else playSE("hold") end
|
else playSE("hold") end
|
||||||
self:onHold()
|
self:onHold()
|
||||||
|
if not self.grid:canPlacePiece(self.piece) then
|
||||||
|
self.game_over = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function GameMode:initializeNextPiece(inputs, ruleset, piece_data, generate_next_piece)
|
function GameMode:initializeNextPiece(inputs, ruleset, piece_data, generate_next_piece)
|
||||||
self.piece_hard_dropped = false
|
if not self.buffer_soft_drop and self.lock_drop or (
|
||||||
local gravity = self:getGravity()
|
|
||||||
self.piece = ruleset:initializePiece(
|
|
||||||
inputs, piece_data, self.grid, gravity,
|
|
||||||
self.prev_inputs, self.move,
|
|
||||||
self:getLockDelay(), self:getDropSpeed(),
|
|
||||||
self.lock_drop, self.lock_hard_drop, self.big_mode,
|
|
||||||
(
|
|
||||||
self.frames == 0 or (ruleset.are and self:getARE() ~= 0)
|
|
||||||
) and self.irs or false
|
|
||||||
)
|
|
||||||
if self.buffer_hard_drop then
|
|
||||||
if config.gamesettings.buffer_lock == 1 then
|
|
||||||
self.piece:dropToBottom(self.grid)
|
|
||||||
if self.lock_on_hard_drop then self.piece.locked = true end
|
|
||||||
end
|
|
||||||
local above_field = (
|
|
||||||
(config.gamesettings.spawn_positions == 1 and
|
|
||||||
ruleset.spawn_above_field) or
|
|
||||||
config.gamesettings.spawn_positions == 3
|
|
||||||
)
|
|
||||||
self:onHardDrop(self.piece.position.y - (
|
|
||||||
self.piece.big and
|
|
||||||
ruleset.big_spawn_positions[self.piece.shape].y or
|
|
||||||
ruleset.spawn_positions[self.piece.shape].y) +
|
|
||||||
(above_field and ruleset:getAboveFieldOffset(
|
|
||||||
piece_data.shape, piece_data.orientation
|
|
||||||
) or 0)
|
|
||||||
)
|
|
||||||
self.buffer_hard_drop = false
|
|
||||||
end
|
|
||||||
if self.buffer_soft_drop then
|
|
||||||
if (
|
|
||||||
self.lock_on_soft_drop and
|
|
||||||
self.piece:isDropBlocked(self.grid) and
|
|
||||||
config.gamesettings.buffer_lock == 1
|
|
||||||
) then
|
|
||||||
self.piece.locked = true
|
|
||||||
end
|
|
||||||
self.buffer_soft_drop = false
|
|
||||||
end
|
|
||||||
if self.piece:isDropBlocked(self.grid) and
|
|
||||||
self.grid:canPlacePiece(self.piece) then
|
|
||||||
playSE("bottom")
|
|
||||||
end
|
|
||||||
if self.lock_drop or (
|
|
||||||
not ruleset.are or self:getARE() == 0
|
not ruleset.are or self:getARE() == 0
|
||||||
) then
|
) then
|
||||||
self.drop_locked = true
|
self.drop_locked = true
|
||||||
end
|
end
|
||||||
if self.lock_hard_drop or (
|
if not self.buffer_hard_drop and self.lock_hard_drop or (
|
||||||
not ruleset.are or self:getARE() == 0
|
not ruleset.are or self:getARE() == 0
|
||||||
) then
|
) then
|
||||||
self.hard_drop_locked = true
|
self.hard_drop_locked = true
|
||||||
end
|
end
|
||||||
|
self.piece = ruleset:initializePiece(
|
||||||
|
inputs, piece_data, self.grid, self:getGravity(),
|
||||||
|
self.prev_inputs, self.move,
|
||||||
|
self:getLockDelay(), self:getDropSpeed(),
|
||||||
|
self.drop_locked, self.hard_drop_locked, self.big_mode,
|
||||||
|
(
|
||||||
|
self.frames == 0 or (ruleset.are and self:getARE() ~= 0)
|
||||||
|
) and self.irs or false
|
||||||
|
)
|
||||||
|
if config.gamesettings.buffer_lock == 3 then
|
||||||
|
if self.buffer_hard_drop then
|
||||||
|
local prev_y = self.piece.position.y
|
||||||
|
self.piece:dropToBottom(self.grid)
|
||||||
|
self.piece.locked = self.lock_on_hard_drop
|
||||||
|
self:onHardDrop(self.piece.position.y - prev_y)
|
||||||
|
end
|
||||||
|
if self.buffer_soft_drop then
|
||||||
|
if (
|
||||||
|
self.lock_on_soft_drop and
|
||||||
|
self.piece:isDropBlocked(self.grid)
|
||||||
|
) then
|
||||||
|
self.piece.locked = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.piece_hard_dropped = false
|
||||||
|
self.piece_soft_locked = false
|
||||||
|
self.buffer_hard_drop = false
|
||||||
|
self.buffer_soft_drop = false
|
||||||
|
if self.piece:isDropBlocked(self.grid) and
|
||||||
|
self.grid:canPlacePiece(self.piece) then
|
||||||
|
playSE("bottom")
|
||||||
|
end
|
||||||
if generate_next_piece == nil then
|
if generate_next_piece == nil then
|
||||||
table.remove(self.next_queue, 1)
|
table.remove(self.next_queue, 1)
|
||||||
table.insert(self.next_queue, self:getNextPiece(ruleset))
|
table.insert(self.next_queue, self:getNextPiece(ruleset))
|
||||||
@@ -602,6 +603,10 @@ function GameMode:animation(x, y, skin, colour)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function GameMode:canDrawLCA()
|
||||||
|
return self.lcd > 0
|
||||||
|
end
|
||||||
|
|
||||||
function GameMode:drawLineClearAnimation()
|
function GameMode:drawLineClearAnimation()
|
||||||
-- animation function
|
-- animation function
|
||||||
-- params: block x, y, skin, colour
|
-- params: block x, y, skin, colour
|
||||||
@@ -835,6 +840,95 @@ function GameMode:drawSectionTimesWithSplits(current_section, section_limit)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function GameMode:drawBackground()
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
love.graphics.draw(
|
||||||
|
backgrounds[self:getBackground()],
|
||||||
|
0, 0, 0,
|
||||||
|
0.5, 0.5
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function GameMode:drawFrame()
|
||||||
|
-- game frame
|
||||||
|
if self.grid.width == 10 and self.grid.height == 24 then
|
||||||
|
love.graphics.draw(misc_graphics["frame"], 48, 64)
|
||||||
|
end
|
||||||
|
|
||||||
|
love.graphics.setColor(0, 0, 0, 200)
|
||||||
|
love.graphics.rectangle(
|
||||||
|
"fill", 64, 80,
|
||||||
|
16 * self.grid.width, 16 * (self.grid.height - 4)
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.grid.width ~= 10 or self.grid.height ~= 24 then
|
||||||
|
love.graphics.setColor(174/255, 83/255, 76/255, 1)
|
||||||
|
love.graphics.setLineWidth(8)
|
||||||
|
love.graphics.line(
|
||||||
|
60,76,
|
||||||
|
68+16*self.grid.width,76,
|
||||||
|
68+16*self.grid.width,84+16*(self.grid.height-4),
|
||||||
|
60,84+16*(self.grid.height-4),
|
||||||
|
60,76
|
||||||
|
)
|
||||||
|
love.graphics.setColor(203/255, 137/255, 111/255, 1)
|
||||||
|
love.graphics.setLineWidth(4)
|
||||||
|
love.graphics.line(
|
||||||
|
60,76,
|
||||||
|
68+16*self.grid.width,76,
|
||||||
|
68+16*self.grid.width,84+16*(self.grid.height-4),
|
||||||
|
60,84+16*(self.grid.height-4),
|
||||||
|
60,76
|
||||||
|
)
|
||||||
|
love.graphics.setLineWidth(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function GameMode:drawReadyGo()
|
||||||
|
-- ready/go graphics
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
|
||||||
|
if self.ready_frames <= 100 and self.ready_frames > 52 then
|
||||||
|
love.graphics.draw(misc_graphics["ready"], 144 - 50, 240 - 14)
|
||||||
|
elseif self.ready_frames <= 50 and self.ready_frames > 2 then
|
||||||
|
love.graphics.draw(misc_graphics["go"], 144 - 27, 240 - 14)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function GameMode:drawCustom() end
|
function GameMode:drawCustom() end
|
||||||
|
|
||||||
|
function GameMode:draw(paused)
|
||||||
|
self:drawBackground()
|
||||||
|
self:drawFrame()
|
||||||
|
self:drawGrid()
|
||||||
|
self:drawPiece()
|
||||||
|
self:drawNextQueue(self.ruleset)
|
||||||
|
self:drawScoringInfo()
|
||||||
|
self:drawReadyGo()
|
||||||
|
self:drawCustom()
|
||||||
|
if self:canDrawLCA() then
|
||||||
|
self:drawLineClearAnimation()
|
||||||
|
end
|
||||||
|
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
love.graphics.setFont(font_3x5_2)
|
||||||
|
if config.gamesettings.display_gamemode == 1 then
|
||||||
|
love.graphics.printf(
|
||||||
|
self.name .. " - " .. self.ruleset.name,
|
||||||
|
0, 460, 640, "left"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
love.graphics.setFont(font_3x5_3)
|
||||||
|
if paused then
|
||||||
|
love.graphics.printf("GAME PAUSED!", 64, 160, 160, "center")
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.completed then
|
||||||
|
self:onGameComplete()
|
||||||
|
elseif self.game_over then
|
||||||
|
self:onGameOver()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return GameMode
|
return GameMode
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ function Marathon2020Game:advanceOneFrame()
|
|||||||
if self.roll_frames < 0 then
|
if self.roll_frames < 0 then
|
||||||
return false
|
return false
|
||||||
elseif self.roll_frames > 4000 then
|
elseif self.roll_frames > 4000 then
|
||||||
if self.grade >= 30 and self.section_cool_count >= 20 then self.grade = 31 end
|
if self:qualifiesForMRoll() then self.grade = 31 end
|
||||||
self.completed = true
|
self.completed = true
|
||||||
end
|
end
|
||||||
elseif self.ready_frames == 0 then
|
elseif self.ready_frames == 0 then
|
||||||
@@ -154,11 +154,11 @@ function Marathon2020Game:advanceOneFrame()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local cool_cutoffs = {
|
local cool_cutoffs = {
|
||||||
frameTime(0,45,00), frameTime(0,41,50), frameTime(0,38,50), frameTime(0,35,00), frameTime(0,32,50),
|
[0] = frameTime(0,45,00),
|
||||||
frameTime(0,29,20), frameTime(0,27,20), frameTime(0,24,80), frameTime(0,22,80), frameTime(0,20,60),
|
frameTime(0,41,50), frameTime(0,38,50), frameTime(0,35,00), frameTime(0,32,50), frameTime(0,29,20),
|
||||||
frameTime(0,19,60), frameTime(0,19,40), frameTime(0,19,40), frameTime(0,18,40), frameTime(0,18,20),
|
frameTime(0,27,20), frameTime(0,24,80), frameTime(0,22,80), frameTime(0,20,60), frameTime(0,19,60),
|
||||||
frameTime(0,16,20), frameTime(0,16,20), frameTime(0,16,20), frameTime(0,16,20), frameTime(0,16,20),
|
frameTime(0,19,40), frameTime(0,19,40), frameTime(0,18,40), frameTime(0,18,20), frameTime(0,16,20),
|
||||||
frameTime(0,15,20)
|
frameTime(0,16,20), frameTime(0,16,20), frameTime(0,16,20), frameTime(0,16,20), frameTime(0,15,20)
|
||||||
}
|
}
|
||||||
|
|
||||||
local levels_for_cleared_rows = { 1, 2, 4, 6 }
|
local levels_for_cleared_rows = { 1, 2, 4, 6 }
|
||||||
@@ -227,13 +227,14 @@ local mid_cleared_line_points = {2, 6, 12, 24}
|
|||||||
local high_cleared_line_points = {1, 4, 9, 20}
|
local high_cleared_line_points = {1, 4, 9, 20}
|
||||||
|
|
||||||
local function getGradeForGradePoints(points)
|
local function getGradeForGradePoints(points)
|
||||||
return math.floor(math.sqrt((points / 50) * 8 + 1) / 2 - 0.5)
|
return math.min(30, math.floor(math.sqrt((points / 50) * 8 + 1) / 2 - 0.5))
|
||||||
-- Don't be afraid of the above function. All it does is make it so that
|
-- Don't be afraid of the above function. All it does is make it so that
|
||||||
-- you need 50 points to get to grade 1, 100 points to grade 2, etc.
|
-- you need 50 points to get to grade 1, 100 points to grade 2, etc.
|
||||||
end
|
end
|
||||||
|
|
||||||
function Marathon2020Game:updateGrade(cleared_lines)
|
function Marathon2020Game:updateGrade(cleared_lines)
|
||||||
-- update grade points and max grade points
|
-- update grade points and max grade points
|
||||||
|
if self.clear then return end
|
||||||
local point_level = math.floor(self.level / 100) + self.delay_level
|
local point_level = math.floor(self.level / 100) + self.delay_level
|
||||||
local plus_points = math.max(
|
local plus_points = math.max(
|
||||||
low_cleared_line_points[cleared_lines],
|
low_cleared_line_points[cleared_lines],
|
||||||
@@ -249,12 +250,11 @@ function Marathon2020Game:updateGrade(cleared_lines)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Marathon2020Game:getTotalGrade()
|
function Marathon2020Game:getTotalGrade()
|
||||||
if self.grade + self.section_cool_count > 50 then return "GM" end
|
|
||||||
return self.grade + self.section_cool_count
|
return self.grade + self.section_cool_count
|
||||||
end
|
end
|
||||||
|
|
||||||
local function getSectionForLevel(level)
|
local function getSectionForLevel(level)
|
||||||
if level < 2001 then
|
if level < 2000 then
|
||||||
return math.floor(level / 100) + 1
|
return math.floor(level / 100) + 1
|
||||||
elseif level < 2020 then
|
elseif level < 2020 then
|
||||||
return 20
|
return 20
|
||||||
@@ -331,14 +331,16 @@ end
|
|||||||
function Marathon2020Game:updateSectionTimes(old_level, new_level)
|
function Marathon2020Game:updateSectionTimes(old_level, new_level)
|
||||||
function sectionCool(section)
|
function sectionCool(section)
|
||||||
self.section_cool_count = self.section_cool_count + 1
|
self.section_cool_count = self.section_cool_count + 1
|
||||||
self.delay_level = math.min(20, self.delay_level + 1)
|
if section <= 10 then
|
||||||
if section < 10 then table.insert(self.section_status, "cool") end
|
self.delay_level = math.min(20, self.delay_level + 1)
|
||||||
|
end
|
||||||
|
table.insert(self.section_status, "cool")
|
||||||
self.cool_timer = 300
|
self.cool_timer = 300
|
||||||
end
|
end
|
||||||
|
|
||||||
local section = getSectionForLevel(old_level)
|
local section = getSectionForLevel(old_level)
|
||||||
|
|
||||||
if section <= 19 and old_level % 100 < 70 and new_level >= math.floor(old_level / 100) * 100 + 70 then
|
if old_level % 100 < 70 and new_level >= math.floor(old_level / 100) * 100 + 70 then
|
||||||
-- record section 70 time
|
-- record section 70 time
|
||||||
section_70_time = self.frames - self.section_start_time
|
section_70_time = self.frames - self.section_start_time
|
||||||
table.insert(self.secondary_section_times, section_70_time)
|
table.insert(self.secondary_section_times, section_70_time)
|
||||||
@@ -350,23 +352,25 @@ function Marathon2020Game:updateSectionTimes(old_level, new_level)
|
|||||||
table.insert(self.section_times, section_time)
|
table.insert(self.section_times, section_time)
|
||||||
self.section_start_time = self.frames
|
self.section_start_time = self.frames
|
||||||
|
|
||||||
if section > 5 then self.delay_level = math.min(20, self.delay_level + 1) end
|
|
||||||
self:checkTorikan(section)
|
|
||||||
self:checkClear(new_level)
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
section <= 19 and self.section_status[section - 1] == "cool" and
|
self.section_status[section - 1] == "cool" and
|
||||||
self.secondary_section_times[section] < self.secondary_section_times[section - 1] + 120 and
|
self.secondary_section_times[section] < self.secondary_section_times[section - 1] + 120 and
|
||||||
self.secondary_section_times[section] < cool_cutoffs[section]
|
self.secondary_section_times[section] < cool_cutoffs[self.delay_level]
|
||||||
) then
|
) then
|
||||||
sectionCool(section)
|
sectionCool(section)
|
||||||
elseif self.section_status[section - 1] == "cool" then
|
elseif self.section_status[section - 1] == "cool" then
|
||||||
table.insert(self.section_status, "none")
|
table.insert(self.section_status, "none")
|
||||||
elseif section <= 19 and self.secondary_section_times[section] < cool_cutoffs[section] then
|
elseif self.secondary_section_times[section] < cool_cutoffs[self.delay_level] then
|
||||||
sectionCool(section)
|
sectionCool(section)
|
||||||
else
|
else
|
||||||
table.insert(self.section_status, "none")
|
table.insert(self.section_status, "none")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if section > 5 then
|
||||||
|
self.delay_level = math.min(20, self.delay_level + 1)
|
||||||
|
end
|
||||||
|
self:checkTorikan(section)
|
||||||
|
self:checkClear(new_level)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -452,7 +456,13 @@ function Marathon2020Game:drawScoringInfo()
|
|||||||
end
|
end
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_3)
|
love.graphics.setFont(font_3x5_3)
|
||||||
love.graphics.printf(self:getTotalGrade(), text_x, 120, 90, "left")
|
|
||||||
|
local grade = self:getTotalGrade()
|
||||||
|
love.graphics.printf(
|
||||||
|
grade > 50 and "GM" or grade,
|
||||||
|
text_x, 120, 90, "left"
|
||||||
|
)
|
||||||
|
|
||||||
love.graphics.printf(self.grade_points, text_x, 220, 90, "left")
|
love.graphics.printf(self.grade_points, text_x, 220, 90, "left")
|
||||||
love.graphics.printf(self.level, text_x, 340, 50, "right")
|
love.graphics.printf(self.level, text_x, 340, 50, "right")
|
||||||
|
|
||||||
@@ -466,7 +476,7 @@ end
|
|||||||
|
|
||||||
function Marathon2020Game:getHighscoreData()
|
function Marathon2020Game:getHighscoreData()
|
||||||
return {
|
return {
|
||||||
grade = self.grade,
|
grade = self:getTotalGrade(),
|
||||||
level = self.level,
|
level = self.level,
|
||||||
frames = self.frames,
|
frames = self.frames,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ function MarathonA2Game:new()
|
|||||||
|
|
||||||
self.roll_frames = 0
|
self.roll_frames = 0
|
||||||
self.combo = 1
|
self.combo = 1
|
||||||
|
self.grade_combo = 1
|
||||||
self.randomizer = History6RollsRandomizer()
|
self.randomizer = History6RollsRandomizer()
|
||||||
self.grade = 0
|
self.grade = 0
|
||||||
self.grade_points = 0
|
self.grade_points = 0
|
||||||
@@ -135,15 +136,23 @@ function MarathonA2Game:updateScore(level, drop_bonus, cleared_lines)
|
|||||||
if cleared_lines >= 4 then
|
if cleared_lines >= 4 then
|
||||||
self.tetris_count = self.tetris_count + 1
|
self.tetris_count = self.tetris_count + 1
|
||||||
end
|
end
|
||||||
if self.grid:checkForBravo(cleared_lines) then self.bravo = 4 else self.bravo = 1 end
|
if self.grid:checkForBravo(cleared_lines) then
|
||||||
|
self.bravo = 4
|
||||||
|
else
|
||||||
|
self.bravo = 1
|
||||||
|
end
|
||||||
if cleared_lines > 0 then
|
if cleared_lines > 0 then
|
||||||
self.combo = self.combo + (cleared_lines - 1) * 2
|
self.combo = self.combo + (cleared_lines - 1) * 2
|
||||||
|
if cleared_lines > 1 then
|
||||||
|
self.grade_combo = self.grade_combo + 1
|
||||||
|
end
|
||||||
self.score = self.score + (
|
self.score = self.score + (
|
||||||
(math.ceil((level + cleared_lines) / 4) + drop_bonus) *
|
(math.ceil((level + cleared_lines) / 4) + drop_bonus) *
|
||||||
cleared_lines * self.combo * self.bravo
|
cleared_lines * self.combo * self.bravo
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
self.combo = 1
|
self.combo = 1
|
||||||
|
self.grade_combo = 1
|
||||||
end
|
end
|
||||||
self.drop_bonus = 0
|
self.drop_bonus = 0
|
||||||
else self.lines = self.lines + cleared_lines end
|
else self.lines = self.lines + cleared_lines end
|
||||||
@@ -253,7 +262,7 @@ function MarathonA2Game:updateGrade(cleared_lines)
|
|||||||
self.grade_points = self.grade_points + (
|
self.grade_points = self.grade_points + (
|
||||||
math.ceil(
|
math.ceil(
|
||||||
grade_point_bonuses[self.grade + 1][cleared_lines] *
|
grade_point_bonuses[self.grade + 1][cleared_lines] *
|
||||||
combo_multipliers[math.min(self.combo, 10)][cleared_lines]
|
combo_multipliers[math.min(self.grade_combo, 10)][cleared_lines]
|
||||||
) * (1 + math.floor(self.level / 250))
|
) * (1 + math.floor(self.level / 250))
|
||||||
)
|
)
|
||||||
if self.grade_points >= 100 and self.grade < 31 then
|
if self.grade_points >= 100 and self.grade < 31 then
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ function MarathonA3Game:new()
|
|||||||
self.speed_level = 0
|
self.speed_level = 0
|
||||||
self.roll_frames = 0
|
self.roll_frames = 0
|
||||||
self.combo = 1
|
self.combo = 1
|
||||||
|
self.grade_combo = 1
|
||||||
self.grade = 0
|
self.grade = 0
|
||||||
self.grade_points = 0
|
self.grade_points = 0
|
||||||
self.roll_points = 0
|
self.roll_points = 0
|
||||||
@@ -236,12 +237,16 @@ function MarathonA3Game:updateScore(level, drop_bonus, cleared_lines)
|
|||||||
if not self.clear then
|
if not self.clear then
|
||||||
if cleared_lines > 0 then
|
if cleared_lines > 0 then
|
||||||
self.combo = self.combo + (cleared_lines - 1) * 2
|
self.combo = self.combo + (cleared_lines - 1) * 2
|
||||||
|
if cleared_lines > 1 then
|
||||||
|
self.grade_combo = self.grade_combo + 1
|
||||||
|
end
|
||||||
self.score = self.score + (
|
self.score = self.score + (
|
||||||
(math.ceil((level + cleared_lines) / 4) + drop_bonus) *
|
(math.ceil((level + cleared_lines) / 4) + drop_bonus) *
|
||||||
cleared_lines * self.combo
|
cleared_lines * self.combo
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
self.combo = 1
|
self.combo = 1
|
||||||
|
self.grade_combo = 1
|
||||||
end
|
end
|
||||||
self.drop_bonus = 0
|
self.drop_bonus = 0
|
||||||
end
|
end
|
||||||
@@ -335,7 +340,7 @@ function MarathonA3Game:updateGrade(cleared_lines)
|
|||||||
self.grade_points = self.grade_points + (
|
self.grade_points = self.grade_points + (
|
||||||
math.ceil(
|
math.ceil(
|
||||||
grade_point_bonuses[self.grade + 1][cleared_lines] *
|
grade_point_bonuses[self.grade + 1][cleared_lines] *
|
||||||
combo_multipliers[math.min(self.combo, 10)][cleared_lines]
|
combo_multipliers[math.min(self.grade_combo, 10)][cleared_lines]
|
||||||
) * (1 + math.floor(self.level / 250))
|
) * (1 + math.floor(self.level / 250))
|
||||||
)
|
)
|
||||||
if self.grade_points >= 100 and self.grade < 31 then
|
if self.grade_points >= 100 and self.grade < 31 then
|
||||||
@@ -351,7 +356,12 @@ function MarathonA3Game:qualifiesForMRoll()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function MarathonA3Game:getAggregateGrade()
|
function MarathonA3Game:getAggregateGrade()
|
||||||
return self.section_cool_grade + math.floor(self.roll_points / 100) + grade_conversion[self.grade]
|
return math.min(
|
||||||
|
self.section_cool_grade +
|
||||||
|
math.floor(self.roll_points / 100) +
|
||||||
|
grade_conversion[self.grade],
|
||||||
|
self.roll_frames > 3238 and 32 or 31
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
local master_grades = { "M", "MK", "MV", "MO", "MM" }
|
local master_grades = { "M", "MK", "MV", "MO", "MM" }
|
||||||
@@ -366,8 +376,6 @@ function MarathonA3Game:getLetterGrade()
|
|||||||
return "M" .. tostring(grade - 17)
|
return "M" .. tostring(grade - 17)
|
||||||
elseif grade < 32 then
|
elseif grade < 32 then
|
||||||
return master_grades[grade - 26]
|
return master_grades[grade - 26]
|
||||||
elseif grade >= 32 and self.roll_frames < 3238 then
|
|
||||||
return "MM"
|
|
||||||
else
|
else
|
||||||
return "GM"
|
return "GM"
|
||||||
end
|
end
|
||||||
@@ -465,7 +473,7 @@ function MarathonA3Game:drawScoringInfo()
|
|||||||
love.graphics.setFont(font_3x5_3)
|
love.graphics.setFont(font_3x5_3)
|
||||||
love.graphics.printf(self.score, 240, 220, 90, "left")
|
love.graphics.printf(self.score, 240, 220, 90, "left")
|
||||||
if self.roll_frames > 3238 then love.graphics.setColor(1, 0.5, 0, 1)
|
if self.roll_frames > 3238 then love.graphics.setColor(1, 0.5, 0, 1)
|
||||||
elseif self.level >= 999 and self.clear then love.graphics.setColor(0, 1, 0, 1) end
|
elseif self.level >= 999 then love.graphics.setColor(0, 1, 0, 1) end
|
||||||
love.graphics.printf(self:getLetterGrade(), 240, 140, 90, "left")
|
love.graphics.printf(self:getLetterGrade(), 240, 140, 90, "left")
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
love.graphics.printf(self.level, 240, 340, 40, "right")
|
love.graphics.printf(self.level, 240, 340, 40, "right")
|
||||||
|
|||||||
@@ -19,13 +19,16 @@ function PhantomManiaGame:new()
|
|||||||
self.next_queue_length = 1
|
self.next_queue_length = 1
|
||||||
|
|
||||||
self.SGnames = {
|
self.SGnames = {
|
||||||
"9", "8", "7", "6", "5", "4", "3", "2", "1",
|
|
||||||
"S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9",
|
"S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9",
|
||||||
|
"M1", "M2", "M3", "M4", "M5", "M6", "M7", "M8", "M9",
|
||||||
"GM"
|
"GM"
|
||||||
}
|
}
|
||||||
|
|
||||||
self.roll_frames = 0
|
self.roll_frames = 0
|
||||||
self.combo = 1
|
self.combo = 1
|
||||||
|
self.tetrises = 0
|
||||||
|
self.section_tetrises = {[0] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
self.section_req = true
|
||||||
self.randomizer = History6RollsRandomizer()
|
self.randomizer = History6RollsRandomizer()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -105,12 +108,23 @@ end
|
|||||||
|
|
||||||
function PhantomManiaGame:onLineClear(cleared_row_count)
|
function PhantomManiaGame:onLineClear(cleared_row_count)
|
||||||
if not self.clear then
|
if not self.clear then
|
||||||
|
if cleared_row_count >= 4 then
|
||||||
|
self.tetrises = self.tetrises + 1
|
||||||
|
self.section_tetrises[math.floor(self.level / 100)] = (
|
||||||
|
self.section_tetrises[math.floor(self.level / 100)] + 1
|
||||||
|
)
|
||||||
|
end
|
||||||
local new_level = self.level + cleared_row_count
|
local new_level = self.level + cleared_row_count
|
||||||
if new_level >= 999 or self:hitTorikan(self.level, new_level) then
|
if new_level >= 999 or self:hitTorikan(self.level, new_level) then
|
||||||
if new_level >= 999 then
|
if new_level >= 999 then
|
||||||
self.level = 999
|
self.level = 999
|
||||||
end
|
end
|
||||||
self.clear = true
|
self.clear = true
|
||||||
|
for i = 0, 9 do
|
||||||
|
if self.section_tetrises[i] < (i == 9 and 1 or 2) then
|
||||||
|
self.section_req = false
|
||||||
|
end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
self.level = new_level
|
self.level = new_level
|
||||||
end
|
end
|
||||||
@@ -138,7 +152,7 @@ PhantomManiaGame.rollOpacityFunction = function(age)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function PhantomManiaGame:drawGrid()
|
function PhantomManiaGame:drawGrid()
|
||||||
if not (self.game_over or self.clear) then
|
if not (self.game_over or self.completed or (self.clear and self.level < 999)) then
|
||||||
self.grid:drawInvisible(self.rollOpacityFunction, nil, false)
|
self.grid:drawInvisible(self.rollOpacityFunction, nil, false)
|
||||||
else
|
else
|
||||||
self.grid:draw()
|
self.grid:draw()
|
||||||
@@ -150,16 +164,14 @@ local function getLetterGrade(level, clear)
|
|||||||
return ""
|
return ""
|
||||||
elseif level < 500 or level == 500 and clear then
|
elseif level < 500 or level == 500 and clear then
|
||||||
return "M"
|
return "M"
|
||||||
elseif level < 700 then
|
elseif level < 600 then
|
||||||
return "MK"
|
return "MK"
|
||||||
elseif level < 800 or level == 800 and clear then
|
elseif level < 700 then
|
||||||
return "MV"
|
return "MV"
|
||||||
elseif level < 900 then
|
elseif level < 800 or level == 800 and clear then
|
||||||
return "MO"
|
return "MO"
|
||||||
elseif level < 999 then
|
elseif level <= 999 then
|
||||||
return "MM"
|
return "MM"
|
||||||
elseif level == 999 then
|
|
||||||
return "GM"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -169,7 +181,9 @@ function PhantomManiaGame:drawScoringInfo()
|
|||||||
local text_x = config["side_next"] and 320 or 240
|
local text_x = config["side_next"] and 320 or 240
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_2)
|
love.graphics.setFont(font_3x5_2)
|
||||||
if getLetterGrade(self.level, self.clear) ~= "" then love.graphics.printf("GRADE", text_x, 120, 40, "left") end
|
if getLetterGrade(self.level, self.clear) ~= "" then
|
||||||
|
love.graphics.printf("GRADE", text_x, 120, 40, "left")
|
||||||
|
end
|
||||||
love.graphics.printf("SCORE", text_x, 200, 40, "left")
|
love.graphics.printf("SCORE", text_x, 200, 40, "left")
|
||||||
love.graphics.printf("LEVEL", text_x, 320, 40, "left")
|
love.graphics.printf("LEVEL", text_x, 320, 40, "left")
|
||||||
local sg = self.grid:checkSecretGrade()
|
local sg = self.grid:checkSecretGrade()
|
||||||
@@ -178,7 +192,16 @@ function PhantomManiaGame:drawScoringInfo()
|
|||||||
end
|
end
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_3)
|
love.graphics.setFont(font_3x5_3)
|
||||||
if getLetterGrade(self.level, self.clear) ~= "" then love.graphics.printf(getLetterGrade(self.level, self.clear), text_x, 140, 90, "left") end
|
if getLetterGrade(self.level, self.clear) ~= "" then
|
||||||
|
if self.roll_frames > 1982 then love.graphics.setColor(1, 0.5, 0, 1)
|
||||||
|
elseif self.level == 999 and self.clear then love.graphics.setColor(0, 1, 0, 1) end
|
||||||
|
if self.level == 999 and self.section_req and self.tetrises >= 31 then
|
||||||
|
love.graphics.printf("GM", text_x, 140, 90, "left")
|
||||||
|
else
|
||||||
|
love.graphics.printf(getLetterGrade(self.level, self.clear), text_x, 140, 90, "left")
|
||||||
|
end
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
end
|
||||||
love.graphics.printf(self.score, text_x, 220, 90, "left")
|
love.graphics.printf(self.score, text_x, 220, 90, "left")
|
||||||
love.graphics.printf(self.level, text_x, 340, 40, "right")
|
love.graphics.printf(self.level, text_x, 340, 40, "right")
|
||||||
if self.clear then
|
if self.clear then
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ require 'funcs'
|
|||||||
local GameMode = require 'tetris.modes.gamemode'
|
local GameMode = require 'tetris.modes.gamemode'
|
||||||
local Piece = require 'tetris.components.piece'
|
local Piece = require 'tetris.components.piece'
|
||||||
|
|
||||||
local History6RollsRandomizer = require 'tetris.randomizers.history_6rolls'
|
local History6RollsRandomizer = require 'tetris.randomizers.history_6rolls_35bag'
|
||||||
|
|
||||||
local PhantomMania2Game = GameMode:extend()
|
local PhantomMania2Game = GameMode:extend()
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ function PhantomMania2Game:new()
|
|||||||
|
|
||||||
self.SGnames = {
|
self.SGnames = {
|
||||||
"S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9",
|
"S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9",
|
||||||
"m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9",
|
"M1", "M2", "M3", "M4", "M5", "M6", "M7", "M8", "M9",
|
||||||
"GM"
|
"GM"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +251,7 @@ PhantomMania2Game.garbageOpacityFunction = function(age)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function PhantomMania2Game:drawGrid()
|
function PhantomMania2Game:drawGrid()
|
||||||
if not (self.game_over) then
|
if not (self.game_over or self.completed or (self.clear and self.level < 1300)) then
|
||||||
self.grid:drawInvisible(self.rollOpacityFunction, self.garbageOpacityFunction)
|
self.grid:drawInvisible(self.rollOpacityFunction, self.garbageOpacityFunction)
|
||||||
else
|
else
|
||||||
self.grid:draw()
|
self.grid:draw()
|
||||||
|
|||||||
@@ -8,12 +8,6 @@ PhantomManiaNGame.tagline = "The old mode from Nullpomino, for Ti-ARS and SRS su
|
|||||||
|
|
||||||
function PhantomManiaNGame:new()
|
function PhantomManiaNGame:new()
|
||||||
PhantomManiaNGame.super:new()
|
PhantomManiaNGame.super:new()
|
||||||
|
|
||||||
self.SGnames = {
|
|
||||||
"M1", "M2", "M3", "M4", "M5", "M6", "M7", "M8", "M9",
|
|
||||||
"M10", "M11", "M12", "M13", "M14", "M15", "M16", "M17", "M18",
|
|
||||||
"GM"
|
|
||||||
}
|
|
||||||
|
|
||||||
self.next_queue_length = 3
|
self.next_queue_length = 3
|
||||||
self.enable_hold = true
|
self.enable_hold = true
|
||||||
|
|||||||
@@ -1,217 +1,18 @@
|
|||||||
require 'funcs'
|
require 'funcs'
|
||||||
|
|
||||||
local GameMode = require 'tetris.modes.gamemode'
|
local MarathonA1Game = require 'tetris.modes.marathon_a1'
|
||||||
local Piece = require 'tetris.components.piece'
|
local Piece = require 'tetris.components.piece'
|
||||||
|
|
||||||
local History4RollsRandomizer = require 'tetris.randomizers.history_4rolls'
|
local History4RollsRandomizer = require 'tetris.randomizers.history_4rolls'
|
||||||
|
|
||||||
local SurvivalA1Game = GameMode:extend()
|
local SurvivalA1Game = MarathonA1Game:extend()
|
||||||
|
|
||||||
SurvivalA1Game.name = "Survival A1"
|
SurvivalA1Game.name = "Survival A1"
|
||||||
SurvivalA1Game.hash = "SurvivalA1"
|
SurvivalA1Game.hash = "SurvivalA1"
|
||||||
SurvivalA1Game.tagline = "The game starts fast and only gets faster!"
|
SurvivalA1Game.tagline = "A constant high-speed marathon!"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function SurvivalA1Game:new()
|
|
||||||
SurvivalA1Game.super:new()
|
|
||||||
|
|
||||||
self.roll_frames = 0
|
|
||||||
self.combo = 1
|
|
||||||
self.bravos = 0
|
|
||||||
|
|
||||||
self.gm_conditions = {
|
|
||||||
level300 = false,
|
|
||||||
level500 = false,
|
|
||||||
level999 = false
|
|
||||||
}
|
|
||||||
|
|
||||||
self.SGnames = {
|
|
||||||
"9", "8", "7", "6", "5", "4", "3", "2", "1",
|
|
||||||
"S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9",
|
|
||||||
"GM"
|
|
||||||
}
|
|
||||||
|
|
||||||
self.randomizer = History4RollsRandomizer()
|
|
||||||
|
|
||||||
self.lock_drop = false
|
|
||||||
self.enable_hard_drop = false
|
|
||||||
self.enable_hold = false
|
|
||||||
self.next_queue_length = 1
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:getARE()
|
|
||||||
return 30
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:getLineARE()
|
|
||||||
return 27
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:getDasLimit()
|
|
||||||
return 15
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:getLineClearDelay()
|
|
||||||
return 44
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:getLockDelay()
|
|
||||||
return 30
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:getGravity()
|
function SurvivalA1Game:getGravity()
|
||||||
return 20
|
return 20
|
||||||
end
|
end
|
||||||
|
|
||||||
local function getRankForScore(score)
|
|
||||||
if score < 400 then return {rank = "9", next = 400}
|
|
||||||
elseif score < 800 then return {rank = "8", next = 800}
|
|
||||||
elseif score < 1400 then return {rank = "7", next = 1400}
|
|
||||||
elseif score < 2000 then return {rank = "6", next = 2000}
|
|
||||||
elseif score < 3500 then return {rank = "5", next = 3500}
|
|
||||||
elseif score < 5500 then return {rank = "4", next = 5500}
|
|
||||||
elseif score < 8000 then return {rank = "3", next = 8000}
|
|
||||||
elseif score < 12000 then return {rank = "2", next = 12000}
|
|
||||||
elseif score < 16000 then return {rank = "1", next = 16000}
|
|
||||||
elseif score < 22000 then return {rank = "S1", next = 22000}
|
|
||||||
elseif score < 30000 then return {rank = "S2", next = 30000}
|
|
||||||
elseif score < 40000 then return {rank = "S3", next = 40000}
|
|
||||||
elseif score < 52000 then return {rank = "S4", next = 52000}
|
|
||||||
elseif score < 66000 then return {rank = "S5", next = 66000}
|
|
||||||
elseif score < 82000 then return {rank = "S6", next = 82000}
|
|
||||||
elseif score < 100000 then return {rank = "S7", next = 100000}
|
|
||||||
elseif score < 120000 then return {rank = "S8", next = 120000}
|
|
||||||
else return {rank = "S9", next = "???"}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:advanceOneFrame()
|
|
||||||
if self.clear then
|
|
||||||
self.roll_frames = self.roll_frames + 1
|
|
||||||
if self.roll_frames > 2968 then
|
|
||||||
self.completed = true
|
|
||||||
end
|
|
||||||
elseif self.ready_frames == 0 then
|
|
||||||
self.frames = self.frames + 1
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:onPieceEnter()
|
|
||||||
if (self.level % 100 ~= 99 and self.level ~= 998) and not self.clear and self.frames ~= 0 then
|
|
||||||
self.level = self.level + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:onLineClear(cleared_row_count)
|
|
||||||
self:checkGMRequirements(self.level, self.level + cleared_row_count)
|
|
||||||
if not self.clear then
|
|
||||||
local new_level = math.min(self.level + cleared_row_count, 999)
|
|
||||||
if new_level == 999 then
|
|
||||||
self.clear = true
|
|
||||||
end
|
|
||||||
self.level = new_level
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:updateScore(level, drop_bonus, cleared_lines)
|
|
||||||
if not self.clear then
|
|
||||||
if self.grid:checkForBravo(cleared_lines) then
|
|
||||||
self.bravo = 4
|
|
||||||
self.bravos = self.bravos + 1
|
|
||||||
else self.bravo = 1 end
|
|
||||||
if cleared_lines > 0 then
|
|
||||||
self.combo = self.combo + (cleared_lines - 1) * 2
|
|
||||||
self.score = self.score + (
|
|
||||||
(math.ceil((level + cleared_lines) / 4) + drop_bonus) *
|
|
||||||
cleared_lines * self.combo * self.bravo
|
|
||||||
)
|
|
||||||
else
|
|
||||||
self.combo = 1
|
|
||||||
end
|
|
||||||
self.drop_bonus = 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:checkGMRequirements(old_level, new_level)
|
|
||||||
if old_level < 300 and new_level >= 300 then
|
|
||||||
if self.score >= 12000 and self.frames <= frameTime(4,15) then
|
|
||||||
self.gm_conditions["level300"] = true
|
|
||||||
end
|
|
||||||
elseif old_level < 500 and new_level >= 500 then
|
|
||||||
if self.score >= 40000 and self.frames <= frameTime(7,30) then
|
|
||||||
self.gm_conditions["level500"] = true
|
|
||||||
end
|
|
||||||
elseif old_level < 999 and new_level >= 999 then
|
|
||||||
if self.score >= 126000 and self.frames <= frameTime(13,30) then
|
|
||||||
self.gm_conditions["level999"] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:drawGrid()
|
|
||||||
self.grid:draw()
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:drawScoringInfo()
|
|
||||||
SurvivalA1Game.super.drawScoringInfo(self)
|
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_2)
|
|
||||||
love.graphics.print(
|
|
||||||
self.das.direction .. " " ..
|
|
||||||
self.das.frames .. " " ..
|
|
||||||
strTrueValues(self.prev_inputs)
|
|
||||||
)
|
|
||||||
love.graphics.printf("NEXT", 64, 40, 40, "left")
|
|
||||||
love.graphics.printf("GRADE", 240, 120, 40, "left")
|
|
||||||
love.graphics.printf("SCORE", 240, 200, 40, "left")
|
|
||||||
love.graphics.printf("NEXT RANK", 240, 260, 90, "left")
|
|
||||||
love.graphics.printf("LEVEL", 240, 320, 40, "left")
|
|
||||||
local sg = self.grid:checkSecretGrade()
|
|
||||||
if sg >= 5 then
|
|
||||||
love.graphics.printf("SECRET GRADE", 240, 430, 180, "left")
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.bravos > 0 then love.graphics.printf("BRAVO", 300, 120, 40, "left") end
|
|
||||||
|
|
||||||
love.graphics.setFont(font_3x5_3)
|
|
||||||
love.graphics.printf(self.score, 240, 220, 90, "left")
|
|
||||||
if self.gm_conditions["level300"] and self.gm_conditions["level500"] and self.gm_conditions["level999"] then
|
|
||||||
love.graphics.printf("GM", 240, 140, 90, "left")
|
|
||||||
else
|
|
||||||
love.graphics.printf(getRankForScore(self.score).rank, 240, 140, 90, "left")
|
|
||||||
end
|
|
||||||
love.graphics.printf(getRankForScore(self.score).next, 240, 280, 90, "left")
|
|
||||||
love.graphics.printf(self.level, 240, 340, 40, "right")
|
|
||||||
love.graphics.printf(self:getSectionEndLevel(), 240, 370, 40, "right")
|
|
||||||
if sg >= 5 then
|
|
||||||
love.graphics.printf(self.SGnames[sg], 240, 450, 180, "left")
|
|
||||||
end
|
|
||||||
if self.bravos > 0 then love.graphics.printf(self.bravos, 300, 140, 40, "left") end
|
|
||||||
|
|
||||||
love.graphics.setFont(font_8x11)
|
|
||||||
love.graphics.printf(formatTime(self.frames), 64, 420, 160, "center")
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:getSectionEndLevel()
|
|
||||||
if self.level >= 900 then return 999
|
|
||||||
else return math.floor(self.level / 100 + 1) * 100 end
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:getBackground()
|
|
||||||
return math.floor(self.level / 100)
|
|
||||||
end
|
|
||||||
|
|
||||||
function SurvivalA1Game:getHighscoreData()
|
|
||||||
return {
|
|
||||||
grade = self.grade,
|
|
||||||
score = self.score,
|
|
||||||
level = self.level,
|
|
||||||
frames = self.frames,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
return SurvivalA1Game
|
return SurvivalA1Game
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ end
|
|||||||
function SurvivalA2Game:advanceOneFrame()
|
function SurvivalA2Game:advanceOneFrame()
|
||||||
if self.clear then
|
if self.clear then
|
||||||
self.roll_frames = self.roll_frames + 1
|
self.roll_frames = self.roll_frames + 1
|
||||||
if self.roll_frames > 2968 then
|
if self.roll_frames > 1800 then
|
||||||
self.completed = true
|
self.completed = true
|
||||||
end
|
end
|
||||||
elseif self.ready_frames == 0 then
|
elseif self.ready_frames == 0 then
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ function SurvivalA3Game:new()
|
|||||||
|
|
||||||
self.SGnames = {
|
self.SGnames = {
|
||||||
"S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9",
|
"S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9",
|
||||||
"m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9",
|
"M1", "M2", "M3", "M4", "M5", "M6", "M7", "M8", "M9",
|
||||||
"GM"
|
"GM"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,11 +38,9 @@ function SurvivalA3Game:new()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function SurvivalA3Game:initialize(ruleset)
|
function SurvivalA3Game:initialize(ruleset)
|
||||||
|
|
||||||
self.torikan_time = frameTime(2,28)
|
self.torikan_time = frameTime(2,28)
|
||||||
if ruleset.world then self.torikan_time = frameTime(3,03) end
|
if ruleset.world then self.torikan_time = frameTime(3,03) end
|
||||||
self.super.initialize(self, ruleset)
|
GameMode.initialize(self, ruleset)
|
||||||
-- ^ notice the . here instead of the :
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function SurvivalA3Game:getARE()
|
function SurvivalA3Game:getARE()
|
||||||
@@ -239,7 +237,7 @@ function SurvivalA3Game:drawScoringInfo()
|
|||||||
|
|
||||||
love.graphics.setFont(font_3x5_3)
|
love.graphics.setFont(font_3x5_3)
|
||||||
if self.roll_frames > 3238 then love.graphics.setColor(1, 0.5, 0, 1)
|
if self.roll_frames > 3238 then love.graphics.setColor(1, 0.5, 0, 1)
|
||||||
elseif self.level >= 1300 and self.clear then love.graphics.setColor(0, 1, 0, 1) end
|
elseif self.level >= 1300 then love.graphics.setColor(0, 1, 0, 1) end
|
||||||
love.graphics.printf(getLetterGrade(math.floor(self.grade)), text_x, 140, 90, "left")
|
love.graphics.printf(getLetterGrade(math.floor(self.grade)), text_x, 140, 90, "left")
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
love.graphics.printf(self.score, text_x, 220, 90, "left")
|
love.graphics.printf(self.score, text_x, 220, 90, "left")
|
||||||
|
|||||||
@@ -375,7 +375,10 @@ end
|
|||||||
|
|
||||||
function CRS:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
function CRS:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||||
|
|
||||||
if piece.shape == "O" then return end
|
if piece.shape == "O" then
|
||||||
|
self:onPieceRotate(piece, grid)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local kicks = CRS.wallkicks[piece.shape][piece:isDropBlocked(grid)][piece.rotation][new_piece.rotation]
|
local kicks = CRS.wallkicks[piece.shape][piece:isDropBlocked(grid)][piece.rotation][new_piece.rotation]
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ function Ruleset:rotatePiece(inputs, piece, grid, prev_inputs, initial)
|
|||||||
self:attemptRotate(new_inputs, piece, grid, initial)
|
self:attemptRotate(new_inputs, piece, grid, initial)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not was_drop_blocked and piece:isDropBlocked(grid) then
|
if not initial and not was_drop_blocked and piece:isDropBlocked(grid) then
|
||||||
playSE("bottom")
|
playSE("bottom")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -161,11 +161,6 @@ function Ruleset:dropPiece(
|
|||||||
inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked,
|
inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked,
|
||||||
hard_drop_enabled, additive_gravity, classic_lock
|
hard_drop_enabled, additive_gravity, classic_lock
|
||||||
)
|
)
|
||||||
if piece.big then
|
|
||||||
gravity = gravity / 2
|
|
||||||
drop_speed = drop_speed / 2
|
|
||||||
end
|
|
||||||
|
|
||||||
local y = piece.position.y
|
local y = piece.position.y
|
||||||
if inputs["down"] == true and drop_locked == false then
|
if inputs["down"] == true and drop_locked == false then
|
||||||
if additive_gravity then
|
if additive_gravity then
|
||||||
@@ -226,16 +221,7 @@ function Ruleset:initializePiece(
|
|||||||
colours = self.colourscheme
|
colours = self.colourscheme
|
||||||
end
|
end
|
||||||
|
|
||||||
local spawn_x
|
local spawn_x = math.floor(spawn_positions[data.shape].x / 10 * grid.width)
|
||||||
if (grid.width ~= 10) then
|
|
||||||
local percent = spawn_positions[data.shape].x / 10
|
|
||||||
for i = grid.width - 1, 0, -1 do
|
|
||||||
if i / grid.width <= percent then
|
|
||||||
spawn_x = i
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local spawn_dy
|
local spawn_dy
|
||||||
if (config.gamesettings.spawn_positions == 1) then
|
if (config.gamesettings.spawn_positions == 1) then
|
||||||
@@ -262,7 +248,6 @@ function Ruleset:initializePiece(
|
|||||||
playSE("irs")
|
playSE("irs")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self:dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked)
|
|
||||||
return piece
|
return piece
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -275,15 +260,13 @@ function Ruleset:processPiece(
|
|||||||
drop_locked, hard_drop_locked,
|
drop_locked, hard_drop_locked,
|
||||||
hard_drop_enabled, additive_gravity, classic_lock
|
hard_drop_enabled, additive_gravity, classic_lock
|
||||||
)
|
)
|
||||||
if piece.locked then return end
|
|
||||||
|
|
||||||
local synchroes_allowed = ({not self.world, true, false})[config.gamesettings.synchroes_allowed]
|
local synchroes_allowed = ({not self.world, true, false})[config.gamesettings.synchroes_allowed]
|
||||||
|
|
||||||
if synchroes_allowed then
|
if synchroes_allowed then
|
||||||
self:rotatePiece(inputs, piece, grid, prev_inputs, false)
|
self:rotatePiece(inputs, piece, grid, prev_inputs, false)
|
||||||
self:movePiece(piece, grid, move, gravity >= 20)
|
self:movePiece(piece, grid, move, gravity >= grid.height - 4)
|
||||||
else
|
else
|
||||||
self:movePiece(piece, grid, move, gravity >= 20)
|
self:movePiece(piece, grid, move, gravity >= grid.height - 4)
|
||||||
self:rotatePiece(inputs, piece, grid, prev_inputs, false)
|
self:rotatePiece(inputs, piece, grid, prev_inputs, false)
|
||||||
end
|
end
|
||||||
self:dropPiece(
|
self:dropPiece(
|
||||||
|
|||||||
Reference in New Issue
Block a user