I am trying to get a simple animation done smoothly in Java using Timer
class, i.e. to move a target
from its current position to the farthest end-of-frame horizontally.
I have used the graphics component's current position inside the Timer
class's actionPerformed()
method and have been increasing the x
location of the component by a certain amount but when I try to run it the component instantly jumps to the next location and waits for the timer to complete and repaint to a new location. (I apologize if I am not phrasing the problem properly.)
I have included the code as a whole so as to provide the entire context:
public class FireAtBill extends JPanel {
private static final long serialVersionUID = 4682094035006759518L;
private int hits, misses;
private Point targetPos;
private Timer t;
private BufferedImage crosshair, target;
public FireAtBill() {
Random random = new Random();
targetPos = new Point(random.nextInt(500),random.nextInt(500) );
t = new Timer(500, new TimerListener());
t.start();
setForeground(Color.WHITE);
setBackground(Color.BLACK);
try {
crosshair = ImageIO.read(new File(System.getProperty("user.dir")+ "/crosshair.jpg"));
target = ImageIO.read(new File(System.getProperty("user.dir")+ "/target.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawString("hits: " + hits + " misses: " + misses, 0, 10);
g2.drawImage(crosshair, 125, 50, this);
g2.drawImage(target, targetPos.x, targetPos.y, this);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Fire At Bill");
frame.setSize(500,500 );
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FireAtBill fireAtBill = new FireAtBill();
frame.getContentPane().add(fireAtBill);
frame.setVisible(true);
}
private class TimerListener implements ActionListener{
double x = targetPos.getX();
public void actionPerformed(ActionEvent event) {
if (x <= 500||targetPos.getX() >= 0) {
if (x<250) {
targetPos.setLocation(targetPos.getX()+15, targetPos.getY());
}
else {
targetPos.setLocation(targetPos.getX()-15, targetPos.getY());
}
}
repaint();
}
}
}
I expect the target
to move smoothly across the screen horizontally, but the target
is jumping from one location to another.
I have tried to increment the x
position of the target
using smaller values and while this smooths out the movement, it does so at the cost of the speed of the target
which I hope to implement as a variable which can be altered by changing its value.
Thanks in advance.
Okay, I found that by decreasing the delay value when initializing the Timer
object I can speed up the repaint process here t = new Timer(500, new TimerListener());
by changing 500
to something like 50
. Decreasing this value will speed up the animation.
And the smoothing can be implemented by decreasing the increment value inside the actionPerformed()
method of the TimeListener
class here targetPos.setLocation(targetPos.getX()+15, targetPos.getY());
by changing the increment value 15
to something like 3
. Decreasing this value will help smooth the animation.