I'm taking my first steps in JavaFX. I want to animate a lot of graphic elements (ellipses, bézier curves, not images) with javafx. These elements are organized in groups of about 10 elements that have to move together. I'm trying to achieve 60 fps and I want to move thousands of these elements.
There are at least four ways to do this:
Using a single canvas, and its graphical context to draw directly at every frame.
Using groups and nodes. Each element is a node. I like this way because there are a lot of classes that can be used to draw easily what I need, and the logical structure of nodes and groups is just what I need.
Each group is a canvas. Draw its elements in its constructor using the canvas graphical context, and then move all the canvases at each frame.
Creating images with the elements that have to stick together, and then move these images. I haven't found already how this can be done, but I suppose it's not hard. The elements may change from time to time, so I will need to recreate some images, but only once in a while.
My question is, which of these ways (or another) would be the fastest way to do it? In particular, does the use of a lot of nodes and groups has a high performance impact?
I would start with option two as this seems to logically fit your needs best. It is also the most straight forward and cleanest way of doing it with JavaFX. If it later turns out that the performance is not good enough you can try to improve this by using caching together with the appropriate cache hints. For example you can optimize your code for speed or for quality this way. This even works dynamically because you can switch between these cache hints depending on the state of your application. If you switch caching on for a group this has basically the same effect as drawing it into a canvas or an image.
Related
I am currently working on a complex project and struggle with increasing the performance, because I ran out of ideas.
So this is what my program looks like at the moment:
It is a Graph, that shows the path of an object, starting at the green node and ending at the red node. The container is a JPanel, which holds another JPanel at the top right corner, containing the buttons, a JLabel at the top left corner for the status and the different Nodes itself of course. The Nodes and lines are JPanels as well.
So what exactly is the problem?
The Graph contains lots of functionalities. Zooming, DnD and adding end deleting new nodes.
All of these functionalities need the container to repaint, especially DnD needs this very often. So this is just an example with 4 nodes. everything works fine. But at 1000+ nodes and 999 lines between them, it really gets slow. The graph should be able to work with ~20K nodes without having big troubles.
Everytime you move a Node 1px with the mouse in any direction, the whole container gets repainted.
Creating a minimal reproducable example is not quiet possible, because the code for this application is long and there are a lot of dependencies, that would make it not "minimal".
The ideas I have to increase performance are:
Reducing the amount of Nodes (and so the amount of lines), so that less components need to be repainted. This is quiet hard, most nodes are not in a straight line, means there are not many ways to do this. One option would be to reduce the Nodes and increase the level of detail with the zoom function.
Clipping the area, that has to be repainted. The problem with this approach is, that I don't know how exactly this clipping function works or whether it is even possible.
The last idea of mine would be, to somehow create a JLayer object containing (total amount of nodes / 100) layers, that are all visible and only repainting the layer, that contains the specific Node. This seems very unstructured, I don't really think that this is an option, just an idea.
What am I asking for right now?:
How do you manage so much components that have to be repainted? There are definitly ways and I am open to try them all. I just want you to give me some advice, hints on useful built in libraries, that I maybe haven't found in my research. And if one of my ideas could be the one I should go for.
I am not asking for concrete code examples, just for your experience.
Thank you in advance and I'm sorry if my question does not fit the SO conventions.
I want to create a 2D Game with Java and LWJGL. It is a retro styled RPG game. So there is a really big map(about 1000x1000 or bigger). I want to do it with tiles but I don't know how to save it/how to render it.
I thought at something like a 2D-Array with numbers in it and the render just sets the right tile at the right place.
But i think the bigger the map gets the more it will slow down.
I hope you can help me. :)
My second suggestion was to make a big image and just pick a part of it(the part where the player is) but than its hard to know where I have to do a collision detection, so this ist just an absurd idea.
Thank you for your suggestions!
As one of the comments mentioned, this subject is far too large to be easily covered with a single answer. But I will give you some advice from personal experience.
As far as saving the map in a 2D array, as long as the map is fairly simple in nature there is no problem. I have created similar style maps (tiled) using 2D integer arrays to represent the map. Then have a drawing method to render the map to an image which I can display. I use multiple layers so I just render each layer of the map separately. Mind you most of my maps are 100x100 or smaller.
I would recommend for such large maps to use some sort of buffer. For example, render only the playable screen plus a slight offset area outside of the map. E.g. if your screen if effectively 30x20 tiles, render 35x25, and just change what is rendered based on current location. One way that you could do this would be to load the map in "chunks". Basically have your map automatically break the map into 50x50 chunks, and only render a chunk if you get close enough that it might be used.
I also recommend having the drawing methods run in their own thread outside of the main game methods. This way you constantly draw the map, without having random blinking or delays.
I'm maintaining my 400*400 tiles map in the Tiled map editor and render it with the Slick2D framework. It provides support for rendering only visible subsections of the map. (TiledMap class).
I've tried both approaches - Image based and tiled based map creation and ended up with the latter. With tiles you can not only create the view of your map but also invisible meta data layers, like collision, spawn spots, item locations etc.
I'm having quite a bit of difficulty wrapping my head around the actual display side of things with libgdx. That is, it just seems fairly jumbled in terms of what needs to be done in order to actually put something up onto the screen. I guess my confusion can sort of be separated into two parts:
What exactly needs to be done in terms of creating an image? There's
Texture, TextureRegion, TextureAtlas, Sprite, Batch, and probably a
few other art related assets that I'm missing. How do these all
relate and tie into each other? What's the "production chain" among
these I guess would be a way of putting it.
In terms of putting
whatever is created from the stuff above onto the monitor or
display, how do the different coordinate and sizing measures relate
and translate to and from each other? Say there's some image X that
I want to put on the screen. IT's got it's own set of dimensions and
coordinates, but then there's also a viewport size (is there a
viewport position?) and a camera position (is there a camera size?).
On top of all that, there's also the overall dispaly size that's
from Gdx.graphics. A few examples of things I might want to do could
be as follow:
X is my "global map" that is bigger than my screen
size. I want to be able to scroll/pan across it. What are the
coordinates/positions I should use when displaying it?
Y is bigger
than my screen size. I want to scale it down and have it always be
in the center of the screen/display. What scaling factor do I use
here, and which coordinates/positions?
Z is smaller than my screen
size. I want to stick it in the upper left corner of my screen and
have it "stick" to the global map I mentioned earlier. Which
positioning system do I use?
Sorry if that was a bunch of stuff... I guess the tl;dr of that second part is just which set of positions/coordinates, sizes, and scales am I supposed to do everything in terms of?
I know this might be a lot to ask at once, and I also know that most of this stuff can be found online, but after sifting through tutorial after tutorial, I can't seem to get a straight answer as to how these things all relate to each other. Any help would be appreciated.
Texture is essentially the raw image data.
TextureRegion allows you to grab smaller areas from a larger texture. For example, it is common practice to pack all of the images for your game/app into a single large texture (the LibGDX “TexturePacker” is a separate program that does this) and then use regions of the larger texture for your individual graphics. This is done because switching textures is a heavy and slow operation and you want to minimize this process.
When you pack your images into a single large image with the TexturePacker it creates a “.atlas” file which stores the names and locations of your individual images. TextureAtlas allows you to load the .atlas file and then extract your original images to use in your program.
Sprite adds position and color capabilities to the texture. Notice that the Texture API has no methods for setting/getting position or color. Sprites will be your characters and other objects that you can actually move around and position on the screen.
Batch/SpriteBatch is an efficient way of drawing multiple sprites to the screen. Instead of making drawing calls for each sprite one at a time the Batch does multiple drawing calls at once.
And hopefully I’m not adding to the confusion, but another I option I really like is using the “Actor” and “Stage” classes over the “Sprite” and “SpriteBatch” classes. Actor is similar to Sprite but adds additional functionality for moving/animating, via the act method. The Stage replaces the SpriteBatch as it uses its own internal SpriteBatch so you do not need to use the SpriteBatch explicitly.
There is also an entire set of UI components (table, button, textfield, slider, progress bar, etc) which are all based off of Actor and work with the Stage.
I can’t really help with question 2. I stick to UI-based apps, so I don’t know the best practices for working with large game worlds. But hopefully someone more knowledgeable in that area can help you with that.
This was to long to reply as a comment so I’m responding as another answer...
I think both Sprite/SpriteBatch and Actor/Stage are equally powerful as you can still animate and move with Sprite/SpriteBatch, but Actor/Stage is easier to work with. The stage has two methods called “act” and “draw” which allows the stage to update and draw every actor it contains very easily. You override the act method for each of your actors to specify what kind of action you want it to do. Look up a few different tutorials for Stage/Actor with sample code and it should become clear how to use it.
Also, I was slightly incorrect before that “Actor” is equivalent to Sprite, because Sprite includes a texture, but Actor by itself does not have any kind of graphical component. There is an extension of Actor called “Image” that includes a Drawable, so the Image class is actually the equivalent to Sprite. Actor is the base class that provides the methods for acting (or “updating”), but it doesn’t have to be graphical. I've used Actors for other purposes such as triggering audio sounds at specific times.
Atlas creates the large Texture containing all of your png files and then allows you to get regions from it for individual png's. So the pipeline for getting a specific png graphic would be Atlas > Region > Sprite/Image. Both Image and Sprite classes have constructors that take a region.
I'm creating a UI system for an android game that will have a large (up to 4096x4096) background area in which menus can be placed anywhere within that screen and a camera will fly to that location when a different menu is needed. Instead of having a large static image, I'd like to be able to animate this slightly. What I'd like to know is how to do this efficiently without lagging up the device. These are the methods I've come up with so far, but maybe there is something better..
1) Have 3 separate 4096x4096 static layers for the background, 1 is the sky, one is the terrain, one is things like clouds and trees. Each layer is placed on top of each other with a slight difference in Z space to give a little parallax effect when the camera moves.
2) Have a large stationary background image, with a layer on top of that with individual specific sprites of clouds, trees and other things that should be animated. I think this might be the most efficient route, as I can choose not to animate parts that are not in view, but it will also limit re-usability as every different object will have to be placed manually in space. My goal is to be able to simply change the assets and be able to have a whole new game.
3) Have 1 large background layer with several frames that plays almost like a video. I feel like this will be the worst on performance(loading several 4096x4096 frames and drawing a different one 30 times a second), but would give me the scene exactly how I want it directly out of After Effects. I doubt this one is even feasible, not just because of the drawing but storage space on android devices just for the menu UI wouldn't allow for several 6MB frames.
Are any of these in the right direction? I have seen a few similar questions asked but none fit close enough to what I needed(A large, moving background that isn't made of tiles).
Any help is appreciated.
As far as your question is tagged for Android, I would recommend the 2nd solution.
The main reason is that solution #1 and #3 involve loading numerous 4096x4096 textures.
Quick calcultation: three 32bit textures with such resolution would use at least 200MB of Video RAM. It means that you can immediatly discard a lot of android devices.
On the other hand, the solution #2 would involve only two big textures: a large stationary background image, and a texture atlas containing specific sprites of clouds, trees...
This solution is really more memory friendly, and will lead to the same aestetic output.
TL;DR: the 3 solutions would work great but only the #2 would fit an embedded device
We're integrating Draw2D/GEF into an application, and are encountering an issue with the standard layouts provided.
We have a collection (say 100) of elements that need to be displayed in a grid-like fashion. We implemented our view using a GraphViewer, and applied a GridLayoutAlgorithm.
This works almost as we'd like it to, but the one stipulation we haven't been able to meet is that each node must be of a constant, defined size. Say, 50x50 pixels. The current GridLayoutAlgorithm we're using resizes the nodes so that they all fit in the window. If our window is small, the 100 elements become minuscule. We would instead like them to fill the width, then wrap to multiple rows, with a vertical scrollbar.
For the life of me, I can't find a simple, straightforward way to accomplish this.
Kind of a bummer answer, but I just ended up writing my own subclass of a GridLayoutAlgorithm and did a bunch of the math by hand. Frustrating that this wasn't included out-of-the-box, but it works fine.