-
Notifications
You must be signed in to change notification settings - Fork 0
/
Building.java
134 lines (118 loc) · 5.07 KB
/
Building.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D;
import java.util.ArrayList;
public class Building
{
public static final ArrayList<Color> COLORS = new ArrayList<Color>();
static //initialize the possible building colors
{
COLORS.add(Color.black);
COLORS.add(new Color(64, 64, 64)); //dark gray
COLORS.add(new Color(136, 45, 23)); //sienna
COLORS.add(new Color(25, 25, 112)); //midnight blue
COLORS.add(Color.white);
COLORS.add(new Color(192, 192, 192)); //light gray
}
public static final Color COLOR_WINDOW = Color.yellow;
public static final int WIDTH_MIN = 70, WIDTH_MAX = 120; //min and max possible width of a building, in pixels
public static final int HEIGHT_MIN = 100, HEIGHT_MAX = 400; //min and max possible height of a building, in pixels
//the width of the sky border of each building
public static final int SKY_STROKE_WIDTH = 3;
//windows are square with that size, and there are that many pixels in the gap between adjacent windows
public static final int WINDOW_SIZE = 6, WINDOW_GAP = 12;
//private data
private static RandomTools random = new RandomTools();
/*
* This is the index of the color of the most recently constructed building in the COLORS arraylist.
* every time a new building is constructed, this value is incremented, so that the building colors are rotated through.
*/
private static int colorIndex = 0;
/*
* The leftX coordinate is stored with double precision because when the building is translated left during a frame, it may move by a fraction
* of a pixel, and precision greater than whole numbers is necessary.
*/
private double leftX;
//In contrast, the bottomY coordinate is stored as an integer because it should be an integer.
private int bottomY;
private Color color; //the building's color
private int width, height;
/**
* Construct a building, with the coordinate of the lower left of the building at the given point.
* The building's color, width, and height are randomly chosen.
*/
public Building (double leftX, int bottomY)
{
this.leftX = leftX;
this.bottomY = bottomY;
width = random.randRange(WIDTH_MIN, WIDTH_MAX);
height = random.randRange(HEIGHT_MIN, HEIGHT_MAX);
//get the next color
color = COLORS.get(colorIndex);
colorIndex++;
if (colorIndex >= COLORS.size())
{
colorIndex = 0;
}
}
/**
* Render the building on the provided Graphics. All drawing operations will be performed, even if the building is offscreen.
*/
public void render (Graphics2D g)
{
//round both x and y coordinates of the building's lower left x and y to integers.
int leftX = (int) Math.round(this.leftX); //the x coordinate of the left edge of the building
int rightX = leftX + width;
int topY = bottomY - height;
//draw the building rectangle. (rectangle drawing begins at top left corner)
g.setColor(color);
g.fillRect(leftX, topY, width, height);
//draw the sky borders
g.setColor(Painter.COLOR_SKY);
g.setStroke(new BasicStroke(SKY_STROKE_WIDTH));
g.drawLine(leftX, bottomY, leftX, topY);
g.drawLine(leftX, topY, rightX, topY);
g.drawLine(rightX, topY, rightX, bottomY);
//draw windows
g.setColor(COLOR_WINDOW);
/*
* the number of windows that fit in a row on the building.
* each window takes up WINDOW_SIZE + WINDOW_GAP, so the number of windows that will fit in a row of size "width" is
* the floor of width / (WINDOW_SIZE + WINDOW_GAP).
*/
int numWindows = width / (WINDOW_SIZE + WINDOW_GAP);
/*
* numWindows windows will be spaced out with WINDOW_GAP between adjacent windows and centered on the building.
* The distance between the left edge of the leftmost window and the right edge of the rightmost window is:
* rowWidth = numWindows * WINDOW_SIZE + (numWindows - 1) * WINDOW_GAP
* The distance between the left edge of the building and the left edge of the leftmost window is:
* the floor of (width - rowWidth) / 2
* Add this distance to the x-coordinate of the left edge of the building to get the x-coordinate of the left edge of the leftmost window
*/
int windowLeftX = leftX + (width - (numWindows * WINDOW_SIZE + (numWindows - 1) * WINDOW_GAP)) / 2;
//iterate from left to right through the possible x coordinates for the left edge of the window
for (int i = 0; i < numWindows; i++)
{
//iterate from top to bottom through the possible y coordinates for the top edge of the window
for (int windowTopY = topY + WINDOW_GAP; bottomY - windowTopY >= 2*WINDOW_SIZE + 3*WINDOW_GAP/2 ; windowTopY += WINDOW_SIZE + WINDOW_GAP)
{
g.fillRect(windowLeftX, windowTopY, WINDOW_SIZE, WINDOW_SIZE);
}
//this is the x-coordinate of the left edge of the window to the right of the current window
windowLeftX += WINDOW_SIZE + WINDOW_GAP;
}
}
//animation methods
/**
* Translates the building LEFT by the given distance.
*/
public void translateLeft (double distance)
{
leftX -= distance;
}
/**
* Returns if the building is so far LEFT that it cannot be seen on the screen; true if offscreen, false if onscreen.
*/
public boolean isOffscreenLeft ()
{
return leftX + width < 0;
}
}