I should be getting a tree. But I am not getting a tree. I am getting a long thing, not a tree.
This is my code:
Main.java
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
public Main() {
setTitle("Tree");
setDefaultCloseOperation(EXIT_ON_CLOSE);
//setResizable(false);
add(new TreeDrawer(), BorderLayout.CENTER);
getContentPane().setBackground(Color.BLACK);
//button shit
JButton generate = new JButton("Generate");
generate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
TreeDrawer.generate();
repaint();
}
});
add(generate, BorderLayout.SOUTH);
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new Main();
});
}
}
TreeDrawer.java
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import javax.swing.JComponent;
public class TreeDrawer extends JComponent {
private static final long serialVersionUID = 1L;
public static final int ROOM_WIDTH = 1080;
public static final int ROOM_HEIGHT = 720 - 47;// 47 is the height of menu bar on top of jframe or some shit
static double len = 100; the length of each branch shit
public TreeDrawer() {
setPreferredSize(new Dimension(ROOM_WIDTH, ROOM_HEIGHT));
}
private static String axiom = "F";
private static String sentence = axiom;
private static Graphics2D graphics;
//this shit will change on vary of l system, new rules and etc
private static String rules(char a) {
if(a == 'F')//a rule
return "FF+[+F-F-F]-[-F+F+F]";
return "";//if nothing else works, shit
}
//generates the whole shit
//probably correct
public static void generate() {
len *= 0.5;//shrink the shit
String nextSentence = "";
for(int i = 0; i < sentence.length(); i++) {
char current = sentence.charAt(i);
nextSentence += rules(current);
}
sentence = nextSentence;
System.out.println(sentence);
turtle();
}
public static void turtle() {
AffineTransform transform = null;//so you can save shit
for(int i = 0; i < sentence.length(); i++) {
char current = sentence.charAt(i);
if(current == 'F') {//draw up
graphics.drawLine(0, 0, 0, (int) -len);
graphics.translate(0, -len);
}
else if(current == '+') {//right turn
graphics.rotate(Math.PI / 6);
}
else if(current == '-') {//left turn
graphics.rotate(-Math.PI / 6);
}
//probably wrong shit
else if(current == '[') {//save transformations
transform = graphics.getTransform();
}
//also probably wrong shit
else if(current == ']') {//restore from last save
graphics.setTransform(transform);
}
}
}
@Override
public void paintComponent(Graphics g) {//so that shit is drawn
graphics = (Graphics2D) g;
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
super.paintComponent(graphics);
graphics.translate(ROOM_WIDTH / 2, ROOM_HEIGHT - 10);
graphics.setPaint(Color.WHITE);
turtle();
}
}
What did I do wrong. I can not figure out how to post a screenshot of the output that I got, but it looks completely off of what is correct. I know that my algorithm of the L-system is right, because that is working well. But I think that when I try to save and restore the transformation state, something goes wrong. Saving the transformation state is the brackets ([ and ]. '[' saves, ']' restores from that save). But I do not know what is wrong. I need help to find what is wrong. Thank you.
Graphics
, you should not maintain a reference to it for any longer than you need to use it. Instead, you should pass it as a parameter to the methods that need to use it. This will save you from some serious weird artefacts and possible NullPointerException
sGraphics
context, you'd best to create a copy of it before you do, as it's a shared resource between all components getting painted.static
is NOT your friend and is poor design.Taking all that into account, something like the following works...at a basic level
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
private TreeDrawer treeDrawer;
public Main() {
setTitle("Tree");
setDefaultCloseOperation(EXIT_ON_CLOSE);
//setResizable(false);
treeDrawer = new TreeDrawer();
add(treeDrawer, BorderLayout.CENTER);
getContentPane().setBackground(Color.BLACK);
//button shit
JButton generate = new JButton("Generate");
generate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
treeDrawer.generate();
repaint();
}
});
add(generate, BorderLayout.SOUTH);
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new Main();
});
}
public class TreeDrawer extends JComponent {
private static final long serialVersionUID = 1L;
public static final int ROOM_WIDTH = 1080;
public static final int ROOM_HEIGHT = 720 - 47;// 47 is the height of menu bar on top of jframe or some shit
double len = 100;
public TreeDrawer() {
setPreferredSize(new Dimension(ROOM_WIDTH, ROOM_HEIGHT));
}
private String axiom = "F";
private String sentence = axiom;
private String rules(char a) {
if (a == 'F')//a rule
{
return "FF+[+F-F-F]-[-F+F+F]";
}
return "";//if nothing else works, shit
}
//probably correct
public void generate() {
len *= 0.5;//shrink the shit
String nextSentence = "";
for (int i = 0; i < sentence.length(); i++) {
char current = sentence.charAt(i);
nextSentence += rules(current);
}
sentence = nextSentence;
System.out.println(sentence);
// turtle();
}
public void turtle(Graphics2D graphics) {
AffineTransform transform = null;//so you can save shit
for (int i = 0; i < sentence.length(); i++) {
char current = sentence.charAt(i);
if (current == 'F') {//draw up
graphics.drawLine(0, 0, 0, (int) -len);
graphics.translate(0, -len);
} else if (current == '+') {//right turn
graphics.rotate(Math.PI / 6);
} else if (current == '-') {//left turn
graphics.rotate(-Math.PI / 6);
} //probably wrong shit
else if (current == '[') {//save transformations
transform = graphics.getTransform();
} //also probably wrong shit
else if (current == ']') {//restore from last save
graphics.setTransform(transform);
}
}
}
@Override
public void paintComponent(Graphics g) {//so that shit is drawn
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
super.paintComponent(g2d);
g2d.translate(ROOM_WIDTH / 2, ROOM_HEIGHT - 10);
g2d.setPaint(Color.WHITE);
turtle(g2d);
g2d.dispose();
}
}
}