Thobias Nordgaard
Thobias Nordgaard

Reputation: 295

Java moving rectangle faster?

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

Answers (5)

Qwerky
Qwerky

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

mKorbel
mKorbel

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

Andrew Thompson
Andrew Thompson

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.

Moving Block

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

Kilian Foth
Kilian Foth

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

aioobe
aioobe

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

Related Questions