Плавная анимация фрактального дерева

У меня есть программа на Java, которая будет рисовать фрактальное дерево на основе рекурсивного метода, и я хочу, чтобы оно плавно росло, и я не уверен, как это сделать.

Ниже приведен мой код. Это школьное задание, просто чтобы об этом знали, но основное задание состояло в том, чтобы нарисовать фрактальное дерево, которое я уже выполнил, анимация второстепенна и больше является личной целью, которую я хочу выполнить.

package Question4;

import java.awt.BasicStroke;
import java.awt.Canvas; 
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;

public class FractalTree1 extends Canvas {

  // fields for drawing
  private JFrame frame;
  private final int WINDOW_WIDTH = 1280;
  private final int WINDOW_HEIGHT = 720;

  public FractalTree1() {
    frame = new JFrame("Fractal Tree");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    frame.setLocationRelativeTo(null);
    frame.setResizable(true);
    frame.add(this);
    frame.setVisible(true);
  }

  public static void main(String[] args) {
    FractalTree1 ft = new FractalTree1();
    ft.setVisible(true);
    ft.setBackground(Color.black);
  }

  @Override
  public void paint(Graphics g) {
    g.setColor(Color.green);
    drawFractalTree(g, WINDOW_WIDTH / 2, WINDOW_HEIGHT - 75, -90, 11);
  }

  public void drawFractalTree(Graphics g, int x1, int y1, double angle, int depth) {
    if (depth == 0) {
    } else {
      int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 10.0);
      int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 10.0);

      Graphics2D g2d = (Graphics2D) g;
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,     RenderingHints.VALUE_ANTIALIAS_ON);

      g2d.setStroke(new BasicStroke(0.5f * depth));
      g2d.drawLine(x1, y1, x2, y2);

      drawFractalTree(g, x2, y2, angle + 30, depth - 1);
      drawFractalTree(g, x2, y2, angle - 30, depth - 1);
    }
  } 
}

РЕДАКТИРОВАТЬ В качестве продолжения сейчас... когда я добавляю к нему Thread.sleep(), он рисует его неловко, так как это рисует рекурсия. Можно ли заставить его рисовать от «ствола» вверх, чтобы он имитировал «растущее» настоящее дерево?


person rlowdon    schedule 28.03.2013    source источник


Ответы (3)


Чтобы это заработало, вам, вероятно, потребуется использовать двойную буферизацию. По сути, вы рисуете внеэкранный буфер и обновляете его на экране, когда рисование завершено.

В вашем методе drawFractalTree() вам нужно будет добавить вызов Thread.sleep() для задержки рисования. Добавляем это сразу после g2d.drawLine(x1, y1, x2, y2); должен сделать трюк. Это может закончиться очень медленно. Чтобы обуздать это, вы можете использовать счетчик и спать в течение 1 мс после каждого 10-го вызова.

person Jaco Van Niekerk    schedule 28.03.2013
comment
Знаете ли вы, как сделать так, чтобы анимация начиналась со ствола и двигалась вверх, имитируя рост дерева? - person rlowdon; 28.03.2013
comment
Хммм... это потребует некоторого расследования, но я думаю, что это будет очень сложно. Помните, что то, что вы рисуете, является фракталом, а не деревом... заставить фрактал вести себя как дерево, все равно что просить слона, рисующего бушмена, трубить. - person Jaco Van Niekerk; 31.03.2013

Чтобы просто начать видеть анимацию, добавьте вызов Thread.sleep(100) в начале drawFractalTree().

person Ray Stojonic    schedule 28.03.2013
comment
Я думаю, это не сработает... Потребуется repaint(), и даже тогда предыдущее построение исчезнет, ​​оставив на экране прыгающую точку - если повезет. :) - person Jaco Van Niekerk; 31.03.2013

Thread.sleep(100);

Это отлично работает, если вы используете изображение для рисования из его графики, а не рисуете напрямую. Таким образом, цвет пикселей изображения не будет меняться каждый раз, когда вы что-то рисуете на нем.

package Question4;

import java.awt.BasicStroke;
import java.awt.Canvas; 
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;

public class FractalTree1 extends Canvas {

// fields for drawing
private JFrame frame;
private final int WINDOW_WIDTH = 1280;
private final int WINDOW_HEIGHT = 720;

private Image buffer = createImage(WINDOW_WIDTH,WINDOW_HEIGHT);
private Graphics bufferg = buffer.getGraphics();
public FractalTree1() {
    frame = new JFrame("Fractal Tree");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    frame.setLocationRelativeTo(null);
    frame.setResizable(true);
    frame.add(this);
    frame.setVisible(true);
}

public static void main(String[] args) {
   FractalTree1 ft = new FractalTree1();
   ft.setVisible(true);
   ft.setBackground(Color.black);
   bufferg.setColor(Color.green);
}

@Override
public void paint(Graphics g) {
    g.drawImage(buffer,0,0,null);
    drawFractalTree(g, WINDOW_WIDTH / 2, WINDOW_HEIGHT - 75, -90, 11);
}

public void drawFractalTree(Graphics g, int x1, int y1, double angle, int depth) {

    if (depth == 0) {
    } else {
    Thread.sleep(100);//It has a catch exception here;
    int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 10.0);
    int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 10.0);

    Graphics2D g2d = (Graphics2D) bufferg;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,           RenderingHints.VALUE_ANTIALIAS_ON);

    g2d.setStroke(new BasicStroke(0.5f * depth));
    g2d.drawLine(x1, y1, x2, y2);
    repaint();
    drawFractalTree(g, x2, y2, angle + 30, depth - 1);
    drawFractalTree(g, x2, y2, angle - 30, depth - 1);
    }
   } 
}
person PeGiannOS    schedule 10.02.2014