Completing a graphics program in Java, I'm trying to animate rain falling using a timer. Right now I am testing my code with a big blue rectangle so I can see where it's going but the animation isn't working for me. I'm very new to Java graphics so I could be making mistakes that just aren't clear to me.
When I try to repaint the square to move, and the paint function is called the whole screen blinks, this may be because I was using recursive functions to draw fractal trees, but I'm not sure. Is there a way to keep everything I have drawn from being repainted and just call repaint on the rain? Any guidance or tips would be appreciated.
import java.awt.*;
import javax.swing.*;
import java.lang.Math;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class FractalTree extends JFrame {
private int frameWidth = 1440;
private int frameHeight = 850;
private int rainX = 0;
private int rainY = 0;
public FractalTree()
{
setBounds(1000, 1000, frameWidth, frameHeight ); //graphics window size
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ActionListener listener = new TimerListener();
final int DELAY = 1500;
Timer t = new Timer(DELAY, listener);
t.start();
setResizable(false);
}
public void setRain(int newRainX, int newRainY)
{
rainX = newRainX;
rainY = newRainY;
}
public void setSkyGround(Graphics g)
{
Color sky = new Color(180, 225, 255);
g.setColor(sky);
g.fillRect(0, 0, frameWidth, 550);
Color sun = new Color(225, 225, 150);
g.setColor(sun);
g.fillOval(1380, -40, 100, 100);
g.drawLine(frameWidth, 0, 1350, 550);
g.drawLine(frameWidth, 0, 1450, 550);
g.drawLine(1350, 550, 1450, 550);
int xpoints[] = {frameWidth, 1450, 1350};
int ypoints[] = {0, 550, 550};
int npoints = 3;
g.fillPolygon(xpoints, ypoints, npoints);
g.drawLine(frameWidth, 0, 1080, 550);
g.drawLine(frameWidth, 0, 880, 550);
g.drawLine(880, 550, 1080, 550);
int xpoints2[] = {frameWidth, 1080, 880};
int ypoints2[] = {0, 550, 550};
int npoints2 = 3;
g.fillPolygon(xpoints2, ypoints2, npoints2);
g.drawLine(frameWidth, 0, 480, 550);
g.drawLine(frameWidth, 0, 280, 550);
g.drawLine(480, 550, 280, 550);
int xpoints3[] = {frameWidth, 480, 280};
int ypoints3[] = {0, 550, 550};
int npoints3 = 3;
g.fillPolygon(xpoints3, ypoints3, npoints3);
g.drawLine(frameWidth, 0, 0, 430);
g.drawLine(frameWidth, 0, 0, 300);
g.drawLine(0, 430, 0, 300);
int xpoints4[] = {frameWidth, 0, 0};
int ypoints4[] = {0, 430, 300};
int npoints4 = 3;
g.fillPolygon(xpoints4, ypoints4, npoints4);
g.drawLine(frameWidth, 0, 0, 100);
g.drawLine(frameWidth, 0, 0, 0);
g.drawLine(0, 100, 0, 0);
int xpoints5[] = {frameWidth, 0, 0};
int ypoints5[] = {0, 0, 100};
int npoints5 = 3;
g.fillPolygon(xpoints5, ypoints5, npoints5);
Color grassBackground = new Color(150, 255, 170);
g.setColor(grassBackground);
g.fillRect(0, 550, frameWidth, frameHeight);
}
public void drawTree(Graphics g, int x1, int y1, double angle, int depth, int red, int green, int blue)
{
if (depth == 0)
{
Color doodle = new Color(red, green, blue);
g.setColor(doodle);
g.fillOval(x1, y1, 10, 10);
}
else
{
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(depth));
Color brown = new Color(100, 25, 0);
g.setColor(brown);
int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 10);
int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 10);
g.drawLine(x1, y1, x2, y2);
drawTree(g, x2, y2, angle - 40, depth - 1, red, green, blue);
drawTree(g, x2, y2, angle + 20, depth - 1, red, green, blue);
}
}
public void realFlowers(Graphics g, int x, int y, int lenWid, int petals)
{
//calculates the increment
double inc = (2*Math.PI/petals);
g.setColor(Color.YELLOW);
//draws petals
for(int i = 0; i < petals; i++){
//keeps spacing consistent depandng on number of petals
double value = i * inc;
//draws petals with calculated spacing relative to number of petals
g.fillOval((int)((lenWid)*Math.cos(value)+x-lenWid/4),(int)((lenWid)*Math.sin(value)+y-lenWid/4), lenWid + lenWid/2, lenWid + lenWid/2);
}
//draws middle flower bud;
g.setColor(Color.ORANGE);
g.fillOval(x - lenWid/4, y - lenWid/4, lenWid + lenWid/2 , lenWid + lenWid/2);
}
public void drawGrass(Graphics g, int width, int height, int interval, int red, int green, int blue)
{
height = frameHeight - height;
Color grass = new Color(red, green, blue);
for(int i = 0; i < width; i= i + interval)
{
for(int j = frameHeight; j > height; j = j - interval)
{
g.setColor(grass);
g.fillRect(i, j, 3, 5);
}
}
}
public void rainDrops(Graphics g, int x, int y, int w, int h)
{
setRain(x, y);
Color rain = new Color(0, 76, 153);
g.setColor(rain);
g.fillRect(x, y, w, h);
}
public void moveRainBy(int dx, int dy)
{
rainX = rainX + dx;
rainY = rainY + dy;
repaint();
}
class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
moveRainBy(1, 1);
}
}
public void paint(Graphics g) {
setSkyGround(g);
drawGrass(g, 1440, 315, 5, 0, 255, 0);
drawGrass(g, 1430, 310, 10, 0, 204, 0);
drawTree(g, 1085, 730, -90, 10, 255, 102, 102);
drawTree(g, 250, 600, -90, 8, 255, 255, 255);
drawTree(g, 1110, 740, -90, 4, 255, 102, 102);
drawTree(g, 1060, 745, -90, 2, 255, 102, 102);
realFlowers(g, 700,700, 8, 8);
rainDrops(g, 200, 200, 30, 30);
}
public static void main(String[] args) {
new FractalTree().setVisible(true);
}
}