I would like to draw a map consisting of a limited set of tiles in different zoom levels, just like google maps for instance. The reason why I consider using tiles is because the map is very large and in the highest magnification the whole map is very large (about 15000 to 20000 pixels).
Now I thought about creating a quadtree to organize the tiles. Each time a frame is drawn, the quadtree logic would evaluate which tiles to render, so that the rendering time is minimal.
However, how would I organize the map tile objects itself? When would I best load the tiles?
Creating a sprite for each tile seems to be overkill, as the dimensions of the tiles and position remains static. A SpriteCache doesn't seem to help in this case, as I am only drawing a subset of the map each frame.
Also, there are quite a few pros and cons in several cases:
When I would load all tiles when launching the application, then it would take a long time to load all of them and cache them in the GPU (Not even considered that all the tiles would fit in the memory).
When I would load the necessary tiles on runtime, I suppose to experience kind of a lag when tiles are being rendered.
Is there a "best practice" for a case like this?
I know there is not a right or a wrong answer to this, but I would like to hear other suggestions to solving this problem.
Thanks!!!!
'how would I organize the map tile objects itself?':
a) You could group tiles into Areas;
b) Then your viewer/camera draws only Areas in view (like frustrum culling, but not for each tile, because it's too expensive to ask each tile if it is on view);
c) Each drawn Area draws its Tiles on correct position (relatively to Area.position).
Here question about 'When would I best load the tiles?' could be solved with answer:
- the best approach is to load sprites before draw call AND only for Area.Tiles on view;
- load sprites from pool.
I tested such approach on Map 1000 x 1000 tiles,
where my Viewer (active tiles) was 3 x 3 Area (90 x 90 tiles). And with such approach it doesn't matter for performance how big is map (while you computer have memory:) ), only viewer size matters...
If viewer could have bigger dimension - then you could pre-render whole Area.Tiles to texture and draw directly one Area.texture for each visible Area on each frame.
Textures should be loaded initially when app starts.
Textures could be linked to tiles when Viewer created and when it moves one area up/down/left/right.
for (Area area : Viewer.areas) {
for (Tile tile : area.tiles) {
tile.texture = <loaded_texture> OR tile.image = new Libgdx.Image(<loaded_texture>) OR any other appropriate for your tile object way
}
}
Related
Situation: I am programming a 2D isometric styled Java game with libGDX.
Right now I have a moveable player that properly collides with tiles of solid objects.
Problem:
Now it comes to the renderorder of tiles. By default the library code renders from the bottom maplayer to the top layer. (Ground is layer 0, object layer is layer 1) Which makes sense. I draw the player on top of that. This means that the player is always on top of everything which doesn't make sense in some situations.
Goal: Since an isometric look means to have a kind of a 3D perspective, the player can be behind or in front of objects. So I have to come up with some code that decides whether the player is rendered behind or in front of it. I have this fridge as an example:
I hope it is comprehensible what I mean with "logical collision". I have some glimpses of ideas how to achieve that but that would be a mess in the code. So I wanted to ask if anyone has experiences with that or can hand me some nice sources that can help me.
Thanks for reading!
It depends HOW you render. One thing that comes to mind, is to render objects/tiles from up to down and left to right, that way in most cases the objects should always be in correct layer. Now depending on how you make the graphics, there could be flaws in this. If so, you could also have few layers of of priority, to draw different parts of objects/tiles, or draw something before other. If you also have tiles and objects as separate type, you could have objects ability to draw before and after the tiles, to fulfill different needs. You could also implement some tiles to have objects, for cases like this, however that could also be waste of processor times comparing to other methods I mentioned.
How you would go about comparing object positions to tile positions is not actually very difficult. Probably a sufficient method would be comparing tile positions to object positions. Lets take a hypothetical situation, where you have tiles that are 32 x 32 in size, and there is object at 25 x 18. The object would be in front of tiles at offset 0 x 0 and 1 x 0, but behind 0 x 1 and 1 x 1 (If we imagine the tiles start from upper corner). Therefore, we first draw tiles at 0 x 0, and 1 x 0, then object, then tiles at 0 x 1 and 1 x 1. It should naturally fall in it's correct place, with fairly simple code logic.
Hope you got some ideas about how to implement it :)
Professional isometric styled games are actually 3D based with an orthographic camera. This way you dont have the complex problem of 2D sprite sorting in an isometric context and can rely on the hardware pixel-based z-Buffering.
Nevertheless, if you want to realize an isometric game without the comfort of a 3d-game engine, like in Java 2D, the approach of different sorted layers doesn't work. Same with the painter-algorithm, cause both are actually intended for pure 2D top-down view based games.
So how to cope with this dilemma?
Well an approach would be to imitate the Z-Buffering technique on a higher granular level, i.e. instead of considering each single pixel of each object in the scene, you consider tiles as a sorting base.
Like z-Buffering, pixels/tiles are rendered in the order of their individual distance to the camera:
The distance-formula of a tile-based object with coordinates (x, y, z) is proportional to:
d=y-x-z
Negative values are allowed, so d(A)=-1 as distance of an object A is closer to the camera and will be hence rendered after object B with distance d(B) = 1 which is farther away ...
The render steps for each render-cycle would therefore be:
Determine all objects which are visible (we don't wanna render all objects in a huge world, if we only see a small part of it)
Calculate the individual distances of each tile-based object in the scene with the given formula
Sort all visible objects by distance
Render all visible objects in descending order
I myself tested this strategy in JavaFX 2D and the result looks like this, i.e. it is a simple working technique for tile-based isometric rendering:
What is the best way to get around the max texture size in Libgdx? I currently have a 2048x2048 texture with an ortho cam zoomed in at 2x which serves as the "map" for my top down shooter. The problem is that 2048x2048 just isn't enough space for the player to move around in, so I need to expand the map without creating a huge texture. Am I going about this wrong? should I not just use a giant texture for the background?
Only some phones will support textures bigger than 2048x2048. This is a GPU hardware/OpenGL driver limitation and not the fault of LibGDX.
The most common solution is to build a map out of several smaller textures that can be repeated to create the illusion of a giant map. You don't just take the map of the world and divide it into 2048x2048 chunks, you instead have a bunch of tiles that are 32x32 pixels and represent things like grass, dirt, grass meeting dirt, etc.
This is why LibGDX has a maps package. See https://github.com/libgdx/libgdx/wiki/Tile-maps
Instead of trying to create the map programmatically you record the map in a text file and use a map loader at runtime. There are a couple of supported map formats. The best way to create the map files is to use a map editor like http://www.mapeditor.org/
I am developing a game using libgdx. Now i'd like to have a Background all over my map (Map size is not fixed yet i'll decide later). My map is tile based but i don't use TiledMaps. So i create and load the map with own code/editor.
My question now: How should i implement the background thing?
I thought about different ways:
Loading a huge Image, which covers all the map. This is not realy good cause i render things, which are not in my viewport (80 Tiles X,50 Tiles Y).
Deviding the Image in 4 or more Images and loading the one in the viewport. The Problem: At some point maybe part of all Images is in viewport so all Images are sent to GPU right?
Having 1 Image which cover the viewport (80,50) and follows the camera. Best performance i think, but it will look stupid...
Or every tile has an own Image and the Objects are drawn above them. Notice that i only render Tiles inside the viewport. But on Gamestart it would need to load Information about every tile in the level.
For Information: My Game is Topdown and the Background Shows the floor so no detailed hills etc are needed, just maybe some simple desert sand look and things like that. Is there another even better way?
What would be the best way for performance and optic?
If your game is Tile Based. It would make much more sense to have the background tiled aswell. Just use another layer for it. If your editor/loader does not support multiple layers, then I would recommend you to switch to another one, or add those features to it (if possible).
The Background Shows the floor so no detailed hills etc are needed, just maybe some simple desert sand look and things like that.
It is very easy to reuse tiles in something like a desert, because all their tiles are very similar (sand).
I'm making a map editor for my 2d tile based RPG game, and I'm running into a roadblock. The problem is actually how to draw the grid lines efficiently for very large maps like, say 300x300 tiles.
Originally I called redrew the entire grid panel every time you moved the mouse or clicked(since it allows you to drag and also highlights the tile you are hovering over). This was horrible for large maps and was very slow.
So my solution was to create a bufferedImage for the grid of a specified size right when a new empty map was created, and redraw that image every time paint was called. This worked very well, except that for anything above 200x200ish java would run out of heap space in creating that bufferedImage. I can't really have a preloaded image because the user should be able to specify a new map to be any size. Also, I like the grid to be drawn over the tiles, otherwise the tiles cover up the lines and it looks messier. That means the grid has to be drawn again every time tiles are added right?
My question is, is there another way to draw a very large grid that will repaint each time you move the mouse?
The program Tiled can easily create maps of 1000x1000 or more, how is it done?? Thanks
EDIT:
I mean the actual grid LINES, not the grid content such as tiles. Right now when the grid is drawn it iterates through the 2D array and draws a line at every length of a tile.
EDIT:
I got it to work by painting only the visible portion of the screen. Turns out it's not that hard to find the coordinates of the view pane in a JScrollPane. :)
Ok so this is similair I guess to what im working on at the moment. I am currently writing a bit of simulation software with a 3D frontend in Ogre3D. I have a tile based map that can be easily 3000 x 3000 sometimes they may be even larger.
Now im not sure how you are going about drawing your grid, if you are just doing 2D/3D, but the main problem for me was how to apply different textures to each tile. If this isnt relevant then hopefully this may help anyway for future lol. The problem for me is that creating a seperate object for eacch tile is a no no, due to speed. If there are even 1024 x 1024 your looking at over 1 million tiles, each with attributes. This worked great on my first tests where I only had 10 x 10 maps but on larger maps it just ground to a halt.
What I am currently doing is rewriting it, the new approach is as follows. (You may be able to adapt this for what you are doing if it helps). The grid is now only 1 object, its a mesh in my case as im working in 3d. Each vertex holds a couple of values, one is the column and one is the row. I have a seperate texture which is the same size as my map, so for a map with 100 columns and 100 rows i create a texture 100 x 100 (this is created dynamically).
I then pass this texture and the vertices to my cg shader (this is where tyou may have to think of an equivalent way of doing things, but I think it should be doable). By looking up the colour at the pixel in this texture relating to the grid slot I want to texture I can find a colour value, these colour values relate to my texture atlas which holds all my possible textures for my map. All you then have to do is use that particular part of the texture atlas for that particular part of the mesh / grid.
I hope that makes some sort of sense, if not then id be happy to explain a bit more. I think even though im using CG shaders, you should be able to come up with an equivalent for non CG based stuff in java. The advantage of this is that you end up with one lookup texture, one object in memory and a buffer holding your vertices which is very quick for lookup.
Hope this helps.
I'm a bit stumped on an Android game I am developing, so maybe someone can help me. Don't bother suggesting AndEngine; I've made it this far on my own and I'd prefer to continue on this path if possible.
The game I'm working on is a simple platformer. Originally the levels were loaded as massive bitmaps, but a few out of memory errors made it obvious that I had to come up with a more efficient system. Now I'm parsing out .tmx files into a 2d array and using a method that creates a bitmap slightly bigger than the device's screen and fills it with the appropriate tiles.
The issue is that accessing this 2d array 1500 times (using 16x16 tiles) is very expensive, and I'm having trouble figuring out a way to not do that so much. Currently I'm having to redraw the image every time I pass over 16 pixels. Current ideas include using larger tiles (smaller array, still limits level size though), attempting to shift the contents of my bitmap and only load in the new row about to be displayed, or using a larger bitmap so that new images don't need to be loaded as often. Any suggestions?
Unless already done or impossible; consider separating the background from the foreground.
If you use a simple background (think Super Mario plain blue backgrounds) then you can most likely reuse those tiles/that bitmap/color/gradient much longer than the foreground elements.
This will also make your array/s contain lots of empty spaces where no foreground exists, meaning you could collapse the array and only store the parts containing tiles. Collapsing the arrays will come with the drawback that you will have to store a height attribute for the tiles to know where they are supposed to go.
(A background separate from the foreground also give the possibility of parallax-effects (background moving in different speed than foreground))
An example of how this changes your lookup:
Consider the game is being run on a 480x800 screen in landscape-mode.
This means 50*30 (1500) tiles to look up.
Every tile is saved in a 2d-array.
The current visible area looks like this:
A ground area, 4 tiles high.
A platform, 5 tiles high and 20 tiles wide, somewhere above the ground.
Another platform 3 tiles high and 5 tiles wide, also above ground.
A wall extending from the ground to the top of the screen, 5 tiles wide.
Removing the background tiles and collapsing the arrays we only have to look up the tiles:
Ground tiles: 50*4
Platform1 tiles: 5*20
Platform2 tiles: 3*5
Wall tiles: 26*5
Total lookups: 50*4 + 5*20 + 3*5 + 26*5 = 445 which is less than a third of the original 1500.
Now, of course there is some extra work to be done to figure out the position of each tile and drawing the background, but assuming a badly optimized case where this takes as much time as the lookup it is still less time than 1000 lookups.
Of course, this is just one of possibly many approaches to the problem.
Also remember small things like that 2d arrays are much slower than 'flat' arrays. If you cannot put the data in a 1d-array, try to minimize the nested calls, e.g. get one row or column at a time and perform the lookups from that array before switching to the next:
//Really bad:
for(int x=0; x<array.length; x++){
for(int y=0; y<array[x].length; y++){
Object o = array[x][y];
}
}
//Better (can be made even better by using the for(Object o : array)-syntax):
for(int x=0; x<array.length; x++){
Object[] yArray = array[x];
for(int y=0; y<yArray.length; y++){
Object o = yArray[y];
}
}
I had to develop this project where we needed to download tiles of image from the web and display them as one whole image. The thing was a casual scroll would end up crashing the entire app because the VM would throw a OutOfMemory Exception. So I developed a view using a TwoDScrollView and MxN ImageViews, which downloaded only those views which were in the users view. As the user scrolls, we maintain a cache and start de allocating images that are "far" away from the viewing region. It was slower but it stopped crashing.
I won't be able to share my part of the code. But here's a Github repo that uses the same approach. Good Luck :)
I can't vouch for them but here's a project specifically fits your needs