restructured folder
This commit is contained in:
@@ -1,29 +0,0 @@
|
||||
-- data
|
||||
require "data/animations"
|
||||
require "data/shaders"
|
||||
require "data/tiledata"
|
||||
require "data/music"
|
||||
require "data/sfx"
|
||||
require "data/scripts/locale"
|
||||
-- support functions
|
||||
require "data/scripts/math"
|
||||
require "data/scripts/hex"
|
||||
require "data/scripts/in_out"
|
||||
-- classes
|
||||
require "data/scripts/audio"
|
||||
require "data/scripts/entity"
|
||||
require "data/scripts/animation"
|
||||
require "data/scripts/collision"
|
||||
require "data/scripts/level"
|
||||
require "data/scripts/camera"
|
||||
require "data/scripts/lights"
|
||||
require "data/scripts/objects"
|
||||
-- UI functions
|
||||
require "data/scripts/debug"
|
||||
require "data/scripts/keybind"
|
||||
require "data/scripts/menu"
|
||||
require "data/scripts/ui"
|
||||
-- game loop
|
||||
require "data/scripts/game"
|
||||
require "data/scripts/gameworld"
|
||||
require "data/scripts/editor"
|
||||
@@ -1,78 +0,0 @@
|
||||
Animation = {}
|
||||
|
||||
function Animation:New(anim_data)
|
||||
local o = {}
|
||||
|
||||
o.path = anim_data.path
|
||||
o.frames = anim_data.frames
|
||||
o.speed = anim_data.speed
|
||||
o.imgs = anim_data.imgs
|
||||
o.subframe = 0
|
||||
o.frame = 1
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
function Animation:ChangeTo(anim_data)
|
||||
if anim_data.path == self.path
|
||||
then
|
||||
return self
|
||||
else
|
||||
return Animation:New(anim_data)
|
||||
end
|
||||
end
|
||||
|
||||
-- to manually handle what frame
|
||||
function Animation:DrawFrame(frame, x, y, rotate, sx, sy)
|
||||
if frame > self.frames then
|
||||
frame = self.frames
|
||||
end
|
||||
local x = x or 0
|
||||
local y = y or 0
|
||||
local sx = sx or 1
|
||||
local sy = sy or 1
|
||||
love.graphics.draw(
|
||||
self.imgs[frame],
|
||||
math.floor(x - Camera.pos.x),
|
||||
math.floor(y - Camera.pos.y),
|
||||
rotate,
|
||||
sx,
|
||||
sy
|
||||
)
|
||||
end
|
||||
|
||||
-- to linearly animate
|
||||
function Animation:Animate()
|
||||
if self.speed ~= 0 then
|
||||
-- try to animate
|
||||
self.subframe = self.subframe + current_dt
|
||||
|
||||
if self.subframe > self.speed then
|
||||
self.frame = self.frame + 1
|
||||
self.subframe = self.subframe - self.speed
|
||||
end
|
||||
|
||||
-- cycle
|
||||
if self.frame >= self.frames+1 then
|
||||
self.frame = self.frame - self.frames
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- to draw the current frame
|
||||
function Animation:Draw(x, y, rotate, sx, sy)
|
||||
local x = x or 0
|
||||
local y = y or 0
|
||||
local sx = sx or 1
|
||||
local sy = sy or 1
|
||||
love.graphics.draw(
|
||||
self.imgs[self.frame],
|
||||
math.floor(x),
|
||||
math.floor(y),
|
||||
rotate,
|
||||
sx,
|
||||
sy
|
||||
)
|
||||
end
|
||||
@@ -1,47 +0,0 @@
|
||||
-- snippet from
|
||||
-- https://love2d.org/wiki/Minimalist_Sound_Manager
|
||||
-- <3
|
||||
do
|
||||
-- will hold the currently playing sources
|
||||
local sources = {}
|
||||
|
||||
-- check for sources that finished playing and remove them
|
||||
-- add to love.update
|
||||
function love.audio.update()
|
||||
local remove = {}
|
||||
for _,s in pairs(sources) do
|
||||
if not s:isPlaying() then
|
||||
remove[#remove + 1] = s
|
||||
end
|
||||
end
|
||||
|
||||
for i,s in ipairs(remove) do
|
||||
sources[s] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- overwrite love.audio.play to create and register source if needed
|
||||
local play = love.audio.play
|
||||
function love.audio.play(audio)
|
||||
local what = audio.path
|
||||
local how = audio.type
|
||||
local loop = audio.loop
|
||||
local src = what
|
||||
if type(what) ~= "userdata" or not what:typeOf("Source") then
|
||||
src = love.audio.newSource(what, how)
|
||||
src:setLooping(loop or false)
|
||||
end
|
||||
|
||||
play(src)
|
||||
sources[src] = src
|
||||
return src
|
||||
end
|
||||
|
||||
-- stops a source
|
||||
local stop = love.audio.stop
|
||||
function love.audio.stop(src)
|
||||
if not src then return end
|
||||
stop(src)
|
||||
sources[src] = nil
|
||||
end
|
||||
end
|
||||
@@ -1,21 +0,0 @@
|
||||
Camera = {
|
||||
pos = {x = 0, y = 0},
|
||||
width = 0,
|
||||
height = 0
|
||||
}
|
||||
|
||||
function Camera:ConfineToLevel()
|
||||
self.pos.x = math.max(0,math.min(self.pos.x,LevelData.Width-self.width/game.scale))
|
||||
self.pos.y = math.max(0,math.min(self.pos.y,LevelData.Height-self.height/game.scale))
|
||||
end
|
||||
|
||||
function Camera:positionCenterAt(x,y)
|
||||
self.pos.x = x-self.width/game.scale/2
|
||||
self.pos.y = y-self.height/game.scale/2
|
||||
self:ConfineToLevel()
|
||||
end
|
||||
|
||||
function Camera:positionAt(x,y)
|
||||
self.pos.x = math.floor((x/self.width)*self.width)
|
||||
self.pos.y = math.floor((y/self.height)*self.height)
|
||||
end
|
||||
@@ -1,73 +0,0 @@
|
||||
Collision = {}
|
||||
--[[
|
||||
Collision
|
||||
|
||||
[bool flag] isDisabled
|
||||
> if true used for collision
|
||||
|
||||
[bool flag] isColliding
|
||||
> if true, this collision is colliding
|
||||
|
||||
[vec2 position] from - x, y
|
||||
> top right corner of collision box
|
||||
|
||||
[vec2 position] to - x, y
|
||||
> bottom left corner of collision box
|
||||
|
||||
[int property] width
|
||||
> width of collision box
|
||||
|
||||
[int property] height
|
||||
> height of collision box
|
||||
--]]
|
||||
|
||||
-- can also be called with only ox and oy, where they become the width and height instead
|
||||
function Collision:New(ox,oy,tx,ty)
|
||||
local o = {isColliding = false, isDisabled = false}
|
||||
|
||||
if tx ~= nil and ty ~= nil then
|
||||
o.from = {x = ox, y = oy}
|
||||
o.to = {x = tx, y = ty}
|
||||
|
||||
o.width = o.to.x - o.from.x
|
||||
o.height = o.to.y - o.from.y
|
||||
else
|
||||
o.width = ox
|
||||
o.height = oy
|
||||
|
||||
o.from = {x = 0, y = 0}
|
||||
o.to = {x = 0, y = 0}
|
||||
end
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
function Collision:CenterAt(x, y)
|
||||
self.from.x = x-self.width/2
|
||||
self.from.y = y-self.height/2
|
||||
self.to.x = x+self.width/2
|
||||
self.to.y = y+self.height/2
|
||||
end
|
||||
|
||||
function Collision:PlaceAt(x, y)
|
||||
self.from.x = x or self.from.x
|
||||
self.from.y = y or self.from.y
|
||||
self.to.x = self.from.x + self.width
|
||||
self.to.y = self.from.x + self.height
|
||||
end
|
||||
|
||||
function Collision:Draw(color)
|
||||
if self.isColliding == true then
|
||||
love.graphics.setColor(0,1,0,0.5)
|
||||
elseif color == 1 then
|
||||
love.graphics.setColor(1,0,0,0.5)
|
||||
elseif color == 2 then
|
||||
love.graphics.setColor(0,1,1,0.5)
|
||||
end
|
||||
love.graphics.rectangle("fill",self.from.x-Camera.pos.x, self.from.y-Camera.pos.y, self.width, self.height)
|
||||
love.graphics.setColor(0,1,90,0.5)
|
||||
love.graphics.rectangle("line",self.from.x-Camera.pos.x, self.from.y-Camera.pos.y, self.width, self.height)
|
||||
end
|
||||
@@ -1,98 +0,0 @@
|
||||
function DebugUI()
|
||||
local mouse_x, mouse_y = love.mouse.getPosition()
|
||||
for _, light in pairs(Lights) do
|
||||
love.graphics.print(light.pos.x,light.pos.x,light.pos.y)
|
||||
love.graphics.print(light.pos.y,light.pos.x,light.pos.y+20)
|
||||
love.graphics.print(light.pos.x,light.pos.x,light.pos.y+40)
|
||||
end
|
||||
|
||||
love.graphics.print("time: "..fps_total..", fps: "..fps_draw..", frametime: "..math.floor(current_dt* 1000).."ms", 10*textScale, 0*textScale, 0, textScale)
|
||||
love.graphics.print(--[["CPUtime: "..checkCPUTime("total")..", CPU: "..(math.floor(checkCPUTime("get")*10000)/100).."%,]] "memoryUsage: "..memoryUsage.."kB", 10*textScale, 20*textScale, 0, textScale)
|
||||
|
||||
love.graphics.setColor(1,1,1)
|
||||
-- lots of variables
|
||||
love.graphics.print("[main_Player]",10*textScale,40*textScale, 0, textScale)
|
||||
love.graphics.print("position: {"..main_Player.pos.x..", "..main_Player.pos.y.."}",10*textScale,60*textScale, 0, textScale)
|
||||
love.graphics.print("velocity: {"..main_Player.vel.x..", "..main_Player.vel.y.."}",10*textScale,80*textScale, 0, textScale)
|
||||
love.graphics.print("scale: {"..main_Player.sprite_scale.x..", "..main_Player.sprite_scale.y.."}",10*textScale,100*textScale, 0, textScale)
|
||||
love.graphics.print("states: \"isOnGround\": "..tostring(main_Player.isOnGround),10*textScale,120*textScale, 0, textScale)
|
||||
love.graphics.print("\"coyoteValue\": "..tostring(main_Player.coyoteValue),10*textScale,140*textScale, 0, textScale)
|
||||
|
||||
love.graphics.print("[Camera]",10*textScale,160*textScale, 0, textScale)
|
||||
love.graphics.print("position: {"..Camera.pos.x..", "..Camera.pos.y.."}",10*textScale,180*textScale, 0, textScale)
|
||||
love.graphics.print("size: {"..Camera.width..", "..Camera.height.."}",10*textScale,200*textScale, 0, textScale)
|
||||
|
||||
love.graphics.print("[Cursor]",10*textScale,220*textScale, 0, textScale)
|
||||
love.graphics.print("position: {"..mouse_x+Camera.pos.x..", "..mouse_y+Camera.pos.y.."}",10*textScale,240*textScale, 0, textScale)
|
||||
|
||||
love.graphics.print(textScale,10*textScale,240*textScale, 0, textScale)
|
||||
love.graphics.print("Level: "..levelNum.." / "..#levelList.." \""..currLevel.."\"",10*textScale,260*textScale, 0, textScale)
|
||||
|
||||
-- player isOnGroundCheck
|
||||
love.graphics.setColor(1,0,0)
|
||||
end
|
||||
|
||||
function DebugColisions()
|
||||
LoadedObjects.DrawCollisions()
|
||||
end
|
||||
|
||||
function DebugEntities()
|
||||
for _, particle in pairs(LoadedParticles) do
|
||||
particle:Debug()
|
||||
end
|
||||
for _, enty in pairs(LoadedObjects.Entities) do
|
||||
enty:Debug()
|
||||
end
|
||||
end
|
||||
|
||||
--[[CPUUsage = {}
|
||||
function checkCPUTime(action, name)
|
||||
if name then
|
||||
if action == "start" then
|
||||
if CPUUsage.name == nil then CPUUsage.name = {} end
|
||||
CPUUsage.name.start = os.clock()
|
||||
elseif action == "fin" then
|
||||
CPUUsage.name.fin = os.clock()
|
||||
CPUUsage.name.use = CPUUsage.name.fin - CPUUsage.name.start
|
||||
if CPUUsage.name.total == nil then CPUUsage.name.total = 0 end
|
||||
CPUUsage.name.total = CPUUsage.name.total + CPUUsage.name.use
|
||||
print(CPUUsage.name.fin.." : "..CPUUsage.name.use.." : "..CPUUsage.name.total)
|
||||
elseif action == "get" then
|
||||
return CPUUsage.name.use
|
||||
elseif action == "total" then
|
||||
return CPUUsage.name.total
|
||||
else
|
||||
return CPUUsage.name.use
|
||||
end
|
||||
-- Totals
|
||||
else
|
||||
if action == "get" then
|
||||
local currentTotalCPU = 0
|
||||
for _, timings in ipairs(CPUUsage) do
|
||||
currentTotalCPU = currentTotalCPU + CPUUsage.timings.use
|
||||
end
|
||||
return currentTotalCPU
|
||||
elseif action == "total" then
|
||||
local currentTotalCPU = 0
|
||||
for _, timings in ipairs(CPUUsage) do
|
||||
currentTotalCPU = currentTotalCPU + CPUUsage.timings.total
|
||||
end
|
||||
return currentTotalCPU
|
||||
else
|
||||
local currentTotalCPU = 0
|
||||
for _, timings in ipairs(CPUUsage) do
|
||||
currentTotalCPU = currentTotalCPU + CPUUsage.timings.use
|
||||
end
|
||||
return currentTotalCPU
|
||||
end
|
||||
end
|
||||
end]]
|
||||
|
||||
function logPrint(string)
|
||||
if logging then print(string) end
|
||||
logWrite(string)
|
||||
end
|
||||
|
||||
function logWrite(string)
|
||||
if logging then logFile:write(string.."\n") end
|
||||
end
|
||||
@@ -1,237 +0,0 @@
|
||||
function EditorStep()
|
||||
palette = palette or false
|
||||
AnimateTiles()
|
||||
if Keybind:HasPressed(Keybind.editor.palette) then
|
||||
if palette then
|
||||
palette = false
|
||||
palette_scroll_x = nil
|
||||
palette_scroll_y = nil
|
||||
else
|
||||
palette = true
|
||||
palette_scroll_x = 0
|
||||
palette_scroll_y = 0
|
||||
end
|
||||
end
|
||||
if love.keyboard.isDown('a',"left") then
|
||||
Camera.pos.x = Camera.pos.x - 3*game.scale
|
||||
end
|
||||
if love.keyboard.isDown('d',"right") then
|
||||
Camera.pos.x = Camera.pos.x + 3*game.scale
|
||||
end
|
||||
if love.keyboard.isDown("up", "w") then
|
||||
Camera.pos.y = Camera.pos.y - 3*game.scale
|
||||
end
|
||||
if love.keyboard.isDown("down", "s") then
|
||||
Camera.pos.y = Camera.pos.y + 3*game.scale
|
||||
end
|
||||
|
||||
if palette then
|
||||
if Keybind:HasPressed(Keybind.debug.debug) then
|
||||
local next = false
|
||||
local export = nil
|
||||
for k, v in pairs(tileset) do
|
||||
if export == nil then
|
||||
export = v
|
||||
end
|
||||
if next then
|
||||
LevelData.tileset = v
|
||||
next = false
|
||||
break
|
||||
end
|
||||
|
||||
if v == LevelData.tileset then
|
||||
next = true
|
||||
end
|
||||
end
|
||||
if next then
|
||||
LevelData.tileset = export
|
||||
end
|
||||
LevelGetTileData()
|
||||
LevelIndexTiles()
|
||||
end
|
||||
end
|
||||
|
||||
if Keybind:HasPressed(Keybind.debug.reload) then
|
||||
ExportLevel("test")
|
||||
end
|
||||
|
||||
if Keybind:HasPressed(Keybind.debug.editor) then
|
||||
editor_mode = false
|
||||
TileCreateObjects()
|
||||
end
|
||||
end
|
||||
|
||||
function EditorScroll(y)
|
||||
if palette then
|
||||
if love.keyboard.isDown("lshift") then
|
||||
palette_scroll_y = palette_scroll_y + y
|
||||
else
|
||||
palette_scroll_x = palette_scroll_x + y
|
||||
end
|
||||
else
|
||||
local oscale = game.scale
|
||||
game.scale = math.max(0.1,game.scale + y/16)
|
||||
end
|
||||
end
|
||||
|
||||
function EditorDraw()
|
||||
GameworldDrawPrepare()
|
||||
GameworldDrawBackground()
|
||||
GridDisplay()
|
||||
GameworldDrawForeground()
|
||||
GameworldDrawEnd()
|
||||
EditorDoEdit()
|
||||
|
||||
DrawSelectingPaletteTile()
|
||||
if palette then
|
||||
EditorDoPalette()
|
||||
end
|
||||
end
|
||||
|
||||
function EditorDoEdit()
|
||||
local mouse_x = love.mouse.getX()
|
||||
local mouse_y = love.mouse.getY()
|
||||
local horizontal = 1+math.floor(((mouse_x/game.scale) / tileProperties.width) + (Camera.pos.x / tileProperties.width))
|
||||
local vertical = 1+math.floor(((mouse_y/game.scale) / tileProperties.height) + (Camera.pos.y / tileProperties.height))
|
||||
local expand_h = 0
|
||||
local expand_v = 0
|
||||
local LevelWidth = LevelGetTileWidth()
|
||||
local LevelHeight = LevelGetTileHeight()
|
||||
|
||||
if horizontal > LevelWidth then
|
||||
expand_h = horizontal-LevelWidth
|
||||
elseif horizontal < 0 then
|
||||
expand_h = horizontal
|
||||
end
|
||||
if vertical > LevelHeight then
|
||||
expand_v = vertical-LevelHeight
|
||||
elseif vertical < 0 then
|
||||
expand_v = vertical
|
||||
end
|
||||
love.graphics.print("> " .. horizontal .. ", " .. vertical .. "; " .. math.floor(mouse_x / game.scale + Camera.pos.x) .. ", " .. math.floor(mouse_y / game.scale + Camera.pos.y))
|
||||
love.graphics.print("> " .. LevelWidth .. "(" .. expand_h .. "), " .. LevelHeight .. "(".. expand_v .. ")", 0, 10)
|
||||
|
||||
if not palette then
|
||||
if LevelTiles[vertical] ~= nil
|
||||
and LevelTiles[vertical][horizontal] ~= nil
|
||||
and love.keyboard.isDown("lshift") ~= true
|
||||
and love.keyboard.isDown("lctrl") ~= true
|
||||
then
|
||||
if Keybind:CheckDown(Keybind.generic.lclick)
|
||||
and selecting_tile ~= nil
|
||||
then
|
||||
SetTile(vertical,horizontal,selecting_tile)
|
||||
elseif Keybind:CheckDown(Keybind.generic.rclick) then
|
||||
SetTile(vertical,horizontal,0)
|
||||
end
|
||||
LevelReloadTiles()
|
||||
|
||||
elseif Keybind:HasPressed(Keybind.generic.lshift) then
|
||||
LevelExpandCanvas(math.sign(expand_h),math.sign(expand_v))
|
||||
LevelReloadTiles()
|
||||
elseif Keybind:HasPressed(Keybind.generic.lctrl) then
|
||||
LevelReduceCanvas(math.sign(expand_h),math.sign(expand_v))
|
||||
LevelReloadTiles()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DrawSelectingPaletteTile()
|
||||
if selecting_tile ~= nil and selecting_tile ~= 0 then
|
||||
|
||||
local mouse_x = love.mouse.getX()
|
||||
local mouse_y = love.mouse.getY()
|
||||
local horizontal = math.floor(((mouse_x/game.scale) / tileProperties.width) + (Camera.pos.x / tileProperties.width))
|
||||
local vertical = math.floor(((mouse_y/game.scale) / tileProperties.height) + (Camera.pos.y / tileProperties.height))
|
||||
local draw_x = tileProperties.width * horizontal - Camera.pos.x
|
||||
local draw_y = tileProperties.height * vertical - Camera.pos.y
|
||||
|
||||
love.graphics.draw(
|
||||
LevelData.tileset,
|
||||
TileIndex[selecting_tile],
|
||||
draw_x,
|
||||
draw_y
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
function EditorDoPalette()
|
||||
|
||||
local width = LevelData.tileset:getPixelWidth()/tileProperties.width
|
||||
local height = LevelData.tileset:getPixelHeight()/tileProperties.height
|
||||
|
||||
love.graphics.setColor(0,0,0,1)
|
||||
love.graphics.rectangle(
|
||||
"fill",
|
||||
(palette_scroll_x + 1) * (tileProperties.width+1),
|
||||
(palette_scroll_y + 1) * (tileProperties.height+1),
|
||||
1 + LevelData.tileset:getPixelWidth() * ((tileProperties.width+1) / tileProperties.width),
|
||||
1 + LevelData.tileset:getPixelHeight()* ((tileProperties.height+1) / tileProperties.height)
|
||||
)
|
||||
|
||||
|
||||
love.graphics.setColor(1,1,1,1)
|
||||
local position_x = 1
|
||||
local position_y = 1
|
||||
for i = 1, #TileIndex-width-1 do
|
||||
|
||||
local tile_x = (palette_scroll_x + position_x) * (tileProperties.width+1)
|
||||
local tile_y = (palette_scroll_y + position_y) * (tileProperties.height+1)
|
||||
|
||||
love.graphics.draw(
|
||||
LevelData.tileset,
|
||||
TileIndex[i],
|
||||
tile_x,
|
||||
tile_y,
|
||||
0,
|
||||
1,
|
||||
1
|
||||
)
|
||||
if Keybind:CheckDown(Keybind.generic.lclick) then
|
||||
local mouse_x = love.mouse.getX()
|
||||
local mouse_y = love.mouse.getY()
|
||||
|
||||
if mouse_x > (tile_x) * game.scale
|
||||
and mouse_x < (tile_x + tileProperties.width) * game.scale
|
||||
and mouse_y > (tile_y) * game.scale
|
||||
and mouse_y < (tile_y + tileProperties.height) * game.scale
|
||||
then
|
||||
selecting_tile = position_x + ((position_y-1) * width)
|
||||
|
||||
love.graphics.print(selecting_tile .. " | " .. tile_x .. ", " .. tile_y, 0, 20)
|
||||
end
|
||||
end
|
||||
|
||||
if Keybind:CheckDown(Keybind.generic.rclick) then
|
||||
selecting_tile = nil
|
||||
end
|
||||
|
||||
if selecting_tile ~= nil and selecting_tile ~= 0 and i == selecting_tile then
|
||||
love.graphics.setColor(1,0,1,1)
|
||||
love.graphics.rectangle(
|
||||
"line",
|
||||
tile_x,
|
||||
tile_y,
|
||||
tileProperties.width,
|
||||
tileProperties.height
|
||||
)
|
||||
love.graphics.setColor(1,1,1,1)
|
||||
end
|
||||
|
||||
position_x = position_x + 1
|
||||
|
||||
if position_x > width then
|
||||
position_x = position_x - width
|
||||
position_y = position_y + 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
love.graphics.rectangle(
|
||||
"line",
|
||||
(palette_scroll_x + 1) * (tileProperties.width+1),
|
||||
(palette_scroll_y + 1) * (tileProperties.height+1),
|
||||
1 + LevelData.tileset:getPixelWidth() * ((tileProperties.width+1) / tileProperties.width),
|
||||
1 + LevelData.tileset:getPixelHeight()* ((tileProperties.height+1) / tileProperties.height)
|
||||
)
|
||||
end
|
||||
@@ -1,78 +0,0 @@
|
||||
Arrow = Entity:New(x,y)
|
||||
|
||||
function Arrow:New(x,y,rotation,speed)
|
||||
local o = Entity:New(x,y)
|
||||
|
||||
o.type = "arrow"
|
||||
|
||||
o.pos = {x = x, y = y}
|
||||
o.speed = speed or 0
|
||||
o.sprite_rotation = rotation or 0
|
||||
o.vel = {
|
||||
x = o.speed * math.cos(o.sprite_rotation),
|
||||
y = o.speed * math.sin(o.sprite_rotation)
|
||||
}
|
||||
o.sprite_offset = {x = 13, y = 1}
|
||||
o.stuck = false
|
||||
o.illuminated = true
|
||||
|
||||
-- animations
|
||||
o.body = Animation:New(animation.kupo.arrow)
|
||||
|
||||
table.insert(LoadedObjects.Entities,o)
|
||||
o.id = #LoadedObjects.Entities
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
function Arrow:HandleAnimation()
|
||||
self:Draw(self.body)
|
||||
end
|
||||
|
||||
function Arrow:DoPhysics()
|
||||
if not self.stuck then
|
||||
-- horizontal collisions
|
||||
if not isThereAnyCollisionAt(
|
||||
self.pos.x + self.vel.x,
|
||||
self.pos.y
|
||||
) then
|
||||
self.pos.x = self.pos.x + self.vel.x
|
||||
else
|
||||
while not isThereObjectAt(
|
||||
self.pos.x + math.sign(self.vel.x),
|
||||
self.pos.y,
|
||||
LoadedObjects.Collisions
|
||||
) do
|
||||
self.pos.x = self.pos.x + math.sign(self.vel.x)
|
||||
end
|
||||
self.stuck = true
|
||||
end
|
||||
-- vertical collision
|
||||
if not isThereAnyCollisionAt(
|
||||
self.pos.x,
|
||||
self.pos.y + self.vel.y
|
||||
) then
|
||||
self.pos.y = self.pos.y + self.vel.y
|
||||
else
|
||||
while not isThereObjectAt(
|
||||
self.pos.x,
|
||||
self.pos.y + math.sign(self.vel.y),
|
||||
LoadedObjects.Collisions
|
||||
) do
|
||||
self.pos.y = self.pos.y + math.sign(self.vel.y)
|
||||
end
|
||||
self.stuck = true
|
||||
end
|
||||
-- stuck into collisions
|
||||
if self.stuck then
|
||||
--lets allow the arrow to tip a bit into the thing
|
||||
self.pos.x = self.pos.x + self.vel.x / 5
|
||||
self.pos.y = self.pos.y + self.vel.y / 5
|
||||
self.vel.x = 0
|
||||
self.vel.y = 0
|
||||
self.illuminated = false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,119 +0,0 @@
|
||||
CursedBook = Entity:New(x,y)
|
||||
|
||||
function CursedBook:New(x,y)
|
||||
local o = Entity:New(x,y)
|
||||
|
||||
o.type = "cursed_book"
|
||||
-- behaviour
|
||||
o.pos = {x = x, y = y}
|
||||
o.speed = 0.01
|
||||
o.range = 20
|
||||
o.target = {x = x, y = y}
|
||||
|
||||
o.status = 0
|
||||
-- 0 - sleep
|
||||
-- 1 - getting up
|
||||
-- 2 - flying
|
||||
-- 3 - attack windup
|
||||
-- 4 - attack
|
||||
o.spawn_range = 100
|
||||
o.attack_range = 50
|
||||
|
||||
-- animations
|
||||
o.body = Animation:New(animation.cursed_book.spawn)
|
||||
o.sprite_tint = {0.7,0.7,0.7}
|
||||
o:centerOffset(o.body)
|
||||
o:getBoundingBox(o.body)
|
||||
|
||||
-- light
|
||||
o.light_range = 500
|
||||
o.light = CreateLight(o.pos.x,o.pos.y,o.light_range,2,HEX2RGB("#fe00d1"))
|
||||
|
||||
table.insert(LoadedObjects.Entities,o)
|
||||
o.id = #LoadedObjects.Entities
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
function CursedBook:Smart()
|
||||
self.target.x = main_Player.pos.x - main_Player.target_offset.x
|
||||
self.target.y = main_Player.pos.y - main_Player.target_offset.y
|
||||
local distance_x = self.target.x - self.pos.x
|
||||
local distance_y = self.target.y - self.pos.y
|
||||
local angle = GetAngleFromVector(distance_x,distance_y)
|
||||
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
|
||||
|
||||
if self.status == 0 then
|
||||
if distance < self.spawn_range then
|
||||
self.status = 1
|
||||
end
|
||||
elseif self.status == -1 then
|
||||
if distance < self.range then
|
||||
self.vel.x = 0
|
||||
self.vel.y = 0
|
||||
else
|
||||
self.vel.x = math.cos(angle)*self.speed*distance
|
||||
self.vel.y = math.sin(angle)*self.speed*distance
|
||||
end
|
||||
elseif self.status == 2 then
|
||||
if distance < self.attack_range then
|
||||
self.status = 3
|
||||
end
|
||||
elseif self.status == 4 then
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function CursedBook:HandleAnimation()
|
||||
if self.status == 1 then
|
||||
if self.body.path == "assets/entities/cursed_book/spawn" then
|
||||
self.body.speed = 1/3
|
||||
local tint = 0.7 + 0.3 * (self.body.frame-1)/self.body.frames
|
||||
self.sprite_tint = {tint,tint,tint}
|
||||
if self.body.frame == self.body.frames then
|
||||
self.status = 2
|
||||
self.body = self.body:ChangeTo(animation.cursed_book.flying)
|
||||
self.sprite_tint = {1,1,1}
|
||||
--self:getBoundingBox(self.body,2,2,-2,-2)
|
||||
self:centerOffset(self.body)
|
||||
end
|
||||
end
|
||||
elseif self.status == 3 then
|
||||
if self.body.path == "assets/entities/cursed_book/flying" then
|
||||
self.body = self.body:ChangeTo(animation.cursed_book.attack_transition)
|
||||
self.body.speed = 1/3
|
||||
self:centerOffset(self.body)
|
||||
if self.body.frame == self.body.frames then
|
||||
self.status = 4
|
||||
self.body = self.body:ChangeTo(animation.cursed_book.attack_loop)
|
||||
self:centerOffset(self.body)
|
||||
end
|
||||
end
|
||||
end
|
||||
self.body:Animate()
|
||||
self:Draw(self.body)
|
||||
end
|
||||
|
||||
function CursedBook:DoPhysics()
|
||||
if self.isFlying then
|
||||
local random_x = math.random(-4, 4)/100
|
||||
local random_y = math.random(-4, 4)/100
|
||||
self.vel.x = self.vel.x + random_x
|
||||
self.vel.y = self.vel.y + random_y
|
||||
end
|
||||
-- move
|
||||
|
||||
self:CollisionMove()
|
||||
self:LightAdjust()
|
||||
end
|
||||
|
||||
function CursedBook:Debug()
|
||||
-- draw center GREEN
|
||||
love.graphics.setColor(0,1,0)
|
||||
love.graphics.circle("line", -Camera.pos.x + self.pos.x, -Camera.pos.y + self.pos.y, self.spawn_range)
|
||||
love.graphics.setColor(1,0,0)
|
||||
love.graphics.circle("line", -Camera.pos.x + self.pos.x, -Camera.pos.y + self.pos.y, self.attack_range)
|
||||
Entity.Debug(self)
|
||||
end
|
||||
@@ -1,34 +0,0 @@
|
||||
Decoration = Entity:New(x,y)
|
||||
|
||||
function Decoration:New(x,y,animation,lightRange)
|
||||
local o = Entity:New(x,y)
|
||||
|
||||
o.type = "decoration"
|
||||
|
||||
o.pos = {x = x, y = y}
|
||||
|
||||
-- animations
|
||||
o.body = Animation:New(animation)
|
||||
o:centerOffset(o.body)
|
||||
o:getBoundingBox(o.body)
|
||||
|
||||
if lightRange ~= nil then
|
||||
o.lightRange = lightRange
|
||||
o.light = CreateLight(o.pos.x,o.pos.y,o.lightRange)
|
||||
end
|
||||
|
||||
table.insert(LoadedObjects.Entities,o)
|
||||
o.id = #LoadedObjects.Entities
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
function Decoration:HandleAnimation()
|
||||
self.body:Animate()
|
||||
self:Draw(self.body)
|
||||
end
|
||||
|
||||
function Decoration:DoPhysics()
|
||||
end
|
||||
@@ -1,115 +0,0 @@
|
||||
Fairy = Entity:New(x,y)
|
||||
|
||||
function Fairy:New(x,y)
|
||||
local o = Entity:New(x,y)
|
||||
|
||||
o.type = "fairy"
|
||||
|
||||
-- behaviour
|
||||
o.pos = {x = x, y = y}
|
||||
o.speed = 1.4
|
||||
o.range = 20
|
||||
o.vision_range = 120
|
||||
o.target = {x = x, y = y}
|
||||
o.hover_distance = 60
|
||||
|
||||
-- animations
|
||||
o.body = Animation:New(animation.fairy.flying)
|
||||
o:centerOffset(o.body)
|
||||
o:getBoundingBox(o.body)
|
||||
|
||||
-- light
|
||||
o.light_range = 80
|
||||
o.light = CreateLight(o.pos.x,o.pos.y,o.light_range,nil,HEX2RGB("#fed100"))
|
||||
|
||||
-- timer
|
||||
o.particle_timer = 0
|
||||
o.particle_time = 5
|
||||
|
||||
table.insert(LoadedObjects.Entities,o)
|
||||
o.id = #LoadedObjects.Entities
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
function Fairy:Smart()
|
||||
|
||||
if self:CheckVisionLine(main_Player,self.vision_range) then
|
||||
|
||||
self.target.x = main_Player.pos.x + main_Player.target_offset.x
|
||||
self.target.y = main_Player.pos.y + main_Player.target_offset.y
|
||||
|
||||
local below = 1
|
||||
while not isThereObjectAt(
|
||||
self.target.x,
|
||||
self.target.y + below * game.scale,
|
||||
LoadedObjects.Collisions
|
||||
) do
|
||||
below = below + 1
|
||||
if below >= self.hover_distance then break end
|
||||
end
|
||||
local top = 1
|
||||
while not isThereObjectAt(
|
||||
self.target.x,
|
||||
self.target.y - top * game.scale,
|
||||
LoadedObjects.Collisions
|
||||
) do
|
||||
top = top + 1
|
||||
if top >= self.hover_distance then break end
|
||||
end
|
||||
self.target.y = self.target.y - top + below
|
||||
end
|
||||
|
||||
local distance_x = self.target.x - self.pos.x
|
||||
local distance_y = self.target.y - self.pos.y
|
||||
local angle = GetAngleFromVector(distance_x,distance_y)
|
||||
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
|
||||
|
||||
if distance < self.range then
|
||||
self.vel.x = 0
|
||||
self.vel.y = 0
|
||||
else
|
||||
self.vel.x = math.cos(angle)*self.speed
|
||||
self.vel.y = math.sin(angle)*self.speed
|
||||
end
|
||||
self.particle_timer = self.particle_timer + 1
|
||||
if self.particle_timer >= self.particle_time then
|
||||
self.particle_timer = 0
|
||||
|
||||
local particle_data = {
|
||||
animation = animation.particle.simple,
|
||||
sprite_tint = HEX2RGB("#fed100"),
|
||||
direction = angle-math.rad(180+math.random(60)-30),
|
||||
speed = 0.8*(distance/50),
|
||||
speed_increase = -0.01,
|
||||
}
|
||||
Particle:New(self.pos.x,self.pos.y,particle_data)
|
||||
end
|
||||
end
|
||||
|
||||
function Fairy:HandleAnimation()
|
||||
self.body:Animate()
|
||||
--if self:isCollidingWith(main_Player) then self.sprite_tint = {1,0,0} else self.sprite_tint = {1,1,1} end
|
||||
self:Draw(self.body)
|
||||
end
|
||||
|
||||
function Fairy:DoPhysics()
|
||||
local random_x = math.random(-4, 4)/10
|
||||
local random_y = math.random(-4, 4)/10
|
||||
|
||||
self.vel.x = self.vel.x + random_x
|
||||
self.vel.y = self.vel.y + random_y
|
||||
|
||||
self:CollisionMove()
|
||||
self.vel.x = 0
|
||||
self.vel.y = 0
|
||||
|
||||
self:LightAdjust()
|
||||
end
|
||||
|
||||
function Fairy:Debug()
|
||||
Entity.Debug(self)
|
||||
self:CheckVisionLineDebug(main_Player,self.vision_range)
|
||||
end
|
||||
@@ -1,168 +0,0 @@
|
||||
Kupo = Entity:New(x,y)
|
||||
|
||||
function Kupo:New(x,y)
|
||||
local o = Entity:New(x,y)
|
||||
|
||||
o.type = "kupo"
|
||||
|
||||
o.pos = {x = x, y = y}
|
||||
o.speed = 20
|
||||
o.range = 200
|
||||
o.target = {x = x, y = y}
|
||||
o.sprite_offset = {x = 8, y = 5}
|
||||
|
||||
-- animations
|
||||
o.body = Animation:New(animation.kupo.body)
|
||||
o.bow = Animation:New(animation.kupo.bow)
|
||||
|
||||
-- bow
|
||||
o.bow_flip = 1
|
||||
o.bow_rotation = 0
|
||||
o.bow_frame = 1
|
||||
o.bow_subframe = 1
|
||||
o.bow_aim_frame = 0
|
||||
o.bow_speed = 1/10
|
||||
o.bow_frames = 6
|
||||
o.bow_extraframes = 18
|
||||
o.bow_aim_frames = 8
|
||||
o.hostile = true
|
||||
|
||||
o.lightRange = o.range/2
|
||||
o.light = CreateLight(o.pos.x,o.pos.y,o.lightRange)
|
||||
|
||||
table.insert(LoadedObjects.Entities,o)
|
||||
o.id = #LoadedObjects.Entities
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
function Kupo:Smart()
|
||||
self.light.pos.x = self.pos.x-self.target_offset.x
|
||||
self.light.pos.y = self.pos.y-self.target_offset.y
|
||||
|
||||
self.target.x = main_Player.pos.x - main_Player.target_offset.x
|
||||
self.target.y = main_Player.pos.y - main_Player.target_offset.y
|
||||
local distance_x = self.target.x - self.pos.x
|
||||
local distance_y = self.target.y - self.pos.y
|
||||
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
|
||||
local angle = GetAngleFromVector(distance_x,distance_y)
|
||||
self.draw_bow = false
|
||||
if distance <= self.range then
|
||||
if self.hostile == true then
|
||||
self.draw_bow = true
|
||||
-- fix so it can rotate from 0 to 360
|
||||
if math.deg(self.bow_rotation - angle) < 0 then
|
||||
self.bow_rotation = self.bow_rotation + math.rad(360)
|
||||
end
|
||||
|
||||
-- fix so it can rotate from 360 to 0
|
||||
if math.deg(self.bow_rotation - angle) > 180 then
|
||||
self.bow_rotation = self.bow_rotation - math.rad(360)
|
||||
end
|
||||
|
||||
-- actual rotation
|
||||
if self.bow_rotation < angle then
|
||||
self.bow_rotation = self.bow_rotation + math.rad(2)
|
||||
else
|
||||
self.bow_rotation = self.bow_rotation - math.rad(2)
|
||||
end
|
||||
--set in place
|
||||
if math.abs(math.deg(self.bow_rotation) - math.deg(angle)) < 2 then
|
||||
self.bow_rotation = angle
|
||||
end
|
||||
|
||||
-- holding tight dispersion -- also affects arrows
|
||||
if self.bow_rotation == angle then
|
||||
self.bow_rotation = self.bow_rotation + math.rad(math.random(math.abs(math.floor(self.bow_frame-self.bow_aim_frames-self.bow_frames)/2)))
|
||||
end
|
||||
|
||||
-- AIMING AI
|
||||
|
||||
self.bow_subframe = self.bow_subframe + current_dt
|
||||
|
||||
if self.bow_subframe > self.bow_speed then
|
||||
self.bow_subframe = self.bow_subframe - self.bow_speed
|
||||
if self.bow_frame == 3 then
|
||||
self.bow_aim_frame = self.bow_aim_frame + 1
|
||||
if self.bow_aim_frame > self.bow_aim_frames then
|
||||
self.bow_aim_frame = self.bow_aim_frame - self.bow_aim_frames
|
||||
self.bow_frame = self.bow_frame + 1
|
||||
Arrow:New(self.pos.x,self.pos.y,self.bow_rotation,15)
|
||||
end
|
||||
else
|
||||
self.bow_frame = self.bow_frame + 1
|
||||
end
|
||||
if self.bow_frame > self.bow_frames + self.bow_extraframes then
|
||||
self.bow_frame = self.bow_frame - self.bow_frames - self.bow_extraframes
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
self.bow_frame = 6
|
||||
-- rest bow animation
|
||||
if distance_x > 0 then
|
||||
if self.bow_rotation > math.rad(45) then
|
||||
self.bow_rotation = self.bow_rotation - math.rad(3)
|
||||
elseif self.bow_rotation < math.rad(45) then
|
||||
self.bow_rotation = self.bow_rotation + math.rad(3)
|
||||
end
|
||||
|
||||
-- set in place
|
||||
if math.abs(math.deg(self.bow_rotation) - 45) < 3 then
|
||||
self.bow_rotation = math.rad(45)
|
||||
end
|
||||
self.sprite_flip.x = 1
|
||||
else
|
||||
if self.bow_rotation > math.rad(135) then
|
||||
self.bow_rotation = self.bow_rotation - math.rad(3)
|
||||
elseif self.bow_rotation < math.rad(135) then
|
||||
self.bow_rotation = self.bow_rotation + math.rad(3)
|
||||
end
|
||||
-- set in place
|
||||
if math.abs(math.deg(self.bow_rotation) - 135) < 3 then
|
||||
self.bow_rotation = math.rad(135)
|
||||
end
|
||||
self.sprite_flip.x = -1
|
||||
end
|
||||
end
|
||||
self.angle = angle
|
||||
end
|
||||
|
||||
function Kupo:HandleAnimation()
|
||||
local distance_x = self.target.x - self.pos.x
|
||||
local distance_y = self.target.y - self.pos.y
|
||||
|
||||
if distance_x > 0 then
|
||||
self.sprite_flip.x = 1
|
||||
else
|
||||
self.sprite_flip.x = -1
|
||||
end
|
||||
|
||||
-- flip sprite to look in the direction is moving
|
||||
if self.vel.x ~= 0 then self.sprite_flip.x = math.sign(self.vel.x) end
|
||||
|
||||
self.body:Animate()
|
||||
self:Draw(self.body)
|
||||
|
||||
if self.draw_bow == true then
|
||||
self.bow:DrawFrame(
|
||||
math.min(self.bow_frame,self.bow_frames),
|
||||
self.pos.x + ( 8 * math.sin(self.bow_rotation)),
|
||||
self.pos.y + (2 - 6 * math.cos(self.bow_rotation)),
|
||||
self.bow_rotation
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
function Kupo:DoPhysics()
|
||||
|
||||
-- horizontal collisions
|
||||
if not isThereAnyCollisionAt(self.pos.x + self.vel.x, self.pos.y) then
|
||||
self.pos.x = self.pos.x + self.vel.x
|
||||
end
|
||||
if not isThereAnyCollisionAt(self.pos.x, self.pos.y + self.vel.y) then
|
||||
self.pos.y = self.pos.y + self.vel.y
|
||||
end
|
||||
end
|
||||
@@ -1,99 +0,0 @@
|
||||
Particle = Entity:New(x,y)
|
||||
|
||||
function Particle:New(x,y,particle_data)
|
||||
local o = Entity:New(x,y)
|
||||
|
||||
o.pos = {x = x, y = y}
|
||||
|
||||
o.speed = particle_data.speed or 0
|
||||
o.direction = particle_data.direction or o.direction
|
||||
o.sprite_rotation = particle_data.sprite_rotation or o.sprite_rotation
|
||||
o.sprite_offset = particle_data.sprite_offset or o.sprite_offset
|
||||
o.sprite_scale = particle_data.sprite_scale or o.sprite_scale
|
||||
o.sprite_tint = particle_data.sprite_tint or o.sprite_tint
|
||||
o.sprite_alpha = particle_data.sprite_alpha or o.sprite_alpha
|
||||
o.sprite_alpha_base = o.sprite_alpha
|
||||
|
||||
o.sprite_flip = particle_data.sprite_flip or o.sprite_flip
|
||||
o.animation_active = particle_data.animation_active or false
|
||||
|
||||
o.time = 0.5
|
||||
o.timer = 0
|
||||
|
||||
o.vel = {
|
||||
x = o.speed * math.cos(o.direction),
|
||||
y = o.speed * math.sin(o.direction)
|
||||
}
|
||||
|
||||
o.speed_increase = particle_data.speed_increase or 0
|
||||
|
||||
if particle_data.light ~= nil then
|
||||
o.lightRange = particle_data.light
|
||||
local flicker = particle_data.light_flicker or nil
|
||||
local color = particle_data.light_color or nil
|
||||
o.light = CreateLight(o.pos.x,o.pos.y,o.lightRange,flicker,color)
|
||||
end
|
||||
|
||||
-- animations
|
||||
if particle_data.animation ~= nil then
|
||||
o.body = Animation:New(particle_data.animation)
|
||||
o:centerOffset(o.body)
|
||||
o:getBoundingBox(o.body)
|
||||
if not o.animation_active then
|
||||
o.body.speed = 0
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(LoadedParticles,o)
|
||||
o.id = #LoadedParticles
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
function Particle:Kill()
|
||||
if self.light ~= nil then
|
||||
KillLight(self.light)
|
||||
end
|
||||
if self.id ~= nil then
|
||||
for _, e in pairs(LoadedParticles) do
|
||||
if e.id > self.id then
|
||||
e.id = e.id - 1
|
||||
end
|
||||
end
|
||||
table.remove(LoadedParticles,self.id)
|
||||
end
|
||||
self = nil
|
||||
end
|
||||
|
||||
function Particle:HandleAnimation()
|
||||
self.timer = self.timer + current_dt
|
||||
self.sprite_alpha = self.sprite_alpha_base*(self.time-self.timer)/self.time
|
||||
if self.light ~= nil then
|
||||
self:LightAdjust()
|
||||
self.light.range = self.lightRange * self.sprite_alpha/2
|
||||
end
|
||||
if self.sprite_alpha < 0 then self:Kill() end
|
||||
if self.body ~= nil then
|
||||
self.body:Animate()
|
||||
self:Draw(self.body)
|
||||
end
|
||||
end
|
||||
|
||||
function Particle:DoPhysics()
|
||||
-- adjust speed
|
||||
if self.speed_increase ~= 0 then
|
||||
self.speed = self.speed + self.speed_increase
|
||||
self.vel.x = self.speed * math.cos(self.direction)
|
||||
self.vel.y = self.speed * math.sin(self.direction)
|
||||
end
|
||||
-- move
|
||||
self:CollisionMove()
|
||||
end
|
||||
|
||||
function Particle:Debug()
|
||||
-- draw center CYAN
|
||||
love.graphics.setColor(0,1,1)
|
||||
love.graphics.circle("fill", -Camera.pos.x + self.pos.x, -Camera.pos.y + self.pos.y, 1)
|
||||
end
|
||||
@@ -1,281 +0,0 @@
|
||||
Player = Entity:New(x,y)
|
||||
|
||||
|
||||
function Player:New(x,y)
|
||||
local o = Entity:New(x,y)
|
||||
|
||||
o.type = "player"
|
||||
-- physics
|
||||
o.moveSpeed = 1.3 -- gameworld pixels
|
||||
o.zeroSpeed = 0.01 -- gameworld pixels
|
||||
o.move_x = 0 -- gameworld pixels
|
||||
|
||||
o.airFriction = 0.01 -- gameworld pixels
|
||||
o.groundFriction = 0.3 -- gameworld pixels
|
||||
|
||||
o.jumpImpulse = 3.5 -- gameworld pixels
|
||||
|
||||
o.coyoteAmount = 5 -- int
|
||||
o.coyoteValue = 5 -- frames
|
||||
|
||||
o.dashCooldownTime = 0.1 -- seconds
|
||||
o.dashCooldownTimer = 0 -- seconds
|
||||
|
||||
-- dash values
|
||||
o.dashTimer = 0 -- seconds
|
||||
o.dashTime = 0.15 -- seconds
|
||||
o.dashDistance = 40 -- gameworld pixels
|
||||
o.dashSpeed = o.dashDistance / (o.dashTime*60) -- pixels
|
||||
o.dashCount = 1 -- int
|
||||
o.dashAmount = 10 -- int
|
||||
|
||||
-- hook values
|
||||
o.hookDistance = 100
|
||||
o.hookedDistance = 80
|
||||
o.hookAnchor = {
|
||||
x = nil,
|
||||
y = nil
|
||||
}
|
||||
|
||||
o.boxCollision = {
|
||||
from = {x = -8, y = -16}, --gameworld pixels
|
||||
to = {x = 8, y = 0} -- gameworld pixels
|
||||
}
|
||||
|
||||
o.lightRange = 10 -- screen pixels
|
||||
|
||||
-- status
|
||||
o.isDashing = false
|
||||
o.isJumping = false
|
||||
o.isHooked = false
|
||||
o.isOnGround = true
|
||||
o.isOnLadder = false
|
||||
o.canJump = true
|
||||
o.canFall = true
|
||||
o.canFriction = true
|
||||
o.maskType = animation.moth_mask
|
||||
|
||||
o.anchorRespawn = {
|
||||
x = o.pos.x,
|
||||
y = o.pos.y
|
||||
}
|
||||
|
||||
-- sprite
|
||||
o.target_offset = {x = 0, y = 0}
|
||||
o.body = Animation:New(animation.nancy.idle)
|
||||
o.mask = Animation:New(animation.moth_mask.idle)
|
||||
o:centerOffset(o.body)
|
||||
o:getBoundingBox(o.body,0,3,-1,-3)
|
||||
|
||||
-- lights
|
||||
o.light = CreateLight(o.pos.x,o.pos.y,o.lightRange)
|
||||
|
||||
table.insert(LoadedObjects.Entities,o)
|
||||
o.id = #LoadedObjects.Entities
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
function Player:Smart()
|
||||
self:LightAdjust(self.target_offset.x,self.target_offset.y)
|
||||
|
||||
-- reset coyoteValue
|
||||
if self.isOnGround then
|
||||
self.coyoteValue = self.coyoteAmount
|
||||
elseif self.coyoteValue > 0 then
|
||||
self.coyoteValue = self.coyoteValue - 1
|
||||
end
|
||||
|
||||
if self.dashTimer <= 0 then
|
||||
-- horizontal movement
|
||||
if Keybind:CheckDown(Keybind.move.left) then
|
||||
self.move_x = -self.moveSpeed
|
||||
elseif Keybind:CheckDown(Keybind.move.right) then
|
||||
self.move_x = self.moveSpeed
|
||||
end
|
||||
|
||||
-- jump if on ground (coyotevalue)
|
||||
if Keybind:CheckDown(Keybind.move.jump) then
|
||||
if self.coyoteValue > 0 then
|
||||
self.vel.y = -self.jumpImpulse
|
||||
self.coyoteValue = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- dash timer
|
||||
self.dashCooldownTimer = math.max(0,self.dashCooldownTimer - current_dt)
|
||||
|
||||
-- try to dash
|
||||
if Keybind:CheckDown(Keybind.move.dash) then
|
||||
if self.dashCooldownTimer == 0
|
||||
and not self.isDashing
|
||||
and self.dashCount > 0 then
|
||||
|
||||
-- state player
|
||||
self.dashCount = self.dashCount - 1
|
||||
self.isDashing = true
|
||||
|
||||
-- get dash direction
|
||||
local vertical = 0
|
||||
if Keybind:CheckDown(Keybind.move.down) then vertical = vertical + 1 end
|
||||
if Keybind:CheckDown(Keybind.move.up) then vertical = vertical - 1 end
|
||||
local horizontal = 0
|
||||
if Keybind:CheckDown(Keybind.move.right) then horizontal = horizontal + 1 end
|
||||
if Keybind:CheckDown(Keybind.move.left) then horizontal = horizontal - 1 end
|
||||
|
||||
-- if no direction, then dash forward
|
||||
if horizontal == 0 and vertical == 0 then
|
||||
horizontal = self.sprite_flip.x
|
||||
end
|
||||
|
||||
-- set dash values
|
||||
self.dashDirection = GetAngleFromVector(horizontal, vertical)
|
||||
self.dashTimer = self.dashTime
|
||||
end
|
||||
else
|
||||
-- not dashing!
|
||||
self.isDashing = false
|
||||
end
|
||||
|
||||
if Keybind:CheckDown(Keybind.move.hook) then
|
||||
local anchor = self:CheckNearest("decoration",self.hookDistance)
|
||||
if anchor then
|
||||
self.isHooked = true
|
||||
self.hookAnchor = {
|
||||
x = anchor.pos.x,
|
||||
y = anchor.pos.y
|
||||
}
|
||||
end
|
||||
else
|
||||
self.isHooked = false
|
||||
end
|
||||
end
|
||||
|
||||
function Player:DoPhysics()
|
||||
if self.dashTimer <= 0 then
|
||||
if self.isOnGround then
|
||||
self.vel.x = self.vel.x * (1-self.groundFriction)
|
||||
else
|
||||
self.vel.x = self.vel.x * (1-self.airFriction)
|
||||
end
|
||||
if math.abs(self.vel.x) < self.zeroSpeed then self.vel.x = 0 end
|
||||
end
|
||||
|
||||
-- reset state
|
||||
self.canFall = true
|
||||
self.isOnGround = false
|
||||
-- adjust timers
|
||||
self.dashTimer = self.dashTimer - current_dt
|
||||
|
||||
-- DASH STATE
|
||||
if self.dashTimer > 0 then
|
||||
self.canFall = false
|
||||
-- dash particle
|
||||
local particle_data = {
|
||||
animation = self.body,
|
||||
sprite_tint = HEX2RGB("#fed100"),
|
||||
sprite_alpha = 0.5,
|
||||
sprite_flip = {
|
||||
x = self.sprite_flip.x,
|
||||
y = self.sprite_flip.y
|
||||
}
|
||||
}
|
||||
Particle:New(self.pos.x,self.pos.y,particle_data)
|
||||
self.dashCooldownTimer = self.dashCooldownTime
|
||||
-- dash movement
|
||||
self.vel.x = self.dashSpeed * math.cos(self.dashDirection)
|
||||
self.vel.y = self.dashSpeed * math.sin(self.dashDirection)
|
||||
end
|
||||
|
||||
-- hook state
|
||||
if self.isHooked then
|
||||
local hook = Vector(self.pos.x, self.pos.y, self.hookAnchor.x, self.hookAnchor.y)
|
||||
if GetVectorValue(hook) > self.hookedDistance then
|
||||
self.canFall = false
|
||||
local hook_angle = GetAngleFromVector(hook[1],hook[2])
|
||||
--pos_x = self.hookAnchor.x + self.hookedDistance * math.cos(-math.rad(180)+hook_angle) + ((gravity ^ 2)/2) * math.sin(hook_angle)
|
||||
--pos_y = self.hookAnchor.y + self.hookedDistance * math.sin(-math.rad(180)+hook_angle) + ((gravity ^ 2)/2) * math.cos(hook_angle)
|
||||
self.vel.x = self.vel.x + gravity * (-math.sin(hook_angle))
|
||||
self.vel.y = self.vel.y + gravity * math.cos(hook_angle)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if self.canFall then
|
||||
-- not in dash or hook; fall normally
|
||||
self.dashTimer = 0
|
||||
self.vel.y = self.vel.y + gravity
|
||||
end
|
||||
|
||||
-- horizontal collision
|
||||
if not self:isCollidingAt(self.pos.x + self.vel.x + self.move_x, self.pos.y, LoadedObjects.Collisions) then
|
||||
self.pos.x = self.pos.x + self.vel.x + self.move_x
|
||||
else
|
||||
self.vel.x = 0
|
||||
end
|
||||
|
||||
-- vertical collision
|
||||
if not self:isCollidingAt(self.pos.x, self.pos.y + self.vel.y, LoadedObjects.Collisions) then
|
||||
self.pos.y = self.pos.y + self.vel.y
|
||||
else
|
||||
if self.vel.y > 0 then
|
||||
self.isOnGround = true
|
||||
self.dashCount = self.dashAmount
|
||||
end
|
||||
self.vel.y = 0
|
||||
end
|
||||
|
||||
-- if u collision w hazard, respawn
|
||||
if self:isCollidingAt(self.pos.x, self.pos.y, LoadedObjects.Hazards) then
|
||||
self:Respawn()
|
||||
end
|
||||
end
|
||||
|
||||
function Player:Respawn()
|
||||
self.pos.x = self.anchorRespawn.x
|
||||
self.pos.y = self.anchorRespawn.y
|
||||
end
|
||||
|
||||
function Player:HandleAnimation()
|
||||
-- flip sprite to look in the direction is moving
|
||||
if self.move_x ~= 0 then self.sprite_flip.x = math.sign(self.move_x) end
|
||||
|
||||
-- animation priority
|
||||
self.body = self.body:ChangeTo(animation.nancy.fall)
|
||||
if self.vel.y > 1.25 then
|
||||
self.mask = self.mask:ChangeTo(self.maskType.fall)
|
||||
elseif self.vel.y < 0 then
|
||||
self.body = self.body:ChangeTo(animation.nancy.jump)
|
||||
self.mask = self.mask:ChangeTo(self.maskType.jump)
|
||||
elseif self.vel.x + self.move_x ~= 0 then
|
||||
self.body = self.body:ChangeTo(animation.nancy.run)
|
||||
self.mask = self.mask:ChangeTo(self.maskType.run)
|
||||
else
|
||||
self.body = self.body:ChangeTo(animation.nancy.idle)
|
||||
self.mask = self.mask:ChangeTo(self.maskType.idle)
|
||||
end
|
||||
|
||||
-- special case: idle animation gets slower by time
|
||||
if self.body.anim_path == animation.nancy.idle.path then
|
||||
if self.body.anim_speed < 0.5 then self.body.anim_speed = self.body.anim_speed + 0.001 end
|
||||
end
|
||||
|
||||
if self.isHooked then
|
||||
love.graphics.line(
|
||||
-Camera.pos.x + self.pos.x,
|
||||
-Camera.pos.y + self.pos.y,
|
||||
-Camera.pos.x + self.hookAnchor.x,
|
||||
-Camera.pos.y + self.hookAnchor.y
|
||||
)
|
||||
end
|
||||
|
||||
self.body:Animate()
|
||||
self:Draw(self.body)
|
||||
if self.dashCount > 0 then
|
||||
self:Draw(self.mask)
|
||||
end
|
||||
self.move_x = 0
|
||||
end
|
||||
@@ -1,257 +0,0 @@
|
||||
Entity = {class = "Entity"}
|
||||
|
||||
function Entity:New(x,y)
|
||||
o = {}
|
||||
o.pos = {x = x, y = y}
|
||||
o.vel = {x = 0, y = 0}
|
||||
|
||||
o.direction = 0
|
||||
|
||||
o.boxCollision = {
|
||||
from = {x = x, y = y},
|
||||
to = {x = x, y = y},
|
||||
}
|
||||
|
||||
o.target_offset = {x = 0, y = 0}
|
||||
|
||||
o.sprite_offset = {x = 0, y = 0}
|
||||
o.sprite_scale = {x = 1, y = 1}
|
||||
o.sprite_rotation = math.rad(0)
|
||||
o.sprite_tint = {1,1,1}
|
||||
o.sprite_alpha = 1
|
||||
o.sprite_flip = { x = 1, y = 1}
|
||||
o.illuminated = false
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
function Entity:CheckNearest(type,maxdistance)
|
||||
local return_entity = nil
|
||||
local shortest = -1
|
||||
for _, entity in pairs(LoadedObjects.Entities) do
|
||||
if not type or entity.type == type then
|
||||
local distance_x = entity.pos.x - self.pos.x
|
||||
local distance_y = entity.pos.y - self.pos.y
|
||||
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
|
||||
|
||||
if not maxdistance or distance < maxdistance then
|
||||
if shortest == -1 or distance < shortest then
|
||||
shortest = distance
|
||||
return_entity = entity
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
return return_entity
|
||||
end
|
||||
|
||||
function Entity:Smart()
|
||||
end
|
||||
|
||||
function Entity:Move()
|
||||
self.pos.x = self.pos.x + self.vel.x
|
||||
self.pos.y = self.pos.y + self.vel.y
|
||||
end
|
||||
|
||||
function Entity:CollisionMove()
|
||||
if not self:isCollidingAt(self.pos.x + self.vel.x, self.pos.y, LoadedObjects.Collisions) then
|
||||
self.pos.x = self.pos.x + self.vel.x
|
||||
else
|
||||
self.vel.x = 0
|
||||
end
|
||||
if not self:isCollidingAt(self.pos.x, self.pos.y + self.vel.y, LoadedObjects.Collisions) then
|
||||
self.pos.y = self.pos.y + self.vel.y
|
||||
else
|
||||
self.vel.y = 0
|
||||
end
|
||||
end
|
||||
|
||||
function Entity:LightAdjust(x,y)
|
||||
if self.light ~= nil then
|
||||
local x = x or 0
|
||||
local y = y or 0
|
||||
self.light.pos.x = self.pos.x
|
||||
self.light.pos.y = self.pos.y
|
||||
end
|
||||
end
|
||||
|
||||
function Entity:Kill()
|
||||
if self.light ~= nil then
|
||||
KillLight(self.light)
|
||||
end
|
||||
if self.id ~= nil then
|
||||
for _, e in pairs(LoadedObjects.Entities) do
|
||||
if e.id > self.id then
|
||||
e.id = e.id - 1
|
||||
end
|
||||
end
|
||||
table.remove(LoadedObjects.Entities,self.id)
|
||||
end
|
||||
self = nil
|
||||
end
|
||||
|
||||
function Entity:CheckVisionLine(entity,range)
|
||||
local target_x = entity.pos.x + entity.target_offset.x
|
||||
local target_y = entity.pos.y + entity.target_offset.y
|
||||
|
||||
local distance_x = target_x - self.pos.x
|
||||
local distance_y = target_y - self.pos.y
|
||||
|
||||
local angle = GetAngleFromVector(distance_x,distance_y)
|
||||
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
|
||||
|
||||
local is_colliding = true
|
||||
|
||||
if distance < range then
|
||||
is_colliding = false
|
||||
for i=1, distance, game.scale do
|
||||
if isThereObjectAt(
|
||||
self.pos.x+math.cos(angle)*i,
|
||||
self.pos.y+math.sin(angle)*i,
|
||||
LoadedObjects.Collisions
|
||||
) then
|
||||
is_colliding = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return not is_colliding
|
||||
end
|
||||
|
||||
function Entity:Draw(animation)
|
||||
local c1, c2, c3, a = love.graphics.getColor()
|
||||
love.graphics.setColor(self.sprite_tint[1],self.sprite_tint[2],self.sprite_tint[3],self.sprite_alpha)
|
||||
animation:Draw(
|
||||
self.pos.x - Camera.pos.x - ( (self.sprite_offset.x) * math.cos(self.sprite_rotation) - (self.sprite_offset.y) * math.sin(self.sprite_rotation)) * self.sprite_scale.x * self.sprite_flip.x,
|
||||
self.pos.y - Camera.pos.y - ( (self.sprite_offset.x) * math.sin(self.sprite_rotation) + (self.sprite_offset.y) * math.cos(self.sprite_rotation)) * self.sprite_scale.y * self.sprite_flip.y,
|
||||
self.sprite_rotation,
|
||||
self.sprite_scale.x * self.sprite_flip.x,
|
||||
self.sprite_scale.y * self.sprite_flip.y
|
||||
)
|
||||
love.graphics.setColor(c1,c2,c3,a)
|
||||
end
|
||||
|
||||
function Entity:centerOffset(animation,x,y)
|
||||
local x = x or 0
|
||||
local y = y or 0
|
||||
self.sprite_offset.x = animation.imgs[1]:getWidth()/2 + x
|
||||
self.sprite_offset.y = animation.imgs[1]:getHeight()/2 + y
|
||||
end
|
||||
|
||||
function Entity:getBoundingBox(animation,top,left,bottom,right)
|
||||
local left = left or 0
|
||||
local right = right or 0
|
||||
local top = top or 0
|
||||
local bottom = bottom or 0
|
||||
self.boxCollision.from.x = -animation.imgs[1]:getWidth()/2 + left
|
||||
self.boxCollision.to.x = animation.imgs[1]:getWidth()/2 + right
|
||||
self.boxCollision.from.y = -animation.imgs[1]:getHeight()/2 + top
|
||||
self.boxCollision.to.y = animation.imgs[1]:getHeight()/2 + bottom
|
||||
end
|
||||
|
||||
-- returns true if theres a collision at that point. also marks collisioned tile as collision true
|
||||
function Entity:isCollidingAt(x,y,object)
|
||||
for _, collision in pairs(object) do
|
||||
if collision.disable then
|
||||
-- Dont calculate if disabled
|
||||
elseif x + self.boxCollision.from.x < collision.to.x
|
||||
and x + self.boxCollision.to.x > collision.from.x
|
||||
and y + self.boxCollision.from.y < collision.to.y
|
||||
and y + self.boxCollision.to.y > collision.from.y
|
||||
then
|
||||
collision.isColliding = true
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Entity:isCollidingWith(entity)
|
||||
return self.pos.x + self.boxCollision.from.x < entity.pos.x + entity.boxCollision.to.x
|
||||
and entity.pos.x + entity.boxCollision.from.x < self.pos.x + self.boxCollision.to.x
|
||||
and self.pos.y + self.boxCollision.from.y < entity.pos.y + entity.boxCollision.to.y
|
||||
and entity.pos.y + entity.boxCollision.from.y < self.pos.y + self.boxCollision.to.y
|
||||
end
|
||||
|
||||
function Entity:isCollidingAtAll(x,y)
|
||||
local result = false
|
||||
if not result then
|
||||
result = self:isCollidingAt(x,y,objects.collisions)
|
||||
end
|
||||
if not result then
|
||||
result = self:isCollidingAt(x,y,objects.ladders)
|
||||
end
|
||||
if not result then
|
||||
result = self:isCollidingAt(x,y,objects.platforms)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function Entity:CheckVisionLineDebug(entity,range)
|
||||
local c1, c2, c3, a = love.graphics.getColor()
|
||||
|
||||
local target_x = entity.pos.x + entity.target_offset.x
|
||||
local target_y = entity.pos.y + entity.target_offset.y
|
||||
|
||||
local distance_x = target_x - self.pos.x
|
||||
local distance_y = target_y - self.pos.y
|
||||
|
||||
local angle = GetAngleFromVector(distance_x,distance_y)
|
||||
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
|
||||
|
||||
if distance < range then
|
||||
for i=1, distance, game.scale do
|
||||
if isThereObjectAt(
|
||||
self.pos.x+math.cos(angle)*i,
|
||||
self.pos.y+math.sin(angle)*i,
|
||||
LoadedObjects.Collisions
|
||||
) then
|
||||
love.graphics.setColor(1,0,0)
|
||||
else
|
||||
love.graphics.setColor(0,1,0)
|
||||
end
|
||||
love.graphics.line(
|
||||
self.pos.x+math.cos(angle)*i-1 - Camera.pos.x,
|
||||
self.pos.y+math.sin(angle)*i-1 - Camera.pos.y,
|
||||
self.pos.x+math.cos(angle)*i - Camera.pos.x,
|
||||
self.pos.y+math.sin(angle)*i - Camera.pos.y
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
love.graphics.setColor(c1,c2,c3,a)
|
||||
end
|
||||
|
||||
function Entity:Debug()
|
||||
-- draw center GREEN
|
||||
love.graphics.setColor(0,1,0)
|
||||
love.graphics.circle("fill", -Camera.pos.x + self.pos.x, -Camera.pos.y + self.pos.y, 1)
|
||||
-- draw collision box PURPLE
|
||||
love.graphics.setColor(1,0,1)
|
||||
love.graphics.rectangle(
|
||||
"line",
|
||||
-Camera.pos.x + self.pos.x + self.boxCollision.from.x,
|
||||
-Camera.pos.y + self.pos.y + self.boxCollision.from.y,
|
||||
-Camera.pos.x + self.pos.x + self.boxCollision.to.x -(-Camera.pos.x + self.pos.x + self.boxCollision.from.x),
|
||||
-Camera.pos.y + self.pos.y + self.boxCollision.to.y -(-Camera.pos.y + self.pos.y + self.boxCollision.from.y)
|
||||
)
|
||||
if self.target ~= nil then
|
||||
love.graphics.line(
|
||||
-Camera.pos.x + self.pos.x,
|
||||
-Camera.pos.y + self.pos.y,
|
||||
-Camera.pos.x + self.target.x,
|
||||
-Camera.pos.y + self.target.y
|
||||
)
|
||||
end
|
||||
end
|
||||
require "data/scripts/entities/kupo"
|
||||
require "data/scripts/entities/arrow"
|
||||
require "data/scripts/entities/decoration"
|
||||
require "data/scripts/entities/player"
|
||||
require "data/scripts/entities/fairy"
|
||||
require "data/scripts/entities/cursed_book"
|
||||
require "data/scripts/entities/particle"
|
||||
@@ -1,72 +0,0 @@
|
||||
function GameStep()
|
||||
SetCollisionFlags()
|
||||
if menu_type == "no" then
|
||||
for _, particle in pairs(LoadedParticles) do
|
||||
particle:Smart()
|
||||
end
|
||||
for _, enty in pairs(LoadedObjects.Entities) do
|
||||
enty:Smart()
|
||||
end
|
||||
end
|
||||
|
||||
for _, particle in pairs(LoadedParticles) do
|
||||
particle:DoPhysics()
|
||||
end
|
||||
for _, enty in pairs(LoadedObjects.Entities) do
|
||||
enty:DoPhysics()
|
||||
end
|
||||
|
||||
AnimateTiles()
|
||||
Camera:positionCenterAt(main_Player.pos.x, main_Player.pos.y)
|
||||
--camera:positionAt(main_Player.pos.x, main_Player.pos.y,game.width,game.height)
|
||||
|
||||
if Keybind:HasPressed(Keybind.debug.debug) then
|
||||
if debug then
|
||||
debug = false
|
||||
debug_collision = true
|
||||
elseif debug_collision then
|
||||
debug_collision = false
|
||||
else
|
||||
debug = true
|
||||
end
|
||||
end
|
||||
|
||||
if Keybind:HasPressed(Keybind.debug.reposition) then
|
||||
if not editor_mode then
|
||||
main_Player.pos.x, main_Player.pos.y = 16,-10
|
||||
end
|
||||
end
|
||||
|
||||
if Keybind:HasPressed(Keybind.debug.reload) then
|
||||
MenuClear()
|
||||
menu_type = "dialog"
|
||||
MenuInit("dialog",DialogSequence.Example)
|
||||
end
|
||||
|
||||
if Keybind:HasPressed(Keybind.debug.editor) then
|
||||
editor_mode = true
|
||||
end
|
||||
end
|
||||
|
||||
function GameDraw()
|
||||
|
||||
GameworldDrawPrepare()
|
||||
GameworldDrawBackground()
|
||||
GameworldDrawForeground()
|
||||
if LevelData.properties.darkness then
|
||||
GameworldDrawLighting()
|
||||
end
|
||||
GameworldDrawParticles()
|
||||
GameworldDrawEntities()
|
||||
GameworldDrawEnd()
|
||||
|
||||
-- hud
|
||||
textScale = 0.5
|
||||
|
||||
-- debug
|
||||
if debug then DebugUI() end
|
||||
if debug_collision then
|
||||
DebugColisions()
|
||||
DebugEntities()
|
||||
end
|
||||
end
|
||||
@@ -1,89 +0,0 @@
|
||||
function GameworldDrawPrepare()
|
||||
if game_resize then
|
||||
Camera.height = game.height
|
||||
Camera.width = game.width
|
||||
end
|
||||
pcr, pcg, pcb, pca = love.graphics.getColor()
|
||||
love.graphics.scale(game.scale,game.scale)
|
||||
love.graphics.setColor(1,1,1,1)
|
||||
end
|
||||
|
||||
function GameworldDrawEnd()
|
||||
love.graphics.setColor(pcr, pcg, pcb, pca)
|
||||
pcr, pcg, pcb, pca = nil, nil, nil, nil
|
||||
end
|
||||
|
||||
function GameworldDrawBackground()
|
||||
-- obscure a bit
|
||||
love.graphics.setColor(0.7,0.7,0.7)
|
||||
for i = 1, #LevelTiles do
|
||||
for j = 1, #LevelTiles[i] do
|
||||
if LevelTiles[i][j].id ~= 0 then
|
||||
|
||||
local depth = TileData[LevelTiles[i][j].id].depth
|
||||
DrawTile(
|
||||
LevelTiles[i][j],
|
||||
tileProperties.scale * j * tileProperties.width + tileProperties.scale * (levelProperties.offset.x - tileProperties.width) - Camera.pos.x,
|
||||
tileProperties.scale * i * tileProperties.height + tileProperties.scale * (levelProperties.offset.y - tileProperties.height) - Camera.pos.y,
|
||||
"background"
|
||||
)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GameworldDrawParticles()
|
||||
love.graphics.setColor(0.7,0.7,0.7)
|
||||
for _, particle in pairs(LoadedParticles) do
|
||||
particle:HandleAnimation()
|
||||
end
|
||||
end
|
||||
|
||||
function GameworldDrawEntities()
|
||||
love.graphics.setColor(1,1,1)
|
||||
for _, enty in pairs(LoadedObjects.Entities) do
|
||||
enty:HandleAnimation()
|
||||
end
|
||||
end
|
||||
|
||||
function GameworldDrawForeground()
|
||||
love.graphics.setColor(1,1,1)
|
||||
for i = 1, #LevelTiles do
|
||||
for j = 1, #LevelTiles[i] do
|
||||
if LevelTiles[i][j].id ~= 0 then
|
||||
|
||||
local depth = TileData[LevelTiles[i][j].id].depth
|
||||
DrawTile(
|
||||
LevelTiles[i][j],
|
||||
tileProperties.scale * j * tileProperties.width + tileProperties.scale * (levelProperties.offset.x - tileProperties.width) - Camera.pos.x,
|
||||
tileProperties.scale * i * tileProperties.height + tileProperties.scale * (levelProperties.offset.y - tileProperties.height) - Camera.pos.y,
|
||||
"foreground"
|
||||
)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GameworldDrawLighting()
|
||||
if game_resize then
|
||||
Canvas.Darkness:release()
|
||||
Canvas.Darkness = CreateDarkness()
|
||||
love.graphics.setCanvas(Canvas.Darkness)
|
||||
SetDarkness()
|
||||
love.graphics.setCanvas()
|
||||
end
|
||||
|
||||
-- work on lighting canvas
|
||||
love.graphics.setCanvas(Canvas.Darkness)
|
||||
SetDarkness()
|
||||
DoLights()
|
||||
DoBorder()
|
||||
-- apply to game canvas
|
||||
love.graphics.setColor(1,1,1,1)
|
||||
love.graphics.scale(game.scale,game.scale)
|
||||
love.graphics.setCanvas()
|
||||
DrawDarkness()
|
||||
love.graphics.scale(1/game.scale,1/game.scale)
|
||||
end
|
||||
@@ -1,30 +0,0 @@
|
||||
function HEX2RGB(color)
|
||||
local r1 = HEX2DEX(color:sub(2,2))
|
||||
local r2 = HEX2DEX(color:sub(3,3))
|
||||
local g1 = HEX2DEX(color:sub(4,4))
|
||||
local g2 = HEX2DEX(color:sub(5,5))
|
||||
local b1 = HEX2DEX(color:sub(6,6))
|
||||
local b2 = HEX2DEX(color:sub(7,7))
|
||||
|
||||
return {(r1*16 + r2)/255, (g1*16 + g2)/255, (b1*16 + b2)/255}
|
||||
end
|
||||
|
||||
function HEX2DEX(hex)
|
||||
if hex == "0" then return 0
|
||||
elseif hex == "1" then return 1
|
||||
elseif hex == "2" then return 2
|
||||
elseif hex == "3" then return 3
|
||||
elseif hex == "4" then return 4
|
||||
elseif hex == "5" then return 5
|
||||
elseif hex == "6" then return 6
|
||||
elseif hex == "7" then return 7
|
||||
elseif hex == "8" then return 8
|
||||
elseif hex == "9" then return 9
|
||||
elseif hex == "a" then return 10
|
||||
elseif hex == "b" then return 11
|
||||
elseif hex == "c" then return 12
|
||||
elseif hex == "d" then return 13
|
||||
elseif hex == "e" then return 14
|
||||
elseif hex == "f" then return 15
|
||||
end
|
||||
end
|
||||
@@ -1,87 +0,0 @@
|
||||
function ExportLevel(levelname, filename)
|
||||
os.execute( "mkdir \"./export\"" )
|
||||
filename = filename or "output.lua"
|
||||
filename = "export/"..filename
|
||||
exportFile = io.open(filename, "w+")
|
||||
|
||||
if exportFile then
|
||||
logPrint("Exporting level \"".. levelname .. "\"...")
|
||||
exportFile:write("return {")
|
||||
|
||||
logPrint("- level name")
|
||||
exportFile:write("\n name = \"" .. levelname .. "\",")
|
||||
|
||||
logPrint("- tileset")
|
||||
for k, v in pairs(tileset) do
|
||||
if v == LevelData.tileset then
|
||||
exportFile:write("\n tileset = tileset." .. k .. ",")
|
||||
end
|
||||
end
|
||||
|
||||
logPrint("- properties")
|
||||
exportFile:write("\n properties = {")
|
||||
exportFile:write("\n darkness = true")
|
||||
exportFile:write("\n },")
|
||||
|
||||
logPrint("- tiles")
|
||||
exportFile:write("\n tiles = {")
|
||||
local rows = #LevelTiles
|
||||
for i = 1, #LevelTiles do
|
||||
exportFile:write("\n { ")
|
||||
logPrint(" - Row "..i.."/"..rows.." "..math.floor(100*((i-1)*100/rows))/100 .."%")
|
||||
for j = 1, #LevelTiles[i] do
|
||||
if j ~= 1 then
|
||||
exportFile:write(", ")
|
||||
end
|
||||
exportFile:write(tostring(LevelTiles[i][j].id))
|
||||
end
|
||||
exportFile:write("}")
|
||||
if i ~= #LevelTiles then
|
||||
exportFile:write(", ")
|
||||
end
|
||||
end
|
||||
logPrint(" - All rows 100%")
|
||||
exportFile:write("\n },")
|
||||
|
||||
logPrint("- objects")
|
||||
exportFile:write("\n objects = {}")
|
||||
|
||||
logPrint("Exporting complete.")
|
||||
exportFile:write("\n}")
|
||||
exportFile:close()
|
||||
end
|
||||
end
|
||||
|
||||
-- Source https://stackoverflow.com/a/11130774
|
||||
function scandir(directory)
|
||||
local i, t, popen = 0, {}, io.popen
|
||||
local pfile = popen('ls "'..directory..'"')
|
||||
for filename in pfile:lines() do
|
||||
i = i + 1
|
||||
t[i] = filename
|
||||
end
|
||||
pfile:close()
|
||||
return t
|
||||
end
|
||||
|
||||
--[[
|
||||
return {
|
||||
name = "level1",
|
||||
tileset = tileset.library,
|
||||
tiles = {
|
||||
{13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13},
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 5,25,26, 6,25,26, 7, 0, 5,25,26, 7, 0, 0, 0, 0, 0, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 5,37,38, 6,37,38, 7, 0, 5,37,38, 7, 0, 0, 0, 0, 0, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 5,37,38, 6,37,38, 7, 0, 5,37,38, 7, 0, 0, 0, 0, 0, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 5,49,50, 6,49,50, 7, 0, 5,49,50, 7, 0, 0, 0, 0, 0, 0},
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
|
||||
},
|
||||
objects = {}
|
||||
}
|
||||
]]
|
||||
if logging then
|
||||
-- Make log stuff
|
||||
os.execute( "mkdir \"./logs\"" )
|
||||
logFile = io.open("logs/mothback_"..os.date("%Y-%m-%d_%H-%M-%S")..".log", "a+")
|
||||
end
|
||||
@@ -1,83 +0,0 @@
|
||||
Keybind = {}
|
||||
Keybind.move = {}
|
||||
Keybind.menu = {}
|
||||
Keybind.debug = {}
|
||||
Keybind.editor = {}
|
||||
Keybind.generic = {}
|
||||
|
||||
function Keybind:CheckDown(action)
|
||||
for _, keyname in pairs(action.keys) do
|
||||
if type(keyname) == "string" then
|
||||
if love.keyboard.isDown(keyname) then return true end
|
||||
else
|
||||
if love.mouse.isDown(keyname) then return true end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Keybind:HasPressed(action)
|
||||
if Keybind:CheckDown(action) then
|
||||
if not action.pressed then
|
||||
action.pressed = true
|
||||
return true
|
||||
end
|
||||
else
|
||||
action.pressed = nil
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Keybind:CheckCollision(cat, key)
|
||||
for _, action in pairs(cat) do
|
||||
for _, keyname in pairs(action.keys) do
|
||||
if key == keyname then return true end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Keybind:AddKey(action, key)
|
||||
table.insert(action.keys, key)
|
||||
end
|
||||
|
||||
function Keybind:ChangeKey(action, position, key)
|
||||
action.keys[position] = key
|
||||
end
|
||||
|
||||
function Keybind:RemoveKeys(action)
|
||||
action.keys = {}
|
||||
end
|
||||
|
||||
function Keybind:Default()
|
||||
--Menu
|
||||
Keybind.menu.pause= { keys = {"escape"}}
|
||||
Keybind.menu.confirm= { keys = {"z", "space", 1}}
|
||||
|
||||
--Move
|
||||
Keybind.move.left = { keys = {"left", "a"}}
|
||||
Keybind.move.right = { keys = {"right", "d"}}
|
||||
Keybind.move.up = { keys = {"up", "w"}}
|
||||
Keybind.move.down = { keys = {"down", "s"}}
|
||||
Keybind.move.jump = { keys = {"z", "space"}}
|
||||
Keybind.move.hook = { keys = {"x", 1}}
|
||||
Keybind.move.dash = { keys = {"c", 2}}
|
||||
|
||||
--Debug
|
||||
Keybind.debug.debug = { keys = {"f1"}}
|
||||
Keybind.debug.reposition = { keys = {"f2"}}
|
||||
Keybind.debug.reload = { keys = {"f3"}}
|
||||
Keybind.debug.editor = { keys = {"f4"}}
|
||||
|
||||
-- Editor
|
||||
Keybind.editor.palette = { keys = {"tab"}}
|
||||
|
||||
-- Generic
|
||||
Keybind.generic.lclick = { keys = {1}}
|
||||
Keybind.generic.rclick = { keys = {2}}
|
||||
Keybind.generic.lshift = { keys = {"lshift"}}
|
||||
Keybind.generic.lctrl = { keys = {"lctrl"}}
|
||||
end
|
||||
|
||||
-- Set default values at start
|
||||
Keybind:Default()
|
||||
@@ -1,741 +0,0 @@
|
||||
function LevelLoadTiles()
|
||||
|
||||
LevelData = dofile("data/levels/"..currLevel)
|
||||
|
||||
--[[
|
||||
on level format:
|
||||
|
||||
id = tile identifier
|
||||
depth = order in the render
|
||||
force = rendering other tile instead of the one in this position
|
||||
overlay = render another tile id or, if multiple tiles {id, id, id,}, choose at random
|
||||
overlay_depth = foreground/background overlay depth
|
||||
type = collision type
|
||||
]]
|
||||
LevelGetTileData()
|
||||
LevelTiles = LevelData.tiles
|
||||
LevelUpdateDimensions()
|
||||
LevelIndexTiles()
|
||||
TileCreateObjects()
|
||||
end
|
||||
|
||||
|
||||
function LevelExpandCanvas(horizontal,vertical)
|
||||
local horizontal = horizontal or 0
|
||||
local vertical = vertical or 0
|
||||
local h = LevelGetTileWidth()
|
||||
local v = LevelGetTileHeight()
|
||||
|
||||
-- get new canvas size
|
||||
local newCanvasH = h + math.abs(horizontal)
|
||||
local newCanvasV = v + math.abs(vertical)
|
||||
|
||||
-- lets make a new temporal canvas
|
||||
local ExpandedLevel = {}
|
||||
for i = 1, newCanvasV do
|
||||
ExpandedLevel[i] = {}
|
||||
for j = 1, newCanvasH do
|
||||
ExpandedLevel[i][j] = InstanceTile(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- lets guess how the new canvas and positions are offset
|
||||
local expand_h = 0
|
||||
if horizontal < 0 then
|
||||
expand_h = -horizontal
|
||||
end
|
||||
|
||||
local expand_v = 0
|
||||
if vertical < 0 then
|
||||
expand_v = -vertical
|
||||
end
|
||||
|
||||
-- get data from old canvas to new canvas
|
||||
for i = 1, #LevelTiles do
|
||||
for j = 1, #LevelTiles[i] do
|
||||
ExpandedLevel[i+expand_v][j+expand_h] = InstanceTile(LevelTiles[i][j].id)
|
||||
end
|
||||
end
|
||||
|
||||
-- use new canvas
|
||||
LevelTiles = ExpandedLevel
|
||||
end
|
||||
|
||||
|
||||
function LevelReduceCanvas(horizontal,vertical)
|
||||
local horizontal = horizontal or 0
|
||||
local vertical = vertical or 0
|
||||
local h = LevelGetTileWidth()
|
||||
local v = LevelGetTileHeight()
|
||||
|
||||
-- get new canvas size
|
||||
local newCanvasH = h - math.abs(horizontal)
|
||||
local newCanvasV = v - math.abs(vertical)
|
||||
|
||||
-- lets make a new temporal canvas
|
||||
local ExpandedLevel = {}
|
||||
for i = 1, newCanvasV do
|
||||
ExpandedLevel[i] = {}
|
||||
for j = 1, newCanvasH do
|
||||
ExpandedLevel[i][j] = InstanceTile(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- lets guess how the new canvas and positions are offset
|
||||
local expand_h = 0
|
||||
if horizontal < 0 then
|
||||
expand_h = -horizontal
|
||||
end
|
||||
|
||||
local expand_v = 0
|
||||
if vertical < 0 then
|
||||
expand_v = -vertical
|
||||
end
|
||||
|
||||
-- get data from old canvas to new canvas
|
||||
for i = 1, #ExpandedLevel do
|
||||
for j = 1, #ExpandedLevel[i] do
|
||||
ExpandedLevel[i][j] = InstanceTile(LevelTiles[i+expand_v][j+expand_h].id)
|
||||
end
|
||||
end
|
||||
|
||||
-- use new canvas
|
||||
LevelTiles = ExpandedLevel
|
||||
|
||||
LevelExpandCanvas()
|
||||
end
|
||||
|
||||
function LevelGetTileData()
|
||||
for k, v in pairs(tileset) do
|
||||
if v == LevelData.tileset then
|
||||
TileData = dofile("data/tileset/"..k..".lua")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function LevelReloadTiles()
|
||||
LevelUpdateDimensions()
|
||||
end
|
||||
|
||||
function LevelUpdateDimensions()
|
||||
LevelData.Width = LevelGetWidth()
|
||||
LevelData.Height = LevelGetHeight()
|
||||
end
|
||||
|
||||
function LevelGetTileHeight()
|
||||
return #LevelTiles
|
||||
end
|
||||
|
||||
function LevelGetTileWidth()
|
||||
local width = 0
|
||||
for i = 1, #LevelTiles do
|
||||
if width < #LevelTiles[i] then width = #LevelTiles[i] end
|
||||
end
|
||||
return width
|
||||
end
|
||||
|
||||
function LevelGetHeight()
|
||||
return LevelGetTileHeight() * tileProperties.height
|
||||
end
|
||||
|
||||
function LevelGetWidth()
|
||||
return LevelGetTileWidth() * tileProperties.width
|
||||
end
|
||||
|
||||
function LevelIndexTiles()
|
||||
TileIndex = {}
|
||||
|
||||
-- index from tileset
|
||||
local width = LevelData.tileset:getPixelWidth()/tileProperties.width
|
||||
local height = LevelData.tileset:getPixelHeight()/tileProperties.height
|
||||
for i = 0, height do
|
||||
for j = 0, width do
|
||||
TileIndex[i*width+j+1] = love.graphics.newQuad(
|
||||
j*tileProperties.width,
|
||||
i*tileProperties.height,
|
||||
tileProperties.width,
|
||||
tileProperties.height,
|
||||
LevelData.tileset:getDimensions()
|
||||
)
|
||||
end
|
||||
end
|
||||
TileDataInitialize()
|
||||
|
||||
-- instance level tiles according to the Properties
|
||||
for i = 1, #LevelTiles do
|
||||
for j = 1, #LevelTiles[i] do
|
||||
SetTile(i,j,LevelTiles[i][j])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TileDataInitialize()
|
||||
for _, Properties in pairs(TileData) do
|
||||
if Properties.animation ~= nil then
|
||||
Properties.tileset = love.graphics.newImage("assets/terrain/"..Properties.animation..".png")
|
||||
Properties.imgs = {}
|
||||
Properties.current_image = 1
|
||||
Properties.current_subimage = 1
|
||||
|
||||
local tileset = Properties.tileset
|
||||
local width = tileset:getPixelWidth()/tileProperties.width
|
||||
local height = tileset:getPixelHeight()/tileProperties.height
|
||||
local image_count = 0
|
||||
|
||||
for i = 0, height-1 do
|
||||
for j = 0, width-1 do
|
||||
local quad =
|
||||
love.graphics.newQuad(
|
||||
j*tileProperties.width,
|
||||
i*tileProperties.height,
|
||||
tileProperties.width,
|
||||
tileProperties.height,
|
||||
tileset:getDimensions()
|
||||
)
|
||||
image_count = image_count + 1
|
||||
|
||||
table.insert(Properties.imgs,quad)
|
||||
end
|
||||
end
|
||||
Properties.image_count = image_count
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function InstanceTile(id)
|
||||
local tile = {}
|
||||
|
||||
tile.id = id
|
||||
local Properties = TileData[tile.id]
|
||||
|
||||
if Properties ~= nil then
|
||||
if type(Properties.overlay) == "table" then
|
||||
tile.display_overlay = Properties.overlay[math.random(#Properties.overlay)]
|
||||
else
|
||||
tile.display_overlay = Properties.overlay
|
||||
end
|
||||
|
||||
if type(Properties.force) == "table" then
|
||||
tile.display = Properties.force[math.random(#Properties.force)]
|
||||
else
|
||||
tile.display = Properties.force
|
||||
end
|
||||
end
|
||||
|
||||
return tile
|
||||
end
|
||||
|
||||
function SetTile(i,j,id)
|
||||
LevelTiles[i][j] = InstanceTile(id)
|
||||
end
|
||||
|
||||
function GridDisplay()
|
||||
for i = 1, #LevelTiles do
|
||||
for j = 1, #LevelTiles[i] do
|
||||
love.graphics.rectangle(
|
||||
"line",
|
||||
tileProperties.scale * (j * tileProperties.width + (levelProperties.offset.x - tileProperties.width)) - Camera.pos.x,
|
||||
tileProperties.scale * (i * tileProperties.height + (levelProperties.offset.y - tileProperties.height)) - Camera.pos.y,
|
||||
tileProperties.scale * tileProperties.width,
|
||||
tileProperties.scale * tileProperties.height
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TileOptimizeObjects()
|
||||
logPrint("Optimizing Objects...")
|
||||
local unoptimized = 0
|
||||
local isTileOptimized = {}
|
||||
|
||||
for i = 1, #LevelTiles do
|
||||
isTileOptimized[i] = {}
|
||||
for j= 1, #LevelTiles[i] do
|
||||
isTileOptimized[i][j] = false
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, #LevelTiles do
|
||||
for j = 1, #LevelTiles[i] do
|
||||
if LevelTiles[i][j].id ~= 0 then
|
||||
local type = TileData[LevelTiles[i][j].id].type
|
||||
|
||||
if type == "whole" and not isTileOptimized[i][j] then
|
||||
|
||||
isTileOptimized[i][j] = true
|
||||
|
||||
local n = 1
|
||||
local check = true
|
||||
while check do
|
||||
check = false
|
||||
if LevelTiles[i][j+n] ~= nil
|
||||
and TileData[LevelTiles[i][j+n].id] ~= nil
|
||||
then
|
||||
local type_check = TileData[LevelTiles[i][j+n].id].type
|
||||
if type_check == "whole"
|
||||
and not isTileOptimized[i][j+n]
|
||||
then
|
||||
check = true
|
||||
isTileOptimized[i][j+n] = true
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local m = 1
|
||||
local check = true
|
||||
while check do
|
||||
check = false
|
||||
local checkline = true
|
||||
for l = 0, n-1 do
|
||||
checkline = false
|
||||
if LevelTiles[i+m] ~= nil
|
||||
and LevelTiles[i+m][j+l] ~= nil
|
||||
and TileData[LevelTiles[i+m][j+l].id] ~= nil
|
||||
then
|
||||
local type_check = TileData[LevelTiles[i+m][j+l].id].type
|
||||
if type_check == "whole"
|
||||
and not isTileOptimized[i+m][j+l]
|
||||
then
|
||||
checkline = true
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if checkline then
|
||||
check = true
|
||||
for l = 0, n-1 do
|
||||
isTileOptimized[i+m][j+l] = true
|
||||
end
|
||||
m = m + 1
|
||||
else
|
||||
check = false
|
||||
end
|
||||
end
|
||||
|
||||
logPrint("- Group size: "..m.."x"..n)
|
||||
unoptimized = unoptimized + m * n
|
||||
local base_x = tileProperties.scale * j * tileProperties.width + tileProperties.scale * (levelProperties.offset.x - tileProperties.height)
|
||||
local base_y = tileProperties.scale * i * tileProperties.height + tileProperties.scale * (levelProperties.offset.y - tileProperties.height)
|
||||
|
||||
local col = Collision:New(
|
||||
base_x,
|
||||
base_y,
|
||||
base_x + tileProperties.width * tileProperties.scale * n,
|
||||
base_y + tileProperties.height * tileProperties.scale * m
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,col)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
logPrint("collisions optimized from " .. unoptimized .. " to " .. #LoadedObjects.Collisions)
|
||||
end
|
||||
|
||||
function TileCreateObjects()
|
||||
LoadedObjects.Collisions = {}
|
||||
LoadedObjects.Platforms = {}
|
||||
LoadedObjects.Ladders = {}
|
||||
LoadedObjects.Hazards = {}
|
||||
|
||||
TileOptimizeObjects()
|
||||
|
||||
for i = 1, #LevelTiles do
|
||||
for j = 1, #LevelTiles[i] do
|
||||
if LevelTiles[i][j].id ~= 0 then
|
||||
|
||||
local type = TileData[LevelTiles[i][j].id].type
|
||||
local light = TileData[LevelTiles[i][j].id].light
|
||||
local base_x = tileProperties.scale * j * tileProperties.width + tileProperties.scale * (levelProperties.offset.x - tileProperties.height)
|
||||
local base_y = tileProperties.scale * i * tileProperties.height + tileProperties.scale * (levelProperties.offset.y - tileProperties.height)
|
||||
|
||||
|
||||
if light ~= 0 and light ~= nil then
|
||||
CreateLight(
|
||||
base_x + tileProperties.width/2 * tileProperties.scale,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale,
|
||||
light
|
||||
)
|
||||
end
|
||||
|
||||
-- wholes are handled in optimization now
|
||||
--[[if type == "whole" then
|
||||
local col = Collision:New(
|
||||
base_x,
|
||||
base_y,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,col)
|
||||
else]]if type == "half_bottom" then
|
||||
|
||||
local col = Collision:New(
|
||||
base_x,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,col)
|
||||
|
||||
elseif type == "half_top" then
|
||||
|
||||
local col = Collision:New(
|
||||
base_x,
|
||||
base_y ,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,col)
|
||||
|
||||
elseif type == "half_right" then
|
||||
|
||||
local col = Collision:New(
|
||||
base_x + tileProperties.height/2 * tileProperties.scale,
|
||||
base_y,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,col)
|
||||
|
||||
elseif type == "half_left" then
|
||||
|
||||
local col = Collision:New(
|
||||
base_x,
|
||||
base_y,
|
||||
base_x + tileProperties.height/2 * tileProperties.scale,
|
||||
base_y + tileProperties.height * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,col)
|
||||
|
||||
elseif type == "platform" then
|
||||
local plat = Collision:New(
|
||||
base_x,
|
||||
base_y + tileProperties.scale * 2,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height/4 * tileProperties.scale + tileProperties.scale * 2
|
||||
)
|
||||
table.insert(LoadedObjects.Platforms,plat)
|
||||
|
||||
elseif type == "ramp2_bot_left_whole" then
|
||||
for k = 1, 8 do
|
||||
-- do ramp owo
|
||||
local slope = Collision:New(
|
||||
base_x,
|
||||
base_y + k * tileProperties.scale - tileProperties.scale,
|
||||
base_x + k * 2 * tileProperties.scale,
|
||||
base_y + k * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,slope)
|
||||
|
||||
end
|
||||
-- fill lower half
|
||||
local col = Collision:New(
|
||||
base_x,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,col)
|
||||
|
||||
elseif type == "ramp2_bot_left_half" then
|
||||
for k = 1, 8 do
|
||||
-- do ramp owo
|
||||
local slope = Collision:New(
|
||||
base_x,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale + k * tileProperties.scale - tileProperties.scale,
|
||||
base_x + k * 2 * tileProperties.scale,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale + k * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,slope)
|
||||
|
||||
end
|
||||
|
||||
elseif type == "ramp2_top_left_whole" then
|
||||
for k = 1, 8 do
|
||||
-- do ramp owo
|
||||
local slope = Collision:New(
|
||||
base_x,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale - tileProperties.scale + k * tileProperties.scale,
|
||||
base_x + tileProperties.width * tileProperties.scale - (k-1) * 2 * tileProperties.scale,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale - tileProperties.scale + k * tileProperties.scale + tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,slope)
|
||||
|
||||
end
|
||||
-- fill higher half
|
||||
local col = Collision:New(
|
||||
base_x,
|
||||
base_y,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,col)
|
||||
|
||||
elseif type == "ramp2_top_left_half" then
|
||||
for k = 1, 8 do
|
||||
-- do ramp owo
|
||||
local slope = Collision:New(
|
||||
base_x,
|
||||
base_y - tileProperties.scale + k * tileProperties.scale,
|
||||
base_x + tileProperties.width * tileProperties.scale - (k-1) * 2 * tileProperties.scale,
|
||||
base_y - tileProperties.scale + k * tileProperties.scale + tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,slope)
|
||||
|
||||
end
|
||||
|
||||
elseif type == "ramp2_bot_right_whole" then
|
||||
for k = 1, 8 do
|
||||
-- do ramp owo
|
||||
local slope = Collision:New(
|
||||
base_x + (k-8) * -2 * tileProperties.scale,
|
||||
base_y - tileProperties.scale + k * tileProperties.scale,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y - tileProperties.scale + k * tileProperties.scale + tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,slope)
|
||||
|
||||
end
|
||||
-- fill lower half
|
||||
local col = Collision:New(
|
||||
base_x,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,col)
|
||||
|
||||
elseif type == "ramp2_bot_right_half" then
|
||||
for k = 1, 8 do
|
||||
-- do ramp owo
|
||||
local slope = Collision:New(
|
||||
base_x + (k-8) * -2 * tileProperties.scale,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale - tileProperties.scale + k * tileProperties.scale,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale - tileProperties.scale + k * tileProperties.scale + tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,slope)
|
||||
|
||||
end
|
||||
|
||||
elseif type == "ramp2_top_right_half" then
|
||||
for k = 1, 8 do
|
||||
-- do ramp owo
|
||||
local slope = Collision:New(
|
||||
base_x + (k-8) * -2 * tileProperties.scale,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale - k * tileProperties.scale,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale - k * tileProperties.scale + tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,slope)
|
||||
|
||||
end
|
||||
|
||||
elseif type == "ramp2_top_right_whole" then
|
||||
for k = 1, 8 do
|
||||
-- do ramp owo
|
||||
local slope = Collision:New(
|
||||
base_x + (k-8) * -2 * tileProperties.scale,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale + tileProperties.height/2 * tileProperties.scale - k * tileProperties.scale,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale + tileProperties.height/2 * tileProperties.scale - k * tileProperties.scale + tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,slope)
|
||||
|
||||
end
|
||||
-- fill higher half
|
||||
local col = Collision:New(
|
||||
base_x,
|
||||
base_y,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height/2 * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,col)
|
||||
|
||||
elseif type == "ramp1_bot_left" then
|
||||
|
||||
for k = 1, 16 do
|
||||
-- do ramp owo
|
||||
local slope = Collision:New(
|
||||
base_x,
|
||||
base_y + k * tileProperties.scale - tileProperties.scale,
|
||||
base_x + k * tileProperties.scale,
|
||||
base_y + k * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Collisions,slope)
|
||||
|
||||
end
|
||||
|
||||
elseif type == "ladder_right" then
|
||||
|
||||
local ladder = Collision:New(
|
||||
base_x + (tileProperties.width-4)* tileProperties.scale,
|
||||
base_y,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Ladders,ladder)
|
||||
|
||||
elseif type == "ladder_platform_right" then
|
||||
|
||||
local ladder = Collision:New(
|
||||
base_x + (tileProperties.width-4)* tileProperties.scale,
|
||||
base_y + tileProperties.scale * 2,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Ladders,ladder)
|
||||
|
||||
local plat = Collision:New(
|
||||
base_x,
|
||||
base_y + tileProperties.scale * 2,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height/4 * tileProperties.scale + tileProperties.scale * 2
|
||||
)
|
||||
table.insert(LoadedObjects.Platforms,plat)
|
||||
|
||||
elseif type == "ladder_left" then
|
||||
|
||||
|
||||
local ladder = Collision:New(
|
||||
base_x,
|
||||
base_y,
|
||||
base_x + tileProperties.scale * 4,
|
||||
base_y + tileProperties.height * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Ladders,ladder)
|
||||
|
||||
elseif type == "ladder_platform_left" then
|
||||
|
||||
|
||||
local ladder = Collision:New(
|
||||
base_x,
|
||||
base_y + tileProperties.scale * 2,
|
||||
base_x + tileProperties.scale * 4,
|
||||
base_y + tileProperties.height * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Ladders,ladder)
|
||||
|
||||
local plat = Collision:New(
|
||||
base_x,
|
||||
base_y + tileProperties.scale * 2,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height/4 * tileProperties.scale + tileProperties.scale * 2
|
||||
)
|
||||
table.insert(LoadedObjects.Platforms,plat)
|
||||
|
||||
elseif type == "bottom_hazard" then
|
||||
|
||||
|
||||
local hazard = Collision:New(
|
||||
base_x,
|
||||
base_y + tileProperties.height * 12/16 * tileProperties.scale,
|
||||
base_x + tileProperties.width * tileProperties.scale,
|
||||
base_y + tileProperties.height * tileProperties.scale
|
||||
)
|
||||
table.insert(LoadedObjects.Hazards,hazard)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AnimateTiles()
|
||||
for _, Properties in pairs(TileData) do
|
||||
if Properties ~= nil then
|
||||
if Properties.animation ~= nil then
|
||||
-- calculate subimage
|
||||
Properties.current_subimage = Properties.current_subimage + current_dt
|
||||
-- cycle image
|
||||
if Properties.current_subimage >= Properties.delay then
|
||||
Properties.current_subimage = Properties.current_subimage - Properties.delay
|
||||
Properties.current_image = Properties.current_image + 1
|
||||
end
|
||||
|
||||
if Properties.current_image > Properties.image_count then
|
||||
Properties.current_image = Properties.current_image - Properties.image_count
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DrawTile(tile,x,y,depth)
|
||||
local Properties = TileData[tile.id]
|
||||
|
||||
if Properties ~= nil then
|
||||
if Properties.animation ~= nil then
|
||||
if Properties.imgs[Properties.current_image] ~= nil
|
||||
and Properties.depth == depth
|
||||
then love.graphics.draw(
|
||||
Properties.tileset,
|
||||
Properties.imgs[Properties.current_image],
|
||||
x,
|
||||
y,
|
||||
0,
|
||||
tileProperties.scale,
|
||||
tileProperties.scale
|
||||
)
|
||||
end
|
||||
elseif Properties.depth == depth then
|
||||
if Properties.force ~= nil then
|
||||
if Properties.force ~= 0 then
|
||||
love.graphics.draw(
|
||||
LevelData.tileset,
|
||||
TileIndex[tile.display],
|
||||
x,
|
||||
y,
|
||||
0,
|
||||
tileProperties.scale,
|
||||
tileProperties.scale
|
||||
)
|
||||
end
|
||||
else
|
||||
love.graphics.draw(
|
||||
LevelData.tileset,
|
||||
TileIndex[tile.id],
|
||||
x,
|
||||
y,
|
||||
0,
|
||||
tileProperties.scale,
|
||||
tileProperties.scale
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
if Properties.overlay ~= nil then
|
||||
if Properties.overlay_depth == depth or Properties.overlay_depth == nil and Properties.depth == depth then
|
||||
if Properties.overlay_animated then
|
||||
local overlay_properties = TileData[Properties.overlay]
|
||||
love.graphics.draw(
|
||||
overlay_properties.tileset,
|
||||
overlay_properties.imgs[overlay_properties.current_image],
|
||||
x,
|
||||
y,
|
||||
0,
|
||||
tileProperties.scale,
|
||||
tileProperties.scale
|
||||
)
|
||||
else
|
||||
love.graphics.draw(
|
||||
LevelData.tileset,
|
||||
TileIndex[tile.display_overlay],
|
||||
x,
|
||||
y,
|
||||
0,
|
||||
tileProperties.scale,
|
||||
tileProperties.scale
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
--[[
|
||||
love.graphics.setColor(0,0,1)
|
||||
love.graphics.print(tostring(tile.display),x+16,y)
|
||||
love.graphics.setColor(1,1,1)
|
||||
]]
|
||||
end
|
||||
end
|
||||
@@ -1,133 +0,0 @@
|
||||
Lights = {}
|
||||
LightTimer = 0
|
||||
|
||||
function CreateDarkness()
|
||||
return love.graphics.newCanvas(game.width/game.scale, game.height/game.scale)
|
||||
end
|
||||
|
||||
function CreateLight(x,y,range,flicker,color,lum)
|
||||
local o = {}
|
||||
o.pos = {
|
||||
x = x,
|
||||
y = y
|
||||
}
|
||||
o.range = range
|
||||
o.lum = lum or 1
|
||||
o.color = color or {1,1,1}
|
||||
o.flicker_value = flicker or 2
|
||||
o.flicker = 0
|
||||
o.dim = 0
|
||||
o.flicker_speed = flicker_speed or 60/12
|
||||
o.flicker_time = 0
|
||||
|
||||
table.insert(Lights,o)
|
||||
o.id = #Lights
|
||||
return o
|
||||
end
|
||||
|
||||
function KillLight(light)
|
||||
if light.id ~= nil then
|
||||
for _, e in pairs(Lights) do
|
||||
if e.id > light.id then
|
||||
e.id = e.id - 1
|
||||
end
|
||||
end
|
||||
table.remove(Lights,light.id)
|
||||
end
|
||||
light = nil
|
||||
end
|
||||
|
||||
function SetDarkness()
|
||||
love.graphics.setCanvas(Canvas.Darkness)
|
||||
|
||||
love.graphics.setColor(0,0,0,1)
|
||||
love.graphics.rectangle("fill",0,0,game.width ,game.height)
|
||||
|
||||
love.graphics.setCanvas()
|
||||
end
|
||||
|
||||
function DoLights()
|
||||
|
||||
love.graphics.setCanvas(Canvas.Darkness)
|
||||
|
||||
for _, light in pairs(Lights) do
|
||||
light.flicker_time = light.flicker_time + 1
|
||||
|
||||
if light.flicker_time >= light.flicker_speed then
|
||||
light.flicker_time = light.flicker_time - light.flicker_speed
|
||||
light.flicker = 0 + math.random(0,1)
|
||||
light.flicker = math.min(math.max(light.flicker, -light.flicker_value),light.flicker_value)
|
||||
end
|
||||
end
|
||||
|
||||
love.graphics.setBlendMode("replace")
|
||||
for _, light in pairs(Lights) do
|
||||
if light.range ~= 0 then
|
||||
love.graphics.setColor(light.color[1],light.color[2],light.color[3],1)
|
||||
local position = {
|
||||
x = (light.pos.x - Camera.pos.x) / game.scale,
|
||||
y = (light.pos.y - Camera.pos.y) / game.scale
|
||||
}
|
||||
local range = (1 + light.range + light.flicker) / game.scale
|
||||
love.graphics.circle(
|
||||
"fill",
|
||||
position.x,
|
||||
position.y,
|
||||
range
|
||||
)
|
||||
end
|
||||
end
|
||||
love.graphics.setColor(0,0,0,0)
|
||||
for _, light in pairs(Lights) do
|
||||
if light.range ~= 0 then
|
||||
local position = {
|
||||
x = (light.pos.x - Camera.pos.x) / game.scale,
|
||||
y = (light.pos.y - Camera.pos.y) / game.scale
|
||||
}
|
||||
local range = (light.range + light.flicker) / game.scale
|
||||
love.graphics.circle(
|
||||
"fill",
|
||||
position.x,
|
||||
position.y,
|
||||
range
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
love.graphics.setBlendMode("alpha")
|
||||
love.graphics.setColor(0,0,0,1)
|
||||
Shaders.InsideLight:send("game_scale", game.scale)
|
||||
|
||||
for _, light in pairs(Lights) do
|
||||
if light.range ~= 0 then
|
||||
local position = {
|
||||
x = (light.pos.x - Camera.pos.x) / game.scale,
|
||||
y = (light.pos.y - Camera.pos.y) / game.scale
|
||||
}
|
||||
local range = (light.range + light.flicker) / game.scale
|
||||
Shaders.InsideLight:send("light_color", light.color)
|
||||
Shaders.InsideLight:send("light_pos", {position.x*game.scale, position.y*game.scale})
|
||||
Shaders.InsideLight:send("range", range)
|
||||
love.graphics.setShader(Shaders.InsideLight)
|
||||
love.graphics.circle(
|
||||
"fill",
|
||||
position.x,
|
||||
position.y,
|
||||
range
|
||||
)
|
||||
love.graphics.setShader()
|
||||
end
|
||||
end
|
||||
|
||||
love.graphics.setCanvas()
|
||||
|
||||
end
|
||||
|
||||
function DoBorder()
|
||||
love.graphics.setCanvas(Canvas.Darkness)
|
||||
love.graphics.setCanvas()
|
||||
end
|
||||
|
||||
function DrawDarkness()
|
||||
love.graphics.draw(Canvas.Darkness, 0, 0, 0, 1/game.scale)
|
||||
end
|
||||
@@ -1,5 +0,0 @@
|
||||
function LocaleLoad(ISO639)
|
||||
local ISO639 = ISO639 or "ENG"
|
||||
dofile("data/locale/"..ISO639..".lua")
|
||||
dofile("data/dialog_sequences.lua")
|
||||
end
|
||||
@@ -1,27 +0,0 @@
|
||||
function math.sign(x)
|
||||
if x<0 then
|
||||
return -1
|
||||
elseif x>0 then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
function Vector(init_x, init_y, final_x, final_y)
|
||||
local distance_x = final_x - init_x
|
||||
local distance_y = final_y - init_y
|
||||
return {distance_x, distance_y}
|
||||
end
|
||||
|
||||
function GetVectorValue(vector)
|
||||
return math.sqrt(vector[1] ^ 2 + vector[2] ^ 2)
|
||||
end
|
||||
|
||||
function GetAngleFromVector(x,y)
|
||||
local reduce = 0
|
||||
if x < 0 then
|
||||
reduce = math.rad(180)
|
||||
end
|
||||
return math.atan(y/x) - reduce
|
||||
end
|
||||
@@ -1,146 +0,0 @@
|
||||
function MenuDraw(menu)
|
||||
local font = love.graphics.getFont()
|
||||
love.graphics.setFont(LocaleFont)
|
||||
-- Set scale to 1
|
||||
love.graphics.scale(0.5,0.5)
|
||||
|
||||
if menu == "pause" then
|
||||
MenuDrawPauseScreen()
|
||||
elseif menu == "dialog" then
|
||||
MenuDrawDialog()
|
||||
end
|
||||
|
||||
for _, element in pairs(UIElement) do
|
||||
element:Draw()
|
||||
end
|
||||
-- Reset scale
|
||||
love.graphics.scale(2,2)
|
||||
love.graphics.setFont(font)
|
||||
end
|
||||
|
||||
function MenuDrawPauseScreen()
|
||||
-- Parameters
|
||||
local pauseWidth = 640
|
||||
local pauseHeight = 480
|
||||
local pauseX = (game.width/2)-(pauseWidth/2)
|
||||
local pauseY = (game.height/2)-(pauseHeight/2)
|
||||
local mouse_x, mouse_y = love.mouse.getPosition()
|
||||
-- Base items
|
||||
love.graphics.setColor(0,0,0,0.3)
|
||||
love.graphics.rectangle("fill", 0, 0, game.width, game.height)
|
||||
love.graphics.setColor(1,1,1,1)
|
||||
love.graphics.rectangle("fill", pauseX, pauseY, pauseWidth, pauseHeight)
|
||||
end
|
||||
|
||||
function MenuDrawDialog()
|
||||
end
|
||||
|
||||
function MenuStep(menu)
|
||||
-- first get mouse
|
||||
local mouse_x, mouse_y = love.mouse.getPosition()
|
||||
for _, element in pairs(UIElement) do
|
||||
if element.type == "Button" then
|
||||
element:checkMouse(mouse_x, mouse_y)
|
||||
elseif element.type == "Dialog" then
|
||||
element:checkConfirm()
|
||||
end
|
||||
end
|
||||
if menu == 0 then
|
||||
elseif menu == "pause" then
|
||||
MenuStepPauseScreen()
|
||||
elseif menu == "dialog" then
|
||||
MenuStepDialog()
|
||||
end
|
||||
end
|
||||
|
||||
function MenuStepPauseScreen()
|
||||
if PauseResume:getVariable() == true then
|
||||
PauseResume = nil
|
||||
PauseOptions = nil
|
||||
PauseExit = nil
|
||||
MenuExit()
|
||||
elseif PauseExit:getVariable() == true then
|
||||
love.event.quit()
|
||||
end
|
||||
end
|
||||
|
||||
function MenuStepDialog()
|
||||
if DialogContainer.value >= DialogContainer.target_value then
|
||||
DialogContainer = nil
|
||||
MenuExit()
|
||||
end
|
||||
end
|
||||
|
||||
function MenuClear()
|
||||
for _, element in pairs(UIElement) do
|
||||
element = nil
|
||||
end
|
||||
UIElement = {}
|
||||
end
|
||||
|
||||
function MenuExit(to)
|
||||
MenuClear()
|
||||
local to = to or "no"
|
||||
menu_type = to
|
||||
end
|
||||
|
||||
function MenuInit(menu,parameter)
|
||||
-- main menu
|
||||
if menu == "pause" then
|
||||
MenuInitPauseScreen()
|
||||
elseif menu == "dialog" then
|
||||
if parameter == nil then
|
||||
parameter = DialogSequence.Example
|
||||
end
|
||||
MenuInitDialog(parameter)
|
||||
end
|
||||
end
|
||||
|
||||
function MenuInitDialog(parameter)
|
||||
DialogContainer = interfaceDialog:New()
|
||||
DialogContainer:loadSequence(parameter)
|
||||
end
|
||||
|
||||
function MenuInitPauseScreen()
|
||||
local buttonStandard = {width = 200, height = 30, separation = 10}
|
||||
-- elements
|
||||
PauseResume = interfaceButton:New(
|
||||
game.width/2,
|
||||
game.height/2-buttonStandard.height-buttonStandard.separation,
|
||||
buttonStandard.width,
|
||||
buttonStandard.height,
|
||||
{false,true},
|
||||
1,
|
||||
{
|
||||
text = Locale.ui.pause_screen_resume,
|
||||
color = {0,0,0.5},
|
||||
color2 = {1,1,1}
|
||||
}
|
||||
)
|
||||
PauseOptions = interfaceButton:New(
|
||||
game.width/2,
|
||||
game.height/2,
|
||||
buttonStandard.width,
|
||||
buttonStandard.height,
|
||||
{false,true},
|
||||
1,
|
||||
{
|
||||
text = Locale.ui.pause_screen_options,
|
||||
color = {0,0,0.5},
|
||||
color2 = {1,1,1}
|
||||
}
|
||||
)
|
||||
PauseExit = interfaceButton:New(
|
||||
game.width/2,
|
||||
game.height/2+buttonStandard.height+buttonStandard.separation,
|
||||
buttonStandard.width,
|
||||
buttonStandard.height,
|
||||
{false,true},
|
||||
1,
|
||||
{
|
||||
text = Locale.ui.pause_screen_exit,
|
||||
color = {0,0,0.5},
|
||||
color2 = {1,1,1}
|
||||
}
|
||||
)
|
||||
end
|
||||
@@ -1,88 +0,0 @@
|
||||
LoadedObjects = {
|
||||
Entities = {},
|
||||
|
||||
Collisions = {},
|
||||
Platforms = {},
|
||||
Ladders = {},
|
||||
Hazards = {}
|
||||
}
|
||||
|
||||
-- level functions
|
||||
function LoadedObjects.DrawCollisions()
|
||||
for _, collision in pairs(LoadedObjects.Collisions) do
|
||||
collision:Draw(1)
|
||||
end
|
||||
|
||||
for _, platform in pairs(LoadedObjects.Platforms) do
|
||||
if platform.disable == true then platform:Draw(2) end
|
||||
if platform.disable == false then platform:Draw(1) end
|
||||
end
|
||||
|
||||
for _, ladder in pairs(LoadedObjects.Ladders) do
|
||||
ladder:Draw(2)
|
||||
end
|
||||
|
||||
for _, hazard in pairs(LoadedObjects.Hazards) do
|
||||
hazard:Draw(1)
|
||||
end
|
||||
end
|
||||
|
||||
-- returns true if theres a collision at that point
|
||||
function isThereObjectAt(x,y,objectType)
|
||||
for _, collision in pairs(objectType) do
|
||||
if collision.disable then
|
||||
-- Dont calculate if dissabled
|
||||
elseif x >= collision.from.x
|
||||
and x <= collision.to.x
|
||||
and y >= collision.from.y
|
||||
and y <= collision.to.y then
|
||||
collision.isColliding = true
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function isThereAnyCollisionAt(x,y)
|
||||
local Check = {
|
||||
LoadedObjects.Collisions,
|
||||
LoadedObjects.Ladders,
|
||||
LoadedObjects.Platforms
|
||||
}
|
||||
for _, type in pairs(Check) do
|
||||
local result = isThereObjectAt(x,y,type)
|
||||
if result then
|
||||
return result
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- flags
|
||||
function SetCollisionFlags()
|
||||
local Check = {
|
||||
LoadedObjects.Collisions,
|
||||
LoadedObjects.Ladders,
|
||||
LoadedObjects.Platforms,
|
||||
LoadedObjects.Hazards
|
||||
}
|
||||
for _, type in pairs(Check) do
|
||||
for _, object in pairs(type) do
|
||||
object.isColliding = false
|
||||
end
|
||||
end
|
||||
for _, platform in pairs(LoadedObjects.Platforms) do
|
||||
if main_Player.pos.y < platform.from.y then
|
||||
platform.disable = false
|
||||
else
|
||||
platform.disable = true
|
||||
end
|
||||
end
|
||||
for _, platform in pairs(LoadedObjects.Hazards) do
|
||||
if main_Player.isOnGround then
|
||||
platform.disable = true
|
||||
else
|
||||
platform.disable = false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,82 +0,0 @@
|
||||
Particle = Entity:New(x,y)
|
||||
|
||||
function Particle:New(x,y,particle_data)
|
||||
local o = Entity:New(x,y)
|
||||
|
||||
o.pos = {x = x, y = y}
|
||||
|
||||
|
||||
o.speed = particle_data.speed or 0
|
||||
o.direction = particle_data.direction or o.direction
|
||||
o.sprite_rotation = particle_data.sprite_rotation or o.sprite_rotation
|
||||
o.sprite_offset = particle_data.sprite_offset or o.sprite_offset
|
||||
o.sprite_scale = particle_data.sprite_scale or o.sprite_scale
|
||||
o.sprite_tint = particle_data.sprite_tint or o.sprite_tint
|
||||
o.sprite_alpha = particle_data.sprite_alpha or o.sprite_alpha
|
||||
o.sprite_alpha_base = o.sprite_alpha
|
||||
|
||||
o.sprite_flip = particle_data.sprite_flip or o.sprite_flip
|
||||
o.animation_active = particle_data.animation_active or false
|
||||
|
||||
o.time = 0.5
|
||||
o.timer = 0
|
||||
|
||||
o.vel = {
|
||||
x = o.speed * math.cos(o.direction),
|
||||
y = o.speed * math.sin(o.direction)
|
||||
}
|
||||
|
||||
if particle_data.light ~= nil then
|
||||
o.lightRange = particle_data.light
|
||||
o.light = CreateLight(o.pos.x,o.pos.y,o.lightRange)
|
||||
end
|
||||
|
||||
-- animations
|
||||
o.body = Animation:New(particle_data.animation)
|
||||
o:centerOffset(o.body)
|
||||
if not o.animation_active then
|
||||
o.body.speed = 0
|
||||
end
|
||||
|
||||
table.insert(LoadedParticles,o)
|
||||
o.id = #LoadedParticles
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
function Particle:Kill()
|
||||
if self.light ~= nil then
|
||||
KillLight(self.light)
|
||||
end
|
||||
if self.id ~= nil then
|
||||
for _, e in pairs(LoadedParticles) do
|
||||
if e.id > self.id then
|
||||
e.id = e.id - 1
|
||||
end
|
||||
end
|
||||
table.remove(LoadedParticles,self.id)
|
||||
end
|
||||
self = nil
|
||||
end
|
||||
|
||||
function Particle:HandleAnimation()
|
||||
self.body:Animate()
|
||||
self.timer = self.timer + current_dt
|
||||
self.sprite_alpha = self.sprite_alpha_base*(self.time-self.timer)/self.time
|
||||
if self.light ~= nil then
|
||||
self.light.range = self.lightRange * self.sprite_alpha/2
|
||||
end
|
||||
if self.sprite_alpha < 0 then self:Kill() end
|
||||
self:Draw(self.body)
|
||||
end
|
||||
|
||||
function Particle:DoPhysics()
|
||||
if not self:isCollidingAt(self.pos.x + self.vel.x, self.pos.y, objects.collisions) then
|
||||
self.pos.x = self.pos.x + self.vel.x
|
||||
end
|
||||
if not self:isCollidingAt(self.pos.x, self.pos.y + self.vel.y, objects.collisions) then
|
||||
self.pos.y = self.pos.y + self.vel.y
|
||||
end
|
||||
end
|
||||
@@ -1,9 +0,0 @@
|
||||
UIElement = {}
|
||||
|
||||
function AddElement(self)
|
||||
table.insert(UIElement,self)
|
||||
self.id = #UIElement
|
||||
end
|
||||
|
||||
require "data/scripts/ui/button"
|
||||
require "data/scripts/ui/dialog"
|
||||
@@ -1,101 +0,0 @@
|
||||
interfaceButton = {type = "Button"}
|
||||
|
||||
-- centered buttons
|
||||
function interfaceButton:New(x,y,w,h,table_values,value,style)
|
||||
|
||||
o = {}
|
||||
o.pos = {
|
||||
x = x,
|
||||
y = y
|
||||
}
|
||||
o.size = {
|
||||
w = w,
|
||||
h = h
|
||||
|
||||
}
|
||||
|
||||
o.values = table_values or {false,true}
|
||||
o.value = value or 1
|
||||
o.target_variable = o.values[o.value]
|
||||
|
||||
o.clicked = false
|
||||
|
||||
o.style = {
|
||||
text = style.text or nil,
|
||||
color = style.color or {1,1,1},
|
||||
color2 = style.color2 or {0,0,0},
|
||||
--color3 = style.color3 or style.color2 or {0,0,0},
|
||||
alpha = style.alpha or 1,
|
||||
scale = style.scale or 1,
|
||||
scale_x = style.scale_x or 1,
|
||||
scale_y = style.scale_y or 1,
|
||||
scale_proportion = 1
|
||||
}
|
||||
|
||||
o.style.unselected = {
|
||||
scale_proportion = o.style.scale_proportion
|
||||
}
|
||||
|
||||
o.style.selected = {
|
||||
scale_proportion = 1.5
|
||||
}
|
||||
|
||||
|
||||
AddElement(o)
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
function interfaceButton:getVariable()
|
||||
return self.target_variable
|
||||
end
|
||||
|
||||
function interfaceButton:checkMouse(mouse_x, mouse_y)
|
||||
if not self.clicked
|
||||
and mouse_x < self.pos.x + self.size.w/2
|
||||
and mouse_x > self.pos.x - self.size.w/2
|
||||
and mouse_y < self.pos.y + self.size.h/2
|
||||
and mouse_y > self.pos.y - self.size.h/2 then
|
||||
self.style.scale_proportion = o.style.selected.scale_proportion
|
||||
if love.mouse.isDown(1) then
|
||||
self.clicked = true
|
||||
self.value = self.value + 1
|
||||
if self.value > #self.values then
|
||||
self.value = 1
|
||||
end
|
||||
self.target_variable = self.values[self.value]
|
||||
end
|
||||
elseif not love.mouse.isDown(1) then
|
||||
self.style.scale_proportion = o.style.unselected.scale_proportion
|
||||
self.clicked = false
|
||||
end
|
||||
end
|
||||
|
||||
function interfaceButton:Draw()
|
||||
local c1, c2, c3, a = love.graphics.getColor()
|
||||
|
||||
love.graphics.setColor(self.style.color[1],self.style.color[2],self.style.color[3],self.style.alpha)
|
||||
love.graphics.rectangle(
|
||||
"fill",
|
||||
self.pos.x-(self.size.w/2)*self.style.scale_x*self.style.scale_proportion,
|
||||
self.pos.y-(self.size.h/2)*self.style.scale_y*self.style.scale_proportion,
|
||||
self.size.w *self.style.scale_x*self.style.scale_proportion,
|
||||
self.size.h *self.style.scale_y*self.style.scale_proportion)
|
||||
love.graphics.setColor(self.style.color2[1],self.style.color2[2],self.style.color2[3],self.style.alpha)
|
||||
love.graphics.rectangle(
|
||||
"line",
|
||||
self.pos.x-(self.size.w/2)*self.style.scale_x*self.style.scale_proportion,
|
||||
self.pos.y-(self.size.h/2)*self.style.scale_y*self.style.scale_proportion,
|
||||
self.size.w *self.style.scale_x*self.style.scale_proportion,
|
||||
self.size.h *self.style.scale_y*self.style.scale_proportion)
|
||||
|
||||
if self.style.text ~= nil then
|
||||
love.graphics.print(self.style.text,self.pos.x,self.pos.y)
|
||||
else
|
||||
love.graphics.print(tostring(self.target_variable),self.pos.x,self.pos.y)
|
||||
end
|
||||
love.graphics.setColor(c1,c2,c3,a)
|
||||
end
|
||||
@@ -1,97 +0,0 @@
|
||||
interfaceDialog = {type = "Dialog"}
|
||||
-- dialog boxes
|
||||
function interfaceDialog:New(style)
|
||||
|
||||
o = {}
|
||||
o.pos = {
|
||||
x = 0,
|
||||
y = game.height*80/100
|
||||
}
|
||||
o.size = {
|
||||
w = game.width,
|
||||
h = game.height*20/100
|
||||
|
||||
}
|
||||
|
||||
o.value = 0
|
||||
o.target_value = 0
|
||||
|
||||
local style = {}
|
||||
|
||||
o.style = {
|
||||
content = style.content or nil,
|
||||
color = style.color or {1,1,1},
|
||||
color2 = style.color2 or {0,0,0},
|
||||
--color3 = style.color3 or style.color2 or {0,0,0},
|
||||
alpha = style.alpha or 1,
|
||||
scale = style.scale or 1,
|
||||
scale_x = style.scale_x or 1,
|
||||
scale_y = style.scale_y or 1,
|
||||
scale_proportion = 1
|
||||
}
|
||||
|
||||
AddElement(o)
|
||||
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
function interfaceDialog:updateContents()
|
||||
if self.value < self.target_value then
|
||||
self.contents = self.sequence[self.value]
|
||||
if self.contents[1] == nil then self.contents[1] = "" end
|
||||
if self.contents[2] == nil then self.contents[2] = "" end
|
||||
if self.contents[3] == nil then self.contents[3] = "" end
|
||||
end
|
||||
end
|
||||
|
||||
function interfaceDialog:loadSequence(sequence)
|
||||
self.sequence = sequence
|
||||
self.value = 1
|
||||
self.target_value = 1+#sequence
|
||||
self:updateContents()
|
||||
end
|
||||
|
||||
function interfaceDialog:checkConfirm()
|
||||
if not self.clicked then
|
||||
if love.mouse.isDown(1) then
|
||||
self.clicked = true
|
||||
self.value = self.value + 1
|
||||
logPrint("Dialog: "..self.value.." of "..self.target_value)
|
||||
self:updateContents()
|
||||
end
|
||||
elseif not love.mouse.isDown(1) then
|
||||
self.clicked = false
|
||||
end
|
||||
end
|
||||
|
||||
function interfaceDialog:Draw()
|
||||
local c1, c2, c3, a = love.graphics.getColor()
|
||||
|
||||
love.graphics.setColor(self.style.color[1],self.style.color[2],self.style.color[3],self.style.alpha)
|
||||
love.graphics.rectangle(
|
||||
"fill",
|
||||
self.pos.x*self.style.scale_x*self.style.scale_proportion,
|
||||
self.pos.y*self.style.scale_y*self.style.scale_proportion,
|
||||
self.size.w*self.style.scale_x*self.style.scale_proportion,
|
||||
self.size.h*self.style.scale_y*self.style.scale_proportion)
|
||||
love.graphics.setColor(self.style.color2[1],self.style.color2[2],self.style.color2[3],self.style.alpha)
|
||||
love.graphics.rectangle(
|
||||
"line",
|
||||
self.pos.x*self.style.scale_x*self.style.scale_proportion,
|
||||
self.pos.y*self.style.scale_y*self.style.scale_proportion,
|
||||
self.size.w*self.style.scale_x*self.style.scale_proportion,
|
||||
self.size.h*self.style.scale_y*self.style.scale_proportion)
|
||||
|
||||
if self.contents ~= nil then
|
||||
love.graphics.printf(self.contents[2],self.pos.x+10,self.pos.y+(self.size.h/2),100,"left")
|
||||
love.graphics.printf(self.contents[1],self.pos.x+(self.size.w/2),self.pos.y+(self.size.h/2),100,"center")
|
||||
love.graphics.printf(self.contents[3],self.pos.x+(self.size.w)-10,self.pos.y+(self.size.h/2),100,"right")
|
||||
else
|
||||
love.graphics.printf("ERROR",self.pos.x+(self.size.w/2),self.pos.y+(self.size.h/2),100,"center")
|
||||
end
|
||||
|
||||
love.graphics.setColor(c1,c2,c3,a)
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
sfx = {}
|
||||
|
||||
Reference in New Issue
Block a user