Closed eipporko closed 11 years ago
"When I call draw method from TileLayer:drawAfterTile() of more than one object of the same class, it only seems to draw the last one." :
obj:methodname(args)
is sugar for obj.methodname(obj,args)
, so If I want to get correct values for x and y coordinates of each object, I need to get it using self parameter within obj:draw()
method, but I can't, because I would need to pass obj reference in TileLayer:drawAfterTile()
.
Now if I try to use self parameter inside obj:draw()
method, I get "Error: *****: attempt to index local 'self' (a number value)" when it is called from TileLayer:drawAfterTile()
.
drawAfterTile is an old slow feature that I've neglected for a while. I really don't like it's current implementation so I'm working on a new one.
It sounds great, so in the meanwhile i'll try to do another stuff . Thanks!
TileLayer:drawAfterTile() has been replaced with TileLayer:setAfterTileFunction(). Now, instead of setting a function for every tile only one function is set per TileLayer that gets called every time a tile is drawn.
See TileLayer:setAfterTileFunction() for more information. Let me know if you need any more help.
Now works :),
You should edit the wiki documentation about this new method, because the function parsed should be of the form funct(tilePositionX, tilePositionY, tileDrawX, tileDrawY, ...)
, instead funct(layer, tilePositionX, tilePositionY, tileDrawX, tileDrawY, ...)
Finally I fix my problems using your new method and parsing it a function that check for a tile if there are any entity to be drawn
function Level:drawEntities(tilePositionX, tilePositionY, tileDrawX, tileDrawY, self)
local ent = {}
-- draw entities
for i,entity in ipairs(self.entities) do
ent.worldX, ent.worldY = self.map:toIso(entity.x,entity.y)
ent.tileX = math.floor(ent.worldX/self.map.tileHeight)
ent.tileY = math.floor(ent.worldY/self.map.tileHeight)
if tilePositionX==ent.tileX and tilePositionY==ent.tileY then
entity:draw()
end
end
end
But with a very large table, it becomes inefficient with too many checks by tile.
Any suggestion?
You could use a spatial hash to divide up your entities into buckets. The grid class that comes with ATL is perfect for this.
local Grid = require("AdvTiledLoader.Grid")
local buckets = Grid:new() -- The buckets to put entities into
local cellSize = 10 -- The number of tiles that a bucket represents
local floor = math.floor -- Localize the flooring function
-- Gets a bucket at the location
local cellX, cellY
function getBucket(buckets, tileX, tileY)
cellX, cellY = floor(tileX / cellSize), floor(tileY / cellSize)
if not buckets(cellX, cellY) then buckets:set(cellX, cellY, {}) end
return buckets(cellX, cellY)
end
-- Puts an entity into a bucket. If the entity has moved then provide the old tile location.
function putIntoBucket(buckets, entity, tileX, tileY, oldTileX, oldTileY)
oldTileX, oldTileY = oldTileX or 0, oldTileY or 0
getBucket(buckets, oldTileX, oldTileY)[ entity ] = nil
getBucket(buckets, tileX, tileY)[ entity ] = true
end
-- Clears the buckets
function clearBuckets(buckets)
buckets:clear()
end
-- Only check the buckets
function Level:drawEntities(tilePositionX, tilePositionY, tileDrawX, tileDrawY, self)
for ent,_ in pairs( getBucket(buckets, tilePositionX, tilePositionY) ) do
ent.worldX, ent.worldY = self.map:toIso(entity.x,entity.y)
ent.tileX = floor(ent.worldX/self.map.tileHeight)
ent.tileY = floor(ent.worldY/self.map.tileHeight)
if tilePositionX==ent.tileX and tilePositionY==ent.tileY then
entity:draw()
end
end
end
I didn't know about spacial hashing. I just tried this algorithm and it works really fine.
Yesterday, I was thinking about implementing a similar algorithm, using a 2-dimensional array but with an array cell for tile.
Thanks again.
Hi Kadoba,
I have an isometric map, and I want to draw my entities in such way that depending on their position in the map they are hidden by tiles or not (example: A Stone) . So, I use TileLayer:drawAfterTile(h, w, funct) method to get it.
I have one class named Level, who has one table named entities that contains objects like: player, mobs, bullets... And when I call Level:draw() method, I only have to make a for loop calling drawAfterTile() with all entities within the table.
But I have problems when:
Video example: https://vimeo.com/52391901
Source code related: