## Simple Tiled Implementation - STI v0.18.2.1

NightKawata
Party member
Posts: 290
Joined: Tue Jan 01, 2013 9:18 pm
Location: Cyberspace, Room 6502
Contact:

### Re: Simple Tiled Implementation - STI v0.18.2.1

I didn't have any major issues using SSYGEN's STALKER-X lib with STI: https://github.com/SSYGEN/STALKER-X
"I view Python for game usage about the same as going fishing with a stick of dynamite. It will do the job but it's big, noisy, you'll probably get soaking wet and you've still got to get the damn fish out of the water." -taylor

Pospos
Citizen
Posts: 70
Joined: Sun Jun 18, 2017 11:10 am

### Re: Simple Tiled Implementation - STI v0.18.2.1

i have this error.
Error: sti/init.lua:234: attempt to perform arithmetic on field 'offsetx' (a nil value)

and this is my code

Code: Select all

local sti = require "sti"

-- Grab window size
windowWidth  = love.graphics.getWidth()
windowHeight = love.graphics.getHeight()

-- Set world meter size (in pixels)
love.physics.setMeter(32)

-- Load a map exported to Lua from Tiled
map = sti("map.lua")

-- Prepare physics world with horizontal and vertical gravity
world = love.physics.newWorld(0, 0)

-- Prepare collision objects
map:box2d_init(world)

-- Create a Custom Layer

-- Add data to Custom Layer
local spriteLayer = map.layers["Sprite Layer"]
spriteLayer.sprites = {
player = {
image = love.graphics.newImage("assets/sprite.png"),
x = 64,
y = 64,
r = 0,
}
}

-- Update callback for Custom Layer
function spriteLayer:update(dt)
for _, sprite in pairs(self.sprites) do
sprite.r = sprite.r + math.rad(90 * dt)
end
end

-- Draw callback for Custom Layer
function spriteLayer:draw()
for _, sprite in pairs(self.sprites) do
local x = math.floor(sprite.x)
local y = math.floor(sprite.y)
local r = sprite.r
love.graphics.draw(sprite.image, x, y, r)
end
end
end

function love.update(dt)
map:update(dt)
end

function love.draw()
-- Draw the map and all objects within
love.graphics.setColor(255, 255, 255)
map:draw()

-- Draw Collision Map (useful for debugging)
love.graphics.setColor(255, 0, 0)
map:box2d_draw()

-- Please note that map:draw, map:box2d_draw, and map:bump_draw take
-- translate and scale arguments (tx, ty, sx, sy) for when you want to
-- grow, shrink, or reposition your map on screen.
end
ⵜⴰⵎⴰⵣⵉⵖⵜ(https://en.wikipedia.org/wiki/Berbers)

FrenchMasterSword
Prole
Posts: 3
Joined: Sat Jan 20, 2018 4:27 pm

### Re: Simple Tiled Implementation - STI v0.18.2.1

Before any other problem, I just can't get löve to display my map ; it tells in the console and in the window that the only tileset used (Atlas ) doesn't exists ; of course it exists at the given place. the path to the map being assets/maps/map.lua
If I change this path to "assets\\maps\\map.lua", it is now map.lua which doesn't exist, I get this error :
stack traceback:
[C]: in function 'newImage'
sti/utils.lua:197: in function 'fix_transparent_color'
sti/init.lua:105: in function 'init'
sti/init.lua:47: in function 'sti'
[string "boot.lua"]:440: in function <[string "boot.lua"]:436>
[C]: in function 'xpcall'
main.lua is alone with the "sti" file and "assets"
my code so far :

Code: Select all

-- Include Simple Tiled Implementation library
local sti = require "sti"
local tx, ty, sx, sy, map

map = sti("assets\\maps\\map.lua")
tx, ty = 0,0
sx, sy = 1.5, 1.5
end

function love.update(dt)
map:update(dt)
end

function love.draw()
map:draw(-tx, -ty, sx, sy)
end

EDIT: well it's just that with, the tmx map, the tilesets have to depend of main.lua.
Also Kairi, I see you often say to draw with -tx and -ty
I suspect it is because the tiles start at the bottom right corner ; but you know, when you start a new map on Tiled, you can change it to upper left !

Marty
Citizen
Posts: 89
Joined: Mon Dec 04, 2017 1:47 am
Location: Germany

### Re: Simple Tiled Implementation - STI v0.18.2.1

FrenchMasterSword wrote:
Sun Jan 21, 2018 10:59 am
Before any other problem, I just can't get löve to display my map ; it tells in the console and in the window that the only tileset used (Atlas ) doesn't exists ; of course it exists at the given place. the path to the map being assets/maps/map.lua
If I change this path to "assets\\maps\\map.lua", it is now map.lua which doesn't exist, I get this error :
stack traceback:
[C]: in function 'newImage'
sti/utils.lua:197: in function 'fix_transparent_color'
sti/init.lua:105: in function 'init'
sti/init.lua:47: in function 'sti'
[string "boot.lua"]:440: in function <[string "boot.lua"]:436>
[C]: in function 'xpcall'
main.lua is alone with the "sti" file and "assets"
my code so far :

Code: Select all

-- Include Simple Tiled Implementation library
local sti = require "sti"
local tx, ty, sx, sy, map

map = sti("assets\\maps\\map.lua")
tx, ty = 0,0
sx, sy = 1.5, 1.5
end

function love.update(dt)
map:update(dt)
end

function love.draw()
map:draw(-tx, -ty, sx, sy)
end

EDIT: well it's just that with, the tmx map, the tilesets have to depend of main.lua.
Also Kairi, I see you often say to draw with -tx and -ty
I suspect it is because the tiles start at the bottom right corner ; but you know, when you start a new map on Tiled, you can change it to upper left !
First of all, use / not \\ to point to your lua map file.
The reason why it cannot track your tileset file is, because the tile map editor stores the references relative to the lua map file, while LÖVE needs those relative to the root directory. I always wondered why Kairi never implemented a work around, so my work around is fixing those paths in the lua file with a post process including some regex. For now, you should change the paths by hand and you are good, I suppose.

───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░░░░░░░░█────
▄▄──█░░░▀█▀░░░█──▄▄
█░░█▀▄░░░░░░░▄▀█░░█

Karai17
Party member
Posts: 855
Joined: Sun Sep 02, 2012 10:46 pm

### Re: Simple Tiled Implementation - STI v0.18.2.1

I recommend creatiing your maps in your game directory so when it comes time to load them, all the files are already where they should be.
STI - An awesome Tiled library
LÖVE3D - A 3D library for LÖVE 0.10+

Dev Blog | GitHub | excessive ❤ moé

Marty
Citizen
Posts: 89
Joined: Mon Dec 04, 2017 1:47 am
Location: Germany

### Re: Simple Tiled Implementation - STI

I'm on the point where I want to include some collision to my map and character. I'm glad there are plugins for bump and box2d already. I don't want to work with box2d, because of its sometimes not expectable behaviours. Bump on the other hand is a little too less for me. What, if I have tiles that are half collidable? Having tiles being half collidable horizontally or vertically could be solved by decreasing the tile width and height. But I'm thinking on the case when you allow diagonal collisions. Bump is not capable of handling triangle shapes on the collisions.

The simplest way is to use HC and build a new plugin for STI that allows 50% diagonal collision tiles like in Zelda-LttP:

I think about besides the "collidable" property on the layer to have a collisionType property on each tile that defaults to the value "full" and should offer some additional values for various collision types like diagonal tiles:

It would also require orientation information, although Zelda-LttP used to store only 4 different collision types:
full, diagonal left top to right bottom, diagonal right top to left bottom and none.

I also could imagine providing a 2nd layer that acts as collision mask. the collision layer could point to a mask layer with a property maskLayer. And supporting even objects (with masks) would be superior even more.

My question is, anybody did something like this for STI already? Also what do you think about this idea, Karai? Would you be interested supporting a HC plugin for STI?

───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░░░░░░░░█────
▄▄──█░░░▀█▀░░░█──▄▄
█░░█▀▄░░░░░░░▄▀█░░█

Saoskia
Prole
Posts: 3
Joined: Tue Feb 13, 2018 7:15 am

### Re: Simple Tiled Implementation - STI v0.18.2.1

First post, yay

I'm having an issue with the box2d plugin.
I'm pretty sure I have everything set up the way it should be in both Tiled and my code (I followed the tutorial on lua.space), but the collisions don't seem to be working. The documentation tells me absolutely nothing, so here I am.

I've looked through my code, and I'm not entirely sure the player has been given a collider. I'll post the code below as well as a .love file.

Can someone tell me if/where the player has been given a collider, and how I can fix it if need be.

Also, I kept getting an error with box2d regarding line 264 of box2d.lua. It has to do with translating the map which I chose not to do, so I just edited it out and everything works fine. If someone could also tell me why I'm getting this error, that would be great too.

Code: Select all

-- Include Simple Tiled Integration into project
local sti = require "sti"

map = sti("maps/hi.lua", { "box2d" })

world = love.physics.newWorld(0, 0)

-- Create new dynamic data layer called "Sprites"

-- Get player spawn object
local player
for k, object in pairs(map.objects) do
if object.name == "Player" then
player = object
break
end
end

-- Create player object
local sprite = love.graphics.newImage("images/purple.png")
layer.player = {
sprite = sprite,
x      = player.x,
y      = player.y,
ox     = sprite:getWidth() / 2,
oy     = sprite:getHeight() / 2
}

layer.update = function(self, dt)

local speed = 200

-- Move player up
if love.keyboard.isDown("w") then
self.player.y = self.player.y - speed * dt
end

-- Move player down
if love.keyboard.isDown("s") then
self.player.y = self.player.y + speed * dt
end

-- Move player left
if love.keyboard.isDown("a") then
self.player.x = self.player.x - speed * dt
end

-- Move player right
if love.keyboard.isDown("d") then
self.player.x = self.player.x + speed * dt
end
end

-- Draw player
layer.draw = function(self)
love.graphics.draw(
self.player.sprite,
math.floor(self.player.x),
math.floor(self.player.y),
0, 1, 1,
self.player.ox,
self.player.oy
)

-- Temporarily draw a point at our location so we know
-- that our sprite is offset properly
love.graphics.setPointSize(5)
love.graphics.points(math.floor(self.player.x), math.floor(self.player.y))
end

-- Remove unneeded object layer
map:removeLayer("Player Spawn")

-- Box2D
map:box2d_init(world)
end

function love.update (dt)
-- Update world
map:update(dt)
end

function love.draw()
-- Draw world
map:draw()
map:box2d_draw(world, 0, 0, 0, 0)
end
TiledTest.love
Thanks

Karai17
Party member
Posts: 855
Joined: Sun Sep 02, 2012 10:46 pm

### Re: Simple Tiled Implementation - STI v0.18.2.1

Take a look at the demo file in the OP, there shoudl be some collision code in there to reference.
STI - An awesome Tiled library
LÖVE3D - A 3D library for LÖVE 0.10+

Dev Blog | GitHub | excessive ❤ moé

Karai17
Party member
Posts: 855
Joined: Sun Sep 02, 2012 10:46 pm

### Re: Simple Tiled Implementation - STI

modiX wrote:
Thu Jan 25, 2018 12:32 pm
I'm on the point where I want to include some collision to my map and character. I'm glad there are plugins for bump and box2d already. I don't want to work with box2d, because of its sometimes not expectable behaviours. Bump on the other hand is a little too less for me. What, if I have tiles that are half collidable? Having tiles being half collidable horizontally or vertically could be solved by decreasing the tile width and height. But I'm thinking on the case when you allow diagonal collisions. Bump is not capable of handling triangle shapes on the collisions.

The simplest way is to use HC and build a new plugin for STI that allows 50% diagonal collision tiles like in Zelda-LttP:

I think about besides the "collidable" property on the layer to have a collisionType property on each tile that defaults to the value "full" and should offer some additional values for various collision types like diagonal tiles:

It would also require orientation information, although Zelda-LttP used to store only 4 different collision types:
full, diagonal left top to right bottom, diagonal right top to left bottom and none.

I also could imagine providing a 2nd layer that acts as collision mask. the collision layer could point to a mask layer with a property maskLayer. And supporting even objects (with masks) would be superior even more.

My question is, anybody did something like this for STI already? Also what do you think about this idea, Karai? Would you be interested supporting a HC plugin for STI?
I had asked vrld if he wanted to make an HC plugin for STI but he was busy at the time and I also got busy too. I made the box2d plugin as a reference and the bump plugin was made by a third party. If you want to make an HC plugin, I'd be very happy to accept a pull request.
STI - An awesome Tiled library
LÖVE3D - A 3D library for LÖVE 0.10+

Dev Blog | GitHub | excessive ❤ moé

Saoskia
Prole
Posts: 3
Joined: Tue Feb 13, 2018 7:15 am

### Re: Simple Tiled Implementation - STI v0.18.2.1

I checked out the OP, and I managed to get a collider onto the player object, but it's not working properly.
The player itself (the image) can still cross over other colliders. The player's collider does its best to actually collide with the other colliders, but ultimately will follow the player. I've managed to record a gif to show what I mean.
ColliderFail.gif (185.65 KiB) Viewed 1356 times
How can I make sure the sprite image stops moving when the collider does?

Code: Select all

-- Include Simple Tiled Integration into project
local sti = require "sti"

map = sti("maps/hi.lua", { "box2d" })

-- Create world
world = love.physics.newWorld(0, 0)
map:box2d_init(world)

-- Create new dynamic data layer called "Sprites"

-- Get player spawn object
local player
for k, object in pairs(map.objects) do
if object.name == "Player" then
player = object
break
end
end

-- Create player object
local sprite = love.graphics.newImage("images/purple.png")
layer.player = {
sprite = sprite,
x      = player.x,
y      = player.y,
ox     = sprite:getWidth() / 2,
oy     = sprite:getHeight() / 2
}

-- Add physics to player object
layer.player.body = love.physics.newBody(world, layer.player.x, layer.player.y, "dynamic")
layer.player.body:setFixedRotation(true)
layer.player.shape = love.physics.newRectangleShape(sprite:getWidth(), sprite:getHeight())
layer.player.fixture = love.physics.newFixture(layer.player.body, layer.player.shape)

layer.update = function(self, dt)

local speed = 200

-- Move player up
if love.keyboard.isDown("w") then
self.player.y = self.player.y - speed * dt
end

-- Move player down
if love.keyboard.isDown("s") then
self.player.y = self.player.y + speed * dt
end

-- Move player left
if love.keyboard.isDown("a") then
self.player.x = self.player.x - speed * dt
end

-- Move player right
if love.keyboard.isDown("d") then
self.player.x = self.player.x + speed * dt
end

self.player.body:setX(self.player.x)
self.player.body:setY(self.player.y)
end

-- Draw player
layer.draw = function(self)
love.graphics.draw(
self.player.sprite,
math.floor(self.player.x),
math.floor(self.player.y),
0, 1, 1,
self.player.ox,
self.player.oy
)

love.graphics.polygon("line", self.player.body:getWorldPoints(self.player.shape:getPoints()))

-- Temporarily draw a point at our location so we know
-- that our sprite is offset properly
love.graphics.setPointSize(5)
love.graphics.points(math.floor(self.player.x), math.floor(self.player.y))
end

-- Remove unneeded object layer
map:removeLayer("Player Spawn")

end

function love.update (dt)
-- Update world
map:update(dt)
world:update(dt)
end

function love.draw()
-- Draw world
map:draw()
map:box2d_draw(world, 0, 0, 0, 0)
end
TiledTest.love