逐步加快精灵(Gradually speeding a sprite)

2019-09-15 03:39发布

我试图让逐渐精灵加速按下按钮,而不是只动恒定的速度。 也创下了最高速度的限制。 我希望你明白我的意思。

timer = new Timer(5, this);
timer.start();

public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D)g;
    g2d.drawImage(image, x, y, this); //x,y = position
    Toolkit.getDefaultToolkit().sync();
    g.dispose();
}

private class TAdapter extends KeyAdapter { 
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_LEFT) {
            dx = -1;
        }
        if (key == KeyEvent.VK_RIGHT) {
            dx = 1;
        }
        if (key == KeyEvent.VK_UP) {
            dy = -1;
        }
        if (key == KeyEvent.VK_DOWN) {
            dy = 1;
        }
    }
}   
    public void actionPerformed(ActionEvent e) {
        x += dx;   
        y += dy;
        repaint();  
    }

Answer 1:

有几件事情(最初)不对您的示例代码...

  1. 您正在覆盖paint方法。 这是建议你重写paintComponent方法来代替。 如果您正在覆盖的paint顶层容器的方法,比如JFrame ,那么建议您不要。 相反,使用类似JPanel作为您的自定义绘画的基础...
  2. 您要处理的的Graphics是过去你上下文。 这是非常危险的,因为这将防止任何从被涂东西。 该Graphics上下文是一个共享资源,需要将使用相同的接收重绘周期内被更新的一切Graphics上下文。
  3. 您正在使用KeyListenerKeyListener来自焦点问题受到影响。 这可以很容易地通过使用的补救键绑定 API。 键绑定也更加灵活,因为他们从动作中独立的物理按键,使您能以不同的按键动作毫不费力的基本操作(如使用按钮)关联和/或重新使用。

所以。 对于你的问题。 你得知道...

  • 目前的速度...
  • 允许的最小速度...
  • 最大允许速度...

你也想保持你改变对象的当前位置。

这个例子没有实际移动“玩家”这么多,因为它移动的背景。 背景位置由改变xDelta ,这是变化的速度...

import java.awt.BorderLayout;
import java.awt.Color;
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.awt.image.BufferedImage;
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 TestSpeed {

    public static void main(String[] args) {
        new TestSpeed();
    }

    public TestSpeed() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class TestPane extends JPanel {

        private BufferedImage background;
        // The current position of the background
        private int xPos = 0;
        // The speed/delta that the xPos is changed...
        private int xDelta = 0;

        public TestPane() {
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (xPos < -(getWidth())) {
                        xPos = 0;
                    }
                    xPos -= xDelta;
                    repaint();
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();
            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "slower");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "faster");

            ActionMap am = getActionMap();
            am.put("slower", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    setSpeed(-1);
                }
            });
            am.put("faster", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    setSpeed(1);
                }
            });
        }

        protected void setSpeed(int delta) {
            xDelta += delta;
            // Check the change in speed to ensure it's within the appropriate range
            if (xDelta < 0) {
                xDelta = 0;
            } else if (xDelta > 9) {
                xDelta = 9;
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        public void invalidate() {
            background = null;
            super.invalidate();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            int x = xPos;
            g.setColor(Color.DARK_GRAY);
            while (x < getWidth()) {
                g.drawLine(x, 0, x, getHeight());
                x += 15;
            }

            int width = getWidth();
            int height = getHeight();
            x = (width / 2) - 5;
            int y = (height / 2) - 5;
            g.setColor(Color.RED);
            g.fillOval(x, y, 10, 10);
        }        
    }    
}


Answer 2:

您需要定义和存储的值最大速度,实际速度和速度递增。 定义的速度递增,而应该首先尝试最简单的办法,就是定义一个恒定的速度递增。 根据所提供的代码:

int maxspeed = 5;
int speed = 1;
int acceleration = 1;

timer = new Timer(5, this);
timer.start();

public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D)g;
    g2d.drawImage(image, x, y, this); //x,y = position
    Toolkit.getDefaultToolkit().sync();
    g.dispose();
}

private class TAdapter extends KeyAdapter { 
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_LEFT) {
            dx = -acceleration;
        }
        if (key == KeyEvent.VK_RIGHT) {
            dx = acceleration;
        }
        if (key == KeyEvent.VK_UP) {
            dy = -acceleration;
        }
        if (key == KeyEvent.VK_DOWN) {
            dy = acceleration;
        }
    }
}

public void actionPerformed(ActionEvent e) {
    if (speed < maxspeed) {
        speed += acceleration;
    }
    x += dx * speed;   
    y += dy * speed;
    repaint();  
}

正如我真的不知道这个问题,还是目标实现的情况下,我不包括任何方式再次,以减缓下来的精灵一旦MAXSPEED被击中。

对速度的收益有些间隔也可以考虑。 与上面的代码中,更新速度将是速度不够快,你可能不会注意到他们。



文章来源: Gradually speeding a sprite