## Simple Tiled Implementation - STI v1.2.3.0

Barnacle_Ed
Prole
Posts: 2
Joined: Mon Jun 01, 2020 1:45 am

### Re: Simple Tiled Implementation - STI v1.2.3.0

Hi everyone, like dashbandith I'm also new to love and STI but I'm also having an issue with the basic tutorial's code. My map file is drawn properly but, for some reason, my Player object isn't getting drawn in the map and I can't figure out why even after poking around a bit with the inspect.lua library. My best guess is that I've done something wrong with the layer.draw callback function. Here's what I can say with certainty:
• My map has a Spawn Point layer with a Player object in it.
• I have a sprite.png image in the same directory as main.lua and it's being properly set to the sprite variable.
• My Sprites Layer is properly being assigned, is set to visible, and has the player property assigned correctly.
• I put a debug print statement in the layer.draw function, but it never seems to fire. My Spawn Point object layer also doesn't seem to appear even when I remove the map:removeLayer("Spawn Point") line.

Any help would be greatly appreciated here. Full contents of my main.lua below.

Code: Select all

local sti = require "lib.sti.sti"
local inspect = require "inspect"

map = sti("magecity.lua")
-- Create new dynamic data layer called "Sprites" as the 8th layer
-- Get player spawn object
local player
for k, object in pairs(map.objects) do
if object.name == "Player" then
player = object
break
end
end
print("\nPlayer\n")
print(inspect(player))

-- Create player object
local sprite = love.graphics.newImage("sprite.png")
layer.player = {
sprite = sprite,
x = player.x,
y = player.y,
ox = sprite:getWidth() / 2,
oy = sprite:getHeight() / 1.35
}
print("\nLayer\n")
print(inspect(layer))
-- 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
)
print("Drawing Sprites layer!")
-- 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("Spawn Point")
end

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

function love.draw()
-- Draw world
map:draw()
end

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

### Re: Simple Tiled Implementation - STI v1.2.3.0

Code: Select all

local layer = map:addCustomLayer("Sprites", 8)
This line seems to trip people up fair bit, I may adjust how this works. But for now, that 8 is the index number you are assigning to the layer. In STI, layers are given both a name and an index. The index is used for draw order, and the name is used for easier lookups.

The way that Lua tables work means that the "length" of a table, and also the built-in ipairs iterator, they will start counting a table's indices from 1 until it reaches a gap. So if you have a table with indices 1, 2, 3, and 5, then the length of the table (and the number of times ipairs will iterate) will be 3, since it can't find #4 and gives up immediately.

So chances are, your map has several layers, but not 8. So it's giving up before that layer.

Code: Select all

print(#map.layers)
If you use the above code, you can see how many layers you have, and change that 8 to 1 higher than what the print offers. Alternative, instead of writing in an exact index number, if you want the new layer to be on top of all other layers, you can do the following:

Code: Select all

local layer = map:addCustomLayer("Sprites", #map.layers + 1)
STI - An awesome Tiled library
LÖVE3D - A 3D library for LÖVE 0.10+

Dev Blog | GitHub | excessive ❤ moé
pgimeno
Party member
Posts: 2596
Joined: Sun Oct 18, 2015 2:58 pm

### Re: Simple Tiled Implementation - STI v1.2.3.0

Karai17 wrote: Mon Jun 01, 2020 6:08 am

Code: Select all

print(#map.layers)
If you use the above code, you can see how many layers you have, and change that 8 to 1 higher than what the print offers.
Unfortunately that isn't guaranteed to work. The only method that works is ipairs. For example:

Code: Select all

local t = {1, 2, 3, 4, [6]=6}
local n
for i in ipairs(t) do
n = i
end
print(#t, n)

prints 6, 4 with LuaJIT and 4, 4 with PUC Lua. ipairs will always stop at the first absent element.
Barnacle_Ed
Prole
Posts: 2
Joined: Mon Jun 01, 2020 1:45 am

### Re: Simple Tiled Implementation - STI v1.2.3.0

Ahhh I didn't realize that the second argument to map:addCustomLayer was the number of layers. I only have a single layer in my map since I hacked it together in an impatient hurry, so that would do it!

For today I'll hardcode a 1 instead of an 8, but I'll poke around with to find a more programmatic solution after getting the player sprite printed.

EDIT #1: OK we're getting closer. The layer.draw callback is firing but I'm still not seeing the sprite on my screen. Maybe it's getting drawn off-screen somehow. I'll investigate.

EDIT #2: I realized it's because the sprite needs to be the topmost layer and I have the tiles as layer 1, so this did the trick (for now)

Code: Select all

local layer = map:addCustomLayer("Sprites", 2)
For me, #map.layers printed out "2" to terminal, but a basic operator apparently having nondeterministic output is...pretty shocking to say the least. Since map.layers is an array with deterministic length I think it should be fine to use #map.layers here right?
dashbandith
Prole
Posts: 2
Joined: Tue May 26, 2020 5:21 am

### Re: Simple Tiled Implementation - STI v1.2.3.0

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

### Re: Simple Tiled Implementation - STI v1.2.3.0

Barnacle_Ed wrote: Mon Jun 01, 2020 4:35 pm For me, #map.layers printed out "2" to terminal, but a basic operator apparently having nondeterministic output is...pretty shocking to say the least. Since map.layers is an array with deterministic length I think it should be fine to use #map.layers here right?
It is deterministic, just a bit unintuitive. The confusion here is that tables in Lua act as both arrays and hashmaps. When you are using them as an array, the # operator works as expected: You get the number of values with sequential keys beginning from 1 until there is a gap. However, # does nothing for non-sequential data. The way I have the layers set up in the layers table, is that the layers are keyed both with a sequential layer number (this allows drawing to be deterministic and faster to iterate through), and with the layer's name as the key for easier programatic access.

So for example, if you insert a new layer as index 3 into the layers and give it the name "Sprites", then you can access that same layer both via map.layers[3] or map.layers["Sprites"].
I'm not the best at writing tutorials ; If anyone wants to update the tutorial or add new tutorials, I'd happily accept PRs.
STI - An awesome Tiled library
LÖVE3D - A 3D library for LÖVE 0.10+

Dev Blog | GitHub | excessive ❤ moé
MistyM
Prole
Posts: 6
Joined: Sun Aug 25, 2019 11:49 am

### Re: Simple Tiled Implementation - STI v1.2.3.0

Hi,

I have a question kind of related to the previous one. So I've done
local playerLayer = map:addCustomLayer("PlayerSprite",#map.layers + 1)
to add a custom player sprite on top of my map but the sprite is still being drawn behind the map layers (i can see it jump out from behind when I got beyond where the map is drawn).
If I print the #map.layers before and after adding the playerLayer it prints 6 and 7 (respectively) so this shows the player layer is being added after the map layers.
Any ideas as to why this might be happening?

EDIT: I figured out my issue. A very stupid one! I'd just been drawing the player before the map in the draw function.
Taycamgame
Prole
Posts: 4
Joined: Sun Jun 14, 2020 5:54 pm

### Re: Simple Tiled Implementation - STI v1.2.3.0

Currently trying to learn STI. I've got a very basic map (just a prototype that will be changed, i'm just trying to implement a map system)
So far I have this code:

Code: Select all

-- Require Simple Tiled Implementation (STI) which allows for easy use of tiled maps
local sti = require("sti")

map = sti("grasslandMap.lua")
end

function love.update(dt)
-- Update map (on every frame)
map:update(dt)
end

function love.draw()
-- Draw the map to the screen
map:draw()
end
However it is throwing the following error:

Code: Select all

Error
areas/grasslandCode.lua:11: attempt to index global 'map' (a nil value)
I copied this from the tutorial https://github.com/karai17/Simple-Tiled ... -to-sti.md
The only thing I changed was the filename of the map i need to use (and barely changing the comments).

Not sure if it matters but the map I created contains a few layers, nothing too complex. It also isn't a single screen (the tutorial used a single screen map), however I don't think it's that since it's just saying that map is nil. Thoughts?
Karai17
Party member
Posts: 909
Joined: Sun Sep 02, 2012 10:46 pm

### Re: Simple Tiled Implementation - STI v1.2.3.0

Are you sure you are using the correct relative path for the map file? For example, may it be in a folder and not on the root of the game's directory?
STI - An awesome Tiled library
LÖVE3D - A 3D library for LÖVE 0.10+

Dev Blog | GitHub | excessive ❤ moé
Taycamgame
Prole
Posts: 4
Joined: Sun Jun 14, 2020 5:54 pm

### Re: Simple Tiled Implementation - STI v1.2.3.0

Karai17 wrote: Sat Aug 22, 2020 1:54 am Are you sure you are using the correct relative path for the map file? For example, may it be in a folder and not on the root of the game's directory?
I got that part sorted - I'm currently in the process of adding collision to the tiles on my map.
I'm attempting to use box2D and I have the following in mapRenderer.lua:
https://pastebin.com/V2jcHQKY

This isn't giving any collision to the tiles though. I did go into Tiled and add Collision Shapes to my tileset (not all tiles, only the ones i had used so far) but this also didn't magically give collision (kinda anticipated that tbf).

Is there something else I need to do to enable collision? The code that I linked is what handles my map stuff (rendering the map, allowing player to move). Is there something I've missed out?

Thanks!

### Who is online

Users browsing this forum: Bing [Bot] and 20 guests