" */
+
+ /* Under normal circumstances, this method also requires that you add an exception -- the
+ * exception that caused a need to call "FastJEngine#error".
+ * For the sake of demonstration, we will create an exception ourselves. */
+ IllegalStateException exampleException = new IllegalStateException("This is an example exception.");
+ FastJEngine.error("Oh dear, looks like something went wrong. This is an error message.", exampleException);
+ }
+}
diff --git a/src/example/java/tech/fastj/example/model2d/Main.java b/src/example/java/tech/fastj/example/model2d/Main.java
new file mode 100644
index 00000000..87964d70
--- /dev/null
+++ b/src/example/java/tech/fastj/example/model2d/Main.java
@@ -0,0 +1,53 @@
+package tech.fastj.example.model2d;
+
+import tech.fastj.engine.FastJEngine;
+import tech.fastj.math.Pointf;
+import tech.fastj.graphics.Display;
+import tech.fastj.graphics.game.Model2D;
+import tech.fastj.graphics.game.Polygon2D;
+import tech.fastj.graphics.util.DrawUtil;
+
+import tech.fastj.systems.control.SimpleManager;
+
+public class Main extends SimpleManager {
+
+ @Override
+ public void init(Display display) {
+ /* Model2D */
+
+ /* WARNING: If you're not familiar with FastJ, you'll need to read through the
+ * "polygon2d" example first.
+ *
+ * In order to create a Model2D, you'll need an array of Polygon2D objects.
+ * A Model2D is essentially a collection of Polygon2D objects, and it treats those objects
+ * as one game object. */
+
+ // We'll create two squares -- just like the ones from the "hellopolygon2d" example.
+ Pointf[] smallSquareMesh1 = DrawUtil.createBox(0f, 0f, 50f);
+ Polygon2D smallSquare1 = new Polygon2D(smallSquareMesh1);
+
+ // To visualize the two squares as different, we'll change the second one up a bit.
+ Pointf[] smallSquareMesh2 = DrawUtil.createBox(50f, 50f, 25f);
+ Polygon2D smallSquare2 = new Polygon2D(smallSquareMesh2);
+
+ // In order to create our Model2D, we need those squares in an array.
+ Polygon2D[] smallSquaresArray = {smallSquare1, smallSquare2};
+
+ // Now, we can create our Model2D object.
+ Model2D smallSquares = new Model2D(smallSquaresArray);
+
+ /* Super simple! Now, this alone does not cause the model to render to the screen. In order
+ * for it to be rendered, you need to add it as a game object to the drawable manager. */
+ drawableManager.addGameObject(smallSquares);
+ }
+
+ @Override
+ public void update(Display display) {
+ // Empty -- this example does not make use of this method.
+ }
+
+ public static void main(String[] args) {
+ FastJEngine.init("Hello, Model2D!", new Main());
+ FastJEngine.run();
+ }
+}
diff --git a/src/example/java/tech/fastj/example/modelreadwrite/Main.java b/src/example/java/tech/fastj/example/modelreadwrite/Main.java
new file mode 100644
index 00000000..09c87f8b
--- /dev/null
+++ b/src/example/java/tech/fastj/example/modelreadwrite/Main.java
@@ -0,0 +1,87 @@
+package tech.fastj.example.modelreadwrite;
+
+import tech.fastj.engine.FastJEngine;
+import tech.fastj.math.Pointf;
+import tech.fastj.graphics.game.Model2D;
+import tech.fastj.graphics.game.Polygon2D;
+import tech.fastj.graphics.util.DrawUtil;
+import tech.fastj.graphics.util.PsdfUtil;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class Main {
+ public static void main(String[] args) {
+ /* Model Reading/Writing */
+
+ /* WARNING: If you're not familiar with FastJ, you'll need to read through the
+ * "model2d" example first.
+ *
+ * Creating models from pure code is convenient, but quite cumbersome to read through. Let's
+ * learn how to read and write them to a file format instead. */
+
+ // We'll start with the model code from the "model2d" example.
+ Pointf[] smallSquareMesh1 = DrawUtil.createBox(0f, 0f, 50f);
+ Polygon2D smallSquare1 = new Polygon2D(smallSquareMesh1);
+
+ Pointf[] smallSquareMesh2 = DrawUtil.createBox(50f, 50f, 25f);
+ Polygon2D smallSquare2 = new Polygon2D(smallSquareMesh2);
+
+ Polygon2D[] smallSquaresArray = {smallSquare1, smallSquare2};
+ Model2D smallSquares = new Model2D(smallSquaresArray);
+
+
+ /* Now that that's out of the way, let's write this Model2D to a file.
+ * DrawUtil contains the function for writing Model2D objects to a file. With this, we'll
+ * write the file, and then print out the contents.
+ *
+ * Model2D objects can be written to the PSDF (Polygon Structural Data Format) format,
+ * which is a format written specifically for use with the FastJ engine.
+ * At a later point in time, the engine will support writing Model2D objects to more
+ * standard formats, but until then we'll be using the PSDF format.
+ */
+
+
+ /* This is the path which we will be writing to. It resolves to
+ * "src/example/resources/modelreadwrite/smallSquares.psdf". */
+ String smallSquaresFilePath = "src/example/resources/modelreadwrite/smallSquares.psdf";
+
+ // And now, we can call the model-writing method.
+ PsdfUtil.writePsdf(smallSquaresFilePath, smallSquares);
+
+
+ /* As a small aside, this gets the file and prints out its contents.
+ * The code is not the primary focus of the example -- this is just to give a visual. */
+ try {
+ String smallSquaresFileContents = Files.readString(Path.of(smallSquaresFilePath));
+ FastJEngine.log("Contents of smallSquares.psdf: \n" + smallSquaresFileContents);
+ } catch (IOException exception) {
+ exception.printStackTrace();
+ }
+
+
+ /* Next up, we'll read the file back.
+ * Since we already have the string denoting the location of the file, we can reuse it. */
+ Polygon2D[] smallSquaresArrayFromFile = PsdfUtil.loadPsdf(smallSquaresFilePath);
+
+ // We can use this to create a new Model2D.
+ Model2D smallSquaresFromFile = new Model2D(smallSquaresArrayFromFile);
+
+ /* Here, we check for equality between the original and the read file.
+ * As expected, the two contain the exact same contents. */
+ FastJEngine.log("smallSquaresfromFile == smallSquares? " + smallSquaresFromFile.equals(smallSquares));
+
+
+ /* Another small aside: this removes the file we created earlier in the program.
+ * This code is not the primary focus of the example -- it's just to clean up the work we did. */
+ try {
+ boolean wasDeleted = Files.deleteIfExists(Path.of(smallSquaresFilePath));
+ if (!wasDeleted) {
+ FastJEngine.warning("The file at \"" + smallSquaresFilePath + "\" was not deleted.");
+ }
+ } catch (IOException exception) {
+ exception.printStackTrace();
+ }
+ }
+}
diff --git a/src/example/java/tech/fastj/example/polygon2d/Main.java b/src/example/java/tech/fastj/example/polygon2d/Main.java
new file mode 100644
index 00000000..49869bcf
--- /dev/null
+++ b/src/example/java/tech/fastj/example/polygon2d/Main.java
@@ -0,0 +1,92 @@
+package tech.fastj.example.polygon2d;
+
+import tech.fastj.engine.FastJEngine;
+import tech.fastj.math.Pointf;
+import tech.fastj.graphics.Display;
+import tech.fastj.graphics.game.Polygon2D;
+import tech.fastj.graphics.util.DrawUtil;
+
+import tech.fastj.systems.control.SimpleManager;
+
+import java.awt.Color;
+
+public class Main extends SimpleManager {
+
+ @Override
+ public void init(Display display) {
+ /* Polygon2D */
+
+ /* In order to create a Polygon2D, you first need to create a mesh.
+ * A mesh is essentially an array of "Pointf"s (vectors) that form a shape when drawn in
+ * order. This mesh is the base upon which the Polygon2D can be constructed, and defines
+ * what sort of shape gets drawn to the screen. */
+
+ // You can create a mesh by hand...
+ Pointf[] smallSquareMeshByHand = {
+ new Pointf(0f, 0f),
+ new Pointf(0f, 50f),
+ new Pointf(50f, 50f),
+ new Pointf(50f, 0f)
+ };
+
+ // ...or by using one of the many "DrawUtil.create" methods.
+ Pointf[] smallSquareMeshFromDrawUtil = DrawUtil.createBox(0f, 0f, 50f);
+
+ /* The two meshes above result in the exact same thing: a square at the point (0, 0) with a
+ * size of 50. */
+
+
+ /* Now, we can create our Polygon2D. We'll use smallSquareMeshByHand for right now, but you
+ * should try switching from it to smallSquareMeshFromDrawUtil to see what happens! */
+ Polygon2D smallSquare = new Polygon2D(smallSquareMeshByHand);
+
+ /* Super simple! Now, this alone does not cause the square to render to the screen. In
+ * order for it to be rendered, you need to add it as a game object to the drawable
+ * manager. */
+ drawableManager.addGameObject(smallSquare);
+
+ /* If you comment out the line above, you'll see that the small square does not get
+ * rendered. */
+
+
+ /* You can set the following properties of a Polygon2D:
+ * - Mesh (Pointf[])
+ * - Paint (solid color, gradient)
+ * - PaintFilled (render the outline or fill)
+ * - Rotation
+ * - Scale
+ * - Translation
+ *
+ * To show this off, we'll create a larger square with the following property values:
+ * - Square mesh at (625, 25) with a size of 47.9
+ * - Blue color
+ * - Outline
+ * - Rotation of 30 degrees
+ * - Scaled to 50% (0.5)
+ * - Translated by (20, 10) */
+ Pointf[] largeSquareMesh = DrawUtil.createBox(625f, 25.5f, 47.9f);
+ Polygon2D largeSquare = new Polygon2D(largeSquareMesh)
+ .setPaint(Color.blue)
+ .setFilled(false);
+
+ /* As you can see from the code above, many of the methods Polygon2D contains allow for
+ * method chaining.
+ * From the code below, you can see that other methods do not. */
+
+ largeSquare.rotate(30f);
+ largeSquare.scale(new Pointf(0.5f, 0.5f));
+ largeSquare.translate(new Pointf(20f, 10f));
+
+ drawableManager.addGameObject(largeSquare);
+ }
+
+ @Override
+ public void update(Display display) {
+ // Empty -- this example does not make use of this method.
+ }
+
+ public static void main(String[] args) {
+ FastJEngine.init("Hello, Polygon2D!", new Main());
+ FastJEngine.run();
+ }
+}
diff --git a/src/example/java/tech/fastj/example/text2d/Main.java b/src/example/java/tech/fastj/example/text2d/Main.java
new file mode 100644
index 00000000..cc4779e4
--- /dev/null
+++ b/src/example/java/tech/fastj/example/text2d/Main.java
@@ -0,0 +1,58 @@
+package tech.fastj.example.text2d;
+
+import tech.fastj.engine.FastJEngine;
+import tech.fastj.math.Pointf;
+import tech.fastj.graphics.Display;
+import tech.fastj.graphics.game.Text2D;
+
+import tech.fastj.systems.control.SimpleManager;
+
+public class Main extends SimpleManager {
+
+ @Override
+ public void init(Display display) {
+ /* Text2D */
+
+ /* In order to create a Text2D, you will need two things:
+ * 1. A message, or some text to display.
+ * 2. A location for the message to be rendered at. */
+
+ // The message is pretty simple -- just a String containing text.
+ String messageString = "Hello, FastJ Text2D!";
+
+ /* The location is fairly simple as well -- just a Pointf containing the x and y location.
+ *
+ * For the sake of clarification, a Pointf is a 2D vector containing x and y variables.
+ * In this case, "messageLocation" represents the point (0, 25) in the 2D coordinate space.
+ *
+ * Note: Text2D render differently from polygons. They are rendered such that the y
+ * location represents the bottom of the text shown.
+ * One good way to account for this is to add the size of the font to the y position. Since
+ * we did not create a custom font for the Text2D, we can use the size of the default font,
+ * "Text2D#DefaultFont#getSize()". */
+ Pointf messageLocation = new Pointf(0f, 0f + Text2D.DefaultFont.getSize());
+
+
+ // Now, we put it all together!
+ Text2D message = new Text2D(messageString, messageLocation);
+
+ /* Super simple! Now, this alone does not cause the text to render to the screen. In order
+ * for it to be rendered, you need to add it as a game object to the drawable manager. */
+ drawableManager.addGameObject(message);
+
+ /* If you comment out the line above, you'll see that the text does not get rendered. */
+
+
+ /* */
+ }
+
+ @Override
+ public void update(Display display) {
+ // Empty -- this example does not make use of this method.
+ }
+
+ public static void main(String[] args) {
+ FastJEngine.init("Hello, Text2D!", new Main());
+ FastJEngine.run();
+ }
+}
diff --git a/src/main/java/tech/fastj/engine/FastJEngine.java b/src/main/java/tech/fastj/engine/FastJEngine.java
index 494c5891..4469d69c 100644
--- a/src/main/java/tech/fastj/engine/FastJEngine.java
+++ b/src/main/java/tech/fastj/engine/FastJEngine.java
@@ -350,7 +350,7 @@ public static void closeGame() {
* as possible, without waiting for the next game update/render to be finished.
*/
public static void forceCloseGame() {
- if (display != null) {
+ if (display != null && display.isReady()) {
display.close();
}
exit();
diff --git a/src/main/java/tech/fastj/systems/behaviors/BehaviorHandler.java b/src/main/java/tech/fastj/systems/behaviors/BehaviorHandler.java
index ad25326b..c81a1561 100644
--- a/src/main/java/tech/fastj/systems/behaviors/BehaviorHandler.java
+++ b/src/main/java/tech/fastj/systems/behaviors/BehaviorHandler.java
@@ -6,7 +6,7 @@
/**
* Interface denoting that the implementing classes directly interface with the {@link BehaviorManager} class.
- *
+ *
* FOR IMPLEMENTORS: In order for these methods to work you need to call {@link
* BehaviorManager#addListenerList(BehaviorHandler)} upon construction.
*/
diff --git a/src/main/java/tech/fastj/systems/control/SimpleManager.java b/src/main/java/tech/fastj/systems/control/SimpleManager.java
index 14dd0509..fe207f6a 100644
--- a/src/main/java/tech/fastj/systems/control/SimpleManager.java
+++ b/src/main/java/tech/fastj/systems/control/SimpleManager.java
@@ -44,11 +44,13 @@ public void render(Display display) {
);
}
+ /** Processes all stored input events. */
@Override
public void processInputEvents() {
inputManager.processEvents();
}
+ /** Stores the specified input event to be processed later ({@link #processInputEvents()}). */
@Override
public void receivedInputEvent(InputEvent inputEvent) {
inputManager.receivedInputEvent(inputEvent);
diff --git a/src/main/java/tech/fastj/systems/input/keyboard/Keyboard.java b/src/main/java/tech/fastj/systems/input/keyboard/Keyboard.java
index 3456be1d..d7fcc585 100644
--- a/src/main/java/tech/fastj/systems/input/keyboard/Keyboard.java
+++ b/src/main/java/tech/fastj/systems/input/keyboard/Keyboard.java
@@ -226,9 +226,11 @@ public static boolean areKeysDown() {
public static void stop() {
reset();
+
if (keyChecker != null) {
keyChecker.shutdownNow();
}
+ keyChecker = null;
}
@Override
diff --git a/src/main/java/tech/fastj/systems/tags/TagHandler.java b/src/main/java/tech/fastj/systems/tags/TagHandler.java
index d9cd61bb..75e37437 100644
--- a/src/main/java/tech/fastj/systems/tags/TagHandler.java
+++ b/src/main/java/tech/fastj/systems/tags/TagHandler.java
@@ -8,7 +8,7 @@
/**
* Interface denoting that the implementing classes directly interface with the {@link BehaviorManager} class.
- *
+ *
* FOR IMPLEMENTORS: In order for these methods to work you need to call {@link
* TagManager#addTaggableEntityList(TagHandler)} upon construction.
*/