From 5c5ffc68876785277ddae72f789d73bb784c4996 Mon Sep 17 00:00:00 2001 From: Joe Zeng Date: Sun, 16 Jun 2019 22:16:09 -0400 Subject: [PATCH] Added Big Mode as a piece type. (#20) Survival A3 and Phantom Mania 2 are now in their fully complete glory! :D Implements #13. --- conf.lua | 2 + load/graphics.lua | 6 ++ tetris/components/grid.lua | 74 +++++++++++++++---- tetris/components/piece.lua | 20 ++++- tetris/modes/gamemode.lua | 3 +- tetris/modes/phantom_mania2.lua | 17 ++++- tetris/modes/survival_a3.lua | 13 ++-- tetris/rulesets/arika.lua | 10 +++ tetris/rulesets/arika_ti.lua | 10 +++ tetris/rulesets/cambridge.lua | 10 +++ tetris/rulesets/ruleset.lua | 15 +++- tetris/rulesets/standard_exp.lua | 10 +++ .../{ => unrefactored_rulesets}/bonkers.lua | 0 .../{ => unrefactored_rulesets}/tengen.lua | 0 14 files changed, 158 insertions(+), 32 deletions(-) rename tetris/rulesets/{ => unrefactored_rulesets}/bonkers.lua (100%) rename tetris/rulesets/{ => unrefactored_rulesets}/tengen.lua (100%) diff --git a/conf.lua b/conf.lua index 8fdb686..8fbc3ff 100644 --- a/conf.lua +++ b/conf.lua @@ -1,6 +1,8 @@ function love.conf(t) t.identity = "cambridge" + t.console = true + t.window.title = "Cambridge" t.window.width = 640 t.window.height = 480 diff --git a/load/graphics.lua b/load/graphics.lua index a51f38d..2c54cc1 100644 --- a/load/graphics.lua +++ b/load/graphics.lua @@ -49,6 +49,12 @@ blocks = { } } +for name, blockset in pairs(blocks) do + for shape, image in pairs(blockset) do + image:setFilter("nearest") + end +end + misc_graphics = { frame = love.graphics.newImage("res/img/frame.png"), ready = love.graphics.newImage("res/img/ready.png"), diff --git a/tetris/components/grid.lua b/tetris/components/grid.lua index ea5c183..4601035 100644 --- a/tetris/components/grid.lua +++ b/tetris/components/grid.lua @@ -38,6 +38,10 @@ function Grid:isRowFull(row) end function Grid:canPlacePiece(piece) + if piece.big then + return self:canPlaceBigPiece(piece) + end + local offsets = piece:getBlockOffsets() for index, offset in pairs(offsets) do local x = piece.position.x + offset.x @@ -49,7 +53,29 @@ function Grid:canPlacePiece(piece) return true end +function Grid:canPlaceBigPiece(piece) + local offsets = piece:getBlockOffsets() + for index, offset in pairs(offsets) do + local x = piece.position.x + offset.x + local y = piece.position.y + offset.y + if x >= 5 or x < 0 or y >= 12 or y < 0 or + self.grid[y * 2 + 1][x * 2 + 1] ~= empty or + self.grid[y * 2 + 1][x * 2 + 2] ~= empty or + self.grid[y * 2 + 2][x * 2 + 1] ~= empty or + self.grid[y * 2 + 2][x * 2 + 2] ~= empty + then + return false + end + end + return true +end + function Grid:canPlacePieceInVisibleGrid(piece) + if piece.big then + return self:canPlaceBigPiece(piece) + -- forget canPlaceBigPieceInVisibleGrid for now + end + local offsets = piece:getBlockOffsets() for index, offset in pairs(offsets) do local x = piece.position.x + offset.x @@ -116,6 +142,10 @@ function Grid:copyBottomRow() end function Grid:applyPiece(piece) + if piece.big then + self:applyBigPiece(piece) + return + end offsets = piece:getBlockOffsets() for index, offset in pairs(offsets) do x = piece.position.x + offset.x @@ -127,6 +157,22 @@ function Grid:applyPiece(piece) end end +function Grid:applyBigPiece(piece) + offsets = piece:getBlockOffsets() + for index, offset in pairs(offsets) do + x = piece.position.x + offset.x + y = piece.position.y + offset.y + for a = 1, 2 do + for b = 1, 2 do + self.grid[y*2+a][x*2+b] = { + skin = piece.skin, + colour = piece.shape + } + end + end + end +end + function Grid:update() for y = 1, 24 do for x = 1, 10 do @@ -148,19 +194,21 @@ function Grid:draw() love.graphics.setColor(0.5, 0.5, 0.5, 1) love.graphics.draw(blocks[self.grid[y][x].skin][self.grid[y][x].colour], 48+x*16, y*16) end - love.graphics.setColor(0.8, 0.8, 0.8, 1) - 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) + if self.grid[y][x].skin ~= "bone" then + love.graphics.setColor(0.8, 0.8, 0.8, 1) + 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 diff --git a/tetris/components/piece.lua b/tetris/components/piece.lua index 3ed1524..8de8e6c 100644 --- a/tetris/components/piece.lua +++ b/tetris/components/piece.lua @@ -2,7 +2,7 @@ local Object = require 'libs.classic' local Piece = Object:extend() -function Piece:new(shape, rotation, position, block_offsets, gravity, lock_delay, skin) +function Piece:new(shape, rotation, position, block_offsets, gravity, lock_delay, skin, big) self.shape = shape self.rotation = rotation self.position = position @@ -12,6 +12,7 @@ function Piece:new(shape, rotation, position, block_offsets, gravity, lock_delay self.skin = skin self.ghost = false self.locked = false + self.big = big end -- Functions that return a new piece to test in rotation systems. @@ -20,7 +21,7 @@ function Piece:withOffset(offset) return Piece( self.shape, self.rotation, {x = self.position.x + offset.x, y = self.position.y + offset.y}, - self.block_offsets, self.gravity, self.lock_delay, self.skin + self.block_offsets, self.gravity, self.lock_delay, self.skin, self.big ) end @@ -30,7 +31,7 @@ function Piece:withRelativeRotation(rot) while new_rot >= 4 do new_rot = new_rot - 4 end return Piece( self.shape, new_rot, self.position, - self.block_offsets, self.gravity, self.lock_delay, self.skin + self.block_offsets, self.gravity, self.lock_delay, self.skin, self.big ) end @@ -145,7 +146,18 @@ function Piece:draw(opacity, brightness, grid, partial_das) for index, offset in pairs(offsets) do local x = self.position.x + offset.x local y = self.position.y + offset.y - love.graphics.draw(blocks[self.skin][self.shape], 64+x*16+partial_das, 16+y*16+gravity_offset) + if self.big then + love.graphics.draw( + blocks[self.skin][self.shape], + 64+x*32+partial_das*2, 16+y*32+gravity_offset*2, + 0, 2, 2 + ) + else + love.graphics.draw( + blocks[self.skin][self.shape], + 64+x*16+partial_das, 16+y*16+gravity_offset + ) + end end return false end diff --git a/tetris/modes/gamemode.lua b/tetris/modes/gamemode.lua index 89a7f04..a468990 100644 --- a/tetris/modes/gamemode.lua +++ b/tetris/modes/gamemode.lua @@ -38,6 +38,7 @@ function GameMode:new() self.next_queue_length = 1 self.draw_section_times = false self.draw_secondary_section_times = false + self.big_mode = false -- variables related to configurable parameters self.drop_locked = false self.hard_drop_locked = false @@ -298,7 +299,7 @@ function GameMode:initializeNextPiece(inputs, ruleset, piece_data, generate_next inputs, piece_data, self.grid, gravity, self.prev_inputs, self.move, self:getLockDelay(), self:getDropSpeed(), - self.lock_drop, self.lock_hard_drop + self.lock_drop, self.lock_hard_drop, self.big_mode ) if self.lock_drop then self.drop_locked = true diff --git a/tetris/modes/phantom_mania2.lua b/tetris/modes/phantom_mania2.lua index 392f4c5..2626250 100644 --- a/tetris/modes/phantom_mania2.lua +++ b/tetris/modes/phantom_mania2.lua @@ -25,6 +25,8 @@ function PhantomMania2Game:new() self.combo = 1 self.hold_age = 0 self.queue_age = 0 + self.roll_points = 0 + self.randomizer = History6RollsRandomizer() self.lock_drop = true @@ -135,7 +137,7 @@ function PhantomMania2Game:onPieceEnter() end local cleared_row_levels = {1, 2, 4, 6} -local cleared_row_points = {0.02, 0.05, 0.15, 0.6} +local cleared_row_points = {2, 6, 15, 40} function PhantomMania2Game:onLineClear(cleared_row_count) if not self.clear then @@ -144,6 +146,7 @@ function PhantomMania2Game:onLineClear(cleared_row_count) if new_level >= 1300 or self:hitTorikan(self.level, new_level) then if new_level >= 1300 then self.level = 1300 + self.big_mode = true end self.clear = true self.grid:clear() @@ -152,6 +155,12 @@ function PhantomMania2Game:onLineClear(cleared_row_count) self.level = math.min(new_level, 1300) end self:advanceBottomRow(-cleared_row_count) + else + self.roll_points = self.roll_points + cleared_row_points[cleared_row_count / 2] + if self.roll_points >= 100 then + self.roll_points = self.roll_points - 100 + self.grade = self.grade + 1 + end end end @@ -225,7 +234,7 @@ PhantomMania2Game.garbageOpacityFunction = function(age) end function PhantomMania2Game:drawGrid() - if not (self.game_over or self.clear) then + if not (self.game_over or (self.clear and self.level < 1300)) then self.grid:drawInvisible(self.rollOpacityFunction, self.garbageOpacityFunction) else self.grid:draw() @@ -243,7 +252,7 @@ local function getLetterGrade(grade) end function PhantomMania2Game:setNextOpacity(i) - if self.level > 1000 then + if self.level > 1000 and self.level < 1300 then local hidden_next_pieces = math.floor(self.level / 100) - 10 if i < hidden_next_pieces then love.graphics.setColor(1, 1, 1, 0) @@ -258,7 +267,7 @@ function PhantomMania2Game:setNextOpacity(i) end function PhantomMania2Game:setHoldOpacity() - if self.level > 1000 then + if self.level > 1000 and self.level < 1300 then love.graphics.setColor(1, 1, 1, 1 - math.min(1, self.hold_age / 15)) else love.graphics.setColor(1, 1, 1, 1) diff --git a/tetris/modes/survival_a3.lua b/tetris/modes/survival_a3.lua index a755b44..4a980a0 100644 --- a/tetris/modes/survival_a3.lua +++ b/tetris/modes/survival_a3.lua @@ -44,13 +44,14 @@ function SurvivalA3Game:getLineARE() end function SurvivalA3Game:getDasLimit() - if self.level < 200 then return 9 + if self.level < 100 then return 9 elseif self.level < 500 then return 7 else return 5 end end function SurvivalA3Game:getLineClearDelay() - return self:getLineARE() - 2 + if self.level < 1300 then return self:getLineARE() - 2 + else return 6 end end function SurvivalA3Game:getLockDelay() @@ -60,7 +61,8 @@ function SurvivalA3Game:getLockDelay() elseif self.level < 600 then return 13 elseif self.level < 1100 then return 12 elseif self.level < 1200 then return 10 - else return 8 end + elseif self.level < 1300 then return 8 + else return 15 end end function SurvivalA3Game:getGravity() @@ -133,6 +135,7 @@ function SurvivalA3Game:onLineClear(cleared_row_count) end self.clear = true self.grid:clear() + self.big_mode = true self.roll_frames = -150 else self.level = math.min(new_level, 1300) @@ -188,10 +191,8 @@ end local function getLetterGrade(grade) if grade == 0 then return "1" - elseif grade <= 9 then - return "S" .. tostring(grade) else - return "M" .. tostring(grade - 9) + return "S" .. tostring(grade) end end diff --git a/tetris/rulesets/arika.lua b/tetris/rulesets/arika.lua index e9f2f79..93c9264 100644 --- a/tetris/rulesets/arika.lua +++ b/tetris/rulesets/arika.lua @@ -16,6 +16,16 @@ ARS.spawn_positions = { Z = { x=4, y=5 }, } +ARS.big_spawn_positions = { + I = { x=2, y=2 }, + J = { x=2, y=3 }, + L = { x=2, y=3 }, + O = { x=2, y=3 }, + S = { x=2, y=3 }, + T = { x=2, y=3 }, + Z = { x=2, y=3 }, +} + ARS.block_offsets = { I={ { {x=0, y=0}, {x=-1, y=0}, {x=-2, y=0}, {x=1, y=0} }, diff --git a/tetris/rulesets/arika_ti.lua b/tetris/rulesets/arika_ti.lua index 663a608..e477595 100644 --- a/tetris/rulesets/arika_ti.lua +++ b/tetris/rulesets/arika_ti.lua @@ -16,6 +16,16 @@ ARS.spawn_positions = { Z = { x=4, y=5 }, } +ARS.big_spawn_positions = { + I = { x=2, y=2 }, + J = { x=2, y=3 }, + L = { x=2, y=3 }, + O = { x=2, y=3 }, + S = { x=2, y=3 }, + T = { x=2, y=3 }, + Z = { x=2, y=3 }, +} + ARS.block_offsets = { I={ { {x=0, y=0}, {x=-1, y=0}, {x=-2, y=0}, {x=1, y=0} }, diff --git a/tetris/rulesets/cambridge.lua b/tetris/rulesets/cambridge.lua index d03992e..148e5c1 100644 --- a/tetris/rulesets/cambridge.lua +++ b/tetris/rulesets/cambridge.lua @@ -16,6 +16,16 @@ CRS.spawn_positions = { Z = { x=4, y=4 }, } +CRS.big_spawn_positions = { + I = { x=2, y=2 }, + J = { x=2, y=3 }, + L = { x=2, y=3 }, + O = { x=2, y=3 }, + S = { x=2, y=2 }, + T = { x=2, y=3 }, + Z = { x=2, y=2 }, +} + CRS.block_offsets = { I={ { {x=0, y=0}, {x=-1, y=0}, {x=-2, y=0}, {x=1, y=0} }, diff --git a/tetris/rulesets/ruleset.lua b/tetris/rulesets/ruleset.lua index 3e20cc1..bc33106 100644 --- a/tetris/rulesets/ruleset.lua +++ b/tetris/rulesets/ruleset.lua @@ -102,12 +102,19 @@ function Ruleset:getDefaultOrientation() return 1 end function Ruleset:initializePiece( inputs, data, grid, gravity, prev_inputs, move, lock_delay, drop_speed, - drop_locked, hard_drop_locked + drop_locked, hard_drop_locked, big ) + local spawn_positions + if big then + spawn_positions = self.big_spawn_positions + else + spawn_positions = self.spawn_positions + end local piece = Piece(data.shape, data.orientation - 1, { - x = self.spawn_positions[data.shape].x, - y = self.spawn_positions[data.shape].y - }, self.block_offsets, 0, 0, data.skin) + x = spawn_positions[data.shape].x, + y = spawn_positions[data.shape].y + }, self.block_offsets, 0, 0, data.skin, big) + self:onPieceCreate(piece) self:rotatePiece(inputs, piece, grid, {}, true) self:dropPiece(inputs, piece, grid, gravity, drop_speed, drop_locked, hard_drop_locked) diff --git a/tetris/rulesets/standard_exp.lua b/tetris/rulesets/standard_exp.lua index 1b8d2df..655faef 100644 --- a/tetris/rulesets/standard_exp.lua +++ b/tetris/rulesets/standard_exp.lua @@ -18,6 +18,16 @@ SRS.spawn_positions = { Z = { x=4, y=5 }, } +SRS.big_spawn_positions = { + I = { x=2, y=2 }, + J = { x=2, y=3 }, + L = { x=2, y=3 }, + O = { x=2, y=3 }, + S = { x=2, y=3 }, + T = { x=2, y=3 }, + Z = { x=2, y=3 }, +} + SRS.block_offsets = { I={ { {x=0, y=0}, {x=-1, y=0}, {x=-2, y=0}, {x=1, y=0} }, diff --git a/tetris/rulesets/bonkers.lua b/tetris/rulesets/unrefactored_rulesets/bonkers.lua similarity index 100% rename from tetris/rulesets/bonkers.lua rename to tetris/rulesets/unrefactored_rulesets/bonkers.lua diff --git a/tetris/rulesets/tengen.lua b/tetris/rulesets/unrefactored_rulesets/tengen.lua similarity index 100% rename from tetris/rulesets/tengen.lua rename to tetris/rulesets/unrefactored_rulesets/tengen.lua