diff --git a/core/src/com/mygdx/game/Game.java b/core/src/com/mygdx/game/Game.java index 2176d64..12b4936 100644 --- a/core/src/com/mygdx/game/Game.java +++ b/core/src/com/mygdx/game/Game.java @@ -22,7 +22,6 @@ public class Game extends ApplicationAdapter { @Override public void create() { game = this; - world = new World(2500, 2500); shaper = new ShapeRenderer(); shaper.setAutoShapeType(true); font = new BitmapFont(); @@ -32,6 +31,10 @@ public class Game extends ApplicationAdapter { worldThread.start(); } + public Game() { + world = new World(2500, 2500); + } + @Override public void render() { // Controls @@ -76,7 +79,7 @@ public class Game extends ApplicationAdapter { try { e.render(shaper); } catch (ArrayIndexOutOfBoundsException ex) { - // No idea why it happens, but it's rendering so meh + // No idea why it happens, but it's rendering so meh //Log.log(Log.ERROR, ex+""); } } diff --git a/core/src/com/mygdx/game/Log.java b/core/src/com/mygdx/game/Log.java index cc74048..c3222b1 100644 --- a/core/src/com/mygdx/game/Log.java +++ b/core/src/com/mygdx/game/Log.java @@ -5,6 +5,8 @@ */ package com.mygdx.game; +import java.util.ArrayList; + /** * * @author fazo @@ -14,12 +16,18 @@ public class Log { public static final int ERROR = 0; public static final int INFO = 1; public static final int DEBUG = 2; + private static ArrayList logListeners; private static int logLevel = 1; public static void log(int level, String msg) { if (level <= logLevel) { - System.out.println(msg); + if (logListeners == null) { + logListeners = new ArrayList(); + } + for (LogListener l : logListeners) { + l.onLog(level, msg); + } } } @@ -31,4 +39,15 @@ public class Log { Log.logLevel = logLevel; } + public interface LogListener { + public abstract void onLog(int level, String msg); + } + + public static void addListener(LogListener l) { + if (logListeners == null) { + logListeners = new ArrayList(); + } + logListeners.add(l); + } + } diff --git a/core/src/logic/World.java b/core/src/logic/World.java index cc6021c..c759179 100644 --- a/core/src/logic/World.java +++ b/core/src/logic/World.java @@ -21,13 +21,14 @@ public class World implements Runnable { private final int width, height, nPlants, creatPerGen; private int generation = 1; - private float fpsLimit = 60; - public ArrayList elements; - public ArrayList toAdd; - public ArrayList creatures; - public ArrayList graveyard; - public ArrayList plants; - public ArrayList deadPlants; + private int fpsLimit = 60, fps = 0; + private final ArrayList elements; + private final ArrayList toAdd; + private final ArrayList creatures; + private final ArrayList graveyard; + private final ArrayList plants; + private final ArrayList deadPlants; + private final ArrayList fpsListeners; public World(int width, int height) { this.width = width; @@ -40,20 +41,31 @@ public class World implements Runnable { plants = new ArrayList(); deadPlants = new ArrayList(); graveyard = new ArrayList(); + fpsListeners = new ArrayList(); newGen(true); } @Override public void run() { - Date d; + Date d, timekeeper = new Date(); long time; - float target; + int target, frames = 0; for (;;) { if (!Game.get().isPaused()) { d = new Date(); update(); + frames++; + Date now = new Date(); + if (now.getTime() - timekeeper.getTime() > 1000) { + fps = frames; + frames = 0; + for (FpsListener f : fpsListeners) { + f.fpsChanged(fps); + } + timekeeper = new Date(); + } if (fpsLimit > 0) { - time = new Date().getTime() - d.getTime(); + time = now.getTime() - d.getTime(); target = 1000 / fpsLimit; if (time < target) { try { @@ -195,6 +207,11 @@ public class World implements Runnable { } } + public interface FpsListener { + + public abstract void fpsChanged(int newValue); + } + private void spawnVegetable() { spawn(false, null); } @@ -215,6 +232,14 @@ public class World implements Runnable { return height; } + public int getGeneration() { + return generation; + } + + public void addFpsListener(FpsListener f) { + fpsListeners.add(f); + } + public void add(Element e) { toAdd.add(e); } @@ -243,8 +268,12 @@ public class World implements Runnable { return fpsLimit; } - public void setFpsLimit(float fpsLimit) { + public void setFpsLimit(int fpsLimit) { this.fpsLimit = fpsLimit; } + public float getFps() { + return fps; + } + } diff --git a/desktop/src/com/mygdx/game/desktop/DesktopLauncher.java b/desktop/src/com/mygdx/game/desktop/DesktopLauncher.java index 039df98..2cbe1eb 100644 --- a/desktop/src/com/mygdx/game/desktop/DesktopLauncher.java +++ b/desktop/src/com/mygdx/game/desktop/DesktopLauncher.java @@ -1,17 +1,62 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ package com.mygdx.game.desktop; -import com.badlogic.gdx.backends.lwjgl.LwjglApplication; -import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; -import com.mygdx.game.Game; +import gui.GUI; +import javax.swing.UIManager; +/** + * + * @author fazo + */ public class DesktopLauncher { - public static void main(String[] arg) { - LwjglApplicationConfiguration.disableAudio = true; - LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); - config.height = 600; - config.width = 800; - config.resizable = false; - new LwjglApplication(new Game(), config); + /** + * @param args the command line arguments + */ + public static void main(String args[]) { + /* Set the Nimbus look and feel */ + // + /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. + * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html + */ + try { + for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { + if ("Nimbus".equals(info.getName())) { + javax.swing.UIManager.setLookAndFeel(info.getClassName()); + break; + } + } + } catch (ClassNotFoundException ex) { + java.util.logging.Logger.getLogger(GUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); + } catch (InstantiationException ex) { + java.util.logging.Logger.getLogger(GUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); + } catch (IllegalAccessException ex) { + java.util.logging.Logger.getLogger(GUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); + } catch (javax.swing.UnsupportedLookAndFeelException ex) { + java.util.logging.Logger.getLogger(GUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); + } + // +/* + Setting the native OS look and feel. This way the program uses the OS's + window toolkit instead of the Java one to render the application, if it + is possible. + */ + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception ex) { + System.out.println("Unable to load native look and feel"); + } + + /* Create and display the form */ + java.awt.EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + new GUI().setVisible(true); + } + }); } } diff --git a/desktop/src/gui/GUI.form b/desktop/src/gui/GUI.form new file mode 100644 index 0000000..c634f00 --- /dev/null +++ b/desktop/src/gui/GUI.form @@ -0,0 +1,182 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/desktop/src/gui/GUI.java b/desktop/src/gui/GUI.java new file mode 100644 index 0000000..145bb98 --- /dev/null +++ b/desktop/src/gui/GUI.java @@ -0,0 +1,206 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package gui; + +import com.badlogic.gdx.backends.lwjgl.LwjglApplication; +import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; +import com.mygdx.game.Game; +import com.mygdx.game.Log; +import com.mygdx.game.Log.LogListener; +import logic.World; + +/** + * + * @author fazo + */ +public class GUI extends javax.swing.JFrame implements LogListener,World.FpsListener { + + private Game game; + private LwjglApplication app; + + /** + * Creates new form GUI + */ + public GUI() { + initComponents(); + setLocationRelativeTo(null); // Center the window + Log.addListener(this); + logTextArea.setText("Started GUI.\n"); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + container = new javax.swing.JPanel(); + tabs = new javax.swing.JTabbedPane(); + logPane = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + logTextArea = new javax.swing.JTextArea(); + jLabel1 = new javax.swing.JLabel(); + logLevelBox = new javax.swing.JComboBox(); + status = new javax.swing.JLabel(); + menuBar = new javax.swing.JMenuBar(); + jMenu1 = new javax.swing.JMenu(); + startButton = new javax.swing.JMenuItem(); + exitButton = new javax.swing.JMenuItem(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + setTitle("AIrium"); + + logTextArea.setEditable(false); + logTextArea.setColumns(20); + logTextArea.setLineWrap(true); + logTextArea.setRows(5); + logTextArea.setText("Started GUI."); + logTextArea.setWrapStyleWord(true); + jScrollPane1.setViewportView(logTextArea); + + jLabel1.setText("Log Level"); + + logLevelBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Errors Only", "Default", "Debug Mode" })); + logLevelBox.setSelectedIndex(1); + logLevelBox.setToolTipText(""); + logLevelBox.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + logLevelBoxItemStateChanged(evt); + } + }); + + javax.swing.GroupLayout logPaneLayout = new javax.swing.GroupLayout(logPane); + logPane.setLayout(logPaneLayout); + logPaneLayout.setHorizontalGroup( + logPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(logPaneLayout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(logLevelBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 404, Short.MAX_VALUE) + ); + logPaneLayout.setVerticalGroup( + logPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(logPaneLayout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 235, Short.MAX_VALUE) + .addGap(10, 10, 10) + .addGroup(logPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(logLevelBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + tabs.addTab("Log", logPane); + + status.setText("Simulation stopped"); + + javax.swing.GroupLayout containerLayout = new javax.swing.GroupLayout(container); + container.setLayout(containerLayout); + containerLayout.setHorizontalGroup( + containerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(tabs) + .addGroup(containerLayout.createSequentialGroup() + .addComponent(status) + .addGap(0, 0, Short.MAX_VALUE)) + ); + containerLayout.setVerticalGroup( + containerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(containerLayout.createSequentialGroup() + .addComponent(tabs) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(status)) + ); + + jMenu1.setText("File"); + + startButton.setText("Start"); + startButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + startButtonActionPerformed(evt); + } + }); + jMenu1.add(startButton); + + exitButton.setText("Exit"); + exitButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + exitButtonActionPerformed(evt); + } + }); + jMenu1.add(exitButton); + + menuBar.add(jMenu1); + + setJMenuBar(menuBar); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(container, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(container, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + + pack(); + }// //GEN-END:initComponents + + private void exitButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitButtonActionPerformed + System.exit(0); + }//GEN-LAST:event_exitButtonActionPerformed + + private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startButtonActionPerformed + if (game != null) { + return; + } + LwjglApplicationConfiguration.disableAudio = true; + LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); + config.height = 600; + config.width = 800; + config.resizable = false; + app = new LwjglApplication(game = new Game(), config); + game.getWorld().addFpsListener(this); + }//GEN-LAST:event_startButtonActionPerformed + @Override + public void onLog(int level, String msg) { + logTextArea.append(msg + "\n"); + setScrollBarToTheBottom(); + } + + public void setScrollBarToTheBottom() { + jScrollPane1.getVerticalScrollBar().setValue(jScrollPane1.getVerticalScrollBar().getMaximum()); + } + + private void logLevelBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_logLevelBoxItemStateChanged + Log.setLogLevel(logLevelBox.getSelectedIndex()); + }//GEN-LAST:event_logLevelBoxItemStateChanged + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel container; + private javax.swing.JMenuItem exitButton; + private javax.swing.JLabel jLabel1; + private javax.swing.JMenu jMenu1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JComboBox logLevelBox; + private javax.swing.JPanel logPane; + private javax.swing.JTextArea logTextArea; + private javax.swing.JMenuBar menuBar; + private javax.swing.JMenuItem startButton; + private javax.swing.JLabel status; + private javax.swing.JTabbedPane tabs; + // End of variables declaration//GEN-END:variables + + @Override + public void fpsChanged(int fps) { + status.setText("Generation: "+game.getWorld().getGeneration()+" FPS: "+fps); + } +}