How to draw on a buffer with Undo capability? - java

While I am not doing some animation or drawing a very complicated graphics.
I need (sort of) double buffering for drawing several primitives. In the application, user enters name of Shape followed by related arguments and that shape is drawn on buffer, and then on screen.
Eg of a command is RECT 100, 50, 200, 120.
For persistence, I can store all commands in list and in
public void paintComponent(Graphics g) of JPanel I draw them one by one.
But this is highly inefficient, because of iterating through list and using a hash map each time to call (or dispatch) the relevant shape-drawing-interface.
How and on what type of buffer can I draw? How can different methods draw on this buffer?
Additionally is there a convenient way to be able to undo previous draws with buffer? Or do I need to redraw on buffer each time a undo is done?
Thanks, I don't want full code, but relevant class names and small pseudocode is appreciated.

JPanel is double buffered by default, so selecting and dragging are typically quite smooth. GraphPanel is a simple object drawing program that illustrates such operations on a List<Node>. A similar approach has been successfully used with thousands of nodes.
The details of implementing an undo strategy depend significantly on the desired behavior, but remove() and repaint() are effective.
Addendum: One common optimization for rendering large numbers of objects uses the flyweight pattern. JTable, JFreeChart and JGraph are examples. This simplified example illustrates the essential mechanism.

Related

Java platformer game performance

I recently started working on a 2d platformer in java, and am asking a performance related question.
In my game, I have a world (relatively small for now).
But over half+ of the world isn't visible to the players camera, however I'm still painting the entire world (even the unseen parts).
Here's what I'm doing right now.
#Override
public void paintComponent(Graphics g){
g.translate(player.camX(), player.camY());
for (GameObject gameObject : solidObjects){
if (gameObject.isTouching(player.getCameraRect()))
gameObject.paint(g);
}
player.paint(g);
for (GameObject gameObject : unSolidObjects){
if (gameObject.isTouching(player.getCameraRect()))
gameObject.paint(g);
}
}
So the question is, would it be faster having an if-statement checking if its on the screen before painting?
Yes.
Doing a check to see if it's on a screen should take no more than 1 or 2 steps.
Painting everything requires you to draw every single pixel on to the screen regardless of whether it's used or not.
If gameObject.paint(g); involves a lot of drawing calls, most likely the branching (check) would save more work than it costs. If it's only like one drawing call to paint a sprite though, your library would already perform such a check to avoid buffer overruns and yours would be redundant.
That said, if you are starting to face performance issues here, then I recommend using some kind of data structure. A simple one is a grid like so:
When your elements move, remove them from the grid cells they occupy and insert them to the new one(s) they occupy. That should just involve manipulating a few integers if you implement this efficiently.
Then when you want to draw elements on the screen, only draw the elements in the grid cells that overlap. That'll prevent you from looping over every single element in the game world. This also comes in handy for accelerated collision detection if you need it.
A quad-tree is an alternative though a little bit more costly to update, but it can provide better search quality if the elements in your game are sparsely distributed.

Java Swing heavy/slow paintComponent - any advice?

I'm making a scrolling 2D map/tile based game. Each tile (stored as tile[21][11] - 231 tiles total per map) can contain up to 21 values (stored as int[3][7]). While full-screen I see about 8 maps at once.
On average, each map takes about 0.03 seconds to draw (found with System.nanoTime). The problem is that as soon as more than 1 map is on the screen, the Swing event polling noticeably slows down.
Is there any solution to this? I can't draw the map a single time to save it as an image because it has transparency involving moving actors, so it changes too frequently. Also I don't think I can call a thread in paintComponent to draw the maps without it glitching out, but I'm not positive.
My Tiles aren't any type of JComponent, they're just data. I call their container the MapPane, which draws all of the tiles in its paintComponent.
Likewise, JTable cells are just data rendered inside a JComponent; the flyweight pattern, mentioned here, is still applicable: the goal is to omit any effort to render non-visible cells. Profile and self-time with a view toward optimizing the rendering; some approaches are examined in the KineticModel cited here.
A BufferedImage that needs no scaling is best. If you must scale, experiment with RenderingHints related to interpolation type. If composition is too expensive, construct maps in the background using SwingWorker; publish() them as they become available and process() them on the EDT, as shown here.

Array of JLabel vs. Graphics2D Painting

I have to create a connect 5 game with a GUI for my CS course final project. I worked with Graphics2D for the last project - a Maze - and working with Graphics2D was a nightmare. At most, the connect5 board will be 20x20, which would be an Area of 400. I was wondering what the performance implications of creating an Array of 400 JLabels to handle the GUI, since it will be easy to determine a mouse click within boundaries, get the array induces, and changing the color of space along with other similar operations whereas the same operations would be much more difficult with Graphics2D. So, my overall question is: would creating an array of that many JLabels be undesirable? If so, what other alternatives might I have? Thanks everyone!
I think the JLabel approach would be undesirable, I think one component with custom painting would be more desirable, because it seems a bit easier.
If you have your classes in that abstract format not tied to the UI or anything (so playable even on the command line where you could output in a text a representation of the board), then it should be simple to loop through the spaces representing the board and make the small set of drawing calls to draw each slot (empty or not).
Seems better to if you wanted to introduce animations like pieces falling down and then bumping up for a while when they hit the piece below it.

Java GUI programming strategy?

Java Beginner.
Hi, I haven't got any much experience with GUI programming. So I'm after some hints on how to tackle this next project. Hopefully I can explain myself well enough.
(source: mobilehomeservicesltd.com)
(see above photo as a reference)
This GUI aspect of my program will be a 2D - Birds-eye-view of a static caravan and veranda/balcony made with basic shapes. So typically the caravan will be represented by a rectangle (just a rectangle, ignore the fill in diagram). Sometimes static caravans have shaped fronts so that would be represented by a polygon as opposed to a rectangle. All in scale dependant on the users input, as all caravans have their individual dimensions.
After the caravan unit is in place I then need to draw another polygon surrounding the caravan representing the balcony/veranda, all to scale. Understand so far?? Good. Here comes the challenge part (for me anyway).
On the polygon representing the balcony I need to be able to draw lines to represent the decking that will be nailed down as a surface (like the diagram above). Now because the caravan could possibly have a shaped front, the decking must follow the shape of the caravan. In other words, if the caravan has an oval or angled front the decking will have to be cut to follow that shaped.
Without boring you all too much with detail. The idea is to let the user decide whether they want the decking fitted in such a way that its running in the same direction as the caravan, or against. Once the user has decided I will then attempt to calculate from the drawing (as it will be to scale) how many full lengths of decking will it take to build this veranda (among various other items).
Now my knowledge is limited on GUI, but I'm up to scratch with panels and drawing lines, rectangles, polygons etc... My original idea was to manually draw the caravan using the g.drawLine method, same with the veranda and then base my calculations on pixel counting to calculate all the various components.
Am I out of my depth attempting this, or is this something relatively easy to program?? Is there a more efficient way of doing this that I should look up before attempting this?
What you want to do is achievable, but its not the simplest of tasks. But don't let that slow you down.
You'll want to get started by understanding how to draw in Swing. Take a look at
Graphics 2D
Custom Painting
You'll also want to be familiar with Swing in general
Creating a GUI with Swing
The basic concept with scaling, is assigning a weight to a pixel. The more distance that a pixel is responsible for, the small your image will become

Performant Bar Chart from FIFO buffer

I have question how to create a performant swing component.
The component should draw some kind of bar chart. The data for the component are stored in a separte FIFO buffer class. Everytime the buffer is updated the component is informed.
At the moment the component draws a BufferedImage everytime the data changes. The paintComponent method of the bar chart component then draws the created BufferedImage.
Due to the fact that there are a lot of data changes in my application, I am thinking to improve the painting of the BufferedImage. Most of the bar chart remains the same. It is just shifted to the right and the latest data changes are added to the left of the bar chart.
At the moment the whole BufferedImage is recreated out of the data stored in the buffer. What I could think of is to shift the old BufferedImage using AffineTransformation and only add the recently added data. This would enormously decrease the amount of drawing operations on the BufferedImage.
But I do not know if this will speed up the application. How expensive is the AffineTransformation on a BufferedImage?
Any remarks are welcome. Also some other hint how to create a performant swing application.
Thanks in advance
Without some sort of baseline, it's very difficult to measure improvement. At a start, you might compare the two approaches shown here using JFreeChart. The DynamicTimeSeriesCollection loafs at 10Hz; I haven't examined the other closely, but it looks flexible.

Categories