This is the final bug of my little dress up game for FEMICOM gamejam.
I can't seem to get these images to draw in the right order! As this is a dress up game, order is very important. Socks should be under shoes, shirts should be over shorts and skirts. However, only one pair of socks goes under ALL of the shoes... the other two pairs only go under ONE pair of shoes.. they're on top of the rest. Same goes for the shorts and skirts and how they should be going under the shirts.
I've tried adding a z variable and ordering by that and even messing around with draw order, but this problem just won't be fixed! I just need a solution that won't break the dragging function because that was my problem last time.
It's much easier to see the problem if you open my file! Any help or tips is greatly appreciated.
Images displaying in the WRONG order
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Images displaying in the WRONG order
- Attachments
-
- Dress Up.love
- (4.81 MiB) Downloaded 89 times
- Jasoco
- Inner party member
- Posts: 3726
- Joined: Mon Jun 22, 2009 9:35 am
- Location: Pennsylvania, USA
- Contact:
Re: Images displaying in the WRONG order
Because you can only sort an indexed table where every row is a number. You can't sort a table where each row is a word or string.
Also you're just sorting by layer, which is just numbered in the order of the images being loaded.
When you iterate through a table using pairs, there is never really a predictable order that each item will be hit. They don't go in the order they were added to the table. So you'd need to use a numbered list.
What I do is add all the drawables to a "draw pool" table at the beginning of the game loop (First clear it completely) using a number and referring to each drawable you want to draw. Then sort that table by its "z".
It's complicated to explain quickly. And I've explained it before.
Here is where I originally explained it: viewtopic.php?p=72457#p72457
And here is a message I sent to another member when he asked about how to do it:
Also you're just sorting by layer, which is just numbered in the order of the images being loaded.
When you iterate through a table using pairs, there is never really a predictable order that each item will be hit. They don't go in the order they were added to the table. So you'd need to use a numbered list.
What I do is add all the drawables to a "draw pool" table at the beginning of the game loop (First clear it completely) using a number and referring to each drawable you want to draw. Then sort that table by its "z".
It's complicated to explain quickly. And I've explained it before.
Here is where I originally explained it: viewtopic.php?p=72457#p72457
And here is a message I sent to another member when he asked about how to do it:
It's just my method for doing it. It's not the defacto standard for doing it. Good luck.It's definitely near perfect. But it's not perfect. It's also very simple.
Basically I don't draw anything directly to the screen. I add each drawable's arguments to a numbered table and give it a type (Rectangle, polygon, image, circle, any other drawable) and a "distance from camera" value which ends up as the sort order.
I then sort this table by it's "distance" value.
And lastly, run through the table, check the type of object, and draw that object of that type using the arguments.
I kind of created a sort of library which I call "drawPool" which demonstrates what I mean. Here's the code to look at. Try putting it in a .lua and see if you can use it as is.
Code: Select all
--[[ 2014-2015 Jason Anderson This is a library I guess. Not really. It doesnt have a license because I dont know anything about licenses. I guess whatever license lets you use it as you wish. I dont claim to own any of this code as it's just code. I did write it myself, but it's nothing special. It also may not work as-is without other stuff or modification, but it probably will actually. Feel free to add your own "kinds" and delete code you want. Just I guess keep my name somewhere or whatever. I dunno. How to use: 1) Require the library in your main.lua as such: drawPool = require 'drawPool' Or you can load it at any time and as many times as you need like this: drawPool = love.filesystem.load("drawPool.lua")() This allows you to have as many pools as you need to and layer them separately. For instance, background layers and foreground layers. Example: drawPool = {} for i = 1, 3 do drawPool[i] = love.filesystem.load("drawPool.lua")() end As long as you run through the drawPool table for each :prepare() and :present() and you :push() the proper objects to the proper drawPool[#] then it'll work perfectly. 2) Call drawPool:prepare() at the beginning of your :update() function. No arguments are required. 3) Any time before presenting, use the drawPool:push() function to add objects to the pool. The arguments should be in the form of a table. Use the standard naming conventions like x or y or w or h (Not width or height, unless it's the text kind. (Note: I use "kind" instead of "type" to avoid conflicting with the type() function.) Sorry, it's inconsistent.) And use the layer argument to determine what the sort order is. Remember, pool objects with the same sort order may fight for priority due to how table.sort works. So I find it better to add a tiny random decimal amount to each object's layer to try and make sure they wont fight. Examples: drawPool:push { kind = "rect", x = 100, y = 100, w = 100, h = 100, color = {255,0,0}, layer = 100 } drawPool:push { kind = "circle", x = 200, y = 120, rad = 80, color = {0,0,255}, layer = 95 } drawPool:push { kind = "text", x = 50, y = 200, width = 300, align = "center", shadow = true, font = your_font, color = {255,255,255}, layer = 103 } drawPool:push { kind = "image", x = 80, y = 60, image = fluffyBunny, quad = bunnyQuad[1], rot = 0, sx = 1, sy = 1, iox = 0, ioy = 0, layer = -304.43 } Where sx/sy is Scale and iox/ioy is Image Offset. Quad is optional. Font is optional. Shadow is optional. setScissor is not really required in anything. I added it as a hack for my UI system but dont really think I need it now anyway. It's too hacky and clunky. It can probably be removed. Colorize requires a shader I made but isnt an important or needed part of the library. 4) In your :draw() function, call drawPool:present(), but only when you're ready to draw everything. Any :push() calls made after :present() will not happen. What happens is every frame, a table is emptied and stuff is added to it, sorted, then iterated through in order to determine what to draw in what order. This lets you basically "draw" any object at any time without worrying whether it's going to be drawn in front of or behind another object. As long as it gets a proper "layer" it'll draw at the right time. You can set layers to really high amounts for certain things (Like UI) and lower amounts for others (Game stuff) for example. Also note, this method can create a lot of garbage if used too much each frame. But it's usually not a problem. You can use this method to completely replace Löve's drawing frontend if you need to and push every single UI element into a pool if you really wanted to. You can use it for the game graphics or for the UI if you need to. I've used it for flat-shaded and textured polygonal 3D games myself. It was originally concieved for a 2D side-scrolling beat-em-up (Like TMNT) to make sure characters drew in the correct order. Something a lot of NES games in the day didnt bother to do. There is officially more text in this README than the entire library. ]] local lgr = love.graphics local v = ... or {} local drawPool = { name = v.name or "No Name" } function drawPool:prepare() self.pool = {} end function drawPool:push(v) if not v.layer then v.layer = 0 end if not v.color then v.color = {255,255,255} end if v.kind == "text" then if not v.font then v.font = font.tiny end elseif v.kind == "rect" or v.kind == "circle" then if not v.fill then v.fill = "fill" end if v.fill == "line" and not v.lineWidth then v.lineWidth = 1 end elseif v.kind == "line" then if not v.lineWidth then v.lineWidth = 1 end end self.pool[#self.pool+1] = v end function drawPool:present() -- print("Name:", self.name) table.sort(self.pool, function(a, b) -- print(a.layer, b.layer) return a.layer < b.layer end) for i = 1, #self.pool do local d = self.pool[i] if d.kind == "image" then if d.quad then lgr.draw(d.image, d.quad, d.x, d.y, d.rot or 0, d.sx or 1, d.sy or 1, d.iox or 0, d.ioy or 0) else lgr.draw(d.image, d.x, d.y, d.rot or 0, d.sx or 1, d.sy or 1, d.iox or 0, d.ioy or 0) end elseif d.kind == "rect" then if d.lineWidth then lgr.setLineWidth(d.lineWidth) end lgr.setColor(d.color) lgr.rectangle(d.fill, d.x, d.y, d.w, d.h) elseif d.kind == "line" then lgr.setLineStyle("rough") if d.lineWidth then lgr.setLineWidth(d.lineWidth) end lgr.setColor(d.color) lgr.line(d.points) elseif d.kind == "circle" then if d.lineWidth then lgr.setLineWidth(d.lineWidth) end lgr.setColor(d.color) lgr.circle(d.fill, d.x, d.y, d.rad, d.detail) elseif d.kind == "text" then local text = d.text or "" lgr.setFont(d.font) if d.width then if d.shadow then lgr.setColor(0,0,0) lgr.printf(text, d.x+1, d.y+1, d.width, d.align) end lgr.setColor(d.color) lgr.printf(text, d.x, d.y, d.width, d.align) else if d.shadow then lgr.setColor(0,0,0) lgr.print(text, d.x+1, d.y+1) end lgr.setColor(d.color) lgr.print(text, d.x, d.y) end end end end return drawPool
Re: Images displaying in the WRONG order
Which is why z have its uses even in 2D.
Who is online
Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 0 guests