forked from finneyj/SolarSystem
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SolarSystem.java
247 lines (224 loc) · 8.88 KB
/
SolarSystem.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.util.*;
/**
* This class provides a graphical user interface to a model of the solar system
* @author Joe Finney
*/
public class SolarSystem extends JFrame
{
private int width = 300;
private int height = 300;
private boolean exiting = false;
private Map<RenderingHints.Key, Object> renderingHints;
private ArrayList<SolarObject> things = new ArrayList<SolarObject>();
/**
* Create a view of the Solar System.
* Once an instance of the SolarSystem class is created,
* a window of the appropriate size is displayed, and
* objects can be displayed in the solar system
*
* @param width the width of the window in pixels.
* @param height the height of the window in pixels.
*/
public SolarSystem(int width, int height)
{
this.width = width;
this.height = height;
this.setTitle("The Solar System");
this.setSize(width, height);
this.setBackground(Color.BLACK);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
renderingHints = new HashMap<>();
renderingHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
renderingHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
renderingHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
renderingHints.put(RenderingHints.KEY_FRACTIONALMETRICS,RenderingHints.VALUE_FRACTIONALMETRICS_ON);
renderingHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
renderingHints.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
renderingHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
}
/**
* A method called by the operating system to draw onto the screen - <p><B>YOU DO NOT (AND SHOULD NOT) NEED TO CALL THIS METHOD.</b></p>
*/
public void paint (Graphics gr)
{
if (renderingHints == null)
return;
BufferedImage i = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = i.createGraphics();
Graphics2D window = (Graphics2D) gr;
g.setRenderingHints(renderingHints);
window.setRenderingHints(renderingHints);
synchronized (this)
{
if (!this.exiting)
{
g.clearRect(0,0,width,height);
for(SolarObject t : things)
{
g.setColor(t.col);
g.fillOval(t.x, t.y, t.diameter, t.diameter);
//try{ Thread.sleep(0); } catch (Exception e) {}
}
}
window.drawImage(i, 0, 0, this);
}
}
//
// Shouldn't really handle colour this way, but the student's haven't been introduced
// to constants properly yet, and Color.getColor() doesn't seem to work... hmmm....
//
private Color getColourFromString(String col)
{
Color color;
if (col.charAt(0) == '#')
{
color = new Color(
Integer.valueOf( col.substring( 1, 3 ), 16 ),
Integer.valueOf( col.substring( 3, 5 ), 16 ),
Integer.valueOf( col.substring( 5, 7 ), 16 ) );
}
else
{
try
{
java.lang.reflect.Field field = Color.class.getField(col);
color = (Color)field.get(null);
} catch (Exception e) {
color = Color.WHITE;
}
}
return color;
}
/**
* Draws a round shape in the window at the given co-ordinates that represents an object in the solar system.
* The SolarSystem class uses <i>Polar Co-ordinates</i> to represent the location
* of objects in the solar system.
*
* @param distance the distance from the sun to the object.
* @param angle the angle (in degrees) that represents how far the planet is around its orbit of the sun.
* @param diameter the size of the object.
* @param col the colour of this object, as a string. Case insentive. <p>One of: BLACK, BLUE, CYAN, DARK_GRAY, GRAY, GREEN, LIGHT_GRAY,
* MAGENTA, ORANGE, PINK, RED, WHITE, YELLOW. Alternatively, a 24 bit hexadecimal string representation of an RGB colour is also accepted, e.g. "#FF0000"</p>
*/
public void drawSolarObject(double distance, double angle, double diameter, String col)
{
Color colour = this.getColourFromString(col);
double centreOfRotationX = ((double) width) / 2.0;
double centreOfRotationY = ((double) height) / 2.0;
double rads = Math.toRadians(angle);
double x = (int) (centreOfRotationX + distance * Math.sin(rads)) - diameter / 2;
double y = (int) (centreOfRotationY + distance * Math.cos(rads)) - diameter / 2;
synchronized (this)
{
if (things.size() > 1000)
{
System.out.println("\n\n");
System.out.println(" ********************************************************* ");
System.out.println(" ***** Only 1000 Entities Supported per Solar System ***** ");
System.out.println(" ********************************************************* ");
System.out.println("\n\n");
System.out.println("If you are't trying to add this many things");
System.out.println("to your SolarSystem, then you have probably");
System.out.println("forgotten to call the finishedDrawing() method");
System.out.println("See the JavaDOC documentation for more information");
System.out.println("\n-- Joe");
System.out.println("\n\n");
this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
}
else
{
SolarObject t = new SolarObject((int)x, (int)y, (int)diameter, colour);
things.add(t);
}
}
}
/**
* Draws a round shape in the window at the given co-ordinates.
* The SolarSystem class uses <i>Polar Co-ordinates</i> to represent the location
* of objects in the solar system. This method operates in the same fashion as drawSolarObject, but
* provides additional co-ordinates to allow the programmer to use an arbitrary point about which
* the object orbits (e.g. a planet rather than the sun).
*
* @param distance the distance from this object to the point about which it is orbiting.
* @param angle the angle (in degrees) that represents how far the object is around its orbit.
* @param diameter the size of the object.
* @param col the colour of this object, as a string. Case insentive. <p>One of: BLACK, BLUE, CYAN, DARK_GRAY, GRAY, GREEN, LIGHT_GRAY,
* MAGENTA, ORANGE, PINK, RED, WHITE, YELLOW</p>
* @param centreOfRotationDistance the distance part of the polar co-ordinate about which this object orbits.
* @param centreOfRotationAngle the angular part of the polar co-ordinate about which this object orbits.
*/
public void drawSolarObjectAbout(double distance, double angle, double diameter, String col, double centreOfRotationDistance, double centreOfRotationAngle)
{
Color colour = this.getColourFromString(col);
double centrerads = Math.toRadians(centreOfRotationAngle);
double centreOfRotationX = (((double) width) / 2.0) + centreOfRotationDistance * Math.sin(centrerads);
double centreOfRotationY = (((double) height) / 2.0) + centreOfRotationDistance * Math.cos(centrerads);
double rads = Math.toRadians(angle);
double x = (int) (centreOfRotationX + distance * Math.sin(rads)) - diameter / 2;
double y = (int) (centreOfRotationY + distance * Math.cos(rads)) - diameter / 2;
synchronized (this)
{
if (things.size() > 1000)
{
System.out.println("\n\n");
System.out.println(" ********************************************************* ");
System.out.println(" ***** Only 1000 Entities Supported per Solar System ***** ");
System.out.println(" ********************************************************* ");
System.out.println("\n\n");
System.out.println("If you are't trying to add this many things");
System.out.println("to your SolarSystem, then you have probably");
System.out.println("forgotten to call the finishedDrawing() method");
System.out.println("See the JavaDOC documentation for more information");
System.out.println("\n-- Joe");
System.out.println("\n\n");
this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
}
else
{
SolarObject t = new SolarObject((int)x, (int)y, (int)diameter, colour);
things.add(t);
}
}
}
/**
* Updates the window to show all objects that have recently been drawn using
* drawSolarObject() or drawSolarObjectAbout().
*
* The method also waits for 20 milliseconds (1/50th of one second) and then
* clears the screen.
*/
public void finishedDrawing()
{
try
{
this.repaint();
Thread.sleep(20);
synchronized (this)
{
things.clear();
}
}
catch (Exception e) { }
}
private class SolarObject
{
public int x;
public int y;
public int diameter;
public Color col;
public SolarObject(int x, int y, int diameter, Color col)
{
this.x = x;
this.y = y;
this.diameter = diameter;
this.col = col;
}
}
}