Okay, so you problem isn't so much the timer, it's an understanding how an animation might be achieved.
- Animation is a change of state over time
- A
Timer
is a pseudo loop which has a specified delay between iterations
Okay, so how does this help? Well, basically, you need to craft a concept of an object moving from it's current position, to a new position and back again (jump up and down)
This is where your Timer
come in. The Timer
provides the delay between one state and the next, which should be long enough for the user to perceive
This is a really basic example, but it demonstrates the basic principle. The key binding Action
isn't responsible for changing the position, it is responsible for changing a state which is then acted upon by the Timer
. Why? Imagine now you have other key bindings (left and right), they shouldn't be changing the state of the objects, as those changes could conflict. Instead, they set a state flag, which is then used to determine what should occur as the state is updated.
The object has a yPos
and can be acted upon by a change value (yDelta
) which affects what change is actually applied to the object. While jump
is true
, the object is moved to it's top most height and moved back down again. Once it completes this cycle, the jump
state is reset, this means that you can't keep pressing Space to perform multiple jumps in the air ... cause that's impossible ;)
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) throws IOException {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int yPos = 200;
private int yDelta = -1;
private boolean jump = false;
public TestPane() {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "space");
am.put("space", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
jump = true;
}
});
Timer timer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (jump) {
if (yPos > 200) {
yPos = 200;
yDelta *= -1;
jump = false;
} else if (yPos < 150) {
yPos = 150;
yDelta *= -1;
} else {
yPos += yDelta;
}
repaint();
}
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - 5) / 2;
g2d.fillRect(x, yPos - 10, 10, 10);
g2d.dispose();
}
}
}
Lots of boring theory
TL;DR
Now, this is an overly simplified example, it doesn't discuss things like framerates, easements or gravity to name a few things. You could have a look at this example which demonstrates the concept of a variable delta which degrades over a time, applying a (very basic) concept of gravity.
There are other ways to achieve similar results, depending on what you want to do, but they revolve around the same concept.
If you're really brave, you could have a look at How can I implement easing functions with a thread which discuess (rather poorly IMHO) the concept of easement - or variable speed animation. You could also have a look at Java image move along points in list and use linear interpolation which talks more about variable animation paths - where t
(time) is variable, which allows you to calculate a value for you animation based on how long it's been playing and how long you would like it to play.
If you're wondering why I'd mention it - it's because you can do things like this which greatly expands what you can do.
But, at the heart of all these things, is a Timer