add loading of maps and rendering of maps with pixel perfect scaling
This commit is contained in:
parent
aedde7b105
commit
be7708edcf
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
/build
|
/build
|
||||||
|
*.tiled-session
|
||||||
|
@ -3,8 +3,8 @@ function love.conf(t)
|
|||||||
|
|
||||||
t.console = true
|
t.console = true
|
||||||
|
|
||||||
t.window.width = 1280/2
|
t.window.width = 854
|
||||||
t.window.height = 720/2
|
t.window.height = 480
|
||||||
t.window.resizable = true
|
t.window.resizable = true
|
||||||
|
|
||||||
t.modules.joystick = false
|
t.modules.joystick = false
|
||||||
|
11
src/data/main.tiled-project
Normal file
11
src/data/main.tiled-project
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"automappingRulesFile": "",
|
||||||
|
"commands": [
|
||||||
|
],
|
||||||
|
"extensionsPath": "extensions",
|
||||||
|
"folders": [
|
||||||
|
"."
|
||||||
|
],
|
||||||
|
"propertyTypes": [
|
||||||
|
]
|
||||||
|
}
|
79
src/data/maps/test.lua
Normal file
79
src/data/maps/test.lua
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
return {
|
||||||
|
version = "1.9",
|
||||||
|
luaversion = "5.1",
|
||||||
|
tiledversion = "1.9.0",
|
||||||
|
class = "",
|
||||||
|
orientation = "orthogonal",
|
||||||
|
renderorder = "right-down",
|
||||||
|
width = 30,
|
||||||
|
height = 20,
|
||||||
|
tilewidth = 16,
|
||||||
|
tileheight = 16,
|
||||||
|
nextlayerid = 3,
|
||||||
|
nextobjectid = 1,
|
||||||
|
properties = {},
|
||||||
|
tilesets = {
|
||||||
|
{
|
||||||
|
name = "test",
|
||||||
|
firstgid = 1,
|
||||||
|
filename = "../tilesets/test.tsx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
layers = {
|
||||||
|
{
|
||||||
|
type = "tilelayer",
|
||||||
|
x = 0,
|
||||||
|
y = 0,
|
||||||
|
width = 30,
|
||||||
|
height = 20,
|
||||||
|
id = 1,
|
||||||
|
name = "walls",
|
||||||
|
class = "",
|
||||||
|
visible = true,
|
||||||
|
opacity = 1,
|
||||||
|
offsetx = 0,
|
||||||
|
offsety = 0,
|
||||||
|
parallaxx = 1,
|
||||||
|
parallaxy = 1,
|
||||||
|
properties = {},
|
||||||
|
encoding = "lua",
|
||||||
|
data = {
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483649, 2147483649, 2147483649, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2147483649, 2147483649, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2147483649, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2147483649, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2147483649, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2147483649, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2147483649, 2147483649, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 2147483649, 2147483649, 2147483649, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type = "objectgroup",
|
||||||
|
draworder = "topdown",
|
||||||
|
id = 2,
|
||||||
|
name = "spawnpoints",
|
||||||
|
class = "",
|
||||||
|
visible = true,
|
||||||
|
opacity = 1,
|
||||||
|
offsetx = 0,
|
||||||
|
offsety = 0,
|
||||||
|
parallaxx = 1,
|
||||||
|
parallaxy = 1,
|
||||||
|
properties = {},
|
||||||
|
objects = {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
src/data/maps/test.tmx
Normal file
32
src/data/maps/test.tmx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<map version="1.9" tiledversion="1.9.0" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="1">
|
||||||
|
<editorsettings>
|
||||||
|
<export target="test.lua" format="lua"/>
|
||||||
|
</editorsettings>
|
||||||
|
<tileset firstgid="1" source="../tilesets/test.tsx"/>
|
||||||
|
<layer id="1" name="walls" width="30" height="20">
|
||||||
|
<data encoding="csv">
|
||||||
|
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
|
1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2147483649,2147483649,2147483649,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,2147483649,2147483649,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,2147483649,0,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,2147483649,0,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,2147483649,0,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,2147483649,0,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,2147483649,2147483649,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0,0,0,2147483649,2147483649,2147483649,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,
|
||||||
|
1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,
|
||||||
|
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
||||||
|
</data>
|
||||||
|
</layer>
|
||||||
|
<objectgroup id="2" name="spawnpoints"/>
|
||||||
|
</map>
|
BIN
src/data/tilesets/test.aseprite
Normal file
BIN
src/data/tilesets/test.aseprite
Normal file
Binary file not shown.
31
src/data/tilesets/test.lua
Normal file
31
src/data/tilesets/test.lua
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
return {
|
||||||
|
version = "1.9",
|
||||||
|
luaversion = "5.1",
|
||||||
|
tiledversion = "1.9.0",
|
||||||
|
name = "test",
|
||||||
|
class = "",
|
||||||
|
tilewidth = 16,
|
||||||
|
tileheight = 16,
|
||||||
|
spacing = 0,
|
||||||
|
margin = 0,
|
||||||
|
columns = 6,
|
||||||
|
image = "test.png",
|
||||||
|
imagewidth = 96,
|
||||||
|
imageheight = 96,
|
||||||
|
objectalignment = "unspecified",
|
||||||
|
tilerendersize = "tile",
|
||||||
|
fillmode = "stretch",
|
||||||
|
tileoffset = {
|
||||||
|
x = 0,
|
||||||
|
y = 0
|
||||||
|
},
|
||||||
|
grid = {
|
||||||
|
orientation = "orthogonal",
|
||||||
|
width = 16,
|
||||||
|
height = 16
|
||||||
|
},
|
||||||
|
properties = {},
|
||||||
|
wangsets = {},
|
||||||
|
tilecount = 36,
|
||||||
|
tiles = {}
|
||||||
|
}
|
BIN
src/data/tilesets/test.png
Normal file
BIN
src/data/tilesets/test.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 329 B |
4
src/data/tilesets/test.tsx
Normal file
4
src/data/tilesets/test.tsx
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<tileset version="1.9" tiledversion="1.9.0" name="test" tilewidth="16" tileheight="16" tilecount="36" columns="6">
|
||||||
|
<image source="test.png" width="96" height="96"/>
|
||||||
|
</tileset>
|
138
src/lib/center.lua
Normal file
138
src/lib/center.lua
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
--[[
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 Semyon Entsov <swalrus@yandex.ru>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
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 center = {}
|
||||||
|
|
||||||
|
function center:setupScreen(width, height)
|
||||||
|
self._WIDTH = width
|
||||||
|
self._HEIGHT = height
|
||||||
|
self._MAX_WIDTH = 0
|
||||||
|
self._MAX_HEIGHT = 0
|
||||||
|
self._MAX_RELATIVE_WIDTH = 0
|
||||||
|
self._MAX_RELATIVE_HEIGHT = 0
|
||||||
|
self._SCREEN_WIDTH = love.graphics.getWidth()
|
||||||
|
self._SCREEN_HEIGHT = love.graphics.getHeight()
|
||||||
|
self._BORDERS = {
|
||||||
|
['t'] = 0,
|
||||||
|
['r'] = 0,
|
||||||
|
['b'] = 0,
|
||||||
|
['l'] = 0
|
||||||
|
}
|
||||||
|
self:apply()
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:setBorders(top, right, bottom, left)
|
||||||
|
self._BORDERS.t = top
|
||||||
|
self._BORDERS.r = right
|
||||||
|
self._BORDERS.b = bottom
|
||||||
|
self._BORDERS.l = left
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:getScale()
|
||||||
|
return self._SCALE
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:getOffsetX()
|
||||||
|
return self._OFFSET_X
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:getOffsetY()
|
||||||
|
return self._OFFSET_Y
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:setMaxWidth(width)
|
||||||
|
self._MAX_WIDTH = width
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:setMaxHeight(height)
|
||||||
|
self._MAX_HEIGHT = height
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:setMaxRelativeWidth(width)
|
||||||
|
self._MAX_RELATIVE_WIDTH = width
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:setMaxRelativeHeight(height)
|
||||||
|
self._MAX_RELATIVE_HEIGHT = height
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:resize(width, height)
|
||||||
|
self._SCREEN_WIDTH = width
|
||||||
|
self._SCREEN_HEIGHT = height
|
||||||
|
self:apply()
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:apply()
|
||||||
|
local available_width = self._SCREEN_WIDTH - self._BORDERS.l - self._BORDERS.r
|
||||||
|
local available_height = self._SCREEN_HEIGHT - self._BORDERS.t - self._BORDERS.b
|
||||||
|
local max_width = available_width
|
||||||
|
local max_height = available_height
|
||||||
|
if self._MAX_RELATIVE_WIDTH > 0 and available_width * self._MAX_RELATIVE_WIDTH < max_width then
|
||||||
|
max_width = available_width * self._MAX_RELATIVE_WIDTH
|
||||||
|
end
|
||||||
|
if self._MAX_RELATIVE_HEIGHT > 0 and available_height * self._MAX_RELATIVE_HEIGHT < max_height then
|
||||||
|
max_height = available_height * self._MAX_RELATIVE_HEIGHT
|
||||||
|
end
|
||||||
|
if self._MAX_WIDTH > 0 and self._MAX_WIDTH < max_width then
|
||||||
|
max_width = self._MAX_WIDTH
|
||||||
|
end
|
||||||
|
if self._MAX_HEIGHT > 0 and self._MAX_HEIGHT < max_height then
|
||||||
|
max_height = self._MAX_HEIGHT
|
||||||
|
end
|
||||||
|
if max_height / max_width > self._HEIGHT / self._WIDTH then
|
||||||
|
self._CANVAS_WIDTH = max_width
|
||||||
|
self._CANVAS_HEIGHT = self._CANVAS_WIDTH * (self._HEIGHT / self._WIDTH)
|
||||||
|
else
|
||||||
|
self._CANVAS_HEIGHT = max_height
|
||||||
|
self._CANVAS_WIDTH = self._CANVAS_HEIGHT * (self._WIDTH / self._HEIGHT)
|
||||||
|
end
|
||||||
|
self._SCALE = self._CANVAS_HEIGHT / self._HEIGHT
|
||||||
|
self._OFFSET_X = self._BORDERS.l + (available_width - self._CANVAS_WIDTH) / 2
|
||||||
|
self._OFFSET_Y = self._BORDERS.t + (available_height - self._CANVAS_HEIGHT) / 2
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:start()
|
||||||
|
love.graphics.push()
|
||||||
|
love.graphics.translate(self._OFFSET_X, self._OFFSET_Y)
|
||||||
|
love.graphics.scale(self._SCALE, self._SCALE)
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:finish()
|
||||||
|
love.graphics.pop()
|
||||||
|
end
|
||||||
|
|
||||||
|
function center:toGame(x, y, w, h)
|
||||||
|
if not (self._OFFSET_X and self._OFFSET_Y and self._SCALE) then
|
||||||
|
return x, y, w, h
|
||||||
|
end
|
||||||
|
|
||||||
|
return (x - self._OFFSET_X) / self._SCALE,
|
||||||
|
(y - self._OFFSET_Y) / self._SCALE,
|
||||||
|
w and w / self._SCALE,
|
||||||
|
h and h / self._SCALE
|
||||||
|
end
|
||||||
|
|
||||||
|
return center
|
||||||
|
|
132
src/lib/sti/graphics.lua
Normal file
132
src/lib/sti/graphics.lua
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
local lg = _G.love.graphics
|
||||||
|
local graphics = { isCreated = lg and true or false }
|
||||||
|
|
||||||
|
function graphics.newSpriteBatch(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.newSpriteBatch(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.newCanvas(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.newCanvas(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.newImage(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.newImage(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.newQuad(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.newQuad(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.getCanvas(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.getCanvas(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.setCanvas(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.setCanvas(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.clear(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.clear(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.push(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.push(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.origin(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.origin(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.scale(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.scale(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.translate(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.translate(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.pop(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.pop(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.draw(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.draw(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.rectangle(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.rectangle(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.getColor(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.getColor(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.setColor(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.setColor(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.line(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.line(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.polygon(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.polygon(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.points(...)
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.points(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.getWidth()
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.getWidth()
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function graphics.getHeight()
|
||||||
|
if graphics.isCreated then
|
||||||
|
return lg.getHeight()
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
return graphics
|
1627
src/lib/sti/init.lua
Normal file
1627
src/lib/sti/init.lua
Normal file
File diff suppressed because it is too large
Load Diff
323
src/lib/sti/plugins/box2d.lua
Normal file
323
src/lib/sti/plugins/box2d.lua
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
--- Box2D plugin for STI
|
||||||
|
-- @module box2d
|
||||||
|
-- @author Landon Manning
|
||||||
|
-- @copyright 2019
|
||||||
|
-- @license MIT/X11
|
||||||
|
|
||||||
|
local love = _G.love
|
||||||
|
local utils = require((...):gsub('plugins.box2d', 'utils'))
|
||||||
|
local lg = require((...):gsub('plugins.box2d', 'graphics'))
|
||||||
|
|
||||||
|
return {
|
||||||
|
box2d_LICENSE = "MIT/X11",
|
||||||
|
box2d_URL = "https://github.com/karai17/Simple-Tiled-Implementation",
|
||||||
|
box2d_VERSION = "2.3.2.7",
|
||||||
|
box2d_DESCRIPTION = "Box2D hooks for STI.",
|
||||||
|
|
||||||
|
--- Initialize Box2D physics world.
|
||||||
|
-- @param world The Box2D world to add objects to.
|
||||||
|
box2d_init = function(map, world)
|
||||||
|
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 collision = {
|
||||||
|
body = body,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function addObjectToWorld(objshape, vertices, userdata, object)
|
||||||
|
local shape
|
||||||
|
|
||||||
|
if objshape == "polyline" then
|
||||||
|
if #vertices == 4 then
|
||||||
|
shape = love.physics.newEdgeShape(unpack(vertices))
|
||||||
|
else
|
||||||
|
shape = love.physics.newChainShape(false, unpack(vertices))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
shape = love.physics.newPolygonShape(unpack(vertices))
|
||||||
|
end
|
||||||
|
|
||||||
|
local currentBody = body
|
||||||
|
--dynamic are objects/players etc.
|
||||||
|
if userdata.properties.dynamic == true then
|
||||||
|
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')
|
||||||
|
-- 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')
|
||||||
|
end
|
||||||
|
|
||||||
|
local fixture = love.physics.newFixture(currentBody, shape)
|
||||||
|
fixture:setUserData(userdata)
|
||||||
|
|
||||||
|
-- Set some custom properties from userdata (or use default set by box2d)
|
||||||
|
fixture:setFriction(userdata.properties.friction or 0.2)
|
||||||
|
fixture:setRestitution(userdata.properties.restitution or 0.0)
|
||||||
|
fixture:setSensor(userdata.properties.sensor or false)
|
||||||
|
fixture:setFilterData(
|
||||||
|
userdata.properties.categories or 1,
|
||||||
|
userdata.properties.mask or 65535,
|
||||||
|
userdata.properties.group or 0
|
||||||
|
)
|
||||||
|
|
||||||
|
local obj = {
|
||||||
|
object = object,
|
||||||
|
body = currentBody,
|
||||||
|
shape = shape,
|
||||||
|
fixture = fixture,
|
||||||
|
}
|
||||||
|
|
||||||
|
table.insert(collision, obj)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getPolygonVertices(object)
|
||||||
|
local vertices = {}
|
||||||
|
for _, vertex in ipairs(object.polygon) do
|
||||||
|
table.insert(vertices, vertex.x)
|
||||||
|
table.insert(vertices, vertex.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
return vertices
|
||||||
|
end
|
||||||
|
|
||||||
|
local function calculateObjectPosition(object, tile)
|
||||||
|
local o = {
|
||||||
|
shape = object.shape,
|
||||||
|
x = (object.dx or object.x) + map.offsetx,
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
local userdata = {
|
||||||
|
object = o,
|
||||||
|
properties = object.properties
|
||||||
|
}
|
||||||
|
|
||||||
|
o.r = object.rotation or 0
|
||||||
|
if o.shape == "rectangle" then
|
||||||
|
local cos = math.cos(math.rad(o.r))
|
||||||
|
local sin = math.sin(math.rad(o.r))
|
||||||
|
local oy = 0
|
||||||
|
|
||||||
|
if object.gid then
|
||||||
|
local tileset = map.tilesets[map.tiles[object.gid].tileset]
|
||||||
|
local lid = object.gid - tileset.firstgid
|
||||||
|
local t = {}
|
||||||
|
|
||||||
|
-- This fixes a height issue
|
||||||
|
o.y = o.y + map.tiles[object.gid].offset.y
|
||||||
|
oy = o.h
|
||||||
|
|
||||||
|
for _, tt in ipairs(tileset.tiles) do
|
||||||
|
if tt.id == lid then
|
||||||
|
t = tt
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if t.objectGroup then
|
||||||
|
for _, obj in ipairs(t.objectGroup.objects) do
|
||||||
|
-- Every object in the tile
|
||||||
|
calculateObjectPosition(obj, object)
|
||||||
|
end
|
||||||
|
|
||||||
|
return
|
||||||
|
else
|
||||||
|
o.w = map.tiles[object.gid].width
|
||||||
|
o.h = map.tiles[object.gid].height
|
||||||
|
end
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, vertex in ipairs(o.polygon) do
|
||||||
|
vertex.x, vertex.y = utils.rotate_vertex(map, vertex, o.x, o.y, cos, sin, oy)
|
||||||
|
end
|
||||||
|
|
||||||
|
local vertices = getPolygonVertices(o)
|
||||||
|
addObjectToWorld(o.shape, vertices, userdata, tile or object)
|
||||||
|
elseif o.shape == "ellipse" then
|
||||||
|
if not o.polygon then
|
||||||
|
o.polygon = utils.convert_ellipse_to_polygon(o.x, o.y, o.w, o.h)
|
||||||
|
end
|
||||||
|
local vertices = getPolygonVertices(o)
|
||||||
|
local triangles = love.math.triangulate(vertices)
|
||||||
|
|
||||||
|
for _, triangle in ipairs(triangles) do
|
||||||
|
addObjectToWorld(o.shape, triangle, userdata, tile or object)
|
||||||
|
end
|
||||||
|
elseif o.shape == "polygon" then
|
||||||
|
-- Recalculate collision polygons inside tiles
|
||||||
|
if tile then
|
||||||
|
local cos = math.cos(math.rad(o.r))
|
||||||
|
local sin = math.sin(math.rad(o.r))
|
||||||
|
for _, vertex in ipairs(o.polygon) do
|
||||||
|
vertex.x = vertex.x + o.x
|
||||||
|
vertex.y = vertex.y + o.y
|
||||||
|
vertex.x, vertex.y = utils.rotate_vertex(map, vertex, o.x, o.y, cos, sin)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local vertices = getPolygonVertices(o)
|
||||||
|
local triangles = love.math.triangulate(vertices)
|
||||||
|
|
||||||
|
for _, triangle in ipairs(triangles) do
|
||||||
|
addObjectToWorld(o.shape, triangle, userdata, tile or object)
|
||||||
|
end
|
||||||
|
elseif o.shape == "polyline" then
|
||||||
|
local vertices = getPolygonVertices(o)
|
||||||
|
addObjectToWorld(o.shape, vertices, userdata, tile or object)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, tile in pairs(map.tiles) do
|
||||||
|
if map.tileInstances[tile.gid] then
|
||||||
|
for _, instance in ipairs(map.tileInstances[tile.gid]) do
|
||||||
|
-- Every object in every instance of a tile
|
||||||
|
if tile.objectGroup then
|
||||||
|
for _, object in ipairs(tile.objectGroup.objects) do
|
||||||
|
if object.properties.collidable == true then
|
||||||
|
object = utils.deepCopy(object)
|
||||||
|
object.dx = instance.x + object.x
|
||||||
|
object.dy = instance.y + object.y
|
||||||
|
calculateObjectPosition(object, instance)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Every instance of a tile
|
||||||
|
if tile.properties.collidable == true then
|
||||||
|
local object = {
|
||||||
|
shape = "rectangle",
|
||||||
|
x = instance.x,
|
||||||
|
y = instance.y,
|
||||||
|
width = map.tilewidth,
|
||||||
|
height = map.tileheight,
|
||||||
|
properties = tile.properties
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateObjectPosition(object, instance)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, layer in ipairs(map.layers) do
|
||||||
|
-- Entire layer
|
||||||
|
if layer.properties.collidable == true then
|
||||||
|
if layer.type == "tilelayer" then
|
||||||
|
for gid, tiles in pairs(map.tileInstances) do
|
||||||
|
local tile = map.tiles[gid]
|
||||||
|
local tileset = map.tilesets[tile.tileset]
|
||||||
|
|
||||||
|
for _, instance in ipairs(tiles) do
|
||||||
|
if instance.layer == layer then
|
||||||
|
local object = {
|
||||||
|
shape = "rectangle",
|
||||||
|
x = instance.x,
|
||||||
|
y = instance.y,
|
||||||
|
width = tileset.tilewidth,
|
||||||
|
height = tileset.tileheight,
|
||||||
|
properties = tile.properties
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateObjectPosition(object, instance)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif layer.type == "objectgroup" then
|
||||||
|
for _, object in ipairs(layer.objects) do
|
||||||
|
calculateObjectPosition(object)
|
||||||
|
end
|
||||||
|
elseif layer.type == "imagelayer" then
|
||||||
|
local object = {
|
||||||
|
shape = "rectangle",
|
||||||
|
x = layer.x or 0,
|
||||||
|
y = layer.y or 0,
|
||||||
|
width = layer.width,
|
||||||
|
height = layer.height,
|
||||||
|
properties = layer.properties
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateObjectPosition(object)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Individual objects
|
||||||
|
if layer.type == "objectgroup" then
|
||||||
|
for _, object in ipairs(layer.objects) do
|
||||||
|
if object.properties.collidable == true then
|
||||||
|
calculateObjectPosition(object)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
map.box2d_collision = collision
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Remove Box2D fixtures and shapes from world.
|
||||||
|
-- @param index The index or name of the layer being removed
|
||||||
|
box2d_removeLayer = function(map, index)
|
||||||
|
local layer = assert(map.layers[index], "Layer not found: " .. index)
|
||||||
|
local collision = map.box2d_collision
|
||||||
|
|
||||||
|
-- Remove collision objects
|
||||||
|
for i = #collision, 1, -1 do
|
||||||
|
local obj = collision[i]
|
||||||
|
|
||||||
|
if obj.object.layer == layer then
|
||||||
|
obj.fixture:destroy()
|
||||||
|
table.remove(collision, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Draw Box2D physics world.
|
||||||
|
-- @param tx Translate on X
|
||||||
|
-- @param ty Translate on Y
|
||||||
|
-- @param sx Scale on X
|
||||||
|
-- @param sy Scale on Y
|
||||||
|
box2d_draw = function(map, tx, ty, sx, sy)
|
||||||
|
local collision = map.box2d_collision
|
||||||
|
|
||||||
|
lg.push()
|
||||||
|
lg.scale(sx or 1, sy or sx or 1)
|
||||||
|
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 shape_type = obj.shape:getType()
|
||||||
|
|
||||||
|
if shape_type == "edge" or shape_type == "chain" then
|
||||||
|
love.graphics.line(points)
|
||||||
|
elseif shape_type == "polygon" then
|
||||||
|
love.graphics.polygon("line", points)
|
||||||
|
else
|
||||||
|
error("sti box2d plugin does not support "..shape_type.." shapes")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
lg.pop()
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Custom Properties in Tiled are used to tell this plugin what to do.
|
||||||
|
-- @table Properties
|
||||||
|
-- @field collidable set to true, can be used on any Layer, Tile, or Object
|
||||||
|
-- @field sensor set to true, can be used on any Tile or Object that is also collidable
|
||||||
|
-- @field dynamic set to true, can be used on any Tile or Object
|
||||||
|
-- @field friction can be used to define the friction of any Object
|
||||||
|
-- @field restitution can be used to define the restitution of any Object
|
||||||
|
-- @field categories can be used to set the filter Category of any Object
|
||||||
|
-- @field mask can be used to set the filter Mask of any Object
|
||||||
|
-- @field group can be used to set the filter Group of any Object
|
193
src/lib/sti/plugins/bump.lua
Normal file
193
src/lib/sti/plugins/bump.lua
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
--- Bump.lua plugin for STI
|
||||||
|
-- @module bump.lua
|
||||||
|
-- @author David Serrano (BobbyJones|FrenchFryLord)
|
||||||
|
-- @copyright 2019
|
||||||
|
-- @license MIT/X11
|
||||||
|
|
||||||
|
local lg = require((...):gsub('plugins.bump', 'graphics'))
|
||||||
|
|
||||||
|
return {
|
||||||
|
bump_LICENSE = "MIT/X11",
|
||||||
|
bump_URL = "https://github.com/karai17/Simple-Tiled-Implementation",
|
||||||
|
bump_VERSION = "3.1.7.1",
|
||||||
|
bump_DESCRIPTION = "Bump hooks for STI.",
|
||||||
|
|
||||||
|
--- Adds each collidable tile to the Bump world.
|
||||||
|
-- @param world The Bump world to add objects to.
|
||||||
|
-- @return collidables table containing the handles to the objects in the Bump world.
|
||||||
|
bump_init = function(map, world)
|
||||||
|
local collidables = {}
|
||||||
|
|
||||||
|
for _, tileset in ipairs(map.tilesets) do
|
||||||
|
for _, tile in ipairs(tileset.tiles) do
|
||||||
|
local gid = tileset.firstgid + tile.id
|
||||||
|
|
||||||
|
if map.tileInstances[gid] then
|
||||||
|
for _, instance in ipairs(map.tileInstances[gid]) do
|
||||||
|
-- Every object in every instance of a tile
|
||||||
|
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 = instance.x + map.offsetx + object.x,
|
||||||
|
y = instance.y + map.offsety + object.y,
|
||||||
|
width = object.width,
|
||||||
|
height = object.height,
|
||||||
|
layer = instance.layer,
|
||||||
|
properties = object.properties
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
world:add(t, t.x, t.y, t.width, t.height)
|
||||||
|
table.insert(collidables, t)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Every instance of a tile
|
||||||
|
if tile.properties and tile.properties.collidable == true then
|
||||||
|
local t = {
|
||||||
|
x = instance.x + map.offsetx,
|
||||||
|
y = instance.y + map.offsety,
|
||||||
|
width = map.tilewidth,
|
||||||
|
height = map.tileheight,
|
||||||
|
layer = instance.layer,
|
||||||
|
type = tile.type,
|
||||||
|
properties = tile.properties
|
||||||
|
}
|
||||||
|
|
||||||
|
world:add(t, t.x, t.y, t.width, t.height)
|
||||||
|
table.insert(collidables, t)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, layer in ipairs(map.layers) do
|
||||||
|
-- Entire layer
|
||||||
|
if layer.properties.collidable == true then
|
||||||
|
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,
|
||||||
|
width = object.width,
|
||||||
|
height = object.height,
|
||||||
|
layer = layer,
|
||||||
|
properties = object.properties
|
||||||
|
}
|
||||||
|
|
||||||
|
world:add(t, t.x, t.y, t.width, t.height)
|
||||||
|
table.insert(collidables, t)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local t = {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
world:add(t, t.x, t.y, t.width, t.height)
|
||||||
|
table.insert(collidables, t)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif layer.type == "imagelayer" then
|
||||||
|
world:add(layer, layer.x, layer.y, layer.width, layer.height)
|
||||||
|
table.insert(collidables, layer)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- individual collidable objects in a layer that is not "collidable"
|
||||||
|
-- or whole collidable objects layer
|
||||||
|
if layer.type == "objectgroup" then
|
||||||
|
for _, obj in ipairs(layer.objects) do
|
||||||
|
if layer.properties.collidable == true or obj.properties.collidable == true then
|
||||||
|
if obj.shape == "rectangle" then
|
||||||
|
local t = {
|
||||||
|
name = obj.name,
|
||||||
|
type = obj.type,
|
||||||
|
x = obj.x + map.offsetx,
|
||||||
|
y = obj.y + map.offsety,
|
||||||
|
width = obj.width,
|
||||||
|
height = obj.height,
|
||||||
|
layer = layer,
|
||||||
|
properties = obj.properties
|
||||||
|
}
|
||||||
|
|
||||||
|
if obj.gid then
|
||||||
|
t.y = t.y - obj.height
|
||||||
|
end
|
||||||
|
|
||||||
|
world:add(t, t.x, t.y, t.width, t.height)
|
||||||
|
table.insert(collidables, t)
|
||||||
|
end -- TODO implement other object shapes?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
map.bump_world = world
|
||||||
|
map.bump_collidables = collidables
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Remove layer
|
||||||
|
-- @param index to layer to be removed
|
||||||
|
bump_removeLayer = function(map, index)
|
||||||
|
local layer = assert(map.layers[index], "Layer not found: " .. index)
|
||||||
|
local collidables = map.bump_collidables
|
||||||
|
|
||||||
|
-- Remove collision objects
|
||||||
|
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
|
||||||
|
map.bump_world:remove(obj)
|
||||||
|
table.remove(collidables, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Draw bump collisions world.
|
||||||
|
-- @param world bump world holding the tiles geometry
|
||||||
|
-- @param tx Translate on X
|
||||||
|
-- @param ty Translate on Y
|
||||||
|
-- @param sx Scale on X
|
||||||
|
-- @param sy Scale on Y
|
||||||
|
bump_draw = function(map, tx, ty, sx, sy)
|
||||||
|
lg.push()
|
||||||
|
lg.scale(sx or 1, sy or sx or 1)
|
||||||
|
lg.translate(math.floor(tx or 0), math.floor(ty or 0))
|
||||||
|
|
||||||
|
local items = map.bump_world:getItems()
|
||||||
|
for _, item in ipairs(items) do
|
||||||
|
lg.rectangle("line", map.bump_world:getRect(item))
|
||||||
|
end
|
||||||
|
|
||||||
|
lg.pop()
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Custom Properties in Tiled are used to tell this plugin what to do.
|
||||||
|
-- @table Properties
|
||||||
|
-- @field collidable set to true, can be used on any Layer, Tile, or Object
|
217
src/lib/sti/utils.lua
Normal file
217
src/lib/sti/utils.lua
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
-- Some utility functions that shouldn't be exposed.
|
||||||
|
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 k
|
||||||
|
|
||||||
|
repeat -- /./ -> /
|
||||||
|
path,k = path:gsub(np_pat2,'/',1)
|
||||||
|
until k == 0
|
||||||
|
|
||||||
|
repeat -- A/../ -> (empty)
|
||||||
|
path,k = path:gsub(np_pat1,'',1)
|
||||||
|
until k == 0
|
||||||
|
|
||||||
|
if path == '' then path = '.' end
|
||||||
|
|
||||||
|
return path
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Compensation for scale/rotation shift
|
||||||
|
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.r > 0 then
|
||||||
|
tileX = tileX + tileH - compy
|
||||||
|
tileY = tileY + tileH + compx - tileW
|
||||||
|
elseif tile.r < 0 then
|
||||||
|
tileX = tileX + compy
|
||||||
|
tileY = tileY - compx + tileH
|
||||||
|
else
|
||||||
|
tileX = tileX + compx
|
||||||
|
tileY = tileY + compy
|
||||||
|
end
|
||||||
|
|
||||||
|
return tileX, tileY
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Cache images in main STI module
|
||||||
|
function utils.cache_image(sti, path, image)
|
||||||
|
image = image or love.graphics.newImage(path)
|
||||||
|
image:setFilter("nearest", "nearest")
|
||||||
|
sti.cache[path] = image
|
||||||
|
end
|
||||||
|
|
||||||
|
-- We just don't know.
|
||||||
|
function utils.get_tiles(imageW, tileW, margin, spacing)
|
||||||
|
imageW = imageW - margin
|
||||||
|
local n = 0
|
||||||
|
|
||||||
|
while imageW >= tileW do
|
||||||
|
imageW = imageW - tileW
|
||||||
|
if n ~= 0 then imageW = imageW - spacing end
|
||||||
|
if imageW >= 0 then n = n + 1 end
|
||||||
|
end
|
||||||
|
|
||||||
|
return n
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Decompress tile layer data
|
||||||
|
function utils.get_decompressed_data(data)
|
||||||
|
local ffi = require "ffi"
|
||||||
|
local d = {}
|
||||||
|
local decoded = ffi.cast("uint32_t*", data)
|
||||||
|
|
||||||
|
for i = 0, data:len() / ffi.sizeof("uint32_t") do
|
||||||
|
table.insert(d, tonumber(decoded[i]))
|
||||||
|
end
|
||||||
|
|
||||||
|
return d
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert a Tiled ellipse object to a LOVE polygon
|
||||||
|
function utils.convert_ellipse_to_polygon(x, y, w, h, max_segments)
|
||||||
|
local ceil = math.ceil
|
||||||
|
local cos = math.cos
|
||||||
|
local sin = math.sin
|
||||||
|
|
||||||
|
local function calc_segments(segments)
|
||||||
|
local function vdist(a, b)
|
||||||
|
local c = {
|
||||||
|
x = a.x - b.x,
|
||||||
|
y = a.y - b.y,
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.x * c.x + c.y * c.y
|
||||||
|
end
|
||||||
|
|
||||||
|
segments = segments or 64
|
||||||
|
local vertices = {}
|
||||||
|
|
||||||
|
local v = { 1, 2, ceil(segments/4-1), ceil(segments/4) }
|
||||||
|
|
||||||
|
local m
|
||||||
|
if love and love.physics then
|
||||||
|
m = love.physics.getMeter()
|
||||||
|
else
|
||||||
|
m = 32
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, i in ipairs(v) do
|
||||||
|
local angle = (i / segments) * math.pi * 2
|
||||||
|
local px = x + w / 2 + cos(angle) * w / 2
|
||||||
|
local py = y + h / 2 + sin(angle) * h / 2
|
||||||
|
|
||||||
|
table.insert(vertices, { x = px / m, y = py / m })
|
||||||
|
end
|
||||||
|
|
||||||
|
local dist1 = vdist(vertices[1], vertices[2])
|
||||||
|
local dist2 = vdist(vertices[3], vertices[4])
|
||||||
|
|
||||||
|
-- Box2D threshold
|
||||||
|
if dist1 < 0.0025 or dist2 < 0.0025 then
|
||||||
|
return calc_segments(segments-2)
|
||||||
|
end
|
||||||
|
|
||||||
|
return segments
|
||||||
|
end
|
||||||
|
|
||||||
|
local segments = calc_segments(max_segments)
|
||||||
|
local vertices = {}
|
||||||
|
|
||||||
|
table.insert(vertices, { x = x + w / 2, y = y + h / 2 })
|
||||||
|
|
||||||
|
for i = 0, segments do
|
||||||
|
local angle = (i / segments) * math.pi * 2
|
||||||
|
local px = x + w / 2 + cos(angle) * w / 2
|
||||||
|
local py = y + h / 2 + sin(angle) * h / 2
|
||||||
|
|
||||||
|
table.insert(vertices, { x = px, y = py })
|
||||||
|
end
|
||||||
|
|
||||||
|
return vertices
|
||||||
|
end
|
||||||
|
|
||||||
|
function utils.rotate_vertex(map, vertex, x, y, cos, sin, oy)
|
||||||
|
if map.orientation == "isometric" then
|
||||||
|
x, y = utils.convert_isometric_to_screen(map, x, y)
|
||||||
|
vertex.x, vertex.y = utils.convert_isometric_to_screen(map, vertex.x, vertex.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Project isometric position to cartesian position
|
||||||
|
function utils.convert_isometric_to_screen(map, x, y)
|
||||||
|
local mapW = map.width
|
||||||
|
local tileW = map.tilewidth
|
||||||
|
local tileH = map.tileheight
|
||||||
|
local tileX = x / tileH
|
||||||
|
local tileY = y / tileH
|
||||||
|
local offsetX = mapW * tileW / 2
|
||||||
|
|
||||||
|
return
|
||||||
|
(tileX - tileY) * tileW / 2 + offsetX,
|
||||||
|
(tileX + tileY) * tileH / 2
|
||||||
|
end
|
||||||
|
|
||||||
|
function utils.hex_to_color(hex)
|
||||||
|
if hex:sub(1, 1) == "#" then
|
||||||
|
hex = hex:sub(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
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
|
||||||
|
return r, g, b, 0
|
||||||
|
end
|
||||||
|
|
||||||
|
return r, g, b, a
|
||||||
|
end
|
||||||
|
|
||||||
|
function utils.fix_transparent_color(tileset, path)
|
||||||
|
local image_data = love.image.newImageData(path)
|
||||||
|
tileset.image = love.graphics.newImage(image_data)
|
||||||
|
|
||||||
|
if tileset.transparentcolor then
|
||||||
|
utils._TC = utils.hex_to_color(tileset.transparentcolor)
|
||||||
|
|
||||||
|
image_data:mapPixel(utils.pixel_function)
|
||||||
|
tileset.image = love.graphics.newImage(image_data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function utils.deepCopy(t)
|
||||||
|
local copy = {}
|
||||||
|
for k,v in pairs(t) do
|
||||||
|
if type(v) == "table" then
|
||||||
|
v = utils.deepCopy(v)
|
||||||
|
end
|
||||||
|
copy[k] = v
|
||||||
|
end
|
||||||
|
return copy
|
||||||
|
end
|
||||||
|
|
||||||
|
return utils
|
@ -1,6 +1,7 @@
|
|||||||
local Gamestate = require("lib.hump.gamestate")
|
local Gamestate = require("lib.hump.gamestate")
|
||||||
local binser = require("lib.binser")
|
local binser = require("lib.binser")
|
||||||
local Vec = require("lib.brinevector")
|
local Vec = require("lib.brinevector")
|
||||||
|
require("screen-scaler")
|
||||||
|
|
||||||
binser.registerStruct("brinevector",
|
binser.registerStruct("brinevector",
|
||||||
function(v) return v.x, v.y end,
|
function(v) return v.x, v.y end,
|
||||||
@ -12,6 +13,6 @@ function love.load()
|
|||||||
love.keyboard.setKeyRepeat(true)
|
love.keyboard.setKeyRepeat(true)
|
||||||
math.randomseed(love.timer.getTime())
|
math.randomseed(love.timer.getTime())
|
||||||
|
|
||||||
Gamestate.switch(require("states.main-menu"))
|
Gamestate.switch(require("states.main"))
|
||||||
Gamestate.registerEvents()
|
Gamestate.registerEvents()
|
||||||
end
|
end
|
||||||
|
254
src/screen-scaler.lua
Normal file
254
src/screen-scaler.lua
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
--- Module resposible for scaling screen and centering contents
|
||||||
|
-- while respecting ratios.
|
||||||
|
-- @module ScreenScaler
|
||||||
|
local ScreenScaler = {}
|
||||||
|
|
||||||
|
local canvas
|
||||||
|
|
||||||
|
-- This "Center" library will do most of the heavy lifting
|
||||||
|
local Center = require("lib.center")
|
||||||
|
|
||||||
|
local getRealDimensions = love.graphics.getDimensions
|
||||||
|
|
||||||
|
--- Set the "ideal" dimensions from which everything else will be scaled.
|
||||||
|
-- @tparam number w virtual width
|
||||||
|
-- @tparam number h virtual height
|
||||||
|
function ScreenScaler.setVirtualDimensions(w, h)
|
||||||
|
assert(type(w) == "number", "Expected width to be number")
|
||||||
|
assert(type(h) == "number", "Expected height to be number")
|
||||||
|
ScreenScaler.width, ScreenScaler.height = nil, nil
|
||||||
|
|
||||||
|
-- Setup library resposible for scaling the screen
|
||||||
|
Center:setupScreen(w, h)
|
||||||
|
canvas = love.graphics.newCanvas(w, h)
|
||||||
|
canvas:setFilter("nearest", "nearest")
|
||||||
|
|
||||||
|
ScreenScaler.width, ScreenScaler.height = w, h
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Unsets virtual dimensions. Effectively disables scaler.
|
||||||
|
function ScreenScaler.unsetVirtualDimensions()
|
||||||
|
ScreenScaler.width = nil
|
||||||
|
ScreenScaler.height = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get virtual dimensions.
|
||||||
|
-- @return width, height
|
||||||
|
function ScreenScaler.getVirtualDimensions()
|
||||||
|
return ScreenScaler.width, ScreenScaler.height
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns true if scaler is enabled.
|
||||||
|
-- @treturn boolean
|
||||||
|
function ScreenScaler.isEnabled()
|
||||||
|
return ScreenScaler.width ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Overwrite default love.mouse functions to return position
|
||||||
|
-- relative to scaled window
|
||||||
|
do
|
||||||
|
local getX = love.mouse.getX
|
||||||
|
function love.mouse.getX()
|
||||||
|
local x = getX()
|
||||||
|
if not ScreenScaler.isEnabled() then
|
||||||
|
return x
|
||||||
|
end
|
||||||
|
return (x - Center:getOffsetX()) / Center:getScale()
|
||||||
|
end
|
||||||
|
|
||||||
|
local getY = love.mouse.getY
|
||||||
|
function love.mouse.getY()
|
||||||
|
local y = getY()
|
||||||
|
if not ScreenScaler.isEnabled() then
|
||||||
|
return y
|
||||||
|
end
|
||||||
|
return (y - Center:getOffsetY()) / Center:getScale()
|
||||||
|
end
|
||||||
|
|
||||||
|
local getPosition = love.mouse.getPosition
|
||||||
|
function love.mouse.getPosition()
|
||||||
|
if ScreenScaler.isEnabled() then
|
||||||
|
return Center:toGame(getPosition())
|
||||||
|
else
|
||||||
|
return getPosition()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: add replacements for setX, setY, setPosition
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Overwrite default getDimensions, getWidth, getHeight
|
||||||
|
-- to return virtual width and height if scaler is enabled
|
||||||
|
do
|
||||||
|
local getWidth = love.graphics.getWidth
|
||||||
|
function love.graphics.getWidth()
|
||||||
|
return ScreenScaler.width or getWidth()
|
||||||
|
end
|
||||||
|
|
||||||
|
local getHeight = love.graphics.getHeight
|
||||||
|
function love.graphics.getHeight()
|
||||||
|
return ScreenScaler.height or getHeight()
|
||||||
|
end
|
||||||
|
|
||||||
|
function love.graphics.getDimensions()
|
||||||
|
return love.graphics.getWidth(), love.graphics.getHeight()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Adjust setScissor and intersectScissor function, so that they are relative
|
||||||
|
-- to the scaled screen. By default these functions are unaffected by transformations
|
||||||
|
do
|
||||||
|
local setScissor = love.graphics.setScissor
|
||||||
|
function love.graphics.setScissor(x, y, w, h)
|
||||||
|
if x and ScreenScaler.isEnabled() then
|
||||||
|
setScissor(Center:toGame(x, y, w, h))
|
||||||
|
else
|
||||||
|
setScissor(x, y, w, h)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local intersectScissor = love.graphics.intersectScissor
|
||||||
|
function love.graphics.intersectScissor(x, y, w, h)
|
||||||
|
if x and ScreenScaler.isEnabled() then
|
||||||
|
intersectScissor(Center:toGame(x, y, w, h))
|
||||||
|
else
|
||||||
|
intersectScissor(x, y, w, h)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function isInBounds(x, y)
|
||||||
|
if not ScreenScaler.isEnabled() then return true end
|
||||||
|
local w, h = ScreenScaler.getVirtualDimensions()
|
||||||
|
return x >= 0 and x < w and y >= 0 and y < h
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create event proccessors for converting normal screen coordinates
|
||||||
|
-- to scaled screen coordinates
|
||||||
|
-- If the user clicked out of bounds, it will not handled
|
||||||
|
local eventPreProccessor = {}
|
||||||
|
function eventPreProccessor.mousepressed(x, y, button, istouch, presses)
|
||||||
|
x, y = Center:toGame(x, y)
|
||||||
|
return isInBounds(x, y), x, y, button, istouch, presses
|
||||||
|
end
|
||||||
|
|
||||||
|
function eventPreProccessor.mousereleased(x, y, button, istouch, presses)
|
||||||
|
x, y = Center:toGame(x, y)
|
||||||
|
return isInBounds(x, y), x, y, button, istouch, presses
|
||||||
|
end
|
||||||
|
|
||||||
|
function eventPreProccessor.mousemoved(x, y, dx, dy, istouch)
|
||||||
|
local scale = Center:getScale()
|
||||||
|
x, y = Center:toGame(x, y)
|
||||||
|
dx, dy = dx / scale, dy / scale
|
||||||
|
return isInBounds(x, y), x, y, dx, dy, istouch, istouch
|
||||||
|
end
|
||||||
|
|
||||||
|
function eventPreProccessor.wheelmoved(x, y)
|
||||||
|
return isInBounds(love.mouse.getPosition()), x, y
|
||||||
|
end
|
||||||
|
|
||||||
|
local function hideOutOfBounds()
|
||||||
|
local r, g, b, a = love.graphics.getColor()
|
||||||
|
love.graphics.setColor(0, 0, 0, 1)
|
||||||
|
local w, h = getRealDimensions()
|
||||||
|
|
||||||
|
if Center._OFFSET_X ~= 0 then
|
||||||
|
love.graphics.rectangle("fill", 0, 0, Center._OFFSET_X, h)
|
||||||
|
love.graphics.rectangle("fill", Center._WIDTH*Center._SCALE+Center._OFFSET_X, 0, Center._OFFSET_X, h)
|
||||||
|
end
|
||||||
|
|
||||||
|
if Center._OFFSET_Y ~= 0 then
|
||||||
|
love.graphics.rectangle("fill", 0, 0, w, Center._OFFSET_Y)
|
||||||
|
love.graphics.rectangle("fill", 0, Center._HEIGHT*Center._SCALE+Center._OFFSET_Y, w, Center._OFFSET_Y)
|
||||||
|
end
|
||||||
|
|
||||||
|
love.graphics.setColor(r, g, b, a)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Modify core game loop so that if scaler is enabled:
|
||||||
|
-- * resize events are not handled
|
||||||
|
-- * out of bounds mouse events are not handled
|
||||||
|
-- * all drawing operations are centered
|
||||||
|
function love.run()
|
||||||
|
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
|
||||||
|
|
||||||
|
local dt = 0
|
||||||
|
|
||||||
|
-- Main loop time.
|
||||||
|
return function()
|
||||||
|
-- Process events.
|
||||||
|
if love.event then
|
||||||
|
love.event.pump()
|
||||||
|
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
|
||||||
|
|
||||||
|
if ScreenScaler.isEnabled() then
|
||||||
|
if name == "resize" then
|
||||||
|
Center:resize(a, b)
|
||||||
|
goto continue
|
||||||
|
elseif eventPreProccessor[name] then
|
||||||
|
local success
|
||||||
|
success, a, b, c, d, e, f = eventPreProccessor[name](a, b, c, d, e, f)
|
||||||
|
if not success then goto continue end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
love.handlers[name](a, b, c, d, e, f)
|
||||||
|
::continue::
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update dt, as we'll be passing it to update
|
||||||
|
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.graphics and love.graphics.isActive() then
|
||||||
|
love.graphics.origin()
|
||||||
|
|
||||||
|
if canvas then
|
||||||
|
love.graphics.clear(love.graphics.getBackgroundColor())
|
||||||
|
|
||||||
|
love.graphics.setCanvas(canvas)
|
||||||
|
love.graphics.clear(love.graphics.getBackgroundColor())
|
||||||
|
love.draw()
|
||||||
|
love.graphics.setCanvas()
|
||||||
|
|
||||||
|
Center:start()
|
||||||
|
love.graphics.draw(canvas)
|
||||||
|
Center:finish()
|
||||||
|
else
|
||||||
|
love.graphics.clear(love.graphics.getBackgroundColor())
|
||||||
|
|
||||||
|
if love.draw then
|
||||||
|
if ScreenScaler.isEnabled() then
|
||||||
|
love.graphics.setCanvas(canvas)
|
||||||
|
love.draw()
|
||||||
|
love.graphics.setCanvas()
|
||||||
|
|
||||||
|
Center:start()
|
||||||
|
love.graphics.draw(canvas)
|
||||||
|
Center:finish()
|
||||||
|
hideOutOfBounds()
|
||||||
|
else
|
||||||
|
love.draw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
love.graphics.present()
|
||||||
|
end
|
||||||
|
|
||||||
|
if love.timer then love.timer.sleep(0.001) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return ScreenScaler
|
@ -4,24 +4,32 @@ local nata = require("lib.nata")
|
|||||||
local data = require("data")
|
local data = require("data")
|
||||||
|
|
||||||
function MainState:enter(_, host_socket)
|
function MainState:enter(_, host_socket)
|
||||||
|
local groups = {
|
||||||
|
physical = {filter = {"pos", "vel"}},
|
||||||
|
player = {filter = {
|
||||||
|
"pos", "acc", "speed",
|
||||||
|
"bolt_count",
|
||||||
|
"bolt_cooldown", "bolt_speed", "bolt_friction"
|
||||||
|
}},
|
||||||
|
controllable_player = {filter = {"controllable"}},
|
||||||
|
sprite = {filter = {"sprite"}},
|
||||||
|
bolt = {filter={"pos", "vel", "bolt"}}
|
||||||
|
}
|
||||||
|
|
||||||
|
local systems = {
|
||||||
|
require("systems.physics"),
|
||||||
|
require("systems.map"),
|
||||||
|
require("systems.player"),
|
||||||
|
require("systems.sprite"),
|
||||||
|
}
|
||||||
|
|
||||||
|
if host_socket then
|
||||||
|
table.insert(systems, require("systems.multiplayer"))
|
||||||
|
end
|
||||||
|
|
||||||
self.ecs = nata.new{
|
self.ecs = nata.new{
|
||||||
groups = {
|
groups = groups,
|
||||||
physical = {filter = {"pos", "vel"}},
|
systems = systems,
|
||||||
player = {filter = {
|
|
||||||
"pos", "acc", "speed",
|
|
||||||
"bolt_count",
|
|
||||||
"bolt_cooldown", "bolt_speed", "bolt_friction"
|
|
||||||
}},
|
|
||||||
controllable_player = {filter = {"controllable"}},
|
|
||||||
sprite = {filter = {"sprite"}},
|
|
||||||
bolt = {filter={"pos", "vel", "bolt"}}
|
|
||||||
},
|
|
||||||
systems = {
|
|
||||||
require("systems.physics"),
|
|
||||||
require("systems.player"),
|
|
||||||
require("systems.sprite"),
|
|
||||||
require("systems.multiplayer")
|
|
||||||
},
|
|
||||||
data = {
|
data = {
|
||||||
host_socket = host_socket
|
host_socket = host_socket
|
||||||
}
|
}
|
||||||
@ -38,8 +46,10 @@ function MainState:update(dt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function MainState:cleanup()
|
function MainState:cleanup()
|
||||||
local MultiplayerSystem = self.ecs:getSystem(require("systems.multiplayer"))
|
local multiplayer = self.ecs:getSystem(require("systems.multiplayer"))
|
||||||
MultiplayerSystem:disconnectPeers()
|
if multiplayer then
|
||||||
|
multiplayer:disconnectPeers()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function MainState:quit()
|
function MainState:quit()
|
||||||
|
37
src/systems/map.lua
Normal file
37
src/systems/map.lua
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
local rgb = require("helpers.rgb")
|
||||||
|
local sti = require("lib.sti")
|
||||||
|
local ScreenScaler = require("screen-scaler")
|
||||||
|
local Map = {}
|
||||||
|
|
||||||
|
local DEBUG_GRID = true
|
||||||
|
local DEBUG_GRID_COLOR = rgb(30, 30, 30)
|
||||||
|
|
||||||
|
function Map:init()
|
||||||
|
self.map = sti("data/maps/test.lua")
|
||||||
|
|
||||||
|
ScreenScaler.setVirtualDimensions(
|
||||||
|
self.map.width * self.map.tilewidth,
|
||||||
|
self.map.height * self.map.tileheight
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Map:update(dt)
|
||||||
|
self.map:update(dt)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Map:draw()
|
||||||
|
if DEBUG_GRID and self.map then
|
||||||
|
local w, h = love.graphics.getDimensions()
|
||||||
|
love.graphics.setColor(DEBUG_GRID_COLOR)
|
||||||
|
for x=0, w, self.map.tilewidth do
|
||||||
|
love.graphics.line(x, 0, x, h)
|
||||||
|
end
|
||||||
|
for y=0, h, self.map.tileheight do
|
||||||
|
love.graphics.line(0, y, w, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
love.graphics.setColor(1, 1, 1)
|
||||||
|
self.map:draw()
|
||||||
|
end
|
||||||
|
|
||||||
|
return Map
|
@ -142,8 +142,8 @@ function Player:draw()
|
|||||||
for _, e in ipairs(self.pool.groups.player.entities) do
|
for _, e in ipairs(self.pool.groups.player.entities) do
|
||||||
if e.aim_dir.x ~= 0 or e.aim_dir.y ~= 0 then
|
if e.aim_dir.x ~= 0 or e.aim_dir.y ~= 0 then
|
||||||
love.graphics.setColor(0.8, 0.2, 0.2)
|
love.graphics.setColor(0.8, 0.2, 0.2)
|
||||||
local aim_pos = e.pos + e.aim_dir * 25
|
local aim_pos = e.pos + e.aim_dir * 15
|
||||||
love.graphics.circle("fill", aim_pos.x, aim_pos.y, 10)
|
love.graphics.circle("fill", aim_pos.x, aim_pos.y, 5)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -3,7 +3,7 @@ local Sprite = {}
|
|||||||
function Sprite:draw()
|
function Sprite:draw()
|
||||||
for _, e in ipairs(self.pool.groups.sprite.entities) do
|
for _, e in ipairs(self.pool.groups.sprite.entities) do
|
||||||
love.graphics.setColor(1, 1, 1)
|
love.graphics.setColor(1, 1, 1)
|
||||||
love.graphics.circle("fill", e.pos.x, e.pos.y, 20)
|
love.graphics.circle("fill", e.pos.x, e.pos.y, 10)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user