/*
* File: Pyramid.java
* Name:
* Section Leader:
* ------------------
* This file is the starter file for the Pyramid problem.
* It includes definitions of the constants that match the
* sample run in the assignment, but you should make sure
* that changing these values causes the generated display
* to change accordingly.
*/
import acm.graphics.*;
import acm.program.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
public class Pyramid extends GraphicsProgram {
/** Width of each brick in pixels */
private static final int BRICK_WIDTH = 30;
/** Width of each brick in pixels */
private static final int BRICK_HEIGHT = 12;
/** Number of bricks in the base of the pyramid */
private static final int BRICKS_IN_BASE = 25;
private ArrayList<GRect> rects;
private ArrayList<ArrayList<GRect>> rectDiagonals;
public void run() {
generatePyramid();
setUpDiagonals();
animate();
}
private void generatePyramid() {
rects = new ArrayList<GRect>();
rectDiagonals = new ArrayList<ArrayList<GRect>>();
for(int i = 0; i < BRICKS_IN_BASE; i++) {
int yOffset = getHeight() - (i + 1) * BRICK_HEIGHT;
for(int j = 0; j < BRICKS_IN_BASE - i; j++) {
int xOffset = (getWidth() - (BRICKS_IN_BASE - i) * BRICK_WIDTH) / 2 + j * BRICK_WIDTH;
GRect rect = new GRect(xOffset, yOffset, BRICK_WIDTH, BRICK_HEIGHT);
rect.setFilled(true);
rects.add(rect);
add(rect);
}
}
}
private void setUpDiagonals() {
int initialIncrement = BRICKS_IN_BASE;
for(int i = 0; i < BRICKS_IN_BASE; i++) {
ArrayList<GRect> rectDiagonal = new ArrayList<GRect>();
int index = i;
int increment = initialIncrement;
for(int j = 0; j < BRICKS_IN_BASE - i; j++) {
rectDiagonal.add(rects.get(index));
index += increment;
increment --;
}
rectDiagonals.add(rectDiagonal);
}
}
private void animate() {
double initialHue = 0;
int hueStep = 0;
double hueStepSize = 200.0;
while(true) {
shiftColors();
double hue = hueStep / hueStepSize * 360;
double[] hsv = {hue, 0.7, 1};
double[] rgb = HSVToRGB(hsv);
Color color = new Color((int) rgb[0], (int) rgb[1], (int) rgb[2]);
for(int j = 0; j < rectDiagonals.get(0).size(); j++) {
rectDiagonals.get(0).get(j).setFillColor(color);
}
hueStep++;
if(hueStep >= hueStepSize)
hueStep = 0;
pause(50);
}
}
private void shiftColors() {
for(int i = rectDiagonals.size() - 1; i > 0; i--) {
int diag = i - 1;
Color color = rectDiagonals.get(diag).get(0).getFillColor();
for(int j = 0; j < rectDiagonals.get(i).size(); j++) {
rectDiagonals.get(i).get(j).setFillColor(color);
}
}
}
private double[] HSVToRGB(double[] hsv) {
double[] rgb = new double[3];
double c = hsv[2] * hsv[1];
double hp = hsv[0] / 60.0;
double x = c * (1 - Math.abs(hp % 2 - 1));
if (hp < 0) {
setRGB(rgb, 0, 0, 0);
}else if(hp < 1) {
setRGB(rgb, c, x, 0);
} else if(hp < 2) {
setRGB(rgb, x, c, 0);
} else if(hp < 3) {
setRGB(rgb, 0, c, x);
} else if(hp < 4) {
setRGB(rgb, 0, x, c);
} else if(hp < 5) {
setRGB(rgb, x, 0, c);
} else if(hp < 6) {
setRGB(rgb, c, 0, x);
} else {
setRGB(rgb, 0, 0, 0);
}
for(int i = 0; i < rgb.length; i++) {
rgb[i] += (hsv[2] - c);
rgb[i] *= 255;
}
return rgb;
}
private void setRGB(double[] rgb, double r, double g, double b) {
rgb[0] = r;
rgb[1] = g;
rgb[2] = b;
}
}