Skip to content

Commit

Permalink
Merge pull request #26 from fastjengine/drawable-improvement
Browse files Browse the repository at this point in the history
Drawable Improvement 2 - Gradient Improvements
  • Loading branch information
lucasstarsz authored Jun 6, 2021
2 parents 270bf58 + 6c2ac6e commit 30b1b45
Show file tree
Hide file tree
Showing 20 changed files with 2,295 additions and 235 deletions.
4 changes: 2 additions & 2 deletions src/main/java/tech/fastj/graphics/game/Polygon2D.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ public Polygon2D(Pointf[] pts, Paint paint, boolean fill, boolean show) {
}

/**
* {@code Polygon2D} constructor that takes in a set of points, a paint variable, fill variable, a show variable, and the
* translation, rotation, and scale of the polygon.
* {@code Polygon2D} constructor that takes in a set of points, a paint variable, fill variable, a show variable,
* and the translation, rotation, and scale of the polygon.
*
* @param pts {@code Pointf} array that defines the points for the polygon.
* @param setLocation {@code Pointf} to set the initial location of the polygon.
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/tech/fastj/graphics/ui/elements/Button.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import tech.fastj.engine.FastJEngine;
import tech.fastj.math.Pointf;
import tech.fastj.graphics.Camera;
import tech.fastj.graphics.util.DrawUtil;
import tech.fastj.graphics.game.Text2D;
import tech.fastj.graphics.ui.UIElement;
import tech.fastj.graphics.util.DrawUtil;

import tech.fastj.systems.control.Scene;
import tech.fastj.systems.input.mouse.Mouse;
Expand Down
165 changes: 73 additions & 92 deletions src/main/java/tech/fastj/graphics/util/DrawUtil.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
package tech.fastj.graphics.util;

import tech.fastj.engine.CrashMessages;
import tech.fastj.engine.FastJEngine;
import tech.fastj.math.Maths;
import tech.fastj.math.Pointf;
import tech.fastj.graphics.Boundary;
import tech.fastj.graphics.Drawable;
import tech.fastj.graphics.game.Polygon2D;
import tech.fastj.graphics.util.gradients.Gradients;
import tech.fastj.graphics.util.gradients.LinearGradientBuilder;
import tech.fastj.graphics.util.gradients.RadialGradientBuilder;

import java.awt.Color;
import java.awt.Font;
Expand Down Expand Up @@ -75,22 +69,28 @@ public static Pointf[] createCollisionOutline(Polygon2D[] polyList) {
Pointf center = centerOf(unshiftedResult);
Arrays.sort(unshiftedResult, (a, b) -> {
// thank goodness for stackoverflow...
if (a.x - center.x >= 0 && b.x - center.x < 0)
if (a.x - center.x >= 0 && b.x - center.x < 0) {
return 1;
if (a.x - center.x < 0 && b.x - center.x >= 0)
}
if (a.x - center.x < 0 && b.x - center.x >= 0) {
return -1;
}
if (a.x - center.x == 0 && b.x - center.x == 0) {
if (a.y - center.y >= 0 || b.y - center.y >= 0)
if (a.y - center.y >= 0 || b.y - center.y >= 0) {
return (a.y > b.y) ? 1 : -1;
}

return (b.y > a.y) ? 1 : -1;
}

// compute the cross product of vectors (center -> a) x (center -> b)
float det = (a.x - center.x) * (b.y - center.y) - (b.x - center.x) * (a.y - center.y);
if (det < 0f)
if (det < 0f) {
return 1;
if (det > 0f)
}
if (det > 0f) {
return -1;
}

// points a and b are on the same line from the center
// check which point is closer to the center
Expand Down Expand Up @@ -187,22 +187,6 @@ public static boolean pathEquals(Path2D path1, Path2D path2) {
return true;
}

/**
* Shorthand for checking equality between two {@link MultipleGradientPaint} objects.
*
* @param mGradientPaint1 The first {@code Paint} specified.
* @param mGradientPaint2 The second {@code Paint} specified.
* @return Whether the two {@code Paint}s are equal.
*/
private static boolean mGradientEquals(MultipleGradientPaint mGradientPaint1, MultipleGradientPaint mGradientPaint2) {
return mGradientPaint1.getTransparency() == mGradientPaint2.getTransparency()
&& mGradientPaint1.getTransform().equals(mGradientPaint2.getTransform())
&& mGradientPaint1.getColorSpace().equals(mGradientPaint2.getColorSpace())
&& mGradientPaint1.getCycleMethod().equals(mGradientPaint2.getCycleMethod())
&& Arrays.deepEquals(mGradientPaint1.getColors(), mGradientPaint2.getColors())
&& Arrays.equals(mGradientPaint1.getFractions(), mGradientPaint2.getFractions());
}

/**
* Checks for equality between two {@link Paint} objects as best as possible.
*
Expand Down Expand Up @@ -261,6 +245,22 @@ public static boolean paintEquals(Paint paint1, Paint paint2) {
return paint1.equals(paint2);
}

/**
* Shorthand for checking equality between two {@link MultipleGradientPaint} objects.
*
* @param mGradientPaint1 The first {@code Paint} specified.
* @param mGradientPaint2 The second {@code Paint} specified.
* @return Whether the two {@code Paint}s are equal.
*/
private static boolean mGradientEquals(MultipleGradientPaint mGradientPaint1, MultipleGradientPaint mGradientPaint2) {
return mGradientPaint1.getTransparency() == mGradientPaint2.getTransparency()
&& mGradientPaint1.getTransform().equals(mGradientPaint2.getTransform())
&& mGradientPaint1.getColorSpace().equals(mGradientPaint2.getColorSpace())
&& mGradientPaint1.getCycleMethod().equals(mGradientPaint2.getCycleMethod())
&& Arrays.deepEquals(mGradientPaint1.getColors(), mGradientPaint2.getColors())
&& Arrays.equals(mGradientPaint1.getFractions(), mGradientPaint2.getFractions());
}

/**
* Creates a {@code Pointf} array of 4 points, based on the specified x, y, width, and height floats.
* <p>
Expand Down Expand Up @@ -453,10 +453,7 @@ public static Pointf[] createBoxFromImage(BufferedImage source) {
*/
public static Rectangle2D.Float createRect(Pointf[] pts) {
if (pts.length != 4) {
FastJEngine.error(
CrashMessages.theGameCrashed("a rectangle creation error."),
new IllegalArgumentException("The length of the parameter point array must be 4.")
);
throw new IllegalArgumentException("The length of the parameter point array must be 4.");
}

return new Rectangle2D.Float(pts[0].x, pts[0].y, pts[1].x - pts[0].x, pts[3].y - pts[0].y);
Expand All @@ -482,7 +479,9 @@ public static Rectangle2D.Float createRectFromImage(BufferedImage source, Pointf
*/
public static Pointf centerOf(Pointf[] points) {
Pointf result = new Pointf();
for (Pointf p : points) result.add(p);
for (Pointf p : points) {
result.add(p);
}
return result.divide(points.length);
}

Expand All @@ -499,22 +498,28 @@ public static Pointf[] pointsOfPath(Path2D.Float path) {

for (PathIterator pi = path.getPathIterator(null); !pi.isDone(); pi.next()) {
switch (pi.currentSegment(coords)) {
case PathIterator.SEG_MOVETO:
case PathIterator.SEG_MOVETO: {
pointList.add(new Pointf(coords[0], coords[1]));
numSubPaths++;
break;
case PathIterator.SEG_LINETO:
}
case PathIterator.SEG_LINETO: {
pointList.add(new Pointf(coords[0], coords[1]));
break;
case PathIterator.SEG_CLOSE:
}
case PathIterator.SEG_CLOSE: {
if (numSubPaths > 1) {
throw new IllegalArgumentException("Path contains multiple sub-paths");
}

return pointList.toArray(new Pointf[0]);
default:
}
default: {
throw new IllegalArgumentException("Path contains curves");
}
}
}

throw new IllegalArgumentException("Unclosed path");
}

Expand All @@ -532,16 +537,20 @@ public static int lengthOfPath(Path2D path) {

for (PathIterator pi = path.getPathIterator(null); !pi.isDone(); pi.next()) {
switch (pi.currentSegment(coords)) {
case PathIterator.SEG_MOVETO:
case PathIterator.SEG_MOVETO: {
break;
case PathIterator.SEG_CLOSE:
}
case PathIterator.SEG_CLOSE: {
numSubPaths++;
break;
case PathIterator.SEG_LINETO:
}
case PathIterator.SEG_LINETO: {
count++;
break;
default:
}
default: {
throw new IllegalArgumentException("Path contains curves");
}
}
}

Expand All @@ -554,7 +563,12 @@ public static int lengthOfPath(Path2D path) {
* @return The randomly generated {@code Color}.
*/
public static Color randomColor() {
return new Color((int) Maths.random(0, 255), (int) Maths.random(0, 255), (int) Maths.random(0, 255), 255);
return new Color(
(int) Maths.random(0, 255),
(int) Maths.random(0, 255),
(int) Maths.random(0, 255),
255
);
}

/**
Expand All @@ -563,7 +577,12 @@ public static Color randomColor() {
* @return The randomly generated {@code Color}.
*/
public static Color randomColorWithAlpha() {
return new Color((int) Maths.random(0, 255), (int) Maths.random(0, 255), (int) Maths.random(0, 255), (int) Maths.random(0, 255));
return new Color(
(int) Maths.random(0, 255),
(int) Maths.random(0, 255),
(int) Maths.random(0, 255),
(int) Maths.random(0, 255)
);
}

/**
Expand All @@ -574,58 +593,20 @@ public static Color randomColorWithAlpha() {
*/
public static Font randomFont() {
Font[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();

int randomFontStyle = Maths.randomInteger(0, 2);
int font = randomFontStyle == 0
? Font.PLAIN
: randomFontStyle == 1
? Font.BOLD
: Font.ITALIC;

return new Font(fontNames[Maths.randomInteger(0, fontNames.length - 1)].getFontName(), font, Maths.randomInteger(1, 256));
}

public static LinearGradientPaint randomLinearGradient(Drawable drawable, Boundary start, Boundary end) {
LinearGradientBuilder linearGradientBuilder = Gradients.linearGradient().position(drawable, start, end);

int randomColorCount = Maths.randomInteger(2, 8);
for (int i = 0; i < randomColorCount; i++) {
linearGradientBuilder.withColor(randomColor());
String randomFontName = fontNames[Maths.randomInteger(0, fontNames.length - 1)].getFontName();

int styleValue = Maths.randomInteger(0, 2);
int randomFontStyle;
if (styleValue == 0) {
randomFontStyle = Font.PLAIN;
} else if (styleValue == 1) {
randomFontStyle = Font.BOLD;
} else {
randomFontStyle = Font.ITALIC;
}

return linearGradientBuilder.build();
}

public static LinearGradientPaint randomLinearGradientWithAlpha(Drawable drawable, Boundary start, Boundary end) {
LinearGradientBuilder linearGradientBuilder = Gradients.linearGradient().position(drawable, start, end);

int randomColorCount = Maths.randomInteger(2, 8);
for (int i = 0; i < randomColorCount; i++) {
linearGradientBuilder.withColor(randomColorWithAlpha());
}

return linearGradientBuilder.build();
}

public static RadialGradientPaint randomRadialGradient(Drawable drawable) {
RadialGradientBuilder radialGradientBuilder = Gradients.radialGradient().position(drawable);

int randomColorCount = Maths.randomInteger(2, 8);
for (int i = 0; i < randomColorCount; i++) {
radialGradientBuilder.withColor(randomColor());
}

return radialGradientBuilder.build();
}

public static RadialGradientPaint randomRadialGradientWithAlpha(Drawable drawable) {
RadialGradientBuilder radialGradientBuilder = Gradients.radialGradient().position(drawable);

int randomColorCount = Maths.randomInteger(2, 8);
for (int i = 0; i < randomColorCount; i++) {
radialGradientBuilder.withColor(randomColorWithAlpha());
}
int randomFontSize = Maths.randomInteger(1, 256);

return radialGradientBuilder.build();
return new Font(randomFontName, randomFontStyle, randomFontSize);
}
}
18 changes: 8 additions & 10 deletions src/main/java/tech/fastj/graphics/util/PsdfUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -40,10 +41,10 @@ public class PsdfUtil {
public static Polygon2D[] loadPsdf(String fileLocation) {
// check for correct file extension
if (!fileLocation.substring(fileLocation.lastIndexOf(".") + 1).equalsIgnoreCase("psdf")) {
FastJEngine.error(PsdfReadErrorMessage,
new IllegalArgumentException("Unsupported file type."
throw new IllegalArgumentException(
"Unsupported file type."
+ System.lineSeparator()
+ "This engine currently only supports files of the extension \".psdf\".")
+ "This engine currently only supports files of the extension \".psdf\"."
);
}

Expand All @@ -59,7 +60,7 @@ public static Polygon2D[] loadPsdf(String fileLocation) {
private static Polygon2D[] parsePsdf(String fileLocation) {
try {
Polygon2D[] result = null;
List<String> lines = Files.readAllLines(Paths.get(fileLocation));
List<String> lines = Files.readAllLines(Path.of(fileLocation));
List<Pointf> polygonPoints = new ArrayList<>();
Paint paint = null;
boolean fillPolygon = false;
Expand All @@ -80,8 +81,7 @@ private static Polygon2D[] parsePsdf(String fileLocation) {
break;
}
case "lg": { // set paint as LinearGradientPaint
LinearGradientBuilder linearGradientBuilder = Gradients.linearGradient();
linearGradientBuilder.position(
LinearGradientBuilder linearGradientBuilder = Gradients.linearGradient(
new Pointf(
Float.parseFloat(tokens[1]),
Float.parseFloat(tokens[2])
Expand All @@ -108,8 +108,7 @@ private static Polygon2D[] parsePsdf(String fileLocation) {
break;
}
case "rg": { // set paint as RadialGradientPaint
RadialGradientBuilder radialGradientBuilder = Gradients.radialGradient();
radialGradientBuilder.position(
RadialGradientBuilder radialGradientBuilder = Gradients.radialGradient(
new Pointf(
Float.parseFloat(tokens[1]),
Float.parseFloat(tokens[2])
Expand Down Expand Up @@ -164,8 +163,7 @@ private static Polygon2D[] parsePsdf(String fileLocation) {
}
return result;
} catch (IOException e) {
FastJEngine.error(PsdfReadErrorMessage, e);
return null;
throw new IllegalStateException("An issue occurred while trying to parse file \"" + fileLocation + "\".", e);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,13 @@
package tech.fastj.graphics.util.gradients;

import tech.fastj.engine.CrashMessages;

import java.awt.MultipleGradientPaint;

/** The top-level interface for all gradient builders in the package {@link tech.fastj.graphics.util}. */
public interface GradientBuilder {

/** Error message defining that a gradient creation error occurred. */
String GradientCreationError = CrashMessages.theGameCrashed("a gradient creation error.");

/**
* Builds a {@code MultipleGradientPaint} object based on the data provided by other methods in the builder.
*
* @return The resulting {@code MultipleGradientPaint} object.
*/
MultipleGradientPaint build();

/**
* Generates an array of linear intervals from {@code 0.0f} to {@code 1.0} inclusive, based on the size provided.
*
* @param size The size of the generated array.
* @return The generated array.
*/
default float[] generateIntervals(int size) {
float[] intervals = new float[size];

for (int i = 0; i < intervals.length; i++) {
intervals[i] = (1f / (intervals.length - 1)) * (float) (i);
}
return intervals;
}
}
Loading

0 comments on commit 30b1b45

Please sign in to comment.