Inspired by @slainte 's post, I wanted to code a simple isometric map renderer with height information.
This is my first try - feedback on tiles and general how to approach this stuff is very welcome.
Right now the height is bruteforced rendered by overlaying the tile sprites height times. This could be optimized by checking the surrounding height and not drawing the area that will be painted over anyway.
Feedback very welcome :)
That's looking nice :) Putting up a prototype like this is a lot of fun. Glad you got inspired by my post
This is how I am doing it right now...
if (h>0) then if (j<self.lv.height) h2=2*self.lv.tiles[i][j+1].z if (i<self.lv.width) h3=2*self.lv.tiles[i+1][j].z local px,py=0,y-h+5 local c1,c2=tiletype[2],tiletype[3] rectfill(ox+px,py,ox+7,h2>0 and y+10-h2 or y+5,c1) rectfill(ox+8,py,ox+15-px,h3>0 and y+10-h3 or y+5,c2) py=y+6 px+=1 while py<y+10 do if (py<y+10-h2) line(ox+px,py,ox+7,py,c1) if (py<y+16-h3) line(ox+8,py,ox+15-px,py,c2) px+=2 py+=1 end y-=h end |
Things I have tried before this and discarded...
- Blitting the tile "border" stacking up... toooo slow
- Blitting vertical lines... nice improvement but not good enough
- Blitting horizontal lines... better (H runs in contiguous memory help)
- Blitting horizontal lines with memset... bosted performance but was a pain to clip screen area and f*cked things more often than not
Potential improvements...
- blit only visible part at the top but I doubt the looping is gonna be better than this
- truly fix the memset approach in a way clipping works fine
- Calculate also +1,+1 to reduce the height to blit (like I do now, but considering front tile +1 can clip the current one, but that might generate different height clippings
- Go mad and calculate up to +N tiles in front that can potentially clip this tile and fully skip it (depends on max heights... now I work with MAXZ=10)
- don't blit a thing and post-process (shader style) all... probably the fastest but will be a killer in complexity
Yeah, I guess the biggest improvement would be to optimize drawing. Painters's algorithm is a problem here.
You could create a zmap when first drawing the map, and use this to check if you actually need to draw something.
If I increase my heigh data (just tried with height x 4) I am close to 100% cpu as well... this is kinda fun to tinker around with.
Seen my last comment in my post? with proper design I could take 60 FPS for a 20x20 map in the current implementation with some space for the game logic to not impact on this...
The Zmap is a good option also but moving around on maps that don't fit on screen might ruin the benefit and have strange performance hic-ups I guess
Ok, I was able to reduce the drawing of a column of sprites to two blits, 4 rects:
local tile=map_data[y][x] local height=height_data[y][x] --for z=0,height do local c1=sget(tile*8,5) local c2=sget(tile*8+14,5) z=height spr(tile, 56+x*8-y*8, 32+x*4+y*4, 2,2) rectfill( 64+x*8-y*8, 37+x*4+y*4, 71+x*8-y*8, 37+x*4+y*4-z*2, c2) rectfill( 64+x*8-y*8, 37+x*4+y*4, 67+x*8-y*8, 40+x*4+y*4, c2) rectfill( 56+x*8-y*8, 37+x*4+y*4, 63+x*8-y*8, 37+x*4+y*4-z*2, c1) rectfill( 59+x*8-y*8, 37+x*4+y*4, 63+x*8-y*8, 40+x*4+y*4, c1) spr(tile, 56+x*8-y*8, 32+x*4+y*4-z*2, 2,2) --end |
I basically draw the tile at ground level, then two rects per side on top of this and then the tile on top of it.
And of course, there was an off by one bug i the right side rect :) It's fixed locally here.
I might give that a try... will 4 line blits :) some improvement there for sure
Maybe the article about porting bumblebots will be of help here. It also features an isometric view with several speed optimizations.
[Please log in to post a comment]