我想让球逐渐移动 [英] I am trying to make ball gradually move

查看:74
本文介绍了我想让球逐渐移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当你按下其中一个箭头键时,我试图让球逐渐移动,现在它只是传送。我想要它,以便你可以看到它移动。基于此示例,我使用的是键绑定,并且有一个名为delta的变量会导致球移动50像素,但就像我说的那样,当你按下箭头键时,球只出现50个像素,我希望它就像你踢球一样你可以看到它从a点到b点。转到我认为问题所在的第89行。

I am trying to make a ball gradually move when you press one of the arrow keys, right now it kind of just teleports. I want it so that you can see it move. Based on this example, I am using key bindings, and there is a variable called delta that causes the ball move by 50 pixels, but like I said the ball just appears 50 pixels in whichever direction the arrow key is you pressed, I want it to be like if you were to kick a ball you can see it get from point a to b. Go to line 89 that is where I think the problem is.

package game;

import java.awt.BasicStroke;
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.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

/**
 * @see https://stackoverflow.com/questions/6991648
 * @see https://stackoverflow.com/questions/6887296
 * @see https://stackoverflow.com/questions/5797965
 */
public class LinePanel extends JPanel {
myObject ball;

private Point b1 = new Point(0,0);


private MouseHandler mouseHandler = new MouseHandler();
private Point p1 = new Point(100, 100);
private Point p2 = new Point(540, 380);
private boolean drawing;

public LinePanel() {
    this.setPreferredSize(new Dimension(640, 480));
    this.addMouseListener(mouseHandler);
    this.addMouseMotionListener(mouseHandler);
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(Color.blue);
    g2d.setRenderingHint(
        RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setStroke(new BasicStroke(8,
        BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
    g.drawLine(p1.x, p1.y, p2.x, p2.y);
    ball = new myObject(b1.x,b1.y,"Stuff/ball.png",50,50);
    g.drawImage(ball.getImage(),ball.getX(),ball.getY(), ball.getWidth(),         ball.getHeight(), null);
    repaint();
}

private class MouseHandler extends MouseAdapter {

    @Override
    public void mousePressed(MouseEvent e) {
        drawing = true;
        p1 = e.getPoint();
        p2 = p1;
        repaint();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        drawing = false;
        p2 = e.getPoint();
        repaint();
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (drawing) {
            p2 = e.getPoint();
            repaint();
        }
    }
}

private class ControlPanel extends JPanel {

    private static final int DELTA = 50;
// above is telling the ball to move by 50 pixels
    // I want it to move by 50 pixels but gradually I dont want it to teleport
    public ControlPanel() {
        this.add(new MoveButton("\u2190", KeyEvent.VK_LEFT, -DELTA, 0));
        this.add(new MoveButton("\u2191", KeyEvent.VK_UP, 0, -DELTA));
        this.add(new MoveButton("\u2192", KeyEvent.VK_RIGHT, DELTA, 0));
        this.add(new MoveButton("\u2193", KeyEvent.VK_DOWN, 0, DELTA));


    }


    private class MoveButton extends JButton {

        KeyStroke k;
        int myX, myY;

        public MoveButton(String name, int code, final int myX, final int myY) {
            super(name);
            this.k = KeyStroke.getKeyStroke(code, 0);
            this.myX = myX;
            this.myY = myY;
            this.setAction(new AbstractAction(this.getText()) {

                @Override
                public void actionPerformed(ActionEvent e) {
                    LinePanel.this.b1.translate(myX, myY);

                    LinePanel.this.repaint();
                }
            });
            ControlPanel.this.getInputMap(
                WHEN_IN_FOCUSED_WINDOW).put(k, k.toString());
            ControlPanel.this.getActionMap().put(k.toString(), new AbstractAction() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    MoveButton.this.doClick();
                }
            });
        }
    }
}



private void display() {
    JFrame f = new JFrame("LinePanel");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.add(this);
    f.add(new ControlPanel(), BorderLayout.SOUTH);
    f.pack();
    f.setLocationRelativeTo(null);
    f.setVisible(true);
}

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {

        @Override
        public void run() {
            new LinePanel().display();
        }
    });
}


}


推荐答案

任何动画的基本前提都是随着时间的推移而改变。

The basic premise for any animation is change over time.

你需要能够将球从位置A移动到位置B给定的时间段。要做到这一点,你需要某种自动收报机,可以用来更新那段时间内球的位置。一般来说,25fps(或大约40毫秒)就足够了。

You need to be able to move the ball from position A to position B over a given time period. To do that, you need some kind of "ticker" that can be used to update the position of the ball over that period. Generally speaking, 25fps (or about 40 milliseconds) is more than enough.

为了在Swing中安全地实现这一目标,最简单的解决方案是使用Swing 定时器。您可以使用 Thread ,但是您负责将更新同步回UI,而且现在确实需要更复杂的。

To achieve this safely in Swing, the easiest solution is to use a Swing Timer. You could use a Thread, but then you become responsible for syncing the updates back to the UI and it's more complexity then is really required at this stage.

此示例使用1秒的持续时间将球从A点移动到B点。这是一个线性动画,您需要调查适当的动画框架以获得更复杂的解决方案。

This example uses a duration of 1 second to move the ball from point A to point B. This is a linear animation and you would need to investigate an appropriate animation framework to get a more complex solution.

import java.awt.BasicStroke;
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.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;

public class LinePanel extends JPanel {

//    myObject ball;
    private Point b1 = new Point(0, 0);
    private Point startPoint = new Point(0, 0);
    private Point targetPoint = new Point(0, 0);
    private MouseHandler mouseHandler = new MouseHandler();
    private Point p1 = new Point(100, 100);
    private Point p2 = new Point(540, 380);
    private boolean drawing;

    private Timer animate;
    private long startTime;
    private int duration = 1000;

    public LinePanel() {
        this.setPreferredSize(new Dimension(640, 480));
        this.addMouseListener(mouseHandler);
        this.addMouseMotionListener(mouseHandler);
        animate = new Timer(40, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                long now = System.currentTimeMillis();
                long dif = now - startTime;
                if (dif >= duration) {
                    dif = duration;
                    ((Timer)e.getSource()).stop();
                }
                float progress = (float)dif / (float)duration;
                b1 = calculateProgress(startPoint, targetPoint, progress);
                repaint();
            }
        });
        animate.setRepeats(true);
        animate.setCoalesce(true);
    }

    public void moveBallTo(Point target) {

        if (animate.isRunning()) {
            animate.stop();
        }

        startPoint = b1;
        targetPoint = target;

        startTime = System.currentTimeMillis();
        animate.start();

    }

    public void moveBallBy(int xDelta, int yDelta) {

        animate.stop();

        Point t = new Point(targetPoint == null ? b1 : targetPoint);
        t.x += xDelta;
        t.y += yDelta;

        moveBallTo(t);

    }

    public Point calculateProgress(Point startPoint, Point targetPoint, double progress) {

        Point point = new Point();

        if (startPoint != null && targetPoint != null) {

            point.x = calculateProgress(startPoint.x, targetPoint.x, progress);
            point.y = calculateProgress(startPoint.y, targetPoint.y, progress);

        }

        return point;

    }

    public int calculateProgress(int startValue, int endValue, double fraction) {

        int value = 0;
        int distance = endValue - startValue;
        value = (int)Math.round((double)distance * fraction);
        value += startValue;

        return value;

    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.blue);
        g2d.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setStroke(new BasicStroke(8,
                BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL));
        g.drawLine(p1.x, p1.y, p2.x, p2.y);

        g.setColor(Color.RED);
        g.drawOval(b1.x - 4, b1.y - 4, 8, 8);
//        ball = new myObject(b1.x, b1.y, "Stuff/ball.png", 50, 50);
//        g.drawImage(ball.getImage(), ball.getX(), ball.getY(), ball.getWidth(), ball.getHeight(), null);
        repaint();
    }

    private class MouseHandler extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            drawing = true;
            p1 = e.getPoint();
            p2 = p1;
            repaint();
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            drawing = false;
            p2 = e.getPoint();
            repaint();
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (drawing) {
                p2 = e.getPoint();
                repaint();
            }
        }
    }

    private class ControlPanel extends JPanel {

        private static final int DELTA = 50;
// above is telling the ball to move by 50 pixels
        // I want it to move by 50 pixels but gradually I dont want it to teleport

        public ControlPanel() {
            this.add(new MoveButton("\u2190", KeyEvent.VK_LEFT, -DELTA, 0));
            this.add(new MoveButton("\u2191", KeyEvent.VK_UP, 0, -DELTA));
            this.add(new MoveButton("\u2192", KeyEvent.VK_RIGHT, DELTA, 0));
            this.add(new MoveButton("\u2193", KeyEvent.VK_DOWN, 0, DELTA));


        }

        private class MoveButton extends JButton {

            KeyStroke k;
            int myX, myY;

            public MoveButton(String name, int code, final int myX, final int myY) {
                super(name);
                this.k = KeyStroke.getKeyStroke(code, 0);
                this.myX = myX;
                this.myY = myY;
                this.setAction(new AbstractAction(this.getText()) {
                    @Override
                    public void actionPerformed(ActionEvent e) {
//                        LinePanel.this.b1.translate(myX, myY);
                        moveBallBy(myX, myY);
                        LinePanel.this.repaint();
                    }
                });
                ControlPanel.this.getInputMap(
                        WHEN_IN_FOCUSED_WINDOW).put(k, k.toString());
                ControlPanel.this.getActionMap().put(k.toString(), new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        MoveButton.this.doClick();
                    }
                });
            }
        }
    }

    private void display() {
        JFrame f = new JFrame("LinePanel");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.add(new ControlPanel(), BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new LinePanel().display();
            }
        });
    }
}

看看......

  • How to use Swing Timers
  • Timing Framework
  • Trident
  • Universal Tween Engine

旁注

这样做 ball = new myObject(b1.x,b1.y,Stuff / ball.png,50,50); 在你的paint方法中是非常低效的。可以快速连续多次调用 paint 。在任何可能的情况下,您希望 paint 方法尽可能优化,在paint方法中花费大量时间会使程序看起来很慢

Doing this ball = new myObject(b1.x, b1.y, "Stuff/ball.png", 50, 50); in you paint method is incredibly inefficient. paint may be called a number of times in quick succession. Where ever possible, you want the paint methods to be as optimized as you can make them, to much time spent in your paint method will make your program look slow

这篇关于我想让球逐渐移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆