Simple Tiled Implementation - STI v1.2.3.0

Showcase your libraries, tools and other projects that help your fellow love users.
Barnacle_Ed
Prole
Posts: 2
Joined: Mon Jun 01, 2020 1:45 am

Re: Simple Tiled Implementation - STI v1.2.3.0

Post by Barnacle_Ed »

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"

function love.load()
  -- Load map file
  map = sti("magecity.lua")
  -- Create new dynamic data layer called "Sprites" as the 8th layer
  local layer = map:addCustomLayer("Sprites", 8)
  -- 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
User avatar
Karai17
Party member
Posts: 930
Joined: Sun Sep 02, 2012 10:46 pm

Re: Simple Tiled Implementation - STI v1.2.3.0

Post by Karai17 »

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é
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: Simple Tiled Implementation - STI v1.2.3.0

Post by pgimeno »

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

Post by Barnacle_Ed »

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

Post by dashbandith »

Hello Karai17, and thanks for the answer I gave myself the task of reading the tutorial more carefully and patiently. I already run your library is very good ... excuse me but your examples are not very clear for novice users, I could be of great help adding the download of the tutorial example to download, test and adapt it. Take it as a base and accompany the lines with comments.
User avatar
Karai17
Party member
Posts: 930
Joined: Sun Sep 02, 2012 10:46 pm

Re: Simple Tiled Implementation - STI v1.2.3.0

Post by Karai17 »

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"].
dashbandith wrote: Tue Jun 09, 2020 4:50 am Hello Karai17, and thanks for the answer I gave myself the task of reading the tutorial more carefully and patiently. I already run your library is very good ... excuse me but your examples are not very clear for novice users, I could be of great help adding the download of the tutorial example to download, test and adapt it. Take it as a base and accompany the lines with comments.
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

Post by MistyM »

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

Post by Taycamgame »

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")

function love.load()
    -- Load map file
    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?
User avatar
Karai17
Party member
Posts: 930
Joined: Sun Sep 02, 2012 10:46 pm

Re: Simple Tiled Implementation - STI v1.2.3.0

Post by Karai17 »

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

Post by Taycamgame »

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!
Post Reply

Who is online

Users browsing this forum: slime and 13 guests