Java 沿直线移动点

Java 沿直线移动点,java,Java,我画了一个形状,看起来像字母“Y”。然后在底部画一个小点 假设形状为3条线,如下所示: 我想沿着线1移动这个点,然后沿着线2,再沿着线2,再沿着线3,最后回到线1底部的起点 它以滑块指定的速度移动 以下是我目前的代码: public class yyyyy extends JFrame{ private Komponent komponent; private Timer timer; private int tick = 0; private int speed = 4; private

我画了一个形状,看起来像字母“Y”。然后在底部画一个小点

假设形状为3条线,如下所示:

我想沿着线1移动这个点,然后沿着线2,再沿着线2,再沿着线3,最后回到线1底部的起点

它以滑块指定的速度移动

以下是我目前的代码:

public class yyyyy extends JFrame{

private Komponent komponent;
private Timer timer;
private int tick = 0;
private int speed = 4;
private int x1 = 225, y1 = 300, y2 = 225, x3 = 150, y3 = 150, x4 = 300; 
private int x = x1, y = y1;

class Komponent extends JComponent{

    /**
     * 
     */
    private static final long serialVersionUID = -4028514932033769012L;

    @Override
    protected void paintComponent(Graphics arg0) {



        if(tick< y1-y2){
            x = x1;
            y = y1-tick;
        }
        else if(tick>y1-y2 && tick < 2*(y1-y2)){
            x = x1-tick + (y1-y2);
            y = y2-tick + (y1-y2);
        }
        else if(tick>2*(y1-y2) && tick < 3*(y1-y2)){
            x = x3 + tick - 2*(y1-y2);
            y = y3 + tick - 2*(y1-y2);
        }
        else if(tick>3*(y1-y2)&& tick < 4*(y1-y2)){
            x = x1 + tick - 3*(y1-y2);
            y = y2 - tick + 3*(y1-y2);
        }
        else if(tick>4*(y1-y2)&& tick < 5*(y1-y2)){
            x = x4 - tick + 4*(y1-y2);
            y = y3 + tick - 4*(y1-y2);
        }
        else{
            x = x1;
            y = y2 + tick - 5*(y1-y2);
        }
        arg0.setColor(Color.BLUE);
        arg0.drawLine(x1, y1, x1, y2);
        arg0.drawLine(x1,y2,x3,y3);
        arg0.drawLine(x1, y2, x4, y3);

        arg0.setColor(Color.RED);
        arg0.fillOval(x-5, y-5, 10, 10);
        super.paintComponent(arg0);
    }

}
public yyyyy (String string){
    super(string);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setBounds(100,100,550,550);
    add(komponent=new Komponent());
    JPanel panel = new JPanel();
    add(panel, BorderLayout.SOUTH);
    final JCheckBox cb = new JCheckBox("Animacja");
    cb.addChangeListener(new ChangeListener() {

        @Override
        public void stateChanged(ChangeEvent e) {
            if(cb.isSelected()){
                timer.start();
            }
            else{
                timer.stop();
            }
        }
    });
    panel.add(cb);
    timer = new Timer(50, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            tick+=speed;
            if(tick > 6*(y1 -y2)){
                tick -= 6*(y1-y2);
            }
            if(tick < 0){
                tick = 6*(y2-y1);
            }
            komponent.repaint();
        }
    });

    final JSlider speedSlider = new JSlider(-30,30,speed);
    panel.add(speedSlider);
    speedSlider.addChangeListener(new ChangeListener() {

        @Override
        public void stateChanged(ChangeEvent e) {
            speed = speedSlider.getValue();
            komponent.repaint();
        }
    });
    setLocationRelativeTo(null);
    setVisible(true);
}

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

        @Override
        public void run() {
            new yyyyy("wat");

        }
    });
}

}
public类yyyy扩展了JFrame{
私营公司;
私人定时器;
私人整数滴答=0;
私人内部速度=4;
私有整数x1=225,y1=300,y2=225,x3=150,y3=150,x4=300;
私有整数x=x1,y=y1;
类Komponent扩展了JComponent{
/**
* 
*/
私有静态最终长serialVersionUID=-4028514932033769012L;
@凌驾
受保护的组件(图形arg0){
如果(勾选y1-y2&&勾选<2*(y1-y2)){
x=x1刻度+(y1-y2);
y=y2刻度+(y1-y2);
}
否则如果(勾选>2*(y1-y2)和勾选<3*(y1-y2)){
x=x3+勾号-2*(y1-y2);
y=y3+勾号-2*(y1-y2);
}
否则如果(勾选>3*(y1-y2)和勾选<4*(y1-y2)){
x=x1+勾号-3*(y1-y2);
y=y2-勾选+3*(y1-y2);
}
否则如果(勾选>4*(y1-y2)和勾选<5*(y1-y2)){
x=x4-勾选+4*(y1-y2);
y=y3+勾号-4*(y1-y2);
}
否则{
x=x1;
y=y2+勾号-5*(y1-y2);
}
arg0.setColor(Color.BLUE);
arg0.拉线(x1,y1,x1,y2);
arg0.抽绳(x1、y2、x3、y3);
arg0.拉线(x1、y2、x4、y3);
arg0.setColor(Color.RED);
arg0.椭圆形(x-5,y-5,10,10);
超级组件(arg0);
}
}
公共YYYY(字符串){
超级(字符串);
setDefaultCloseOperation(关闭时退出);
立根(100550550);
添加(komponent=新komponent());
JPanel面板=新的JPanel();
添加(面板,边界布局。南部);
最终JCheckBox cb=新JCheckBox(“Animacja”);
cb.addChangeListener(新的ChangeListener(){
@凌驾
公共无效状态已更改(更改事件e){
if(cb.isSelected()){
timer.start();
}
否则{
timer.stop();
}
}
});
增补(cb);
计时器=新计时器(50,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
滴答声+=速度;
如果(勾选>6*(y1-y2)){
勾号-=6*(y1-y2);
}
如果(勾选<0){
勾号=6*(y2-y1);
}
komponent.repaint();
}
});
最终JSlider速度滑块=新JSlider(-30,30,速度);
面板。添加(速度滑块);
addChangeListener(新的ChangeListener(){
@凌驾
公共无效状态已更改(更改事件e){
速度=speedSlider.getValue();
komponent.repaint();
}
});
setLocationRelativeTo(空);
setVisible(真);
}
公共静态void main(字符串[]args){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
新YYYY(“wat”);
}
});
}
}
现在我有两个问题: 1.勾号的重置是否正确定义?我觉得在所有直线的距离之和为2*之后,它应该变为0。 2.代码中我用注释标记的部分。如何检查点的当前x和y应为多少?我试着用直线方程来做,但并没有多大的成功(点总是在窗外拍摄)


编辑:代码更新。

尽管问题已经在评论中得到了回答(虽然这主要是一个调试提示,虽然这不是一个真正的答案…),但我建议您对此进行概括

您可能需要使用一组固定的坐标手动为每个线段建模。相反,您可以创建一个应该遵循的通用“路径”。路径上的位置可以定义为介于0.0和1.0之间的值

然后,将定时和插值分离,并且可以单独处理定时本身。然后,您甚至可以添加漂亮的动画效果,例如,在某处添加一些
Math.sin
,并获得有趣的缓入/缓出效果

然而,下面是一个示例,展示了如何实现这种通用路径跟随器。只需在
main
方法中更改
PathFollower
实例的创建,即可将其从跟随
Y
更改为跟随
X

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class PathFollowerTest
{
    public static void main(String[] args)
    {
        final PathFollower pathFollower = createPathFollowerY();
        //final PathFollower pathFollower = createPathFollowerX();

        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI(pathFollower);
            }
        });
    }

    private static PathFollower createPathFollowerY()
    {
        Point2D p0 = new Point2D.Double(225, 300);
        Point2D p1 = new Point2D.Double(225, 225);
        Point2D p2 = new Point2D.Double(150, 150);
        Point2D p3 = new Point2D.Double(300, 150);
        PathFollower pathFollower = new PathFollower();
        pathFollower.addPoint(p0);
        pathFollower.addPoint(p1);
        pathFollower.addPoint(p2);
        pathFollower.addPoint(p1);
        pathFollower.addPoint(p3);
        pathFollower.addPoint(p1);
        pathFollower.addPoint(p0);
        return pathFollower;
    }

    private static PathFollower createPathFollowerX()
    {
        Point2D p0 = new Point2D.Double(150, 300);
        Point2D p1 = new Point2D.Double(225, 225);
        Point2D p2 = new Point2D.Double(150, 150);
        Point2D p3 = new Point2D.Double(300, 300);
        Point2D p4 = new Point2D.Double(300, 150);
        PathFollower pathFollower = new PathFollower();
        pathFollower.addPoint(p0);
        pathFollower.addPoint(p1);
        pathFollower.addPoint(p2);
        pathFollower.addPoint(p1);
        pathFollower.addPoint(p4);
        pathFollower.addPoint(p1);
        pathFollower.addPoint(p3);
        pathFollower.addPoint(p1);
        pathFollower.addPoint(p0);
        return pathFollower;
    }

    private static void createAndShowGUI(final PathFollower pathFollower)
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setBounds(100, 100, 550, 550);
        f.getContentPane().setLayout(new BorderLayout());

        PathFollowerPanel pathFollowerPanel = 
            new PathFollowerPanel(pathFollower);
        f.getContentPane().add(pathFollowerPanel, BorderLayout.CENTER);

        final PathFollowerController pathFollowerController = 
            new PathFollowerController(
                pathFollower, pathFollowerPanel);

        JPanel panel = new JPanel();
        f.getContentPane().add(panel, BorderLayout.SOUTH);
        final JCheckBox cb = new JCheckBox("Animacja");
        cb.addChangeListener(new ChangeListener()
        {
            @Override
            public void stateChanged(ChangeEvent e)
            {
                pathFollowerController.setRunning(cb.isSelected());
            }
        });
        panel.add(cb);

        final JSlider speedSlider = new JSlider(-30, 30, 0);
        panel.add(speedSlider);
        speedSlider.addChangeListener(new ChangeListener()
        {
            @Override
            public void stateChanged(ChangeEvent e)
            {
                pathFollowerController.setSpeed(speedSlider.getValue());
            }
        });
        f.setLocationRelativeTo(null);
        f.setVisible(true);

    }
}

class PathFollowerController
{
    private int speed = 0;
    private PathFollower pathFollower;
    private PathFollowerPanel pathFollowerPanel;

    private final Timer timer = new Timer(50, new ActionListener()
    {
        private double alpha = 0;

        @Override
        public void actionPerformed(ActionEvent e)
        {
            alpha += speed / 500.0;
            alpha %= 1.0;
            while (alpha < -1.0)
            {
                alpha += 1.0;
            }
            pathFollower.setAlpha(alpha < 0 ? -alpha : alpha);
            pathFollowerPanel.repaint();
        }
    });

    PathFollowerController(PathFollower pathFollower,
        PathFollowerPanel pathFollowerPanel)
    {
        this.pathFollower = pathFollower;
        this.pathFollowerPanel = pathFollowerPanel;
    }

    void setRunning(boolean running)
    {
        if (running)
        {
            timer.start();
        }
        else
        {
            timer.stop();
        }
    }

    public void setSpeed(int speed)
    {
        this.speed = speed;
    }
}

class PathFollower
{
    private final List<Point2D> points;
    private Shape path;
    private double pathLength = -1;
    private double alpha = 0;

    PathFollower()
    {
        points = new ArrayList<Point2D>();
    }

    void addPoint(Point2D p)
    {
        points.add(new Point2D.Double(p.getX(), p.getY()));
        path = null;
        pathLength = -1;
    }

    void setAlpha(double alpha)
    {
        this.alpha = alpha;
    }

    Point2D getCurrentPoint()
    {
        return computePoint(alpha);
    }

    Shape getPath()
    {
        if (path == null)
        {
            path = createPath();
        }
        return path;
    }

    private Shape createPath()
    {
        Path2D path = new Path2D.Double();
        for (int i = 0; i < points.size(); i++)
        {
            Point2D p = points.get(i);
            double x = p.getX();
            double y = p.getY();
            if (i == 0)
            {
                path.moveTo(x, y);
            }
            else
            {
                path.lineTo(x, y);
            }
        }
        return path;
    }

    private double computePathLength()
    {
        double pathLength = 0;
        for (int i = 0; i < points.size() - 1; i++)
        {
            Point2D p0 = points.get(i);
            Point2D p1 = points.get(i + 1);
            pathLength += p0.distance(p1);
        }
        return pathLength;
    }

    private Point2D computePoint(double alpha)
    {
        if (pathLength < 0)
        {
            pathLength = computePathLength();
        }
        double alphaPosition = alpha * pathLength;
        double accumulatedLength = 0;
        for (int i = 0; i < points.size() - 1; i++)
        {
            Point2D p0 = points.get(i);
            Point2D p1 = points.get(i + 1);
            double distance = p0.distance(p1);
            double nextLength = accumulatedLength + distance;
            if (nextLength >= alphaPosition)
            {
                double localAlpha = 
                    (alphaPosition - accumulatedLength) / distance;
                double x = p0.getX() + localAlpha * (p1.getX() - p0.getX());
                double y = p0.getY() + localAlpha * (p1.getY() - p0.getY());
                return new Point2D.Double(x, y);
            }
            accumulatedLength = nextLength;
        }
        Point2D p = points.get(points.size() - 1);
        return new Point2D.Double(p.getX(), p.getY());
    }

}

class PathFollowerPanel extends JPanel
{
    private final PathFollower pathFollower;

    PathFollowerPanel(PathFollower pathFollower)
    {
        this.pathFollower = pathFollower;
    }

    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D) gr;
        g.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

        g.setColor(Color.BLUE);
        g.setStroke(new BasicStroke(3.0f));
        g.draw(pathFollower.getPath());

        g.setColor(Color.RED);
        Point2D p = pathFollower.getCurrentPoint();
        double r = 5;
        g.fill(new Ellipse2D.Double(
            p.getX() - r, p.getY() - r, r + r, r + r));
    }
}
import java.awt.BasicStroke;
导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.RenderingHints;
导入java.awt.Shape;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.geom.Ellipse2D;
导入java.awt.geom.Path2D;
导入java.awt.geom.Point2D;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.JCheckBox;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JSlider;
导入javax.swing.SwingUtilities;
导入javax.swing.Timer;
导入javax.swing.event.ChangeEvent;
导入javax.swing.event.ChangeListener;
公共类PathFollowerTest
{
公共静态void main(字符串[]args)
{
最终路径跟随者路径跟随者=createPathFollowerY();
//最终路径跟随者路径跟随者=createPathFollowerX();
SwingUtilities.invokeLater(新的Runnable()
{
@凌驾
公开募捐
{
createAndShowGUI(路径跟随者);
}
});
}
私有静态PathFollower createPathFollowerY()
{
Point2D p0=新的Point2D.Double(225300);
Point2D p1=新的Point2D.Double(225225);
Point2D p2=新的Point2D.Doubl