Advertisement
OrangoMango

SolarSystem.java

Dec 16th, 2023 (edited)
803
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.66 KB | Source Code | 0 0
  1. import javafx.application.Application;
  2. import javafx.scene.Scene;
  3. import javafx.stage.Stage;
  4. import javafx.scene.layout.StackPane;
  5. import javafx.scene.canvas.*;
  6. import javafx.scene.paint.Color;
  7. import javafx.animation.*;
  8. import javafx.util.Duration;
  9. import javafx.geometry.Point2D;
  10. import javafx.scene.input.KeyCode;
  11.  
  12. import java.util.*;
  13.  
  14. public class SolarSystem extends Application{
  15.     private static final int WIDTH = 1000;
  16.     private static final int HEIGHT = 800;
  17.     private static final double SCALE = 200 / 1.50e11;
  18.     private static final double TIMESTEP = 3600*24; // 1 Day
  19.     private static final double G = 6.6743e-11;
  20.  
  21.     private static class Planet{
  22.         private double x, y;
  23.         private double xVelocity, yVelocity;
  24.         private double mass, radius;
  25.         private Color color;
  26.         private List<Point2D> orbit = new ArrayList<>();
  27.         private boolean signChanged = false, renderOrbit = true;
  28.  
  29.         public Planet(Color color, double radius, double mass, double x, double y, double xVelocity, double yVelocity){
  30.             this.color = color;
  31.             this.radius = radius;
  32.             this.mass = mass;
  33.             this.x = x;
  34.             this.y = y;
  35.             this.xVelocity = xVelocity;
  36.             this.yVelocity = yVelocity;
  37.         }
  38.  
  39.         private Point2D getAttractionForce(Planet planet){
  40.             double distanceX = planet.x-this.x;
  41.             double distanceY = planet.y-this.y;
  42.             double distance = Math.sqrt(Math.pow(distanceX, 2)+Math.pow(distanceY, 2));
  43.  
  44.             double force = SolarSystem.G*this.mass*planet.mass/Math.pow(distance, 2);
  45.             double angle = Math.atan2(distanceY, distanceX);
  46.             double forceX = force * Math.cos(angle);
  47.             double forceY = force * Math.sin(angle);
  48.  
  49.             /*
  50.             Distance moon-sun: 1.504E11
  51.             Sun force for moon: 4.313523549126089E20
  52.             Distance moon-earth: 4.0E8
  53.             Earth force for moon: 1.831019119125E20
  54.             */
  55.  
  56.             /*if (this == MOON && planet == SUN){
  57.                 System.out.println("Distance moon-sun: "+distance);
  58.                 System.out.println("Sun force for moon: "+force);
  59.             } else if (this == MOON && planet == EARTH){
  60.                 System.out.println("Distance moon-earth: "+distance);
  61.                 System.out.println("Earth force for moon: "+force);
  62.             }*/
  63.  
  64.             return new Point2D(forceX, forceY);
  65.         }
  66.  
  67.         public void updatePosition(List<Planet> planets){
  68.             double totalForceX = 0;
  69.             double totalForceY = 0;
  70.  
  71.             for (Planet planet : planets){
  72.                 if (planet == this) continue;
  73.                 Point2D force = getAttractionForce(planet);
  74.                 totalForceX += force.getX();
  75.                 totalForceY += force.getY();
  76.             }
  77.  
  78.             double temp = this.xVelocity;
  79.             this.xVelocity += totalForceX/this.mass*TIMESTEP;
  80.             this.yVelocity += totalForceY/this.mass*TIMESTEP;
  81.  
  82.             if (temp*this.xVelocity < 0){ // The sign changed
  83.                 this.signChanged = !this.signChanged;
  84.                 if (!this.signChanged){
  85.                     this.renderOrbit = false;
  86.                 }
  87.             }
  88.  
  89.             this.x += this.xVelocity*TIMESTEP;
  90.             this.y += this.yVelocity*TIMESTEP;
  91.         }
  92.  
  93.         public void render(GraphicsContext gc){
  94.             final double x = this.x*SolarSystem.SCALE+WIDTH/2;
  95.             final double y = this.y*SolarSystem.SCALE+HEIGHT/2;
  96.  
  97.             if (this.renderOrbit){
  98.                 this.orbit.add(new Point2D(x, y));
  99.             }
  100.  
  101.             gc.setFill(this.color);
  102.             final double radius = this.radius; // TODO
  103.             gc.fillOval(x-radius, y-radius, radius*2, radius*2);
  104.         }
  105.  
  106.         public void renderOrbit(GraphicsContext gc){
  107.             gc.setStroke(Color.WHITE);
  108.             gc.setLineWidth(2);
  109.             for (int i = 0; i < this.orbit.size()-1; i++){
  110.                 gc.strokeLine(this.orbit.get(i).getX(), this.orbit.get(i).getY(), this.orbit.get(i+1).getX(), this.orbit.get(i+1).getY());
  111.             }
  112.         }
  113.     }
  114.  
  115.     private List<Planet> planets = new ArrayList<>();
  116.     private Map<KeyCode, Boolean> keys = new HashMap<>();
  117.     private static int WATCHING_PLANET = 0;
  118.  
  119.     private static Planet MOON, EARTH, SUN;
  120.  
  121.     @Override
  122.     public void start(Stage stage){
  123.         Canvas canvas = new Canvas(WIDTH, HEIGHT);
  124.         GraphicsContext gc = canvas.getGraphicsContext2D();
  125.         StackPane pane = new StackPane(canvas);
  126.  
  127.         canvas.setFocusTraversable(true);
  128.         canvas.setOnKeyPressed(e -> this.keys.put(e.getCode(), true));
  129.         canvas.setOnKeyReleased(e -> this.keys.put(e.getCode(), false));
  130.  
  131.         reset();
  132.  
  133.         Timeline loop = new Timeline(new KeyFrame(Duration.millis(1000.0/40), e -> {
  134.             for (Planet planet : planets){
  135.                 planet.updatePosition(planets);
  136.             }
  137.             update(gc);
  138.         }));
  139.         loop.setCycleCount(Animation.INDEFINITE);
  140.         loop.play();
  141.  
  142.         Scene scene = new Scene(pane, WIDTH, HEIGHT);
  143.         stage.setScene(scene);
  144.  
  145.         stage.setTitle("Solar system");
  146.         stage.setResizable(false);
  147.         stage.show();
  148.     }
  149.  
  150.     private void reset(){
  151.         planets.clear();
  152.         Planet sun = new Planet(Color.YELLOW, 16, 1.989e30, 0, 0, 0, 0);
  153.         Planet earth = new Planet(Color.CYAN, 8, 5.972e24, -1.50e11, 0, 0, 2.97e4);
  154.         Planet moon = new Planet(Color.GRAY, 4, 7.35e22, -(1.50e11+4e8), 0, 0, 1022);
  155.         Planet mercury = new Planet(Color.ORANGE, 6, 3.30e23, -6.982e10, 0, 0, 4.736e4);
  156.         Planet mars = new Planet(Color.RED, 5, 6.41e23, -2.49e11, 0, 0, 2.407e4);
  157.         Planet venus = new Planet(Color.LIME, 4, 4.86e24, -1.08e11, 0, 0, 3.502e4);
  158.         planets.add(sun);
  159.         planets.add(earth);
  160.         planets.add(moon);
  161.         //planets.add(mercury);
  162.         //planets.add(mars);
  163.         //planets.add(venus);
  164.  
  165.         MOON = moon;
  166.         EARTH = earth;
  167.         SUN = sun;
  168.     }
  169.  
  170.     private void update(GraphicsContext gc){
  171.         gc.clearRect(0, 0, WIDTH, HEIGHT);
  172.         gc.setFill(Color.BLACK);
  173.         gc.fillRect(0, 0, WIDTH, HEIGHT);
  174.  
  175.         if (this.keys.getOrDefault(KeyCode.ESCAPE, false)){
  176.             System.exit(0);
  177.         } else if (this.keys.getOrDefault(KeyCode.R, false)){
  178.             reset();
  179.             this.keys.put(KeyCode.R, false);
  180.         }
  181.  
  182.         // DEBUG
  183.         if (this.keys.getOrDefault(KeyCode.DIGIT0, false)){
  184.             WATCHING_PLANET = 0;
  185.             this.keys.put(KeyCode.DIGIT0, false);
  186.         } else if (this.keys.getOrDefault(KeyCode.DIGIT1, false)){
  187.             WATCHING_PLANET = 1;
  188.             this.keys.put(KeyCode.DIGIT1, false);
  189.         } else if (this.keys.getOrDefault(KeyCode.DIGIT2, false)){
  190.             WATCHING_PLANET = 2;
  191.             this.keys.put(KeyCode.DIGIT2, false);
  192.         } else if (this.keys.getOrDefault(KeyCode.DIGIT3, false)){
  193.             WATCHING_PLANET = 3;
  194.             this.keys.put(KeyCode.DIGIT3, false);
  195.         } else if (this.keys.getOrDefault(KeyCode.DIGIT4, false)){
  196.             WATCHING_PLANET = 4;
  197.             this.keys.put(KeyCode.DIGIT4, false);
  198.         } else if (this.keys.getOrDefault(KeyCode.DIGIT5, false)){
  199.             WATCHING_PLANET = 5;
  200.             this.keys.put(KeyCode.DIGIT5, false);
  201.         }
  202.  
  203.         for (Planet planet : planets){
  204.             planet.renderOrbit(gc);
  205.             planet.render(gc);
  206.         }
  207.  
  208.         gc.setFill(Color.WHITE);
  209.         gc.fillText(String.format("x: %.3f y: %.3f\nxVel: %.3f\nyVel: %.3f\nTarget: %d", planets.get(WATCHING_PLANET).x, planets.get(WATCHING_PLANET).y, planets.get(WATCHING_PLANET).xVelocity, planets.get(WATCHING_PLANET).yVelocity, WATCHING_PLANET), 50, 50);
  210.     }
  211.  
  212.     public static void main(String[] args){
  213.         launch(args);
  214.     }
  215. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement