Skip to content

Commit

Permalink
(#10) begin working on Paint support for Drawables
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasstarsz committed May 28, 2021
1 parent b0414c0 commit 3e44d61
Show file tree
Hide file tree
Showing 6 changed files with 309 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
exports tech.fastj.graphics.game;
exports tech.fastj.graphics.ui;
exports tech.fastj.graphics.ui.elements;
exports tech.fastj.graphics.util;

exports tech.fastj.systems.input;
exports tech.fastj.systems.input.keyboard;
Expand Down
30 changes: 29 additions & 1 deletion src/main/java/tech/fastj/graphics/game/Polygon2D.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
Expand All @@ -34,6 +35,7 @@ public class Polygon2D extends GameObject {
private Pointf[] points;

private Color color;
private Paint paint;
private boolean paintFilled;

private float rotation;
Expand Down Expand Up @@ -140,6 +142,26 @@ public Color getColor() {
return color;
}

/**
* Gets the paint for this polygon.
*
* @return The {@code Color} set for this polygon.
*/
public Paint getPaint() {
return paint;
}

/**
* Sets the pain for this polygon.
*
* @param newPaint The {@code Paint} to be used for the polygon.
* @return This instance of the {@code Polygon2D}, for method chaining.
*/
public Polygon2D setPaint(Paint newPaint) {
paint = newPaint;
return this;
}

/**
* Sets the color for the polygon.
*
Expand Down Expand Up @@ -271,13 +293,19 @@ public void scale(Pointf scaleMod, Pointf centerpoint) {
public void render(Graphics2D g) {
if (!shouldRender()) return;

g.setColor(color);
// g.setColor(color);

Paint oldPaint = g.getPaint();

g.setPaint(paint);

if (paintFilled) {
g.fill(renderPath);
} else {
g.draw(renderPath);
}

g.setPaint(oldPaint);
}

@Override
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/tech/fastj/graphics/util/GradientBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package tech.fastj.graphics.util;

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;
}
}
30 changes: 30 additions & 0 deletions src/main/java/tech/fastj/graphics/util/Gradients.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package tech.fastj.graphics.util;

import java.awt.GradientPaint;
import java.awt.LinearGradientPaint;
import java.awt.RadialGradientPaint;

/** Class to streamline working with the {@link GradientPaint} class (and its implementations) within FastJ. */
public class Gradients {

/** The amount of colors allowed in a single {@link LinearGradientBuilder} or {@link RadialGradientBuilder}. */
public static final int ColorLimit = 8;

/**
* Gets a builder instance for creating a {@link LinearGradientPaint}.
*
* @return A {@link LinearGradientPaint} builder.
*/
public static LinearGradientBuilder linearGradient() {
return LinearGradientBuilder.builder();
}

/**
* Gets a builder instance for creating a {@link RadialGradientPaint}.
*
* @return A {@link RadialGradientPaint} builder.
*/
public static RadialGradientBuilder radialGradient() {
return RadialGradientBuilder.builder();
}
}
116 changes: 116 additions & 0 deletions src/main/java/tech/fastj/graphics/util/LinearGradientBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package tech.fastj.graphics.util;

import tech.fastj.engine.FastJEngine;
import tech.fastj.math.Pointf;
import tech.fastj.graphics.Boundary;
import tech.fastj.graphics.Drawable;

import java.awt.Color;
import java.awt.LinearGradientPaint;

/** A builder class for creating {@link LinearGradientPaint} objects. */
public class LinearGradientBuilder implements GradientBuilder {

private Pointf from;
private Pointf to;

private final Color[] colors;
private int count;

/** Initializes a {@code LinearGradientBuilder}'s internals. */
LinearGradientBuilder() {
colors = new Color[Gradients.ColorLimit];
}

/**
* Sets the starting and ending points for the builder, based on the provided {@link Drawable} and {@link Boundary}
* values.
*
* @param drawable The basis for what the {@code start} and {@code end} end positions evaluate to.
* @param start The starting boundary to create the gradient from.
* @param end The ending boundary to create the gradient from.
* @return The {@code LinearGradientBuilder}, for method chaining.
*/
public LinearGradientBuilder position(Drawable drawable, Boundary start, Boundary end) {
if (start.equals(end)) {
FastJEngine.error(
GradientBuilder.GradientCreationError,
new IllegalStateException(
"The starting and ending positions for a gradient must not be the same."
+ System.lineSeparator()
+ "Both positions evaluated to: " + start.name()
)
);
}

this.from = drawable.getBound(start);
this.to = drawable.getBound(end);

return this;
}

/**
* Sets the starting and ending points for the builder, based on the provided {@link Pointf} values.
*
* @param start The {@code Pointf} defining the starting point of the gradient.
* @param end The {@code Pointf} defining the ending point of the gradient.
* @return The {@code LinearGradientBuilder}, for method chaining.
*/
public LinearGradientBuilder position(Pointf start, Pointf end) {
if (start.equals(end)) {
FastJEngine.error(
GradientBuilder.GradientCreationError,
new IllegalStateException(
"The starting and ending positions for a gradient must not be the same."
+ System.lineSeparator()
+ "Both positions evaluated to: " + start
)
);
}

this.from = start;
this.to = end;

return this;
}

/**
* Adds a {@link Color} to the builder to be used in the resulting gradient.
* <p>
* The amount of colors used in a {@link LinearGradientBuilder} not exceed {@link Gradients#ColorLimit}.
*
* @param color The {@code Color} being added.
* @return The {@code LinearGradientBuilder}, for method chaining.
*/
public LinearGradientBuilder withColor(Color color) {
if (count == Gradients.ColorLimit) {
FastJEngine.error(GradientBuilder.GradientCreationError,
new IllegalStateException("Gradients cannot contain more than " + Gradients.ColorLimit + " colors.")
);
}

colors[count] = color;
count++;
return this;
}

/**
* Creates a new {@link LinearGradientPaint} object, using the data provided by other method calls.
*
* @return The resulting {@code LinearGradientPaint}.
*/
@Override
public LinearGradientPaint build() {
float[] fractions = generateIntervals(colors.length);
return new LinearGradientPaint(from.x, from.y, to.x, to.y, fractions, colors);
}

/**
* Gets a new instance of a {@link LinearGradientBuilder}.
*
* @return The {@code LinearGradientBuilder} instance.
*/
static LinearGradientBuilder builder() {
return new LinearGradientBuilder();
}
}
99 changes: 99 additions & 0 deletions src/main/java/tech/fastj/graphics/util/RadialGradientBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package tech.fastj.graphics.util;

import tech.fastj.engine.FastJEngine;
import tech.fastj.math.Pointf;
import tech.fastj.graphics.Boundary;
import tech.fastj.graphics.Drawable;

import java.awt.Color;
import java.awt.RadialGradientPaint;

/** A builder class for creating {@link RadialGradientPaint} objects. */
public class RadialGradientBuilder implements GradientBuilder {

private Pointf center;
private float radius;

private final Color[] colors;
private int count;

/** Initializes a {@code RadialGradientBuilder}'s internals. */
RadialGradientBuilder() {
colors = new Color[Gradients.ColorLimit];
}

/**
* Sets the centerpoint and radius for the builder, based on the provided {@link Drawable}.
*
* @param drawable The drawable to get the center and radius from.
* @return The {@code RadialGradientBuilder}, for method chaining.
*/
public RadialGradientBuilder position(Drawable drawable) {
this.center = drawable.getCenter();

Pointf drawableSize = Pointf.subtract(this.center, drawable.getBound(Boundary.TopLeft));
this.radius = (float) Math.hypot(drawableSize.x, drawableSize.y);

return this;
}

/**
* Sets the centerpoint and radius for the builder, based on the provided {@link Pointf} and float values.
*
* @param center The {@code Pointf} defining the centerpoint for the gradient.
* @param radius The {@code float} defining the radius for the gradient.
* @return The {@code LinearGradientBuilder}, for method chaining.
*/
public RadialGradientBuilder position(Pointf center, float radius) {
if (radius <= 0f) {
FastJEngine.error(
GradientBuilder.GradientCreationError,
new IllegalStateException("The radius for a gradient must be larger than 0.")
);
}
this.center = center;
this.radius = radius;

return this;
}

/**
* Adds a {@link Color} to the builder to be used in the resulting gradient.
* <p>
* The amount of colors used in a {@link RadialGradientBuilder} not exceed {@link Gradients#ColorLimit}.
*
* @param color The {@code Color} being added.
* @return The {@code LinearGradientBuilder}, for method chaining.
*/
public RadialGradientBuilder withColor(Color color) {
if (count == Gradients.ColorLimit) {
FastJEngine.error(GradientBuilder.GradientCreationError,
new IllegalStateException("Gradients cannot contain more than " + Gradients.ColorLimit + " colors.")
);
}

colors[count] = color;
count++;
return this;
}

/**
* Creates a new {@link RadialGradientPaint} object, using the data provided by other method calls.
*
* @return The resulting {@code RadialGradientPaint}.
*/
@Override
public RadialGradientPaint build() {
float[] fractions = generateIntervals(colors.length);
return new RadialGradientPaint(center.x, center.y, radius, fractions, colors);
}

/**
* Gets a new instance of a {@link RadialGradientBuilder}.
*
* @return The {@code RadialGradientBuilder} instance.
*/
static RadialGradientBuilder builder() {
return new RadialGradientBuilder();
}
}

0 comments on commit 3e44d61

Please sign in to comment.