Reputation: 295
So I am trying to make the popular game pong in java. I've made the player rectangle and setup the action listener so I am ready to move the player up and down on the screen. But I have run into a problem. When I am moving the player I have a choice of moving X pixels per move.
But if I set the X pixels being moved to lets say 1. Then the player is moving too slow. If I set X pixels to 10 then he skips 9 pixels and the animation looks rough. How can I smoothen the animation and still move fast?
here is some code:
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == keyUp){
playerYCordinate -= 10;
}else if(e.getKeyCode() == keyDown){
playerYCordinate += 10;
}
repaint();
}
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == keyUp){
}else if(e.getKeyCode() == keyDown){
}
repaint();
}
Upvotes: 4
Views: 1880
Reputation: 18435
In gaming it is traditional to use a game loop to control the application, rather than the event driven system that drives Swing.
You could have a variable that stores paddle movement, say an enum with UP
, DOWN
and STATIONARY
. Your key listener would set the value of this variable and then the game loop will check the variable and update the position of the paddle accordingly.
This technique decouples the speed of the application with the speed of the environment it runs on.
Upvotes: 2
Reputation: 109815
don't use KeyListener
for Swing JComponents
use KeyBinding for Swing JComponents
don't paint to the JFrame
put there JPanel
and use method paintComponent()
instead of paint()
, your movement will be smooth and natural
Upvotes: 1
Reputation: 168825
How can I smoothen the animation and still move fast?
One technique is to paint semi-transparent versions of the moving object along the path it would have taken if stepping less pixels per move.
E.G. for a 10 pixel move, draw a version at 10% opacity for the 1st pixel of moving, 20% for the 2nd etc.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MovingBlock {
MovingBlock() {
final JPanel gui = new JPanel() {
private static final long serialVersionUID = 1L;
int x = 0;
int step = 60;
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
x+=10;
Color fg = getForeground();
for (int ii=x-step; ii<x; ii+=4) {
double transparency = (double)(x-ii)/(double)step;
Color now = new Color(
fg.getRed(),
fg.getGreen(),
fg.getBlue(),
(int)(255*(1-transparency)));
g2.setColor(now);
g2.fillRect(ii, 3, 5, 10);
}
if (x>getWidth()) {
x=0;
}
}
};
gui.setBackground(Color.BLACK);
gui.setForeground(Color.GREEN.darker());
gui.setPreferredSize(new Dimension(400,16));
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
gui.repaint();
}
};
Timer timer = new Timer(20, listener);
timer.start();
JFrame f = new JFrame("Moving Block");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setContentPane(gui);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new MovingBlock();
}
});
}
}
Upvotes: 2
Reputation: 14336
As long as you depend on key presses to control your rectangles, you can only move as fast as the keyrepeat events come in (or as fast as the user can type). Either listen to something else like a mouse move, or configure your keyboard for a higher repeat rate.
Upvotes: 0
Reputation: 420951
Don't rely on key-repeat features provided by the system. They may occur with a low rate (which causes the problems you describe) and depend on system keyboard settings.
I recommend you to use keyPressed
to start a Timer
and keyReleased
to stop it.
The timer could schedule to execute a TimerTask
every 20:th millisecond or so, which could update the coordinates and call repaint()
. (Don't worry about calling repaint()
too often. If the EDT can't keep up, it will collapse consecutive calls to repaint into a single paint.)
Upvotes: 4