format and stuff
This commit is contained in:
parent
53aa6d698d
commit
99b420cc7f
@ -1,8 +1,7 @@
|
||||
function GameKeyPressed(key)
|
||||
|
||||
if key == "escape" then
|
||||
musicBattle:setVolume(0)
|
||||
musicPause:setVolume(0.5)
|
||||
musicPause:setVolume(0.6)
|
||||
|
||||
_G.GAMESTATE = "PAUSE"
|
||||
print("STATE CHANEGD: PAUSED!")
|
||||
@ -13,13 +12,8 @@ function GameKeyPressed(key)
|
||||
DebugFlag = not DebugFlag
|
||||
end
|
||||
|
||||
--TODO: Move player movement code into here!
|
||||
|
||||
|
||||
--[[
|
||||
-- TODO: Better restart
|
||||
--TODO: Better restart
|
||||
if key == "r" and not _G.PAUSED then
|
||||
love.load()
|
||||
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)
|
||||
--Check if anyone has won
|
||||
if checkWinState() == true then
|
||||
print("STATE CHNAGED: WIN!")
|
||||
_G.GAMESTATE = "WIN"
|
||||
end
|
||||
--WindField
|
||||
World:update(dt)
|
||||
|
||||
local max = math.max
|
||||
|
||||
KeyPressTime1 = max(0, KeyPressTime1 - dt)
|
||||
if KeyPressTime1 <= 0 then
|
||||
EnableKeyPress1 = true
|
||||
@ -13,6 +35,7 @@ function UpdateGame(dt)
|
||||
if KeyPressTime2 <= 0 then
|
||||
EnableKeyPress2 = true
|
||||
end
|
||||
|
||||
for i, v in ipairs(Bullets1) do
|
||||
v:update(dt)
|
||||
if v.y < 0 then --top of screen
|
||||
@ -69,7 +92,10 @@ function UpdateGame(dt)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
UserPlayer1:handleKeys("w", "s", "a", "d", dt)
|
||||
UserPlayer2:handleKeys("up", "down", "left", "right", dt)
|
||||
UserPlayer1:updateCol()
|
||||
UserPlayer2:updateCol()
|
||||
UserPlayer1:update(dt)
|
||||
UserPlayer2:update(dt)
|
||||
end
|
||||
|
@ -1,11 +1,11 @@
|
||||
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
|
||||
local rounding = 30 -- used for rounding the buttons
|
||||
|
||||
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
|
||||
love.graphics.setColor(love.math.colorFromBytes(244,67,54))
|
||||
love.graphics.setColor(love.math.colorFromBytes(244, 67, 54))
|
||||
end
|
||||
-- Draw rectangle
|
||||
love.graphics.rectangle("line", x, y, w, h, rounding, rounding)
|
||||
@ -25,13 +25,12 @@ local function title()
|
||||
local height = love.graphics.getHeight()
|
||||
local width = love.graphics.getWidth()
|
||||
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.setColor(0,0,0)
|
||||
love.graphics.print("MENU", 100,100)
|
||||
love.graphics.setColor(0, 0, 0)
|
||||
love.graphics.print("MENU", 100, 100)
|
||||
end
|
||||
|
||||
|
||||
function DrawMenu()
|
||||
local bwidth, bheight = 300, 140
|
||||
title()
|
||||
@ -40,5 +39,5 @@ function DrawMenu()
|
||||
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)
|
||||
|
||||
love.graphics.setColor(255,255,255) -- reset colours
|
||||
love.graphics.setColor(255, 255, 255) -- reset colours
|
||||
end
|
@ -1,5 +1,5 @@
|
||||
function MenuKeyPressed(key)
|
||||
if key == 'return' then
|
||||
if key == "return" then
|
||||
-- 0 Start Game
|
||||
-- 1 ??
|
||||
-- 2 ???
|
||||
@ -9,17 +9,13 @@ function MenuKeyPressed(key)
|
||||
_G.GAMESTATE = "GAME"
|
||||
print("STATE CHANEGD: GAME!")
|
||||
musicMenu:stop()
|
||||
|
||||
elseif MENU_POS == 1 then
|
||||
print("STATE CHANEGD: DUNNO!")
|
||||
|
||||
elseif MENU_POS == 2 then
|
||||
print("STATE CHANEGD: DUNNO!")
|
||||
|
||||
elseif MENU_POS == 3 then
|
||||
love.event.quit()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if love.keyboard.isDown("up") then
|
||||
@ -37,5 +33,4 @@ function MenuKeyPressed(key)
|
||||
_G.MENU_POS = _G.MENU_POS + 1
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1,2 +1 @@
|
||||
function UpdateMenu(dt)
|
||||
end
|
||||
function UpdateMenu(dt) end
|
||||
|
@ -1,11 +1,11 @@
|
||||
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
|
||||
local rounding = 30 -- used for rounding the buttons
|
||||
|
||||
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
|
||||
love.graphics.setColor(love.math.colorFromBytes(244,67,54))
|
||||
love.graphics.setColor(love.math.colorFromBytes(244, 67, 54))
|
||||
end
|
||||
-- Draw rectangle
|
||||
love.graphics.rectangle("fill", x, y, w, h, rounding, rounding)
|
||||
@ -18,11 +18,10 @@ local function button(x,y, w, h, text, selected)
|
||||
local textY = y + (h - th) / 2
|
||||
-- Place text inside the rectangle
|
||||
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)
|
||||
end
|
||||
|
||||
|
||||
function DrawPause()
|
||||
local opacity = 0.3
|
||||
local height = love.graphics.getHeight()
|
||||
@ -31,15 +30,15 @@ function DrawPause()
|
||||
love.graphics.setFont(GameFont)
|
||||
|
||||
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.setColor(1,1,1)
|
||||
love.graphics.print("PAUSED", 100,100)
|
||||
love.graphics.setColor(1, 1, 1)
|
||||
love.graphics.print("PAUSED", 100, 100)
|
||||
--love.graphics.print("" .. PAUSE_POS, 200,200)
|
||||
|
||||
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, 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
|
@ -1,5 +1,5 @@
|
||||
function PauseKeyPressed(key)
|
||||
if key == 'return' then
|
||||
if key == "return" then
|
||||
musicBattle:setVolume(0.5)
|
||||
musicPause:setVolume(0)
|
||||
-- 0 Return to game
|
||||
@ -11,21 +11,17 @@ function PauseKeyPressed(key)
|
||||
_G.PAUSED = false
|
||||
musicBattle:setVolume(0.5)
|
||||
musicPause:setVolume(0)
|
||||
|
||||
elseif PAUSE_POS == 1 then
|
||||
_G.GAMESTATE = "MENU"
|
||||
print("STATE CHANEGD: MENU!")
|
||||
_G.PAUSED = false
|
||||
musicPause:stop()
|
||||
musicBattle:stop()
|
||||
|
||||
elseif PAUSE_POS == 2 then
|
||||
love.event.quit()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
if love.keyboard.isDown("up") then
|
||||
if _G.PAUSE_POS == 0 then
|
||||
_G.PAUSE_POS = 0
|
||||
|
@ -1,2 +1 @@
|
||||
function UpdatePause(dt)
|
||||
end
|
||||
function UpdatePause(dt) end
|
||||
|
@ -1,3 +1,11 @@
|
||||
--[[
|
||||
* Game states:
|
||||
* - MENU
|
||||
* - GAME
|
||||
* - PAUSE
|
||||
* - WIN
|
||||
]]
|
||||
--
|
||||
GAMESTATE = "MENU"
|
||||
|
||||
MENU_POS = 0
|
||||
@ -6,3 +14,7 @@ MENU_MAX = 3 --0 play, 1 ?, 2 ?, 3 quit
|
||||
PAUSED = false
|
||||
PAUSE_POS = 0
|
||||
PAUSE_MAX = 2 -- 0 resume, 1 menu, 2 quit
|
||||
|
||||
-- WIN flags for P1 and P2
|
||||
P1_WIN = false
|
||||
P2_WIN = false
|
||||
|
@ -7,14 +7,10 @@
|
||||
-- the terms of the MIT license. See LICENSE for details.
|
||||
--
|
||||
|
||||
|
||||
local Object = {}
|
||||
Object.__index = Object
|
||||
|
||||
|
||||
function Object:new()
|
||||
end
|
||||
|
||||
function Object:new() end
|
||||
|
||||
function Object:extend()
|
||||
local cls = {}
|
||||
@ -29,9 +25,8 @@ function Object:extend()
|
||||
return cls
|
||||
end
|
||||
|
||||
|
||||
function Object:implement(...)
|
||||
for _, cls in pairs({...}) do
|
||||
for _, cls in pairs({ ... }) do
|
||||
for k, v in pairs(cls) do
|
||||
if self[k] == nil and type(v) == "function" then
|
||||
self[k] = v
|
||||
@ -40,7 +35,6 @@ function Object:implement(...)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Object:is(T)
|
||||
local mt = getmetatable(self)
|
||||
while mt do
|
||||
@ -52,17 +46,14 @@ function Object:is(T)
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function Object:__tostring()
|
||||
return "Object"
|
||||
end
|
||||
|
||||
|
||||
function Object:__call(...)
|
||||
local obj = setmetatable({}, self)
|
||||
obj:new(...)
|
||||
return obj
|
||||
end
|
||||
|
||||
|
||||
return Object
|
||||
|
@ -23,7 +23,7 @@ local _internal = {}
|
||||
-- @tparam number line Line number
|
||||
-- @tparam[opt] table info Debug info table
|
||||
function profile.hooker(event, line, info)
|
||||
info = info or debug.getinfo(2, 'fnS')
|
||||
info = info or debug.getinfo(2, "fnS")
|
||||
local f = info.func
|
||||
-- ignore the profiler itself
|
||||
if _internal[f] or info.what ~= "Lua" then
|
||||
@ -35,7 +35,7 @@ function profile.hooker(event, line, info)
|
||||
end
|
||||
-- find the line definition
|
||||
if not _defined[f] then
|
||||
_defined[f] = info.short_src..":"..info.linedefined
|
||||
_defined[f] = info.short_src .. ":" .. info.linedefined
|
||||
_ncalls[f] = 0
|
||||
_telapsed[f] = 0
|
||||
end
|
||||
@ -45,10 +45,10 @@ function profile.hooker(event, line, info)
|
||||
_tcalled[f] = nil
|
||||
end
|
||||
if event == "tail call" then
|
||||
local prev = debug.getinfo(3, 'fnS')
|
||||
local prev = debug.getinfo(3, "fnS")
|
||||
profile.hooker("return", line, prev)
|
||||
profile.hooker("call", line, info)
|
||||
elseif event == 'call' then
|
||||
elseif event == "call" then
|
||||
_tcalled[f] = clock()
|
||||
else
|
||||
_ncalls[f] = _ncalls[f] + 1
|
||||
@ -64,7 +64,7 @@ end
|
||||
|
||||
--- Starts collecting data.
|
||||
function profile.start()
|
||||
if rawget(_G, 'jit') then
|
||||
if rawget(_G, "jit") then
|
||||
jit.off()
|
||||
jit.flush()
|
||||
end
|
||||
@ -82,7 +82,7 @@ function profile.stop()
|
||||
-- merge closures
|
||||
local lookup = {}
|
||||
for f, d in pairs(_defined) do
|
||||
local id = (_labeled[f] or '?')..d
|
||||
local id = (_labeled[f] or "?") .. d
|
||||
local f2 = lookup[id]
|
||||
if f2 then
|
||||
_ncalls[f2] = _ncalls[f2] + (_ncalls[f] or 0)
|
||||
@ -93,7 +93,7 @@ function profile.stop()
|
||||
lookup[id] = f
|
||||
end
|
||||
end
|
||||
collectgarbage('collect')
|
||||
collectgarbage("collect")
|
||||
end
|
||||
|
||||
--- Resets all collected data.
|
||||
@ -107,7 +107,7 @@ function profile.reset()
|
||||
for f in pairs(_tcalled) do
|
||||
_tcalled[f] = nil
|
||||
end
|
||||
collectgarbage('collect')
|
||||
collectgarbage("collect")
|
||||
end
|
||||
|
||||
--- This is an internal function.
|
||||
@ -144,7 +144,7 @@ function profile.query(limit)
|
||||
if _tcalled[f] then
|
||||
dt = clock() - _tcalled[f]
|
||||
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
|
||||
return t
|
||||
end
|
||||
@ -165,22 +165,24 @@ function profile.report(n)
|
||||
s = tostring(s)
|
||||
local l1 = s:len()
|
||||
if l1 < l2 then
|
||||
s = s..(' '):rep(l2-l1)
|
||||
s = s .. (" "):rep(l2 - l1)
|
||||
elseif l1 > l2 then
|
||||
s = s:sub(l1 - l2 + 1, l1)
|
||||
end
|
||||
row[j] = s
|
||||
end
|
||||
out[i] = table.concat(row, ' | ')
|
||||
out[i] = table.concat(row, " | ")
|
||||
end
|
||||
|
||||
local row = " +-----+-------------------------------+-------------+--------------------------+----------------------------------+ \n"
|
||||
local col = " | # | Function | Calls | Time | Code | \n"
|
||||
local sz = row..col..row
|
||||
local row =
|
||||
" +-----+-------------------------------+-------------+--------------------------+----------------------------------+ \n"
|
||||
local col =
|
||||
" | # | Function | Calls | Time | Code | \n"
|
||||
local sz = row .. col .. row
|
||||
if #out > 0 then
|
||||
sz = sz..' | '..table.concat(out, ' | \n | ')..' | \n'
|
||||
sz = sz .. " | " .. table.concat(out, " | \n | ") .. " | \n"
|
||||
end
|
||||
return '\n'..sz..row
|
||||
return "\n" .. sz .. row
|
||||
end
|
||||
|
||||
-- store all internal profiler functions
|
||||
|
@ -10,13 +10,12 @@ local module = {}
|
||||
-- @param sort If "size" will sort by size, or if "id" will sort by id
|
||||
-- @param ids Array with ids of each file
|
||||
-- @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)
|
||||
return {x = x, y = y, w = w, h = h}
|
||||
return { x = x, y = y, w = w, h = h }
|
||||
end
|
||||
|
||||
local function nextpow2( n )
|
||||
local function nextpow2(n)
|
||||
local res = 1
|
||||
while res <= n do
|
||||
res = res * 2
|
||||
@ -29,14 +28,18 @@ function module.Atlas( files, sort, ids, pow2 )
|
||||
for i = 1, #files do
|
||||
images[i] = {}
|
||||
--images[i].name = files[i]
|
||||
if ids then images[i].id = ids[i] end
|
||||
images[i].img = love.graphics.newImage( files[i] )
|
||||
if ids then
|
||||
images[i].id = ids[i]
|
||||
end
|
||||
images[i].img = love.graphics.newImage(files[i])
|
||||
images[i].w = images[i].img:getWidth()
|
||||
images[i].h = images[i].img:getHeight()
|
||||
images[i].area = images[i].w * images[i].h
|
||||
end
|
||||
if sort == "size" or sort == "id" then
|
||||
table.sort( images, function( a, b ) return ( a.area > b.area ) end )
|
||||
table.sort(images, function(a, b)
|
||||
return (a.area > b.area)
|
||||
end)
|
||||
end
|
||||
return images
|
||||
end
|
||||
@ -46,16 +49,22 @@ function module.Atlas( files, sort, ids, pow2 )
|
||||
if root.left or root.right then
|
||||
if root.left then
|
||||
local node = add(root.left, id, w, h)
|
||||
if node then return node end
|
||||
if node then
|
||||
return node
|
||||
end
|
||||
end
|
||||
if root.right then
|
||||
local node = add(root.right, id, w, h)
|
||||
if node then return node end
|
||||
if node then
|
||||
return node
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
if w > root.w or h > root.h then return nil end
|
||||
if w > root.w or h > root.h then
|
||||
return nil
|
||||
end
|
||||
|
||||
local _w, _h = root.w - w, root.h - h
|
||||
|
||||
@ -75,7 +84,9 @@ function module.Atlas( files, sort, ids, pow2 )
|
||||
end
|
||||
|
||||
local function unmap(root)
|
||||
if not root then return {} end
|
||||
if not root then
|
||||
return {}
|
||||
end
|
||||
|
||||
local tree = {}
|
||||
if root.id then
|
||||
@ -105,8 +116,12 @@ function module.Atlas( files, sort, ids, pow2 )
|
||||
local w, h = images[1].w, images[1].h
|
||||
|
||||
if pow2 then
|
||||
if w % 1 == 0 then w = nextpow2(w) end
|
||||
if h % 1 == 0 then h = nextpow2(h) end
|
||||
if w % 1 == 0 then
|
||||
w = nextpow2(w)
|
||||
end
|
||||
if h % 1 == 0 then
|
||||
h = nextpow2(h)
|
||||
end
|
||||
end
|
||||
|
||||
repeat
|
||||
@ -116,14 +131,24 @@ function module.Atlas( files, sort, ids, pow2 )
|
||||
|
||||
for i = 1, #images do
|
||||
node = add(root, i, images[i].w, images[i].h)
|
||||
if not node then break end
|
||||
if not node then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not node then
|
||||
if h <= w then
|
||||
if pow2 then h = h * 2 else h = h + 1 end
|
||||
if pow2 then
|
||||
h = h * 2
|
||||
else
|
||||
if pow2 then w = w * 2 else w = w + 1 end
|
||||
h = h + 1
|
||||
end
|
||||
else
|
||||
if pow2 then
|
||||
w = w * 2
|
||||
else
|
||||
w = w + 1
|
||||
end
|
||||
end
|
||||
else
|
||||
break
|
||||
@ -137,17 +162,21 @@ function module.Atlas( files, sort, ids, pow2 )
|
||||
|
||||
local coords = unmap(root)
|
||||
local map = love.graphics.newCanvas(w, h)
|
||||
love.graphics.setCanvas( map )
|
||||
-- love.graphics.clear()
|
||||
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
|
||||
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 )
|
||||
table.sort(coords, function(a, b)
|
||||
return (a.id < b.id)
|
||||
end)
|
||||
end
|
||||
|
||||
return { image = map, coords = coords }
|
||||
|
@ -9,12 +9,12 @@ local STI = {
|
||||
_URL = "https://github.com/karai17/Simple-Tiled-Implementation",
|
||||
_VERSION = "1.2.3.0",
|
||||
_DESCRIPTION = "Simple Tiled Implementation is a Tiled Map Editor library designed for the *awesome* LÖVE framework.",
|
||||
cache = {}
|
||||
cache = {},
|
||||
}
|
||||
STI.__index = STI
|
||||
|
||||
local love = _G.love
|
||||
local cwd = (...):gsub('%.init$', '') .. "."
|
||||
local cwd = (...):gsub("%.init$", "") .. "."
|
||||
local utils = require(cwd .. "utils")
|
||||
local ceil = math.ceil
|
||||
local floor = math.floor
|
||||
@ -31,10 +31,7 @@ local function new(map, plugins, ox, oy)
|
||||
else
|
||||
-- Check for valid map type
|
||||
local ext = map:sub(-4, -1)
|
||||
assert(ext == ".lua", string.format(
|
||||
"Invalid file type: %s. File must be of type: lua.",
|
||||
ext
|
||||
))
|
||||
assert(ext == ".lua", string.format("Invalid file type: %s. File must be of type: lua.", ext))
|
||||
|
||||
-- Get directory of map
|
||||
dir = map:reverse():find("[/\\]") or ""
|
||||
@ -86,7 +83,7 @@ function Map:init(path, plugins, ox, oy)
|
||||
self.offsety = oy or 0
|
||||
|
||||
self.freeBatchSprites = {}
|
||||
setmetatable(self.freeBatchSprites, { __mode = 'k' })
|
||||
setmetatable(self.freeBatchSprites, { __mode = "k" })
|
||||
|
||||
-- Set tiles, images
|
||||
local gid = 1
|
||||
@ -111,11 +108,11 @@ function Map:init(path, plugins, ox, oy)
|
||||
-- Build atlas for image collection
|
||||
local files, ids = {}, {}
|
||||
for j = 1, #tileset.tiles do
|
||||
files[ j ] = utils.format_path(path .. tileset.tiles[j].image)
|
||||
ids[ j ] = tileset.tiles[j].id
|
||||
files[j] = utils.format_path(path .. tileset.tiles[j].image)
|
||||
ids[j] = tileset.tiles[j].id
|
||||
end
|
||||
|
||||
local map = atlas.Atlas( files, "ids", ids )
|
||||
local map = atlas.Atlas(files, "ids", ids)
|
||||
|
||||
if lg.isCreated then
|
||||
local formatted_path = utils.format_path(path .. tileset.name)
|
||||
@ -174,7 +171,7 @@ end
|
||||
-- @param plugins A list of plugins to load
|
||||
function Map:loadPlugins(plugins)
|
||||
for _, plugin in ipairs(plugins) do
|
||||
local pluginModulePath = cwd .. 'plugins.' .. plugin
|
||||
local pluginModulePath = cwd .. "plugins." .. plugin
|
||||
local ok, pluginModule = pcall(require, pluginModulePath)
|
||||
if ok then
|
||||
for k, func in pairs(pluginModule) do
|
||||
@ -232,11 +229,7 @@ function Map:setTiles(index, tileset, gid)
|
||||
gid = gid,
|
||||
tileset = index,
|
||||
type = type,
|
||||
quad = quad(
|
||||
quadX, quadY,
|
||||
tileW, tileH,
|
||||
imageW, imageH
|
||||
),
|
||||
quad = quad(quadX, quadY, tileW, tileH, imageW, imageH),
|
||||
properties = properties or {},
|
||||
terrain = terrain,
|
||||
animation = animation,
|
||||
@ -286,11 +279,7 @@ function Map:setAtlasTiles(index, tileset, coords, gid)
|
||||
gid = firstgid + tile.id,
|
||||
tileset = index,
|
||||
class = tile.class,
|
||||
quad = quad(
|
||||
coords[i].x, coords[i].y,
|
||||
tile.width, tile.height,
|
||||
imageW, imageH
|
||||
),
|
||||
quad = quad(coords[i].x, coords[i].y, tile.width, tile.height, imageW, imageH),
|
||||
properties = tile.properties or {},
|
||||
terrain = terrain,
|
||||
animation = tile.animation,
|
||||
@ -318,13 +307,19 @@ end
|
||||
function Map:setLayer(layer, path)
|
||||
if layer.encoding then
|
||||
if layer.encoding == "base64" then
|
||||
assert(require "ffi", "Compressed maps require LuaJIT FFI.\nPlease Switch your interperator to LuaJIT or your Tile Layer Format to \"CSV\".")
|
||||
assert(
|
||||
require("ffi"),
|
||||
'Compressed maps require LuaJIT FFI.\nPlease Switch your interperator to LuaJIT or your Tile Layer Format to "CSV".'
|
||||
)
|
||||
local fd = love.data.decode("string", "base64", layer.data)
|
||||
|
||||
if not layer.compression then
|
||||
layer.data = utils.get_decompressed_data(fd)
|
||||
else
|
||||
assert(love.data.decompress, "zlib and gzip compression require LOVE 11.0+.\nPlease set your Tile Layer Format to \"Base64 (uncompressed)\" or \"CSV\".")
|
||||
assert(
|
||||
love.data.decompress,
|
||||
'zlib and gzip compression require LOVE 11.0+.\nPlease set your Tile Layer Format to "Base64 (uncompressed)" or "CSV".'
|
||||
)
|
||||
|
||||
if layer.compression == "zlib" then
|
||||
local data = love.data.decompress("string", "zlib", fd)
|
||||
@ -346,14 +341,20 @@ function Map:setLayer(layer, path)
|
||||
if layer.type == "tilelayer" then
|
||||
self:setTileData(layer)
|
||||
self:setSpriteBatches(layer)
|
||||
layer.draw = function() self:drawTileLayer(layer) end
|
||||
layer.draw = function()
|
||||
self:drawTileLayer(layer)
|
||||
end
|
||||
elseif layer.type == "objectgroup" then
|
||||
self:setObjectData(layer)
|
||||
self:setObjectCoordinates(layer)
|
||||
self:setObjectSpriteBatches(layer)
|
||||
layer.draw = function() self:drawObjectLayer(layer) end
|
||||
layer.draw = function()
|
||||
self:drawObjectLayer(layer)
|
||||
end
|
||||
elseif layer.type == "imagelayer" then
|
||||
layer.draw = function() self:drawImageLayer(layer) end
|
||||
layer.draw = function()
|
||||
self:drawImageLayer(layer)
|
||||
end
|
||||
|
||||
if layer.image ~= "" then
|
||||
local formatted_path = utils.format_path(path .. layer.image)
|
||||
@ -424,10 +425,10 @@ function Map:setObjectCoordinates(layer)
|
||||
object.rectangle = {}
|
||||
|
||||
local vertices = {
|
||||
{ x=x, y=y },
|
||||
{ x=x + w, y=y },
|
||||
{ x=x + w, y=y + h },
|
||||
{ x=x, y=y + h },
|
||||
{ x = x, y = y },
|
||||
{ x = x + w, y = y },
|
||||
{ x = x + w, y = y + h },
|
||||
{ x = x, y = y + h },
|
||||
}
|
||||
|
||||
for _, vertex in ipairs(vertices) do
|
||||
@ -551,7 +552,7 @@ function Map:addNewLayerTile(layer, chunk, tile, x, y)
|
||||
x = tileX,
|
||||
y = tileY,
|
||||
r = tile.r,
|
||||
oy = 0
|
||||
oy = 0,
|
||||
}
|
||||
|
||||
-- NOTE: STI can run headless so it is not guaranteed that a batch exists.
|
||||
@ -738,7 +739,7 @@ function Map:setObjectSpriteBatches(layer)
|
||||
x = tileX,
|
||||
y = tileY - oy,
|
||||
r = tileR,
|
||||
oy = oy
|
||||
oy = oy,
|
||||
}
|
||||
|
||||
self.tileInstances[tile.gid] = self.tileInstances[tile.gid] or {}
|
||||
@ -866,12 +867,15 @@ function Map:update(dt)
|
||||
tile.time = tile.time - tonumber(tile.animation[tile.frame].duration)
|
||||
tile.frame = tile.frame + 1
|
||||
|
||||
if tile.frame > #tile.animation then tile.frame = 1 end
|
||||
if tile.frame > #tile.animation then
|
||||
tile.frame = 1
|
||||
end
|
||||
end
|
||||
|
||||
if update and self.tileInstances[tile.gid] then
|
||||
for _, j in pairs(self.tileInstances[tile.gid]) do
|
||||
local t = self.tiles[tonumber(tile.animation[tile.frame].tileid) + self.tilesets[tile.tileset].firstgid]
|
||||
local t =
|
||||
self.tiles[tonumber(tile.animation[tile.frame].tileid) + self.tilesets[tile.tileset].firstgid]
|
||||
j.batch:set(j.id, t.quad, j.x, j.y, j.r, tile.sx, tile.sy, 0, j.oy)
|
||||
end
|
||||
end
|
||||
@ -948,18 +952,18 @@ end
|
||||
--- Draw an individual Layer
|
||||
-- @param layer The Layer to draw
|
||||
function Map.drawLayer(_, layer)
|
||||
local r,g,b,a = lg.getColor()
|
||||
local r, g, b, a = lg.getColor()
|
||||
-- if the layer has a tintcolor set
|
||||
if layer.tintcolor then
|
||||
r, g, b, a = unpack(layer.tintcolor)
|
||||
a = a or 255 -- alpha may not be specified
|
||||
lg.setColor(r/255, g/255, b/255, a/255) -- Tiled uses 0-255
|
||||
lg.setColor(r / 255, g / 255, b / 255, a / 255) -- Tiled uses 0-255
|
||||
-- if a tintcolor is not given just use the current color
|
||||
else
|
||||
lg.setColor(r, g, b, a * layer.opacity)
|
||||
end
|
||||
layer:draw()
|
||||
lg.setColor(r,g,b,a)
|
||||
lg.setColor(r, g, b, a)
|
||||
end
|
||||
|
||||
--- Default draw function for Tile Layers
|
||||
@ -998,7 +1002,7 @@ function Map:drawObjectLayer(layer)
|
||||
|
||||
local line = { 160, 160, 160, 255 * layer.opacity }
|
||||
local fill = { 160, 160, 160, 255 * layer.opacity * 0.5 }
|
||||
local r,g,b,a = lg.getColor()
|
||||
local r, g, b, a = lg.getColor()
|
||||
local reset = { r, g, b, a * layer.opacity }
|
||||
|
||||
local function sortVertices(obj)
|
||||
@ -1058,7 +1062,7 @@ function Map:drawObjectLayer(layer)
|
||||
for _, batch in pairs(layer.batches) do
|
||||
lg.draw(batch, 0, 0)
|
||||
end
|
||||
lg.setColor(r,g,b,a)
|
||||
lg.setColor(r, g, b, a)
|
||||
end
|
||||
|
||||
--- Default draw function for Image Layers
|
||||
@ -1284,22 +1288,9 @@ function Map:swapTile(instance, tile)
|
||||
-- Update sprite batch
|
||||
if instance.batch then
|
||||
if tile then
|
||||
instance.batch:set(
|
||||
instance.id,
|
||||
tile.quad,
|
||||
instance.x,
|
||||
instance.y,
|
||||
tile.r,
|
||||
tile.sx,
|
||||
tile.sy
|
||||
)
|
||||
instance.batch:set(instance.id, tile.quad, instance.x, instance.y, tile.r, tile.sx, tile.sy)
|
||||
else
|
||||
instance.batch:set(
|
||||
instance.id,
|
||||
instance.x,
|
||||
instance.y,
|
||||
0,
|
||||
0)
|
||||
instance.batch:set(instance.id, instance.x, instance.y, 0, 0)
|
||||
|
||||
self.freeBatchSprites[instance.batch] = self.freeBatchSprites[instance.batch] or {}
|
||||
table.insert(self.freeBatchSprites[instance.batch], instance)
|
||||
@ -1344,35 +1335,26 @@ end
|
||||
-- @param y The Y axis location of the point (in tiles)
|
||||
-- @return number The X axis location of the point (in pixels)
|
||||
-- @return number The Y axis location of the point (in pixels)
|
||||
function Map:convertTileToPixel(x,y)
|
||||
function Map:convertTileToPixel(x, y)
|
||||
if self.orientation == "orthogonal" then
|
||||
local tileW = self.tilewidth
|
||||
local tileH = self.tileheight
|
||||
return
|
||||
x * tileW,
|
||||
y * tileH
|
||||
return x * tileW, y * tileH
|
||||
elseif self.orientation == "isometric" then
|
||||
local mapH = self.height
|
||||
local tileW = self.tilewidth
|
||||
local tileH = self.tileheight
|
||||
local offsetX = mapH * tileW / 2
|
||||
return
|
||||
(x - y) * tileW / 2 + offsetX,
|
||||
(x + y) * tileH / 2
|
||||
elseif self.orientation == "staggered" or
|
||||
self.orientation == "hexagonal" then
|
||||
return (x - y) * tileW / 2 + offsetX, (x + y) * tileH / 2
|
||||
elseif self.orientation == "staggered" or self.orientation == "hexagonal" then
|
||||
local tileW = self.tilewidth
|
||||
local tileH = self.tileheight
|
||||
local sideLen = self.hexsidelength or 0
|
||||
|
||||
if self.staggeraxis == "x" then
|
||||
return
|
||||
x * tileW,
|
||||
ceil(y) * (tileH + sideLen) + (ceil(y) % 2 == 0 and tileH or 0)
|
||||
return x * tileW, ceil(y) * (tileH + sideLen) + (ceil(y) % 2 == 0 and tileH or 0)
|
||||
else
|
||||
return
|
||||
ceil(x) * (tileW + sideLen) + (ceil(x) % 2 == 0 and tileW or 0),
|
||||
y * tileH
|
||||
return ceil(x) * (tileW + sideLen) + (ceil(x) % 2 == 0 and tileW or 0), y * tileH
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1386,17 +1368,13 @@ function Map:convertPixelToTile(x, y)
|
||||
if self.orientation == "orthogonal" then
|
||||
local tileW = self.tilewidth
|
||||
local tileH = self.tileheight
|
||||
return
|
||||
x / tileW,
|
||||
y / tileH
|
||||
return x / tileW, y / tileH
|
||||
elseif self.orientation == "isometric" then
|
||||
local mapH = self.height
|
||||
local tileW = self.tilewidth
|
||||
local tileH = self.tileheight
|
||||
local offsetX = mapH * tileW / 2
|
||||
return
|
||||
y / tileH + (x - offsetX) / tileW,
|
||||
y / tileH - (x - offsetX) / tileW
|
||||
return y / tileH + (x - offsetX) / tileW, y / tileH - (x - offsetX) / tileW
|
||||
elseif self.orientation == "staggered" then
|
||||
local staggerX = self.staggeraxis == "x"
|
||||
local even = self.staggerindex == "even"
|
||||
@ -1481,13 +1459,13 @@ function Map:convertPixelToTile(x, y)
|
||||
local relativeX = x - referenceX * tileW
|
||||
local relativeY = y - referenceY * tileH
|
||||
|
||||
if (halfH - relativeX * ratio > relativeY) then
|
||||
if halfH - relativeX * ratio > relativeY then
|
||||
return topLeft(referenceX, referenceY)
|
||||
elseif (-halfH + relativeX * ratio > relativeY) then
|
||||
elseif -halfH + relativeX * ratio > relativeY then
|
||||
return topRight(referenceX, referenceY)
|
||||
elseif (halfH + relativeX * ratio < relativeY) then
|
||||
elseif halfH + relativeX * ratio < relativeY then
|
||||
return bottomLeft(referenceX, referenceY)
|
||||
elseif (halfH * 3 - relativeX * ratio < relativeY) then
|
||||
elseif halfH * 3 - relativeX * ratio < relativeY then
|
||||
return bottomRight(referenceX, referenceY)
|
||||
end
|
||||
|
||||
@ -1550,7 +1528,7 @@ function Map:convertPixelToTile(x, y)
|
||||
{ x = centerX, y = top },
|
||||
{ x = centerX - colW, y = centerY },
|
||||
{ x = centerX + colW, y = centerY },
|
||||
{ x = centerX, y = centerY + rowH }
|
||||
{ x = centerX, y = centerY + rowH },
|
||||
}
|
||||
end
|
||||
|
||||
@ -1586,9 +1564,7 @@ function Map:convertPixelToTile(x, y)
|
||||
|
||||
local offsets = staggerX and offsetsStaggerX or offsetsStaggerY
|
||||
|
||||
return
|
||||
referenceX + offsets[nearest].x,
|
||||
referenceY + offsets[nearest].y
|
||||
return referenceX + offsets[nearest].x, referenceY + offsets[nearest].y
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
-- @license MIT/X11
|
||||
|
||||
local love = _G.love
|
||||
local utils = require((...):gsub('plugins.box2d', 'utils'))
|
||||
local lg = require((...):gsub('plugins.box2d', 'graphics'))
|
||||
local utils = require((...):gsub("plugins.box2d", "utils"))
|
||||
local lg = require((...):gsub("plugins.box2d", "graphics"))
|
||||
|
||||
return {
|
||||
box2d_LICENSE = "MIT/X11",
|
||||
@ -40,13 +40,13 @@ return {
|
||||
local currentBody = body
|
||||
--dynamic are objects/players etc.
|
||||
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.
|
||||
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
|
||||
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
|
||||
|
||||
local fixture = love.physics.newFixture(currentBody, shape)
|
||||
@ -89,12 +89,12 @@ return {
|
||||
y = (object.dy or object.y) + map.offsety,
|
||||
w = object.width,
|
||||
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 = {
|
||||
object = o,
|
||||
properties = object.properties
|
||||
properties = object.properties,
|
||||
}
|
||||
|
||||
o.r = object.rotation or 0
|
||||
@ -133,10 +133,10 @@ return {
|
||||
end
|
||||
|
||||
o.polygon = {
|
||||
{ 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+o.h },
|
||||
{ x=o.x+0, y=o.y+o.h }
|
||||
{ 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 + o.h },
|
||||
{ x = o.x + 0, y = o.y + o.h },
|
||||
}
|
||||
|
||||
for _, vertex in ipairs(o.polygon) do
|
||||
@ -202,7 +202,7 @@ return {
|
||||
y = instance.y,
|
||||
width = map.tilewidth,
|
||||
height = map.tileheight,
|
||||
properties = tile.properties
|
||||
properties = tile.properties,
|
||||
}
|
||||
|
||||
calculateObjectPosition(object, instance)
|
||||
@ -227,7 +227,7 @@ return {
|
||||
y = instance.y,
|
||||
width = tileset.tilewidth,
|
||||
height = tileset.tileheight,
|
||||
properties = tile.properties
|
||||
properties = tile.properties,
|
||||
}
|
||||
|
||||
calculateObjectPosition(object, instance)
|
||||
@ -245,7 +245,7 @@ return {
|
||||
y = layer.y or 0,
|
||||
width = layer.width,
|
||||
height = layer.height,
|
||||
properties = layer.properties
|
||||
properties = layer.properties,
|
||||
}
|
||||
|
||||
calculateObjectPosition(object)
|
||||
@ -295,7 +295,7 @@ return {
|
||||
lg.translate(math.floor(tx or 0), math.floor(ty or 0))
|
||||
|
||||
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()
|
||||
|
||||
if shape_type == "edge" or shape_type == "chain" then
|
||||
@ -303,12 +303,12 @@ return {
|
||||
elseif shape_type == "polygon" then
|
||||
love.graphics.polygon("line", points)
|
||||
else
|
||||
error("sti box2d plugin does not support "..shape_type.." shapes")
|
||||
error("sti box2d plugin does not support " .. shape_type .. " shapes")
|
||||
end
|
||||
end
|
||||
|
||||
lg.pop()
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
--- Custom Properties in Tiled are used to tell this plugin what to do.
|
||||
|
@ -4,7 +4,7 @@
|
||||
-- @copyright 2019
|
||||
-- @license MIT/X11
|
||||
|
||||
local lg = require((...):gsub('plugins.bump', 'graphics'))
|
||||
local lg = require((...):gsub("plugins.bump", "graphics"))
|
||||
|
||||
return {
|
||||
bump_LICENSE = "MIT/X11",
|
||||
@ -36,8 +36,7 @@ return {
|
||||
width = object.width,
|
||||
height = object.height,
|
||||
layer = instance.layer,
|
||||
properties = object.properties
|
||||
|
||||
properties = object.properties,
|
||||
}
|
||||
|
||||
world:add(t, t.x, t.y, t.width, t.height)
|
||||
@ -55,7 +54,7 @@ return {
|
||||
height = map.tileheight,
|
||||
layer = instance.layer,
|
||||
type = tile.type,
|
||||
properties = tile.properties
|
||||
properties = tile.properties,
|
||||
}
|
||||
|
||||
world:add(t, t.x, t.y, t.width, t.height)
|
||||
@ -72,19 +71,18 @@ return {
|
||||
if layer.type == "tilelayer" then
|
||||
for y, tiles in ipairs(layer.data) do
|
||||
for x, tile in pairs(tiles) do
|
||||
|
||||
if tile.objectGroup then
|
||||
for _, object in ipairs(tile.objectGroup.objects) do
|
||||
if object.properties.collidable == true then
|
||||
local t = {
|
||||
name = object.name,
|
||||
type = object.type,
|
||||
x = ((x-1) * map.tilewidth + tile.offset.x + map.offsetx) + object.x,
|
||||
y = ((y-1) * map.tileheight + tile.offset.y + map.offsety) + object.y,
|
||||
x = ((x - 1) * map.tilewidth + tile.offset.x + map.offsetx) + object.x,
|
||||
y = ((y - 1) * map.tileheight + tile.offset.y + map.offsety) + object.y,
|
||||
width = object.width,
|
||||
height = object.height,
|
||||
layer = layer,
|
||||
properties = object.properties
|
||||
properties = object.properties,
|
||||
}
|
||||
|
||||
world:add(t, t.x, t.y, t.width, t.height)
|
||||
@ -93,15 +91,14 @@ return {
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local t = {
|
||||
x = (x-1) * map.tilewidth + tile.offset.x + map.offsetx,
|
||||
y = (y-1) * map.tileheight + tile.offset.y + map.offsety,
|
||||
x = (x - 1) * map.tilewidth + tile.offset.x + map.offsetx,
|
||||
y = (y - 1) * map.tileheight + tile.offset.y + map.offsety,
|
||||
width = tile.width,
|
||||
height = tile.height,
|
||||
layer = layer,
|
||||
type = tile.type,
|
||||
properties = tile.properties
|
||||
properties = tile.properties,
|
||||
}
|
||||
|
||||
world:add(t, t.x, t.y, t.width, t.height)
|
||||
@ -128,7 +125,7 @@ return {
|
||||
width = obj.width,
|
||||
height = obj.height,
|
||||
layer = layer,
|
||||
properties = obj.properties
|
||||
properties = obj.properties,
|
||||
}
|
||||
|
||||
if obj.gid then
|
||||
@ -157,11 +154,7 @@ return {
|
||||
for i = #collidables, 1, -1 do
|
||||
local obj = collidables[i]
|
||||
|
||||
if obj.layer == layer
|
||||
and (
|
||||
layer.properties.collidable == true
|
||||
or obj.properties.collidable == true
|
||||
) then
|
||||
if obj.layer == layer and (layer.properties.collidable == true or obj.properties.collidable == true) then
|
||||
map.bump_world:remove(obj)
|
||||
table.remove(collidables, i)
|
||||
end
|
||||
@ -185,7 +178,7 @@ return {
|
||||
end
|
||||
|
||||
lg.pop()
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
--- 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
|
||||
function utils.format_path(path)
|
||||
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_gen1, np_gen2 = "[^SEP]+SEP%.%.SEP?", "SEP+%.?SEP"
|
||||
local np_pat1, np_pat2 = np_gen1:gsub("SEP", "/"), np_gen2:gsub("SEP", "/")
|
||||
local k
|
||||
|
||||
repeat -- /./ -> /
|
||||
path,k = path:gsub(np_pat2,'/',1)
|
||||
path, k = path:gsub(np_pat2, "/", 1)
|
||||
until k == 0
|
||||
|
||||
repeat -- A/../ -> (empty)
|
||||
path,k = path:gsub(np_pat1,'',1)
|
||||
path, k = path:gsub(np_pat1, "", 1)
|
||||
until k == 0
|
||||
|
||||
if path == '' then path = '.' end
|
||||
if path == "" then
|
||||
path = "."
|
||||
end
|
||||
|
||||
return path
|
||||
end
|
||||
@ -25,8 +27,12 @@ function utils.compensate(tile, tileX, tileY, tileW, tileH)
|
||||
local compx = 0
|
||||
local compy = 0
|
||||
|
||||
if tile.sx < 0 then compx = tileW end
|
||||
if tile.sy < 0 then compy = tileH end
|
||||
if tile.sx < 0 then
|
||||
compx = tileW
|
||||
end
|
||||
if tile.sy < 0 then
|
||||
compy = tileH
|
||||
end
|
||||
|
||||
if tile.r > 0 then
|
||||
tileX = tileX + tileH - compy
|
||||
@ -56,8 +62,12 @@ function utils.get_tiles(imageW, tileW, margin, spacing)
|
||||
|
||||
while imageW >= tileW do
|
||||
imageW = imageW - tileW
|
||||
if n ~= 0 then imageW = imageW - spacing end
|
||||
if imageW >= 0 then n = n + 1 end
|
||||
if n ~= 0 then
|
||||
imageW = imageW - spacing
|
||||
end
|
||||
if imageW >= 0 then
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
|
||||
return n
|
||||
@ -65,7 +75,7 @@ end
|
||||
|
||||
-- Decompress tile layer data
|
||||
function utils.get_decompressed_data(data)
|
||||
local ffi = require "ffi"
|
||||
local ffi = require("ffi")
|
||||
local d = {}
|
||||
local decoded = ffi.cast("uint32_t*", data)
|
||||
|
||||
@ -95,7 +105,7 @@ function utils.convert_ellipse_to_polygon(x, y, w, h, max_segments)
|
||||
segments = segments or 64
|
||||
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
|
||||
if love and love.physics then
|
||||
@ -117,7 +127,7 @@ function utils.convert_ellipse_to_polygon(x, y, w, h, max_segments)
|
||||
|
||||
-- Box2D threshold
|
||||
if dist1 < 0.0025 or dist2 < 0.0025 then
|
||||
return calc_segments(segments-2)
|
||||
return calc_segments(segments - 2)
|
||||
end
|
||||
|
||||
return segments
|
||||
@ -148,9 +158,7 @@ function utils.rotate_vertex(map, vertex, x, y, cos, sin, oy)
|
||||
vertex.x = vertex.x - x
|
||||
vertex.y = vertex.y - y
|
||||
|
||||
return
|
||||
x + cos * vertex.x - sin * vertex.y,
|
||||
y + sin * vertex.x + cos * vertex.y - (oy or 0)
|
||||
return x + cos * vertex.x - sin * vertex.y, y + sin * vertex.x + cos * vertex.y - (oy or 0)
|
||||
end
|
||||
|
||||
--- Project isometric position to cartesian position
|
||||
@ -162,9 +170,7 @@ function utils.convert_isometric_to_screen(map, x, y)
|
||||
local tileY = y / tileH
|
||||
local offsetX = mapW * tileW / 2
|
||||
|
||||
return
|
||||
(tileX - tileY) * tileW / 2 + offsetX,
|
||||
(tileX + tileY) * tileH / 2
|
||||
return (tileX - tileY) * tileW / 2 + offsetX, (tileX + tileY) * tileH / 2
|
||||
end
|
||||
|
||||
function utils.hex_to_color(hex)
|
||||
@ -175,16 +181,14 @@ function utils.hex_to_color(hex)
|
||||
return {
|
||||
r = tonumber(hex:sub(1, 2), 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
|
||||
|
||||
function utils.pixel_function(_, _, r, g, b, a)
|
||||
local mask = utils._TC
|
||||
|
||||
if r == mask.r and
|
||||
g == mask.g and
|
||||
b == mask.b then
|
||||
if r == mask.r and g == mask.g and b == mask.b then
|
||||
return r, g, b, 0
|
||||
end
|
||||
|
||||
@ -205,7 +209,7 @@ end
|
||||
|
||||
function utils.deepCopy(t)
|
||||
local copy = {}
|
||||
for k,v in pairs(t) do
|
||||
for k, v in pairs(t) do
|
||||
if type(v) == "table" then
|
||||
v = utils.deepCopy(v)
|
||||
end
|
||||
|
@ -20,11 +20,12 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
]]--
|
||||
]]
|
||||
--
|
||||
|
||||
local path = ... .. '.'
|
||||
local path = ... .. "."
|
||||
local wf = {}
|
||||
wf.Math = require(path .. 'mlib.mlib')
|
||||
wf.Math = require(path .. "mlib.mlib")
|
||||
|
||||
World = {}
|
||||
World.__index = World
|
||||
@ -32,14 +33,28 @@ World.__index = World
|
||||
function wf.newWorld(xg, yg, sleep)
|
||||
local world = wf.World.new(wf, xg, yg, sleep)
|
||||
|
||||
world.box2d_world:setCallbacks(world.collisionOnEnter, world.collisionOnExit, world.collisionPre, world.collisionPost)
|
||||
world.box2d_world:setCallbacks(
|
||||
world.collisionOnEnter,
|
||||
world.collisionOnExit,
|
||||
world.collisionPre,
|
||||
world.collisionPost
|
||||
)
|
||||
world:collisionClear()
|
||||
world:addCollisionClass('Default')
|
||||
world:addCollisionClass("Default")
|
||||
|
||||
-- Points all box2d_world functions to this wf.World object
|
||||
-- This means that the user can call world:setGravity for instance without having to say world.box2d_world:setGravity
|
||||
for k, v in pairs(world.box2d_world.__index) do
|
||||
if k ~= '__gc' and k ~= '__eq' and k ~= '__index' and k ~= '__tostring' and k ~= 'update' and k ~= 'destroy' and k ~= 'type' and k ~= 'typeOf' then
|
||||
if
|
||||
k ~= "__gc"
|
||||
and k ~= "__eq"
|
||||
and k ~= "__index"
|
||||
and k ~= "__tostring"
|
||||
and k ~= "update"
|
||||
and k ~= "destroy"
|
||||
and k ~= "type"
|
||||
and k ~= "typeOf"
|
||||
then
|
||||
world[k] = function(self, ...)
|
||||
return v(self.box2d_world, ...)
|
||||
end
|
||||
@ -84,18 +99,20 @@ function World:draw(alpha)
|
||||
for _, body in ipairs(bodies) do
|
||||
local fixtures = body:getFixtures()
|
||||
for _, fixture in ipairs(fixtures) do
|
||||
if fixture:getShape():type() == 'PolygonShape' then
|
||||
love.graphics.polygon('line', body:getWorldPoints(fixture:getShape():getPoints()))
|
||||
elseif fixture:getShape():type() == 'EdgeShape' or fixture:getShape():type() == 'ChainShape' then
|
||||
local points = {body:getWorldPoints(fixture:getShape():getPoints())}
|
||||
if fixture:getShape():type() == "PolygonShape" then
|
||||
love.graphics.polygon("line", body:getWorldPoints(fixture:getShape():getPoints()))
|
||||
elseif fixture:getShape():type() == "EdgeShape" or fixture:getShape():type() == "ChainShape" then
|
||||
local points = { body:getWorldPoints(fixture:getShape():getPoints()) }
|
||||
for i = 1, #points, 2 do
|
||||
if i < #points-2 then love.graphics.line(points[i], points[i+1], points[i+2], points[i+3]) end
|
||||
if i < #points - 2 then
|
||||
love.graphics.line(points[i], points[i + 1], points[i + 2], points[i + 3])
|
||||
end
|
||||
elseif fixture:getShape():type() == 'CircleShape' then
|
||||
end
|
||||
elseif fixture:getShape():type() == "CircleShape" then
|
||||
local body_x, body_y = body:getPosition()
|
||||
local shape_x, shape_y = fixture:getShape():getPoint()
|
||||
local r = fixture:getShape():getRadius()
|
||||
love.graphics.circle('line', body_x + shape_x, body_y + shape_y, r, 360)
|
||||
love.graphics.circle("line", body_x + shape_x, body_y + shape_y, r, 360)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -106,8 +123,12 @@ function World:draw(alpha)
|
||||
local joints = self.box2d_world:getJoints()
|
||||
for _, joint in ipairs(joints) do
|
||||
local x1, y1, x2, y2 = joint:getAnchors()
|
||||
if x1 and y1 then love.graphics.circle('line', x1, y1, 4) end
|
||||
if x2 and y2 then love.graphics.circle('line', x2, y2, 4) end
|
||||
if x1 and y1 then
|
||||
love.graphics.circle("line", x1, y1, 4)
|
||||
end
|
||||
if x2 and y2 then
|
||||
love.graphics.circle("line", x2, y2, 4)
|
||||
end
|
||||
end
|
||||
love.graphics.setColor(255, 255, 255, alpha)
|
||||
|
||||
@ -115,15 +136,17 @@ function World:draw(alpha)
|
||||
love.graphics.setColor(64, 64, 222, alpha)
|
||||
for _, query_draw in ipairs(self.query_debug_draw) do
|
||||
query_draw.frames = query_draw.frames - 1
|
||||
if query_draw.type == 'circle' then
|
||||
love.graphics.circle('line', query_draw.x, query_draw.y, query_draw.r)
|
||||
elseif query_draw.type == 'rectangle' then
|
||||
love.graphics.rectangle('line', query_draw.x, query_draw.y, query_draw.w, query_draw.h)
|
||||
elseif query_draw.type == 'line' then
|
||||
if query_draw.type == "circle" then
|
||||
love.graphics.circle("line", query_draw.x, query_draw.y, query_draw.r)
|
||||
elseif query_draw.type == "rectangle" then
|
||||
love.graphics.rectangle("line", query_draw.x, query_draw.y, query_draw.w, query_draw.h)
|
||||
elseif query_draw.type == "line" then
|
||||
love.graphics.line(query_draw.x1, query_draw.y1, query_draw.x2, query_draw.y2)
|
||||
elseif query_draw.type == 'polygon' then
|
||||
elseif query_draw.type == "polygon" then
|
||||
local triangles = love.math.triangulate(query_draw.vertices)
|
||||
for _, triangle in ipairs(triangles) do love.graphics.polygon('line', triangle) end
|
||||
for _, triangle in ipairs(triangles) do
|
||||
love.graphics.polygon("line", triangle)
|
||||
end
|
||||
end
|
||||
end
|
||||
for i = #self.query_debug_draw, 1, -1 do
|
||||
@ -143,7 +166,9 @@ function World:setExplicitCollisionEvents(value)
|
||||
end
|
||||
|
||||
function World:addCollisionClass(collision_class_name, collision_class)
|
||||
if self.collision_classes[collision_class_name] then error('Collision class ' .. collision_class_name .. ' already exists.') end
|
||||
if self.collision_classes[collision_class_name] then
|
||||
error("Collision class " .. collision_class_name .. " already exists.")
|
||||
end
|
||||
|
||||
if self.explicit_collision_events then
|
||||
self.collision_classes[collision_class_name] = collision_class or {}
|
||||
@ -177,10 +202,18 @@ function World:collisionClassesSet()
|
||||
local collision_table = self:getCollisionCallbacksTable()
|
||||
for collision_class_name, collision_list in pairs(collision_table) do
|
||||
for _, collision_info in ipairs(collision_list) do
|
||||
if collision_info.type == 'enter' then self:addCollisionEnter(collision_class_name, collision_info.other) end
|
||||
if collision_info.type == 'exit' then self:addCollisionExit(collision_class_name, collision_info.other) end
|
||||
if collision_info.type == 'pre' then self:addCollisionPre(collision_class_name, collision_info.other) end
|
||||
if collision_info.type == 'post' then self:addCollisionPost(collision_class_name, collision_info.other) end
|
||||
if collision_info.type == "enter" then
|
||||
self:addCollisionEnter(collision_class_name, collision_info.other)
|
||||
end
|
||||
if collision_info.type == "exit" then
|
||||
self:addCollisionExit(collision_class_name, collision_info.other)
|
||||
end
|
||||
if collision_info.type == "pre" then
|
||||
self:addCollisionPre(collision_class_name, collision_info.other)
|
||||
end
|
||||
if collision_info.type == "post" then
|
||||
self:addCollisionPost(collision_class_name, collision_info.other)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -213,26 +246,34 @@ end
|
||||
|
||||
function World:addCollisionEnter(type1, type2)
|
||||
if not self:isCollisionBetweenSensors(type1, type2) then
|
||||
table.insert(self.collisions.on_enter.non_sensor, {type1 = type1, type2 = type2})
|
||||
else table.insert(self.collisions.on_enter.sensor, {type1 = type1, type2 = type2}) end
|
||||
table.insert(self.collisions.on_enter.non_sensor, { type1 = type1, type2 = type2 })
|
||||
else
|
||||
table.insert(self.collisions.on_enter.sensor, { type1 = type1, type2 = type2 })
|
||||
end
|
||||
end
|
||||
|
||||
function World:addCollisionExit(type1, type2)
|
||||
if not self:isCollisionBetweenSensors(type1, type2) then
|
||||
table.insert(self.collisions.on_exit.non_sensor, {type1 = type1, type2 = type2})
|
||||
else table.insert(self.collisions.on_exit.sensor, {type1 = type1, type2 = type2}) end
|
||||
table.insert(self.collisions.on_exit.non_sensor, { type1 = type1, type2 = type2 })
|
||||
else
|
||||
table.insert(self.collisions.on_exit.sensor, { type1 = type1, type2 = type2 })
|
||||
end
|
||||
end
|
||||
|
||||
function World:addCollisionPre(type1, type2)
|
||||
if not self:isCollisionBetweenSensors(type1, type2) then
|
||||
table.insert(self.collisions.pre.non_sensor, {type1 = type1, type2 = type2})
|
||||
else table.insert(self.collisions.pre.sensor, {type1 = type1, type2 = type2}) end
|
||||
table.insert(self.collisions.pre.non_sensor, { type1 = type1, type2 = type2 })
|
||||
else
|
||||
table.insert(self.collisions.pre.sensor, { type1 = type1, type2 = type2 })
|
||||
end
|
||||
end
|
||||
|
||||
function World:addCollisionPost(type1, type2)
|
||||
if not self:isCollisionBetweenSensors(type1, type2) then
|
||||
table.insert(self.collisions.post.non_sensor, {type1 = type1, type2 = type2})
|
||||
else table.insert(self.collisions.post.sensor, {type1 = type1, type2 = type2}) end
|
||||
table.insert(self.collisions.post.non_sensor, { type1 = type1, type2 = type2 })
|
||||
else
|
||||
table.insert(self.collisions.post.sensor, { type1 = type1, type2 = type2 })
|
||||
end
|
||||
end
|
||||
|
||||
function World:doesType1IgnoreType2(type1, type2)
|
||||
@ -246,31 +287,46 @@ function World:doesType1IgnoreType2(type1, type2)
|
||||
end
|
||||
local ignored_types = {}
|
||||
for _, collision_class_type in ipairs(collision_ignores[type1]) do
|
||||
if collision_class_type == 'All' then
|
||||
if collision_class_type == "All" then
|
||||
for _, collision_class_name in ipairs(all) do
|
||||
table.insert(ignored_types, collision_class_name)
|
||||
end
|
||||
else table.insert(ignored_types, collision_class_type) end
|
||||
else
|
||||
table.insert(ignored_types, collision_class_type)
|
||||
end
|
||||
end
|
||||
for key, _ in pairs(collision_ignores[type1]) do
|
||||
if key == 'except' then
|
||||
if key == "except" then
|
||||
for _, except_type in ipairs(collision_ignores[type1].except) do
|
||||
for i = #ignored_types, 1, -1 do
|
||||
if ignored_types[i] == except_type then table.remove(ignored_types, i) end
|
||||
if ignored_types[i] == except_type then
|
||||
table.remove(ignored_types, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, ignored_type in ipairs(ignored_types) do
|
||||
if ignored_type == type2 then return true end
|
||||
if ignored_type == type2 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function World:isCollisionBetweenSensors(type1, type2)
|
||||
if not self.is_sensor_memo[type1] then self.is_sensor_memo[type1] = {} end
|
||||
if not self.is_sensor_memo[type1][type2] then self.is_sensor_memo[type1][type2] = (self:doesType1IgnoreType2(type1, type2) or self:doesType1IgnoreType2(type2, type1)) end
|
||||
if self.is_sensor_memo[type1][type2] then return true
|
||||
else return false end
|
||||
if not self.is_sensor_memo[type1] then
|
||||
self.is_sensor_memo[type1] = {}
|
||||
end
|
||||
if not self.is_sensor_memo[type1][type2] then
|
||||
self.is_sensor_memo[type1][type2] = (
|
||||
self:doesType1IgnoreType2(type1, type2) or self:doesType1IgnoreType2(type2, type1)
|
||||
)
|
||||
end
|
||||
if self.is_sensor_memo[type1][type2] then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- https://love2d.org/forums/viewtopic.php?f=4&t=75441
|
||||
@ -289,18 +345,18 @@ function World:generateCategoriesMasks()
|
||||
end
|
||||
for object_type, ignore_list in pairs(collision_ignores) do
|
||||
for key, ignored_type in pairs(ignore_list) do
|
||||
if ignored_type == 'All' then
|
||||
if ignored_type == "All" then
|
||||
for _, all_object_type in ipairs(all) do
|
||||
table.insert(incoming[all_object_type], object_type)
|
||||
table.insert(expanded[object_type], all_object_type)
|
||||
end
|
||||
elseif type(ignored_type) == 'string' then
|
||||
if ignored_type ~= 'All' then
|
||||
elseif type(ignored_type) == "string" then
|
||||
if ignored_type ~= "All" then
|
||||
table.insert(incoming[ignored_type], object_type)
|
||||
table.insert(expanded[object_type], ignored_type)
|
||||
end
|
||||
end
|
||||
if key == 'except' then
|
||||
if key == "except" then
|
||||
for _, except_ignored_type in ipairs(ignored_type) do
|
||||
for i, v in ipairs(incoming[except_ignored_type]) do
|
||||
if v == object_type then
|
||||
@ -322,7 +378,9 @@ function World:generateCategoriesMasks()
|
||||
end
|
||||
local edge_groups = {}
|
||||
for k, v in pairs(incoming) do
|
||||
table.sort(v, function(a, b) return string.lower(a) < string.lower(b) end)
|
||||
table.sort(v, function(a, b)
|
||||
return string.lower(a) < string.lower(b)
|
||||
end)
|
||||
end
|
||||
local i = 0
|
||||
for k, v in pairs(incoming) do
|
||||
@ -330,7 +388,10 @@ function World:generateCategoriesMasks()
|
||||
for _, c in ipairs(v) do
|
||||
str = str .. c
|
||||
end
|
||||
if not edge_groups[str] then i = i + 1; edge_groups[str] = {n = i} end
|
||||
if not edge_groups[str] then
|
||||
i = i + 1
|
||||
edge_groups[str] = { n = i }
|
||||
end
|
||||
table.insert(edge_groups[str], k)
|
||||
end
|
||||
local categories = {}
|
||||
@ -343,12 +404,12 @@ function World:generateCategoriesMasks()
|
||||
end
|
||||
end
|
||||
for k, v in pairs(expanded) do
|
||||
local category = {categories[k]}
|
||||
local category = { categories[k] }
|
||||
local current_masks = {}
|
||||
for _, c in ipairs(v) do
|
||||
table.insert(current_masks, categories[c])
|
||||
end
|
||||
self.masks[k] = {categories = category, masks = current_masks}
|
||||
self.masks[k] = { categories = category, masks = current_masks }
|
||||
end
|
||||
end
|
||||
|
||||
@ -356,24 +417,39 @@ function World:getCollisionCallbacksTable()
|
||||
local collision_table = {}
|
||||
for collision_class_name, collision_class in pairs(self.collision_classes) do
|
||||
collision_table[collision_class_name] = {}
|
||||
for _, v in ipairs(collision_class.enter or {}) do table.insert(collision_table[collision_class_name], {type = 'enter', other = v}) end
|
||||
for _, v in ipairs(collision_class.exit or {}) do table.insert(collision_table[collision_class_name], {type = 'exit', other = v}) end
|
||||
for _, v in ipairs(collision_class.pre or {}) do table.insert(collision_table[collision_class_name], {type = 'pre', other = v}) end
|
||||
for _, v in ipairs(collision_class.post or {}) do table.insert(collision_table[collision_class_name], {type = 'post', other = v}) end
|
||||
for _, v in ipairs(collision_class.enter or {}) do
|
||||
table.insert(collision_table[collision_class_name], { type = "enter", other = v })
|
||||
end
|
||||
for _, v in ipairs(collision_class.exit or {}) do
|
||||
table.insert(collision_table[collision_class_name], { type = "exit", other = v })
|
||||
end
|
||||
for _, v in ipairs(collision_class.pre or {}) do
|
||||
table.insert(collision_table[collision_class_name], { type = "pre", other = v })
|
||||
end
|
||||
for _, v in ipairs(collision_class.post or {}) do
|
||||
table.insert(collision_table[collision_class_name], { type = "post", other = v })
|
||||
end
|
||||
end
|
||||
return collision_table
|
||||
end
|
||||
|
||||
local function collEnsure(collision_class_name1, a, collision_class_name2, b)
|
||||
if a.collision_class == collision_class_name2 and b.collision_class == collision_class_name1 then return b, a
|
||||
else return a, b end
|
||||
if a.collision_class == collision_class_name2 and b.collision_class == collision_class_name1 then
|
||||
return b, a
|
||||
else
|
||||
return a, b
|
||||
end
|
||||
end
|
||||
|
||||
local function collIf(collision_class_name1, collision_class_name2, a, b)
|
||||
if (a.collision_class == collision_class_name1 and b.collision_class == collision_class_name2) or
|
||||
(a.collision_class == collision_class_name2 and b.collision_class == collision_class_name1) then
|
||||
if
|
||||
(a.collision_class == collision_class_name1 and b.collision_class == collision_class_name2)
|
||||
or (a.collision_class == collision_class_name2 and b.collision_class == collision_class_name1)
|
||||
then
|
||||
return true
|
||||
else return false end
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function World.collisionOnEnter(fixture_a, fixture_b, contact)
|
||||
@ -384,22 +460,33 @@ function World.collisionOnEnter(fixture_a, fixture_b, contact)
|
||||
for _, collision in ipairs(a.world.collisions.on_enter.sensor) do
|
||||
if collIf(collision.type1, collision.type2, a, b) then
|
||||
a, b = collEnsure(collision.type1, a, collision.type2, b)
|
||||
table.insert(a.collision_events[collision.type2], {collision_type = 'enter', collider_1 = a, collider_2 = b, contact = contact})
|
||||
table.insert(
|
||||
a.collision_events[collision.type2],
|
||||
{ collision_type = "enter", collider_1 = a, collider_2 = b, contact = contact }
|
||||
)
|
||||
if collision.type1 == collision.type2 then
|
||||
table.insert(b.collision_events[collision.type1], {collision_type = 'enter', collider_1 = b, collider_2 = a, contact = contact})
|
||||
table.insert(
|
||||
b.collision_events[collision.type1],
|
||||
{ collision_type = "enter", collider_1 = b, collider_2 = a, contact = contact }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif not (fixture_a:isSensor() or fixture_b:isSensor()) then
|
||||
if a and b then
|
||||
for _, collision in ipairs(a.world.collisions.on_enter.non_sensor) do
|
||||
if collIf(collision.type1, collision.type2, a, b) then
|
||||
a, b = collEnsure(collision.type1, a, collision.type2, b)
|
||||
table.insert(a.collision_events[collision.type2], {collision_type = 'enter', collider_1 = a, collider_2 = b, contact = contact})
|
||||
table.insert(
|
||||
a.collision_events[collision.type2],
|
||||
{ collision_type = "enter", collider_1 = a, collider_2 = b, contact = contact }
|
||||
)
|
||||
if collision.type1 == collision.type2 then
|
||||
table.insert(b.collision_events[collision.type1], {collision_type = 'enter', collider_1 = b, collider_2 = a, contact = contact})
|
||||
table.insert(
|
||||
b.collision_events[collision.type1],
|
||||
{ collision_type = "enter", collider_1 = b, collider_2 = a, contact = contact }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -415,22 +502,33 @@ function World.collisionOnExit(fixture_a, fixture_b, contact)
|
||||
for _, collision in ipairs(a.world.collisions.on_exit.sensor) do
|
||||
if collIf(collision.type1, collision.type2, a, b) then
|
||||
a, b = collEnsure(collision.type1, a, collision.type2, b)
|
||||
table.insert(a.collision_events[collision.type2], {collision_type = 'exit', collider_1 = a, collider_2 = b, contact = contact})
|
||||
table.insert(
|
||||
a.collision_events[collision.type2],
|
||||
{ collision_type = "exit", collider_1 = a, collider_2 = b, contact = contact }
|
||||
)
|
||||
if collision.type1 == collision.type2 then
|
||||
table.insert(b.collision_events[collision.type1], {collision_type = 'exit', collider_1 = b, collider_2 = a, contact = contact})
|
||||
table.insert(
|
||||
b.collision_events[collision.type1],
|
||||
{ collision_type = "exit", collider_1 = b, collider_2 = a, contact = contact }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif not (fixture_a:isSensor() or fixture_b:isSensor()) then
|
||||
if a and b then
|
||||
for _, collision in ipairs(a.world.collisions.on_exit.non_sensor) do
|
||||
if collIf(collision.type1, collision.type2, a, b) then
|
||||
a, b = collEnsure(collision.type1, a, collision.type2, b)
|
||||
table.insert(a.collision_events[collision.type2], {collision_type = 'exit', collider_1 = a, collider_2 = b, contact = contact})
|
||||
table.insert(
|
||||
a.collision_events[collision.type2],
|
||||
{ collision_type = "exit", collider_1 = a, collider_2 = b, contact = contact }
|
||||
)
|
||||
if collision.type1 == collision.type2 then
|
||||
table.insert(b.collision_events[collision.type1], {collision_type = 'exit', collider_1 = b, collider_2 = a, contact = contact})
|
||||
table.insert(
|
||||
b.collision_events[collision.type1],
|
||||
{ collision_type = "exit", collider_1 = b, collider_2 = a, contact = contact }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -453,7 +551,6 @@ function World.collisionPre(fixture_a, fixture_b, contact)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif not (fixture_a:isSensor() or fixture_b:isSensor()) then
|
||||
if a and b then
|
||||
for _, collision in ipairs(a.world.collisions.pre.non_sensor) do
|
||||
@ -484,7 +581,6 @@ function World.collisionPost(fixture_a, fixture_b, contact, ni1, ti1, ni2, ti2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif not (fixture_a:isSensor() or fixture_b:isSensor()) then
|
||||
if a and b then
|
||||
for _, collision in ipairs(a.world.collisions.post.non_sensor) do
|
||||
@ -501,34 +597,36 @@ function World.collisionPost(fixture_a, fixture_b, contact, ni1, ti1, ni2, ti2)
|
||||
end
|
||||
|
||||
function World:newCircleCollider(x, y, r, settings)
|
||||
return self.wf.Collider.new(self, 'Circle', x, y, r, settings)
|
||||
return self.wf.Collider.new(self, "Circle", x, y, r, settings)
|
||||
end
|
||||
|
||||
function World:newRectangleCollider(x, y, w, h, settings)
|
||||
return self.wf.Collider.new(self, 'Rectangle', x, y, w, h, settings)
|
||||
return self.wf.Collider.new(self, "Rectangle", x, y, w, h, settings)
|
||||
end
|
||||
|
||||
function World:newBSGRectangleCollider(x, y, w, h, corner_cut_size, settings)
|
||||
return self.wf.Collider.new(self, 'BSGRectangle', x, y, w, h, corner_cut_size, settings)
|
||||
return self.wf.Collider.new(self, "BSGRectangle", x, y, w, h, corner_cut_size, settings)
|
||||
end
|
||||
|
||||
function World:newPolygonCollider(vertices, settings)
|
||||
return self.wf.Collider.new(self, 'Polygon', vertices, settings)
|
||||
return self.wf.Collider.new(self, "Polygon", vertices, settings)
|
||||
end
|
||||
|
||||
function World:newLineCollider(x1, y1, x2, y2, settings)
|
||||
return self.wf.Collider.new(self, 'Line', x1, y1, x2, y2, settings)
|
||||
return self.wf.Collider.new(self, "Line", x1, y1, x2, y2, settings)
|
||||
end
|
||||
|
||||
function World:newChainCollider(vertices, loop, settings)
|
||||
return self.wf.Collider.new(self, 'Chain', vertices, loop, settings)
|
||||
return self.wf.Collider.new(self, "Chain", vertices, loop, settings)
|
||||
end
|
||||
|
||||
-- Internal AABB box2d query used before going for more specific and precise computations.
|
||||
function World:_queryBoundingBox(x1, y1, x2, y2)
|
||||
local colliders = {}
|
||||
local callback = function(fixture)
|
||||
if not fixture:isSensor() then table.insert(colliders, fixture:getUserData()) end
|
||||
if not fixture:isSensor() then
|
||||
table.insert(colliders, fixture:getUserData())
|
||||
end
|
||||
return true
|
||||
end
|
||||
self.box2d_world:queryBoundingBox(x1, y1, x2, y2, callback)
|
||||
@ -536,7 +634,7 @@ function World:_queryBoundingBox(x1, y1, x2, y2)
|
||||
end
|
||||
|
||||
function World:collisionClassInCollisionClassesList(collision_class, collision_classes)
|
||||
if collision_classes[1] == 'All' then
|
||||
if collision_classes[1] == "All" then
|
||||
local all_collision_classes = {}
|
||||
for class, _ in pairs(self.collision_classes) do
|
||||
table.insert(all_collision_classes, class)
|
||||
@ -552,25 +650,43 @@ function World:collisionClassInCollisionClassesList(collision_class, collision_c
|
||||
end
|
||||
end
|
||||
for _, class in ipairs(all_collision_classes) do
|
||||
if class == collision_class then return true end
|
||||
if class == collision_class then
|
||||
return true
|
||||
end
|
||||
end
|
||||
else
|
||||
for _, class in ipairs(collision_classes) do
|
||||
if class == collision_class then return true end
|
||||
if class == collision_class then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function World:queryCircleArea(x, y, radius, collision_class_names)
|
||||
if not collision_class_names then collision_class_names = {'All'} end
|
||||
if self.query_debug_drawing_enabled then table.insert(self.query_debug_draw, {type = 'circle', x = x, y = y, r = radius, frames = self.draw_query_for_n_frames}) end
|
||||
if not collision_class_names then
|
||||
collision_class_names = { "All" }
|
||||
end
|
||||
if self.query_debug_drawing_enabled then
|
||||
table.insert(
|
||||
self.query_debug_draw,
|
||||
{ type = "circle", x = x, y = y, r = radius, frames = self.draw_query_for_n_frames }
|
||||
)
|
||||
end
|
||||
|
||||
local colliders = self:_queryBoundingBox(x-radius, y-radius, x+radius, y+radius)
|
||||
local colliders = self:_queryBoundingBox(x - radius, y - radius, x + radius, y + radius)
|
||||
local outs = {}
|
||||
for _, collider in ipairs(colliders) do
|
||||
if self:collisionClassInCollisionClassesList(collider.collision_class, collision_class_names) then
|
||||
for _, fixture in ipairs(collider.body:getFixtures()) do
|
||||
if self.wf.Math.polygon.getCircleIntersection(x, y, radius, {collider.body:getWorldPoints(fixture:getShape():getPoints())}) then
|
||||
if
|
||||
self.wf.Math.polygon.getCircleIntersection(
|
||||
x,
|
||||
y,
|
||||
radius,
|
||||
{ collider.body:getWorldPoints(fixture:getShape():getPoints()) }
|
||||
)
|
||||
then
|
||||
table.insert(outs, collider)
|
||||
break
|
||||
end
|
||||
@ -581,15 +697,27 @@ function World:queryCircleArea(x, y, radius, collision_class_names)
|
||||
end
|
||||
|
||||
function World:queryRectangleArea(x, y, w, h, collision_class_names)
|
||||
if not collision_class_names then collision_class_names = {'All'} end
|
||||
if self.query_debug_drawing_enabled then table.insert(self.query_debug_draw, {type = 'rectangle', x = x, y = y, w = w, h = h, frames = self.draw_query_for_n_frames}) end
|
||||
if not collision_class_names then
|
||||
collision_class_names = { "All" }
|
||||
end
|
||||
if self.query_debug_drawing_enabled then
|
||||
table.insert(
|
||||
self.query_debug_draw,
|
||||
{ type = "rectangle", x = x, y = y, w = w, h = h, frames = self.draw_query_for_n_frames }
|
||||
)
|
||||
end
|
||||
|
||||
local colliders = self:_queryBoundingBox(x, y, x+w, y+h)
|
||||
local colliders = self:_queryBoundingBox(x, y, x + w, y + h)
|
||||
local outs = {}
|
||||
for _, collider in ipairs(colliders) do
|
||||
if self:collisionClassInCollisionClassesList(collider.collision_class, collision_class_names) then
|
||||
for _, fixture in ipairs(collider.body:getFixtures()) do
|
||||
if self.wf.Math.polygon.isPolygonInside({x, y, x+w, y, x+w, y+h, x, y+h}, {collider.body:getWorldPoints(fixture:getShape():getPoints())}) then
|
||||
if
|
||||
self.wf.Math.polygon.isPolygonInside(
|
||||
{ x, y, x + w, y, x + w, y + h, x, y + h },
|
||||
{ collider.body:getWorldPoints(fixture:getShape():getPoints()) }
|
||||
)
|
||||
then
|
||||
table.insert(outs, collider)
|
||||
break
|
||||
end
|
||||
@ -600,21 +728,35 @@ function World:queryRectangleArea(x, y, w, h, collision_class_names)
|
||||
end
|
||||
|
||||
function World:queryPolygonArea(vertices, collision_class_names)
|
||||
if not collision_class_names then collision_class_names = {'All'} end
|
||||
if self.query_debug_drawing_enabled then table.insert(self.query_debug_draw, {type = 'polygon', vertices = vertices, frames = self.draw_query_for_n_frames}) end
|
||||
if not collision_class_names then
|
||||
collision_class_names = { "All" }
|
||||
end
|
||||
if self.query_debug_drawing_enabled then
|
||||
table.insert(
|
||||
self.query_debug_draw,
|
||||
{ type = "polygon", vertices = vertices, frames = self.draw_query_for_n_frames }
|
||||
)
|
||||
end
|
||||
|
||||
local cx, cy = self.wf.Math.polygon.getCentroid(vertices)
|
||||
local d_max = 0
|
||||
for i = 1, #vertices, 2 do
|
||||
local d = self.wf.Math.line.getLength(cx, cy, vertices[i], vertices[i+1])
|
||||
if d > d_max then d_max = d end
|
||||
local d = self.wf.Math.line.getLength(cx, cy, vertices[i], vertices[i + 1])
|
||||
if d > d_max then
|
||||
d_max = d
|
||||
end
|
||||
local colliders = self:_queryBoundingBox(cx-d_max, cy-d_max, cx+d_max, cy+d_max)
|
||||
end
|
||||
local colliders = self:_queryBoundingBox(cx - d_max, cy - d_max, cx + d_max, cy + d_max)
|
||||
local outs = {}
|
||||
for _, collider in ipairs(colliders) do
|
||||
if self:collisionClassInCollisionClassesList(collider.collision_class, collision_class_names) then
|
||||
for _, fixture in ipairs(collider.body:getFixtures()) do
|
||||
if self.wf.Math.polygon.isPolygonInside(vertices, {collider.body:getWorldPoints(fixture:getShape():getPoints())}) then
|
||||
if
|
||||
self.wf.Math.polygon.isPolygonInside(
|
||||
vertices,
|
||||
{ collider.body:getWorldPoints(fixture:getShape():getPoints()) }
|
||||
)
|
||||
then
|
||||
table.insert(outs, collider)
|
||||
break
|
||||
end
|
||||
@ -625,14 +767,21 @@ function World:queryPolygonArea(vertices, collision_class_names)
|
||||
end
|
||||
|
||||
function World:queryLine(x1, y1, x2, y2, collision_class_names)
|
||||
if not collision_class_names then collision_class_names = {'All'} end
|
||||
if not collision_class_names then
|
||||
collision_class_names = { "All" }
|
||||
end
|
||||
if self.query_debug_drawing_enabled then
|
||||
table.insert(self.query_debug_draw, {type = 'line', x1 = x1, y1 = y1, x2 = x2, y2 = y2, frames = self.draw_query_for_n_frames})
|
||||
table.insert(
|
||||
self.query_debug_draw,
|
||||
{ type = "line", x1 = x1, y1 = y1, x2 = x2, y2 = y2, frames = self.draw_query_for_n_frames }
|
||||
)
|
||||
end
|
||||
|
||||
local colliders = {}
|
||||
local callback = function(fixture, ...)
|
||||
if not fixture:isSensor() then table.insert(colliders, fixture:getUserData()) end
|
||||
if not fixture:isSensor() then
|
||||
table.insert(colliders, fixture:getUserData())
|
||||
end
|
||||
return 1
|
||||
end
|
||||
self.box2d_world:rayCast(x1, y1, x2, y2, callback)
|
||||
@ -647,10 +796,14 @@ function World:queryLine(x1, y1, x2, y2, collision_class_names)
|
||||
end
|
||||
|
||||
function World:addJoint(joint_type, ...)
|
||||
local args = {...}
|
||||
if args[1].body then args[1] = args[1].body end
|
||||
if type(args[2]) == "table" and args[2].body then args[2] = args[2].body end
|
||||
local joint = love.physics['new' .. joint_type](unpack(args))
|
||||
local args = { ... }
|
||||
if args[1].body then
|
||||
args[1] = args[1].body
|
||||
end
|
||||
if type(args[2]) == "table" and args[2].body then
|
||||
args[2] = args[2].body
|
||||
end
|
||||
local joint = love.physics["new" .. joint_type](unpack(args))
|
||||
return joint
|
||||
end
|
||||
|
||||
@ -665,13 +818,13 @@ function World:destroy()
|
||||
collider:destroy()
|
||||
end
|
||||
local joints = self.box2d_world:getJoints()
|
||||
for _, joint in ipairs(joints) do joint:destroy() end
|
||||
for _, joint in ipairs(joints) do
|
||||
joint:destroy()
|
||||
end
|
||||
self.box2d_world:destroy()
|
||||
self.box2d_world = nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
local Collider = {}
|
||||
Collider.__index = Collider
|
||||
|
||||
@ -702,42 +855,60 @@ function Collider.new(world, collider_type, ...)
|
||||
self.exit_collision_data = {}
|
||||
self.stay_collision_data = {}
|
||||
|
||||
local args = {...}
|
||||
local args = { ... }
|
||||
local shape, fixture
|
||||
if self.type == 'Circle' then
|
||||
self.collision_class = (args[4] and args[4].collision_class) or 'Default'
|
||||
self.body = love.physics.newBody(self.world.box2d_world, args[1], args[2], (args[4] and args[4].body_type) or 'dynamic')
|
||||
if self.type == "Circle" then
|
||||
self.collision_class = (args[4] and args[4].collision_class) or "Default"
|
||||
self.body =
|
||||
love.physics.newBody(self.world.box2d_world, args[1], args[2], (args[4] and args[4].body_type) or "dynamic")
|
||||
shape = love.physics.newCircleShape(args[3])
|
||||
|
||||
elseif self.type == 'Rectangle' then
|
||||
self.collision_class = (args[5] and args[5].collision_class) or 'Default'
|
||||
self.body = love.physics.newBody(self.world.box2d_world, args[1] + args[3]/2, args[2] + args[4]/2, (args[5] and args[5].body_type) or 'dynamic')
|
||||
elseif self.type == "Rectangle" then
|
||||
self.collision_class = (args[5] and args[5].collision_class) or "Default"
|
||||
self.body = love.physics.newBody(
|
||||
self.world.box2d_world,
|
||||
args[1] + args[3] / 2,
|
||||
args[2] + args[4] / 2,
|
||||
(args[5] and args[5].body_type) or "dynamic"
|
||||
)
|
||||
shape = love.physics.newRectangleShape(args[3], args[4])
|
||||
|
||||
elseif self.type == 'BSGRectangle' then
|
||||
self.collision_class = (args[6] and args[6].collision_class) or 'Default'
|
||||
self.body = love.physics.newBody(self.world.box2d_world, args[1] + args[3]/2, args[2] + args[4]/2, (args[6] and args[6].body_type) or 'dynamic')
|
||||
elseif self.type == "BSGRectangle" then
|
||||
self.collision_class = (args[6] and args[6].collision_class) or "Default"
|
||||
self.body = love.physics.newBody(
|
||||
self.world.box2d_world,
|
||||
args[1] + args[3] / 2,
|
||||
args[2] + args[4] / 2,
|
||||
(args[6] and args[6].body_type) or "dynamic"
|
||||
)
|
||||
local w, h, s = args[3], args[4], args[5]
|
||||
shape = love.physics.newPolygonShape({
|
||||
-w/2, -h/2 + s, -w/2 + s, -h/2,
|
||||
w/2 - s, -h/2, w/2, -h/2 + s,
|
||||
w/2, h/2 - s, w/2 - s, h/2,
|
||||
-w/2 + s, h/2, -w/2, h/2 - s
|
||||
-w / 2,
|
||||
-h / 2 + s,
|
||||
-w / 2 + s,
|
||||
-h / 2,
|
||||
w / 2 - s,
|
||||
-h / 2,
|
||||
w / 2,
|
||||
-h / 2 + s,
|
||||
w / 2,
|
||||
h / 2 - s,
|
||||
w / 2 - s,
|
||||
h / 2,
|
||||
-w / 2 + s,
|
||||
h / 2,
|
||||
-w / 2,
|
||||
h / 2 - s,
|
||||
})
|
||||
|
||||
elseif self.type == 'Polygon' then
|
||||
self.collision_class = (args[2] and args[2].collision_class) or 'Default'
|
||||
self.body = love.physics.newBody(self.world.box2d_world, 0, 0, (args[2] and args[2].body_type) or 'dynamic')
|
||||
elseif self.type == "Polygon" then
|
||||
self.collision_class = (args[2] and args[2].collision_class) or "Default"
|
||||
self.body = love.physics.newBody(self.world.box2d_world, 0, 0, (args[2] and args[2].body_type) or "dynamic")
|
||||
shape = love.physics.newPolygonShape(unpack(args[1]))
|
||||
|
||||
elseif self.type == 'Line' then
|
||||
self.collision_class = (args[5] and args[5].collision_class) or 'Default'
|
||||
self.body = love.physics.newBody(self.world.box2d_world, 0, 0, (args[5] and args[5].body_type) or 'dynamic')
|
||||
elseif self.type == "Line" then
|
||||
self.collision_class = (args[5] and args[5].collision_class) or "Default"
|
||||
self.body = love.physics.newBody(self.world.box2d_world, 0, 0, (args[5] and args[5].body_type) or "dynamic")
|
||||
shape = love.physics.newEdgeShape(args[1], args[2], args[3], args[4])
|
||||
|
||||
elseif self.type == 'Chain' then
|
||||
self.collision_class = (args[3] and args[3].collision_class) or 'Default'
|
||||
self.body = love.physics.newBody(self.world.box2d_world, 0, 0, (args[3] and args[3].body_type) or 'dynamic')
|
||||
elseif self.type == "Chain" then
|
||||
self.collision_class = (args[3] and args[3].collision_class) or "Default"
|
||||
self.body = love.physics.newBody(self.world.box2d_world, 0, 0, (args[3] and args[3].body_type) or "dynamic")
|
||||
shape = love.physics.newChainShape(args[1], unpack(args[2]))
|
||||
end
|
||||
|
||||
@ -752,9 +923,9 @@ function Collider.new(world, collider_type, ...)
|
||||
sensor:setSensor(true)
|
||||
sensor:setUserData(self)
|
||||
|
||||
self.shapes['main'] = shape
|
||||
self.fixtures['main'] = fixture
|
||||
self.sensors['main'] = sensor
|
||||
self.shapes["main"] = shape
|
||||
self.fixtures["main"] = fixture
|
||||
self.sensors["main"] = sensor
|
||||
self.shape = shape
|
||||
self.fixture = fixture
|
||||
|
||||
@ -764,21 +935,45 @@ function Collider.new(world, collider_type, ...)
|
||||
-- Points all body, fixture and shape functions to this wf.Collider object
|
||||
-- This means that the user can call collider:setLinearVelocity for instance without having to say collider.body:setLinearVelocity
|
||||
for k, v in pairs(self.body.__index) do
|
||||
if k ~= '__gc' and k ~= '__eq' and k ~= '__index' and k ~= '__tostring' and k ~= 'destroy' and k ~= 'type' and k ~= 'typeOf' then
|
||||
if
|
||||
k ~= "__gc"
|
||||
and k ~= "__eq"
|
||||
and k ~= "__index"
|
||||
and k ~= "__tostring"
|
||||
and k ~= "destroy"
|
||||
and k ~= "type"
|
||||
and k ~= "typeOf"
|
||||
then
|
||||
self[k] = function(self, ...)
|
||||
return v(self.body, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
for k, v in pairs(self.fixture.__index) do
|
||||
if k ~= '__gc' and k ~= '__eq' and k ~= '__index' and k ~= '__tostring' and k ~= 'destroy' and k ~= 'type' and k ~= 'typeOf' then
|
||||
if
|
||||
k ~= "__gc"
|
||||
and k ~= "__eq"
|
||||
and k ~= "__index"
|
||||
and k ~= "__tostring"
|
||||
and k ~= "destroy"
|
||||
and k ~= "type"
|
||||
and k ~= "typeOf"
|
||||
then
|
||||
self[k] = function(self, ...)
|
||||
return v(self.fixture, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
for k, v in pairs(self.shape.__index) do
|
||||
if k ~= '__gc' and k ~= '__eq' and k ~= '__index' and k ~= '__tostring' and k ~= 'destroy' and k ~= 'type' and k ~= 'typeOf' then
|
||||
if
|
||||
k ~= "__gc"
|
||||
and k ~= "__eq"
|
||||
and k ~= "__index"
|
||||
and k ~= "__tostring"
|
||||
and k ~= "destroy"
|
||||
and k ~= "type"
|
||||
and k ~= "typeOf"
|
||||
then
|
||||
self[k] = function(self, ...)
|
||||
return v(self.shape, ...)
|
||||
end
|
||||
@ -796,7 +991,9 @@ function Collider:collisionEventsClear()
|
||||
end
|
||||
|
||||
function Collider:setCollisionClass(collision_class_name)
|
||||
if not self.world.collision_classes[collision_class_name] then error("Collision class " .. collision_class_name .. " doesn't exist.") end
|
||||
if not self.world.collision_classes[collision_class_name] then
|
||||
error("Collision class " .. collision_class_name .. " doesn't exist.")
|
||||
end
|
||||
self.collision_class = collision_class_name
|
||||
for _, fixture in pairs(self.fixtures) do
|
||||
if self.world.masks[collision_class_name] then
|
||||
@ -810,10 +1007,15 @@ function Collider:enter(other_collision_class_name)
|
||||
local events = self.collision_events[other_collision_class_name]
|
||||
if events and #events >= 1 then
|
||||
for _, e in ipairs(events) do
|
||||
if e.collision_type == 'enter' then
|
||||
if not self.collision_stay[other_collision_class_name] then self.collision_stay[other_collision_class_name] = {} end
|
||||
table.insert(self.collision_stay[other_collision_class_name], {collider = e.collider_2, contact = e.contact})
|
||||
self.enter_collision_data[other_collision_class_name] = {collider = e.collider_2, contact = e.contact}
|
||||
if e.collision_type == "enter" then
|
||||
if not self.collision_stay[other_collision_class_name] then
|
||||
self.collision_stay[other_collision_class_name] = {}
|
||||
end
|
||||
table.insert(
|
||||
self.collision_stay[other_collision_class_name],
|
||||
{ collider = e.collider_2, contact = e.contact }
|
||||
)
|
||||
self.enter_collision_data[other_collision_class_name] = { collider = e.collider_2, contact = e.contact }
|
||||
return true
|
||||
end
|
||||
end
|
||||
@ -828,14 +1030,16 @@ function Collider:exit(other_collision_class_name)
|
||||
local events = self.collision_events[other_collision_class_name]
|
||||
if events and #events >= 1 then
|
||||
for _, e in ipairs(events) do
|
||||
if e.collision_type == 'exit' then
|
||||
if e.collision_type == "exit" then
|
||||
if self.collision_stay[other_collision_class_name] then
|
||||
for i = #self.collision_stay[other_collision_class_name], 1, -1 do
|
||||
local collision_stay = self.collision_stay[other_collision_class_name][i]
|
||||
if collision_stay.collider.id == e.collider_2.id then table.remove(self.collision_stay[other_collision_class_name], i) end
|
||||
if collision_stay.collider.id == e.collider_2.id then
|
||||
table.remove(self.collision_stay[other_collision_class_name], i)
|
||||
end
|
||||
end
|
||||
self.exit_collision_data[other_collision_class_name] = {collider = e.collider_2, contact = e.contact}
|
||||
end
|
||||
self.exit_collision_data[other_collision_class_name] = { collider = e.collider_2, contact = e.contact }
|
||||
return true
|
||||
end
|
||||
end
|
||||
@ -875,9 +1079,11 @@ function Collider:getObject()
|
||||
end
|
||||
|
||||
function Collider:addShape(shape_name, shape_type, ...)
|
||||
if self.shapes[shape_name] or self.fixtures[shape_name] then error("Shape/fixture " .. shape_name .. " already exists.") end
|
||||
local args = {...}
|
||||
local shape = love.physics['new' .. shape_type](unpack(args))
|
||||
if self.shapes[shape_name] or self.fixtures[shape_name] then
|
||||
error("Shape/fixture " .. shape_name .. " already exists.")
|
||||
end
|
||||
local args = { ... }
|
||||
local shape = love.physics["new" .. shape_type](unpack(args))
|
||||
local fixture = love.physics.newFixture(self.body, shape)
|
||||
if self.world.masks[self.collision_class] then
|
||||
fixture:setCategory(unpack(self.world.masks[self.collision_class].categories))
|
||||
@ -894,7 +1100,9 @@ function Collider:addShape(shape_name, shape_type, ...)
|
||||
end
|
||||
|
||||
function Collider:removeShape(shape_name)
|
||||
if not self.shapes[shape_name] then return end
|
||||
if not self.shapes[shape_name] then
|
||||
return
|
||||
end
|
||||
self.shapes[shape_name] = nil
|
||||
self.fixtures[shape_name]:setUserData(nil)
|
||||
self.fixtures[shape_name]:destroy()
|
||||
@ -926,4 +1134,3 @@ wf.World = World
|
||||
wf.Collider = Collider
|
||||
|
||||
return wf
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
46
main.lua
46
main.lua
@ -1,10 +1,14 @@
|
||||
require 'constants'
|
||||
require("constants")
|
||||
|
||||
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.
|
||||
if love.timer then love.timer.step() end
|
||||
if love.timer then
|
||||
love.timer.step()
|
||||
end
|
||||
|
||||
local dt = 0
|
||||
|
||||
@ -13,32 +17,40 @@ function love.run()
|
||||
-- Process events.
|
||||
if love.event then
|
||||
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 not love.quit or not love.quit() then
|
||||
return a or 0
|
||||
end
|
||||
end
|
||||
love.handlers[name](a,b,c,d,e,f)
|
||||
love.handlers[name](a, b, c, d, e, f)
|
||||
end
|
||||
end
|
||||
|
||||
-- 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
|
||||
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
|
||||
love.graphics.origin()
|
||||
love.graphics.clear(love.graphics.getBackgroundColor())
|
||||
|
||||
if love.draw then love.draw() end
|
||||
if love.draw then
|
||||
love.draw()
|
||||
end
|
||||
|
||||
love.graphics.present()
|
||||
end
|
||||
|
||||
if love.timer then love.timer.sleep(0.001) end
|
||||
if love.timer then
|
||||
love.timer.sleep(0.001)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -112,12 +124,11 @@ function love.load()
|
||||
musicStory = love.audio.newSource("music/story.mp3", "stream")
|
||||
|
||||
musicPause = musicBattle:clone()
|
||||
musicPause:setFilter{
|
||||
type = 'lowpass',
|
||||
volume = 0.3,
|
||||
musicPause:setFilter({
|
||||
type = "lowpass",
|
||||
volume = 0.7,
|
||||
highgain = 0.4,
|
||||
}
|
||||
|
||||
})
|
||||
end
|
||||
|
||||
function love.keypressed(key)
|
||||
@ -130,7 +141,6 @@ function love.keypressed(key)
|
||||
if _G.GAMESTATE == "GAME" then
|
||||
GameKeyPressed(key)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function love.update(dt)
|
||||
@ -162,6 +172,11 @@ function love.update(dt)
|
||||
love.audio.play(musicPause)
|
||||
end
|
||||
end
|
||||
if _G.GAMESTATE == "WIN" then
|
||||
print(P1_WIN)
|
||||
print(P2_WIN)
|
||||
love.event.quit()
|
||||
end
|
||||
end
|
||||
|
||||
function love.draw()
|
||||
@ -179,5 +194,4 @@ function love.draw()
|
||||
love.graphics.print("" .. GAMESTATE, 200, 200)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
68
player.lua
68
player.lua
@ -47,38 +47,38 @@ function Player:shoot(bulletSpeed)
|
||||
return newBullet
|
||||
end
|
||||
|
||||
function handleKeys(dt)
|
||||
end
|
||||
|
||||
-- Update method for the Player class
|
||||
function Player:update(dt)
|
||||
if _G.GAMESTATE == "GAME" then
|
||||
self.vx = 0
|
||||
self.vy = 0
|
||||
local bulletSpeed = 20000
|
||||
|
||||
if self.p == 1 then
|
||||
-- Handle player 1 controls
|
||||
if love.keyboard.isDown("w") then
|
||||
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("s") then
|
||||
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("a") then
|
||||
elseif love.keyboard.isDown(left) then
|
||||
self.rotation = self.rotation - (self.rotSpeed * dt)
|
||||
elseif love.keyboard.isDown("d") then
|
||||
elseif love.keyboard.isDown(right) then
|
||||
self.rotation = self.rotation + (self.rotSpeed * dt)
|
||||
end
|
||||
|
||||
self.collider:setLinearVelocity(self.vx, self.vy)
|
||||
end
|
||||
|
||||
-- Check for collision with walls
|
||||
if self.collider:enter("Wall") then
|
||||
print("Player 1 collided with wall")
|
||||
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
|
||||
|
||||
if EnableKeyPress1 == true and GAMESTATE == "GAME" then
|
||||
-- Update method for the Player class
|
||||
function Player:update(dt)
|
||||
local bulletSpeed = 20000
|
||||
|
||||
if EnableKeyPress1 == true and self.p == 1 then
|
||||
if love.keyboard.isDown("space") then
|
||||
local newBullet = self:shoot(bulletSpeed)
|
||||
table.insert(Bullets1, newBullet)
|
||||
@ -86,30 +86,8 @@ function Player:update(dt)
|
||||
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
|
||||
local newBullet = self:shoot(bulletSpeed)
|
||||
table.insert(Bullets2, newBullet)
|
||||
@ -117,10 +95,6 @@ function Player:update(dt)
|
||||
EnableKeyPress2 = false
|
||||
end
|
||||
end
|
||||
end
|
||||
self.x = self.collider:getX()
|
||||
self.y = self.collider:getY()
|
||||
end
|
||||
end
|
||||
|
||||
function Player:draw()
|
||||
|
Loading…
x
Reference in New Issue
Block a user