1

I'm trying to create a moving sprite in java, which I have managed to do, except every time I move it there is an afterimage that follows the sprite. Are there any ways I could easily fix this problem without radically changing my code?

I'm completely stumped as to any kind of ways I could fix this problem.

To get the full context I have to post all three files.

Here's the first file:

package gameproject;

import java.awt.Image;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;

public class CarMovement {

private int dx;
private int dy;
private int x = 635;
private int y = 550;
private int w;
private int h;
private Image moveimage;

public CarMovement() {

    loadImage();
}

private void loadImage() {

    ImageIcon q = new ImageIcon("racecar.png");
    moveimage = q.getImage(); 

    w = moveimage.getWidth(null);
    h = moveimage.getHeight(null);
}

public void move() {

    x += dx;
    y += dy;
}

public int getX() {

    return x;
}

public int getY() {

    return y;
}

public int getWidth() {

    return w;
}

public int getHeight() {

    return h;
}    

public Image getImage() {

    return moveimage;
}

public void keyPressed(KeyEvent e) {

    int key = e.getKeyCode();

    if (key == KeyEvent.VK_A) {
        dx = -10;
    }

    if (key == KeyEvent.VK_D) {
        dx = 10;
    }

    if (key == KeyEvent.VK_W) {
        dy = -10;
    }

    if (key == KeyEvent.VK_S) {
        dy = 10;
    }
}

public void keyReleased(KeyEvent e) {

    int key = e.getKeyCode();

    if (key == KeyEvent.VK_A) {
        dx = 0;
    }

    if (key == KeyEvent.VK_D) {
        dx = 0;
    }

    if (key == KeyEvent.VK_W) {
        dy = 0;
    }

    if (key == KeyEvent.VK_S) {
        dy = 0;
    }
}
}

The second:

 package gameproject;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
import javax.swing.Timer;

public class CarMovement2 extends JPanel implements ActionListener {

private Timer timer;
private CarMovement racecar;
private final int DELAY = 10;

public CarMovement2() {

    initBoard();
}

private void initBoard() {

    addKeyListener(new TAdapter());
    setBackground(Color.black);
setFocusable(true);

    racecar = new CarMovement();

    timer = new Timer(DELAY, this);
    timer.start();
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(new Color(0, 204, 0));
    g.fillRect(0, 0, 400, 1100);
    g.fillRect(1525, 0, 400, 1100);
    g.setColor(new Color(102, 102, 102));
    g.fillRect(400, 0, 1125, 1100);
    g.setColor(new Color(255, 255, 255));
    g.fillRect(940, 25, 25, 100);
    g.fillRect(940, 325, 25, 100);
    g.fillRect(940, 475, 25, 100);
    g.fillRect(940, 625, 25, 100);
    g.fillRect(940, 775, 25, 100);
    g.fillRect(940, 925, 25, 100);
    g.setColor(new Color(255, 255, 255));
    g.fillRect(400, 175, 1125, 100);
    g.setColor(new Color(0, 0, 0));
    g.fillRect(400, 225, 50, 50);
    g.fillRect(450, 175, 50, 50);
    g.fillRect(500, 225, 50, 50);
    g.fillRect(550, 175, 50, 50);
    g.fillRect(600, 225, 50, 50);
    g.fillRect(650, 175, 50, 50);
    g.fillRect(700, 225, 50, 50);
    g.fillRect(750, 175, 50, 50);
    g.fillRect(800, 225, 50, 50);
    g.fillRect(850, 175, 50, 50);
    g.fillRect(900, 225, 50, 50);
    g.fillRect(950, 175, 50, 50);
    g.fillRect(1000, 225, 50, 50);
    g.fillRect(1050, 175, 50, 50);
    g.fillRect(1100, 225, 50, 50);
    g.fillRect(1150, 175, 50, 50);
    g.fillRect(1200, 225, 50, 50);
    g.fillRect(1250, 175, 50, 50);
    g.fillRect(1300, 225, 50, 50);
    g.fillRect(1350, 175, 50, 50);
    g.fillRect(1400, 225, 50, 50);
    g.fillRect(1450, 175, 50, 50);
    g.fillRect(1500, 225, 25, 50);
    g.setColor(new Color(255, 255, 255));
    g.fillRect(380, 0, 20, 1100);
    g.fillRect(1525, 0, 20, 1100);
    doDrawing(g);

    Toolkit.getDefaultToolkit().sync();
}

private void doDrawing(Graphics g) {

    Graphics2D g2d = (Graphics2D) g;

    g2d.drawImage(racecar.getImage(), racecar.getX(), 
        racecar.getY(), this);
}

@Override
public void actionPerformed(ActionEvent e) {

    step();
}

private void step() {

    racecar.move();

    repaint(racecar.getX()-1, racecar.getY()-1, 
            racecar.getWidth()+2, racecar.getHeight()+2);
}    

private class TAdapter extends KeyAdapter {

    @Override
    public void keyReleased(KeyEvent e) {
        racecar.keyReleased(e);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        racecar.keyPressed(e);
    }
}
}

The third:

package gameproject;


import java.awt.EventQueue;
import javax.swing.JFrame;
public final class CarMovement3 extends JFrame {

 public CarMovement3() {

    InitUI();
}

private void InitUI() {

    add(new CarMovement2());

    setTitle("Top Speed Triumph");
    setSize(1900, 1100);
    setResizable(false);

    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public static void main(String[] args) {

    EventQueue.invokeLater(() -> {
        CarMovement3 ex = new CarMovement3();
        ex.setVisible(true);
    });
}


}

And the link to the sprite : http://www.clker.com/clipart-red-sports-car-top-view.html

Evan
  • 11
  • 1

1 Answers1

0

So, your problem stems from using...

repaint(racecar.getX() - 1, racecar.getY() - 1,
        racecar.getWidth() + 2, racecar.getHeight() + 2);

Basically, you're not covering enough of the "existing" area that use to occupy to completely "remove" it.

You can simply use repaint() instead and it will solve your basic problem. I'd avoid worrying about this level of optimisation until it actually becomes a problem.

If you want to use it, then I would take a snap shot of the location of the care before it was moved (ie grab it's current x/y position) and merge that with it's new location so you cover both areas. That, or call repaint(x, y, width, height) twice, once with the old position and once with the new

private void step() {
    Rectangle old = new Rectangle(racecar.getX(), racecar.getY(), racecar.getWidth(), racecar.getHeight());

    racecar.move();

    Rectangle now = new Rectangle(racecar.getX(), racecar.getY(), racecar.getWidth(), racecar.getHeight());

    repaint(old);
    repaint(now);
}

Also, you'll find that KeyListener is unreliable, I would suggest making use of the key bindings API which will solve the issues which KeyListener suffers from

I would also recommend using ImageIO over ImageIcon as more reliable way of loading your images, see Reading/Loading an Image for more details

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366