local LevelData = require "leveldata" local Game = {} Game.__index = Game MAX_POWER = 999999999999 local player_spr = love.graphics.newImage("res/sprite/player.png") local ent_spr = { enemy = love.graphics.newImage("res/sprite/enemy.png"), enemy_neg = love.graphics.newImage("res/sprite/enemy_neg.png"), elixir = love.graphics.newImage("res/sprite/elixir.png"), gate = love.graphics.newImage("res/sprite/gate.png"), vorpal = love.graphics.newImage("res/sprite/vorpal_sword.png"), pickaxe = love.graphics.newImage("res/sprite/pickaxe.png"), stairs_up = love.graphics.newImage("res/sprite/stairs_up.png"), stairs_down = love.graphics.newImage("res/sprite/stairs_down.png"), crown = love.graphics.newImage("res/sprite/crown.png"), } local held_spr = { vorpal = love.graphics.newImage("res/sprite/vorpal_held.png"), pickaxe = love.graphics.newImage("res/sprite/pickaxe_held.png"), } function Game.new() local self = { player_power = 5, player_x = 1, player_y = 8, player_item = nil, floor = 1, level_data = LevelData:new(), undo_history = {}, } setmetatable(self, Game) return self end function Game:keypressed(key,scancode,isrepeat) if self.player_item ~= "crown" then if scancode=="up" or scancode=="k" or scancode=="w" or scancode=="kp8" then self:step(0,-1) elseif scancode=="down" or scancode=="j" or scancode=="s" or scancode=="kp2" then self:step(0,1) elseif scancode=="left" or scancode=="h" or scancode=="a" or scancode=="kp4" then self:step(-1,0) elseif scancode=="right" or scancode=="l" or scancode=="d" or scancode=="kp6" then self:step(1,0) end end if scancode=="z" then self:undo() end end function Game:step(ox,oy) tx = self.player_x + ox ty = self.player_y + oy --check if border if tx < 1 or ty < 1 or tx > 15 or ty > 15 then return end -- check if reinforced wall if self.level_data[self.floor].walls[ty][tx]==2 then return end -- check if normal wall if self.level_data[self.floor].walls[ty][tx]==1 then if self.player_item == "pickaxe" then --push to undo memory self.undo_history[#self.undo_history+1] = { "dig", { floor = self.floor, px = self.player_x, py = self.player_y, wx = tx, wy = ty, } } --remove wall self.level_data[self.floor].walls[ty][tx]=0 --remove item self.player_item = nil end return end --check if entity local move_legal = true local entities = self.level_data[self.floor].entities for i=1,#entities do if entities[i].x == tx and entities[i].y == ty then if entities[i].type == nil then --removed entity break elseif entities[i].type == "enemy" then if self.player_item == "vorpal" then self.undo_history[#self.undo_history+1] = { "vorpal", { floor = self.floor, px = self.player_x, py = self.player_y, ent_type = entities[i].type, ent = entities[i], } } --remove entity entities[i].type = nil --remove item self.player_item = nil break elseif entities[i].value >= self.player_power then return else --push to undo memory self.undo_history[#self.undo_history+1] = { "fight", { floor = self.floor, px = self.player_x, py = self.player_y, power = self.player_power, ent_type = entities[i].type, ent = entities[i], } } --remove entity entities[i].type = nil --absorb power self.player_power = self.player_power + entities[i].value break end elseif entities[i].type == "enemy_neg" then if self.player_item == "vorpal" then --push to undo memory self.undo_history[#self.undo_history+1] = { "vorpal", { floor = self.floor, px = self.player_x, py = self.player_y, ent_type = entities[i].type, ent = entities[i], } } --remove entity entities[i].type = nil --remove item self.player_item = nil break elseif entities[i].value >= self.player_power then return else --push to undo memory self.undo_history[#self.undo_history+1] = { "fight", { floor = self.floor, px = self.player_x, py = self.player_y, power = self.player_power, ent_type = entities[i].type, ent = entities[i], } } --remove entity entities[i].type = nil --absorb power self.player_power = self.player_power - entities[i].value break end elseif entities[i].type == "elixir" then --push to undo memory self.undo_history[#self.undo_history+1] = { "fight", { floor = self.floor, px = self.player_x, py = self.player_y, power = self.player_power, ent_type = entities[i].type, ent = entities[i], } } --remove entity entities[i].type = nil --double power self.player_power = self.player_power * 2 break elseif entities[i].type == "gate" then --push to undo memory self.undo_history[#self.undo_history+1] = { "fight", { floor = self.floor, px = self.player_x, py = self.player_y, power = self.player_power, ent_type = entities[i].type, ent = entities[i], } } --remove entity entities[i].type = nil --divide power by two self.player_power = math.ceil(self.player_power / 2) break elseif entities[i].type == "pickaxe" then --can't pick up if you have an item if self.player_item then return end --push to undo memory self.undo_history[#self.undo_history+1] = { "item_get", { floor = self.floor, px = self.player_x, py = self.player_y, ent_type = entities[i].type, ent = entities[i], } } --remove entity entities[i].type = nil --equip item self.player_item = "pickaxe" break elseif entities[i].type == "vorpal" then --can't pick up if you have an item if self.player_item then return end --push to undo memory self.undo_history[#self.undo_history+1] = { "item_get", { floor = self.floor, px = self.player_x, py = self.player_y, ent_type = entities[i].type, ent = entities[i], } } --remove entity entities[i].type = nil --equip item self.player_item = "vorpal" break elseif entities[i].type == "crown" then --can't pick up if you have an item if self.player_item then return end --push to undo memory self.undo_history[#self.undo_history+1] = { "item_get", { floor = self.floor, px = self.player_x, py = self.player_y, ent_type = entities[i].type, ent = entities[i], } } --remove entity entities[i].type = nil --equip item self.player_item = "crown" break elseif entities[i].type == "stairs_up" then self.floor = self.floor + 1 break elseif entities[i].type == "stairs_down" then self.floor = self.floor - 1 break else return end end end --ensure the power cap is upheld to self.player_power = math.min(self.player_power,MAX_POWER) --move if possible if move_legal then self.player_x = tx self.player_y = ty end end function Game:undo() if #self.undo_history == 0 then return end undo_item = self.undo_history[#self.undo_history] if undo_item[1] == "vorpal" then self.floor = undo_item[2].floor self.player_x = undo_item[2].px self.player_y = undo_item[2].py undo_item[2].ent.type = undo_item[2].ent_type self.player_item = "vorpal" elseif undo_item[1] == "dig" then self.floor = undo_item[2].floor self.player_x = undo_item[2].px self.player_y = undo_item[2].py self.level_data[self.floor].walls[undo_item[2].wy][undo_item[2].wx]=1 self.player_item = "pickaxe" elseif undo_item[1] == "item_get" then self.floor = undo_item[2].floor self.player_x = undo_item[2].px self.player_y = undo_item[2].py undo_item[2].ent.type = undo_item[2].ent_type self.player_item = nil elseif undo_item[1] == "fight" then --works for elixirs and gates too self.floor = undo_item[2].floor self.player_x = undo_item[2].px self.player_y = undo_item[2].py self.player_power = undo_item[2].power undo_item[2].ent.type = undo_item[2].ent_type else assert(false) end --remove the item from stack self.undo_history[#self.undo_history] = nil end function Game:update(dt) end function Game:draw() love.graphics.setLineWidth(2) love.graphics.push() --win screen if self.player_item == "crown" then love.graphics.printf("YOU WIN!", 0,32,248,"center") love.graphics.printf("YOU WIN!", 0,32,248,"center") love.graphics.draw(ent_spr.crown, 116,52,0) love.graphics.printf("You succeeded at scaling up the Tower of Scale, and displayed the mastery over the power scaling!", 8,80,232,"center") love.graphics.printf("SCORE:"..player_power_to_string(self.player_power),0,128,248,"center") if self.player_power >= 10000000000 then love.graphics.printf("GRADE: S",0,144,248,"center") elseif self.player_power >= 1000000000 then love.graphics.printf("GRADE: A",0,144,248,"center") elseif self.player_power >= 100000000 then love.graphics.printf("GRADE: B",0,144,248,"center") elseif self.player_power >= 10000000 then love.graphics.printf("GRADE: C",0,144,248,"center") else love.graphics.printf("GRADE: D",0,144,248,"center") end love.graphics.printf("Want to do better?\nPress Z to undo!", 0,200,248,"center") love.graphics.pop() return end --floor and walls love.graphics.setColor(1,1,1,1) love.graphics.rectangle("fill",0,0,248,248) local walls = self.level_data[self.floor].walls for x=1,15 do for y=1,15 do if walls[y][x]==2 then love.graphics.setColor(1,1,1,1) elseif walls[y][x]==1 then love.graphics.setColor(0.85,0.85,0.85,1) else love.graphics.setColor(0.05,0.05,0.05,1) end love.graphics.rectangle("fill",x*16-12,y*16-12,16,16) if walls[y][x]==2 then love.graphics.setColor(0,0,0,1) love.graphics.rectangle("fill",x*16-10,y*16-10,2,2) love.graphics.rectangle("fill",x*16-5,y*16-10,2,2) love.graphics.rectangle("fill",x*16-10,y*16-5,2,2) love.graphics.rectangle("fill",x*16-5,y*16,2,2) love.graphics.rectangle("fill",x*16,y*16-5,2,2) love.graphics.rectangle("fill",x*16-10,y*16,2,2) love.graphics.rectangle("fill",x*16,y*16-10,2,2) love.graphics.rectangle("fill",x*16,y*16,2,2) end end end --entity sprites love.graphics.setFont(FONT_DIGITS) local entities = self.level_data[self.floor].entities for i=1,#entities do if entities[i].type then --sprite love.graphics.setColor(1,1,1,1) love.graphics.draw(ent_spr[entities[i].type],entities[i].x*16-12,entities[i].y*16-12) end end --entity values love.graphics.setFont(FONT_DIGITS) local entities = self.level_data[self.floor].entities for i=1,#entities do if entities[i].type then if entities[i].value_str then love.graphics.setColor(0,0,0,1) love.graphics.printf(entities[i].value_str,entities[i].x*16-10,entities[i].y*16-1,16,"right") love.graphics.printf(entities[i].value_str,entities[i].x*16-12,entities[i].y*16-1,16,"right") love.graphics.printf(entities[i].value_str,entities[i].x*16-11,entities[i].y*16,16,"right") love.graphics.printf(entities[i].value_str,entities[i].x*16-11,entities[i].y*16-2,16,"right") love.graphics.printf(entities[i].value_str,entities[i].x*16-10,entities[i].y*16,16,"right") love.graphics.printf(entities[i].value_str,entities[i].x*16-10,entities[i].y*16-2,16,"right") love.graphics.printf(entities[i].value_str,entities[i].x*16-12,entities[i].y*16,16,"right") love.graphics.printf(entities[i].value_str,entities[i].x*16-12,entities[i].y*16-2,16,"right") love.graphics.setColor(1,1,1,1) love.graphics.printf(entities[i].value_str,entities[i].x*16-11,entities[i].y*16-1,16,"right") end end end --player love.graphics.setColor(1,1,1,1) love.graphics.draw(player_spr,self.player_x*16-12,self.player_y*16-12) --player info love.graphics.setColor(1,1,1,1) love.graphics.setFont(FONT_STANDARD) love.graphics.print("FLOOR "..(self.floor>9 and self.floor or " "..self.floor).." POWER:"..player_power_to_string(self.player_power),1,249) --tutorial textboxes local textboxes = self.level_data[self.floor].textboxes for i=1,#textboxes do love.graphics.setColor(0,0,0,1) love.graphics.rectangle("fill",textboxes[i].x,textboxes[i].y,textboxes[i].w,textboxes[i].h) love.graphics.setColor(1,1,1,1) love.graphics.rectangle("line",textboxes[i].x-1,textboxes[i].y-1,textboxes[i].w+2,textboxes[i].h+2) love.graphics.printf( textboxes[i].str, textboxes[i].x+1,textboxes[i].y+1,textboxes[i].w-2, "center" ) end --held item if self.player_item then love.graphics.draw(held_spr[self.player_item],72,250) end love.graphics.pop() love.graphics.setColor(1,1,1,1) end return Game