Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package solarsystem;
- import java.awt.Color;
- import java.awt.Dimension;
- import java.awt.GradientPaint;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.util.Observable;
- import java.util.Observer;
- import java.util.Random;
- import javax.swing.JComponent;
- import javax.swing.JFrame;
- import javax.swing.JPanel;
- import javax.swing.JSlider;
- import javax.swing.event.ChangeEvent;
- import javax.swing.event.ChangeListener;
- /**
- *
- * @author NDUNN
- * @date Jan 29, 2010
- */
- public class SolarSystemView extends JComponent implements Observer {
- // Make the sun this proportion of screen DEFAULT_WIDTH
- private static final double SUN_RADIUS_PROPORTION = 0.2;
- private static final double EARTH_RADIUS_PROPORTION = .3 * SUN_RADIUS_PROPORTION;
- private static final double MOON_RADIUS_PROPORTION = .2 * EARTH_RADIUS_PROPORTION;
- private static final double EARTH_DISTANCE_PROPORTION_SCREEN = 0.4;
- private static final double MOON_DISTANCE_PROPORTION_SCREEN = 0.1;
- private static final int DEFAULT_WIDTH = 640;
- private static final int DEFAULT_HEIGHT = 640;
- private static final int NUM_STARS = 100;
- private static final int MAX_STAR_RADIUS = 3;
- private static final double TWO_PI = 2.0 * Math.PI;
- private SolarSystemModel model;
- private Random random = new Random();
- private int[] starX;
- private int[] starY;
- private int[] starRadius;
- public SolarSystemView(SolarSystemModel model) {
- super();
- this.model = model;
- setPreferredSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
- createStarField(DEFAULT_WIDTH, DEFAULT_HEIGHT, MAX_STAR_RADIUS);
- }
- /**
- * Creates and populates our arrays of star x values, star y values, and
- * star radii
- * @param width what is max x value we should consider for star
- * @param height what is max y value we should consider for star
- */
- private void createStarField(int width, int height, int maxRadius) {
- // Create the arrays
- starX = new int[NUM_STARS];
- starY = new int[NUM_STARS];
- starRadius = new int[NUM_STARS];
- // Fill them in with random values
- for (int i = 0; i < NUM_STARS; i++) {
- starX[i] = random.nextInt(width);
- starY[i] = random.nextInt(height);
- starRadius[i] = random.nextInt(maxRadius);
- }
- }
- /**
- * Draws a black backdrop with star field
- * @param g2
- */
- private void drawSpaceBackdrop(Graphics2D g2) {
- // Draw background as black
- g2.setColor(Color.BLACK);
- g2.fillRect(0, 0, getWidth(), getHeight());
- g2.setColor(Color.WHITE);
- for (int i = 0; i < NUM_STARS; i++) {
- g2.fillOval(starX[i], starY[i], starRadius[i], starRadius[i]);
- }
- }
- /**
- *
- * @param g2 graphics context with (0,0) in center of screen (where sun will
- * be centered)
- */
- private void drawSun(Graphics2D g2) {
- int sunRadius = (int) (SUN_RADIUS_PROPORTION * getWidth());
- GradientPaint sunColor = new GradientPaint(0, 0, Color.YELLOW, 0, sunRadius, Color.RED);
- g2.setPaint(sunColor);
- g2.fillOval(-sunRadius/2, -sunRadius/2, sunRadius, sunRadius);
- }
- /**
- * Draws the earth to the screen, whose position is dependent upon the
- * day of the year
- * @param g2 the graphics context with its origin in the center of the sun
- */
- private void drawEarth(Graphics2D g2) {
- // Draw the earth
- // Calculate what portion along its orbit the earth is, and thus how
- // far to rotate about our centerpoint
- double earthTheta = map(model.getDay(), 0, SolarSystemModel.DAYS_PER_EARTH_REVOLUTION_AROUND_SUN, 0, TWO_PI);
- // Rotate our coordinate system by that much
- g2.rotate(earthTheta);
- // Translate the earth
- int distanceFromEarthToSun = (int) (EARTH_DISTANCE_PROPORTION_SCREEN * getWidth());
- g2.translate(distanceFromEarthToSun, 0);
- int earthRadius = (int) (EARTH_RADIUS_PROPORTION * getWidth());
- GradientPaint earthColor = new GradientPaint(0, 0, Color.BLUE, 0, earthRadius, Color.GREEN.darker(), true);
- g2.setPaint(earthColor);
- g2.fillOval(-earthRadius/2, -earthRadius/2, earthRadius, earthRadius);
- }
- /**
- * Draw the moon to the screen, whose position is dependent upon that of
- * the earth and the day of the year, which dictates its position along
- * its orbit around earth
- * @param g2 the graphics context with its origin in the center of the earth
- */
- private void drawMoon(Graphics2D g2) {
- double moonTheta = map(model.getDay(), 0, SolarSystemModel.DAYS_PER_MOON_ORBIT_AROUND_EARTH, 0, TWO_PI);
- int moonRadius = (int) (MOON_RADIUS_PROPORTION * getWidth());
- g2.setColor(Color.WHITE);
- g2.rotate(moonTheta);
- int distanceFromEarthToMoon = (int) (MOON_DISTANCE_PROPORTION_SCREEN * getWidth());
- // Translate the earth
- g2.translate(distanceFromEarthToMoon, 0);
- g2.fillOval(-moonRadius/2, -moonRadius/2, moonRadius, moonRadius);
- }
- @Override
- public void paintComponent(Graphics g) {
- Graphics2D g2 = (Graphics2D) g;
- drawSpaceBackdrop(g2);
- // Set the origin to be in the center of the screen
- g2.translate(getWidth()/2, getHeight()/2);
- // Order matters, since the earth placement is dependent upon the sun
- // placement, and the moon placement is dependent upon the earth placement
- drawSun(g2);
- drawEarth(g2);
- drawMoon(g2);
- }
- public static void main(String[] args) {
- JFrame frame = new JFrame("Solar System");
- final SolarSystemModel model = new SolarSystemModel();
- final SolarSystemView view = new SolarSystemView(model);
- model.addObserver(view);
- JPanel panel = new JPanel();
- panel.add(view);
- final JSlider daySlider = new JSlider(0,SolarSystemModel.DAYS_PER_EARTH_REVOLUTION_AROUND_SUN);
- daySlider.setPaintLabels(true);
- daySlider.setPaintTicks(true);
- daySlider.setMajorTickSpacing(100);
- panel.add(daySlider);
- daySlider.addChangeListener(new ChangeListener() {
- public void stateChanged(ChangeEvent e) {
- model.setDay(daySlider.getValue());
- }
- });
- frame.add(panel);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frame.pack();
- frame.setVisible(true);
- }
- public void update(Observable o, Object arg) {
- repaint();
- }
- /**
- * @param value The incoming value to be converted
- * @param low1 Lower bound of the value's current range
- * @param high1 Upper bound of the value's current range
- * @param low2 Lower bound of the value's target range
- * @param high2 Upper bound of the value's target range
- */
- public static final double map(double value, double low1, double high1, double low2, double high2) {
- double diff = value - low1;
- double proportion = diff / (high1 - low1);
- return lerp(low2, high2, proportion);
- }
- // Linearly interpolate between two values
- public static final double lerp(double value1, double value2, double amt) {
- return ((value2 - value1) * amt) + value1;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement