Added Big Mode as a piece type. (#20)

Survival A3 and Phantom Mania 2 are now in their fully complete glory! :D

Implements #13.
This commit is contained in:
Joe Zeng 2019-06-16 22:16:09 -04:00 committed by GitHub
parent 5131061e42
commit 5c5ffc6887
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 158 additions and 32 deletions

View File

@ -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

View File

@ -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"),

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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} },

View File

@ -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} },

View File

@ -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} },

View File

@ -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)

View File

@ -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} },