简体   繁体   English

我想让球逐渐移动

[英]I am trying to make ball gradually move

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. 基于这个例子 ,我使用的是键绑定,并且有一个名为delta的变量会导致球移动50个像素,但就像我说的那样,只要你按下箭头键,球就会出现50个像素,我想要它就像你要踢球一样,你可以看到它从a点到b点。 Go to line 89 that is where I think the problem is. 转到第89行,这是我认为问题所在。

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. 任何动画的基本前提是随着时间的推移而变化。

You need to be able to move the ball from position A to position B over a given time period. 你需要能够在给定的时间内将球从位置A移动到位置B. 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. 一般来说,25fps(或大约40毫秒)绰绰有余。

To achieve this safely in Swing, the easiest solution is to use a Swing Timer . 为了在Swing中安全地实现这一点,最简单的解决方案是使用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. 你可以使用一个Thread ,但是你负责将更新同步回UI,而且在这个阶段确实需要更复杂。

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

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

Take a look at ... 看一眼 ...

Side note 边注

Doing this ball = new myObject(b1.x, b1.y, "Stuff/ball.png", 50, 50); 做这个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. paint可以快速连续多次调用。 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 在任何可能的情况下,您都希望paint方法尽可能优化,在绘制方法中花费大量时间会使程序看起来很慢

Lots of ways to do the code and I'm not familiar with the environment. 有很多方法可以做代码而且我不熟悉环境。 But basically you use the key stroke to set the direction of movement, and then you have another routine that moves the ball in that direction. 但基本上你使用击键来设定运动方向,然后你有另一个程序将球移向那个方向。 How many pixels you move in one step an how long the step takes is your speed. 一步一步移动多少像素,步长需要的是你的速度。

How you use the keyboard is down to the game play. 你如何使用键盘取决于游戏玩法。 Holding down accelerates, When going right pressing left stops it. 按住加速,向右按下左键停止。 Do you want to give it inertia. 你想给它惯性吗? ie going right to left slows motion to the right to zero then starts going left. 即从右到左减慢向右运动到零然后开始向左。

All sorts of options but the trick is make moving the ball one routine and then use your input device to control the direction , acceleration etc. 各种各样的选择,但诀窍是将球移动一个例程然后使用您的输入设备来控制方向,加速度等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我正在尝试使用线程在小程序中移动球,但它没有移动 - I am trying to move a ball in applet using thread but its not moving 如何在java中连续左右移动球? - How can I make a ball move left and right continuously in java? 如何让弹跳球移动得更快? 动态速度? - How do I make bouncing ball move quicker? dynamic velocity? 如何使弹跳球移动? - How do I make my bouncing ball move? 使球移动以指定方向 - Make ball move to specify direction 试图在JavaFX中创建一个“球”类,该类由可通过按钮控制以在屏幕上左右,上下移动的圆圈组成 - Trying to make a “Ball” class in JavaFX that consists of a circle controllable by buttons to move left, right, up and down across the screen Java无法动弹 - Java-can't make a ball move 我正在尝试使用java applet开发游戏,球的运动会停止整个游戏? - I am trying to develop a game using java applet, the motion of a ball halts whole of my game? 我正在尝试制作一个动画,使 imageView 使用 Object animator 上下移动,当我点击 onClick() 时让它飘走 - I am trying to make an animation that makes an imageView move up and down using Object animator and when I hit onClick() have it float away 我正在尝试制作一个在命令行上播放的跳棋游戏,我不知道如何根据用户输入移动棋子 - I am trying to make a checkers game that plays on the command line, I can't figure out how to move the piece based on the users Input
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM