From 18d06d51285ca1c3bcc83599a5453ea433e410d5 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 13 Jun 2021 17:56:06 -0400 Subject: [PATCH] (#10) Add rotation/scale support to Text2D - Added constructors that don't require translation parameters, and constructors that allow initial scale/rotation. --- .../java/tech/fastj/graphics/Transform2D.java | 7 +- .../java/tech/fastj/graphics/game/Text2D.java | 64 +++++++++++-- .../testcases/graphics/game/Text2DTests.java | 93 ++++++++++++++----- 3 files changed, 131 insertions(+), 33 deletions(-) diff --git a/src/main/java/tech/fastj/graphics/Transform2D.java b/src/main/java/tech/fastj/graphics/Transform2D.java index 262fb7da..1a367f4f 100644 --- a/src/main/java/tech/fastj/graphics/Transform2D.java +++ b/src/main/java/tech/fastj/graphics/Transform2D.java @@ -5,6 +5,7 @@ import java.awt.geom.AffineTransform; +/** Convenience class for storing/performing 2D transformations using {@link AffineTransform}. */ public class Transform2D { /** {@link Pointf} representing a default translation of {@code (0f, 0f)}. */ @@ -39,16 +40,18 @@ public Pointf getScale() { public float getRotation() { float approximatedRotation = (float) Math.toDegrees(Math.atan2(rotationTransform.getShearY(), rotationTransform.getScaleY())); + float normalizedRotation = rotation % 360f; - if (Maths.floatEquals(rotation % 360f, approximatedRotation)) { + if (Maths.floatEquals(normalizedRotation, approximatedRotation)) { return rotation; } - float rotationCheck = Math.abs(rotation % 360f) + Math.abs(approximatedRotation); + float rotationCheck = Math.abs(normalizedRotation) + Math.abs(approximatedRotation); if (Maths.floatEquals(rotationCheck, 360f) || Maths.floatEquals(rotationCheck, 0f)) { return rotation; } + // according to logical thinking, this should not be reached. throw new IllegalStateException( "Something went wrong calculating the rotation.... we expected " + rotation + ", but we got " + approximatedRotation + " instead. :(" ); diff --git a/src/main/java/tech/fastj/graphics/game/Text2D.java b/src/main/java/tech/fastj/graphics/game/Text2D.java index b33a2157..eda60ec7 100644 --- a/src/main/java/tech/fastj/graphics/game/Text2D.java +++ b/src/main/java/tech/fastj/graphics/game/Text2D.java @@ -36,36 +36,85 @@ public class Text2D extends GameObject { private boolean hasMetrics; /** - * {@code Text2D} Constructor that takes in a string of text and a location. + * {@code Text2D} Constructor that takes in a string of text. + *

+ * This constructor defaults the color to {@link #DefaultColor}, the font to {@link #DefaultFont}, and sets the + * {@code show} boolean to {@link #DefaultShow}. + * + * @param setText Sets the displayed text. + */ + public Text2D(String setText) { + this(setText, DefaultColor, DefaultFont, DefaultShow); + } + + /** + * {@code Text2D} Constructor that takes in a string of text and an initial translation. *

* This constructor defaults the color to {@link #DefaultColor}, the font to {@link #DefaultFont}, and sets the * {@code show} boolean to {@link #DefaultShow}. * * @param setText Sets the displayed text. - * @param setTranslation Sets the x and y location of the text. + * @param setTranslation Sets the initial x and y translation of the text. */ public Text2D(String setText, Pointf setTranslation) { - this(setText, setTranslation, DefaultColor, DefaultFont, DefaultShow); + this(setText, DefaultColor, DefaultFont, DefaultShow); + setTranslation(setTranslation); } /** - * {@code Text2D} Constructor that takes in a string of text, a location, a color, a font, and a show variable. + * {@code Text2D} Constructor that takes in a string of text, a color, a font, and a show variable. + * + * @param setText Sets the displayed text. + * @param setColor Sets the text's color. + * @param setFont Sets the text's font. + * @param show Sets whether the text will be drawn to the screen. + */ + public Text2D(String setText, Color setColor, Font setFont, boolean show) { + text = setText; + font = setFont; + + setColor(setColor); + setFont(setFont); + setShouldRender(show); + } + + /** + * {@code Text2D} Constructor that takes in a string of text, a translation, a color, a font, and a show variable. * * @param setText Sets the displayed text. - * @param setTranslation Sets the x and y location of the text. + * @param setTranslation Sets the initial x and y translation of the text. * @param setColor Sets the text's color. * @param setFont Sets the text's font. * @param show Sets whether the text will be drawn to the screen. */ public Text2D(String setText, Pointf setTranslation, Color setColor, Font setFont, boolean show) { + this(setText, setColor, setFont, show); + setTranslation(setTranslation); + } + + /** + * {@code Text2D} Constructor that takes in a string of text, a translation/rotation/scale, a color, a font, and a + * show variable. + * + * @param setText Sets the displayed text. + * @param setTranslation Sets the initial x and y translation of the text. + * @param setRotation Sets the initial rotation of the text. + * @param setScale Sets the initial scale of the text. + * @param setColor Sets the text's color. + * @param setFont Sets the text's font. + * @param show Sets whether the text will be drawn to the screen. + */ + public Text2D(String setText, Pointf setTranslation, float setRotation, Pointf setScale, Color setColor, Font setFont, boolean show) { text = setText; font = setFont; setTranslation(setTranslation); + setRotation(setRotation); + setScale(setScale); + setColor(setColor); + setFont(setFont); setShouldRender(show); - - setMetrics(FastJEngine.getDisplay().getGraphics()); } /** @@ -162,6 +211,7 @@ public void destroy(Scene originScene) { text = null; color = null; font = null; + hasMetrics = false; super.destroyTheRest(originScene); } diff --git a/src/test/java/unittest/testcases/graphics/game/Text2DTests.java b/src/test/java/unittest/testcases/graphics/game/Text2DTests.java index 7f937164..9d06ec70 100644 --- a/src/test/java/unittest/testcases/graphics/game/Text2DTests.java +++ b/src/test/java/unittest/testcases/graphics/game/Text2DTests.java @@ -12,8 +12,8 @@ import org.junit.jupiter.api.Test; import unittest.EnvironmentHelper; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static unittest.EnvironmentHelper.runFastJWith; @@ -24,6 +24,20 @@ public static void onlyRunIfNotHeadless() { assumeFalse(EnvironmentHelper.IsEnvironmentHeadless); } + @Test + void checkText2DConstructor_withStringTextParam() { + runFastJWith(() -> { + String text = "Hello, world!"; + + Text2D text2D = new Text2D(text); + + assertEquals(text, text2D.getText(), "The actual text should match the expected text."); + assertEquals(Text2D.DefaultColor, text2D.getColor(), "The actual color should match the expected color."); + assertEquals(Text2D.DefaultFont, text2D.getFont(), "The actual font should match the default font."); + assertEquals(Text2D.DefaultShow, text2D.shouldRender(), "The actual show variable should match the default show variable."); + }); + } + @Test void checkText2DConstructor_withStringTextParam_andPointfTranslationParam() { runFastJWith(() -> { @@ -41,45 +55,82 @@ void checkText2DConstructor_withStringTextParam_andPointfTranslationParam() { } @Test - void checkText2DConstructor_withStringTextParam_andPointfTranslationParam_andColorParam_andFontParam_andShowParam() { + void checkText2DConstructor_withStringTextParam_andRandomlyGeneratedTranslationParam_andRandomlyGeneratedColorFontShowParams() { runFastJWith(() -> { String text = "Hello, world!"; Pointf randomTranslation = new Pointf(Maths.random(-50f, 50f), Maths.random(-50f, 50f)); Color randomColor = DrawUtil.randomColorWithAlpha(); Font randomFont = DrawUtil.randomFont(); - boolean shouldRender = Maths.randomBoolean(); + boolean randomShouldRender = Maths.randomBoolean(); - Text2D text2D = new Text2D(text, randomTranslation, randomColor, randomFont, shouldRender); + Text2D text2D = new Text2D(text, randomTranslation, randomColor, randomFont, randomShouldRender); assertEquals(text, text2D.getText(), "The actual text should match the expected text."); assertEquals(randomTranslation, text2D.getTranslation(), "The actual translation should match the expected translation."); assertEquals(randomColor, text2D.getColor(), "The actual color should match the expected random color."); assertEquals(randomFont, text2D.getFont(), "The actual font should match the expected random font."); - assertEquals(shouldRender, text2D.shouldRender(), "The actual show variable should match the expected random show variable."); + assertEquals(randomShouldRender, text2D.shouldRender(), "The actual show variable should match the expected random show variable."); }); } @Test - void checkText2DConstructor_withStringTextParam_andPointfTranslationParam_andColorParam_andFontParam_andShowParam_usingMethodChaining() { + void checkText2DConstructor_withStringTextParam_andRandomlyGeneratedTransformationParams_andRandomlyGeneratedColorFontShowParams() { runFastJWith(() -> { String text = "Hello, world!"; + Color randomColor = DrawUtil.randomColorWithAlpha(); + Font randomFont = DrawUtil.randomFont(); + boolean randomShouldRender = Maths.randomBoolean(); + Pointf randomTranslation = new Pointf(Maths.random(-50f, 50f), Maths.random(-50f, 50f)); + Pointf randomScale = new Pointf(Maths.random(-50f, 50f), Maths.random(-50f, 50f)); + float randomRotation = Maths.random(-5000f, 5000f); + float expectedNormalizedRotation = randomRotation % 360; + + Text2D text2D = new Text2D(text, randomTranslation, randomRotation, randomScale, randomColor, randomFont, randomShouldRender); + + assertEquals(text, text2D.getText(), "The actual text should match the expected text."); + assertEquals(randomTranslation, text2D.getTranslation(), "The actual translation should match the expected translation."); + assertEquals(randomRotation, text2D.getRotation(), "The created polygon's rotation should match the randomly generated rotation."); + assertEquals(expectedNormalizedRotation, text2D.getRotationWithin360(), "The created model's normalized rotation should match the normalized rotation."); + assertEquals(randomScale, text2D.getScale(), "The created polygon's scaling should match the randomly generated scale."); + assertEquals(randomColor, text2D.getColor(), "The actual color should match the expected random color."); + assertEquals(randomFont, text2D.getFont(), "The actual font should match the expected random font."); + assertEquals(randomShouldRender, text2D.shouldRender(), "The actual show variable should match the expected random show variable."); + }); + } + + @Test + void checkText2DConstructor_withStringTextParam_andRandomlyGeneratedTransformationParams_andRandomlyGeneratedColorFontShowParams_usingMethodChaining() { + runFastJWith(() -> { + String text = "Hello, world!"; + Color randomColor = DrawUtil.randomColorWithAlpha(); Font randomFont = DrawUtil.randomFont(); - boolean shouldRender = Maths.randomBoolean(); + boolean randomShouldRender = Maths.randomBoolean(); + + Pointf randomTranslation = new Pointf(Maths.random(-50f, 50f), Maths.random(-50f, 50f)); + Pointf randomScale = new Pointf(Maths.random(-50f, 50f), Maths.random(-50f, 50f)); + float randomRotation = Maths.random(-5000f, 5000f); + float expectedNormalizedRotation = randomRotation % 360; - Text2D text2D = (Text2D) new Text2D(text, randomTranslation) + Text2D text2D = (Text2D) new Text2D(text) .setColor(randomColor) .setFont(randomFont) - .setShouldRender(shouldRender); + .setTranslation(randomTranslation) + .setRotation(randomRotation) + .setScale(randomScale) + .setShouldRender(randomShouldRender); assertEquals(text, text2D.getText(), "The actual text should match the expected text."); assertEquals(randomTranslation, text2D.getTranslation(), "The actual translation should match the expected translation."); + assertEquals(randomRotation, text2D.getRotation(), "The created polygon's rotation should match the randomly generated rotation."); + assertEquals(expectedNormalizedRotation, text2D.getRotationWithin360(), "The created model's normalized rotation should match the normalized rotation."); + assertEquals(randomScale, text2D.getScale(), "The created polygon's scaling should match the randomly generated scale."); assertEquals(randomColor, text2D.getColor(), "The actual color should match the expected random color."); assertEquals(randomFont, text2D.getFont(), "The actual font should match the expected random font."); - assertEquals(shouldRender, text2D.shouldRender(), "The actual show variable should match the expected random show variable."); + assertEquals(randomShouldRender, text2D.shouldRender(), "The actual show variable should match the expected random show variable."); }); } @@ -101,34 +152,28 @@ void checkTranslateText2D_shouldMatchExpected() { } @Test - void checkRotateText2D_shouldThrowException() { + void checkRotateText2D_shouldMatchExpected() { runFastJWith(() -> { String text = "Hello, world!"; - Pointf originalTranslation = Pointf.Origin.copy(); float randomRotation = Maths.random(-50f, 50f); - Text2D text2D = new Text2D(text, originalTranslation); - Throwable exception = assertThrows(IllegalStateException.class, () -> text2D.rotate(randomRotation, Pointf.Origin)); + Text2D text2D = new Text2D(text); - String expectedErrorMessage = "ERROR: The game crashed, due to the call of a method not yet implemented."; - String actualErrorMessage = exception.getMessage(); - assertEquals(expectedErrorMessage, actualErrorMessage); + assertDoesNotThrow(() -> text2D.rotate(randomRotation, Pointf.Origin), "Rotating Text2D objects is implemented, and should not throw an exception."); + assertEquals(randomRotation, text2D.getRotation(), "The actual rotation should match the expected rotation."); }); } @Test - void checkScaleText2D_shouldThrowException() { + void checkScaleText2D_shouldMatchExpected() { runFastJWith(() -> { String text = "Hello, world!"; - Pointf originalTranslation = Pointf.Origin.copy(); Pointf randomScale = new Pointf(Maths.random(-50f, 50f), Maths.random(-50f, 50f)); - Text2D text2D = new Text2D(text, originalTranslation); - Throwable exception = assertThrows(IllegalStateException.class, () -> text2D.scale(randomScale, originalTranslation)); + Text2D text2D = new Text2D(text); - String expectedErrorMessage = "ERROR: The game crashed, due to the call of a method not yet implemented."; - String actualErrorMessage = exception.getMessage(); - assertEquals(expectedErrorMessage, actualErrorMessage); + assertDoesNotThrow(() -> text2D.scale(randomScale), "Scaling Text2D objects is implemented, and should not throw an exception."); + assertEquals(Pointf.add(randomScale, 1f), text2D.getScale(), "The actual scale should match the expected scale."); }); } }