Compare commits
25 Commits
v0.2.6
...
v0.3-beta1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57c7d9c4c3 | ||
|
|
9f52d8bf10 | ||
|
|
57bd6a8286 | ||
|
|
1a68cd8fce | ||
|
|
56baf46839 | ||
|
|
305d07e10a | ||
|
|
8d954cabc2 | ||
|
|
0281220ea0 | ||
|
|
aef5d88d3f | ||
|
|
3676f7697c | ||
|
|
acb0eb1a71 | ||
|
|
a89bf05cab | ||
|
|
8008315994 | ||
|
|
90f62cb7dd | ||
|
|
eaee5fc7f0 | ||
|
|
e3b038b5a7 | ||
|
|
083693496e | ||
|
|
ba576dfc77 | ||
|
|
e195ccd721 | ||
|
|
70f703eb2f | ||
|
|
dc4d4a8259 | ||
|
|
565510c7b2 | ||
|
|
c26a3f37de | ||
|
|
0c1ce2f717 | ||
|
|
f14ab2a328 |
@@ -81,6 +81,8 @@ It should run automatically!
|
||||
|
||||
Simply drag your mode, ruleset, and randomizer Lua files into their respective [directory](https://love2d.org/wiki/love.filesystem), and they should appear automatically.
|
||||
|
||||
**WARNING:** The .exe / .love files and the bleeding edge releases have different save directories. Read the above link carefully!
|
||||
|
||||
For more detailed instructions, install [this](https://github.com/SashLilac/cambridge-modpack) mod pack to get a taste of the mod potential.
|
||||
|
||||
License
|
||||
|
||||
@@ -45,7 +45,7 @@ Other sounds from:
|
||||
Music
|
||||
-----
|
||||
|
||||
1. TGM3 credit roll music.
|
||||
1. Second Reality opening scene music (1993).
|
||||
2. The FitnessGram™ Pacer Test.
|
||||
|
||||
All background music is (currently) only unofficially included. In later releases they may be replaced with specifically licensed music as applicable.
|
||||
|
||||
@@ -20,6 +20,7 @@ backgrounds = {
|
||||
love.graphics.newImage("res/backgrounds/1800.png"),
|
||||
love.graphics.newImage("res/backgrounds/1900.png"),
|
||||
title = love.graphics.newImage("res/backgrounds/title.png"),
|
||||
snow = love.graphics.newImage("res/backgrounds/snow.png"),
|
||||
input_config = love.graphics.newImage("res/backgrounds/options-input.png"),
|
||||
game_config = love.graphics.newImage("res/backgrounds/options-game.png"),
|
||||
}
|
||||
@@ -48,6 +49,18 @@ blocks = {
|
||||
F = love.graphics.newImage("res/img/bone.png"),
|
||||
A = love.graphics.newImage("res/img/bone.png"),
|
||||
X = love.graphics.newImage("res/img/bone.png"),
|
||||
},
|
||||
["gem"] = {
|
||||
R = love.graphics.newImage("res/img/gem1.png"),
|
||||
O = love.graphics.newImage("res/img/gem3.png"),
|
||||
Y = love.graphics.newImage("res/img/gem7.png"),
|
||||
G = love.graphics.newImage("res/img/gem6.png"),
|
||||
C = love.graphics.newImage("res/img/gem2.png"),
|
||||
B = love.graphics.newImage("res/img/gem4.png"),
|
||||
M = love.graphics.newImage("res/img/gem5.png"),
|
||||
F = love.graphics.newImage("res/img/gem9.png"),
|
||||
A = love.graphics.newImage("res/img/gem9.png"),
|
||||
X = love.graphics.newImage("res/img/gem9.png"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,4 +97,5 @@ misc_graphics = {
|
||||
go = love.graphics.newImage("res/img/go.png"),
|
||||
select_mode = love.graphics.newImage("res/img/select_mode.png"),
|
||||
strike = love.graphics.newImage("res/img/strike.png"),
|
||||
santa = love.graphics.newImage("res/img/santa.png")
|
||||
}
|
||||
3
main.lua
@@ -129,6 +129,7 @@ function love.keypressed(key, scancode)
|
||||
love.window.setFullscreen(config["fullscreen"])
|
||||
elseif scancode == "f2" and scene.title ~= "Input Config" and scene.title ~= "Game" then
|
||||
scene = InputConfigScene()
|
||||
switchBGM(nil)
|
||||
-- secret sound playing :eyes:
|
||||
elseif scancode == "f8" and scene.title == "Title" then
|
||||
config.secret = not config.secret
|
||||
@@ -251,7 +252,7 @@ function love.joystickhat(joystick, hat, direction)
|
||||
end
|
||||
|
||||
function love.focus(f)
|
||||
if f then
|
||||
if f and (scene.title ~= "Game" or not scene.paused) then
|
||||
resumeBGM()
|
||||
else
|
||||
pauseBGM()
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
tar -a -c -f cambridge.zip libs/binser.lua libs/classic.lua libs/discordRPC.lua load res scene tetris conf.lua main.lua scene.lua funcs.lua
|
||||
tar -a -c -f cambridge.zip libs/binser.lua libs/classic.lua libs/simple-slider.lua libs/discordRPC.lua load res scene tetris conf.lua main.lua scene.lua funcs.lua
|
||||
rename cambridge.zip cambridge.love
|
||||
BIN
res/backgrounds/snow.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
res/img/gem1.png
Normal file
|
After Width: | Height: | Size: 462 B |
BIN
res/img/gem2.png
Normal file
|
After Width: | Height: | Size: 388 B |
BIN
res/img/gem3.png
Normal file
|
After Width: | Height: | Size: 445 B |
BIN
res/img/gem4.png
Normal file
|
After Width: | Height: | Size: 426 B |
BIN
res/img/gem5.png
Normal file
|
After Width: | Height: | Size: 376 B |
BIN
res/img/gem6.png
Normal file
|
After Width: | Height: | Size: 377 B |
BIN
res/img/gem7.png
Normal file
|
After Width: | Height: | Size: 399 B |
BIN
res/img/gem9.png
Normal file
|
After Width: | Height: | Size: 354 B |
BIN
res/img/santa.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
@@ -4,13 +4,17 @@ CreditsScene.title = "Credits"
|
||||
|
||||
function CreditsScene:new()
|
||||
self.frames = 0
|
||||
switchBGM("credit_roll", "gm3")
|
||||
end
|
||||
|
||||
function CreditsScene:update()
|
||||
self.frames = self.frames + 1
|
||||
if self.frames >= 2200 then
|
||||
if self.frames >= 4200 then
|
||||
playSE("mode_decide")
|
||||
scene = TitleScene()
|
||||
switchBGM(nil)
|
||||
elseif self.frames == 3600 then
|
||||
fadeoutBGM(2)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -23,27 +27,27 @@ function CreditsScene:render()
|
||||
)
|
||||
|
||||
love.graphics.setFont(font_3x5_4)
|
||||
love.graphics.print("Cambridge Credits", 320, 500 - self.frames)
|
||||
love.graphics.print("THANK YOU\nFOR PLAYING!", 320, math.max(1500 - self.frames, 240))
|
||||
love.graphics.print("Cambridge Credits", 320, 500 - self.frames / 2)
|
||||
love.graphics.print("THANK YOU\nFOR PLAYING!", 320, math.max(1500 - self.frames / 2, 240))
|
||||
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
love.graphics.print("Game Developers", 320, 550 - self.frames)
|
||||
love.graphics.print("Project Heads", 320, 640 - self.frames)
|
||||
love.graphics.print("Other Game Developers", 320, 730 - self.frames)
|
||||
love.graphics.print("Special Thanks", 320, 900 - self.frames)
|
||||
love.graphics.print("- SashLilac / SpinTriple", 320, math.max(2000 - self.frames, 320))
|
||||
love.graphics.print("Game Developers", 320, 550 - self.frames / 2)
|
||||
love.graphics.print("Project Heads", 320, 640 - self.frames / 2)
|
||||
love.graphics.print("Other Game Developers", 320, 730 - self.frames / 2)
|
||||
love.graphics.print("Special Thanks", 320, 900 - self.frames / 2)
|
||||
love.graphics.print("- SashLilac / SpinTriple", 320, math.max(2000 - self.frames / 2, 320))
|
||||
|
||||
love.graphics.setFont(font_3x5_2)
|
||||
love.graphics.print("Oshisaure\nJoe Zeng", 320, 590 - self.frames)
|
||||
love.graphics.print("Mizu\nHailey", 320, 680 - self.frames)
|
||||
love.graphics.print("Axel Fox - Multimino\nMine - Tetra Online\nDr Ocelot - Tetra Legends\nFelicity / nightmareci - Shiromino\n2Tie - TGMsim\nPhoenix Flare - Master of Blocks", 320, 770 - self.frames)
|
||||
love.graphics.print("Oshisaure\nJoe Zeng", 320, 590 - self.frames / 2)
|
||||
love.graphics.print("Mizu\nHailey", 320, 680 - self.frames / 2)
|
||||
love.graphics.print("Axel Fox - Multimino\nMine - Tetra Online\nDr Ocelot - Tetra Legends\nFelicity / nightmareci - Shiromino\n2Tie - TGMsim\nPhoenix Flare - Master of Blocks", 320, 770 - self.frames / 2)
|
||||
love.graphics.print(
|
||||
"RocketLanterns\nCylinderKnot\nHammrTime\nKirby703\nMattMayuga\nMyPasswordIsWeak\n" ..
|
||||
"Nikki Karissa\noffwo\nsinefuse\nTetro48\nTimmSkiller\nuser74003\nAgentBasey\n" ..
|
||||
"CheeZed_Fish\neightsixfivezero\nEricICX\ngizmo4487\nM1ssing0\nMarkGamed7794\n" ..
|
||||
"pokemonfan1937\nSimon\nstratus\nZaptorZap\nThe Absolute PLUS Discord\nTetra Legends Discord\n" ..
|
||||
"Tetra Online Discord\nMultimino Discord\nCambridge Discord\nAnd to you, the player!",
|
||||
320, 940 - self.frames
|
||||
320, 940 - self.frames / 2
|
||||
)
|
||||
end
|
||||
|
||||
@@ -51,6 +55,7 @@ function CreditsScene:onInputPress(e)
|
||||
if e.input == "menu_decide" or e.scancode == "return" or
|
||||
e.input == "menu_back" or e.scancode == "delete" or e.scancode == "backspace" then
|
||||
scene = TitleScene()
|
||||
switchBGM(nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -36,10 +36,9 @@ function GameScene:update()
|
||||
inputs[input] = value
|
||||
end
|
||||
self.game:update(inputs, self.ruleset)
|
||||
end
|
||||
|
||||
self.game.grid:update()
|
||||
end
|
||||
end
|
||||
|
||||
function GameScene:render()
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
@@ -87,9 +86,9 @@ function GameScene:onInputPress(e)
|
||||
elseif e.input == "retry" then
|
||||
scene = GameScene(self.retry_mode, self.retry_ruleset)
|
||||
elseif e.input == "pause" and not (self.game.game_over or self.game.completed) then
|
||||
if not self.paused then pauseBGM()
|
||||
else resumeBGM() end
|
||||
self.paused = not self.paused
|
||||
if self.paused then pauseBGM()
|
||||
else resumeBGM() end
|
||||
elseif e.input == "menu_back" then
|
||||
scene = ModeSelectScene()
|
||||
elseif e.input and string.sub(e.input, 1, 5) ~= "menu_" then
|
||||
|
||||
@@ -7,14 +7,17 @@ require 'libs.simple-slider'
|
||||
|
||||
ConfigScene.options = {
|
||||
-- this serves as reference to what the options' values mean i guess?
|
||||
{"manlock", "Manual Locking",{"Per ruleset","Per gamemode","Harddrop", "Softdrop"}},
|
||||
{"piece_colour", "Piece Colours", {"Per ruleset","Arika" ,"TTC"}},
|
||||
{"world_reverse","A Button Rotation", {"Left" ,"Auto" ,"Right"}},
|
||||
{"display_gamemode", "Display Gamemode", {"On", "Off"}},
|
||||
{"das_last_key", "DAS Switch", {"Default", "Instant"}},
|
||||
{"smooth_movement", "Smooth Piece Drop", {"On", "Off"}},
|
||||
{"synchroes_allowed", "Synchroes", {"Per ruleset", "On", "Off"}},
|
||||
{"diagonal_input", "Diagonal Input", {"On", "Off"}}
|
||||
-- Format: {name in config, displayed name, uses slider?, options OR slider name}
|
||||
{"manlock", "Manual Locking", false, {"Per ruleset", "Per gamemode", "Harddrop", "Softdrop"}},
|
||||
{"piece_colour", "Piece Colours", false, {"Per ruleset", "Arika", "TTC"}},
|
||||
{"world_reverse", "A Button Rotation", false, {"Left", "Auto", "Right"}},
|
||||
{"display_gamemode", "Display Gamemode", false, {"On", "Off"}},
|
||||
{"das_last_key", "DAS Switch", false, {"Default", "Instant"}},
|
||||
{"smooth_movement", "Smooth Piece Drop", false, {"On", "Off"}},
|
||||
{"synchroes_allowed", "Synchroes", false, {"Per ruleset", "On", "Off"}},
|
||||
{"diagonal_input", "Diagonal Input", false, {"On", "Off"}},
|
||||
{"sfx_volume", "SFX", true, "sfxSlider"},
|
||||
{"bgm_volume", "BGM", true, "bgmSlider"},
|
||||
}
|
||||
local optioncount = #ConfigScene.options
|
||||
|
||||
@@ -46,25 +49,33 @@ function ConfigScene:render()
|
||||
0.5, 0.5
|
||||
)
|
||||
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
love.graphics.print("SFX Volume: " .. math.floor(self.sfxSlider:getValue()) .. "%", 75, 325)
|
||||
love.graphics.print("BGM Volume: " .. math.floor(self.bgmSlider:getValue()) .. "%", 375, 325)
|
||||
|
||||
love.graphics.setFont(font_3x5_4)
|
||||
love.graphics.print("GAME SETTINGS", 80, 40)
|
||||
|
||||
--Lazy check to see if we're on the SFX or BGM slider. Probably will need to be rewritten if more options get added.
|
||||
love.graphics.setColor(1, 1, 1, 0.5)
|
||||
if not ConfigScene.options[self.highlight][3] then
|
||||
love.graphics.rectangle("fill", 20, 98 + self.highlight * 20, 170, 22)
|
||||
else
|
||||
love.graphics.rectangle("fill", 65 + (1+self.highlight-#self.options) * 300, 322, 215, 33)
|
||||
end
|
||||
|
||||
love.graphics.setFont(font_3x5_2)
|
||||
for i, option in ipairs(ConfigScene.options) do
|
||||
if not option[3] then
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.printf(option[2], 40, 100 + i * 20, 150, "left")
|
||||
for j, setting in ipairs(option[3]) do
|
||||
for j, setting in ipairs(option[4]) do
|
||||
love.graphics.setColor(1, 1, 1, config.gamesettings[option[1]] == j and 1 or 0.5)
|
||||
love.graphics.printf(setting, 100 + 110 * j, 100 + i * 20, 100, "center")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
love.graphics.print("SFX Volume: " .. math.floor(self.sfxSlider:getValue()) .. "%", 75, 325)
|
||||
love.graphics.print("BGM Volume: " .. math.floor(self.bgmSlider:getValue()) .. "%", 375, 325)
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 0.75)
|
||||
self.sfxSlider:draw()
|
||||
@@ -83,13 +94,25 @@ function ConfigScene:onInputPress(e)
|
||||
playSE("cursor")
|
||||
self.highlight = Mod1(self.highlight+1, optioncount)
|
||||
elseif e.input == "left" or e.scancode == "left" then
|
||||
if not self.options[self.highlight][3] then
|
||||
playSE("cursor_lr")
|
||||
local option = ConfigScene.options[self.highlight]
|
||||
config.gamesettings[option[1]] = Mod1(config.gamesettings[option[1]]-1, #option[3])
|
||||
config.gamesettings[option[1]] = Mod1(config.gamesettings[option[1]]-1, #option[4])
|
||||
else
|
||||
playSE("cursor")
|
||||
sld = self[self.options[self.highlight][4]]
|
||||
sld.value = math.max(sld.min, math.min(sld.max, (sld:getValue() - 3) / (sld.max - sld.min)))
|
||||
end
|
||||
elseif e.input == "right" or e.scancode == "right" then
|
||||
if not self.options[self.highlight][3] then
|
||||
playSE("cursor_lr")
|
||||
local option = ConfigScene.options[self.highlight]
|
||||
config.gamesettings[option[1]] = Mod1(config.gamesettings[option[1]]+1, #option[3])
|
||||
config.gamesettings[option[1]] = Mod1(config.gamesettings[option[1]]+1, #option[4])
|
||||
else
|
||||
playSE("cursor")
|
||||
sld = self[self.options[self.highlight][4]]
|
||||
sld.value = math.max(sld.min, math.min(sld.max, (sld:getValue() + 3) / (sld.max - sld.min)))--math.max(0, (math.floor(sld:getValue())+2)/(sld.max-sld.min))
|
||||
end
|
||||
elseif e.input == "menu_back" or e.scancode == "delete" or e.scancode == "backspace" then
|
||||
loadSave()
|
||||
scene = SettingsScene()
|
||||
|
||||
@@ -27,6 +27,11 @@ local mainmenuidle = {
|
||||
|
||||
function TitleScene:new()
|
||||
self.main_menu_state = 1
|
||||
self.frames = 0
|
||||
self.snow_bg_opacity = 0
|
||||
self.y_offset = 0
|
||||
self.text = ""
|
||||
self.text_flag = false
|
||||
DiscordRPC:update({
|
||||
details = "In menus",
|
||||
state = mainmenuidle[math.random(#mainmenuidle)],
|
||||
@@ -34,17 +39,39 @@ function TitleScene:new()
|
||||
end
|
||||
|
||||
function TitleScene:update()
|
||||
if self.text_flag then
|
||||
self.frames = self.frames + 1
|
||||
self.snow_bg_opacity = self.snow_bg_opacity + 0.01
|
||||
end
|
||||
if self.frames < 125 then self.y_offset = self.frames
|
||||
elseif self.frames < 185 then self.y_offset = 125
|
||||
else self.y_offset = 310 - self.frames end
|
||||
end
|
||||
|
||||
function TitleScene:render()
|
||||
love.graphics.setFont(font_3x5_2)
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 1 - self.snow_bg_opacity)
|
||||
love.graphics.draw(
|
||||
backgrounds["title"],
|
||||
0, 0, 0,
|
||||
0.5, 0.5
|
||||
)
|
||||
|
||||
love.graphics.setColor(1, 1, 1, self.snow_bg_opacity)
|
||||
love.graphics.draw(
|
||||
backgrounds["snow"],
|
||||
0, 0, 0,
|
||||
0.5, 0.5
|
||||
)
|
||||
|
||||
love.graphics.draw(
|
||||
misc_graphics["santa"],
|
||||
400, -205 + self.y_offset,
|
||||
0, 0.5, 0.5
|
||||
)
|
||||
love.graphics.print("Happy Holidays!", 320, -100 + self.y_offset)
|
||||
|
||||
love.graphics.print(self.restart_message and "Restart Cambridge..." or "", 0, 0)
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 0.5)
|
||||
@@ -74,6 +101,11 @@ function TitleScene:onInputPress(e)
|
||||
playSE("cursor")
|
||||
elseif e.input == "menu_back" or e.scancode == "backspace" or e.scancode == "delete" then
|
||||
love.event.quit()
|
||||
else
|
||||
self.text = self.text .. (e.scancode ~= nil and e.scancode or "")
|
||||
if self.text == "ffffff" then
|
||||
self.text_flag = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -5,11 +5,20 @@ TuningScene.title = "Tuning Settings"
|
||||
require 'load.save'
|
||||
require 'libs.simple-slider'
|
||||
|
||||
TuningScene.options = {
|
||||
-- Serves as a reference for the options available in the menu. Format: {name in config, name as displayed if applicable, slider name}
|
||||
{"das", "DAS", "dasSlider"},
|
||||
{"arr", "ARR", "arrSlider"},
|
||||
}
|
||||
|
||||
local optioncount = #TuningScene.options
|
||||
|
||||
function TuningScene:new()
|
||||
DiscordRPC:update({
|
||||
details = "In menus",
|
||||
state = "Changing tuning settings",
|
||||
})
|
||||
self.highlight = 1
|
||||
|
||||
self.dasSlider = newSlider(290, 225, 400, config.das, 0, 20, function(v) config.das = math.floor(v) end, {width=20})
|
||||
self.arrSlider = newSlider(290, 325, 400, config.arr, 0, 6, function(v) config.arr = math.floor(v) end, {width=20})
|
||||
@@ -28,6 +37,11 @@ function TuningScene:render()
|
||||
0.5, 0.5
|
||||
)
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 0.5)
|
||||
love.graphics.rectangle("fill", 75, 73 + self.highlight * 100, 400, 33)
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
|
||||
love.graphics.setFont(font_3x5_4)
|
||||
love.graphics.print("TUNING SETTINGS", 80, 40)
|
||||
|
||||
@@ -48,6 +62,20 @@ function TuningScene:onInputPress(e)
|
||||
playSE("mode_decide")
|
||||
saveConfig()
|
||||
scene = SettingsScene()
|
||||
elseif e.input == "up" or e.scancode == "up" then
|
||||
playSE("cursor")
|
||||
self.highlight = Mod1(self.highlight-1, optioncount)
|
||||
elseif e.input == "down" or e.scancode == "down" then
|
||||
playSE("cursor")
|
||||
self.highlight = Mod1(self.highlight+1, optioncount)
|
||||
elseif e.input == "left" or e.scancode == "left" then
|
||||
playSE("cursor")
|
||||
sld = self[self.options[self.highlight][3]]
|
||||
sld.value = math.max(sld.min, math.min(sld.max, (sld:getValue() - 1) / (sld.max - sld.min)))
|
||||
elseif e.input == "right" or e.scancode == "right" then
|
||||
playSE("cursor")
|
||||
sld = self[self.options[self.highlight][3]]
|
||||
sld.value = math.max(sld.min, math.min(sld.max, (sld:getValue() + 1) / (sld.max - sld.min)))
|
||||
elseif e.input == "menu_back" or e.scancode == "delete" or e.scancode == "backspace" then
|
||||
loadSave()
|
||||
scene = SettingsScene()
|
||||
|
||||
@@ -194,7 +194,7 @@ function Grid:applyPiece(piece)
|
||||
for index, offset in pairs(offsets) do
|
||||
x = piece.position.x + offset.x
|
||||
y = piece.position.y + offset.y
|
||||
if y + 1 > 0 then
|
||||
if y + 1 > 0 and y < 24 then
|
||||
self.grid[y+1][x+1] = {
|
||||
skin = piece.skin,
|
||||
colour = piece.colour
|
||||
@@ -273,6 +273,43 @@ function Grid:checkSecretGrade()
|
||||
return sgrade
|
||||
end
|
||||
|
||||
function Grid:hasGemBlocks()
|
||||
for y = 1, 24 do
|
||||
for x = 1, 10 do
|
||||
if self.grid[y][x].skin == "gem" then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Grid:mirror()
|
||||
local new_grid = {}
|
||||
for y = 1, 24 do
|
||||
new_grid[y] = {}
|
||||
for x = 1, 10 do
|
||||
new_grid[y][x] = empty
|
||||
end
|
||||
end
|
||||
|
||||
for y = 1, 24 do
|
||||
for x = 1, 10 do
|
||||
new_grid[y][x] = self.grid[y][11 - x]
|
||||
end
|
||||
end
|
||||
self.grid = new_grid
|
||||
end
|
||||
|
||||
function Grid:applyMap(map)
|
||||
for y, row in pairs(map) do
|
||||
for x, block in pairs(row) do
|
||||
self.grid_age[y][x] = 0
|
||||
self.grid[y][x] = block
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Grid:update()
|
||||
for y = 1, 24 do
|
||||
for x = 1, 10 do
|
||||
@@ -380,4 +417,44 @@ function Grid:drawInvisible(opacity_function, garbage_opacity_function, lock_fla
|
||||
end
|
||||
end
|
||||
|
||||
function Grid:drawCustom(colour_function, gamestate)
|
||||
--[[
|
||||
colour_function: (game, block, x, y, age) -> (R, G, B, A, outlineA)
|
||||
When called, calls the supplied function on every block passing the block itself as argument
|
||||
as well as coordinates and the grid_age value of the same cell.
|
||||
Should return a RGBA colour for the block, as well as the opacity of the stack outline (0 for no outline).
|
||||
|
||||
gamestate: the gamemode instance itself to pass in colour_function
|
||||
]]
|
||||
for y = 5, 24 do
|
||||
for x = 1, 10 do
|
||||
local block = self.grid[y][x]
|
||||
if block ~= empty then
|
||||
local R, G, B, A, outline = colour_function(gamestate, block, x, y, self.grid_age[y][x])
|
||||
if self.grid[y][x].colour == "X" then
|
||||
A = 1
|
||||
end
|
||||
love.graphics.setColor(R, G, B, A)
|
||||
love.graphics.draw(blocks[self.grid[y][x].skin][self.grid[y][x].colour], 48+x*16, y*16)
|
||||
if outline > 0 and self.grid[y][x].colour ~= "X" then
|
||||
love.graphics.setColor(0.64, 0.64, 0.64, outline)
|
||||
love.graphics.setLineWidth(1)
|
||||
if y > 1 and self.grid[y-1][x] == empty then
|
||||
love.graphics.line(48.0+x*16, -0.5+y*16, 64.0+x*16, -0.5+y*16)
|
||||
end
|
||||
if y < 24 and self.grid[y+1][x] == empty then
|
||||
love.graphics.line(48.0+x*16, 16.5+y*16, 64.0+x*16, 16.5+y*16)
|
||||
end
|
||||
if x > 1 and self.grid[y][x-1] == empty then
|
||||
love.graphics.line(47.5+x*16, -0.0+y*16, 47.5+x*16, 16.0+y*16)
|
||||
end
|
||||
if x < 10 and self.grid[y][x+1] == empty then
|
||||
love.graphics.line(64.5+x*16, -0.0+y*16, 64.5+x*16, 16.0+y*16)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Grid
|
||||
|
||||
@@ -162,6 +162,7 @@ function GameMode:update(inputs, ruleset)
|
||||
not self.hard_drop_locked then
|
||||
self:onHardDrop(piece_dy)
|
||||
if self.lock_on_hard_drop then
|
||||
self.piece_hard_dropped = true
|
||||
self.piece.locked = true
|
||||
end
|
||||
end
|
||||
@@ -311,6 +312,15 @@ function GameMode:chargeDAS(inputs)
|
||||
end
|
||||
end
|
||||
|
||||
function GameMode:areCancel(inputs, ruleset)
|
||||
if ruleset.are_cancel and self.piece_hard_dropped and
|
||||
not self.prev_inputs.up and
|
||||
strTrueValues(inputs) ~= "" then
|
||||
self.lcd = 0
|
||||
self.are = 0
|
||||
end
|
||||
end
|
||||
|
||||
function GameMode:processDelays(inputs, ruleset, drop_speed)
|
||||
if self.ready_frames == 100 then
|
||||
playedReadySE = false
|
||||
@@ -331,18 +341,7 @@ function GameMode:processDelays(inputs, ruleset, drop_speed)
|
||||
end
|
||||
elseif self.lcd > 0 then
|
||||
self.lcd = self.lcd - 1
|
||||
if ruleset.are_cancel and
|
||||
(self.move == "none" and not self.prev_inputs["up"] and
|
||||
not self.prev_inputs["rotate_left"] and not self.prev_inputs["rotate_left2"] and
|
||||
not self.prev_inputs["rotate_right"] and not self.prev_inputs["rotate_right2"] and
|
||||
not self.prev_inputs["rotate_180"]) and
|
||||
(inputs["left"] or inputs["right"] or inputs["up"] or
|
||||
inputs["rotate_left"] or inputs["rotate_left2"] or
|
||||
inputs["rotate_right"] or inputs["rotate_right2"] or
|
||||
inputs["rotate_180"]) then
|
||||
self.lcd = 0
|
||||
self.are = 0
|
||||
end
|
||||
self:areCancel(inputs, ruleset)
|
||||
if self.lcd == 0 then
|
||||
self.grid:clearClearedRows()
|
||||
playSE("fall")
|
||||
@@ -352,17 +351,7 @@ function GameMode:processDelays(inputs, ruleset, drop_speed)
|
||||
end
|
||||
elseif self.are > 0 then
|
||||
self.are = self.are - 1
|
||||
if ruleset.are_cancel and
|
||||
(self.move == "none" and not self.prev_inputs["up"] and
|
||||
not self.prev_inputs["rotate_left"] and not self.prev_inputs["rotate_left2"] and
|
||||
not self.prev_inputs["rotate_right"] and not self.prev_inputs["rotate_right2"] and
|
||||
not self.prev_inputs["rotate_180"]) and
|
||||
(inputs["left"] or inputs["right"] or inputs["up"] or
|
||||
inputs["rotate_left"] or inputs["rotate_left2"] or
|
||||
inputs["rotate_right"] or inputs["rotate_right2"] or
|
||||
inputs["rotate_180"]) then
|
||||
self.are = 0
|
||||
end
|
||||
self:areCancel(inputs, ruleset)
|
||||
if self.are == 0 then
|
||||
self:initializeOrHold(inputs, ruleset)
|
||||
end
|
||||
@@ -407,6 +396,7 @@ function GameMode:hold(inputs, ruleset, ihs)
|
||||
end
|
||||
|
||||
function GameMode:initializeNextPiece(inputs, ruleset, piece_data, generate_next_piece)
|
||||
self.piece_hard_dropped = false
|
||||
local gravity = self:getGravity()
|
||||
self.piece = ruleset:initializePiece(
|
||||
inputs, piece_data, self.grid, gravity,
|
||||
|
||||
@@ -27,7 +27,7 @@ function MarathonA3Game:new()
|
||||
self.section_cool_grade = 0
|
||||
self.section_status = { [0] = "none" }
|
||||
self.section_start_time = 0
|
||||
self.section_70_times = { [0] = 0 }
|
||||
self.secondary_section_times = { [0] = 0 }
|
||||
self.section_times = { [0] = 0 }
|
||||
self.section_cool = false
|
||||
|
||||
@@ -163,8 +163,8 @@ function MarathonA3Game:onLineClear(cleared_row_count)
|
||||
self:updateSectionTimes(self.level, self.level + advanced_levels)
|
||||
if not self.clear then
|
||||
self.level = math.min(self.level + advanced_levels, 999)
|
||||
end
|
||||
self.speed_level = self.speed_level + advanced_levels
|
||||
end
|
||||
if self.level == 999 and not self.clear then
|
||||
self.clear = true
|
||||
self.grid:clear()
|
||||
@@ -194,7 +194,7 @@ function MarathonA3Game:updateSectionTimes(old_level, new_level)
|
||||
-- record new section
|
||||
section_time = self.frames - self.section_start_time
|
||||
table.insert(self.section_times, section_time)
|
||||
self.section_start_time = self.frames
|
||||
if new_level < 999 then self.section_start_time = self.frames end
|
||||
|
||||
self.speed_level = self.section_cool and self.speed_level + 100 or self.speed_level
|
||||
|
||||
@@ -214,15 +214,15 @@ function MarathonA3Game:updateSectionTimes(old_level, new_level)
|
||||
elseif old_level % 100 < 70 and new_level % 100 >= 70 then
|
||||
-- record section 70 time
|
||||
section_70_time = self.frames - self.section_start_time
|
||||
table.insert(self.section_70_times, section_70_time)
|
||||
table.insert(self.secondary_section_times, section_70_time)
|
||||
|
||||
if section <= 9 and self.section_status[section - 1] == "cool" and
|
||||
self.section_70_times[section] < self.section_70_times[section - 1] + 120 then
|
||||
self.secondary_section_times[section] < self.secondary_section_times[section - 1] + 120 then
|
||||
self.section_cool = true
|
||||
self.coolregret_message = "COOL!!"
|
||||
self.coolregret_timer = 300
|
||||
elseif self.section_status[section - 1] == "cool" then self.section_cool = false
|
||||
elseif section <= 9 and self.section_70_times[section] < cool_cutoffs[section] then
|
||||
elseif section <= 9 and self.secondary_section_times[section] < cool_cutoffs[section] then
|
||||
self.section_cool = true
|
||||
self.coolregret_message = "COOL!!"
|
||||
self.coolregret_timer = 300
|
||||
@@ -395,6 +395,16 @@ MarathonA3Game.mRollOpacityFunction = function(age)
|
||||
else return 1 - age / 4 end
|
||||
end
|
||||
|
||||
function MarathonA3Game:sectionColourFunction(section)
|
||||
if self.section_status[section] == "cool" then
|
||||
return { 0, 1, 0, 1 }
|
||||
elseif self.section_status[section] == "regret" then
|
||||
return { 1, 0, 0, 1 }
|
||||
else
|
||||
return { 1, 1, 1, 1 }
|
||||
end
|
||||
end
|
||||
|
||||
function MarathonA3Game:drawScoringInfo()
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
|
||||
@@ -415,6 +425,8 @@ function MarathonA3Game:drawScoringInfo()
|
||||
|
||||
-- draw section time data
|
||||
current_section = math.floor(self.level / 100) + 1
|
||||
self:drawSectionTimesWithSecondary(current_section)
|
||||
--[[
|
||||
|
||||
section_x = 530
|
||||
section_70_x = 440
|
||||
@@ -425,20 +437,21 @@ function MarathonA3Game:drawScoringInfo()
|
||||
end
|
||||
end
|
||||
|
||||
for section, time in pairs(self.section_70_times) do
|
||||
for section, time in pairs(self.secondary_section_times) do
|
||||
if section > 0 then
|
||||
love.graphics.printf(formatTime(time), section_70_x, 40 + 20 * section, 90, "left")
|
||||
end
|
||||
end
|
||||
|
||||
local current_x
|
||||
if table.getn(self.section_times) < table.getn(self.section_70_times) then
|
||||
if table.getn(self.section_times) < table.getn(self.secondary_section_times) then
|
||||
current_x = section_x
|
||||
else
|
||||
current_x = section_70_x
|
||||
end
|
||||
|
||||
if not self.clear then love.graphics.printf(formatTime(self.frames - self.section_start_time), current_x, 40 + 20 * current_section, 90, "left") end
|
||||
]]--
|
||||
|
||||
if(self.coolregret_timer > 0) then
|
||||
love.graphics.printf(self.coolregret_message, 64, 400, 160, "center")
|
||||
@@ -475,7 +488,7 @@ function MarathonA3Game:getSectionEndLevel()
|
||||
end
|
||||
|
||||
function MarathonA3Game:getBackground()
|
||||
return math.floor(self.level / 100)
|
||||
return math.floor(self.speed_level / 100)
|
||||
end
|
||||
|
||||
return MarathonA3Game
|
||||
|
||||
568
tetris/modes/sakura.lua
Normal file
@@ -0,0 +1,568 @@
|
||||
require 'funcs'
|
||||
|
||||
local GameMode = require 'tetris.modes.gamemode'
|
||||
local Piece = require 'tetris.components.piece'
|
||||
|
||||
local SakuraRandomizer = require 'tetris.randomizers.sakura'
|
||||
|
||||
local SakuraGame = GameMode:extend()
|
||||
|
||||
SakuraGame.name = "Sakura A3"
|
||||
SakuraGame.hash = "SakuraA3"
|
||||
SakuraGame.tagline = "Clear away the Gem Blocks as fast as possible!"
|
||||
|
||||
local b = {
|
||||
["r"] = { skin = "2tie", colour = "R" },
|
||||
["o"] = { skin = "2tie", colour = "O" },
|
||||
["y"] = { skin = "2tie", colour = "Y" },
|
||||
["g"] = { skin = "2tie", colour = "G" },
|
||||
["c"] = { skin = "2tie", colour = "C" },
|
||||
["b"] = { skin = "2tie", colour = "B" },
|
||||
["m"] = { skin = "2tie", colour = "M" },
|
||||
["R"] = { skin = "gem", colour = "R" },
|
||||
["O"] = { skin = "gem", colour = "O" },
|
||||
["Y"] = { skin = "gem", colour = "Y" },
|
||||
["G"] = { skin = "gem", colour = "G" },
|
||||
["C"] = { skin = "gem", colour = "C" },
|
||||
["B"] = { skin = "gem", colour = "B" },
|
||||
["M"] = { skin = "gem", colour = "M" },
|
||||
}
|
||||
|
||||
local effects = {
|
||||
[4] = "mirror",
|
||||
[8] = "xray",
|
||||
[12] = "color",
|
||||
[13] = "mirror",
|
||||
[16] = "roll",
|
||||
[23] = "big"
|
||||
}
|
||||
|
||||
local maps = {
|
||||
[1] = {
|
||||
[22] = {nil, nil, b.O, b.R, nil, nil, b.M, b.m, nil, nil},
|
||||
[23] = {nil, b.G, b.c, b.c, b.c, b.c, b.c, b.c, b.Y, nil},
|
||||
[24] = {nil, b.C, b.y, b.y, b.y, b.y, b.y, b.y, b.B, nil},
|
||||
},
|
||||
[2] = {
|
||||
[20] = {nil, nil, nil, nil, b.G, b.b, b.b, b.M, nil, nil},
|
||||
[21] = {nil, nil, nil, nil, b.c, b.c, b.c, b.c, nil, nil},
|
||||
[22] = {nil, nil, nil, nil, nil, b.R, b.Y, b.O, nil, nil},
|
||||
[23] = {nil, b.B, b.c, b.c, b.c, b.c, b.c, b.c, b.c, nil},
|
||||
[24] = {nil, b.b, b.b, b.b, b.b, b.b, b.b, b.b, b.C, nil},
|
||||
},
|
||||
[3] = {
|
||||
[20] = {nil, nil, nil, b.R, b.m, b.o, b.M, nil, nil, nil},
|
||||
[21] = {nil, nil, nil, nil, b.o, b.O, nil, nil, nil, nil},
|
||||
[22] = {nil, nil, nil, nil, b.G, b.Y, nil, nil, nil, nil},
|
||||
[23] = {nil, b.m, b.o, b.m, b.o, b.m, b.o, b.m, b.o, nil},
|
||||
[24] = {nil, b.B, b.m, b.o, b.m, b.o, b.m, b.o, b.C, nil},
|
||||
},
|
||||
[4] = {
|
||||
[21] = {nil, nil, b.O, b.g, b.g, b.g, b.g, nil, nil, nil},
|
||||
[22] = {nil, nil, nil, b.R, b.M, b.b, b.b, nil, nil, nil},
|
||||
[23] = {b.G, nil, b.Y, b.g, b.g, b.g, b.g, b.g, nil, nil},
|
||||
[24] = {b.b, b.C, b.b, b.b, b.b, b.b, b.b, b.b, b.B, nil},
|
||||
},
|
||||
[5] = {
|
||||
[16] = {nil, b.B, b.c, b.y, b.c, b.G, b.c, b.y, b.C, nil},
|
||||
[22] = {nil, nil, b.c, b.y, b.c, b.y, b.c, b.y, nil, nil},
|
||||
[23] = {nil, b.O, b.y, b.c, b.y, b.c, b.y, b.c, b.Y, nil},
|
||||
[24] = {nil, b.R, b.c, b.y, b.c, b.y, b.c, b.y, b.M, nil},
|
||||
},
|
||||
[6] = {
|
||||
[21] = {nil, nil, nil, nil, b.O, b.Y, nil, nil, nil, nil},
|
||||
[22] = {nil, nil, b.R, nil, b.b, b.y, nil, b.M, nil, nil},
|
||||
[23] = {nil, nil, nil, nil, b.y, b.b, nil, nil, nil, nil},
|
||||
[24] = {nil, b.G, b.y, b.b, b.C, b.y, b.b, b.y, b.B, nil},
|
||||
},
|
||||
[7] = {
|
||||
[20] = {nil, b.C, b.G, nil, b.r, b.g, b.r, b.g, nil, nil},
|
||||
[21] = {nil, nil, nil, nil, b.R, b.M, b.g, b.r, nil, nil},
|
||||
[22] = {b.r, nil, nil, nil, b.r, b.g, b.O, b.Y, nil, nil},
|
||||
[23] = {b.g, b.r, b.g, b.r, b.g, b.r, b.g, b.r, nil, nil},
|
||||
[24] = {b.r, b.g, b.r, b.g, b.r, b.g, b.r, b.g, b.B, nil},
|
||||
},
|
||||
[8] = {
|
||||
[15] = {nil, nil, nil, b.B, b.m, b.m, b.m, b.m, b.m, b.C},
|
||||
[16] = {nil, nil, nil, nil, nil, nil, nil, nil, nil, b.m},
|
||||
[17] = {nil, nil, nil, nil, nil, nil, nil, nil, nil, b.m},
|
||||
[18] = {nil, b.Y, b.y, b.y, b.y, b.y, b.y, b.y, b.y, b.G},
|
||||
[21] = {b.b, b.b, b.b, b.b, b.b, b.b, b.O, nil, nil, nil},
|
||||
[22] = {b.b, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
[23] = {b.M, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
[24] = {b.o, b.o, b.o, b.o, b.o, b.o, b.o, b.o, b.R, nil},
|
||||
},
|
||||
[9] = {
|
||||
[18] = {nil, nil, nil, b.Y, b.m, b.m, b.m, b.m, nil, nil},
|
||||
[19] = {nil, nil, nil, b.c, b.c, b.c, b.c, b.G, nil, nil},
|
||||
[20] = {b.m, b.m, b.m, b.O, b.M, b.R, nil, nil, nil, nil},
|
||||
[21] = {b.c, b.c, b.c, b.c, b.c, b.c, b.c, b.c, nil, nil},
|
||||
[22] = {b.m, b.m, b.m, b.m, b.m, b.m, b.m, b.m, nil, nil},
|
||||
[23] = {b.c, b.c, b.c, b.c, b.c, b.c, b.c, b.c, b.C, nil},
|
||||
[24] = {b.m, b.m, b.m, b.m, b.m, b.m, b.m, b.m, b.B, nil},
|
||||
},
|
||||
[10] = {
|
||||
[18] = {nil, nil, nil, b.C, b.g, b.g, b.B, nil, nil, nil},
|
||||
[19] = {nil, nil, b.G, b.g, b.g, b.g, b.g, b.Y, nil, nil},
|
||||
[20] = {nil, b.M, b.g, b.g, b.g, b.g, b.g, b.g, b.O, nil},
|
||||
[21] = {nil, nil, nil, nil, b.c, nil, nil, nil, nil, nil},
|
||||
[22] = {nil, nil, nil, nil, b.c, nil, nil, nil, nil, nil},
|
||||
[23] = {nil, nil, nil, nil, b.c, nil, b.o, nil, nil, nil},
|
||||
[24] = {nil, nil, nil, nil, b.R, b.o, b.o, nil, nil, nil},
|
||||
},
|
||||
[11] = {
|
||||
[18] = {nil, nil, nil, nil, b.o, b.o, nil, nil, nil, nil},
|
||||
[19] = {nil, nil, nil, nil, b.R, nil, nil, nil, nil, nil},
|
||||
[20] = {nil, nil, nil, nil, b.r, b.O, nil, nil, nil, nil},
|
||||
[21] = {nil, nil, nil, nil, nil, b.M, nil, nil, nil, nil},
|
||||
[22] = {nil, nil, nil, nil, b.o, b.o, nil, nil, nil, nil},
|
||||
[23] = {nil, nil, nil, nil, b.G, b.Y, nil, nil, nil, nil},
|
||||
[24] = {b.C, b.g, b.g, nil, b.o, b.o, nil, b.g, b.g, b.B},
|
||||
},
|
||||
[12] = {
|
||||
[21] = {nil, nil, nil, nil, nil, nil, nil, b.g, b.g, b.Y},
|
||||
[22] = {nil, nil, b.r, b.G, b.r, nil, nil, nil, b.O, b.g},
|
||||
[23] = {nil, b.r, b.C, b.r, b.B, b.r, nil, nil, nil, b.M},
|
||||
[24] = {b.r, b.r, b.r, b.R, b.r, b.r, b.r, nil, nil, nil},
|
||||
},
|
||||
[13] = {
|
||||
[20] = {b.c, nil, nil, nil, nil, nil, nil, nil, nil, b.B},
|
||||
[21] = {b.c, b.c, nil, nil, nil, nil, nil, nil, b.C, b.c},
|
||||
[22] = {b.c, b.c, b.c, nil, nil, nil, nil, b.G, b.c, b.c},
|
||||
[23] = {b.b, b.b, b.b, b.b, nil, nil, b.Y, b.b, b.b, b.b},
|
||||
[24] = {nil, b.M, b.b, b.b, b.b, b.O, b.b, b.b, b.R, nil},
|
||||
},
|
||||
[14] = {
|
||||
[20] = {nil, nil, nil, b.y, b.r, b.y, nil, nil, nil, nil},
|
||||
[21] = {b.R, nil, nil, b.Y, b.y, b.r, b.G, nil, nil, nil},
|
||||
[22] = {nil, nil, nil, b.y, b.r, b.y, b.r, b.y, b.r, b.B},
|
||||
[23] = {nil, nil, nil, nil, nil, nil, nil, b.O, b.y, b.r},
|
||||
[24] = {nil, nil, nil, nil, nil, nil, b.M, b.y, b.r, b.C},
|
||||
},
|
||||
[15] = {
|
||||
[17] = {nil, nil, b.b, nil, nil, nil, nil, b.b, nil, nil},
|
||||
[18] = {nil, nil, b.b, b.y, b.b, b.b, b.y, b.b, nil, nil},
|
||||
[19] = {nil, nil, nil, b.y, b.b, b.b, b.y, nil, nil, nil},
|
||||
[20] = {nil, nil, nil, nil, b.O, b.Y, nil, nil, nil, nil},
|
||||
[22] = {nil, nil, nil, nil, b.M, b.R, nil, nil, nil, nil},
|
||||
[23] = {nil, nil, nil, b.G, b.y, b.y, b.C, nil, nil, nil},
|
||||
[24] = {nil, nil, b.B, b.y, b.y, b.y, b.y, b.y, nil, nil},
|
||||
},
|
||||
[16] = {
|
||||
[18] = {nil, nil, b.O, nil, nil, nil, nil, b.B, nil, nil},
|
||||
[19] = {nil, nil, b.c, nil, nil, b.G, nil, b.c, nil, nil},
|
||||
[20] = {nil, nil, b.c, nil, b.C, b.R, nil, b.c, nil, nil},
|
||||
[21] = {nil, nil, b.c, nil, nil, nil, nil, b.c, nil, nil},
|
||||
[22] = {nil, nil, b.Y, b.c, b.c, b.c, b.c, b.M, nil, nil},
|
||||
},
|
||||
[17] = {
|
||||
[15] = {b.O, nil, nil, b.g, nil, nil, b.m, nil, nil, b.Y},
|
||||
[16] = {nil, nil, nil, b.g, nil, nil, b.m, nil, nil, nil},
|
||||
[17] = {nil, nil, nil, b.g, nil, nil, b.R, nil, nil, nil},
|
||||
[18] = {nil, nil, nil, b.g, nil, nil, b.m, nil, nil, nil},
|
||||
[19] = {nil, nil, nil, b.M, nil, nil, b.m, nil, nil, nil},
|
||||
[20] = {nil, nil, nil, b.g, nil, nil, b.m, nil, nil, nil},
|
||||
[21] = {nil, nil, nil, b.g, nil, nil, b.G, nil, nil, nil},
|
||||
[22] = {nil, nil, nil, b.g, nil, nil, b.m, nil, nil, nil},
|
||||
[23] = {nil, nil, nil, b.g, nil, nil, b.m, nil, nil, nil},
|
||||
[24] = {nil, b.m, b.m, b.m, b.B, b.C, b.g, b.g, b.g, nil},
|
||||
},
|
||||
[18] = {
|
||||
[19] = {nil, nil, nil, b.y, b.B, b.y, b.y, nil, nil, nil},
|
||||
[20] = {nil, nil, b.y, nil, nil, nil, nil, b.y, nil, nil},
|
||||
[21] = {nil, b.o, nil, nil, b.C, b.R, nil, nil, b.O, nil},
|
||||
[22] = {nil, b.M, nil, nil, b.Y, b.G, nil, nil, b.o, nil},
|
||||
[23] = {nil, b.r, b.o, nil, nil, nil, nil, b.o, b.r, nil},
|
||||
[24] = {nil, b.r, b.r, b.o, b.o, b.o, b.o, b.r, b.r, nil},
|
||||
},
|
||||
[19] = {
|
||||
[15] = {nil, nil, nil, nil, nil, nil, b.O, nil, nil, nil},
|
||||
[16] = {nil, nil, nil, nil, nil, b.o, nil, nil, nil, nil},
|
||||
[17] = {nil, nil, nil, nil, b.o, b.r, b.o, nil, nil, nil},
|
||||
[18] = {nil, b.o, nil, nil, b.o, b.r, b.r, b.o, nil, nil},
|
||||
[19] = {nil, b.o, b.o, nil, nil, b.R, b.r, b.r, nil, nil},
|
||||
[20] = {nil, nil, b.M, b.r, nil, b.r, b.r, b.r, b.r, nil},
|
||||
[21] = {nil, nil, b.r, b.r, b.r, b.r, b.y, b.G, b.o, b.o},
|
||||
[22] = {nil, b.r, b.o, b.y, b.Y, b.y, b.y, b.y, b.y, b.o},
|
||||
[23] = {nil, b.o, b.o, b.y, b.y, b.c, b.c, b.c, b.c, b.C},
|
||||
[24] = {nil, nil, b.o, b.y, b.b, b.b, b.B, b.b, b.b, b.b},
|
||||
},
|
||||
[20] = {
|
||||
[20] = {nil, nil, b.B, b.b, b.b, b.b, b.b, b.b, nil, nil},
|
||||
[21] = {b.c, nil, nil, b.C, b.c, b.c, b.c, nil, nil, b.c},
|
||||
[22] = {b.g, b.g, nil, nil, b.G, b.g, nil, nil, b.g, b.g},
|
||||
[23] = {b.y, b.y, b.o, nil, nil, nil, nil, b.Y, b.y, b.y},
|
||||
[24] = {b.r, b.r, b.r, b.R, nil, nil, b.M, b.r, b.r, b.r},
|
||||
},
|
||||
[21] = {
|
||||
[16] = {nil, nil, b.g, b.g, b.g, b.g, b.g, nil, nil, nil},
|
||||
[17] = {nil, b.g, b.g, b.g, b.g, b.g, b.g, b.B, b.g, nil},
|
||||
[18] = {b.g, b.g, b.g, b.g, b.g, b.g, b.g, b.g, b.C, nil},
|
||||
[19] = {b.g, nil, nil, b.g, b.o, b.o, b.g, nil, nil, b.g},
|
||||
[20] = {nil, b.R, nil, b.g, b.o, b.o, nil, b.M, nil, b.G},
|
||||
[21] = {nil, nil, nil, nil, b.o, b.o, nil, nil, nil, nil},
|
||||
[22] = {nil, nil, nil, nil, b.o, b.o, nil, nil, nil, nil},
|
||||
[23] = {nil, nil, nil, nil, b.o, b.o, nil, nil, nil, nil},
|
||||
[24] = {nil, nil, nil, nil, b.Y, b.O, nil, nil, nil, nil},
|
||||
},
|
||||
[22] = {
|
||||
[15] = {nil, nil, b.b, nil, nil, nil, nil, b.b, nil, nil},
|
||||
[16] = {nil, b.b, b.O, b.b, nil, nil, b.b, b.Y, b.b, nil},
|
||||
[17] = {nil, nil, b.b, nil, nil, nil, nil, b.b, nil, nil},
|
||||
[20] = {nil, nil, nil, nil, b.R, b.M, nil, nil, nil, nil},
|
||||
[23] = {nil, nil, nil, b.b, b.C, b.G, b.b, nil, nil, nil},
|
||||
[24] = {nil, nil, nil, b.b, b.b, b.B, b.b, nil, nil, nil},
|
||||
},
|
||||
[23] = {
|
||||
[13] = {nil, nil, nil, nil, nil, nil, nil, nil, b.c, b.m},
|
||||
[14] = {nil, nil, nil, nil, nil, nil, nil, nil, b.y, b.g},
|
||||
[15] = {b.G, b.B, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
[16] = {b.r, b.O, nil, nil, nil, nil, nil, nil, nil, nil},
|
||||
[23] = {nil, nil, nil, nil, b.C, b.M, nil, nil, nil, nil},
|
||||
[24] = {nil, nil, nil, nil, b.R, b.Y, nil, nil, nil, nil},
|
||||
},
|
||||
[24] = {
|
||||
[20] = {b.g, b.g, b.g, b.g, b.G, nil, nil, nil, nil, nil},
|
||||
[21] = {nil, nil, nil, nil, nil, b.O, b.y, b.y, b.y, b.Y},
|
||||
[23] = {b.M, b.r, b.r, b.r, b.R, nil, nil, nil, nil, nil},
|
||||
[24] = {nil, nil, nil, nil, nil, b.M, b.r, b.r, b.r, b.R},
|
||||
},
|
||||
[25] = {
|
||||
[18] = {nil, nil, nil, nil, nil, b.B, nil, nil, nil, nil},
|
||||
[19] = {nil, nil, nil, b.G, nil, nil, nil, b.C, nil, nil},
|
||||
[20] = {nil, nil, nil, nil, nil, b.Y, nil, nil, nil, nil},
|
||||
[21] = {nil, nil, nil, b.M, nil, nil, nil, b.O, nil, nil},
|
||||
[22] = {nil, nil, nil, nil, nil, b.R, nil, nil, nil, nil},
|
||||
},
|
||||
[26] = {
|
||||
[13] = {nil, nil, nil, nil, b.r, b.r, nil, nil, nil, nil},
|
||||
[14] = {nil, nil, nil, nil, b.o, b.o, nil, nil, nil, nil},
|
||||
[15] = {nil, nil, nil, nil, b.o, b.o, nil, nil, nil, nil},
|
||||
[16] = {nil, nil, nil, nil, b.o, b.o, nil, nil, nil, nil},
|
||||
[17] = {nil, nil, nil, b.O, b.o, b.o, b.Y, nil, nil, nil},
|
||||
[18] = {nil, nil, b.o, b.c, b.c, b.c, b.c, b.o, nil, nil},
|
||||
[19] = {nil, nil, b.o, b.c, b.c, b.c, b.c, b.o, nil, nil},
|
||||
[20] = {nil, nil, b.o, nil, nil, b.G, nil, b.o, nil, nil},
|
||||
[21] = {nil, nil, b.o, nil, b.M, b.R, nil, b.o, nil, nil},
|
||||
[22] = {nil, nil, b.o, b.b, b.b, b.b, b.B, b.o, nil, nil},
|
||||
[23] = {nil, nil, b.o, b.C, b.b, b.b, b.b, b.o, nil, nil},
|
||||
[24] = {nil, nil, b.o, b.o, b.o, b.o, b.o, b.o, nil, nil},
|
||||
},
|
||||
[27] = {
|
||||
[15] = {nil, b.C, b.o, b.g, b.g, b.g, b.g, b.g, b.B, nil},
|
||||
[16] = {b.g, nil, b.y, b.o, b.g, b.g, b.g, b.g, nil, b.y},
|
||||
[17] = {b.g, b.g, nil, b.y, b.o, b.g, b.g, nil, b.y, b.o},
|
||||
[18] = {b.g, b.g, b.g, nil, b.y, b.o, nil, b.y, b.o, b.g},
|
||||
[19] = {b.g, b.g, b.g, b.o, nil, b.G, b.y, b.o, b.g, b.g},
|
||||
[20] = {b.g, b.g, b.o, b.o, b.Y, nil, b.o, b.g, b.g, b.g},
|
||||
[21] = {b.g, b.o, b.y, nil, b.o, b.O, nil, b.g, b.g, b.g},
|
||||
[22] = {b.o, b.y, nil, b.g, b.g, b.o, b.y, nil, b.g, b.g},
|
||||
[23] = {b.y, nil, b.g, b.g, b.g, b.g, b.o, b.y, nil, b.g},
|
||||
[24] = {nil, b.M, b.g, b.g, b.g, b.g, b.g, b.o, b.R, nil},
|
||||
},
|
||||
}
|
||||
|
||||
local STAGE_TRANSITION_TIME = 300
|
||||
|
||||
function SakuraGame:new()
|
||||
self.super:new()
|
||||
|
||||
self.randomizer = SakuraRandomizer()
|
||||
|
||||
self.current_map = 1
|
||||
self.time_limit = 10800
|
||||
self.cleared_frames = STAGE_TRANSITION_TIME
|
||||
self.stage_frames = 0
|
||||
self.time_extend = 0
|
||||
self.maps_cleared = 0
|
||||
self.map_20_time = 0
|
||||
self.stage_pieces = 0
|
||||
self.grid:applyMap(maps[self.current_map])
|
||||
|
||||
self.lock_drop = true
|
||||
self.lock_hard_drop = true
|
||||
self.enable_hold = true
|
||||
self.next_queue_length = 3
|
||||
end
|
||||
|
||||
function SakuraGame:checkRequirements()
|
||||
if self.maps_cleared >= 14 + 2 * (self.current_map - 20) and
|
||||
self.map_20_time <= frameTime(8,00) - frameTime(0,30) * (self.current_map - 20)
|
||||
then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function SakuraGame:getGravity()
|
||||
if self.level < 8 then return 4/256
|
||||
elseif self.level < 19 then return 5/256
|
||||
elseif self.level < 35 then return 6/256
|
||||
elseif self.level < 40 then return 8/256
|
||||
elseif self.level < 50 then return 10/256
|
||||
elseif self.level < 60 then return 12/256
|
||||
elseif self.level < 70 then return 16/256
|
||||
elseif self.level < 80 then return 32/256
|
||||
elseif self.level < 90 then return 48/256
|
||||
elseif self.level < 100 then return 64/256
|
||||
elseif self.level < 108 then return 4/256
|
||||
elseif self.level < 119 then return 5/256
|
||||
elseif self.level < 125 then return 6/256
|
||||
elseif self.level < 131 then return 8/256
|
||||
elseif self.level < 139 then return 12/256
|
||||
elseif self.level < 149 then return 32/256
|
||||
elseif self.level < 156 then return 48/256
|
||||
elseif self.level < 164 then return 80/256
|
||||
elseif self.level < 174 then return 112/256
|
||||
elseif self.level < 180 then return 128/256
|
||||
elseif self.level < 200 then return 144/256
|
||||
elseif self.level < 212 then return 16/256
|
||||
elseif self.level < 221 then return 48/256
|
||||
elseif self.level < 232 then return 80/256
|
||||
elseif self.level < 244 then return 112/256
|
||||
elseif self.level < 256 then return 144/256
|
||||
elseif self.level < 267 then return 176/256
|
||||
elseif self.level < 277 then return 192/256
|
||||
elseif self.level < 287 then return 208/256
|
||||
elseif self.level < 295 then return 224/256
|
||||
elseif self.level < 300 then return 240/256
|
||||
else return 20 end
|
||||
end
|
||||
|
||||
function SakuraGame:onLineClear(cleared_row_count)
|
||||
self.level = self.level + cleared_row_count
|
||||
for i = 13, 24 do
|
||||
for j = 1, 10 do
|
||||
local block = self.grid.grid[i][j]
|
||||
if block and block.skin == "gem" and block.colour == "X" then
|
||||
self.time_limit = self.time_limit + 60
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SakuraGame:onPieceEnter()
|
||||
if self.level % 100 ~= 99 and not self.clear and self.stage_frames ~= 0 then
|
||||
self.level = self.level + 1
|
||||
end
|
||||
if effects[self.current_map] == "mirror" and
|
||||
self.stage_pieces % 3 == 0 and self.stage_pieces ~= 0
|
||||
then
|
||||
self.grid:mirror()
|
||||
end
|
||||
self.stage_pieces = self.stage_pieces + 1
|
||||
end
|
||||
|
||||
function SakuraGame:advanceOneFrame(inputs, ruleset)
|
||||
if self.ready_frames == 0 then
|
||||
if self.lcd > 0 then
|
||||
if self.stage_frames <= frameTime(0,10) then self.time_extend = 600
|
||||
elseif self.stage_frames <= frameTime(0,30) then self.time_extend = 300
|
||||
else self.time_extend = 0 end
|
||||
end
|
||||
|
||||
if not self.grid:hasGemBlocks() or
|
||||
(self.stage_frames >= 3600 and self.current_map <= 20) then
|
||||
self.lcd = 0
|
||||
self.are = 0
|
||||
if self.stage_frames >= 3600 then self.time_extend = 0 end
|
||||
self.piece = nil
|
||||
|
||||
-- transition to next map
|
||||
if self.cleared_frames > 0 then
|
||||
self.cleared_frames = self.cleared_frames - 1
|
||||
if self.time_extend > 0 then
|
||||
self.time_limit = self.time_limit + 3
|
||||
self.time_extend = self.time_extend - 3
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
self.hold_queue = nil
|
||||
if self.current_map > 20 or (self.stage_frames < 3600 and self.current_map <= 20) then self.maps_cleared = self.maps_cleared + 1 end
|
||||
self.stage_frames = -1
|
||||
self.level = 0
|
||||
self.grid:clear()
|
||||
if (self.current_map == 20) then self.map_20_time = self.frames end
|
||||
if self.current_map >= 20 and self:checkRequirements() then
|
||||
self.clear = true
|
||||
self.completed = true
|
||||
return false
|
||||
else
|
||||
self.current_map = self.current_map + 1
|
||||
self.big_mode = effects[self.current_map] == "big"
|
||||
self.ready_frames = 100
|
||||
self.stage_pieces = 0
|
||||
self.grid:applyMap(maps[self.current_map])
|
||||
end
|
||||
|
||||
-- this is necessary to fix timer
|
||||
self.frames = self.frames - 1
|
||||
self.time_limit = self.time_limit + 1
|
||||
end
|
||||
|
||||
self.frames = self.frames + 1
|
||||
self.stage_frames = self.stage_frames + 1
|
||||
self.time_limit = self.time_limit - 1
|
||||
if self.time_limit <= 0 then self.game_over = true end
|
||||
|
||||
if self.piece ~= nil and self.frames % 30 == 0 and
|
||||
effects[self.current_map] == "roll"
|
||||
then
|
||||
ruleset:attemptRotate(
|
||||
{[config.gamesettings.world_reverse == 3 or
|
||||
(ruleset.world and config.gamesettings.world_reverse == 2)
|
||||
and "rotate_left" or "rotate_right"] = true},
|
||||
self.piece, self.grid, false
|
||||
)
|
||||
end
|
||||
else
|
||||
self.cleared_frames = STAGE_TRANSITION_TIME
|
||||
if not self.prev_inputs.hold and inputs.hold then
|
||||
self.hold_queue = table.remove(self.next_queue, 1)
|
||||
table.insert(self.next_queue, self:getNextPiece(ruleset))
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function colourXRay(game, block, x, y, age)
|
||||
local r, g, b, a = .5,.5,.5
|
||||
if ((game.stage_frames/2 - x) % 30 < 1)
|
||||
or game.stage_frames == 0
|
||||
or game.cleared_frames ~= STAGE_TRANSITION_TIME
|
||||
or game.stage_pieces % 2 == 0
|
||||
then
|
||||
a = 1
|
||||
else
|
||||
a = 1 - age / 4
|
||||
end
|
||||
return r, g, b, a, a
|
||||
end
|
||||
|
||||
local function colourColor(game, block, x, y, age)
|
||||
local r, g, b, a = .5,.5,.5
|
||||
if game.stage_frames == 0 or game.cleared_frames ~= STAGE_TRANSITION_TIME then
|
||||
a = 1
|
||||
else
|
||||
a = (game.stage_frames/30 + (y + math.abs(x-5.5))/5) % 1
|
||||
end
|
||||
return r, g, b, a, 0
|
||||
end
|
||||
|
||||
function SakuraGame:drawGrid()
|
||||
if effects[self.current_map] == "xray" then
|
||||
self.grid:drawCustom(colourXRay, self)
|
||||
elseif effects[self.current_map] == "color" then
|
||||
self.grid:drawCustom(colourColor, self)
|
||||
else
|
||||
self.grid:draw()
|
||||
-- if self.piece ~= nil and self.level < 100 then
|
||||
self:drawGhostPiece(ruleset)
|
||||
-- end
|
||||
end
|
||||
end
|
||||
|
||||
function SakuraGame:drawScoringInfo()
|
||||
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("STAGE", 240, 120, 80, "left")
|
||||
love.graphics.printf("TIME LIMIT", 240, 180, 80, "left")
|
||||
love.graphics.printf("LEVEL", 240, 320, 40, "left")
|
||||
if self.current_map <= 20 then
|
||||
love.graphics.printf("STAGE LIMIT", 240, 240, 100, "left")
|
||||
end
|
||||
if effects[self.current_map] then
|
||||
love.graphics.printf("EFFECT: " .. effects[self.current_map], 240, 300, 160, "left")
|
||||
end
|
||||
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
love.graphics.setColor(
|
||||
(self.time_limit % 4 < 2 and
|
||||
self.time_limit <= frameTime(0,10) and
|
||||
self.grid:hasGemBlocks() and
|
||||
self.time_limit ~= 0) and
|
||||
{ 1, 0.3, 0.3, 1 } or
|
||||
{ 1, 1, 1, 1 }
|
||||
)
|
||||
love.graphics.printf(formatTime(self.time_limit), 240, 200, 120, "left")
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
if self.current_map <= 20 then
|
||||
love.graphics.printf(formatTime(3600 - self.stage_frames), 240, 260, 120, "left")
|
||||
end
|
||||
love.graphics.printf(self.level, 240, 340, 40, "right")
|
||||
love.graphics.printf(math.floor((self.level + 100) / 100) * 100, 240, 370, 40, "right")
|
||||
|
||||
love.graphics.setFont(font_8x11)
|
||||
love.graphics.printf(formatTime(self.frames), 64, 420, 160, "center")
|
||||
love.graphics.printf(self.current_map, 290, 110, 80, "left")
|
||||
end
|
||||
|
||||
function SakuraGame:drawCustom()
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
|
||||
if self.ready_frames ~= 0 and not self.clear then
|
||||
love.graphics.setFont(font_3x5_4)
|
||||
love.graphics.printf("STAGE " .. self.current_map, 64, 170, 160, "center")
|
||||
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
if effects[self.current_map] then
|
||||
love.graphics.printf("EFFECT: " .. effects[self.current_map], 64, 270, 160, "center")
|
||||
end
|
||||
end
|
||||
|
||||
if self.cleared_frames > 0 and
|
||||
(not self.grid:hasGemBlocks() or
|
||||
(self.stage_frames >= 3600 and self.current_map <= 20)) then
|
||||
love.graphics.setFont(font_3x5_2)
|
||||
love.graphics.printf("TIME LIMIT", 64, 180, 160, "center")
|
||||
love.graphics.printf("TIME EXTEND", 64, 240, 160, "center")
|
||||
love.graphics.printf("STAGE TIME", 64, 300, 160, "center")
|
||||
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
love.graphics.printf("STAGE " .. self.current_map, 64, 100, 160, "center")
|
||||
love.graphics.setColor(
|
||||
self.cleared_frames % 4 < 2 and
|
||||
{ 1, 1, 0.3, 1 } or
|
||||
{ 1, 1, 1, 1 }
|
||||
)
|
||||
love.graphics.printf(formatTime(self.time_limit), 64, 200, 160, "center")
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.printf(formatTime(self.time_extend), 64, 260, 160, "center")
|
||||
love.graphics.printf(formatTime(self.stage_frames), 64, 320, 160, "center")
|
||||
|
||||
love.graphics.setFont(font_3x5_4)
|
||||
love.graphics.printf((self.stage_frames >= 3600 and self.current_map <= 20) and "" or "CLEAR!", 64, 130, 160, "center")
|
||||
end
|
||||
|
||||
if self.clear then
|
||||
love.graphics.setFont(font_3x5_3)
|
||||
love.graphics.printf("EXCELLENT!", 64, 180, 160, "center")
|
||||
|
||||
love.graphics.setFont(font_3x5_2)
|
||||
if self.current_map ~= 27 then
|
||||
love.graphics.printf("...but let's go\nbetter next time", 64, 220, 160, "center")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SakuraGame:getBackground()
|
||||
return (self.current_map - 1) % 20
|
||||
end
|
||||
|
||||
function SakuraGame:getHighscoreData()
|
||||
return {
|
||||
maps = self.maps_cleared,
|
||||
current_map = self.current_map,
|
||||
frames = self.frames,
|
||||
}
|
||||
end
|
||||
|
||||
return SakuraGame
|
||||
16
tetris/randomizers/fixed_sequence.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
local Randomizer = require 'tetris.randomizers.randomizer'
|
||||
|
||||
local Sequence = Randomizer:extend()
|
||||
|
||||
function Sequence:initialize()
|
||||
self.sequence = "IJLOT"
|
||||
self.counter = 0
|
||||
end
|
||||
|
||||
function Sequence:generatePiece()
|
||||
local piece = string.sub(self.sequence, self.counter + 1, self.counter + 1)
|
||||
self.counter = (self.counter + 1) % string.len(self.sequence)
|
||||
return piece
|
||||
end
|
||||
|
||||
return Sequence
|
||||
10
tetris/randomizers/sakura.lua
Normal file
@@ -0,0 +1,10 @@
|
||||
local Sequence = require 'tetris.randomizers.fixed_sequence'
|
||||
|
||||
local Sakura = Sequence:extend()
|
||||
|
||||
function Sakura:initialize()
|
||||
self.super:initialize()
|
||||
self.sequence = "LIJOTSZILJOTISJZLOIJSZTIOJZTLSOZTISOLTJSIZTOJLIZSTOIZLTJOSILTZSOITJLZSTJJISOLJITSLZOIZSJOITSZLJTSZLISTJLZOTIOZSJILTZSOITZJSOLTJSZIOJLZIOJTZIZLOSIZTJOILZSOJIOSZTJILOSSILZOTJIZTSOLZTSOIJTZSILTZOSIJZTOLJISOLJTZSOLTZJSOTILZJTOLZIJSOZTJLOZSTLOZITSOLZTJIOSLZJTO"
|
||||
end
|
||||
|
||||
return Sakura
|
||||
@@ -6,6 +6,8 @@ local SRS = Ruleset:extend()
|
||||
SRS.name = "ACE-SRS"
|
||||
SRS.hash = "ACE Standard"
|
||||
|
||||
SRS.MANIPULATIONS_MAX = 128
|
||||
|
||||
SRS.spawn_positions = {
|
||||
I = { x=5, y=2 },
|
||||
J = { x=4, y=3 },
|
||||
@@ -26,23 +28,11 @@ SRS.big_spawn_positions = {
|
||||
Z = { x=2, y=1 },
|
||||
}
|
||||
|
||||
function SRS:onPieceMove(piece, grid)
|
||||
piece.lock_delay = 0 -- move reset
|
||||
if piece:isDropBlocked(grid) then
|
||||
piece.manipulations = piece.manipulations + 1
|
||||
if piece.manipulations >= 128 then
|
||||
piece:dropToBottom(grid)
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SRS:onPieceRotate(piece, grid)
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
if piece:isDropBlocked(grid) then
|
||||
piece.manipulations = piece.manipulations + 1
|
||||
if piece.manipulations >= 128 then
|
||||
piece:dropToBottom(grid)
|
||||
if piece.manipulations >= self.MANIPULATIONS_MAX then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -115,8 +115,8 @@ function Ruleset:attemptRotate(new_inputs, piece, grid, initial)
|
||||
local new_piece = piece:withRelativeRotation(rot_dir)
|
||||
|
||||
if (grid:canPlacePiece(new_piece)) then
|
||||
self:onPieceRotate(piece, grid)
|
||||
piece:setRelativeRotation(rot_dir)
|
||||
self:onPieceRotate(piece, grid)
|
||||
else
|
||||
if not(initial and self.enable_IRS_wallkicks == false) then
|
||||
self:attemptWallkicks(piece, new_piece, rot_dir, grid)
|
||||
|
||||
@@ -8,6 +8,8 @@ SRS.hash = "Standard"
|
||||
|
||||
SRS.enable_IRS_wallkicks = true
|
||||
|
||||
SRS.MANIPULATIONS_MAX = 15
|
||||
|
||||
function SRS:check_new_low(piece)
|
||||
for _, block in pairs(piece:getBlockOffsets()) do
|
||||
local y = piece.position.y + block.y
|
||||
@@ -75,7 +77,7 @@ end
|
||||
|
||||
function SRS:onPieceDrop(piece, grid)
|
||||
self:check_new_low(piece)
|
||||
if piece.manipulations >= 15 and piece:isDropBlocked(grid) then
|
||||
if piece.manipulations >= self.MANIPULATIONS_MAX and piece:isDropBlocked(grid) then
|
||||
piece.locked = true
|
||||
else
|
||||
piece.lock_delay = 0 -- step reset
|
||||
@@ -86,8 +88,7 @@ function SRS:onPieceMove(piece, grid)
|
||||
piece.lock_delay = 0 -- move reset
|
||||
if piece:isDropBlocked(grid) then
|
||||
piece.manipulations = piece.manipulations + 1
|
||||
if piece.manipulations >= 15 then
|
||||
piece:dropToBottom(grid)
|
||||
if piece.manipulations >= self.MANIPULATIONS_MAX then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
@@ -97,9 +98,9 @@ function SRS:onPieceRotate(piece, grid)
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
self:check_new_low(piece)
|
||||
piece.manipulations = piece.manipulations + 1
|
||||
if piece.manipulations >= self.MANIPULATIONS_MAX then
|
||||
piece:moveInGrid({ x = 0, y = 1 }, 1, grid)
|
||||
if piece:isDropBlocked(grid) then
|
||||
if piece.manipulations >= 15 then
|
||||
piece:dropToBottom(grid)
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,6 +18,9 @@ SRS.colourscheme = {
|
||||
SRS.softdrop_lock = false
|
||||
SRS.harddrop_lock = true
|
||||
|
||||
SRS.MANIPULATIONS_MAX = 10
|
||||
SRS.ROTATIONS_MAX = 8
|
||||
|
||||
SRS.spawn_positions = {
|
||||
I = { x=5, y=4 },
|
||||
J = { x=4, y=5 },
|
||||
@@ -162,15 +165,18 @@ function SRS:onPieceCreate(piece, grid)
|
||||
end
|
||||
|
||||
function SRS:onPieceDrop(piece, grid)
|
||||
if (piece.manipulations >= self.MANIPULATIONS_MAX or piece.rotations >= self.ROTATIONS_MAX) and piece:isDropBlocked(grid) then
|
||||
piece.locked = true
|
||||
else
|
||||
piece.lock_delay = 0 -- step reset
|
||||
end
|
||||
end
|
||||
|
||||
function SRS:onPieceMove(piece, grid)
|
||||
piece.lock_delay = 0 -- move reset
|
||||
if piece:isDropBlocked(grid) then
|
||||
piece.manipulations = piece.manipulations + 1
|
||||
if piece.manipulations >= 10 then
|
||||
piece:dropToBottom(grid)
|
||||
if piece.manipulations >= self.MANIPULATIONS_MAX then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
@@ -180,8 +186,7 @@ function SRS:onPieceRotate(piece, grid)
|
||||
piece.lock_delay = 0 -- rotate reset
|
||||
if piece:isDropBlocked(grid) then
|
||||
piece.rotations = piece.rotations + 1
|
||||
if piece.rotations >= 8 then
|
||||
piece:dropToBottom(grid)
|
||||
if piece.rotations >= self.ROTATIONS_MAX then
|
||||
piece.locked = true
|
||||
end
|
||||
end
|
||||
|
||||