Render order with LOADANIM/DRAWANIM

Previous topic - Next topic

waroffice

Good morning,

I'm not sure if this is a bug or I am doing something wrong.

I have a tile map engine that has 4 layers and a player.

It renders them in this order.

Layer1
Layer2
Layer3
Player
Layer4

Only it is always showing the player on top of everything.

At first I thought it was the ID of the sprites so I loaded the same file again with a different ID and set that for layer 4 and it still renders the player last.

Some code and screenshots:

Code (glbasic) Select


LOADANIM "TILES.png",0,32,32  // 0 is the handle
LOADANIM "player.png",1,32,32 // 1 is the handle

FOR u = 0 TO w
FOR v = 0 TO h
IF (u+x_off<=map_data.width) AND (v+y_off<=map_data.height)
IF L1 THEN DRAWANIM 0,map[u+x_off][v+y_off].L1_tile,x+(u*tile_height),y+(v*tile_height)
IF L2 THEN DRAWANIM 0,map[u+x_off][v+y_off].L2_tile,x+(u*tile_height),y+(v*tile_height)
IF L3 THEN DRAWANIM 0,map[u+x_off][v+y_off].L3_tile,x+(u*tile_height),y+(v*tile_height)
DRAWANIM 1,7,(Player.X*tile_height)-(x_off*tile_height),(Player.Y*tile_height)-(y_off*tile_height) // Player
IF L4 THEN DRAWANIM 0,map[u+x_off][v+y_off].L4_tile,x+(u*tile_height),y+(v*tile_height)
ENDIF
NEXT
NEXT



I turned off rendering the first 3 layers for this shot



I then made the changes as below and got this (with the layers all intact)

Code (glbasic) Select


LOADANIM "TILES.png",0,32,32  // 0 is the handle
LOADANIM "player.png",1,32,32 // 1 is the handle
LOADANIM "TILES.png",2,32,32  // 2 is the handle

FOR u = 0 TO w
FOR v = 0 TO h
IF (u+x_off<=map_data.width) AND (v+y_off<=map_data.height)
IF L1 THEN DRAWANIM 0,map[u+x_off][v+y_off].L1_tile,x+(u*tile_height),y+(v*tile_height)
IF L2 THEN DRAWANIM 0,map[u+x_off][v+y_off].L2_tile,x+(u*tile_height),y+(v*tile_height)
IF L3 THEN DRAWANIM 0,map[u+x_off][v+y_off].L3_tile,x+(u*tile_height),y+(v*tile_height)
DRAWANIM 1,7,(Player.X*tile_height)-(x_off*tile_height),(Player.Y*tile_height)-(y_off*tile_height) // Player
IF L4 THEN DRAWANIM 2,map[u+x_off][v+y_off].L4_tile,x+(u*tile_height),y+(v*tile_height)  // Additional tile set
ENDIF
NEXT
NEXT




fuzzy70

Not being at home at the moment I cannot test but without seeing more code, especially the contents of the L4 array along with what is being used to make L4 true.

As a test I would remove the IF part of the IF L4 & draw that directly (same as you draw the player). If it then draws over the player like it should then there is some error in the logic used to plot or how you are setting the L4 variable.

I would also be tempted to make the player its own layer like L4 then change the foreground layer up one to L5.

Another thing I would do is split off the plotting code to a separate function as judging by the code the player is getting drawn every time
Code (glbasic) Select
IF (u+x_off<=map_data.width) AND (v+y_off<=map_data.height) equals true, which means it is getting drawn a lot when it only needs to be drawn once.

Sorry I couldn't be more help at the moment.

Lee
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

waroffice

I will clarify the L4 variable.  Its just toggled with a key press so I can turn on or off each layer.

I added that in after reaslising it was drawing the player on top.


ah thats it.

its drawing the player ever iteration.

I need to only draw the player once like you say

Would looping through the map twice be bad?

EG:

Code (glbasic) Select

FOR u = 0 TO w
FOR v = 0 TO h
IF (u+x_off<=map_data.width) AND (v+y_off<=map_data.height)
IF L1 THEN DRAWANIM 0,map[u+x_off][v+y_off].L1_tile,x+(u*tile_height),y+(v*tile_height)
IF L2 THEN DRAWANIM 0,map[u+x_off][v+y_off].L2_tile,x+(u*tile_height),y+(v*tile_height)
IF L3 THEN DRAWANIM 0,map[u+x_off][v+y_off].L3_tile,x+(u*tile_height),y+(v*tile_height)
ENDIF
NEXT
NEXT

DRAWANIM 1,7,(Player.X*tile_height)-(x_off*tile_height),(Player.Y*tile_height)-(y_off*tile_height) // Player

IF L4
    FOR u = 0 TO w
FOR v = 0 TO h
IF (u+x_off<=map_data.width) AND (v+y_off<=map_data.height)
                    DRAWANIM 0,map[u+x_off][v+y_off].L4_tile,x+(u*tile_height),y+(v*tile_height)
                ENDIF
        NEXT
    NEXT
ENDIF

fuzzy70

It works but not really an elegent or efficient way of doing it. One solution is like I said in breaking it out into a Function eg
Code (glbasic) Select

draw_layer(1)
draw_layer(2)
draw_layer(3)
DRAWANIM 1,7,(Player.X*tile_height)-(x_off*tile_height),(Player.Y*tile_height)-(y_off*tile_height) // Player
draw_layer(4)

FUNCTION draw_layer: layerid
FOR u = 0 TO w
FOR v = 0 TO h
IF (u+x_off<=map_data.width) AND (v+y_off<=map_data.height)
Drawlayer layerid
ENDIF
NEXT
NEXT
ENDFUNCTION


Above is just a rough example, am pretty sure you can pass types to functions, a search of the forum should find out how. I tend to wrap my plotting functions into the type if it is used purely for that task.

Lee
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

MrTAToad

There is no rendering order as such in GLBasic - sprites are rendered only in the order that you use a sprite command.

Its quite possible that one or more graphics aren't being loaded or a sprite ID is being reused when it shouldn't be.


fuzzy70

"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

dreamerman

Everything fine with GLB, you just made simple mistake in code ;-)
As mentioned above, you are drawing player character every iteration so, in shorts:
tile 1x1 -> draw layer, draw player on his position, draw layer
tile 2x1 -> draw layer, draw player on his position (even if he's not on that tile), draw layer
so player char always will be on top..
Correctly it shoul be made like in your second post or as fuzzy70 written.
You can also easily optimize your code a little, just store 'u+x_off' and other similar in some variables for each iteration.
Code (glbasic) Select
FOR u = 0 TO w
FOR v = 0 TO h
cu = u+x_off; cv = v+y_off
IF (cu<=map_data.width) AND (cv<=map_data.height)
cx = x+(u*tile_height); cy = y+(v*tile_height)
IF L1 THEN DRAWANIM 0,map[cu][cv].L1_tile,cx,cy
IF L2 THEN DRAWANIM 0,map[cu][cv].L2_tile,cx,cy
IF L3 THEN DRAWANIM 0,map[cu][cv].L3_tile,cx,cy
ENDIF
NEXT
NEXT
Check my source code editor for GLBasic - link Update: 20.04.2020

waroffice

Thanks dreamerman and fuzzy70,

I will read that tutorial when I get time, I'm at work now, but I do understand my mistake.

Thanks for looking