package com.callumcarmicheal.solar; import java.awt.Font; import java.io.InputStream; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import javax.swing.JOptionPane; import org.lwjgl.LWJGLException; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMode; import org.lwjgl.opengl.GL11; import org.lwjgl.util.glu.GLU; import org.newdawn.slick.Color; import org.newdawn.slick.TrueTypeFont; import org.newdawn.slick.util.ResourceLoader; import com.callumcarmicheal.OpenGL.GLUT; import com.callumcarmicheal.OpenGL.Util; import com.callumcarmicheal.maths.Vector4f; import com.callumcarmicheal.solar.render.Camera; import com.callumcarmicheal.solar.simulation.*; /* * @name Solar System (REWRITE) * @author Callum Carmicheal * @date 24/08/2015 * @description A Solar System Simulation */ public class Main { // Program -> Variables public static Main instance; // Simulation -> Variables SimOptions simulationHandler; // Rendering -> Variables boolean grabMouse = false, disposing = false, fontLoaded = false, isPaused = false, isVisible = false, updateQuery = false, updateQueryRecieved = false, updateFinished = false; HashMap Stars = new HashMap(), Planets = new HashMap(), Satellites = new HashMap(); TrueTypeFont renderFont; Camera renderCamera; float FOV = 60.0f, zNear = 0.001f, zFar = 1000.001f; // LISTENERS --> void keyboardListener() { // Check if our keyboard listener is created and then execute commands // from it if (Keyboard.isCreated()) { // Hold Keys renderCamera.keyboardUpdate(false, false); // Fetch all pressed keys (Press once) while (Keyboard.next()) { // Check if key is pressed if (Keyboard.getEventKeyState()) { /* KEY PRESSED */ { if (Keyboard.getEventKey() == Keyboard.KEY_F1) JOptionPane.showMessageDialog( null, (Object) "Press 0 to Add a Star \n" + "Press 1 to Add a Planet \n" + "Press 2 to Add a Satellite \n", "Help", JOptionPane.PLAIN_MESSAGE); if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) disposing = true; if (Keyboard.getEventKey() == Keyboard.KEY_PAUSE) isPaused = !isPaused; if (Keyboard.getEventKey() == Keyboard.KEY_0) addStar(); if (Keyboard.getEventKey() == Keyboard.KEY_1) addPlanetOrSatellite(true); if (Keyboard.getEventKey() == Keyboard.KEY_2) addPlanetOrSatellite(false); } renderCamera.keyboardUpdate(true, true); } else { /* KEY RELEASED */ renderCamera.keyboardUpdate(true, false); } } } else /* Try to create keyboard listener */{ try { Keyboard.create(); } catch (LWJGLException e) { System.err.println("Failed to create LWJGL Keyboard Listener"); e.printStackTrace(); } } } void mouseListener() { // Check if our mouse listener is created and then execute commands from // it if (Mouse.isCreated()) { // Set Grabbed state //Mouse.setGrabbed(this.grabMouse); //if (grabMouse) { } } else /* Try to create mouse listener */{ try { Mouse.create(); } catch (LWJGLException e) { System.err.println("Failed to create LWJGL Mouse Listener"); e.printStackTrace(); } } } // LISTENERS <-- // SIMULATION --> void updateSimulationData() { if(!isVisible || isPaused) return; } void addStar() { String starName = JOptionPane.showInputDialog(null, "Enter star's name. *Optional", "Add star to galaxy", JOptionPane.QUESTION_MESSAGE); float starX = Float.parseFloat(JOptionPane.showInputDialog(null, "Enter X", "Add star to galaxy", JOptionPane.QUESTION_MESSAGE)); float starY = Float.parseFloat(JOptionPane.showInputDialog(null, "Enter Y", "Add star to galaxy", JOptionPane.QUESTION_MESSAGE)); float starZ = Float.parseFloat(JOptionPane.showInputDialog(null, "Enter Z", "Add star to galaxy", JOptionPane.QUESTION_MESSAGE)); SimObject starObj; if (starName != null) starObj = new SimObject(starName, starX, starX, starZ, true); else starObj = new SimObject("", starX, starX, starZ, true); protectHashMap(Stars, starObj.UID, starObj); JOptionPane.showMessageDialog(null, (Object)"Created Star With Params (N:" + starName + "|X:" + starX + "|Y:" + starY + "|Z:" + starZ + "|true)"); } void addPlanetOrSatellite(boolean isPlanet) { String starName = JOptionPane.showInputDialog(null, "Enter object's Name. *Optional", "Add object to star", JOptionPane.QUESTION_MESSAGE); int starIndex = Integer.parseInt(JOptionPane.showInputDialog(null, "Enter StarINDEX (TODO: Do something in here ....)", "Add object to star", JOptionPane.QUESTION_MESSAGE)); boolean validRadius = false; while (validRadius == false) { float starX = Float.parseFloat(JOptionPane.showInputDialog(null, "Enter X (Relitive to Home Star)", "Add object to star", JOptionPane.QUESTION_MESSAGE)); float starY = Float.parseFloat(JOptionPane.showInputDialog(null, "Enter Y (Relitive to Home Star)", "Add object to star", JOptionPane.QUESTION_MESSAGE)); float starZ = Float.parseFloat(JOptionPane.showInputDialog(null, "Enter Z (Relitive to Home Star)", "Add object to star", JOptionPane.QUESTION_MESSAGE)); if(starName != null) { String velocityRAW = "0"; int velocity = 0; while(velocity == 0) { try { velocityRAW = JOptionPane.showInputDialog(null, "Select velocity (1-500)", "Adding object to Star", JOptionPane.QUESTION_MESSAGE); velocity = Integer.parseInt(velocityRAW); if( velocity < 1 || velocity > (isPlanet?500:100)) { JOptionPane.showMessageDialog(null, "Invalid velocity(" + velocity + ") | please select a velocity (1-500)", "Adding object to Star", JOptionPane.ERROR_MESSAGE); velocity = 0; } } catch(Exception ex) { JOptionPane.showMessageDialog(null, "There was a error parsing the value given. (" + velocityRAW + ")", "Error, please try again", JOptionPane.ERROR_MESSAGE); } } SimObject spaceyRockThingyHomeSTAR = (SimObject) Stars.values().toArray()[0]; SimObject spaceyRockThingy = new SimObject( starName, starX - spaceyRockThingyHomeSTAR.Location.x, starY - spaceyRockThingyHomeSTAR.Location.y, starZ - spaceyRockThingyHomeSTAR.Location.y, false); spaceyRockThingy.orbitBase = connectTo(spaceyRockThingyHomeSTAR, isPlanet); spaceyRockThingy.radius = (float) Math.sqrt( Math.abs(spaceyRockThingy.orbitBase.Location.x - spaceyRockThingy.Location.x) * Math.abs(spaceyRockThingy.orbitBase.Location.x - spaceyRockThingy.Location.x) + Math.abs(spaceyRockThingy.orbitBase.Location.y - spaceyRockThingy.Location.y) * Math.abs(spaceyRockThingy.orbitBase.Location.y - spaceyRockThingy.Location.y) ); if(spaceyRockThingy.radius < 5) { JOptionPane.showMessageDialog(null, "", "Adding object to Star", JOptionPane.ERROR_MESSAGE); } else { validRadius = true; spaceyRockThingy.degree = (float) Math.toDegrees( Math.asin( Math.abs( (spaceyRockThingy.Location.y - spaceyRockThingy.orbitBase.Location.y) / spaceyRockThingy.radius ) ) ); if(spaceyRockThingy.Location.x < spaceyRockThingy.orbitBase.Location.x) { if(spaceyRockThingy.Location.y < spaceyRockThingy.orbitBase.Location.y) { spaceyRockThingy.degree -= 180; } else { spaceyRockThingy.degree = 180 - spaceyRockThingy.degree; } } else { if(spaceyRockThingy.Location.y < spaceyRockThingy.orbitBase.Location.y) { spaceyRockThingy.degree *= -1; // Flip the degree. } } spaceyRockThingy.velocity = velocity/spaceyRockThingy.radius; System.out.println("Added new object to star + (" + spaceyRockThingy.UID + "|" + spaceyRockThingy.Name + ")"); if(isPlanet) { protectHashMap(Planets, spaceyRockThingy.UID, spaceyRockThingy); } else { protectHashMap(Satellites, spaceyRockThingy.UID, spaceyRockThingy); } } } } } // SIMULATION <-- // HASHMAP --> void protectHashMap(HashMap mapList, Object key, Object whatToPlace) { //updateQuery = true; //while(!updateQueryRecieved) {} //updateQueryRecieved = true; mapList.put(key, whatToPlace); //updateFinished = true; } void protectHashMap() { //if(updateQuery) { // updateQuery = false; // updateQueryRecieved = true; // while(!updateFinished) {} // updateFinished = false; //} } public SimObject connectTo(SimObject base, boolean isPlanet) { Iterator i; SimObject master = null; HashMap masterSet; if(isPlanet) { masterSet = Stars; } else { masterSet = Planets; } double Distance = 10000; i = masterSet.keySet().iterator(); Object key; while (i.hasNext()) { key = i.next(); SimObject obj = (SimObject) masterSet.get(key); double dTemp = Math.sqrt(Math.abs(obj.Location.x - base.Location.x)) * Math.abs( obj.Location.x - base.Location.x ) + Math.abs( obj.Location.y - base.Location.y ) * Math.abs( obj.Location.y - base.Location.y ); if(dTemp > Distance) { master = (SimObject)masterSet.get(key); Distance = Math.sqrt( Math.abs(master.Location.x - base.Location.x) * Math.abs(master.Location.x - base.Location.x) + Math.abs(master.Location.y - base.Location.y) * Math.abs(master.Location.y - base.Location.y) ); } } return master; } // HASHMAP <-- // RENDER --> void Render() { protectHashMap(); if(!isVisible) return; // Clear the rendering output/buffer GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); GL11.glMatrixMode(GL11.GL_MODELVIEW); Util.fixCamera(); GL11.glScaled(1, 1, 1); GL11.glPushMatrix(); { renderCamera.useCamera(); } GL11.glPopMatrix(); // Clear the current matrix (Model View) GL11.glLoadIdentity(); /* Render Our Planets/System */ { Iterator ite; ite = Stars.values().iterator(); while(ite.hasNext()) { try { SimObject theStar = (SimObject) ite.next(); theStar.onRender(simulationHandler, renderFont); } catch (Exception ex) {}; } ite = Planets.values().iterator(); while(ite.hasNext()) { try { SimObject spaceyRockThing = (SimObject)ite.next(); if(!isPaused) spaceyRockThing.onUpdate(simulationHandler); spaceyRockThing.onRender(simulationHandler, renderFont); } catch(Exception ex) { } } ite = Satellites.values().iterator(); while(ite.hasNext()) { try { SimObject spaceyInterwebConnectorThingy = (SimObject)ite.next(); if(!isPaused) spaceyInterwebConnectorThingy.onUpdate(simulationHandler); spaceyInterwebConnectorThingy.onRender(simulationHandler, renderFont); } catch(Exception ex) { } } } // Render GUI (Text Overlay) if (fontLoaded) { GL11.glPushMatrix(); { GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glPushMatrix(); { GL11.glLoadIdentity(); GL11.glOrtho(0, Display.getWidth(), Display.getHeight(), 0, 1, -1); GL11.glMatrixMode(GL11.GL_MODELVIEW); GL11.glDisable(GL11.GL_CULL_FACE); GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT); GL11.glLoadIdentity(); int diff = 15; renderFont.drawString(10, diff * 0, "Authors: CallumC, Bastien Fremondiere", Color.red); renderFont.drawString(10, diff * 1, "Version: Who knows, last i remember it was 0.<SOMETHING>", Color.yellow); renderFont.drawString(10, diff * 2, "LOC : " + renderCamera.getLocation().toString(), Color.green); renderFont.drawString(10, diff * 3, "ROT : " + renderCamera.getRotation().toString(), Color.green); renderFont.drawString(10, diff * 4, "TIME : " + simulationHandler.simulationTime, Color.cyan); GL11.glEnable(GL11.GL_DEPTH_TEST); GL11.glEnable(GL11.GL_CULL_FACE); GL11.glMatrixMode(GL11.GL_PROJECTION); } GL11.glPopMatrix(); GL11.glMatrixMode(GL11.GL_MODELVIEW); GL11.glDisable(GL11.GL_BLEND); } GL11.glPopMatrix(); GL11.glTranslatef(0, 0, -20); } GL11.glFlush(); } void onWindowResize(boolean createCam) { int w = Display.getWidth(); int h = Display.getHeight(); float aspectRatio; h = (h == 0) ? 1 : h; w = (w == 0) ? 1 : w; aspectRatio = (float) w / (float) h; if (createCam) renderCamera = new Camera(new Vector4f(FOV, aspectRatio, zNear, zFar)); else { if (renderCamera.ISREADY) renderCamera.setRenderSettings(FOV, aspectRatio, zNear, zFar); } } // RENDER <-- public void Init() { boolean displayShown = false; try { Display.setDisplayMode(new DisplayMode(1024, 800)); Display.setResizable(true); Display.create(); Keyboard.create(); // Create keyboard listener Mouse.create(); displayShown = true; if (displayShown) { Display.setTitle("LOADING RESOURCES (Loading Font [res/fonts/constan.ttf])"); // Load font from a .TTF file try { InputStream inputStream = ResourceLoader .getResourceAsStream("res/fonts/constan.ttf"); Font awtFont2 = Font.createFont(Font.TRUETYPE_FONT, inputStream); awtFont2 = awtFont2.deriveFont(15f); // set font size renderFont = new TrueTypeFont(awtFont2, true); // Anti-A fontLoaded = true; } catch (Exception e) { e.printStackTrace(); } Display.setTitle("LOADING RESOURCES ()"); { Display.setTitle("LOADING RESOURCES (Loading Sim-Data)"); simulationHandler = new SimOptions(); } Display.setTitle("DONE LOADING RESOURCES"); } } catch (LWJGLException e) { e.printStackTrace(); } if (displayShown) { /* Initialise OpenGL */ onWindowResize(true); Display.setTitle("Solar System Simulation"); // Start Game loop while (!disposing) { if (!disposing) disposing = Display.isCloseRequested(); // Disposing has been checked, if not lets Render and Start Simulations if (!disposing) { // Do calculations if (Display.wasResized()) onWindowResize(false); // Take the Input mouseListener(); keyboardListener(); // Update our SimData updateSimulationData(); // Render Render(); // Check if close was requested and Update Display isVisible = Display.isVisible(); Display.update(); } } } else { System.out.println("Failed to init the display output"); System.err.println("Please try again later"); System.exit(0); } // End the display instance Display.destroy(); } public Main() { this.instance = this; Init(); } }