I got me 90 odd images that form an explosion animation. When I come to 'play' the animation, I use a Swing Timer to set a new Icon for a JLabel, and cycle through until I reach the last image.
My question is this: is it better to have loaded and stored all the ImageIcons in some static form somewhere, or load them from file every time I need them?
Explosions are quite common in the game, and I have two sizes of them (scaling each image for every size of explosion seemed rather inefficient when I want them to swap very quickly) which makes for 200 images (roundabout).
Store or load?
For a game, using Swing components to represent game objects (Sprites) is probably not the best way. I would use a single JPanel as the rendering component and override its paintComponent() method to do rendering for my own game objects.
This way you avoid dealing with Swing components intricacies (e.g. they may add unwanted gaps / offsets where they really paint, as well they make it harder to control the painting order - important when two objects overlap).
I wouldn't use any type of Icon, just use java.awt.Image, or you own type to represent an image (e.g. to render part of an underlying image - as sprite sheet requires). Icon doesn't really add any value for a game.
If the image data fits easily into memory, I would load all the images before even starting. If there are too many images to preload them all, I would use some sort of cache that retains as many images as possible - the cache may use an LRU based scheme to decide which images to retain when it gets full.
I use a SwingTimer to set a new Icon for a JLabel, and cycle through until I reach the last image.
You may want to consider using an Animated Icon. It can be used anywhere an Icon can be used.
The AnimatedIcon class uses loaded Icons, so I guess my answer would be to pre-load for ease of use and CPU efficiency.
Related
I am trying to draw circles (representing people) on a PNG map of Earth. Obviously, I don't want people to be floating in the oceans as the simulated civilization expands. How would I create specified areas on the map that I can draw on? Can I simply restrict the background of the PNG?
I tried using the clip() method, but it still allowed spawning within the oceans. Any suggestions (or if you recommend clip(), how would you use it in this case) would be appreciated.
You somehow have to tell your program where drawing is allowed and where not. There are a bunch of approaches to this:
Try to define a set of features on your PNG image and only spawn (or don't spawn) civilizations if these features are met.
Make a "map" out of your map. Define areas on your PNG image where spawning is allowed and where spawning is not allowed. You can use this using the Polygon class for example.
Make a second PNG image in which you make all oceans purely transparent. Then, only spawn civilizations on the original image at locations where the image with transparency is non-transparent.
Just a bunch of ideas.
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 developing on a machine from 2008, and unfortunately cannot upgrade at the moment. I really need to optimize performance in this tool I am building.
My entire project is fairly large, and I'm currently creating my own Map Editor for use to create Maps for my main project later on down the road. It's fairly simple, and is being designed to load, save, and edit Arrays of 'Tiles' possessed by a Map. It's basically a 2D-Map Editor, customized for my needs.
When a Map is loaded into the Editor, its Tileset (one large BufferedImage), is broken down into each individual Tile (with a smaller BufferedImage), loaded into the right side of the GUI into a large bunch of JLabels with icons. I've used various Swing LayoutManagers to achieve my desired positioning.
Inside the MapCanvas area, essentially the same thing is done. Each Tile, whether empty or not, has a JLabel with an Icon, loaded onto the Grid. I've asked around before about whether using Swing components would be more efficient than using Java2D to design and draw, and the consensus was that it didn't really matter (and to be honest, Swing probably does it better than what I would write myself).
I believe my problem is stemming from the way that I interconnect each JLabel and their icons.
My goal was to reduce the number of duplicate Icons I have to create, which in theory should reduce memory usage and CPU usage. Tiles in the Editor are interacted with as follows:
If no tile is selected to be 'stamped,' there will just be an alpha composite of a color painted over the JLabel's icon to denote that it is being hovered, and will revert upon a MouseExit
If there is a tile on the active Stamp tool, that tile's image will replace the JLabel's icon -temporarily- to denote that it is being hovered, and will revert upon a MouseExit
If there is a tile on the active Stamp tool, and a JLabel is clicked, that JLabel's icon will be set to the active Stamp tile "permanently" unless reverted
If the option to have Grid Lines is toggled on, each JLabel's icon will be processed through the ImageFactory to have dashed lines running along the top and left edges (forms a grid, as seen in the picture)
If the Zoom level is changed, each JLabel's preferredSize is set to accomodate, and the icon has to be resized in the ImageFactory (grid lines applied depending)
Upon loading a Map into the Editor, each JLabel is created, given its corresponding BufferedImage (be that empty or not), and thrown into the Map's field ArrayList. The preferredSize is set so the Layout looks right, and it is added to the MapCanvas (which is just a JPanel).
I created various ArrayList and HashMap objects, so that I could pass a JLabel as a Key, and get back a BufferedImage. That way, when hovering iver a JLabel, the MouseEvent can send the event's source back to the listener, and it can grab the correct BufferedImage based on the JLabel it receives. The image can then be processed by my ImageFactory class in one of the ways listed above.
So basically when a JLabel recieves a MouseEvent, this happens:
MouseEvent sends source JLabel to ActionListener
Listener uses source JLabel as Key to grab desired BufferedImage chunk
BufferedImage chunk is then processed accordingly (which could be a color Alpha composite, a Zoom factor applied to it, or grid lines added to it, or a combination of these)
Is there any better way to do this? This doesn't take any noticeable toll on my 2 year old Laptop, but there is very noticeable lag when the Mouse interacts with the JLabels on my older Desktop machine.
Seeing as I will be actively developing on both, I want the environment to run smoothly, and if that means I have to be stricter on memory and CPU usage, then so be it.
But I can't really seem to come up with a system that is more memory efficient.
Are the ArrayLists and HashMaps the problems? Are the many image operations the problems?
I've taken advantage of JLabel's "setName(String)" method in various ways already (for example, each JLabel has a name containing its location in the single-dimension Array of JLabels, and its x-and-y coordintes on the graph, i.e. "maptile#24:1,9"), but that requires iterating through Arrays, and my hope was that specifically grabbing the BufferedImages with Keys would be more efficient.
Java collections are dynamic, meaning they resize as you add data. The actual model for their sizing function (used by ArrayList and presumably HashMap) is something similar to when they reach capacity they double their capacity, which consists of declaring a new block in memory and copying across all the stored data.
If you know the maximum possible size for each of your HashMaps and ArrayLists you may benefit from using the constructors that take an initial capacity. Here & Here This will prevent them using more memory than necessary. And will prevent any possible delays from increasing capacity.
You may also benefit from reading the top few paragraphs of the documentation for each type as they can provide good explanations of efficient usage (e.g. HashMaps loadfactor).
It may also be useful for you to consider other types of List and Map (if you are not aware of the difference in their implementations), e.g LinkedList has far more efficient delete and insert operations than ArrayList, however it is much slower for random access to an index than an ArrayList as it must traverse each prior index to reach the desired index, whereas an ArrayList can directly access the desired index.
However it's hard to guess how noticeable any changes you make based on these recommendations would be.
Ok, so I have this map and I have various sliders on the right. After changing slider values and pressing 'Execute' button, some provinces in the map below should change colour.
However, I don't know how to implement the map below. I have used 33 png drawable for each province. I have set them all to have a same big rectangle dimension so that they'd align themselves.
I am getting an 'Out of memory on byte allocation' error.
I assume this is because of all the large drawables I have.
I'm new to android and I want to ask, is there a way to implement this without the error?
Also the map should always be displayed on the left side of the screen so the images always have to be visible.
I would recommend making a SVG and changing the colors programmatically.
Graphics are hard to scale and are heavy space users, scalable graphics are slim, look great everywhere (device size and dpi) and easy to manage (single file instead of 33).
I'm in the process of writing a custom heatmap generator. I'm wondering what the fastest way is to draw boxes (up to around 1 million) in Java. Most questions I've found have concentrated on dynamic images (like in games), and I'm wondering if there's a better way to go for static images. I've tried using swing (via a GridLayout and adding a colored canvas to each box), drawing directly on the panel with Graphics2D, and also by using the Processing libraries. While Processing is pretty fast and generates a clean image, the window seems to have problems keeping it; it generates different parts of the image whenever you minimize, move the windows, etc.
I've heard of OpenGL, but I've never touched it, and I wanted some feedback as to whether that (or something else) would be a better approach before investing time in it.
For static images, I paint them to a BufferedImage (BI) and then draw that via Graphics2D.
I keep a boolean that tells me whether the BI is up to date. That way I only incur the expensive painting cost once. If you want to get fancy, you can scale the BI to handle minor resizing. For a major resizing you'll probably want to repaint the BI so as not to introduce artifacts. It's also useful for overlaying data (such as cross hairs, the value under the cursor, etc) as you're only painting the BI and the data.