2D Tiled Game Optimization in Java - java

I'm working on a 2d top down game in pure Java and until now I've got a noise mapping system that works with chunks of tiles (and entities) just like Minecraft.
The way I store tiles is by creating a int[s * s] array, where s is the size (in tiles) that a side of the chunk has. Then, I have a static array of Tiles which contains each of the possible tiles in the game, indexed with an integer. Those are the integers stored in the int[s * s] in each chunk. Now, I want to be able to overlay tiles, such as invisible spawn tiles, walls, trees and transition tiles (like when grass changes to sand: there should be a border of grass over the sand, which would be a new tile).
The problem is that only one integer can be stored in each coordinate of the chunk. Another way to do it would be to put actual instances of the tiles inside the chunks and make the overlaying tiles point to the ones directly below them (like a stack), but I think that's kind of a bad approach. Another approach which I tested was to make an array of Lists of tiles, that was also really bad.
Which would be a good way to accomplish this?

Typically you would separate the storage for tiles and objects.
You would have an int [w*h] or similar for the tiles themselves,
which would only allow one tile per square.
Separately, you could have a ArrayList [w*h] which stores a list of
entities in each square. This array would contain null for empty
squares, so the extra storage cost for the majority of squares (that
have no entities in them) is minimal.
There are other approaches of course, but this has the advantage that it is both simple and pretty efficient.
Only real downside is that you will have to write separate code for handling tiles and entities - but since you usually handle tiles and entities differently anyway then this is unlikely to be a big problem.

Related

Creating 2D Angled Top Down Terrain Instead of Fully Flat

Similar to the game Factorio im trying to create "3D" terrain but of course in 2D Factorio seems to do this very well, creating terrain that looks like this
Where you can see edges of terrain and its very clearly curved. In my own 2D game Ive been trying to think of how to do the same thing, but all the ways I can think of seem to be slow or CPU intensive. Currently my terrain looks like this:
Simply 2D quads textured and drawn on screen, each quad is 16x16 (except the water thats technically a background but its not important now), How could I even begin to change my terrain to look more like a Factorio or other "2.5D" games, do they simply use different textures and check where the tile would be relative to other tiles? Or do they take a different approach?
Thanks in advance for your help!
I am a Factorio dev but I have not done this, so I can only tell you what I know generally.
There is a basic way to do it and then there are optional improvements.
Either way you will need two things
Set of textures for every situation you want to handle
Set of rules "local topology -> texture"
So you have your 2d tile map, and you move a window across it and whenever it matches a pattern, you apply an appropriate texture.
You probably wouldn't want to do that on the run in every tick, but rather calculate it all when you generate the map (or map segment - Factorio generates new areas when needed).
I will be using your picture and my imba ms paint skills to demonstrate.
This is an example of such rule. Green is land, blue is water, grey is "I don't care".
In reality you will need a lot of such rules to cover all cases (100+ I believe).
In your case, this rule would apply at the two highlighted spots.
This is all you need to have a working generator.
There is one decision that you need to make here. As you can see, the shoreline runs inside the tile, not between tiles. So you need to chose whether it will run through the last land tile, or the last water tile. The picture can therefore be a result of these two maps (my template example would be from the left one):
Both choices are ok. In fact, Factorio switched from the "shoreline on land" on the left to the "shoreline on water" on the right quite recently. Just keep in mind that you will need to adjust the walking/pathfinding to account for this.
Now note that the two areas matched by the one pattern in the example look different. This can be a result of two possible improvements that make the result nicer.
First is that for one case you can have more different textures and pick a random one. You will need to keep that choice in the game save so that it looks the same after load.
Another one is more advanced. While the basic algorithm can already give you pretty good results, there are things it can't do.
You can use larger templates and larger textures that span over several tiles. That way you can draw larger compact pieces of the terrain without being limited by the fact that all the tiles need to be connectable to all (valid) others.
The example you provided are still 2D textures (technically). But since the textures themselves are 'fancy 3D', they appear to be 3D/2D angled.
So your best bet would be to upgrade your textures. (and add shadow to entities for extra depth).
Edit:
The edges you asked about are probably layed-out by checking if a 'tile' is an edge, and if so it adds an edge-texture on top the background. While the actual tile itself is also a flat image (just like the water). Add some shadow afterwards and the 3D illusion is complete.
I hope this answers your question, otherwise feel free to ask clarification.

How to implement a logical render order of isometric tiles?

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:

2-Dimensional Tile-Based Game: Each tile as an object impractical?

I've been trying various ways of creating a two-dimensional tile-based game for a few months now. I have always had each tile be a separate object of a 'Tile' class. The tile objects are stored in a two-dimensional array of objects. This has proven to be extremely impractical, mostly in terms of performance with many tiles being rendered at once. I have aided in this by only allowing tiles within a certain distance of the player being rendered, but this isn't that great either. I have also had problems with the objects returning a null-pointer exception when I try to edit the tile's values in-game. This has to do with the objects in the 2D array not being properly initialized.
Is there any other, simpler way of doing this? I can't imagine every tile-based game uses this exact way, I must be overlooking something.
EDIT: Perhaps LWJGL just isn't the correct library to use? I am having similar problems with implementing a font system with LWJGL... typing out more than a sentence will bring down the FPS by 100 or even more.
For static objects (not going anywhere, staying where they are) 1 tile = 1 object is OK. That's how it was done in Wolf3d. For moving objects you have multiple options.
You can, if you really really want to, store object sub-parts in adjacent cells/tiles when an object isn't contained fully within just one of them and crosses one or more cell/tile boundaries. But that may be not quite handy as you'd need to split your objects into parts on the fly.
A more reasonable approach is to not store moving objects in cells/tiles at all and process them more or less independently of the static objects. But then you will need to have some code to determine object visibility. Actually, in graphics the most basic performance problems come from unnecessary calculations and rendering. Generally, you don't want to even try to render what's invisible. Likewise, if some computations (especially complex ones) can be moved outside of the innermost loops, they should be.
Other than that it's pretty hard to give any specific advice given so little details about what you're doing, how you're doing it and seeing the actual code. You should really try to make your questions specific.
A two-dimensional array of Tile objects should be fine........ this is what most 2D games use and you should certainly be able to get good enough performance out of OpenGL / LWJGL to render this at a good speed (100FPS+).
Things to check:
Make sure you are clipping to only deisplay the visible set of tiles (According to the screen width and height and the player's position)
Make sure the code to draw each tile is fast... ideally you should be drawing just one textured square for each tile. In particular, you shouldn't be doing any complex operations on a per-tile basis in your rendering code.
If you're clever, you can draw multiple tiles in one OpenGL call with VBOs / clever use of texture coordinates etc. But this is probably unnecessary for a tile-based game.

how to draw large grids for map editor?

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.

Collidable color Java/Android game

I'm trying to develop side scrolling game for android involving many many textures so I was thinking if I could create a separate layer, all a single unique color (very similar to a green screen effect) make a collidable and make it invisible to the player.
(foreground layer) visual Image
(2nd layer)collidable copy of foreground layer with main character
(3rd layer)Background image
I not sure if this is possible or how to implement it efficiently, the idea just came to me randomly one day.
Future regards, Thanks
I assume your game is entirely 2D, using either bit-blits or quads (two 3D triangles always screen-aligned) as sprites. Over the years there have been lots of schemes for doing collision detection using the actual image data, whether from the background or the sprite definition itself. If you have direct access to video RAM, reading one pixel position can quickly tell if you've collided or not, giving pixel-wise accuracy not possible with something like bounding boxes. However, there are issues greatly complicating this: figuring out what you've collided with, or if your speed lands you many pixels into a graphical object, or if it is thin and you pass through it, or how to determine an angle of deflection, etc.
Using 3D graphics hardware and quads, you could potentially change render states, rendering in monochrome to an off-screen texture, yielding the 2nd collidable layer you described. Yet that texture is then resident in graphics memory, which isn't freely/easily accessible like your system memory is. And getting that data back/forth over the bus is slow. It's also costly, requiring an entire additional render pass (worst case, halving your frame rate) plus you have all that extra graphics RAM used up... all just to do something like collision-detect. Much better schemes exist, especially using data structures.
It's better to use bounding boxes, or even a hierarchy of sub-bounding boxes. After that, you can determine if you've landed on the other side of, say, a sloped line, requiring only division/addition operations. Your game already manages all the sprites you're moving, so integrate some data structures to help your collision detection. For instance, I just suggested in another thread the use of linked lists to limit the objects you must collision-detect against one another.
Ideas like yours might not always work, but your continual creative thinking will lead to ones that do. Sometimes you just have to try coding them to find out!

Categories