Sign in to follow this  
Kefka Palazzo

Tileset rendering

Recommended Posts

Kefka Palazzo    100
Hello, everyone. I am making a (kinda) game engine, which uses a tileset (two of them per map) to render the background. The design is as follows: There's a Game_Map Object which holds the byte data for the map (loaded from file), and two Image objects containing tilesets, there is also other stuff, non-related to the drawing. The screen is 10x9 tiles wide (as on GBC), but the drawing is extended to 11x10 to allow smooth transition when moving the tilemap. The problem is that I use two for loops to draw each individual tile in place using ImageDraw() which copies the needed tile to the screen. This gets called 110 times (!), so I get only 6-7 fps, 8 on a good day. Now, I understand that this design plainly sucks, so I would like to ask, are there any other efficient ways to do that?

Share this post


Link to post
Share on other sites
Captain P    1092
What language and framework are you using? How big are those tiles? Can you show us the relevant code?

After all, drawing 110 relatively small sprites on modern systems shouldn't be that heavy, so there's likely something else going on.

Share this post


Link to post
Share on other sites
szecs    2990
My hardware can render 100x100 tiles (2 texture mapped quads rendered with blending on top of each other) with 20 fps.
Maybe you bind textures for every single tiles, that can slow things down.
You should batch tiles by texture ID, or bake everything in one atlas texture, so you don't have to bind, just once, or once per frame.

Share this post


Link to post
Share on other sites
Kefka Palazzo    100
I use VB.Net; tiles are 16x16 and packed in a tileset 128x1024 in size (that's 384 kB). Shrinking the tileset didn't help; and the problem seems to be the line where ImageDraw gets called, because removing it shoots the fps up 60 (rendering only the location message (map name which gets displayed in a box which floats away), which goes pretty damn smooth. As far as I understand objects, removing ImageDraw doesn't affect the Game_Map object holding the tilesets (2x128x1024), so... what could it possibly be? :confused:

Share this post


Link to post
Share on other sites
szecs    2990
Maybe you should render all the tiles first, then all the "location messages". (batch the different kinds of renderings)
And the 2 tilesets mean that you have to do some "switching" between the 2 sets per tile, am I right? I guess that switching slows things down.
Render the whole tile-map with the bottom tileset, then render the whole tile-map with the top tileset.

Share this post


Link to post
Share on other sites
Kefka Palazzo    100
Quote:
Original post by szecs
Maybe you should render all the tiles first, then all the "location messages". (batch the different kinds of renderings)
And the 2 tilesets mean that you have to do some "switching" between the 2 sets per tile, am I right? I guess that switching slows things down.
Render the whole tile-map with the bottom tileset, then render the whole tile-map with the top tileset.


Well, the location message gets drawn last, and removing it altogether changed nothing. Switching? Hurr... I tried removing the ifs, so the top tileset is used for rendering only, no luck.

Sub render (g as Graphics)
Dim mp As Map = Me.GameTemp.CurrentMap
Dim x As Integer = Me.GameTemp.X
Dim y As Integer = Me.GameTemp.Y
For ix As Integer = 0 To 12
For iy As Integer = 0 To 11
Dim tile As Integer = 0
tile = mp.GetTile(x - 5 + ix, y - 5 + iy)

Dim ex As Integer = Me.GameTemp.X * 16 - Me.GameTemp.TrueX
Dim ey As Integer = Me.GameTemp.Y * 16 - Me.GameTemp.TrueY

Dim rown As Integer = tile Mod 8
Dim row As Integer = Math.Floor(tile / 8)
Dim rtile As New Rectangle(rown * 16, row * 16, 16, 16)
'the next line is simply the stripped down "render tile" thing. Still 7 fps.
g.DrawImage(mp.Tiles1, ix * 16 + ex - 16, iy * 16 + ey - 16, rtile, GraphicsUnit.Pixel)

Next

Next
If Me.GameTemp.InfoTimer > 0 Then
'this draws the location message, commented out for clarity
' g.FillRectangle(New SolidBrush(GameTemp.WinColor), 8, GameTemp.InfoTimer - 28, 100, 28)
' g.DrawRectangle(New Pen(GameTemp.WinBorderColor), 8, GameTemp.InfoTimer - 28, 100, 28)
' g.DrawString(GameTemp.InfoText, New Font(GameTemp.FontName, GameTemp.FontSize, Fontstyle.Regular, GraphicsUnit.Pixel), New SolidBrush(GameTemp.FontColor), 16, GameTemp.InfoTimer - 24)

' Me.GameTemp.InfoTimer -= 1
End If
end sub

Share this post


Link to post
Share on other sites
Captain P    1092
From what I can find on this DrawImage function is that it's just rather slow. It looks like you're using code that's geared towards GUI-based, event-driven applications. That often doesn't work well for games. You may want to look for a library or framework that's geared towards real-time graphical applications. I'm not familiar with VB.NET so I can't give you any suggestions though.

But really, something that can't even draw 110 16x16 sprites with decent performance just isn't suited for this kind of application.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this