Ява - построение синусоид

Я использую следующий код для генерации синусоиды: Синусоидальная волна
Скорость этой анимации медленная-быстрая-медленная. Код:

public static final double SINE_TO_180 = 114.58865012930961, TIMES = 180, SINE_OF_90 = Math.sin(Math.toRadians(90));

public static void main(String[] args) throws Exception{
    float velc = 200;
    float angle = 45;
    float resistance = 0f;
    double multiple = (velc * 2.5 / SINE_TO_180);
    int offset = 0;
    double y = 0;
    double x = 0;
    double h = 0;
    double cos = Math.cos(Math.toRadians(angle));
    double sin = Math.sin(Math.toRadians(angle));
    for(int i = offset; i < TIMES + 1 + offset; i ++){
        y += ((Math.sin(Math.toRadians(i * 2)))) * multiple * sin;
        if(y >= h)
            h = y;
        x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
//          x += multiple * cos;
//          if(i + offset < TIMES / 2){
//              x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
//          }else{
//              x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
//          }
    }
    y = Math.round(y);
    //do round x?
    x = Math.round(x);
    System.out.println("X: " + x);
    JFrame frm = new JFrame("Projectile!");
    frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    BufferedImage b = new BufferedImage((int)x + 1, (int)h + 1, BufferedImage.TYPE_INT_RGB);
    Graphics g = b.getGraphics();
    y = 0;
    x = 0;

    JLabel l = new JLabel(new ImageIcon(b));
    frm.add(l);
    frm.pack();
    frm.setVisible(true);

    for(int i = offset; i < TIMES + 1 + offset; i ++){
        y += ((Math.sin(Math.toRadians(i * 2)))) * multiple * sin;

        x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
 //         x += multiple * cos;
//          if(i + offset < TIMES / 2){
//              x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
//          }else{
//              x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
//          }
        g.setColor(Color.red);
        g.drawLine((int)x, (int)(h - y), (int)x, (int)(h - y));
        l.setIcon(new ImageIcon(b));
        frm.repaint();
        Thread.sleep((int)(1000.0 / 24.0));
    }
    ImageIO.write(b, "png", new File("C:\\proj.png"));
}

Теперь я хотел бы изменить синусоидальную анимацию на быструю-медленную-быструю, где она медленная на пике, поэтому я попробовал следующий результат и получил это:
SineWave2
Я ожидаю, что он будет одинаковым, только разная скорость анимации. Код:

public static void main(String[] args) throws Exception{
    float velc = 200;
    float angle = 45;
    float resistance = 0f;
    double multiple = (velc * 2.5 / SINE_TO_180);
    int offset = 0;
    double y = 0;
    double x = 0;
    double h = 0;
    double cos = Math.cos(Math.toRadians(angle));
    double sin = Math.sin(Math.toRadians(angle));
    for(int i = offset; i < TIMES + 1 + offset; i ++){
        y += (1 - Math.sin(Math.toRadians(i * 2))) * multiple * sin;
        if(y >= h)
            h = y;
//          x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
        x += 2;
        //          x += multiple * cos;
//          if(i + offset < TIMES / 2){
//              x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
//          }else{
//              x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
//          }
    }
    y = Math.round(y);
    //do round x?
    x = Math.round(x);
    System.out.println("X: " + x);
    JFrame frm = new JFrame("Projectile!");
    frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    BufferedImage b = new BufferedImage((int)x + 1, (int)h + 1, BufferedImage.TYPE_INT_RGB);
    Graphics g = b.getGraphics();
    y = 0;
    x = 0;

    JLabel l = new JLabel(new ImageIcon(b));
    frm.add(l);
    frm.pack();
    frm.setVisible(true);

    for(int i = offset; i < TIMES + 1 + offset; i ++){
        y += (1 - Math.sin(Math.toRadians(i * 2))) * multiple * sin;
        x += 2;
//          x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
//          x += multiple * cos;
//          if(i + offset < TIMES / 2){
//              x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
//          }else{
//              x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
//          }
        g.setColor(Color.red);
        g.drawLine((int)x, (int)(h - y), (int)x, (int)(h - y));
        l.setIcon(new ImageIcon(b));
        frm.repaint();
        Thread.sleep((int)(1000.0 / 24.0));
    }
    ImageIO.write(b, "png", new File("C:\\proj2.png"));
}

Кто-нибудь знает, что я делаю не так, потому что я ожидаю, что результат будет таким же, как у первого, только с другой скоростью анимации?

1 ответ

Решение

Если вы хотите иметь плавную анимацию, я бы разделил данные и анимацию;

сначала создайте свои данные - это (математическая) функция [имеется в виду f(x)->y], так что вы можете просто использовать массив для данных

private int endOfX = 100; //adjust as you wish
private int[] data;
public void calculateData(){
    data = new int[amendOfX ountPixels];
    for(int x = 0; x < endOfX ; x++){
        y = x*x; //this is an example, use your mathematical function here
    }
}

так что - теперь вы можете легко использовать эти данные для обеспечения плавной анимации

public class AnimationOfFunction(){
    public static void main(String[] args){
        new AnimationOfFunktion().createAndShowGui(); //as from java tutorials
    }

    private BufferedImage img;
    private Graphics gr;
    private void createAndShowGui(){
        calculateData(); first of all we create the data!
        JFrame frame = new JFrame();//then create your frame here
        JPanel panel = createContent(); //create your drawing panel here
        frame.add(panel);//adding drawing panel
        frame.pack(); //setting the proper size of frame
        frame.setVisible(true); //show frame          
        startAnimation(panel); //this is important - after showing the frame you start your animation here!
    }
}

так что - это будет началом вашего приложения, что теперь делать? Сначала создайте правильную панель рисования:

private JPanel createContent(){
    //create a anonym class
    @surpress serial
    JPanel panel = new JPanel(){

        @override
        public void paintComponent(Graphics gr){
            super.paintComponent(gr);
            gr.drawImage(img, 0,0, null);
        }

    } 
    panel.setPreferredSize(new Dimension(img.getWidth(), img.getHeight() ));
    return panel;
}

и самое главное - вы должны запустить анимацию:

private void startAnimation(final JPanel panel){
    //create a anonym class
    Runnable r = new Runnable(){
        private int py = 0; //previous values
        private int py = 0; //previous values
        @overrdie
        public void run(){
            for(int x = 0; x < endOfX ; x++){
                int y = data[x];
                //now we have x and y, so you can plot your function;
                gr.drawLine(px, py, x,y); //you can scale here
                int sleeptime = calculateSleepTime(px,py, x,y);
                Thread.sleep(sleeptime);

                //set the previouse values;
                px = x;
                py = y;

                //important - repaint your panel to create an 'animation'
                panel.repaint();

            }
        }
    }

    //having that runnable we must start that runnable within an thread
    Thread thread = new Thread(r);
    thread.setDaemon(true);
    thread.start();
}

так что же делать дальше? мы должны рассчитать время сна: если расстояние между двумя точками "большое", мы спим дольше, если расстояние короткое, мы спим меньше...

public int calculateSleeptime(int px, int py, int x, int y){
    int distance = (y-py)*(y-py)+(x-px)*(x-px);
    distance = (int)(Math.sqrt(distance);
    int sleepTime = distance*100; //play with this value!
    return sleeptime;
}

Я написал этот код полностью из моей головы, у меня не было какой-либо IDE, чтобы проверить, содержит ли он орфографические ошибки или ошибки компиляции, пожалуйста, сделайте это для себя, а также я не инициировал BufferedImage img ang Graphics gr, но очевидно, что вы уже можете это сделать!

Другие вопросы по тегам