如何从2个存储x,y值和整数索引之间的时间变化的数组列表创建动画?

vsmadaxz  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(398)

我现在正在做一个3体模拟(重力),我通过随机猜测dt(时间步长)并把它们放入一个迭代方程中,计算出每一个新的x和y值。然后在每次迭代之后,我将每个x和y值保存在一个arraylist中,它包含了我放入变量的时间dt。我对java非常陌生,我很感激每一个答案,尽管考虑到我的知识,我会更感谢一个更简单的答案(我是一个16岁的非英语国家,我为任何错误道歉)我已经导入了arraylist,list和linkedlist,我的x和y列表的一个例子是

List<Double> xlistobject1 = new ArrayList<Double>();
List<Double> ylistobject1 = new ArrayList<Double>();

在while循环迭代过程中:

xlistobject1.add(xobject1); // where xobject1 and yobject1 are the x and y
ylistobject1.add(yobject1); // coordinates

我已经研究了最好的方法来制作动画,但是没有一个适合我。我真的不能把我的头围绕画布,jframe等等,因为他们需要这么多的先验知识,这个主题。由于时间跨度已经由n个迭代次数dt来定义,我想你不能在列表中的每个位置都画一个点然后按play,因为要创建一个相对平滑的动画,你必须带一个计时器来设置一个固定的动画长度,比如30秒,这意味着你将时间重新缩放到这个固定的长度上,最终会丢失精确的坐标信息,因为我的显示器只能显示1920x1080像素?
我已经得到了:
我复制了eclipse安装中唯一的一个框架(在文本的底部),并删除了移动部分,该部分已经存在,试图移动到列表中循环的x和y的值,直到我的列表被清除为止。在那之后,我会重新调整模拟的时间(n-counter
dt),这样它可以适应20秒,每秒30帧,这样模拟有600个时间步,所以如果我没有出错,你必须除以(n-counter*dt)/600来得到x和y比例因子。我的主要问题是如何将我的想法实现到java中。我希望我没把你搞糊涂,也没说废话。谢谢你的帮助!:)这是我的“动画”-代码:

import java.util.ArrayList;
import java.util.List;
import java.util.LinkedList;
import java.util.Vector;
import java.util.Stack;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;

final public class Test
{

JFrame frame;
DrawPanel drawPanel;

private int oneX = 7;
private int oneY = 7;

public static void main(String... args)
{
    new Test().go();
}

private void go()
{
    frame = new JFrame("Test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    drawPanel = new DrawPanel();

    frame.getContentPane().add(BorderLayout.CENTER, drawPanel);

    frame.setResizable(false);
    frame.setSize(1920, 1000);
    frame.setLocationByPlatform(true);
    frame.setVisible(true);
    moveIt();
}

class DrawPanel extends JPanel
{
    private static final long serialVersionUID = 1L;

    public void paintComponent(Graphics g)
    {
        g.setColor(Color.BLUE);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
        g.setColor(Color.RED);
        g.fillRect(3, 3, this.getWidth() - 6, this.getHeight() - 6);
        g.setColor(Color.WHITE);
        g.fillRect(6, 6, this.getWidth() - 12, this.getHeight() - 12);
        g.setColor(Color.BLACK);
        g.fillRect(oneX, oneY, 6, 6);
        // Object 1
   !    for i = 0 to xlistobject1.count - 1
   !    //move circle to x=xlistobject1.item(i)
   !    //move circle to y=ylistobject1.item(i)
                next

                try
                { 
                     Thread.sleep(10);
                }
                catch (Exception e)
               {
                e.printStackTrace();
               }
               frame.repaint();
    }
}

}

9rbhqvlz

9rbhqvlz1#

重要的是要了解 paintComponent 方法只是按组件在某个时刻出现的样子绘制组件——它不是一个进行动画的地方。
我对你的代码做了两个小改动,让你明白这一点:
把循环和睡眠从 paintComponent .
添加了一个计时器 oneX 以及 oneY 并触发你的 DrawPanel .
你会想做更复杂的x和y坐标更新,你会想画更多的东西 paintComponent ,但我希望这能让你开始。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

final public class SwingTest
{

    JFrame frame;
    DrawPanel drawPanel;

    private int oneX = 7;
    private int oneY = 7;

    public static void main(String... args)
    {
        new SwingTest().go();
    }

    private void go()
    {
        frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        drawPanel = new DrawPanel();

        frame.getContentPane().add(BorderLayout.CENTER, drawPanel);

        frame.setResizable(false);
        frame.setSize(1920, 1000);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
        // added this timer, which updates every 100ms
        Timer timer = new Timer(100, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // move the box
                oneX += 1;
                oneY += 1;
                drawPanel.repaint();
            }
        });
        timer.start();
    }

    class DrawPanel extends JPanel
    {
        private static final long serialVersionUID = 1L;

        public void paintComponent(Graphics g)
        {
            g.setColor(Color.BLUE);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());
            g.setColor(Color.RED);
            g.fillRect(3, 3, this.getWidth() - 6, this.getHeight() - 6);
            g.setColor(Color.WHITE);
            g.fillRect(6, 6, this.getWidth() - 12, this.getHeight() - 12);
            g.setColor(Color.BLACK);
            g.fillRect(oneX, oneY, 6, 6);
            // removed your loop
        }
    }
}

以后要考虑的另一个技巧是:为要显示的每个对象创建一个类,并拥有该类的示例列表,而不是为对象的每个属性创建单独的列表。这样,在创建新对象时只有一个插入操作,一个 get 从列表中可以获得绘制或更新它所需的所有属性。

相关问题