How do I optimize JFrame drawImage for RGBA images? - java

I'm working on a 2D game in Java using swing JFrame.
At the moment I can get >60fps repainting a grid of 64x64 image tiles, but when I want to add my tree images which are 80x170 each and have transparent edges around the tree, my fps grinds to about 8.
I've considered drawing the trees to their own BufferedImage grid, but it needs to be updated frequently, whenever a player moves or AI moves, etc.
I've noticed using smaller images and drawing them at a larger scale does not help, and am really struggling to see how I can get around this.

Related

Rotate 2d graphics images on fixed background

I am writing Java code to rotate images on a fixed background image, like rotating a needle image on clock background.
There are multiple needle in the watch, one needle for hours and another one for minutes.
How to rotate 2d graphics images on fixed background?
Start with a base, static image (ie a clock face), where the parts you need to animate have being cut out.
On top of this you can render each element you need at the required locations.
Start by having a look at...
Performing Custom Painting
2D Graphics
You'll need some way to update the movement. This can be achieved through the use of a single or multiple javax.swing.Timer timers, see Concurrency in Swing for details.
The rotation is a little more fun, but can be achieved through the use of an AffineTransform
Take a look at...
Rotate BufferedImage Inside JPanel
Rotate an image in java by the specified angle
Image not at proper place after rotating (graphics) (which is close to what you asked)

Drawing shapes with transparent colors much slower than opaque colors in Java

I am currently working on making a Java videogame with a few friends. It is a top-down RPG that is drawn with tiles of different types. I just added a day/night cycle to the game, and found that using transparent colors to draw to the screen is very slow. I recently learned how to make colors transparent by adding an alpha-value after the RGB values, and it works very well, but as I said, it is slow. I tried switching between transparent colors and opaque colors and discovered that the lag is because of the transparency. Basically, after a tile is drawn, it calls the method for getting the desired transparency factor, makes a new color, and calls g.fillRect() over the tile. This is done for every tile on screen.
I would like to know if there is another way to have a transparent overlay without just drawing the overlay over the whole window, because we want to be able to add light sources that replace the transparency for specific tiles. The tiles are drawn to the screen from a spritesheet. Any suggestions are welcomed.

Generating Very Large Images at Runtime with OpenGL and libgdx

I am generating very large hex grids (up to 120k total hexes at 32px wide hexes results in over 12k wide images) and I'm trying to find an efficient way to bind these to OpenGL textures in libgdx. I was thinking of using multiple FBOs and breaking the grid up as necessary into tiles, but I'm not sure how to ensure continuity between the FBOs. I can't start with one massive FBO, because that is backed up by a texture so it would fail from trying to load it to video memory. I can't use a standard bitmap on the heap because I need the drawing functionality of an OpenGL surface.
So what I was thinking was I would need to overdraw on the FBOs and somehow pick up on the next FBO exactly where the previous left off. However I'm not sure how to go about this. I'm drawing the hex grid with a series of hexagonal meshes, FYI.
Of course, there's probably some other much simpler and more efficient way to do this that I'm not even thinking of, which is why I pose this question to you fine people!
You have to draw it in pieces. You need to be able to draw your hex grid from an arbitrary position. This means being able to compute which hexes to draw based on a rectangle overlaid over the map. This isn't a hard problem, and I wouldn't worry too much about drawing extra stuff off-screen. You should master this ability to view the hexmap from any position before moving on.
Once you've mastered that, it's really simple.
Draw the top-left corner and store the pixel data. Then move the area you're drawing over exactly one image width. Draw and store that. Move the area over one image width. Draw and store it. Keep doing that until you've covered the entire width.
Move down one image height and repeat the process. Once you've run out of width and height, you're done. Save your mega-huge image.
You don't need FBOs for this. You could draw it to the screen if you wanted. Though if you want maximum performance, I would suggest using FBOs, double buffering them, and using glReadPixels though a pixel buffer object. That should cut down a lot on latency.

Android Game Development - How can I fill a circle with a repeated pattern?

I'm currently developing a game for Android.
As part of the game, I need to have a circle that increases and decreases in size, but not with a simple single-colour paint fill.
Instead, is there a way I could dynamically draw a circle onto a canvas then fill it with a given image (probably another bitmap - tiled, in order to fill the image)?
Many thanks in advance,
Will.
You want to do a simple Canvas.drawCircle(), but using a Paint with a BitmapShader.

Using a canvas much larger than the screen

I'm trying to draw a 2D contour plot of some data on Android and I'm wondering what the best approach would be to draw those. The whole datasets can be relatively large (2k * 2k points) and zooming and moving inside the plot should be very fast. Most of the time only a small part of the data will be drawn as the user has zoomed in on the data.
My idea now would be to draw the whole plot onto a large canvas, but clip it to the portion visible on the screen, so that only that part would be really drawn in the end. I find the 2D drawing API of Android somewhat confusing and I'm not sure if this is really a feasible approach and how I would then go about executing it.
So my questions are:
Is it a good idea to draw onto a canvas much larger than the screen and use clipping to display only the relevant part?
How would I create a larger canvas and how would I select which parts should be drawn?
You should start the other way around. Instead of creating a huge canvas you should detect what part of your plot you need to draw and draw only that.
So basically you need some navigation/scrolling and you need to keep the offset from the starting point in memory to calculate where you are. Using the offset you can easily zoom in and out because you just need to scale the plot to the screen.
Is it a good idea to draw onto a
canvas much larger than the screen and
use clipping to display only the
relevant part?
A better question might be, do you have any other options. Some might argue that this is a bad idea since your going to keep memory in use when it isn't relevant to whats happening on the UI. However, from my experiences with the Canvas, I think you'll find this should work out just fine. Now, if you are trying to keep "5 square miles" of canvas in memory your definitely going to have to find a better way to manage it.
How would I create a larger canvas and
how would I select which parts should
be drawn?
I would expect that you will be creating your own "scrolling" method when the user touches the screen via overriding the onTouchEvent method. Basically your going to need to keep track of a starting point X and Y and just track that value as you move the Canvas on screen. In order to move the Canvas there are a number of built in's like translate and scale that you can use to both move the Canvas in X and Y as well as scale it when the user zooms in or out.
I don't think that is a good idea to draw your 2D contour plot on a big bitmap because you need a vector type graphics to zoom in and out in order to keep it sharp. Only pictures are good to scale down but graphs will lose thin lines or come out deformed when scaled down in bitmaps.
The proper way is to do it all mathematically and to calculate which part of the graph should be drawn for required position and zoom. Using anti_alias paint for lines and text, the graph would always come out sharp and good...
When the user zooms out, some items should not be drawn as they could not fit into the screen or would clutter it. So the graph would be always optimised for the zoom level...

Categories