format and stuff

main
Simon Kellet 2 months ago
parent 53aa6d698d
commit 99b420cc7f
  1. 12
      Game/GameKeyPressed.lua
  2. 32
      Game/UpdateGame.lua
  3. 61
      Menu/DrawMenu.lua
  4. 7
      Menu/MenuKeyPressed.lua
  5. 3
      Menu/UpdateMenu.lua
  6. 65
      Pause/DrawPause.lua
  7. 44
      Pause/PauseKeyPressed.lua
  8. 3
      Pause/UpdatePause.lua
  9. 14
      constants.lua
  10. BIN
      game.love
  11. 69
      libs/classic.lua
  12. 244
      libs/profile.lua
  13. 317
      libs/sti/atlas.lua
  14. 2
      libs/sti/graphics.lua
  15. 632
      libs/sti/init.lua
  16. 114
      libs/sti/plugins/box2d.lua
  17. 103
      libs/sti/plugins/bump.lua
  18. 78
      libs/sti/utils.lua
  19. 2065
      libs/windfield/init.lua
  20. 2469
      libs/windfield/mlib/mlib.lua
  21. 48
      main.lua
  22. 4
      mapsloader.lua
  23. 108
      player.lua

@ -1,8 +1,7 @@
function GameKeyPressed(key) function GameKeyPressed(key)
if key == "escape" then if key == "escape" then
musicBattle:setVolume(0) musicBattle:setVolume(0)
musicPause:setVolume(0.5) musicPause:setVolume(0.6)
_G.GAMESTATE = "PAUSE" _G.GAMESTATE = "PAUSE"
print("STATE CHANEGD: PAUSED!") print("STATE CHANEGD: PAUSED!")
@ -13,13 +12,8 @@ function GameKeyPressed(key)
DebugFlag = not DebugFlag DebugFlag = not DebugFlag
end end
--TODO: Move player movement code into here! --TODO: Better restart
--[[
-- TODO: Better restart
if key == "r" and not _G.PAUSED then if key == "r" and not _G.PAUSED then
love.load() love.load()
end end
]]--
end end

@ -1,9 +1,31 @@
local function checkWinState()
-- Check P1's health
if UserPlayer1.health <= 0 then --P1 win
_G.P1_WIN = true
_G.P2_WIN = false
UserPlayer1.health = 0
return true
end
if UserPlayer2.health <= 0 then --P2 win
_G.P1_WIN = false
_G.P2_WIN = true
UserPlayer2.health = 0
return true
end
return false
end
local max = math.max -- optimisations
function UpdateGame(dt) function UpdateGame(dt)
--Check if anyone has won
if checkWinState() == true then
print("STATE CHNAGED: WIN!")
_G.GAMESTATE = "WIN"
end
--WindField --WindField
World:update(dt) World:update(dt)
local max = math.max
KeyPressTime1 = max(0, KeyPressTime1 - dt) KeyPressTime1 = max(0, KeyPressTime1 - dt)
if KeyPressTime1 <= 0 then if KeyPressTime1 <= 0 then
EnableKeyPress1 = true EnableKeyPress1 = true
@ -13,6 +35,7 @@ function UpdateGame(dt)
if KeyPressTime2 <= 0 then if KeyPressTime2 <= 0 then
EnableKeyPress2 = true EnableKeyPress2 = true
end end
for i, v in ipairs(Bullets1) do for i, v in ipairs(Bullets1) do
v:update(dt) v:update(dt)
if v.y < 0 then --top of screen if v.y < 0 then --top of screen
@ -69,7 +92,10 @@ function UpdateGame(dt)
end end
end end
end end
UserPlayer1:handleKeys("w", "s", "a", "d", dt)
UserPlayer2:handleKeys("up", "down", "left", "right", dt)
UserPlayer1:updateCol()
UserPlayer2:updateCol()
UserPlayer1:update(dt) UserPlayer1:update(dt)
UserPlayer2:update(dt) UserPlayer2:update(dt)
end end

@ -1,44 +1,43 @@
local function button(x,y, w, h, text, selected) local function button(x, y, w, h, text, selected)
--x,y is the top left corner of the button --x,y is the top left corner of the button
local rounding = 30 -- used for rounding the buttons local rounding = 30 -- used for rounding the buttons
if not selected then if not selected then
love.graphics.setColor(love.math.colorFromBytes(41,134,204)) love.graphics.setColor(love.math.colorFromBytes(41, 134, 204))
elseif selected then elseif selected then
love.graphics.setColor(love.math.colorFromBytes(244,67,54)) love.graphics.setColor(love.math.colorFromBytes(244, 67, 54))
end end
-- Draw rectangle -- Draw rectangle
love.graphics.rectangle("line", x, y, w, h, rounding, rounding) love.graphics.rectangle("line", x, y, w, h, rounding, rounding)
-- Get width and height of text -- Get width and height of text
local tw = MenuFont:getWidth(text) local tw = MenuFont:getWidth(text)
local th = MenuFont:getHeight(text) local th = MenuFont:getHeight(text)
-- Calculate position to center the text -- Calculate position to center the text
local textX = x + (w - tw) / 2 local textX = x + (w - tw) / 2
local textY = y + (h - th) / 2 local textY = y + (h - th) / 2
-- Place text inside the rectangle -- Place text inside the rectangle
love.graphics.setFont(MenuFont) love.graphics.setFont(MenuFont)
love.graphics.print(text, textX, textY) love.graphics.print(text, textX, textY)
end end
local function title() local function title()
local height = love.graphics.getHeight() local height = love.graphics.getHeight()
local width = love.graphics.getWidth() local width = love.graphics.getWidth()
love.graphics.setFont(GameFont) love.graphics.setFont(GameFont)
love.graphics.setColor(0.5,1,1) love.graphics.setColor(0.5, 1, 1)
love.graphics.rectangle("fill", 0, 0, width, height) love.graphics.rectangle("fill", 0, 0, width, height)
love.graphics.setColor(0,0,0) love.graphics.setColor(0, 0, 0)
love.graphics.print("MENU", 100,100) love.graphics.print("MENU", 100, 100)
end end
function DrawMenu() function DrawMenu()
local bwidth, bheight = 300, 140 local bwidth, bheight = 300, 140
title() title()
button(100, 200, bwidth, bheight, "Play", MENU_POS == 0 and true or false) button(100, 200, bwidth, bheight, "Play", MENU_POS == 0 and true or false)
button(100, 350, bwidth, bheight, "???", MENU_POS == 1 and true or false) button(100, 350, bwidth, bheight, "???", MENU_POS == 1 and true or false)
button(100, 500, bwidth, bheight, "???", MENU_POS == 2 and true or false) button(100, 500, bwidth, bheight, "???", MENU_POS == 2 and true or false)
button(100, 650, bwidth, bheight, "Quit", MENU_POS == 3 and true or false) button(100, 650, bwidth, bheight, "Quit", MENU_POS == 3 and true or false)
love.graphics.setColor(255,255,255) -- reset colours love.graphics.setColor(255, 255, 255) -- reset colours
end end

@ -1,5 +1,5 @@
function MenuKeyPressed(key) function MenuKeyPressed(key)
if key == 'return' then if key == "return" then
-- 0 Start Game -- 0 Start Game
-- 1 ?? -- 1 ??
-- 2 ??? -- 2 ???
@ -9,17 +9,13 @@ function MenuKeyPressed(key)
_G.GAMESTATE = "GAME" _G.GAMESTATE = "GAME"
print("STATE CHANEGD: GAME!") print("STATE CHANEGD: GAME!")
musicMenu:stop() musicMenu:stop()
elseif MENU_POS == 1 then elseif MENU_POS == 1 then
print("STATE CHANEGD: DUNNO!") print("STATE CHANEGD: DUNNO!")
elseif MENU_POS == 2 then elseif MENU_POS == 2 then
print("STATE CHANEGD: DUNNO!") print("STATE CHANEGD: DUNNO!")
elseif MENU_POS == 3 then elseif MENU_POS == 3 then
love.event.quit() love.event.quit()
end end
end end
if love.keyboard.isDown("up") then if love.keyboard.isDown("up") then
@ -37,5 +33,4 @@ function MenuKeyPressed(key)
_G.MENU_POS = _G.MENU_POS + 1 _G.MENU_POS = _G.MENU_POS + 1
end end
end end
end end

@ -1,2 +1 @@
function UpdateMenu(dt) function UpdateMenu(dt) end
end

@ -1,45 +1,44 @@
local function button(x,y, w, h, text, selected) local function button(x, y, w, h, text, selected)
--x,y is the top left corner of the button --x,y is the top left corner of the button
local rounding = 30 -- used for rounding the buttons local rounding = 30 -- used for rounding the buttons
if not selected then if not selected then
love.graphics.setColor(love.math.colorFromBytes(41,134,204)) love.graphics.setColor(love.math.colorFromBytes(41, 134, 204))
elseif selected then elseif selected then
love.graphics.setColor(love.math.colorFromBytes(244,67,54)) love.graphics.setColor(love.math.colorFromBytes(244, 67, 54))
end end
-- Draw rectangle -- Draw rectangle
love.graphics.rectangle("fill", x, y, w, h, rounding, rounding) love.graphics.rectangle("fill", x, y, w, h, rounding, rounding)
-- Get width and height of text -- Get width and height of text
local tw = MenuFont:getWidth(text) local tw = MenuFont:getWidth(text)
local th = MenuFont:getHeight(text) local th = MenuFont:getHeight(text)
-- Calculate position to center the text -- Calculate position to center the text
local textX = x + (w - tw) / 2 local textX = x + (w - tw) / 2
local textY = y + (h - th) / 2 local textY = y + (h - th) / 2
-- Place text inside the rectangle -- Place text inside the rectangle
love.graphics.setFont(MenuFont) love.graphics.setFont(MenuFont)
love.graphics.setColor(1,1,1) -- reset colours love.graphics.setColor(1, 1, 1) -- reset colours
love.graphics.print(text, textX, textY) love.graphics.print(text, textX, textY)
end end
function DrawPause() function DrawPause()
local opacity = 0.3 local opacity = 0.3
local height = love.graphics.getHeight() local height = love.graphics.getHeight()
local width = love.graphics.getWidth() local width = love.graphics.getWidth()
local bwidth, bheight = 300, 140 local bwidth, bheight = 300, 140
love.graphics.setFont(GameFont) love.graphics.setFont(GameFont)
DrawGame() --Draw a single frame of the game DrawGame() --Draw a single frame of the game
love.graphics.setColor(0.1,0.1,0.1, opacity) --overlay opaque img love.graphics.setColor(0.1, 0.1, 0.1, opacity) --overlay opaque img
love.graphics.rectangle("fill", 0, 0, width, height) love.graphics.rectangle("fill", 0, 0, width, height)
love.graphics.setColor(1,1,1) love.graphics.setColor(1, 1, 1)
love.graphics.print("PAUSED", 100,100) love.graphics.print("PAUSED", 100, 100)
--love.graphics.print("" .. PAUSE_POS, 200,200) --love.graphics.print("" .. PAUSE_POS, 200,200)
button(100, 200, bwidth, bheight, "Return", PAUSE_POS == 0 and true or false) button(100, 200, bwidth, bheight, "Return", PAUSE_POS == 0 and true or false)
button(100, 350, bwidth, bheight, "Menu", PAUSE_POS == 1 and true or false) button(100, 350, bwidth, bheight, "Menu", PAUSE_POS == 1 and true or false)
button(100, 500, bwidth, bheight, "Quit", PAUSE_POS == 2 and true or false) button(100, 500, bwidth, bheight, "Quit", PAUSE_POS == 2 and true or false)
love.graphics.setColor(255,255,255) -- reset colours love.graphics.setColor(255, 255, 255) -- reset colours
end end

@ -1,30 +1,26 @@
function PauseKeyPressed(key) function PauseKeyPressed(key)
if key == 'return' then if key == "return" then
musicBattle:setVolume(0.5) musicBattle:setVolume(0.5)
musicPause:setVolume(0) musicPause:setVolume(0)
-- 0 Return to game -- 0 Return to game
-- 1 Quit -- 1 Quit
if PAUSE_POS == 0 then if PAUSE_POS == 0 then
-- unpause the game -- unpause the game
_G.GAMESTATE = "GAME" _G.GAMESTATE = "GAME"
print("STATE CHANEGD: GAME!") print("STATE CHANEGD: GAME!")
_G.PAUSED = false _G.PAUSED = false
musicBattle:setVolume(0.5) musicBattle:setVolume(0.5)
musicPause:setVolume(0) musicPause:setVolume(0)
elseif PAUSE_POS == 1 then
elseif PAUSE_POS == 1 then _G.GAMESTATE = "MENU"
_G.GAMESTATE = "MENU" print("STATE CHANEGD: MENU!")
print("STATE CHANEGD: MENU!") _G.PAUSED = false
_G.PAUSED = false musicPause:stop()
musicPause:stop() musicBattle:stop()
musicBattle:stop() elseif PAUSE_POS == 2 then
elseif PAUSE_POS == 2 then
love.event.quit() love.event.quit()
end end
end
end
if love.keyboard.isDown("up") then if love.keyboard.isDown("up") then
if _G.PAUSE_POS == 0 then if _G.PAUSE_POS == 0 then
@ -41,4 +37,4 @@ function PauseKeyPressed(key)
_G.PAUSE_POS = _G.PAUSE_POS + 1 _G.PAUSE_POS = _G.PAUSE_POS + 1
end end
end end
end end

@ -1,2 +1 @@
function UpdatePause(dt) function UpdatePause(dt) end
end

@ -1,3 +1,11 @@
--[[
* Game states:
* - MENU
* - GAME
* - PAUSE
* - WIN
]]
--
GAMESTATE = "MENU" GAMESTATE = "MENU"
MENU_POS = 0 MENU_POS = 0
@ -5,4 +13,8 @@ MENU_MAX = 3 --0 play, 1 ?, 2 ?, 3 quit
PAUSED = false PAUSED = false
PAUSE_POS = 0 PAUSE_POS = 0
PAUSE_MAX = 2 -- 0 resume, 1 menu, 2 quit PAUSE_MAX = 2 -- 0 resume, 1 menu, 2 quit
-- WIN flags for P1 and P2
P1_WIN = false
P2_WIN = false

Binary file not shown.

@ -7,62 +7,53 @@
-- the terms of the MIT license. See LICENSE for details. -- the terms of the MIT license. See LICENSE for details.
-- --
local Object = {} local Object = {}
Object.__index = Object Object.__index = Object
function Object:new() end
function Object:new()
end
function Object:extend() function Object:extend()
local cls = {} local cls = {}
for k, v in pairs(self) do for k, v in pairs(self) do
if k:find("__") == 1 then if k:find("__") == 1 then
cls[k] = v cls[k] = v
end end
end end
cls.__index = cls cls.__index = cls
cls.super = self cls.super = self
setmetatable(cls, self) setmetatable(cls, self)
return cls return cls
end end
function Object:implement(...) function Object:implement(...)
for _, cls in pairs({...}) do for _, cls in pairs({ ... }) do
for k, v in pairs(cls) do for k, v in pairs(cls) do
if self[k] == nil and type(v) == "function" then if self[k] == nil and type(v) == "function" then
self[k] = v self[k] = v
end end
end end
end end
end end
function Object:is(T) function Object:is(T)
local mt = getmetatable(self) local mt = getmetatable(self)
while mt do while mt do
if mt == T then if mt == T then
return true return true
end end
mt = getmetatable(mt) mt = getmetatable(mt)
end end
return false return false
end end
function Object:__tostring() function Object:__tostring()
return "Object" return "Object"
end end
function Object:__call(...) function Object:__call(...)
local obj = setmetatable({}, self) local obj = setmetatable({}, self)
obj:new(...) obj:new(...)
return obj return obj
end end
return Object return Object

@ -23,91 +23,91 @@ local _internal = {}
-- @tparam number line Line number -- @tparam number line Line number
-- @tparam[opt] table info Debug info table -- @tparam[opt] table info Debug info table
function profile.hooker(event, line, info) function profile.hooker(event, line, info)
info = info or debug.getinfo(2, 'fnS') info = info or debug.getinfo(2, "fnS")
local f = info.func local f = info.func
-- ignore the profiler itself -- ignore the profiler itself
if _internal[f] or info.what ~= "Lua" then if _internal[f] or info.what ~= "Lua" then
return return
end end
-- get the function name if available -- get the function name if available
if info.name then if info.name then
_labeled[f] = info.name _labeled[f] = info.name
end end
-- find the line definition -- find the line definition
if not _defined[f] then if not _defined[f] then
_defined[f] = info.short_src..":"..info.linedefined _defined[f] = info.short_src .. ":" .. info.linedefined
_ncalls[f] = 0 _ncalls[f] = 0
_telapsed[f] = 0 _telapsed[f] = 0
end end
if _tcalled[f] then if _tcalled[f] then
local dt = clock() - _tcalled[f] local dt = clock() - _tcalled[f]
_telapsed[f] = _telapsed[f] + dt _telapsed[f] = _telapsed[f] + dt
_tcalled[f] = nil _tcalled[f] = nil
end end
if event == "tail call" then if event == "tail call" then
local prev = debug.getinfo(3, 'fnS') local prev = debug.getinfo(3, "fnS")
profile.hooker("return", line, prev) profile.hooker("return", line, prev)
profile.hooker("call", line, info) profile.hooker("call", line, info)
elseif event == 'call' then elseif event == "call" then
_tcalled[f] = clock() _tcalled[f] = clock()
else else
_ncalls[f] = _ncalls[f] + 1 _ncalls[f] = _ncalls[f] + 1
end end
end end
--- Sets a clock function to be used by the profiler. --- Sets a clock function to be used by the profiler.
-- @tparam function func Clock function that returns a number -- @tparam function func Clock function that returns a number
function profile.setclock(f) function profile.setclock(f)
assert(type(f) == "function", "clock must be a function") assert(type(f) == "function", "clock must be a function")
clock = f clock = f
end end
--- Starts collecting data. --- Starts collecting data.
function profile.start() function profile.start()
if rawget(_G, 'jit') then if rawget(_G, "jit") then
jit.off() jit.off()
jit.flush() jit.flush()
end end
debug.sethook(profile.hooker, "cr") debug.sethook(profile.hooker, "cr")
end end
--- Stops collecting data. --- Stops collecting data.
function profile.stop() function profile.stop()
debug.sethook() debug.sethook()
for f in pairs(_tcalled) do for f in pairs(_tcalled) do
local dt = clock() - _tcalled[f] local dt = clock() - _tcalled[f]
_telapsed[f] = _telapsed[f] + dt _telapsed[f] = _telapsed[f] + dt
_tcalled[f] = nil _tcalled[f] = nil
end end
-- merge closures -- merge closures
local lookup = {} local lookup = {}
for f, d in pairs(_defined) do for f, d in pairs(_defined) do
local id = (_labeled[f] or '?')..d local id = (_labeled[f] or "?") .. d
local f2 = lookup[id] local f2 = lookup[id]
if f2 then if f2 then
_ncalls[f2] = _ncalls[f2] + (_ncalls[f] or 0) _ncalls[f2] = _ncalls[f2] + (_ncalls[f] or 0)
_telapsed[f2] = _telapsed[f2] + (_telapsed[f] or 0) _telapsed[f2] = _telapsed[f2] + (_telapsed[f] or 0)
_defined[f], _labeled[f] = nil, nil _defined[f], _labeled[f] = nil, nil
_ncalls[f], _telapsed[f] = nil, nil _ncalls[f], _telapsed[f] = nil, nil
else else
lookup[id] = f lookup[id] = f
end end
end end
collectgarbage('collect') collectgarbage("collect")
end end
--- Resets all collected data. --- Resets all collected data.
function profile.reset() function profile.reset()
for f in pairs(_ncalls) do for f in pairs(_ncalls) do
_ncalls[f] = 0 _ncalls[f] = 0
end end
for f in pairs(_telapsed) do for f in pairs(_telapsed) do
_telapsed[f] = 0 _telapsed[f] = 0
end end
for f in pairs(_tcalled) do for f in pairs(_tcalled) do
_tcalled[f] = nil _tcalled[f] = nil
end end
collectgarbage('collect') collectgarbage("collect")
end end
--- This is an internal function. --- This is an internal function.
@ -115,11 +115,11 @@ end
-- @tparam function b Second function -- @tparam function b Second function
-- @treturn boolean True if "a" should rank higher than "b" -- @treturn boolean True if "a" should rank higher than "b"
function profile.comp(a, b) function profile.comp(a, b)
local dt = _telapsed[b] - _telapsed[a] local dt = _telapsed[b] - _telapsed[a]
if dt == 0 then if dt == 0 then
return _ncalls[b] < _ncalls[a] return _ncalls[b] < _ncalls[a]
end end
return dt < 0 return dt < 0
end end
--- Generates a report of functions that have been called since the profile was started. --- Generates a report of functions that have been called since the profile was started.
@ -127,26 +127,26 @@ end
-- @tparam[opt] number limit Maximum number of rows -- @tparam[opt] number limit Maximum number of rows
-- @treturn table Table of rows -- @treturn table Table of rows
function profile.query(limit) function profile.query(limit)
local t = {} local t = {}
for f, n in pairs(_ncalls) do for f, n in pairs(_ncalls) do
if n > 0 then if n > 0 then
t[#t + 1] = f t[#t + 1] = f
end end
end end
table.sort(t, profile.comp) table.sort(t, profile.comp)
if limit then if limit then
while #t > limit do while #t > limit do
table.remove(t) table.remove(t)
end end
end end
for i, f in ipairs(t) do for i, f in ipairs(t) do
local dt = 0 local dt = 0
if _tcalled[f] then if _tcalled[f] then
dt = clock() - _tcalled[f] dt = clock() - _tcalled[f]
end end
t[i] = { i, _labeled[f] or '?', _ncalls[f], _telapsed[f] + dt, _defined[f] } t[i] = { i, _labeled[f] or "?", _ncalls[f], _telapsed[f] + dt, _defined[f] }
end end
return t return t
end end
local cols = { 3, 29, 11, 24, 32 } local cols = { 3, 29, 11, 24, 32 }
@ -156,38 +156,40 @@ local cols = { 3, 29, 11, 24, 32 }
-- @tparam[opt] number limit Maximum number of rows -- @tparam[opt] number limit Maximum number of rows
-- @treturn string Text-based profiling report -- @treturn string Text-based profiling report
function profile.report(n) function profile.report(n)
local out = {} local out = {}
local report = profile.query(n) local report = profile.query(n)
for i, row in ipairs(report) do for i, row in ipairs(report) do
for j = 1, 5 do for j = 1, 5 do
local s = row[j] local s = row[j]
local l2 = cols[j] local l2 = cols[j]
s = tostring(s) s = tostring(s)
local l1 = s:len() local l1 = s:len()
if l1 < l2 then if l1 < l2 then
s = s..(' '):rep(l2-l1) s = s .. (" "):rep(l2 - l1)
elseif l1 > l2 then elseif l1 > l2 then
s = s:sub(l1 - l2 + 1, l1) s = s:sub(l1 - l2 + 1, l1)
end end
row[j] = s row[j] = s
end end
out[i] = table.concat(row, ' | ') out[i] = table.concat(row, " | ")
end end
local row = " +-----+-------------------------------+-------------+--------------------------+----------------------------------+ \n" local row =
local col = " | # | Function | Calls | Time | Code | \n" " +-----+-------------------------------+-------------+--------------------------+----------------------------------+ \n"
local sz = row..col..row local col =
if #out > 0 then " | # | Function | Calls | Time | Code | \n"
sz = sz..' | '..table.concat(out, ' | \n | ')..' | \n' local sz = row .. col .. row
end if #out > 0 then
return '\n'..sz..row sz = sz .. " | " .. table.concat(out, " | \n | ") .. " | \n"
end
return "\n" .. sz .. row
end end
-- store all internal profiler functions -- store all internal profiler functions
for _, v in pairs(profile) do for _, v in pairs(profile) do
if type(v) == "function" then if type(v) == "function" then
_internal[v] = true _internal[v] = true
end end
end end
return profile return profile

@ -10,150 +10,179 @@ local module = {}
-- @param sort If "size" will sort by size, or if "id" will sort by id -- @param sort If "size" will sort by size, or if "id" will sort by id
-- @param ids Array with ids of each file -- @param ids Array with ids of each file
-- @param pow2 If true, will force a power of 2 size -- @param pow2 If true, will force a power of 2 size
function module.Atlas( files, sort, ids, pow2 ) function module.Atlas(files, sort, ids, pow2)
local function Node(x, y, w, h)
local function Node(x, y, w, h) return { x = x, y = y, w = w, h = h }
return {x = x, y = y, w = w, h = h} end
end
local function nextpow2(n)
local function nextpow2( n ) local res = 1
local res = 1 while res <= n do
while res <= n do res = res * 2
res = res * 2 end
end return res
return res end
end
local function loadImgs()
local function loadImgs() local images = {}
local images = {} for i = 1, #files do
for i = 1, #files do images[i] = {}
images[i] = {} --images[i].name = files[i]
--images[i].name = files[i] if ids then
if ids then images[i].id = ids[i] end images[i].id = ids[i]
images[i].img = love.graphics.newImage( files[i] ) end
images[i].w = images[i].img:getWidth() images[i].img = love.graphics.newImage(files[i])
images[i].h = images[i].img:getHeight() images[i].w = images[i].img:getWidth()
images[i].area = images[i].w * images[i].h images[i].h = images[i].img:getHeight()
end images[i].area = images[i].w * images[i].h
if sort == "size" or sort == "id" then end
table.sort( images, function( a, b ) return ( a.area > b.area ) end ) if sort == "size" or sort == "id" then
end table.sort(images, function(a, b)
return images return (a.area > b.area)
end end)
end
--TODO: understand this func return images
local function add(root, id, w, h) end
if root.left or root.right then
if root.left then --TODO: understand this func
local node = add(root.left, id, w, h) local function add(root, id, w, h)
if node then return node end if root.left or root.right then
end if root.left then
if root.right then local node = add(root.left, id, w, h)
local node = add(root.right, id, w, h) if node then
if node then return node end return node
end end
return nil end
end if root.right then
local node = add(root.right, id, w, h)
if w > root.w or h > root.h then return nil end if node then
return node
local _w, _h = root.w - w, root.h - h end
end
if _w <= _h then return nil
root.left = Node(root.x + w, root.y, _w, h) end
root.right = Node(root.x, root.y + h, root.w, _h)
else if w > root.w or h > root.h then
root.left = Node(root.x, root.y + h, w, _h) return nil
root.right = Node(root.x + w, root.y, _w, root.h) end
end
local _w, _h = root.w - w, root.h - h
root.w = w
root.h = h if _w <= _h then
root.id = id root.left = Node(root.x + w, root.y, _w, h)
root.right = Node(root.x, root.y + h, root.w, _h)
return root else
end root.left = Node(root.x, root.y + h, w, _h)
root.right = Node(root.x + w, root.y, _w, root.h)
local function unmap(root) end
if not root then return {} end
root.w = w
local tree = {} root.h = h
if root.id then root.id = id
tree[root.id] = {}
tree[root.id].x, tree[root.id].y = root.x, root.y return root
end end
local left = unmap(root.left) local function unmap(root)
local right = unmap(root.right) if not root then
return {}
for k, v in pairs(left) do end
tree[k] = {}
tree[k].x, tree[k].y = v.x, v.y local tree = {}
end if root.id then
for k, v in pairs(right) do tree[root.id] = {}
tree[k] = {} tree[root.id].x, tree[root.id].y = root.x, root.y
tree[k].x, tree[k].y = v.x, v.y end
end
local left = unmap(root.left)
return tree local right = unmap(root.right)
end
for k, v in pairs(left) do
local function bake() tree[k] = {}
local images = loadImgs() tree[k].x, tree[k].y = v.x, v.y
end
local root = {} for k, v in pairs(right) do
local w, h = images[1].w, images[1].h tree[k] = {}
tree[k].x, tree[k].y = v.x, v.y
if pow2 then end
if w % 1 == 0 then w = nextpow2(w) end
if h % 1 == 0 then h = nextpow2(h) end return tree
end end
repeat local function bake()
local node local images = loadImgs()
root = Node(0, 0, w, h) local root = {}
local w, h = images[1].w, images[1].h
for i = 1, #images do
node = add(root, i, images[i].w, images[i].h) if pow2 then
if not node then break end if w % 1 == 0 then
end w = nextpow2(w)
end
if not node then if h % 1 == 0 then
if h <= w then h = nextpow2(h)
if pow2 then h = h * 2 else h = h + 1 end end
else end
if pow2 then w = w * 2 else w = w + 1 end
end repeat
else local node
break
end root = Node(0, 0, w, h)
until false
for i = 1, #images do
local limits = love.graphics.getSystemLimits() node = add(root, i, images[i].w, images[i].h)
if w > limits.texturesize or h > limits.texturesize then if not node then
return "Resulting texture is too large for this system" break
end end
end
local coords = unmap(root)
local map = love.graphics.newCanvas(w, h) if not node then
love.graphics.setCanvas( map ) if h <= w then
-- love.graphics.clear() if pow2 then
h = h * 2
for i = 1, #images do else
love.graphics.draw(images[i].img, coords[i].x, coords[i].y) h = h + 1
if ids then coords[i].id = images[i].id end end
end else
love.graphics.setCanvas() if pow2 then
w = w * 2
if sort == "ids" then else
table.sort( coords, function( a, b ) return ( a.id < b.id ) end ) w = w + 1
end end
end
return { image = map, coords = coords } else
end break
end
return bake() until false
local limits = love.graphics.getSystemLimits()
if w > limits.texturesize or h > limits.texturesize then
return "Resulting texture is too large for this system"
end
local coords = unmap(root)
local map = love.graphics.newCanvas(w, h)
love.graphics.setCanvas(map)
-- love.graphics.clear()
for i = 1, #images do
love.graphics.draw(images[i].img, coords[i].x, coords[i].y)
if ids then
coords[i].id = images[i].id
end
end
love.graphics.setCanvas()
if sort == "ids" then
table.sort(coords, function(a, b)
return (a.id < b.id)
end)
end
return { image = map, coords = coords }
end
return bake()
end end
return module return module

@ -1,4 +1,4 @@
local lg = _G.love.graphics local lg = _G.love.graphics
local graphics = { isCreated = lg and true or false } local graphics = { isCreated = lg and true or false }
function graphics.newSpriteBatch(...) function graphics.newSpriteBatch(...)

File diff suppressed because it is too large Load Diff

@ -4,14 +4,14 @@
-- @copyright 2019 -- @copyright 2019
-- @license MIT/X11 -- @license MIT/X11
local love = _G.love local love = _G.love
local utils = require((...):gsub('plugins.box2d', 'utils')) local utils = require((...):gsub("plugins.box2d", "utils"))
local lg = require((...):gsub('plugins.box2d', 'graphics')) local lg = require((...):gsub("plugins.box2d", "graphics"))
return { return {
box2d_LICENSE = "MIT/X11", box2d_LICENSE = "MIT/X11",
box2d_URL = "https://github.com/karai17/Simple-Tiled-Implementation", box2d_URL = "https://github.com/karai17/Simple-Tiled-Implementation",
box2d_VERSION = "2.3.2.7", box2d_VERSION = "2.3.2.7",
box2d_DESCRIPTION = "Box2D hooks for STI.", box2d_DESCRIPTION = "Box2D hooks for STI.",
--- Initialize Box2D physics world. --- Initialize Box2D physics world.
@ -19,7 +19,7 @@ return {
box2d_init = function(map, world) box2d_init = function(map, world)
assert(love.physics, "To use the Box2D plugin, please enable the love.physics module.") assert(love.physics, "To use the Box2D plugin, please enable the love.physics module.")
local body = love.physics.newBody(world, map.offsetx, map.offsety) local body = love.physics.newBody(world, map.offsetx, map.offsety)
local collision = { local collision = {
body = body, body = body,
} }
@ -40,32 +40,32 @@ return {
local currentBody = body local currentBody = body
--dynamic are objects/players etc. --dynamic are objects/players etc.
if userdata.properties.dynamic == true then if userdata.properties.dynamic == true then
currentBody = love.physics.newBody(world, map.offsetx, map.offsety, 'dynamic') currentBody = love.physics.newBody(world, map.offsetx, map.offsety, "dynamic")
-- static means it shouldn't move. Things like walls/ground. -- static means it shouldn't move. Things like walls/ground.
elseif userdata.properties.static == true then elseif userdata.properties.static == true then
currentBody = love.physics.newBody(world, map.offsetx, map.offsety, 'static') currentBody = love.physics.newBody(world, map.offsetx, map.offsety, "static")
-- kinematic means that the object is static in the game world but effects other bodies -- kinematic means that the object is static in the game world but effects other bodies
elseif userdata.properties.kinematic == true then elseif userdata.properties.kinematic == true then
currentBody = love.physics.newBody(world, map.offsetx, map.offsety, 'kinematic') currentBody = love.physics.newBody(world, map.offsetx, map.offsety, "kinematic")
end end
local fixture = love.physics.newFixture(currentBody, shape) local fixture = love.physics.newFixture(currentBody, shape)
fixture:setUserData(userdata) fixture:setUserData(userdata)
-- Set some custom properties from userdata (or use default set by box2d) -- Set some custom properties from userdata (or use default set by box2d)
fixture:setFriction(userdata.properties.friction or 0.2) fixture:setFriction(userdata.properties.friction or 0.2)
fixture:setRestitution(userdata.properties.restitution or 0.0) fixture:setRestitution(userdata.properties.restitution or 0.0)
fixture:setSensor(userdata.properties.sensor or false) fixture:setSensor(userdata.properties.sensor or false)
fixture:setFilterData( fixture:setFilterData(
userdata.properties.categories or 1, userdata.properties.categories or 1,
userdata.properties.mask or 65535, userdata.properties.mask or 65535,
userdata.properties.group or 0 userdata.properties.group or 0
) )
local obj = { local obj = {
object = object, object = object,
body = currentBody, body = currentBody,
shape = shape, shape = shape,
fixture = fixture, fixture = fixture,
} }
@ -84,33 +84,33 @@ return {
local function calculateObjectPosition(object, tile) local function calculateObjectPosition(object, tile)
local o = { local o = {
shape = object.shape, shape = object.shape,
x = (object.dx or object.x) + map.offsetx, x = (object.dx or object.x) + map.offsetx,
y = (object.dy or object.y) + map.offsety, y = (object.dy or object.y) + map.offsety,
w = object.width, w = object.width,
h = object.height, h = object.height,
polygon = object.polygon or object.polyline or object.ellipse or object.rectangle polygon = object.polygon or object.polyline or object.ellipse or object.rectangle,
} }
local userdata = { local userdata = {
object = o, object = o,
properties = object.properties properties = object.properties,
} }
o.r = object.rotation or 0 o.r = object.rotation or 0
if o.shape == "rectangle" then if o.shape == "rectangle" then
local cos = math.cos(math.rad(o.r)) local cos = math.cos(math.rad(o.r))
local sin = math.sin(math.rad(o.r)) local sin = math.sin(math.rad(o.r))
local oy = 0 local oy = 0
if object.gid then if object.gid then
local tileset = map.tilesets[map.tiles[object.gid].tileset] local tileset = map.tilesets[map.tiles[object.gid].tileset]
local lid = object.gid - tileset.firstgid local lid = object.gid - tileset.firstgid
local t = {} local t = {}
-- This fixes a height issue -- This fixes a height issue
o.y = o.y + map.tiles[object.gid].offset.y o.y = o.y + map.tiles[object.gid].offset.y
oy = o.h oy = o.h
for _, tt in ipairs(tileset.tiles) do for _, tt in ipairs(tileset.tiles) do
if tt.id == lid then if tt.id == lid then
@ -133,10 +133,10 @@ return {
end end
o.polygon = { o.polygon = {
{ x=o.x+0, y=o.y+0 }, { x = o.x + 0, y = o.y + 0 },
{ x=o.x+o.w, y=o.y+0 }, { x = o.x + o.w, y = o.y + 0 },
{ x=o.x+o.w, y=o.y+o.h }, { x = o.x + o.w, y = o.y + o.h },
{ x=o.x+0, y=o.y+o.h } { x = o.x + 0, y = o.y + o.h },
} }
for _, vertex in ipairs(o.polygon) do for _, vertex in ipairs(o.polygon) do
@ -149,7 +149,7 @@ return {
if not o.polygon then if not o.polygon then
o.polygon = utils.convert_ellipse_to_polygon(o.x, o.y, o.w, o.h) o.polygon = utils.convert_ellipse_to_polygon(o.x, o.y, o.w, o.h)
end end
local vertices = getPolygonVertices(o) local vertices = getPolygonVertices(o)
local triangles = love.math.triangulate(vertices) local triangles = love.math.triangulate(vertices)
for _, triangle in ipairs(triangles) do for _, triangle in ipairs(triangles) do
@ -167,7 +167,7 @@ return {
end end
end end
local vertices = getPolygonVertices(o) local vertices = getPolygonVertices(o)
local triangles = love.math.triangulate(vertices) local triangles = love.math.triangulate(vertices)
for _, triangle in ipairs(triangles) do for _, triangle in ipairs(triangles) do
@ -197,12 +197,12 @@ return {
-- Every instance of a tile -- Every instance of a tile
if tile.properties.collidable == true then if tile.properties.collidable == true then
local object = { local object = {
shape = "rectangle", shape = "rectangle",
x = instance.x, x = instance.x,
y = instance.y, y = instance.y,
width = map.tilewidth, width = map.tilewidth,
height = map.tileheight, height = map.tileheight,
properties = tile.properties properties = tile.properties,
} }
calculateObjectPosition(object, instance) calculateObjectPosition(object, instance)
@ -222,12 +222,12 @@ return {
for _, instance in ipairs(tiles) do for _, instance in ipairs(tiles) do
if instance.layer == layer then if instance.layer == layer then
local object = { local object = {
shape = "rectangle", shape = "rectangle",
x = instance.x, x = instance.x,
y = instance.y, y = instance.y,
width = tileset.tilewidth, width = tileset.tilewidth,
height = tileset.tileheight, height = tileset.tileheight,
properties = tile.properties properties = tile.properties,
} }
calculateObjectPosition(object, instance) calculateObjectPosition(object, instance)
@ -240,12 +240,12 @@ return {
end end
elseif layer.type == "imagelayer" then elseif layer.type == "imagelayer" then
local object = { local object = {
shape = "rectangle", shape = "rectangle",
x = layer.x or 0, x = layer.x or 0,
y = layer.y or 0, y = layer.y or 0,
width = layer.width, width = layer.width,
height = layer.height, height = layer.height,
properties = layer.properties properties = layer.properties,
} }
calculateObjectPosition(object) calculateObjectPosition(object)
@ -295,7 +295,7 @@ return {
lg.translate(math.floor(tx or 0), math.floor(ty or 0)) lg.translate(math.floor(tx or 0), math.floor(ty or 0))
for _, obj in ipairs(collision) do for _, obj in ipairs(collision) do
local points = {obj.body:getWorldPoints(obj.shape:getPoints())} local points = { obj.body:getWorldPoints(obj.shape:getPoints()) }
local shape_type = obj.shape:getType() local shape_type = obj.shape:getType()
if shape_type == "edge" or shape_type == "chain" then if shape_type == "edge" or shape_type == "chain" then
@ -303,12 +303,12 @@ return {
elseif shape_type == "polygon" then elseif shape_type == "polygon" then
love.graphics.polygon("line", points) love.graphics.polygon("line", points)
else else
error("sti box2d plugin does not support "..shape_type.." shapes") error("sti box2d plugin does not support " .. shape_type .. " shapes")
end end
end end
lg.pop() lg.pop()
end end,
} }
--- Custom Properties in Tiled are used to tell this plugin what to do. --- Custom Properties in Tiled are used to tell this plugin what to do.

@ -4,13 +4,13 @@
-- @copyright 2019 -- @copyright 2019
-- @license MIT/X11 -- @license MIT/X11
local lg = require((...):gsub('plugins.bump', 'graphics')) local lg = require((...):gsub("plugins.bump", "graphics"))
return { return {
bump_LICENSE = "MIT/X11", bump_LICENSE = "MIT/X11",
bump_URL = "https://github.com/karai17/Simple-Tiled-Implementation", bump_URL = "https://github.com/karai17/Simple-Tiled-Implementation",
bump_VERSION = "3.1.7.1", bump_VERSION = "3.1.7.1",
bump_DESCRIPTION = "Bump hooks for STI.", bump_DESCRIPTION = "Bump hooks for STI.",
--- Adds each collidable tile to the Bump world. --- Adds each collidable tile to the Bump world.
-- @param world The Bump world to add objects to. -- @param world The Bump world to add objects to.
@ -29,15 +29,14 @@ return {
for _, object in ipairs(tile.objectGroup.objects) do for _, object in ipairs(tile.objectGroup.objects) do
if object.properties.collidable == true then if object.properties.collidable == true then
local t = { local t = {
name = object.name, name = object.name,
type = object.type, type = object.type,
x = instance.x + map.offsetx + object.x, x = instance.x + map.offsetx + object.x,
y = instance.y + map.offsety + object.y, y = instance.y + map.offsety + object.y,
width = object.width, width = object.width,
height = object.height, height = object.height,
layer = instance.layer, layer = instance.layer,
properties = object.properties properties = object.properties,
} }
world:add(t, t.x, t.y, t.width, t.height) world:add(t, t.x, t.y, t.width, t.height)
@ -49,13 +48,13 @@ return {
-- Every instance of a tile -- Every instance of a tile
if tile.properties and tile.properties.collidable == true then if tile.properties and tile.properties.collidable == true then
local t = { local t = {
x = instance.x + map.offsetx, x = instance.x + map.offsetx,
y = instance.y + map.offsety, y = instance.y + map.offsety,
width = map.tilewidth, width = map.tilewidth,
height = map.tileheight, height = map.tileheight,
layer = instance.layer, layer = instance.layer,
type = tile.type, type = tile.type,
properties = tile.properties properties = tile.properties,
} }
world:add(t, t.x, t.y, t.width, t.height) world:add(t, t.x, t.y, t.width, t.height)
@ -72,19 +71,18 @@ return {
if layer.type == "tilelayer" then if layer.type == "tilelayer" then
for y, tiles in ipairs(layer.data) do for y, tiles in ipairs(layer.data) do
for x, tile in pairs(tiles) do for x, tile in pairs(tiles) do
if tile.objectGroup then if tile.objectGroup then
for _, object in ipairs(tile.objectGroup.objects) do for _, object in ipairs(tile.objectGroup.objects) do
if object.properties.collidable == true then if object.properties.collidable == true then
local t = { local t = {
name = object.name, name = object.name,
type = object.type, type = object.type,
x = ((x-1) * map.tilewidth + tile.offset.x + map.offsetx) + object.x, x = ((x - 1) * map.tilewidth + tile.offset.x + map.offsetx) + object.x,
y = ((y-1) * map.tileheight + tile.offset.y + map.offsety) + object.y, y = ((y - 1) * map.tileheight + tile.offset.y + map.offsety) + object.y,
width = object.width, width = object.width,
height = object.height, height = object.height,
layer = layer, layer = layer,
properties = object.properties properties = object.properties,
} }
world:add(t, t.x, t.y, t.width, t.height) world:add(t, t.x, t.y, t.width, t.height)
@ -93,15 +91,14 @@ return {
end end
end end
local t = { local t = {
x = (x-1) * map.tilewidth + tile.offset.x + map.offsetx, x = (x - 1) * map.tilewidth + tile.offset.x + map.offsetx,
y = (y-1) * map.tileheight + tile.offset.y + map.offsety, y = (y - 1) * map.tileheight + tile.offset.y + map.offsety,
width = tile.width, width = tile.width,
height = tile.height, height = tile.height,
layer = layer, layer = layer,
type = tile.type, type = tile.type,
properties = tile.properties properties = tile.properties,
} }
world:add(t, t.x, t.y, t.width, t.height) world:add(t, t.x, t.y, t.width, t.height)
@ -112,23 +109,23 @@ return {
world:add(layer, layer.x, layer.y, layer.width, layer.height) world:add(layer, layer.x, layer.y, layer.width, layer.height)
table.insert(collidables, layer) table.insert(collidables, layer)
end end
end end
-- individual collidable objects in a layer that is not "collidable" -- individual collidable objects in a layer that is not "collidable"
-- or whole collidable objects layer -- or whole collidable objects layer
if layer.type == "objectgroup" then if layer.type == "objectgroup" then
for _, obj in ipairs(layer.objects) do for _, obj in ipairs(layer.objects) do
if layer.properties.collidable == true or obj.properties.collidable == true then if layer.properties.collidable == true or obj.properties.collidable == true then
if obj.shape == "rectangle" then if obj.shape == "rectangle" then
local t = { local t = {
name = obj.name, name = obj.name,
type = obj.type, type = obj.type,
x = obj.x + map.offsetx, x = obj.x + map.offsetx,
y = obj.y + map.offsety, y = obj.y + map.offsety,
width = obj.width, width = obj.width,
height = obj.height, height = obj.height,
layer = layer, layer = layer,
properties = obj.properties properties = obj.properties,
} }
if obj.gid then if obj.gid then
@ -143,7 +140,7 @@ return {
end end
end end
map.bump_world = world map.bump_world = world
map.bump_collidables = collidables map.bump_collidables = collidables
end, end,
@ -157,11 +154,7 @@ return {
for i = #collidables, 1, -1 do for i = #collidables, 1, -1 do
local obj = collidables[i] local obj = collidables[i]
if obj.layer == layer if obj.layer == layer and (layer.properties.collidable == true or obj.properties.collidable == true) then
and (
layer.properties.collidable == true
or obj.properties.collidable == true
) then
map.bump_world:remove(obj) map.bump_world:remove(obj)
table.remove(collidables, i) table.remove(collidables, i)
end end
@ -185,7 +178,7 @@ return {
end end
lg.pop() lg.pop()
end end,
} }
--- Custom Properties in Tiled are used to tell this plugin what to do. --- Custom Properties in Tiled are used to tell this plugin what to do.

@ -3,19 +3,21 @@ local utils = {}
-- https://github.com/stevedonovan/Penlight/blob/master/lua/pl/path.lua#L286 -- https://github.com/stevedonovan/Penlight/blob/master/lua/pl/path.lua#L286
function utils.format_path(path) function utils.format_path(path)
local np_gen1,np_gen2 = '[^SEP]+SEP%.%.SEP?','SEP+%.?SEP' local np_gen1, np_gen2 = "[^SEP]+SEP%.%.SEP?", "SEP+%.?SEP"
local np_pat1, np_pat2 = np_gen1:gsub('SEP','/'), np_gen2:gsub('SEP','/') local np_pat1, np_pat2 = np_gen1:gsub("SEP", "/"), np_gen2:gsub("SEP", "/")
local k local k
repeat -- /./ -> / repeat -- /./ -> /
path,k = path:gsub(np_pat2,'/',1) path, k = path:gsub(np_pat2, "/", 1)
until k == 0 until k == 0
repeat -- A/../ -> (empty) repeat -- A/../ -> (empty)
path,k = path:gsub(np_pat1,'',1) path, k = path:gsub(np_pat1, "", 1)
until k == 0 until k == 0
if path == '' then path = '.' end if path == "" then
path = "."
end
return path return path
end end
@ -25,8 +27,12 @@ function utils.compensate(tile, tileX, tileY, tileW, tileH)
local compx = 0 local compx = 0
local compy = 0 local compy = 0
if tile.sx < 0 then compx = tileW end if tile.sx < 0 then
if tile.sy < 0 then compy = tileH end compx = tileW
end
if tile.sy < 0 then
compy = tileH
end
if tile.r > 0 then if tile.r > 0 then
tileX = tileX + tileH - compy tileX = tileX + tileH - compy
@ -51,13 +57,17 @@ end
-- We just don't know. -- We just don't know.
function utils.get_tiles(imageW, tileW, margin, spacing) function utils.get_tiles(imageW, tileW, margin, spacing)
imageW = imageW - margin imageW = imageW - margin
local n = 0 local n = 0
while imageW >= tileW do while imageW >= tileW do
imageW = imageW - tileW imageW = imageW - tileW
if n ~= 0 then imageW = imageW - spacing end if n ~= 0 then
if imageW >= 0 then n = n + 1 end imageW = imageW - spacing
end
if imageW >= 0 then
n = n + 1
end
end end
return n return n
@ -65,8 +75,8 @@ end
-- Decompress tile layer data -- Decompress tile layer data
function utils.get_decompressed_data(data) function utils.get_decompressed_data(data)
local ffi = require "ffi" local ffi = require("ffi")
local d = {} local d = {}
local decoded = ffi.cast("uint32_t*", data) local decoded = ffi.cast("uint32_t*", data)
for i = 0, data:len() / ffi.sizeof("uint32_t") do for i = 0, data:len() / ffi.sizeof("uint32_t") do
@ -79,8 +89,8 @@ end
-- Convert a Tiled ellipse object to a LOVE polygon -- Convert a Tiled ellipse object to a LOVE polygon
function utils.convert_ellipse_to_polygon(x, y, w, h, max_segments) function utils.convert_ellipse_to_polygon(x, y, w, h, max_segments)
local ceil = math.ceil local ceil = math.ceil
local cos = math.cos local cos = math.cos
local sin = math.sin local sin = math.sin
local function calc_segments(segments) local function calc_segments(segments)
local function vdist(a, b) local function vdist(a, b)
@ -95,7 +105,7 @@ function utils.convert_ellipse_to_polygon(x, y, w, h, max_segments)
segments = segments or 64 segments = segments or 64
local vertices = {} local vertices = {}
local v = { 1, 2, ceil(segments/4-1), ceil(segments/4) } local v = { 1, 2, ceil(segments / 4 - 1), ceil(segments / 4) }
local m local m
if love and love.physics then if love and love.physics then
@ -106,8 +116,8 @@ function utils.convert_ellipse_to_polygon(x, y, w, h, max_segments)
for _, i in ipairs(v) do for _, i in ipairs(v) do
local angle = (i / segments) * math.pi * 2 local angle = (i / segments) * math.pi * 2
local px = x + w / 2 + cos(angle) * w / 2 local px = x + w / 2 + cos(angle) * w / 2
local py = y + h / 2 + sin(angle) * h / 2 local py = y + h / 2 + sin(angle) * h / 2
table.insert(vertices, { x = px / m, y = py / m }) table.insert(vertices, { x = px / m, y = py / m })
end end
@ -117,7 +127,7 @@ function utils.convert_ellipse_to_polygon(x, y, w, h, max_segments)
-- Box2D threshold -- Box2D threshold
if dist1 < 0.0025 or dist2 < 0.0025 then if dist1 < 0.0025 or dist2 < 0.0025 then
return calc_segments(segments-2) return calc_segments(segments - 2)
end end
return segments return segments
@ -130,8 +140,8 @@ function utils.convert_ellipse_to_polygon(x, y, w, h, max_segments)
for i = 0, segments do for i = 0, segments do
local angle = (i / segments) * math.pi * 2 local angle = (i / segments) * math.pi * 2
local px = x + w / 2 + cos(angle) * w / 2 local px = x + w / 2 + cos(angle) * w / 2
local py = y + h / 2 + sin(angle) * h / 2 local py = y + h / 2 + sin(angle) * h / 2
table.insert(vertices, { x = px, y = py }) table.insert(vertices, { x = px, y = py })
end end
@ -141,30 +151,26 @@ end
function utils.rotate_vertex(map, vertex, x, y, cos, sin, oy) function utils.rotate_vertex(map, vertex, x, y, cos, sin, oy)
if map.orientation == "isometric" then if map.orientation == "isometric" then
x, y = utils.convert_isometric_to_screen(map, x, y) x, y = utils.convert_isometric_to_screen(map, x, y)
vertex.x, vertex.y = utils.convert_isometric_to_screen(map, vertex.x, vertex.y) vertex.x, vertex.y = utils.convert_isometric_to_screen(map, vertex.x, vertex.y)
end end
vertex.x = vertex.x - x vertex.x = vertex.x - x
vertex.y = vertex.y - y vertex.y = vertex.y - y
return return x + cos * vertex.x - sin * vertex.y, y + sin * vertex.x + cos * vertex.y - (oy or 0)
x + cos * vertex.x - sin * vertex.y,
y + sin * vertex.x + cos * vertex.y - (oy or 0)
end end
--- Project isometric position to cartesian position --- Project isometric position to cartesian position
function utils.convert_isometric_to_screen(map, x, y) function utils.convert_isometric_to_screen(map, x, y)
local mapW = map.width local mapW = map.width
local tileW = map.tilewidth local tileW = map.tilewidth
local tileH = map.tileheight local tileH = map.tileheight
local tileX = x / tileH local tileX = x / tileH
local tileY = y / tileH local tileY = y / tileH
local offsetX = mapW * tileW / 2 local offsetX = mapW * tileW / 2
return return (tileX - tileY) * tileW / 2 + offsetX, (tileX + tileY) * tileH / 2
(tileX - tileY) * tileW / 2 + offsetX,
(tileX + tileY) * tileH / 2
end end
function utils.hex_to_color(hex) function utils.hex_to_color(hex)
@ -175,16 +181,14 @@ function utils.hex_to_color(hex)
return { return {
r = tonumber(hex:sub(1, 2), 16) / 255, r = tonumber(hex:sub(1, 2), 16) / 255,
g = tonumber(hex:sub(3, 4), 16) / 255, g = tonumber(hex:sub(3, 4), 16) / 255,
b = tonumber(hex:sub(5, 6), 16) / 255 b = tonumber(hex:sub(5, 6), 16) / 255,
} }
end end
function utils.pixel_function(_, _, r, g, b, a) function utils.pixel_function(_, _, r, g, b, a)
local mask = utils._TC local mask = utils._TC
if r == mask.r and if r == mask.r and g == mask.g and b == mask.b then
g == mask.g and
b == mask.b then
return r, g, b, 0 return r, g, b, 0
end end
@ -205,7 +209,7 @@ end
function utils.deepCopy(t) function utils.deepCopy(t)
local copy = {} local copy = {}
for k,v in pairs(t) do for k, v in pairs(t) do
if type(v) == "table" then if type(v) == "table" then
v = utils.deepCopy(v) v = utils.deepCopy(v)
end end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,10 +1,14 @@
require 'constants' require("constants")
function love.run() function love.run()
if love.load then love.load(love.arg.parseGameArguments(arg), arg) end if love.load then
love.load(love.arg.parseGameArguments(arg), arg)
end
-- We don't want the first frame's dt to include time taken by love.load. -- We don't want the first frame's dt to include time taken by love.load.
if love.timer then love.timer.step() end if love.timer then
love.timer.step()
end
local dt = 0 local dt = 0
@ -13,32 +17,40 @@ function love.run()
-- Process events. -- Process events.
if love.event then if love.event then
love.event.pump() love.event.pump()
for name, a,b,c,d,e,f in love.event.poll() do for name, a, b, c, d, e, f in love.event.poll() do
if name == "quit" then if name == "quit" then
if not love.quit or not love.quit() then if not love.quit or not love.quit() then
return a or 0 return a or 0
end end
end end
love.handlers[name](a,b,c,d,e,f) love.handlers[name](a, b, c, d, e, f)
end end
end end
-- Update dt, as we'll be passing it to update -- Update dt, as we'll be passing it to update
if love.timer then dt = love.timer.step() end if love.timer then
dt = love.timer.step()
end
-- Call update and draw -- Call update and draw
if love.update then love.update(dt) end -- will pass 0 if love.timer is disabled if love.update then
love.update(dt)
end -- will pass 0 if love.timer is disabled
if love.graphics and love.graphics.isActive() then if love.graphics and love.graphics.isActive() then
love.graphics.origin() love.graphics.origin()
love.graphics.clear(love.graphics.getBackgroundColor()) love.graphics.clear(love.graphics.getBackgroundColor())
if love.draw then love.draw() end if love.draw then
love.draw()
end
love.graphics.present() love.graphics.present()
end end
if love.timer then love.timer.sleep(0.001) end if love.timer then
love.timer.sleep(0.001)
end
end end
end end
@ -92,7 +104,7 @@ function love.load()
--Bullet lists --Bullet lists
Bullets1 = {} Bullets1 = {}
Bullets2 = {} Bullets2 = {}
DebugFlag = false DebugFlag = false
EnableKeyPress1 = true EnableKeyPress1 = true
KeyPressTime1 = 0 KeyPressTime1 = 0
@ -112,12 +124,11 @@ function love.load()
musicStory = love.audio.newSource("music/story.mp3", "stream") musicStory = love.audio.newSource("music/story.mp3", "stream")
musicPause = musicBattle:clone() musicPause = musicBattle:clone()
musicPause:setFilter{ musicPause:setFilter({
type = 'lowpass', type = "lowpass",
volume = 0.3, volume = 0.7,
highgain = 0.4, highgain = 0.4,
} })
end end
function love.keypressed(key) function love.keypressed(key)
@ -130,7 +141,6 @@ function love.keypressed(key)
if _G.GAMESTATE == "GAME" then if _G.GAMESTATE == "GAME" then
GameKeyPressed(key) GameKeyPressed(key)
end end
end end
function love.update(dt) function love.update(dt)
@ -162,6 +172,11 @@ function love.update(dt)
love.audio.play(musicPause) love.audio.play(musicPause)
end end
end end
if _G.GAMESTATE == "WIN" then
print(P1_WIN)
print(P2_WIN)
love.event.quit()
end
end end
function love.draw() function love.draw()
@ -179,5 +194,4 @@ function love.draw()
love.graphics.print("" .. GAMESTATE, 200, 200) love.graphics.print("" .. GAMESTATE, 200, 200)
end end
end end
end end

@ -1,4 +1,4 @@
function loadMap(lvl) function loadMap(lvl)
local mapfilelocation = "maps/" local mapfilelocation = "maps/"
local extention = ".lua" local extention = ".lua"
local mapname = mapfilelocation .. "map" .. lvl .. extention local mapname = mapfilelocation .. "map" .. lvl .. extention
@ -13,4 +13,4 @@ function loadMap(lvl)
Walls[#Walls]:setCollisionClass("Wall") Walls[#Walls]:setCollisionClass("Wall")
end end
end end
end end

@ -47,79 +47,53 @@ function Player:shoot(bulletSpeed)
return newBullet return newBullet
end end
function handleKeys(dt) function Player:handleKeys(up, down, left, right, dt)
self.vx, self.vy = 0, 0 --reset every frame
if love.keyboard.isDown(up) then
self.vx = cos(self.rotation) * (self.speed * dt)
self.vy = sin(self.rotation) * (self.speed * dt)
elseif love.keyboard.isDown(down) then
self.vx = cos(self.rotation) * (self.speed * dt) * -1
self.vy = sin(self.rotation) * (self.speed * dt) * -1
elseif love.keyboard.isDown(left) then
self.rotation = self.rotation - (self.rotSpeed * dt)
elseif love.keyboard.isDown(right) then
self.rotation = self.rotation + (self.rotSpeed * dt)
end
self.collider:setLinearVelocity(self.vx, self.vy)
end
function Player:updateCol()
if self.p == 1 then
self.x = self.collider:getX()
self.y = self.collider:getY()
elseif self.p == 2 then
self.x = self.collider:getX()
self.y = self.collider:getY()
end
end end
-- Update method for the Player class -- Update method for the Player class
function Player:update(dt) function Player:update(dt)
if _G.GAMESTATE == "GAME" then local bulletSpeed = 20000
self.vx = 0
self.vy = 0 if EnableKeyPress1 == true and self.p == 1 then
local bulletSpeed = 20000 if love.keyboard.isDown("space") then
local newBullet = self:shoot(bulletSpeed)
if self.p == 1 then table.insert(Bullets1, newBullet)
-- Handle player 1 controls KeyPressTime1 = KeyDelay1
if love.keyboard.isDown("w") then EnableKeyPress1 = false
self.vx = cos(self.rotation) * (self.speed * dt) end
self.vy = sin(self.rotation) * (self.speed * dt) end
elseif love.keyboard.isDown("s") then
self.vx = cos(self.rotation) * (self.speed * dt) * -1
self.vy = sin(self.rotation) * (self.speed * dt) * -1
elseif love.keyboard.isDown("a") then
self.rotation = self.rotation - (self.rotSpeed * dt)
elseif love.keyboard.isDown("d") then
self.rotation = self.rotation + (self.rotSpeed * dt)
end
self.collider:setLinearVelocity(self.vx, self.vy)
-- Check for collision with walls
if self.collider:enter("Wall") then
print("Player 1 collided with wall")
end
if EnableKeyPress1 == true and GAMESTATE == "GAME" then
if love.keyboard.isDown("space") then
local newBullet = self:shoot(bulletSpeed)
table.insert(Bullets1, newBullet)
KeyPressTime1 = KeyDelay1
EnableKeyPress1 = false
end
end
self.x = self.collider:getX()
self.y = self.collider:getY()
elseif self.p == 2 then
-- Handle player 2 controls
if love.keyboard.isDown("up") then
self.vx = cos(self.rotation) * (self.speed * dt)
self.vy = sin(self.rotation) * (self.speed * dt)
elseif love.keyboard.isDown("down") then
self.vx = cos(self.rotation) * (self.speed * dt) * -1
self.vy = sin(self.rotation) * (self.speed * dt) * -1
elseif love.keyboard.isDown("left") then
self.rotation = self.rotation - (self.rotSpeed * dt)
elseif love.keyboard.isDown("right") then
self.rotation = self.rotation + (self.rotSpeed * dt)
end
self.collider:setLinearVelocity(self.vx, self.vy)
-- Check for collision with walls
if self.collider:enter("Wall") then
print("Player 2 collided with wall")
end
if EnableKeyPress2 == true then if EnableKeyPress2 == true and self.p == 2 then
if love.keyboard.isDown("return") then if love.keyboard.isDown("return") then
local newBullet = self:shoot(bulletSpeed) local newBullet = self:shoot(bulletSpeed)
table.insert(Bullets2, newBullet) table.insert(Bullets2, newBullet)
KeyPressTime2 = KeyDelay2 KeyPressTime2 = KeyDelay2
EnableKeyPress2 = false EnableKeyPress2 = false
end
end
end end
self.x = self.collider:getX()
self.y = self.collider:getY()
end end
end end

Loading…
Cancel
Save