456 lines
17 KiB
Lua
456 lines
17 KiB
Lua
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
|