diff --git a/load/graphics.lua b/load/graphics.lua index c12cac7..b527e0d 100644 --- a/load/graphics.lua +++ b/load/graphics.lua @@ -49,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"), } } diff --git a/res/img/gem1.png b/res/img/gem1.png new file mode 100644 index 0000000..04ea2a9 Binary files /dev/null and b/res/img/gem1.png differ diff --git a/res/img/gem2.png b/res/img/gem2.png new file mode 100644 index 0000000..9c0f357 Binary files /dev/null and b/res/img/gem2.png differ diff --git a/res/img/gem3.png b/res/img/gem3.png new file mode 100644 index 0000000..4578705 Binary files /dev/null and b/res/img/gem3.png differ diff --git a/res/img/gem4.png b/res/img/gem4.png new file mode 100644 index 0000000..88b0187 Binary files /dev/null and b/res/img/gem4.png differ diff --git a/res/img/gem5.png b/res/img/gem5.png new file mode 100644 index 0000000..701e49d Binary files /dev/null and b/res/img/gem5.png differ diff --git a/res/img/gem6.png b/res/img/gem6.png new file mode 100644 index 0000000..7f16200 Binary files /dev/null and b/res/img/gem6.png differ diff --git a/res/img/gem7.png b/res/img/gem7.png new file mode 100644 index 0000000..225a22a Binary files /dev/null and b/res/img/gem7.png differ diff --git a/res/img/gem9.png b/res/img/gem9.png new file mode 100644 index 0000000..7277ccb Binary files /dev/null and b/res/img/gem9.png differ diff --git a/tetris/components/grid.lua b/tetris/components/grid.lua index 38d3044..f6eab5a 100644 --- a/tetris/components/grid.lua +++ b/tetris/components/grid.lua @@ -273,6 +273,26 @@ 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: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 diff --git a/tetris/modes/sakura.lua b/tetris/modes/sakura.lua new file mode 100644 index 0000000..51a928d --- /dev/null +++ b/tetris/modes/sakura.lua @@ -0,0 +1,350 @@ +require 'funcs' + +local GameMode = require 'tetris.modes.gamemode' +local Piece = require 'tetris.components.piece' + +local History6RollsRandomizer = require 'tetris.randomizers.history_6rolls_35bag' + +local SakuraGame = GameMode:extend() + +SakuraGame.name = "Sakura Beta" +SakuraGame.hash = "SakuraBeta" +SakuraGame.tagline = "Test mode for gem blocks" + +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 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}, + }, +} + +function SakuraGame:new() + self.super:new() + + self.randomizer = History6RollsRandomizer() + + self.current_map = 1 + self.time_limit = 10800 + self.cleared_frames = 300 + self.stage_frames = 0 + self.time_extend = 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:getGravity() + return 1/64 +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() then + -- 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 + self.stage_frames = -1 + self.current_map = self.current_map + 1 + self.grid:clear() + if self.current_map >= 21 then + self.clear = true + self.completed = true + return false + else + self.ready_frames = 100 + 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 + else + self.cleared_frames = 300 + 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 + +function SakuraGame:drawGrid() + self.grid:draw() + self:drawGhostPiece() +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("STAGE TIME", 240, 240, 80, "left") + + 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) + love.graphics.printf(formatTime(self.stage_frames), 240, 260, 120, "left") + + 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") + end + + if self.cleared_frames > 0 and not self.grid:hasGemBlocks() 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("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) + love.graphics.printf("...but let's go\nbetter next time", 64, 220, 160, "center") + end +end + +function SakuraGame:getBackground() + return (self.current_map - 1) % 20 +end + +function SakuraGame:getHighscoreData() + return { + map = self.current_map, + frames = self.frames, + } +end + +return SakuraGame \ No newline at end of file