Compare commits

..

21 Commits

Author SHA1 Message Date
ae1231c47a Merge pull request #17 from nightmareci/master
Improved latency and performance
2021-05-27 09:34:46 -04:00
Ishaan Bhardwaj
366ac1d552 Update credits.lua 2021-05-23 17:37:38 -04:00
302353f716 Update README.md 2021-05-23 17:20:26 -04:00
nightmareci
7f550b629f Made start-of-line spacing all hard tabs 2021-05-23 11:57:04 -07:00
nightmareci
6b2252e6d9 Implemented custom love.run to get lower latency 2021-05-23 11:07:07 -07:00
Ishaan Bhardwaj
e1741440f2 Fixed an edge case with the last save commit 2021-05-22 21:42:14 -04:00
Ishaan Bhardwaj
c56f290921 Fixed a bug where the game would sometimes not save on macOS
Version bump to beta5.2
2021-05-22 21:19:33 -04:00
Ishaan Bhardwaj
86e975f929 Fixed up an edge case in immobile spin 2021-05-22 14:41:51 -04:00
Ishaan Bhardwaj
9f8e9a9778 Changed additive gravity behavior for main TGM modes 2021-05-21 15:34:50 -04:00
Ishaan Bhardwaj
62f9475fa9 Small cosmetic change to input config menus 2021-05-21 15:32:28 -04:00
Ishaan Bhardwaj
99d3732d00 Bump to v0.3-beta5.1, release tomorrow 2021-05-20 23:25:24 -04:00
Ishaan Bhardwaj
f5121b62e5 Added bigint comparison metamethods 2021-05-15 22:39:15 -04:00
Ishaan Bhardwaj
cbdbfa6633 Fixed a small cosmetic issue in Survival A1 2021-04-26 21:51:42 -04:00
Ishaan Bhardwaj
1b1abc9792 Fixed an issue with buffer lock inputs 2021-04-20 16:11:49 -04:00
Ishaan Bhardwaj
894e99e677 Cambridge has a logo now! 2021-04-16 22:14:59 -04:00
Ishaan Bhardwaj
d4b619da89 Fixed an edge case with last commit 2021-04-08 13:17:34 -04:00
Ishaan Bhardwaj
3766149cb7 Fixed a 0 ARR gravity bug 2021-04-08 11:55:36 -04:00
Ishaan Bhardwaj
449ca16bc4 Updated to be on rebrand 2021-04-01 14:11:38 -04:00
Ishaan Bhardwaj
71d76e8a6b Fixed Death torikan (why was this changed?) 2021-03-30 22:08:48 -04:00
Ishaan Bhardwaj
3bdc6e1b2d HOTFIX TO BETA5: Fixed another floorkick issue with ARS 2021-03-30 21:29:09 -04:00
Ishaan Bhardwaj
d9b6c85704 Fix up credits a bit, add new people 2021-03-28 10:03:27 -04:00
20 changed files with 177 additions and 129 deletions

View File

@@ -5,7 +5,7 @@ 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
@@ -32,13 +32,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 +66,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 +78,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
------- -------

View File

@@ -6,5 +6,6 @@ function love.conf(t)
t.window.title = "Cambridge" t.window.title = "Cambridge"
t.window.width = 640 t.window.width = 640
t.window.height = 480 t.window.height = 480
t.window.icon = "res/img/cambridge_icon.png"
t.window.vsync = false t.window.vsync = false
end end

View File

@@ -32,6 +32,15 @@ local mt = {
end, end,
__tostring = function() __tostring = function()
return bigint.unserialize(self, "s") return bigint.unserialize(self, "s")
end,
__eq = function(lhs, rhs)
return bigint.compare(lhs, rhs, "==")
end,
__lt = function(lhs, rhs)
return bigint.compare(lhs, rhs, "<")
end,
__le = function(lhs, rhs)
return bigint.compare(lhs, rhs, "<=")
end end
} }

View File

@@ -1,8 +1,17 @@
local binser = require 'libs.binser' local binser = require 'libs.binser'
function loadSave() function loadSave()
config = loadFromFile('config.sav') local info = love.filesystem.getInfo(love.filesystem.getSaveDirectory())
highscores = loadFromFile('highscores.sav') if not info or info.type ~= "directory" then
love.filesystem.remove(love.filesystem.getSaveDirectory())
love.filesystem.createDirectory(love.filesystem.getSaveDirectory())
end
config = loadFromFile(
love.filesystem.getSaveDirectory() .. '/config.sav'
)
highscores = loadFromFile(
love.filesystem.getSaveDirectory() .. '/highscores.sav'
)
end end
function loadFromFile(filename) function loadFromFile(filename)
@@ -31,7 +40,7 @@ function initConfig()
end end
if not config.input then if not config.input then
scene = KeyConfigScene() scene = InputConfigScene()
else else
if config.current_mode then current_mode = config.current_mode end if config.current_mode then current_mode = config.current_mode end
if config.current_ruleset then current_ruleset = config.current_ruleset end if config.current_ruleset then current_ruleset = config.current_ruleset end
@@ -40,9 +49,13 @@ function initConfig()
end end
function saveConfig() function saveConfig()
binser.writeFile('config.sav', config) binser.writeFile(
love.filesystem.getSaveDirectory() .. '/config.sav', config
)
end end
function saveHighscores() function saveHighscores()
binser.writeFile('highscores.sav', highscores) binser.writeFile(
love.filesystem.getSaveDirectory() .. '/highscores.sav', highscores
)
end end

View File

@@ -1 +1 @@
version = "v0.3-beta5" version = "v0.3-beta5.2"

View File

@@ -55,44 +55,6 @@ 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()
@@ -308,3 +270,56 @@ 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

BIN
res/img/cambridge_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -30,30 +30,35 @@ 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 - self.frames / 2)
love.graphics.print("THANK YOU\nFOR PLAYING!", 320, math.max(1750 - self.frames / 2, 240)) love.graphics.print("THANK YOU\nFOR PLAYING!", 320, math.max(1770 - self.frames / 2, 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 - self.frames / 2)
love.graphics.print("Project Heads", 320, 640 - 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("Other Game Developers", 320, 730 - self.frames / 2)
love.graphics.print("Special Thanks", 320, 900 - self.frames / 2) love.graphics.print("Special Thanks", 320, 950 - self.frames / 2)
love.graphics.print("- SashLilac / SpinTriple", 320, math.max(2000 - self.frames / 2, 320)) love.graphics.print("- Milla", 320, math.max(1850 - self.frames / 2, 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 - self.frames / 2)
love.graphics.print("Mizu\nHailey", 320, 680 - 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(
"Axel Fox - Multimino\nMine - Tetra Online\nDr Ocelot - Tetra Legends\n" ..
"Felicity / nightmareci - Shiromino\n2Tie - TGMsim\nPhoenix Flare - Master of Blocks\n" ..
"RayRay26 - Spirit Drop\nosk - TETR.IO\nMarkGamed7794 - Picoris 2",
320, 770 - self.frames / 2
)
love.graphics.print( love.graphics.print(
"RocketLanterns\nCylinderKnot\nHammrTime\nKirby703\nMattMayuga\nMyPasswordIsWeak\n" .. "RocketLanterns\nCylinderKnot\nHammrTime\nKirby703\nMattMayuga\nMyPasswordIsWeak\n" ..
"Nikki Karissa\noffwo\nsinefuse\nTetro48\nTimmSkiller\nuser74003\nAgentBasey\n" .. "Nikki Karissa\noffwo\nsinefuse\nTetro48\nTimmSkiller\nuser74003\nAgentBasey\n" ..
"CheeZed_Fish\neightsixfivezero\nEricICX\ngizmo4487\nM1ssing0\nMarkGamed7794\n" .. "CheeZed_Fish\neightsixfivezero\nEricICX\ngizmo4487\nM1ssing0\n" ..
"pokemonfan1937\nSimon\nstratus\nZaptorZap\nArchina\nOliver\ncolour_thief\n" .. "pokemonfan1937\nSimon\nstratus\nZaptorZap\nArchina\nOliver\ncolour_thief\n" ..
"Caithness\nkdex\nzid\nsaphie\nSuper302\nAurora\nswitchpalacecorner\nKitaru\n" .. "Caithness\nkdex\nzid\nsaphie\nSuper302\nAurora\nswitchpalacecorner\nKitaru\n" ..
"JBroms\nMany more I definitely missed!\n" .. "JBroms\nMany more I definitely missed!\n" ..
"The Absolute PLUS Discord\nTetra Legends Discord\nTetra Online Discord\n" .. "The Absolute PLUS Discord\nTetra Legends Discord\nTetra Online Discord\n" ..
"Multimino Discord\nHard Drop Discord\nCambridge Discord (R.I.P.)\n" .. "Multimino Discord\nHard Drop Discord\nCambridge Discord\n" ..
"And to you, the player!", "And to you, the player!",
320, 940 - self.frames / 2 320, 990 - self.frames / 2
) )
end end

View File

@@ -29,7 +29,7 @@ function ConfigScene:render()
love.graphics.print("INPUT CONFIG", 80, 40) love.graphics.print("INPUT CONFIG", 80, 40)
love.graphics.setFont(font_3x5_2) love.graphics.setFont(font_3x5_2)
love.graphics.print("Which controls do you want to change?", 80, 90) love.graphics.print("Which controls do you want to configure?", 80, 90)
love.graphics.setColor(1, 1, 1, 0.5) love.graphics.setColor(1, 1, 1, 0.5)
love.graphics.rectangle("fill", 75, 118 + 50 * self.menu_state, 200, 33) love.graphics.rectangle("fill", 75, 118 + 50 * self.menu_state, 200, 33)
@@ -56,7 +56,9 @@ function ConfigScene:onInputPress(e)
elseif e.input == "down" or e.scancode == "down" then elseif e.input == "down" or e.scancode == "down" then
self:changeOption(1) self:changeOption(1)
playSE("cursor") playSE("cursor")
elseif e.input == "menu_back" or e.scancode == "backspace" or e.scancode == "delete" then elseif config.input and (
e.input == "menu_back" or e.scancode == "backspace" or e.scancode == "delete"
) then
scene = SettingsScene() scene = SettingsScene()
end end
end end

View File

@@ -61,7 +61,7 @@ function KeyConfigScene:render()
if self.input_state > table.getn(configurable_inputs) then if self.input_state > table.getn(configurable_inputs) then
love.graphics.print("press enter to confirm, delete/backspace to retry" .. (config.input and ", escape to cancel" or "")) love.graphics.print("press enter to confirm, delete/backspace to retry" .. (config.input and ", escape to cancel" or ""))
else else
love.graphics.print("press key input for " .. configurable_inputs[self.input_state] .. ", tab to skip" .. (config.input and ", escape to cancel" or ""), 0, 0) love.graphics.print("press key input for " .. configurable_inputs[self.input_state] .. ", tab to skip, escape to cancel", 0, 0)
love.graphics.print("function keys (F1, F2, etc.), escape, and tab can't be changed", 0, 20) love.graphics.print("function keys (F1, F2, etc.), escape, and tab can't be changed", 0, 20)
end end
end end
@@ -69,8 +69,7 @@ end
function KeyConfigScene:onInputPress(e) function KeyConfigScene:onInputPress(e)
if e.type == "key" then if e.type == "key" then
-- function keys, escape, and tab are reserved and can't be remapped -- function keys, escape, and tab are reserved and can't be remapped
if e.scancode == "escape" and config.input then if e.scancode == "escape" then
-- cancel only if there was an input config already
scene = InputConfigScene() scene = InputConfigScene()
elseif self.input_state > table.getn(configurable_inputs) then elseif self.input_state > table.getn(configurable_inputs) then
if e.scancode == "return" then if e.scancode == "return" then

View File

@@ -62,7 +62,7 @@ function StickConfigScene:render()
if self.input_state > table.getn(configurable_inputs) then if self.input_state > table.getn(configurable_inputs) then
love.graphics.print("press enter to confirm, delete/backspace to retry" .. (config.input and ", escape to cancel" or "")) love.graphics.print("press enter to confirm, delete/backspace to retry" .. (config.input and ", escape to cancel" or ""))
else else
love.graphics.print("press joystick input for " .. configurable_inputs[self.input_state] .. ", tab to skip" .. (config.input and ", escape to cancel" or ""), 0, 0) love.graphics.print("press joystick input for " .. configurable_inputs[self.input_state] .. ", tab to skip, escape to cancel", 0, 0)
end end
self.axis_timer = self.axis_timer + 1 self.axis_timer = self.axis_timer + 1
@@ -82,9 +82,11 @@ function StickConfigScene:onInputPress(e)
elseif self.input_state > table.getn(configurable_inputs) then elseif self.input_state > table.getn(configurable_inputs) then
if e.scancode == "return" then if e.scancode == "return" then
-- save new input, then load next scene -- save new input, then load next scene
local had_config = config.input ~= nil
if not config.input then config.input = {} end
config.input.joysticks = self.new_input config.input.joysticks = self.new_input
saveConfig() saveConfig()
scene = InputConfigScene() scene = had_config and InputConfigScene() or TitleScene()
elseif e.scancode == "delete" or e.scancode == "backspace" then elseif e.scancode == "delete" or e.scancode == "backspace" then
-- retry -- retry
self.input_state = 1 self.input_state = 1

View File

@@ -206,14 +206,14 @@ function GameMode:update(inputs, ruleset)
self.piece.last_rotated = false self.piece.last_rotated = false
self:onPieceMove(self.piece, self.grid, piece_dx) self:onPieceMove(self.piece, self.grid, piece_dx)
end end
if (piece_drot ~= 0) then
self.piece.last_rotated = true
self:onPieceRotate(self.piece, self.grid, piece_drot)
end
if (piece_dy ~= 0) then if (piece_dy ~= 0) then
self.piece.last_rotated = false self.piece.last_rotated = false
self:onPieceDrop(self.piece, self.grid, piece_dy) self:onPieceDrop(self.piece, self.grid, piece_dy)
end end
if (piece_drot ~= 0) then
self.piece.last_rotated = true
self:onPieceRotate(self.piece, self.grid, piece_drot)
end
if inputs["up"] == true and if inputs["up"] == true and
self.piece:isDropBlocked(self.grid) and self.piece:isDropBlocked(self.grid) and
@@ -242,7 +242,8 @@ function GameMode:update(inputs, ruleset)
if self.piece.locked == true then if self.piece.locked == true then
-- spin detection, immobile only for now -- spin detection, immobile only for now
if self.immobile_spin_bonus and ( if self.immobile_spin_bonus and
self.piece.last_rotated and (
self.piece:isDropBlocked(self.grid) and self.piece:isDropBlocked(self.grid) and
self.piece:isMoveBlocked(self.grid, { x=-1, y=0 }) and self.piece:isMoveBlocked(self.grid, { x=-1, y=0 }) and
self.piece:isMoveBlocked(self.grid, { x=1, y=0 }) and self.piece:isMoveBlocked(self.grid, { x=1, y=0 }) and
@@ -529,16 +530,13 @@ function GameMode:initializeNextPiece(inputs, ruleset, piece_data, generate_next
self.lock_drop, self.lock_hard_drop, self.big_mode, self.lock_drop, self.lock_hard_drop, self.big_mode,
( (
self.frames == 0 or (ruleset.are and self:getARE() ~= 0) self.frames == 0 or (ruleset.are and self:getARE() ~= 0)
) and self.irs or false, ) and self.irs or false
self.buffer_hard_drop, self.buffer_soft_drop,
self.lock_on_hard_drop, self.lock_on_soft_drop
) )
if self.piece:isDropBlocked(self.grid) and
self.grid:canPlacePiece(self.piece) then
playSE("bottom")
end
if self.buffer_hard_drop then if self.buffer_hard_drop then
self.buffer_hard_drop = false 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 = ( local above_field = (
(config.gamesettings.spawn_positions == 1 and (config.gamesettings.spawn_positions == 1 and
ruleset.spawn_above_field) or ruleset.spawn_above_field) or
@@ -552,10 +550,22 @@ function GameMode:initializeNextPiece(inputs, ruleset, piece_data, generate_next
piece_data.shape, piece_data.orientation piece_data.shape, piece_data.orientation
) or 0) ) or 0)
) )
self.buffer_hard_drop = false
end end
if self.buffer_soft_drop then 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 self.buffer_soft_drop = false
end end
if self.piece:isDropBlocked(self.grid) and
self.grid:canPlacePiece(self.piece) then
playSE("bottom")
end
if self.lock_drop or ( if self.lock_drop or (
not ruleset.are or self:getARE() == 0 not ruleset.are or self:getARE() == 0
) then ) then

View File

@@ -33,6 +33,7 @@ function MarathonA1Game:new()
self.randomizer = History4RollsRandomizer() self.randomizer = History4RollsRandomizer()
self.additive_gravity = false
self.lock_drop = false self.lock_drop = false
self.enable_hard_drop = false self.enable_hard_drop = false
self.enable_hold = false self.enable_hold = false

View File

@@ -34,6 +34,7 @@ function MarathonA2Game:new()
"GM" "GM"
} }
self.additive_gravity = false
self.lock_drop = false self.lock_drop = false
self.lock_hard_drop = false self.lock_hard_drop = false
self.enable_hold = false self.enable_hold = false

View File

@@ -39,6 +39,7 @@ self.SGnames = {
"GM" "GM"
} }
self.additive_gravity = false
self.lock_drop = true self.lock_drop = true
self.lock_hard_drop = true self.lock_hard_drop = true
self.enable_hold = true self.enable_hold = true

View File

@@ -111,9 +111,8 @@ function SurvivalA1Game:onLineClear(cleared_row_count)
local new_level = math.min(self.level + cleared_row_count, 999) local new_level = math.min(self.level + cleared_row_count, 999)
if new_level == 999 then if new_level == 999 then
self.clear = true self.clear = true
else
self.level = new_level
end end
self.level = new_level
end end
end end

View File

@@ -30,11 +30,6 @@ function SurvivalA2Game:new()
self.lock_hard_drop = true self.lock_hard_drop = true
end end
function SurvivalA2Game:initialize(ruleset)
SurvivalA2Game.super.initialize(self, ruleset)
self.world = ruleset.world
end
function SurvivalA2Game:getARE() function SurvivalA2Game:getARE()
if self.level < 100 then return 18 if self.level < 100 then return 18
elseif self.level < 300 then return 14 elseif self.level < 300 then return 14
@@ -74,8 +69,7 @@ function SurvivalA2Game:getGravity()
end end
function SurvivalA2Game:hitTorikan(old_level, new_level) function SurvivalA2Game:hitTorikan(old_level, new_level)
local torikan_time = self.world and frameTime(3,55) or frameTime(3,25) if old_level < 500 and new_level >= 500 and self.frames > frameTime(3,25) then
if old_level < 500 and new_level >= 500 and self.frames > torikan_time then
self.level = 500 self.level = 500
return true return true
end end

View File

@@ -37,41 +37,41 @@ function ARS:attemptWallkicks(piece, new_piece, rot_dir, grid)
(piece:isMoveBlocked(grid, {x=-1, y=0}) or piece:isMoveBlocked(grid, {x=1, y=0})) then (piece:isMoveBlocked(grid, {x=-1, y=0}) or piece:isMoveBlocked(grid, {x=1, y=0})) then
-- kick right, right2, left -- kick right, right2, left
if grid:canPlacePiece(new_piece:withOffset({x=1, y=0})) then if grid:canPlacePiece(new_piece:withOffset({x=1, y=0})) then
self:onPieceRotate(piece, grid)
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0}) piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
self:onPieceRotate(piece, grid)
elseif grid:canPlacePiece(new_piece:withOffset({x=2, y=0})) then elseif grid:canPlacePiece(new_piece:withOffset({x=2, y=0})) then
self:onPieceRotate(piece, grid)
piece:setRelativeRotation(rot_dir):setOffset({x=2, y=0}) piece:setRelativeRotation(rot_dir):setOffset({x=2, y=0})
elseif grid:canPlacePiece(new_piece:withOffset({x=-1, y=0})) then
self:onPieceRotate(piece, grid) self:onPieceRotate(piece, grid)
elseif grid:canPlacePiece(new_piece:withOffset({x=-1, y=0})) then
piece:setRelativeRotation(rot_dir):setOffset({x=-1, y=0}) piece:setRelativeRotation(rot_dir):setOffset({x=-1, y=0})
self:onPieceRotate(piece, grid)
end end
elseif piece:isDropBlocked(grid) and (new_piece.rotation == 1 or new_piece.rotation == 3) then elseif piece:isDropBlocked(grid) and (new_piece.rotation == 1 or new_piece.rotation == 3) then
-- kick up, up2 -- kick up, up2
if grid:canPlacePiece(new_piece:withOffset({x=0, y=-1})) then if grid:canPlacePiece(new_piece:withOffset({x=0, y=-1})) then
self:onPieceRotate(piece, grid)
piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-1}) piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-1})
elseif grid:canPlacePiece(new_piece:withOffset({x=0, y=-2})) then
self:onPieceRotate(piece, grid) self:onPieceRotate(piece, grid)
elseif grid:canPlacePiece(new_piece:withOffset({x=0, y=-2})) then
piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-2}) piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-2})
self:onPieceRotate(piece, grid)
end end
end end
else else
-- kick right, kick left -- kick right, kick left
if grid:canPlacePiece(new_piece:withOffset({x=1, y=0})) then if grid:canPlacePiece(new_piece:withOffset({x=1, y=0})) then
self:onPieceRotate(piece, grid)
piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0}) piece:setRelativeRotation(rot_dir):setOffset({x=1, y=0})
elseif grid:canPlacePiece(new_piece:withOffset({x=-1, y=0})) then
self:onPieceRotate(piece, grid) self:onPieceRotate(piece, grid)
elseif grid:canPlacePiece(new_piece:withOffset({x=-1, y=0})) then
piece:setRelativeRotation(rot_dir):setOffset({x=-1, y=0}) piece:setRelativeRotation(rot_dir):setOffset({x=-1, y=0})
self:onPieceRotate(piece, grid)
elseif piece.shape == "T" elseif piece.shape == "T"
and new_piece.rotation == 0 and new_piece.rotation == 0
and piece:isDropBlocked(grid) and piece:isDropBlocked(grid)
and grid:canPlacePiece(new_piece:withOffset({x=0, y=-1})) and grid:canPlacePiece(new_piece:withOffset({x=0, y=-1}))
then then
-- T floorkick -- T floorkick
self:onPieceRotate(piece, grid)
piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-1}) piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-1})
self:onPieceRotate(piece, grid)
end end
end end

View File

@@ -52,11 +52,11 @@ function ARS:attemptWallkicks(piece, new_piece, rot_dir, grid)
if grid:canPlacePiece(new_piece:withOffset({x=0, y=-1})) then if grid:canPlacePiece(new_piece:withOffset({x=0, y=-1})) then
piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-1}) piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-1})
piece.floorkick = 1 piece.floorkick = 1
self:onPieceRotate(piece, grid) self:onPieceRotate(piece, grid, true)
elseif grid:canPlacePiece(new_piece:withOffset({x=0, y=-2})) then elseif grid:canPlacePiece(new_piece:withOffset({x=0, y=-2})) then
piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-2}) piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-2})
piece.floorkick = 1 piece.floorkick = 1
self:onPieceRotate(piece, grid) self:onPieceRotate(piece, grid, true)
end end
end end
else else
@@ -76,7 +76,7 @@ function ARS:attemptWallkicks(piece, new_piece, rot_dir, grid)
-- T floorkick -- T floorkick
piece.floorkick = piece.floorkick + 1 piece.floorkick = piece.floorkick + 1
piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-1}) piece:setRelativeRotation(rot_dir):setOffset({x=0, y=-1})
self:onPieceRotate(piece, grid) self:onPieceRotate(piece, grid, true)
end end
end end
@@ -93,10 +93,10 @@ function ARS:onPieceDrop(piece, grid)
end end
end end
function ARS:onPieceRotate(piece, grid) function ARS:onPieceRotate(piece, grid, floorkick)
if piece.floorkick >= 2 and piece:isDropBlocked(grid) then if piece.floorkick >= 2 and piece:isDropBlocked(grid) then
piece.locked = true piece.locked = true
elseif piece.floorkick >= 1 then elseif piece.floorkick >= 1 and not floorkick then
piece.floorkick = piece.floorkick + 1 piece.floorkick = piece.floorkick + 1
end end
end end

View File

@@ -123,6 +123,7 @@ function Ruleset:movePiece(piece, grid, move, instant)
local was_drop_blocked = piece:isDropBlocked(grid) local was_drop_blocked = piece:isDropBlocked(grid)
local offset = ({x=0, y=0}) local offset = ({x=0, y=0})
local moves = 0 local moves = 0
local y = piece.position.y
if move == "left" then if move == "left" then
offset.x = -1 offset.x = -1
moves = 1 moves = 1
@@ -151,6 +152,9 @@ function Ruleset:movePiece(piece, grid, move, instant)
if not was_drop_blocked and piece:isDropBlocked(grid) then if not was_drop_blocked and piece:isDropBlocked(grid) then
playSE("bottom") playSE("bottom")
end end
if instant and piece.position.y ~= y then
self:onPieceDrop(piece, grid)
end
end end
function Ruleset:dropPiece( function Ruleset:dropPiece(
@@ -206,9 +210,7 @@ end
function Ruleset:initializePiece( function Ruleset:initializePiece(
inputs, data, grid, gravity, prev_inputs, inputs, data, grid, gravity, prev_inputs,
move, lock_delay, drop_speed, move, lock_delay, drop_speed,
drop_locked, hard_drop_locked, big, irs, drop_locked, hard_drop_locked, big, irs
buffer_hard_drop, buffer_soft_drop,
lock_on_hard_drop, lock_on_soft_drop
) )
local spawn_positions local spawn_positions
if big then if big then
@@ -261,13 +263,6 @@ function Ruleset:initializePiece(
end end
end end
self:dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked) self:dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked)
if (buffer_hard_drop and config.gamesettings.buffer_lock == 1) then
piece:dropToBottom(grid)
if lock_on_hard_drop then piece.locked = true end
end
if (buffer_soft_drop and lock_on_soft_drop and piece:isDropBlocked(grid) and config.gamesettings.buffer_lock == 1) then
piece.locked = true
end
return piece return piece
end end
@@ -280,6 +275,7 @@ 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]