ColorfulAbstractGradient.java
1    /* 
2     * A program to paint an abstract gradient in the vertical direction. 
3     */
4    
5    package npw;
6    
7    import painter.SPainter;
8    import shapes.SCircle;
9    
10   import javax.swing.*;
11   import java.awt.*;
12   import java.util.Random;
13   import java.util.Scanner;
14   
15   public class ColorfulAbstractGradient {
16   
17       public static void main(String[] args) {
18           SwingUtilities.invokeLater(ColorfulAbstractGradient::new);
19       }
20   
21       public ColorfulAbstractGradient() {
22           paintTheImage();
23       }
24   
25       private void paintTheImage(){
26           // Grab the input information
27           int width = getNumber("width");
28           int height = getNumber("height");
29           int dotSpace = getNumber("horizontal space between dots");
30           // Establish the painter
31           SPainter painter = new SPainter("Abstract Gradient", width, height);
32           SCircle dot = new SCircle(5);
33   
34           // Move the painter to the upper left corner to get ready to paint the gradient
35           painter.mfd(height/2.0);
36           painter.tl();
37           painter.mfd(width/2.0);
38           painter.tl();
39   
40           // Paint it!
41           paintGradient(painter, dot, height, width, dotSpace);
42       }
43   
44       private static int getNumber(String prompt) {
45           String nss = JOptionPane.showInputDialog(null,prompt+"?");
46           Scanner scanner = new Scanner(nss);
47           return scanner.nextInt();
48       }
49   
50       private void paintGradient(SPainter painter, SCircle dot, int height, int width, int dotSpace){
51           // Calculate the number of columns. We want to fill the screen, but don't want any columns half on the canvas.
52           // A column takes up the horizontal space of a dot's diameter plus the space between it and a neighbor.
53           double colWidth = dot.diameter() + dotSpace;
54           // We don't want a column all the way on the edge on the right side, so subtract 1.
55           int nrOfCols = (int) Math.floor(( width / colWidth )) - 1;
56   
57           int cols = 0;
58           while (cols < nrOfCols){
59               nextCol(painter, dot, dotSpace);
60               paintColumn(painter, dot, height);
61               cols = cols + 1;
62           }
63       }
64   
65       private void paintOneDot(SPainter painter, SCircle dot){
66           painter.setColor(randomColor());
67           painter.paint(dot);
68           painter.setColor(Color.BLACK);
69       }
70   
71       private Color randomColor() {
72           Random rgen = new Random();
73           int r = rgen.nextInt(256);
74           int g = rgen.nextInt(256);
75           int b = rgen.nextInt(256);
76           return new Color(r,g,b);
77       }
78   
79       // Dots are spaced more tightly together near the bottom of the canvas.
80       private void paintColumn(SPainter painter, SCircle dot, int height) {
81           int totalDistanceTraveled = 0;
82   
83           // Paint a column with decreasing distance between dots.
84           while(totalDistanceTraveled < height - (dot.radius() * 3)) {
85               int travel = randomDistance((height - totalDistanceTraveled) / 4);
86               totalDistanceTraveled = totalDistanceTraveled + travel;
87               painter.mfd(travel);
88               paintOneDot(painter, dot);
89           }
90   
91           // Make the method invariant with respect to painter position.
92           painter.mbk(totalDistanceTraveled);
93       }
94   
95       // Moves the painter to the next column.
96       private void nextCol(SPainter painter, SCircle dot, int dotSpace){
97           painter.tl();
98           painter.mfd(dot.diameter() + dotSpace);
99           painter.tr();
100      }
101  
102      private int randomDistance(int maxDistance){
103          Random rgen = new Random();
104          return rgen.nextInt(maxDistance);
105      }
106  }
107