4

所以我正在尝试用java制作流行的游戏乒乓球。我已经制作了播放器矩形并设置了动作监听器,因此我准备好在屏幕上上下移动播放器。但是我遇到了一个问题。当我移动玩家时,我可以选择每次移动 X 像素。

但是,如果我将要移动的 X 像素设置为 1。那么玩家移动得太慢了。如果我将 X 像素设置为 10,那么他会跳过 9 像素,动画看起来很粗糙。我怎样才能平滑动画并仍然快速移动?

这是一些代码:

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();
            }
4

5 回答 5

4

不要依赖系统提供的键重复功能。它们可能以低速率发生(这会导致您描述的问题)并且取决于系统键盘设置。

我建议您使用keyPressed来启动TimerkeyReleased停止它。

计时器可以安排TimerTask每 20:th 毫秒左右执行一次,这可以更新坐标并调用repaint(). (不要担心调用repaint()太频繁。如果 EDT 跟不上,它会将连续调用重绘为单个绘制。)

于 2012-06-11T09:38:50.420 回答
2

我怎样才能平滑动画并仍然快速移动?

一种技术是沿着移动对象的路径绘制半透明版本的移动对象,如果每次移动的像素更少。

EG 用于 10 像素的移动,以 10% 的不透明度为移动的第一个像素绘制一个版本,第二个移动的像素为 20%,以此类推。

移动块

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();
            }
        });
    }
}
于 2012-06-11T09:37:54.760 回答
2

在游戏中,传统上使用游戏循环来控制应用程序,而不是驱动 Swing 的事件驱动系统。

你可以有一个存储桨运动的变量,比如一个带有UP,DOWN和的枚举STATIONARY。您的关键监听器将设置此变量的值,然后游戏循环将检查该变量并相应地更新桨的位置。

这种技术将应用程序的速度与其运行环境的速度解耦。

于 2012-06-11T10:25:21.800 回答
1
  • 不要KeyListener用于Swing JComponents

  • 使用KeyBinding _Swing JComponents

  • 不要画到JFrame那里JPanel,用方法paintComponent()代替paint(),你的动作会流畅自然

于 2012-06-11T10:25:06.793 回答
0

只要您依靠按键来控制矩形,您就只能在 keyrepeat 事件进入时(或用户可以键入的速度)移动。要么听听鼠标移动之类的其他声音,要么将键盘配置为更高的重复率。

于 2012-06-11T09:39:34.023 回答