Tile based game

Hi there!



First of all: JME rocks! Thanks a lot guys - fine piece of software you made there.



I'm quite new to JME. Currently I'm trying to add a tile-system to a RPG I'm working on. There are a few problems though. I tried some approaches but they just don't seem to fit right.



1st Approach: Lots of Boxes

In the beginning I decided to make boxes because they seemed just like the solution. They covered everything including height. I added 500 boxes to the root node and everything seemed fine. But then I added 3000 boxes and the fps broke down drastically. I thought maybe Java wasn't the right thing for 3D games but then I decided to make sure.



2nd Approach: Lots of Quads

I made the same thing just with quads instead of boxes. There was no performance boost though. The fps were still crap. So it wasn't Java's being slow, it had something to do with the Scenegraph or JME. Therefore I decided to throw the idea of many 3D-Objects away, since there would be like 10.000+ tiles in the end.



3rd Approach: Terrain

I played around with the terrain-classes and found many ways to implement a game world. My favourite: terrainpage with imageheightmap -> can be as big as I like even with easy-to-make heights -> sweet! So the problems with the size of the map was somehow solved. But another problem occured… how do I implement the tile system? I came across texture-splatting, proceduraltexturegenerator, texture.setScale,… but nothing seems to be the right thing for my needs.



Do I really have to write a program that adds small jpgs according to some defined array and that spits out a giant image that is the only texture of the terrain?

Is there no better way to make tiles "fetchable"?



Could really need some advice - thank you!

Hey mars, and welcome.



The real problem with the "quads (or boxes) as tiles" approach is that you end up sending a small amount of data to your graphics card lots and lots of times.  Your graphics card prefers to have things sent in batches.  One way to use quads but increase fps is to reuse the same geometry data each time.  You can do this through the use of SharedMesh.  You still have the problem that you are constantly updating a scenegraph of thousands of items that are probably never changing (or only very seldom).  You can use locking to solve that, especially locking transforms.



Another approach would be to merge all of the quads with the same tile type into a larger piece of geometry.  There are some user submitted code for doing that if you search through the forum.  You might also have a look at the Geometry Clone work also on the forums.



There's probably a dozen other ways to improve the technique as well.  Hope that helps get you started!

Suppose you had a huge sliding block puzzle with 1000 pieces, the textures are constant but the current active tile is shaded yellow.



How would you go about implementing this ??

Thanks for the advice.



I tried SharedMesh and lock. SharedMesh didn't increase fps. Using lock() on each SharedMesh and the tile node gave a little performance boost but it's still not as fast as it should be. I'm going for quad-merging later on.



@theprism

I would try some things like swapping texture, applying some effect with apply() or something else.

A sliding block has a missing piece to slide the block into - cant see that swapping textures would do it

The only solution for merging Quads that I've found is that one: http://www.jmonkeyengine.com/wiki/doku.php?id=geometrybatch .

I tried it but it didn't work out - don't have any objects. I guess it's in an early stage.



But I'm working on another solution. Why do I need 100k tiles loaded when I just see 100? I'm working on a program that adds and removes tiles depending on the player position - that should do it.

mars said:

But I'm working on another solution. Why do I need 100k tiles loaded when I just see 100? I'm working on a program that adds and removes tiles depending on the player position - that should do it.


Isnt that what culling takes care of
1 Like

Culling will keep it from being sent to the card, but adding and removing predictively is smart for keeping the scenegraph manageable.  As for yellow highlights, why can't you use a materialstate change for that?

I'm already doing this with hexes and quads.  you want to use GeometryInstance (do a search for it).  I'm able to do rather large boards with good performance.  You can individually alter the texture, rotation, and translation of any given quad instance within the batch which works out very well.



If you need any help or ideas let me know.

I tried the TestGeometryInstancing demo. It doesn't solve the fps-problem but might be very useful for making height and forming the terrain for my game - thanks!

I'm still sticking to my idea of removing not-seen tiles from the scenegraph, so tiles are added while the player moves to a certain spot. I'm going to report how it worked out.

What kind of FPS are you seeing?  Snylt (who created the instancing classes) and I have discussed a few ways to use GeometryInstancing for very large boards but I've not needed to implement them since I am working on a turn-based game and anything much higher than 30-40fps isn't really needed (though at a current workable board size - 30x40 - I'm getting around 800fps).  If you use one big instance it cannot be culled (assuming your gameboard is always in view) so you're managing the entire board in an all or nothing fashion.



A possible solution for a large board is to create several smaller sections (instanced) and then link them together to form your board.  This would allow sections to be culled and would likely increase performace a good bit with something like a 100x100 board.  You could maybe build 10x10 sections and then assemble the board out of those (you'd need to experiment to find a balance between number of sections and culling performance).  You can also use lock()ing to your advantage if the board does not change very often.



I have no doubt jME can handle what you are trying to do, but you're likely going to have to be a bit clever about how you handle it, as I would expect with any game engine trying to create so many tiles.

Allright: tested and works fine!

The Tilemap can now be as big as I like.



What I've done:

  • Made a huge Hashmap<position,quad> (entire world) //position is a class with just x,z coordinates.
  • Made a Hashmap that contains currently loaded tiles
  • Made a "trigger field" Hashmap <position,boolean> that sets an area that has to be surpassed in order to reload tiles.
  • Function: if the current player position equals none of the positions in the trigger field:

    > detachAllChildren from param2 Node

    > remove "added tiles" hashmap

    > Set param1*quads around the player (copy stuff from world-hashmap to appliedtiles-hashmap)

    > attachchilds(appliedtiles-hashmap



    and done.



    I can't post any code for now, because it's all object oriented and spread among some files. I'm also using some special selfmade stuff for my game so you're going to be confused. Maybe I'll post a simplyfied procedural code someday.



    If someone has questions about the logic I used, send me a personal message.

Nice work!  Glad to see you were able to solve your issue.  If you do get a chance to post it I would be interested in checking out your code.

mars said:

The only solution for merging Quads that I've found is that one: http://www.jmonkeyengine.com/wiki/doku.php?id=geometrybatch .
I tried it but it didn't work out - don't have any objects. I guess it's in an early stage.

But I'm working on another solution. Why do I need 100k tiles loaded when I just see 100? I'm working on a program that adds and removes tiles depending on the player position - that should do it.


This used to work on an older version of JME, but I haven't tried it with the current version.