Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用线程实现轻松功能_Java_Eclipse - Fatal编程技术网

Java 如何使用线程实现轻松功能

Java 如何使用线程实现轻松功能,java,eclipse,Java,Eclipse,我试图找到一种高效、正常或简单的方法来在java程序中实现easing函数。我得到了缓解功能,但我觉得有一个更有效的方法来实现它;一个我看不见的,可能是因为隧道视觉。这是我的密码;有人能告诉我应该做些什么,或者给我指出我需要去研究的方向吗 public class slide extends JPanel implements Runnable { Thread ease = new Thread(this); float total = 0; float dur;

我试图找到一种高效、正常或简单的方法来在java程序中实现easing函数。我得到了缓解功能,但我觉得有一个更有效的方法来实现它;一个我看不见的,可能是因为隧道视觉。这是我的密码;有人能告诉我应该做些什么,或者给我指出我需要去研究的方向吗

public class slide extends JPanel implements Runnable {

    Thread ease = new Thread(this);
    float total = 0;
    float dur;

    slide() {

        ease.start();
        setLayout(null);

    }

    public float calc(float t, float b, float c, float d) {

        return c * t / d + b;

    }

    public void run() {
        while (true) {
            try {
                if (total < 50) {
                    total += 1;
                } else {
                    ease.stop();
                }
                setBounds(400, Math.round(200 * total / 50 + 0), 250, 150);
                repaint();
                System.out.println(total + " " + dur);
                ease.sleep(10);
            } catch (Exception e) {
            }
        }

    }
}
公共类幻灯片扩展JPanel实现可运行{
螺纹松动=新螺纹(此);
浮动总数=0;
浮动dur;
幻灯片(){
ease.start();
setLayout(空);
}
公共浮动计算(浮动t、浮动b、浮动c、浮动d){
返回c*t/d+b;
}
公开募捐{
while(true){
试一试{
如果(总数<50){
总数+=1;
}否则{
放松。停止();
}
挫折(400,数学四舍五入(200*total/50+0)、250、150);
重新油漆();
系统输出打印项次(总计+“”+dur);
放松睡眠(10);
}捕获(例外e){
}
}
}
}

我试着为我在网上找到的线性缓和函数实现calc()方法,但实际上毫无用处,因为我被迫将方程直接插入到

中,否则无法使其工作。好吧,因此动画是一个相当复杂和深入的主题,我不打算在这里介绍,它还涉及到很多我不太懂的数学,所以我们不会深入到大量的细节,有比我更好的人可以解释它,你可以在网上阅读

首先,我们做一些假设

动画是随时间的变化,其中时间是可变的。地役权是(在本例中)速度随时间的变化。这意味着动画的速度在任何给定的时间点都是可变的

基本上,我们要做的是“正常化”一切。也就是说,在动画开始时,时间为0,在动画结束时,时间为1,介于这两个值之间的所有其他值都是这两个值之间的分数

如果你能这样想,事情就容易多了。因此,根据时间轴上的给定点,您可以决定应该做什么。例如,在50%的时间里,你应该处于起点和终点之间的一半

好吧,但这些对我们有什么帮助?如果我们要绘制一个易入易出动画,它看起来会像

SplineInterpolator si = new SplineInterpolator(1, 0, 0, 1);
for (double t = 0; t <= 1; t += 0.1) {
    System.out.println(si.interpolate(t));
}
0.0
0.011111693284790492
0.057295031944523504
0.16510933001160544
0.3208510585798438
0.4852971690762217
0.6499037832761319
0.8090819765428142
0.9286158775101805
0.9839043020410436
0.999702

其中,x轴为时间,y轴为速度(在两个轴上都在0和1之间)。所以,在x(时间)上的任意给定点,我们应该能够计算速度

现在,我们可以使用一些Bézier脊椎/曲线的数学来计算物体在时间轴上给定点的速度

现在,我直接从计时框架中借用了大部分代码,但是如果您真的感兴趣,还可以查看

(注意:我确实写了这样的东西,然后两天后,发现计时框架已经实现了……这是一个有趣的练习……)

现在,关于这个实现需要注意的是,它实际上不会返回对象的速度,但它会返回沿时间轴(0-1)的时间进度,好吧,听起来很奇怪,但它允许您计算起点和终点之间的当前位置
(startValue+((endValue-startValue)*进度))
沿时间线

我不想详细讨论这个问题,因为我真的不懂数学,我只知道如何应用它,但基本上,我们计算曲线上的点(x/y),然后对这些值(0-1)进行规格化,以便于查找

interpolate
方法使用二进制搜索来查找给定时间段内最近的匹配点,然后计算该点的速度/y位置

public class SplineInterpolator {

    private final double points[];
    private final List<PointUnit> normalisedCurve;

    public SplineInterpolator(double x1, double y1, double x2, double y2) {
        points = new double[]{ x1, y1, x2, y2 };

        final List<Double> baseLengths = new ArrayList<>();
        double prevX = 0;
        double prevY = 0;
        double cumulativeLength = 0;
        for (double t = 0; t <= 1; t += 0.01) {
            Point2D xy = getXY(t);
            double length = cumulativeLength
                            + Math.sqrt((xy.getX() - prevX) * (xy.getX() - prevX)
                                            + (xy.getY() - prevY) * (xy.getY() - prevY));

            baseLengths.add(length);
            cumulativeLength = length;
            prevX = xy.getX();
            prevY = xy.getY();
        }

        normalisedCurve = new ArrayList<>(baseLengths.size());
        int index = 0;
        for (double t = 0; t <= 1; t += 0.01) {
            double length = baseLengths.get(index++);
            double normalLength = length / cumulativeLength;
            normalisedCurve.add(new PointUnit(t, normalLength));
        }
    }

    public double interpolate(double fraction) {
        int low = 1;
        int high = normalisedCurve.size() - 1;
        int mid = 0;
        while (low <= high) {
            mid = (low + high) / 2;

            if (fraction > normalisedCurve.get(mid).getPoint()) {
                low = mid + 1;
            } else if (mid > 0 && fraction < normalisedCurve.get(mid - 1).getPoint()) {
                high = mid - 1;
            } else {
                break;
            }
        }
        /*
         * The answer lies between the "mid" item and its predecessor.
         */
        final PointUnit prevItem = normalisedCurve.get(mid - 1);
        final double prevFraction = prevItem.getPoint();
        final double prevT = prevItem.getDistance();

        final PointUnit item = normalisedCurve.get(mid);
        final double proportion = (fraction - prevFraction) / (item.getPoint() - prevFraction);
        final double interpolatedT = prevT + (proportion * (item.getDistance() - prevT));
        return getY(interpolatedT);
    }

    protected Point2D getXY(double t) {
        final double invT = 1 - t;
        final double b1 = 3 * t * invT * invT;
        final double b2 = 3 * t * t * invT;
        final double b3 = t * t * t;
        final Point2D xy = new Point2D.Double((b1 * points[0]) + (b2 * points[2]) + b3, (b1 * points[1]) + (b2 * points[3]) + b3);
        return xy;
    }

    protected double getY(double t) {
        final double invT = 1 - t;
        final double b1 = 3 * t * invT * invT;
        final double b2 = 3 * t * t * invT;
        final double b3 = t * t * t;
        return (b1 * points[2]) + (b2 * points[3]) + b3;
    }

    public class PointUnit {

        private final double distance;
        private final double point;

        public PointUnit(double distance, double point) {
            this.distance = distance;
            this.point = point;
        }

        public double getDistance() {
            return distance;
        }

        public double getPoint() {
            return point;
        }

    }

}
好吧,现在你可能会想,“等一下,这是一个线性过程!”,但事实并非如此,如果你画出它,你会发现前三个值和后三个值非常接近,其他值以不同的程度分布,这是我们的“进展”值,我们应该沿着时间线走多远

所以现在,你的头应该要爆炸了(我的是)-这就是为什么我说,使用一个框架

但你会如何使用它?!这是有趣的部分,现在记住,一切都是可变的,动画的持续时间,对象随时间的速度,滴答声或更新的数量,都是可变的

这一点很重要,因为这就是这样的功能所在!例如,如果动画由于某些外部因素而暂停,此实现可以简单地跳过这些“帧”这听起来可能是件坏事,但相信我,这一切都是为了愚弄人们的眼睛,让他们“思考”某些事情正在发生变化;)

(以下是8fps,所以非常糟糕)

瞧,我们有一个轻松进出的动画

现在,开始使用动画框架!只是简单多了:P

  • 对于“快进/慢出”,您可以使用
    0,0,1,1
  • 对于“慢进/快出”,您可以使用
    0,1,0,0
  • 对于“慢入”,您可以使用
    1,0,1,1
  • 对于“慢出”,您可以使用
    0,0,0,1
(或者至少这些是我使用的值)


实验,看看你得到了什么好的,所以动画是一个相当复杂和深入的主题,我不打算在这里讨论,它还涉及很多数学,我不太懂,所以我们不会深入到大量的细节,有比我更好的人可以解释它,你可以在网上看到

首先,我们做一些假设<
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.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

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

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

    public class TestPane extends JPanel {

        private int startAt = 0;
        private int endAt;
        private int x = startAt;
        private Timer timer;
        private SplineInterpolator splineInterpolator;
        private long startTime = -1;
        private long playTime = 5000; // 5 seconds

        public TestPane() {
            splineInterpolator = new SplineInterpolator(1, 0, 0, 1);
            timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (startTime < 0) {
                        startTime = System.currentTimeMillis();
                    }
                    long now = System.currentTimeMillis();
                    long duration = now - startTime;
                    double t = (double) duration / (double) playTime;
                    if (duration >= playTime) {
                        t = 1;
                    }

                    double progress = splineInterpolator.interpolate(t);

                    x = startAt + ((int) Math.round((endAt - startAt) * progress));
                    repaint();
                }
            });
            timer.setInitialDelay(0);
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (!timer.isRunning()) {
                        startTime = -1;
                        startAt = 0;
                        endAt = getWidth() - 10;
                        timer.start();
                    }
                }
            });
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.RED);
            g2d.fillRect(x, (getHeight() / 2) - 5, 10, 10);
            g2d.dispose();
        }

    }

    public static class SplineInterpolator {

        private final double points[];
        private final List<PointUnit> normalisedCurve;

        public SplineInterpolator(double x1, double y1, double x2, double y2) {
            points = new double[]{x1, y1, x2, y2};

            final List<Double> baseLengths = new ArrayList<>();
            double prevX = 0;
            double prevY = 0;
            double cumulativeLength = 0;
            for (double t = 0; t <= 1; t += 0.01) {
                Point2D xy = getXY(t);
                double length = cumulativeLength
                                + Math.sqrt((xy.getX() - prevX) * (xy.getX() - prevX)
                                                + (xy.getY() - prevY) * (xy.getY() - prevY));

                baseLengths.add(length);
                cumulativeLength = length;
                prevX = xy.getX();
                prevY = xy.getY();
            }

            normalisedCurve = new ArrayList<>(baseLengths.size());
            int index = 0;
            for (double t = 0; t <= 1; t += 0.01) {
                double length = baseLengths.get(index++);
                double normalLength = length / cumulativeLength;
                normalisedCurve.add(new PointUnit(t, normalLength));
            }
        }

        public double interpolate(double fraction) {
            int low = 1;
            int high = normalisedCurve.size() - 1;
            int mid = 0;
            while (low <= high) {
                mid = (low + high) / 2;

                if (fraction > normalisedCurve.get(mid).getPoint()) {
                    low = mid + 1;
                } else if (mid > 0 && fraction < normalisedCurve.get(mid - 1).getPoint()) {
                    high = mid - 1;
                } else {
                    break;
                }
            }
            /*
             * The answer lies between the "mid" item and its predecessor.
             */
            final PointUnit prevItem = normalisedCurve.get(mid - 1);
            final double prevFraction = prevItem.getPoint();
            final double prevT = prevItem.getDistance();

            final PointUnit item = normalisedCurve.get(mid);
            final double proportion = (fraction - prevFraction) / (item.getPoint() - prevFraction);
            final double interpolatedT = prevT + (proportion * (item.getDistance() - prevT));
            return getY(interpolatedT);
        }

        protected Point2D getXY(double t) {
            final double invT = 1 - t;
            final double b1 = 3 * t * invT * invT;
            final double b2 = 3 * t * t * invT;
            final double b3 = t * t * t;
            final Point2D xy = new Point2D.Double((b1 * points[0]) + (b2 * points[2]) + b3, (b1 * points[1]) + (b2 * points[3]) + b3);
            return xy;
        }

        protected double getY(double t) {
            final double invT = 1 - t;
            final double b1 = 3 * t * invT * invT;
            final double b2 = 3 * t * t * invT;
            final double b3 = t * t * t;
            return (b1 * points[2]) + (b2 * points[3]) + b3;
        }

        public class PointUnit {

            private final double distance;
            private final double point;

            public PointUnit(double distance, double point) {
                this.distance = distance;
                this.point = point;
            }

            public double getDistance() {
                return distance;
            }

            public double getPoint() {
                return point;
            }

        }

    }

}
if (startTime < 0) {
    startTime = System.currentTimeMillis();
}
long now = System.currentTimeMillis();
long duration = now - startTime;
double t = (double) duration / (double) playTime;
if (duration >= playTime) {
    t = 1;
}

double progress = splineInterpolator.interpolate(t);

x = startAt + ((int) Math.round((endAt - startAt) * progress));
repaint();