0

I am currently making a "Hero" move around in eclipse by repainting it in an altered X coordinate if a key is pressed. This is working, however the movement is rough and even appears laggy. I would really appreciate any help / advice, the code looks long but it is really basic.

Code for the level

JFrame window = new JFrame("Level");
Hero hero = new Hero(0, 800);

public Level()
{
    this.setFocusable(true);
    this.addKeyListener(this);
    window.add(this);
    window.setSize(1400, 980);
    window.setLocation(40,20);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setVisible(true);
}

public void paint(Graphics g)
{
    try {
        Image i = ImageIO.read(getClass().getResource("/Sprites/Background.jpg"));
        g.drawImage(i, 0, 0, null);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    hero.drawHero(g);
}

@Override
public void keyPressed(KeyEvent kp) 
{
    if(kp.getKeyCode()==KeyEvent.VK_RIGHT)
    {
            hero.setxAxis(hero.getxAxis()+5);
            this.repaint();
    }
    if(kp.getKeyCode()==KeyEvent.VK_LEFT)
    {
            hero.setxAxis(hero.getxAxis()-5);
            this.repaint();
    }
}

Code for the hero

public class Hero {
int xAxis;
int yAxis;
Image heroImage;
public Hero(int xAxis, int yAxis)
{
    super();
    this.xAxis = xAxis;
    this.yAxis = yAxis;
    try {
        heroImage = ImageIO.read(getClass().getResource("/Sprites/Pic1.png"));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public int getxAxis() {
    return xAxis;
}

public void setxAxis(int xAxis) {
    this.xAxis = xAxis;
}

public int getyAxis() {
    return yAxis;
}

public void setyAxis(int yAxis) {
    this.yAxis = yAxis;
}

public void drawHero(Graphics g) {
    g.drawImage(heroImage, xAxis, yAxis, null);
}

}

cwsl26
  • 33
  • 6
  • Are you running the GUI on the Event Dispatch Thread (EDT)? If not, expect trouble. – Lew Bloch May 10 '17 at 19:45
  • No i'm not. Could you explain how to do this? @LewBloch – cwsl26 May 10 '17 at 19:52
  • And where i would use it? @LewBloch Thank you by the way. – cwsl26 May 10 '17 at 19:55
  • Read the Fine Manual! http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html Also, consider doing some research on your own, e.g., use a search engine. You cannot learn programming from SO! You must develop the habit and skill of doing your own homework. – Lew Bloch May 10 '17 at 19:57
  • 2
    Don't load resources in the paint method; prefer paintComponent over paint; call super.paintXxx before doing any custom painting; prefer key bindings over KeyListener – MadProgrammer May 10 '17 at 20:28
  • @MadProgrammer I tried everything everyone else said before you and it didn't work. Tried the first two things you said and instantly it runs 1000% smoother. Thanks! – cwsl26 May 10 '17 at 20:58
  • Apparently not everything everyone else said. Had you read the referenced tutorial, for example, you'd've learned to load resources off the EDT. – Lew Bloch May 10 '17 at 21:12
  • I tried it, it ran smoother but still not how i wanted it. – cwsl26 May 10 '17 at 21:13

2 Answers2

0

Try with Double or Triple buffering Check this out! How do you double buffer in java for a game?

More info from Wiki: In computer graphics, double buffering is a technique for drawing graphics that shows no (or less) stutter, tearing, and other artifacts.

It is difficult for a program to draw a display so that pixels do not change more than once. For instance, when updating a page of text, it is much easier to clear the entire page and then draw the letters than to somehow erase all the pixels that are not in both the old and new letters. However, this intermediate image is seen by the user as flickering. In addition, computer monitors constantly redraw the visible video page (at around 60 times a second), so even a perfect update may be visible momentarily as a horizontal divider between the "new" image and the un-redrawn "old" image, known as tearing.

https://en.wikipedia.org/wiki/Multiple_buffering#Double_buffering_in_computer_graphics

Community
  • 1
  • 1
Gastón Corti
  • 51
  • 1
  • 6
  • 1
    Swing it self, when used correctly is double buffeted by default – MadProgrammer May 10 '17 at 20:26
  • I didn't see BufferStrategy in the code provided. Does swing use it "behind the curtain"? i think not. – Gastón Corti May 11 '17 at 12:15
  • Yes, Swing use an internal buffer to paint all the child components, has done since it was created, this is why you can do animation in Swing without using any type of double buffering unlike AWT – MadProgrammer May 11 '17 at 19:52
  • You can look straight at the [JavaDocs](https://docs.oracle.com/javase/8/docs/api/javax/swing/JPanel.html) - *"Creates a new JPanel with a double buffer and a flow layout."*. There's a bunch of other methods which you can use to turn it on and off as well – MadProgrammer May 11 '17 at 19:54
0

Start by taking a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works and how you can intergarte with it.

Painting in Swing uses a passive rendering algorithm, this means that a paint cycle can occur at any time for any number of reasons many without your control or knowledge.

This means that paint can be called at any time. Painting should be done as quickly as possible, so as not to degrade the performance of the application.

To this end, you should not be loading resources, making overly complex logical decisions or updating the state from within the paint methods.

Start by loading the image somewhere else, maybe in the constructor as an example.

Painting is a complex series of chained method calls (the "paint chain") which easily broken, which leads to all sorts of weirdness. As a general recommendation, it's recommend to override paintComponent to perform your custom painting, you should also call super.paintComponent in order to maintain the original "paint chain"

I'd also recommend using the Key Bindings API over KeyListener, apart from providing a more flexible and re-usable solution, it also solves the focus related issues of the KeyListener

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366