I'd like some advice regarding structure of a game I'm working on. Specifically where to place painting methods.
Currently there is a applet wrapper class for a Jpanel which runs the game loop.
The game itself is meant to simulate a very large area. objects will have x&y values which themselves will part of a larger x&y grid.
i.e. object1 position is 150000x30000 in grid block 1,5.
objects will need to be able to move into neighbouring grids, however I'd rather not run each grid block until needed as 99% of them will be empty.
Currently the UI is a Jpanel with a few buttons + listeners, a large drawing pane is needed to display the objects.
my question is:
what class should this internal drawing pane be based on? I'd like to have control to zoom and pan around the grid. it only needs to draw what is visible, but object movements will continue in the game loop.
what painting strategy would be applicable for simple (icons really when zoomed out) moving around vast areas, I'm guessing relying on the EDT to repaint isn't going to be good enough?
I'm not really after specific code, I want to learn myself how to do this, I just need pointing in the right direction, as most things I read don't seam to quite cover what I'm after, or don't make use of JRE6+ features.
Many Thanks
Rather than paint each grid cell in your drawing pane, why don't you have each object repaint itself onto the grid?
Related
I'm trying to make a kind of AsteroidFighter game in Java.
I create a JPanel and paint several .png-files on the Panel, my spaceship, some obstacles like asteroids and collectables and of course the projectiles my spaceship is shooting. All of these objects are moving.
Both the obstacles and the projectiles are saved in ArrayLists.
I am using a swing-timer to repaint my JPanel every 25 ms.
As far as I know, i should use the paintComponent method from my JPanel only for drawing/painting my .png-files and NOT for recalculating the positions of my objects and detecting collisions between my projectiles, obstacles und my spaceship.
My question is:
How/where should i recalculate positions and detect collisions?
Should I use an extra Thread/Runnable, which will, as far as I know,
interfere with the Event Dispatch Thread?
Should I use a Swingworker, which is executed not only once but in an endless loop?
Or should I use something else i did not think about so far?
Thank You in advance for some suggestions, either where and what to read/recherche or what to use.
Cheers, max
I've been using a JPanel and overriding paintComponent() in order to perform my drawing in Swing games. I'm now trying to add an inventory, which will contain different items the player can drag around and move to different slots in his "backpack" on the screen. Should Swing games only draw on a single JPanel or other component (example: draw images of item at mouse location) or can you add JButtons whose icons are pictures of the items?
Should the game only have the one drawing component, or can you include more?
Principally, you can have any number of components that you want to have. Swing – as any other sufficently elaborate library such as SWT for Java or Qt and WxWidgets for C++ – is intelligent enough to draw to the screen only what actually really is necessary.
As long as you do not run into performance issues, there is no problem with that. If this actually happens, you might first want to look at your own paintComponent implementation as this is the most probable location where you lose efficiency.
I am currently making a path-laying Tile game in Java where I am using a JLayeredPane with multiple layers. The game runs fine, but everytime the repaint method is called, the entire pane flickers.
Right now I have the game running on a timer where every tick automatically moves the character one tile at a time along the path in which I have laid out. Naturally, I would need to update the screen in order to reflect the changes to the user, but the problem is that the repaint method forces a redraw on all layers of the LayeredPane. Every tick would cause a flicker on the map area of the screen. While it is bearable, I would just like to get rid of it so it looks nicer.
I have researched on the use of double buffering and have even set the option to double buffer the pane to true as well (e.g. pane.setDoubleBuffered(true)), but have had no luck with various implementations. Is there a way to just draw the entire pane with all layers for every tick in an outside buffer, then copy it in one go over to the main screen?
Thank you
I am making a game in Java. Basically, I have two different "planes" of updating that I need to take care of the. The base layer is the actual game painting itself. It is simply a JPanel that covers the entire JFrame, and is drawn to using its Graphics object.
I use a fixed timestep to take care of these first graphical updates. I have overwritten the paintComponent() method to do absolutely nothing, as I have written a custom render(float interpolation) method that takes care of that, as to prevent unwanted updates.
However, this panel can take no input beyond primitive mouse clicks and keyboard input. I need the ability to create various menus, text boxes, etc, that are also on the screen. Like various abilities, or even the "Menu" button that usually appears in the upper left corner of most games.
To take care of that input, such as creating buttons, I have a second JPanel that has setOpaque(false) applied to it. Then I create various Swing components that I might need, such as a JButton.
To contain the two JPanels, I use a JLayeredPane, and set their layers appropriately, as seen below. This way the input layer should always be on top of the actual game layer.
The code below shows how I create and add the Swing components to each other. addLoginDialog() is a method that adds a Swing component for the login. It has been tested and works properly, and isn't the problem.
private void initComponents()
{
//This code is inside of the JFrame
wholePane = new JLayeredPane();
add(wholePane);
guiPanel = new GUIPanel();
guiPanel.setOpaque(false);
gamePanel = new RPGPanel();
gamePanel.setOpaque(false);
wholePane.add(gamePanel, JLayeredPane.DEFAULT_LAYER);
wholePane.add(guiPanel, JLayeredPane.POPUP_LAYER);
guiPanel.addLoginDialog();
}
So when I run the code, I get horrible flickering. This is the code that is run from my fixed timestep ~60 times per second.
public void handleRepaint()
{
//I don't use repaint() for the game drawing so I can be sure that fps is controlled.
Graphics g = gamePanel.getGraphics();
gamePanel.render(g);
g.dispose();
wholePane.repaint();
}
The problem is, I think, that the two different systems of updating the screen are clashing. The standard paintComponent() system is great for more static screens, but when I need to update consistently and keep track of the fps, I can't have updates going off randomly.
However, for the input layer, I only want to update as Swing normally does. When the mouse moves over a button, when I component is moved or is resized, etc.
Also, note the way the screen flickers: The Background image goes blank and then comes back again repeatedly. The input panel is always there, but is actually painted behind the game drawing, which shouldn't happen, because it is put in the default layer. The reason I know it isn't completely disappearing is because the game painting is partially transparent, so I can see underneath it, and the buttons I added are still there.
My main question is, how can I stop the flickering? Why is the game drawing being drawn on top of the input components when the game drawing is being done on the Panel that is in a lower layer in the JLayeredPane? And I supposed most importantly, what is causing the flickering? Thank you for any help.
Why is the game drawing being drawn on top of the input components
when the game drawing is being done on the Panel that is in a lower
layer in the JLayeredPane?
Mostly because you've circumvented how Swing works.
Let's start with the fact that the Graphics context is a shared resource (typically there is a single Graphics context per native peer), that is, every component gets the same context, this means, when you use your own painting routine, you are basically painting over every thing else.
The RepaintManager is responsible for making decisions about what and when something should be painted. So what you now have is two artist fighting over the same canvas, wanting to paint on it simultaneously, which is just making a mess.
Add into the fray that Swing's painting process is not thread safe and you end up with a complete mess.
If you absolutely must have control, then you need to remove Swing's painting engine from the equation.
Start by taking a look at Passive vs. Active Rendering
ps- There is also hard ware acceleration benefits to using a BufferStrategy
I was building a simplistic "game" as sort of tutorial into developing apps or such in java.
My Main class extends JFrame. It was just moving a ball around the screen. After getting to the point where I can move the ball can move I started implementing collision with the boundaries of the window and spent several minutes trying to figure out why the only went some beyond the border on 3 sides and then far beyond the top before I realized that the boundaries were being obeyed but that they were the edges of the actual window, beyond the display area.
How would I set up the Main class so that the boundaries are the visible area? Would it extend a different class? And then what it be inside of something else?
It's hard to say what you may be doing wrong without code,
but for one thing, you should never be drawing directly in the JFrame and should avoid extending JFrame.
Instead extend JPanel, get it's boundaries, and draw in this JPanel.
Also, make sure to override the JPanel's paintComponent(...) method,
to also call the super.paintComponent(g) inside the override.
Put the JPanel into a JFrame for display.
Make sure to check out the Swing drawing tutorials before doing this coding because often you have to change basic assumptions when doing graphics program and especially animation programs.