Reputation: 100
I'm trying to build a 2d game.
I have a background-image that static and an Image of the character. When i press a move-key (WASD) the Mainclass (were the keylistener is) calling a function in a class called Player The function is changing the location of the character (Image). And after this function is called i use repaint() to repaint the character on new position. If i remove the background i can see the old images still left from the other positions. So this meens i have to repaint the player and the background for each step.
There might be a better solution for this? Worst case scenario: It's an onlinegame and there are many players moving around and each 100 milliseconds the repaint is called for update every players posisions. I have a feeling this will take out all the memory of the players computer or at least the game will not feel so good
Upvotes: 1
Views: 8038
Reputation: 324118
(i used a jpanel inside the jframe) and use bufferedimage of java.awt.image
Instead you can try using a JLabel with Icons. Then all you do is invoke the setLocation(...)
method of the label. The Swing RepaintManager will look after repainting the old location and the new location.
Here's an example to get you started. This example uses separate Timers for each image. In your game you would reset the location of all images at the same time when your single Timer fires.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class AnimationBackground extends JLabel implements ActionListener
{
int deltaX = 2;
int deltaY = 3;
int directionX = 1;
int directionY = 1;
public AnimationBackground(
int startX, int startY,
int deltaX, int deltaY,
int directionX, int directionY,
int delay)
{
this.deltaX = deltaX;
this.deltaY = deltaY;
this.directionX = directionX;
this.directionY = directionY;
setIcon( new ImageIcon("dukewavered.gif") );
setSize( getPreferredSize() );
setLocation(startX, startY);
new javax.swing.Timer(delay, this).start();
}
public void actionPerformed(ActionEvent e)
{
Container parent = getParent();
// Determine next X position
int nextX = getLocation().x + (deltaX * directionX);
if (nextX < 0)
{
nextX = 0;
directionX *= -1;
}
if ( nextX + getSize().width > parent.getSize().width)
{
nextX = parent.getSize().width - getSize().width;
directionX *= -1;
}
// Determine next Y position
int nextY = getLocation().y + (deltaY * directionY);
if (nextY < 0)
{
nextY = 0;
directionY *= -1;
}
if ( nextY + getSize().height > parent.getSize().height)
{
nextY = parent.getSize().height - getSize().height;
directionY *= -1;
}
// Move the label
setLocation(nextX, nextY);
}
public static void main(String[] args)
{
JPanel panel = new JPanel(null)
{
Image image = new ImageIcon("mong.jpg").getImage();
protected void paintComponent(Graphics g)
{
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
super.paintComponent(g);
}
};
panel.setOpaque(false);
// panel.add( new AnimationBackground(10, 10, 2, 3, 1, 1, 10) );
panel.add( new AnimationBackground(300, 100, 3, 2, -1, 1, 20) );
panel.add( new AnimationBackground(200, 200, 2, 3, 1, -1, 20) );
panel.add( new AnimationBackground(50, 50, 5, 5, -1, -1, 20) );
// panel.add( new AnimationBackground(0, 000, 5, 0, 1, 1, 20) );
panel.add( new AnimationBackground(0, 200, 5, 0, 1, 1, 80) );
JFrame frame = new JFrame();
frame.setContentPane(panel);
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setSize(400, 400);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
You will need to provide a background image and an image for the label where the code creates an ImageIcon.
Upvotes: 1
Reputation: 5326
There is efficient to redraw only part of your component. Read this tutorial.
Basically you have to call component.repaint(posX, posY, length, height)
twice:
once at he old player image position (will repaint the background) and then at the new position.
(This solution was also proposed by G_H in the comments.)
Upvotes: 0
Reputation: 205785
Don't paint directly in the JFrame
content pane. Instead, override paintComponent()
in a JComponent
. This AnimationTest
draws into a JPanel
, which is double buffered by default. The example also shows one approach to examining the time budget devoted to painting.
Upvotes: 4
Reputation: 96
I think repaint is the only solution, I once created a 2d car simulation game and that's what i do, I also change the coordinates of all Car objects and then repaint the whole thing. I tried to simulate 2000 Car objects running at 100 ms repaint on all of them without trouble. hehe fun
Upvotes: 2
Reputation: 44808
As far as I know, there is no other solution. Repainting every 100 ms generally isn't too memory intensive on most computers.
Upvotes: 2