Author Topic: Variable sized tiles  (Read 13112 times)

linux_junkie

  • Newcomer
  • Posts: 28
  • Karma: +0/-0
    • View Profile
    • Email
Variable sized tiles
« on: November 08, 2010, 02:07:19 PM »
I'm working on a graphical roguelike, only using libtcod for utilities, like FoV and pathfinding.  My problem is, I have variable sized tiles, and I don't know where to even begin with implementing them.

Currently, I'm just using a vector containing all the tiles in the level, with their positions, and draw the ones that are in view.  The problem with this is the speed.  Scanning every tile is slow, and I have yet to find a better solution.

I feel like their must be some superior method, and it's probably an obvious one, but I'm clearly missing it.  What can I do to solve this problem?  I can't just resize the tiles, because they come from another tileset, and resizing them to fit the same area would cause graphical glitches and artifacts.  There *must* be a solution to this problem, and someone must have encountered this before.

corremn

  • Rogueliker
  • ***
  • Posts: 700
  • Karma: +0/-0
  • SewerJack Extraordinaire
    • View Profile
    • Demise RogueLike Games
Re: Variable sized tiles
« Reply #1 on: November 08, 2010, 11:30:58 PM »
Could you explain what you mean by scanning every tile?  What are you using to draw the tiles? SDL, OpenGl.  Does variable size tiles apply to terrain, does this still map to a x*y grid?

I would think that scanning through a vector on all tiles in a map should not be slow. Are you sure this is where you slowdown occurs?

(By your name I assume you are not using MSVC in debug build, which can be very slow with iterator checks.)
« Last Edit: November 08, 2010, 11:35:04 PM by corremn »
corremn's Roguelikes. To admit defeat is to blaspheme against the Emperor.  Warhammer 40000 the Roguelike

Ex

  • IRC Communications Delegate
  • Rogueliker
  • ***
  • Posts: 313
  • Karma: +0/-0
    • View Profile
Re: Variable sized tiles
« Reply #2 on: November 09, 2010, 03:27:13 AM »
You want to use a multidimensional array for holding the tiles on the map instead of a vector. Vectors are fairly slow, but arrays are very fast. You also shouldn't be storing the graphical data in the map tiles themselves. The map tiles should only say which graphic to draw in that particular location. The graphics should be stored preferably in a single dimensional array, but a vector would do fine too. Variable tile sizes involve loading in different graphics, and altering the spacing of these graphics in the display routine. The map itself won't be altered when using a different tile size, the only thing that will be changed is the array or vector that holds the graphics.

linux_junkie

  • Newcomer
  • Posts: 28
  • Karma: +0/-0
    • View Profile
    • Email
Re: Variable sized tiles
« Reply #3 on: November 09, 2010, 03:49:32 PM »
I suppose I should have clarified more.  The floor tiles are uniform in size, and aren't the problem.  The wall tiles, however, are of varying sizes, so they don't conform to a grid, hence multidimensional arrays are out of the question.

I'm using OpenGL for the rendering, on the Android platform, which isn't exactly the fastest system around.  The slowdown definitely occurs here, in the rendering loop.  Scanning hundreds of tiles many times a second is slow, and I need to keep my FPS up to make the game playable.

The graphical data is stored in textures, which are internally represented by integer values, so this isn't part of the problem.  I've considered using BSP trees, but it seems like overkill, and a bit messy for a 2D game.

I'm really unsure how to progress from here...

Z

  • Rogueliker
  • ***
  • Posts: 905
  • Karma: +0/-0
    • View Profile
    • Z's Roguelike Stuff
Re: Variable sized tiles
« Reply #4 on: November 09, 2010, 06:09:23 PM »
This is probably not what you need as it seems quite simple, but I don't understand your problem, so we can try. For the isometric view, you can just draw all your walls starting from the ones which are furthest from the point of view (i.e. top of the screen) and ending on those which are closest. This can be done easily by changing the sequence of walls generated by your FOR loops or whatever you use. This way you can be sure that a wall or monster which is closer never obscures one which is more distant. I don't think this would need optimizing... [OK, I am not sure whether you are even working in the isometric view, so this might be even less useful]

Maybe your problem is that you are working in OpenGL? This is designed for rendering 3D scenes and seems very strange for a 2D game. For each floor and wall and monster and item type, create a ready-to-use bitmap which can be directly copied without any modifications ("blitted") to the screen, and then just put these bitmaps at correct locations.

linux_junkie

  • Newcomer
  • Posts: 28
  • Karma: +0/-0
    • View Profile
    • Email
Re: Variable sized tiles
« Reply #5 on: November 09, 2010, 06:55:40 PM »
This is probably not what you need as it seems quite simple, but I don't understand your problem, so we can try. For the isometric view, you can just draw all your walls starting from the ones which are furthest from the point of view (i.e. top of the screen) and ending on those which are closest. This can be done easily by changing the sequence of walls generated by your FOR loops or whatever you use. This way you can be sure that a wall or monster which is closer never obscures one which is more distant. I don't think this would need optimizing... [OK, I am not sure whether you are even working in the isometric view, so this might be even less useful]

Maybe your problem is that you are working in OpenGL? This is designed for rendering 3D scenes and seems very strange for a 2D game. For each floor and wall and monster and item type, create a ready-to-use bitmap which can be directly copied without any modifications ("blitted") to the screen, and then just put these bitmaps at correct locations.

The game isn't isometric.  I'm using OpenGL out of necessity.  Since I'm working on the Android platform, I'm limited by memory, and I have a lot of graphics to load.  16MB on older models is the limit for an application.  However, with OpenGL, I can access the VRAM, which opens up nearly 256MB of memory.  Also, speed is a critical issue, since it's in realtime, and OpenGL is much faster than using the 2D rendering.  With OpenGL, I can load my tilesets as textures, and just directly blit the parts of the textures I need.

The Z-ordering issue I'm less concerned with, as I could find a solution for that.  However, because the wall tiles won't be contained in a grid, but rather will have direct pixel coordinates, I can't simply loop through a 2D array.  Instead, I'll have to loop through an array containing *all* wall tiles, and check to see whether or not they're in viewing range.  On any sizable map, this will take a while, when repeated dozens of times a second.

The easy solution would be to limit the map size, and just keep using the vector array system I'm using now, but I really don't want to restrict gameplay due to implementation problems.

Since I seem to be having trouble describing the problem properly, I'll give an indepth explanation:

So, I have a 2D array of floor tiles.  These can simply be for looped, no problem.  Wall tiles, however, don't conform to any sort of grid, since each wall tile has different dimensions.  Thus, it is necessary to specify direct pixel coordinates for each wall tile, as opposed to grid coordinates, like those used for the floor tiles.  So, whereas a floor tile might have coordinate (5, 7), which would correspond to pixel coordinates (32 * 5, 32 * 7), if the floor tiles were 32x32, a wall tile would have no grid coordinate, just a pixel coordinate, like (517, 892).

There's no way to align variable sized tiles to a grid.  Trying to do so would create overlap, visible seams, and other visual artifacts.  So right now, I have a big array containing the wall tiles, and scan each individual one, testing it to see if it falls within the camera's coordinates.  This is way too expensive.  I've been researching 3D methods of solving these problems, but most methods seem unnecessarily complex.

BSP trees, for example, is the typical 3D method of doing this, but that's usually used to speed up the processing of millions of polygons, as opposed to maybe a couple hundred of my wall tiles.  Due to the smaller set size, I'm unsure implementing the rather complex BSP trees would actually gain me a significant speed boost.

Quadtrees are also a consideration, but, again, seem awfully complex for a 2D application.

I'm really at a loss here, and am not up for the challenge of implementing these difficult data structures, just to possibly find out it was a waste of time.  I really need a solution for this damned problem, it's really doing my head in.

corremn

  • Rogueliker
  • ***
  • Posts: 700
  • Karma: +0/-0
  • SewerJack Extraordinaire
    • View Profile
    • Demise RogueLike Games
Re: Variable sized tiles
« Reply #6 on: November 09, 2010, 11:34:09 PM »
Hmm, maybe through a screen shot of what you are attempting.

I still thing you should look at attaching wall tiles to the grid.  You can still use variable size tiles just that they are attached to a certain grid square. (so a wall will have a grid x,y, and a pixel width and hieght and a texture offset x,y and maybe a grid-pixel offset so texture can be offset from the centre of the grid.   You might cut parts of the wall pixels off so they dont show in the unseen parts of the map.

Or you can break down the textures to the same size of the floor tiles. So one wall tile for instance may be made up of 4 32x32 parts and only render the visible parts.

Either way finding a way to attach the wall tiles to the grid will probably be the easiest and quickest method.  I really cant see how this will be hard, just a lot of simple maths, deciding on what needs to be seen, which depends entirely on the visible floor grid.

corremn's Roguelikes. To admit defeat is to blaspheme against the Emperor.  Warhammer 40000 the Roguelike

Ex

  • IRC Communications Delegate
  • Rogueliker
  • ***
  • Posts: 313
  • Karma: +0/-0
    • View Profile
Re: Variable sized tiles
« Reply #7 on: November 10, 2010, 01:19:24 AM »
You can still use a multidimensional array which is normally displayed as a grid. In each tile, simply store a per pixel offset. The wall graphics will be larger than a "normal" tile, but the per pixel offset stored in the tile will allow you position each graphic correctly. During display, add the offset to the graphic's normal position, which will give the correct display location. I've actually done this myself before.

For example, if you have a wall graphic which is 4 pixels higher than a normal tile, and 12 pixels longer, and you wanted the wall graphic to be centered on the tile, your offset would be -6,-2.
« Last Edit: November 10, 2010, 01:25:41 AM by Elig »

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: Variable sized tiles
« Reply #8 on: November 10, 2010, 06:36:02 AM »
Wall tiles, however, don't conform to any sort of grid, since each wall tile has different dimensions.

What was the reason to do that? I can't imagine why wall tiles should be variable sized in a tile based game. Looks like you have created your own problem and it didn't just happen.

Fenrir

  • Rogueliker
  • ***
  • Posts: 473
  • Karma: +1/-2
  • The Monstrous Wolf
    • View Profile
Re: Variable sized tiles
« Reply #9 on: November 10, 2010, 01:45:25 PM »
He said that the floor was comprised of tiles. He never said that player movement would be restricted to them, so I'm assuming that he doesn't mean to do that, as I agree that it wouldn't make sense. If memory serves, tiles are used for backgrounds in games that aren't what we would consider "tile-based". It's more reasonable to have a small tile repeated across the landscape than one huge texture.

linux_junkie

  • Newcomer
  • Posts: 28
  • Karma: +0/-0
    • View Profile
    • Email
Re: Variable sized tiles
« Reply #10 on: November 10, 2010, 06:24:21 PM »
You can still use a multidimensional array which is normally displayed as a grid. In each tile, simply store a per pixel offset. The wall graphics will be larger than a "normal" tile, but the per pixel offset stored in the tile will allow you position each graphic correctly. During display, add the offset to the graphic's normal position, which will give the correct display location. I've actually done this myself before.

For example, if you have a wall graphic which is 4 pixels higher than a normal tile, and 12 pixels longer, and you wanted the wall graphic to be centered on the tile, your offset would be -6,-2.

Wow.  I feel stupid now.  That's a simple, easy solution, and I can't believe it never occurred to me.  This is, after all, my first game that's not ASCII, so I still find there's a lot for me to learn.  Thank you very much.

linux_junkie

  • Newcomer
  • Posts: 28
  • Karma: +0/-0
    • View Profile
    • Email
Re: Variable sized tiles
« Reply #11 on: November 10, 2010, 06:28:26 PM »
He said that the floor was comprised of tiles. He never said that player movement would be restricted to them, so I'm assuming that he doesn't mean to do that, as I agree that it wouldn't make sense. If memory serves, tiles are used for backgrounds in games that aren't what we would consider "tile-based". It's more reasonable to have a small tile repeated across the landscape than one huge texture.

Exactly.  It uses tiles, but movement is pixel perfect, ala Diablo (or one of thousands of other games).  Indeed, tiles are far superior for backgrounds than one huge texture, especially since OpenGL has a limit to the size of a texture that can be loaded into memory (4048x4048, or something like that, I think).

Thanks again to everyone for their help.  Using the gridded system with offsets that Elig mentioned, I should be able to implement the rendering much, much easier, and much faster.

Unfortunately, collision detection will still be a challenge, and will require a quadtree to keep performance high.  I have no idea where to even start implementing a quadtree, having never used a tree structure before, at least, without just copying existing code.

Oh well.  Thanks again everyone, and wish me luck!

Z

  • Rogueliker
  • ***
  • Posts: 905
  • Karma: +0/-0
    • View Profile
    • Z's Roguelike Stuff
Re: Variable sized tiles
« Reply #12 on: November 10, 2010, 07:18:41 PM »
Exactly.  It uses tiles, but movement is pixel perfect, ala Diablo (or one of thousands of other games).

Diablo is grid-based, although it uses very good animations and non-discrete time system to hide this fact. (At least Diablo I, I am not sure about Diablo II.)