JPanel.removeAll() not functioning properly - java

So I'm currently teaching myself to use GUI, and I decided to go back to the code for a game of Go Fish that I created and add in a GUI to it. For the panel that holds the CPU Player's cards, it displays the back of some playing cards to indicate the size of the CPU's hand.
Whenever a change occurs in the CPU's hand size, my method updateComputerCards gets called to adjust the amount of cards appearing on the screen. It does this by calling the removeAll() method for my panel, and then proceeds to re-add the proper amount of card images.
My issue though, is that when the game first begins, and matches are found within the CPU's hand, the method works as intended, and the amount of cards appearing shrinks. However, every subsequent time that the method is called, nothing changes in the GUI despite the CPU having a hand of cards of a different size.
Through the debugger I can see that the removeAll() method is not removing all the components on the panel for some reason, even though it succeeds in doing so without issue the first time it is called. Can anyone help me out here?
public void updateComputerCards(ArrayList<Integer> hand) {
labelPanel.removeAll();
for (int i = 0; i < hand.size(); i++) {
labelPanel.add(computerCardLabels.get(i));
labelPanel.add(b.createHorizontalStrut(10));
}
}

You need to call the repaint() method after making the changes.
See Painting in AWT and Swing.

Related

Java: Drawing grid to screen using 2D Array without lag/screen flickering

I am attempting to create a very simple top-down game in Java, but I am unsure how to approach a problem dealing with program performance.
I used a 2D array to store certain values that represent certain things, such as the surrounding environment and the player's position. I then used the paint() method to draw a grid to the screen based on a section of the 2D array. The player is always in the center of the grid. I have it coded such that the player never truly "moves", but rather the environment around him "moves" (if you press a key to move up, a new section of the array is drawn that is the same as the past section except it has a new row at the top and the bottom-most row is now the past section's second-to-bottom row, all the while the player stays in the center, if that makes sense).
Thus, we have a situation where the whole screen needs to be redrawn each time the player moves. As you might have gathered, this is bad for the program's performance, since it has to iterate through a 2D array and draw it the screen each time I call repaint(). If the user hits the key to move upwards twice in succession, the program will lag and the screen will flicker as it redraws the whole section of the array.
How can I improve the performance issue, given that I want to keep the player in the center of the screen at all times and have the environment move around him? Should I instead investigate Jscrollpanes? Is iterating through arrays in the paint() method not the way to go?
Thank you so much for both your time and also helping an inexperienced programmer.

How should I draw and move my Java Pacman

I need some help with a Java assignment I have, I'm required to build a clone of Pac-Man.
The problem is, I don't know how to draw the movements of the Pac-Man or the Ghosts. I'm thinking I should only draw the walls once, and continiously redraw the characters, but I don't know how I should do it or what methods of drawing I should use.
Generally speaking, it is no good idea not to redraw the complete GUI of any game you write several times each second (the quotient of complete redraws over a second is referred to as the 'frame-rate' of a game). If you do not do this, you might observe weird effects like: The contents look strange if you resize or move the window in case its not displayed in full-screen, there might by weird graphical effects, and, most important, the images of your game-characters won't disappear at their previous positions, if you do not draw the background over them again.
Common approach is to set up a Thread that is not doing anything else but invoking some redraw methods about 60 times each second (60 fps (frames per second) appear fluent to the human eye as our temporal resolution lies in that scale) and to use another Thread that updates the position data of the characters and passes it to the draw-Thread together with the static wall-position-data.

Is there a way to continue to add graphics on a JPanel without having to redoing present graphics (ie. using the repaint() method)?

I've currently rewritten paintComponent() to paint three dots on my JPanel when the program begins to run. Each time the user presses a button I would like to add another dot. I understand I can keep a list of objects as a field and have paintComponent() iterate through that and paint each object, but I plan to have 1000s of iterations (this is the Chaos Game) and iterating through a large list each time I repaint can get costly in terms of time. I would like to avoid this. Any suggestions?

How to get mouse position and buffer?

How do I get the mouse position. I have tried:
int mouseX = MouseInfo.getPointerInfo().getLocation().x;
int mouseY = MouseInfo.getPointerInfo().getLocation().y;
But that does it for the whole screen. Anyway to do it relative to the JPanel/JFrame
If I'm only using Graphics JFrame and JPanel that is being repainted every millisecond, should I have buffers? Or will it be fine?
How do I add a mouseAcionEvent only to the frame so it gets X() and Y() of mouse but only in frame?
Use a MouseListener instead of MouseInfo. MouseListener will trigger events which are contextual to the component which raised them, which means you won't need to translate the events into the component space as the event will already be converted to within the component context.
See How to write a mouse listener for more details
How should I update my game rePaint() every millisecond or another way?
Use a javax.swing.Timer...
See How to use Swing Timers for more details...
Should I use buffers?
That will depend. Swing components are already double buffered, but if you use a more complex timing mechanism (AKA game loop), you might find it useful, even to roll your own.
I, personally, would start simple
How can I improve the way I thought out my code in the first place? Is it right having 10 loops or only all in 1 to reduce lag ect.
There are probably lots of things, but start with broader idea...
Breakdown entities to their own responsibilities, for example, the player should know where it is and how it should be painted. It could even know how it's suppose to move based on the current state of the game. This way you could create any number of entities, all with there own set of rules which are isolated and easily updated.
Devise a controller mechanism which is responsible for taking in keyboard and mouse events and simply updating the current state of the game model. That is, rather than going "the user pressed the 'left' key, move player to the left", it would simply raise a flag in the game model that the "left" state has been triggered (or untriggered) and the engine would, on the next update loop, ensure that each entity knew about the change
Don't use magic or hard coded numbers, instead provide some kind of ability to scale the scene. For example, you could decide what is shown on the screen based on the size of the window...

Java Repaint method creates new objects on top of old ones

This is probably a stupid question but I can not seem to either remember how to stop the program from doing this or I never learned it.
I'm creating a blackjack game which draws random cards with the paintComponent. When the hit button is clicked, I want it to draw the next card and generate the new total. However, whenever I click the hit button, it draws the new card perfect, but it then creates all new cards on top of my already drawn cards.
How do I stop the repaint method from picking new random cards and keep them the same throughout the program? I should mention, all the cards are stored in an array and are called to with a random number generator. Also, this happens when I resize the java window.
If asked, I will post the code but I feel like this has a simple solution.
You will need to move your 'select random card' logic outside of the paint method.
It might be a better idea to calculate all the cards in your array when you first build it, rather than selecting randomly at paint time. In other words, when you create the 'deck' array, build the entire deck so that every card knows what they are, before the user even begins to be dealt any cards from the deck. This way, there is no risk of them changing during gameplay. If you're only talking about 52 cards, or a small multiple of 52 cards, then the array is still pretty small and it'll be quick to randomise the entire array.
Alternatively, you could put a check on your "select random card" method that says something like this...
int cardValue = -1;
paintComponent(){
if (cardValue == -1){
cardValue = drawRandomCard();
}
// now paint it.
}
ie - restrict the drawRandomCard() to only run if the card doesn't already have a value.
Ultimately though, the best solution would be to completely separate the painting code from the logic - its bad coding practice for GUI activities like painting to be mixed in with programming logic.

Categories

Resources