How to implement a scrollable, zoomable map in JavaFX/ScalaFX? - java

I am implementing a map as a computer game accessory; it should show the geography of the computer game with a few informative overlays. I wonder what's the best way to achieve this in JavaFX, or more precisely ScalaFX.
Right now, I have a very naive implementation:
I have tiles for the map in different zoom levels. For each zoom level, I arrange ImageViews in a Group and transform that group, so that all zoom levels use the same coordinates.
A separate group with the same coordinates is used for my overlays.
I zoom using the mouse wheel and make only one zoom level visible, depending on the current zoom.
I pack all this into a ScrollPane.
That has a few limitations:
all tiles, for all zoom levels, are loaded at startup. That's ugly, but works in my particular use case.
using a ScrollPane only works if the map has limited bounds. Again, fine here, but not for maps in general.
the UX is weird: the ScrollPane scrolls with the mouse wheel, while most maps scroll per drag and drop; most maps zoom with the mouse wheel or pinch to zoom. It's critical that zooming preserves the "anchors" (mouse/touch positions) during the gesture. (It would also be nice to be mobile-ready out of the box, but that's just dreaming right now...)
different levels of detail in the overlay, depending on the current zoom, are possible, but probably not very efficient or convenient.
Obviously, this is one of the approaches I tried. This question mentions a library by some eppleton, but it doesn't seem to be maintained, and the blog that used to describe the library doesn't exist anymore. Also, it seems to focus on providing a game engine, with a tile having meaning to the game; a tile in a map is just an image, and the overlay doesn't care where one tile begins or ends.
To finish this with a concrete question: Are there any libraries or techniques that I can use to fulfill my needs? I'm especially interested in my third bullet point (UX), but I guess that if there's a suitable approach, it would cover points 1 to 3.

UPDATED:
Few more options are on the table now:
Gluon Map
GMapsFX
One option is not to build but use existing open source project, such as openmapfx

Related

Wrapping a GridPane in a ScrollPane or programatically modifying it. Most efficient approach?

In a game I have a GridPane displaying the Tiles of the world in square cells. The player can, using the keyboard, move what is displayed by a column\row. The approaches I've thought of are:
Having the GridPane change programmatically the displayed tiles by moving everything by x steps on player input.
Wrapping the GridPane in a ScrollPane and tying the ScrollPane's scroll to Keyboard input.
My question is, assuming that things that are off-sight but on the same map are always loaded, what are the pros and cons of each approach efficiency-wise? Most specifically, I'm wondering if wrapping the GridPane in a ScrollPane would keep the Images loaded even if they are off-screen, thus impacting performance and if in that case it would be better to just reload them when needed. I'm also wondering if there's a third, more efficient way I haven't thought about.
I'm using JavaFX8
General approach
The most efficient approach for providing a limited viewport onto a very large world is to use a tile based model for the world and to only load the graphics resources and display the tiles that are required for the current viewport.
Sample canvas based implementation
A nice overview of how to accomplish this is the eppleton JavaFX tile engine which is described in an eppleton blog post. That particular implementation uses a Canvas direct draw based approach rather than a scene graph node oriented approach.
Sample scene graph node based implementation
A scene graph based approach relies on what is termed a virtual control; where the control provides cells which are windows on to the underlying data model. The JavaFX ListView and TableView are examples of virtualized controls. These virtual controls can be backed my data structures which contain thousands of items but only visual items for the currently visible tens of items are actually shown on the screen. As the control is scrolled or its underlying data structure is modified, callbacks are invoked to refresh the graphical nodes for each displayed cell.
An example of a scene graph based virtual control for a grid is the ControlsFX GridView. Note that, unlike the canvas based eppleton Tile Engine, the ControlsFX GridView is not specifically built for and optimized to be the core tile based renderer for a game engine, so if you would use GridView in such a way, you would need to add significantly more features to a fork or extension of the GridView to bring it functionally on par with a full gameplay tile engine.
Existing specifications and toolsets
Note that there are existing specifications for Tile map formats such as TMX and existing editors to create files which conform to such formats. Usage of a tilemap is appropriate for both realtime and turn based games and may even be useful outside the gaming genre, though it's traditional usage is in the creation of video games.
Answers to additional questions
would you mind elaborating, even if just slightly about what you mean with GridView is not optimized?
Your primary application seems to be writing tile based game engine. Such an engine usually provides support for reading tile map data, tile image data, overlaying animated sprites on to the tiles, etc. Those kind of features aren't in a ControlsFX GridView because that has a different focus (e.g. displaying a viewport of thumbnail images for a file directory). The point is not that GridView is not optimized performance wise (because it is), the point is that GridView won't provide you with the optimal set of out of the box features which you might need for your particular application (a tile based game).
I forgot to mention in my case the Entities move Tile by Tile and not Pixel by Pixel
That makes implementation simpler as you only have to worry about tiles at discrete co-ordinates and the entity can be an exact tile co-ordinate without an offset for current location and rendering between tiles. However it doesn't really change the whole approach of using a virtualized viewport of only onto the world which only renders what you can currently see rather than rendering the entire world all the time.
Had I know all this a year ago I would had taken a very different route in my delevopment.
Sometimes it pays to do research and sometimes you learn by mistakes :-) I'm sure John Carmack would have written the original Doom differently if he knew then what he knows now. I wouldn't let such things worry you too much. Just assess where you are now and go from there.

Best way to load big background in libgdx

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).

Scroll a java 2d game tile map, while generating additional tiles

Finally decided to learn 2d (for now) java game programming. Am working on a game that has a central object that the user will guide with the directional keys. I have that working perfectly, cobbled together from examples and tutorials I've found.
I'm using this method of generating colored background tiles but I'd like to scroll (move) the background as the primary object the user is moving reaches the window edges. I'm fairly sure I can make that work, I have the basics in place, but I can't find a good tutorial or actual demonstration of a way to continue to generate additional tiles to fill in the space the user is moving too.
At this point, this is purely background and I have no need to save the exact tiles generated - but eventually I would like this ability. I'm sure I'll have to find a way to divide the areas into "chunks" like minecraft does.
But for now - how can I continually fill in the area with the same pattern? Or is there a better way to create the tiles that's better for this?
Instead of a solid color you can use a TexturePaint, as shown here. Let your model contain a reference to the desired texture for each grid cell. Let your view use a flyweight pattern for rendering, as illustrated here.

2D graphics library for Android

I'm working on an Android application that requires 2D graphical view with a large set of objects. Here's what I basically need to display:
In my case, there could be hundreds of spatially distributed objects. This view is going to behave like a map, so the user is able to scroll in horizontally and vertically, zoom in and zoom out. It also requires click event handling, so the user is able to click any triangle and I then should display some extended information related with that particular triangle.
I'm mostly concerned about 3 things:
In case I re-draw all the objects per in my onDraw() handler, that would be really slow. Also, there I cases when I don't even need to draw all these objects since some of them are invisible depending on zoom level and scroll position. These requires using quad trees which I don't want to implement manually.
All these objects are defined as (x,y,rotation,type), so in case customer decides that we need a "show all" button, I'll have to implement a functionality to calculate bounding boxes.
I need to be able to handle click events and (probably) dragging for all these shapes.
Is there any library that can help me with these tasks? Just don't want to spend 3 days on stuff that I believe must already have been implemented.
All the methods in the Canvas class of the android.graphics package should suffice. The Canvas does clipping (meaning drawing commands get discarded if it's not visible) so if the image is static you could render it into a Picture and draw that on onDraw().
I think the drawing methods have methods to calculate bounds and return them. See Path's computeBounds(RectF bounds, boolean exact).

What buffering strategy should I use for my 2D scrolling map?

So, I'm creating a 2d top-down game in Java.
I'm following instructions from Java 2D: Hardware Accelerating - Part 2 - Buffer Strategies to take advantage of hardware acceleration.
Basically, what I'm thinking is this:
I'd like to be able to easily add more sections to the map. So I'd rather not go the route suggested in a few of the tutorials I've seen (each map tile has an adjacency list of surrounding tiles; beginning with a center tile, populate the screen with a breadth-first search).
Instead, my idea would be to have screen-sized collections of tiles (say 32x32 for simplicity), and each of these screen "chunks" would have an list referencing each adjacent collection. Then, I would create a buffer for the current screen and the 8 adjacent screens and draw the visible portion in the VRAM buffer.
My question is, would this be a correct way to go about this, or is there a better option? I've looked through quite a few tutorials, but they all seem to offer the same (seemingly high maintenance) options.
It would seem this would be a better choice, as doing things at the tile level would require 1024 times as many adjacency lists. Also, the reason I was considering putting only the visible portion in VRAM, while leaving the "current" screen and its adjacent screens in standard buffers was because I'm new to hardware acceleration and am not entirely sure how much space is acceptable to assume to be available. Because Java attempts to accelerate standard buffers anyways, it should theoretically be as fast as putting each in VRAM?
Any and all suggestions are welcome!
I haven't looked at any of the popular tile-based game engines, but I'd consider using the fly-weight pattern to render only the tiles that are visible in the viewport of a JScrollPane. JTable is both an example and a usable implementation.
Addendum: One advantage of the JTable approach is view-model separation, which allows one to relegate the acquisition of tile-related resources to the model. This makes it easier to optimize without having to change the view.
Even without scroll bars, one can leverage scrollRectToVisible() by extending JComponent or an appropriate subclass. The setDoubleBuffered() method may be helpful, too.

Categories