mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Added 3D mark arrows and cleaned up other classes.
This commit is contained in:
@@ -58,7 +58,7 @@ public class BoatModel extends Model {
|
||||
*/
|
||||
public void changeColour(Color newColour) {
|
||||
changeColourChild(HULL_INDEX, newColour);
|
||||
changeColourChild(SAIL_INDEX, newColour);
|
||||
changeColourChild(MAST_INDEX, newColour);
|
||||
}
|
||||
|
||||
private void changeColourChild(int index, Color newColour) {
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
package seng302.visualiser.fxObjects.assets_3D;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.transform.Rotate;
|
||||
|
||||
/**
|
||||
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2
|
||||
* dimensional boat. It contains a single polygon for the boat, a group of lines to show it's path,
|
||||
* a wake object and two text labels to annotate the boat teams name and the boats velocity. The
|
||||
* boat will update it's position onscreen everytime UpdatePosition is called unless the window is
|
||||
* minimized in which case it attempts to store animations and apply them when the window is
|
||||
* maximised.
|
||||
*/
|
||||
public class BoatObject extends Group {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SelectedBoatListener {
|
||||
|
||||
void notifySelected(BoatObject boatObject, Boolean isSelected);
|
||||
}
|
||||
|
||||
private BoatModel boatAssets;
|
||||
private Group wake;
|
||||
private Color colour = Color.BLACK;
|
||||
private Boolean isSelected = false;
|
||||
private Rotate rotation = new Rotate(0,0,1);
|
||||
|
||||
private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates a BoatGroup with the default triangular boat polygon.
|
||||
*/
|
||||
public BoatObject() {
|
||||
boatAssets = ModelFactory.boatGameView(BoatMeshType.DINGHY, colour);
|
||||
boatAssets.hideSail();
|
||||
boatAssets.getAssets().getTransforms().addAll(
|
||||
rotation
|
||||
);
|
||||
boatAssets.getAssets().setOnMouseClicked(event -> {
|
||||
setIsSelected(!isSelected);
|
||||
updateListeners();
|
||||
});
|
||||
boatAssets.getAssets().setCache(true);
|
||||
wake = ModelFactory.importModel(ModelType.WAKE).getAssets();
|
||||
super.getChildren().addAll(boatAssets.getAssets());
|
||||
}
|
||||
|
||||
public void setFill (Color value) {
|
||||
this.colour = value;
|
||||
boatAssets.changeColour(colour);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves the boat and its children annotations to coordinates specified
|
||||
* @param x The X coordinate to move the boat to
|
||||
* @param y The Y coordinate to move the boat to
|
||||
* @param rotation The rotation by which the boat moves
|
||||
* @param velocity The velocity the boat is moving
|
||||
* @param sailIn Boolean to toggle sail state.
|
||||
* @param windDir .
|
||||
*/
|
||||
public void moveTo(double x, double y, double rotation, double velocity, Boolean sailIn, double windDir) {
|
||||
Double dx = Math.abs(boatAssets.getAssets().getLayoutX() - x);
|
||||
Double dy = Math.abs(boatAssets.getAssets().getLayoutY() - y);
|
||||
Platform.runLater(() -> {
|
||||
rotateTo(rotation, sailIn, windDir);
|
||||
this.layoutXProperty().setValue(x);
|
||||
this.layoutYProperty().setValue(y);
|
||||
wake.setLayoutX(x);
|
||||
wake.setLayoutY(y);
|
||||
});
|
||||
}
|
||||
|
||||
private Double normalizeHeading(double heading, double windDirection) {
|
||||
Double normalizedHeading = heading - windDirection;
|
||||
normalizedHeading = (double) Math.floorMod(normalizedHeading.longValue(), 360L);
|
||||
return normalizedHeading;
|
||||
}
|
||||
|
||||
|
||||
private void rotateTo(double heading, boolean sailsIn, double windDir) {
|
||||
rotation.setAngle(heading);
|
||||
wake.getTransforms().setAll(new Rotate(heading, new Point3D(0,0,1)));
|
||||
if (sailsIn) {
|
||||
boatAssets.showSail();
|
||||
Double sailWindOffset = 30.0;
|
||||
Double upwindAngleLimit = 15.0;
|
||||
Double downwindAngleLimit = 10.0; //Upwind from normalised horizontal
|
||||
Double normalizedHeading = normalizeHeading(heading, windDir);
|
||||
if (normalizedHeading < 180) {
|
||||
if (normalizedHeading < sailWindOffset + upwindAngleLimit){
|
||||
boatAssets.rotateSail(-upwindAngleLimit);
|
||||
} else if (normalizedHeading > 90 + sailWindOffset){
|
||||
boatAssets.rotateSail(-90 + downwindAngleLimit);
|
||||
} else {
|
||||
boatAssets.rotateSail(-heading + windDir + sailWindOffset);
|
||||
}
|
||||
} else {
|
||||
if (normalizedHeading > 360 - (sailWindOffset + upwindAngleLimit)) {
|
||||
boatAssets.rotateSail(upwindAngleLimit);
|
||||
} else if (normalizedHeading < 270 - sailWindOffset) {
|
||||
boatAssets.rotateSail(90 - downwindAngleLimit);
|
||||
} else {
|
||||
boatAssets.rotateSail(-heading + windDir - sailWindOffset);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
boatAssets.hideSail();
|
||||
}
|
||||
}
|
||||
|
||||
public Group getWake () {
|
||||
return wake;
|
||||
}
|
||||
|
||||
public void setIsSelected(Boolean isSelected) {
|
||||
this.isSelected = isSelected;
|
||||
}
|
||||
|
||||
private void updateListeners() {
|
||||
for (SelectedBoatListener sbl : selectedBoatListenerListeners) {
|
||||
sbl.notifySelected(this, this.isSelected);
|
||||
}
|
||||
}
|
||||
|
||||
public void addSelectedBoatListener(SelectedBoatListener sbl) {
|
||||
selectedBoatListenerListeners.add(sbl);
|
||||
}
|
||||
}
|
||||
@@ -4,45 +4,42 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.Paint;
|
||||
import javafx.scene.transform.Scale;
|
||||
import seng302.visualiser.fxObjects.assets_2D.MarkArrowFactory;
|
||||
import seng302.visualiser.fxObjects.assets_2D.MarkArrowFactory.RoundingSide;
|
||||
import seng302.visualiser.fxObjects.MarkArrowFactory;
|
||||
import seng302.visualiser.fxObjects.MarkArrowFactory.RoundingSide;
|
||||
|
||||
/**
|
||||
* Visual object for a mark. Contains a coloured circle and any specified arrows.
|
||||
*/
|
||||
public class Marker3D extends Group {
|
||||
|
||||
private Group mark = ModelFactory.importModel(ModelType.PLAIN_MARKER).getAssets();
|
||||
private Paint colour = Color.BLACK;
|
||||
private Model mark;
|
||||
private List<Group> enterArrows = new ArrayList<>();
|
||||
private List<Group> exitArrows = new ArrayList<>();
|
||||
private int enterArrowIndex = 0;
|
||||
private int exitArrowIndex = 0;
|
||||
private ModelType markType;
|
||||
private ModelType arrowType;
|
||||
|
||||
/**
|
||||
* Creates a new Marker containing only a circle. The default colour is black.
|
||||
*/
|
||||
public Marker3D() {
|
||||
// mark.setRadius(5);
|
||||
// mark.setCenterX(0);
|
||||
// mark.setCenterY(0);
|
||||
Platform.runLater(() -> {
|
||||
mark.getTransforms().add(new Scale(5,5,5));
|
||||
this.getChildren().addAll(mark, new Group());
|
||||
}); //Empty group placeholder or arrows.
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Marker containing only a circle of the given colour.
|
||||
* @param colour the desired colour for the marker.
|
||||
*/
|
||||
public Marker3D(Paint colour) {
|
||||
this();
|
||||
this.colour = colour;
|
||||
// mark.setFill(colour);
|
||||
public Marker3D(ModelType modelType) {
|
||||
markType = modelType;
|
||||
switch (markType) {
|
||||
case PLAIN_MARKER:
|
||||
arrowType = ModelType.PLAIN_ARROW;
|
||||
break;
|
||||
case FINISH_MARKER:
|
||||
arrowType = ModelType.FINISH_ARROW;
|
||||
break;
|
||||
case START_MARKER:
|
||||
arrowType = ModelType.START_ARROW;
|
||||
break;
|
||||
}
|
||||
mark = ModelFactory.importModel(modelType);
|
||||
Platform.runLater(() ->
|
||||
this.getChildren().addAll(mark.getAssets())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,13 +50,13 @@ public class Marker3D extends Group {
|
||||
* @param exitAngle The angle the arrow wil point from the marker.
|
||||
*/
|
||||
public void addArrows(RoundingSide roundingSide, double entryAngle,
|
||||
double exitAngle) {
|
||||
double exitAngle) {
|
||||
//Change Color.GRAY to this.colour to revert all gray arrows.
|
||||
enterArrows.add(
|
||||
MarkArrowFactory.constructEntryArrow(roundingSide, entryAngle, exitAngle, Color.GRAY)
|
||||
MarkArrowFactory.constructEntryArrow3D(roundingSide, entryAngle, arrowType).getAssets()
|
||||
);
|
||||
exitArrows.add(
|
||||
MarkArrowFactory.constructExitArrow(roundingSide, exitAngle, Color.GRAY)
|
||||
MarkArrowFactory.constructExitArrow3D(roundingSide, exitAngle, arrowType).getAssets()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -81,12 +78,9 @@ public class Marker3D extends Group {
|
||||
|
||||
private void showArrow(List<Group> arrowList, int arrowListIndex) {
|
||||
if (arrowListIndex < arrowList.size()) {
|
||||
if (arrowListIndex == 1) {;
|
||||
}
|
||||
Platform.runLater(() -> {
|
||||
this.getChildren().remove(1);
|
||||
this.getChildren().add(arrowList.get(arrowListIndex));
|
||||
});
|
||||
Platform.runLater(() ->
|
||||
this.getChildren().setAll(mark.getAssets(), arrowList.get(arrowListIndex))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +88,6 @@ public class Marker3D extends Group {
|
||||
* Hides all arrows.
|
||||
*/
|
||||
public void hideAllArrows() {
|
||||
Platform.runLater(() -> this.getChildren().setAll(mark, new Group()));
|
||||
Platform.runLater(() -> this.getChildren().setAll(mark.getAssets()));
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,10 @@ import javafx.scene.Group;
|
||||
*/
|
||||
public class Model {
|
||||
|
||||
AnimationTimer animationTimer;
|
||||
Group assets;
|
||||
protected AnimationTimer animationTimer;
|
||||
protected Group assets;
|
||||
|
||||
Model (Group assets, AnimationTimer animation) {
|
||||
public Model (Group assets, AnimationTimer animation) {
|
||||
this.assets = assets;
|
||||
this.animationTimer = animation;
|
||||
if (animation != null) {
|
||||
@@ -25,7 +25,7 @@ public class Model {
|
||||
}
|
||||
}
|
||||
|
||||
public void setAnimation(AnimationTimer animation) {
|
||||
void setAnimation(AnimationTimer animation) {
|
||||
animationTimer = animation;
|
||||
if (animation != null) {
|
||||
animation.start();
|
||||
|
||||
@@ -9,6 +9,7 @@ import javafx.scene.CacheHint;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.PhongMaterial;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.scene.shape.MeshView;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Scale;
|
||||
@@ -78,7 +79,7 @@ public class ModelFactory {
|
||||
Group boatAssets = getUnmodifiedBoatModel(boatType, primaryColour);
|
||||
boatAssets.getTransforms().setAll(
|
||||
new Rotate(-90, new Point3D(0,0,1)),
|
||||
new Scale(0.06, 0.06, 0.06)
|
||||
new Scale(0.3, 0.3, 0.3)
|
||||
);
|
||||
return new BoatModel(boatAssets, null, boatType);
|
||||
}
|
||||
@@ -137,6 +138,10 @@ public class ModelFactory {
|
||||
return makeTrail(assets);
|
||||
case PLAYER_IDENTIFIER:
|
||||
return makeIdentifierIcon(assets);
|
||||
case START_ARROW:
|
||||
case FINISH_ARROW:
|
||||
case PLAIN_ARROW:
|
||||
makeArrow(assets);
|
||||
default:
|
||||
return new Model(new Group(assets), null);
|
||||
}
|
||||
@@ -174,23 +179,17 @@ public class ModelFactory {
|
||||
}
|
||||
|
||||
private static Model makeOcean(Group group) {
|
||||
// group.setScaleY(Double.MAX_VALUE);
|
||||
// group.setScaleX(Double.MAX_VALUE);
|
||||
group.getTransforms().addAll(
|
||||
new Rotate(90, new Point3D(1, 0, 0)),
|
||||
new Scale(10,4,10)
|
||||
Circle ocean = new Circle(
|
||||
0,0,250, Color.SKYBLUE
|
||||
);
|
||||
// group.getChildren().add(new AmbientLight());
|
||||
// Circle ocean = new Circle(0,0,500, Color.SKYBLUE);
|
||||
// ocean.setStroke(Color.TRANSPARENT);
|
||||
// group.getChildren().add(ocean);
|
||||
ocean.setStroke(Color.TRANSPARENT);
|
||||
group.getChildren().add(ocean);
|
||||
return new Model(new Group(group), null);
|
||||
}
|
||||
|
||||
private static Model makeBarrier(Group assets) {
|
||||
assets.getTransforms().addAll(
|
||||
new Rotate(90, new Point3D(1,0,0)),
|
||||
new Scale(1.5,1.5,1.5)
|
||||
new Rotate(90, new Point3D(1,0,0))
|
||||
);
|
||||
return new Model(new Group(assets), null);
|
||||
}
|
||||
@@ -213,7 +212,8 @@ public class ModelFactory {
|
||||
|
||||
private static Model makeTrail(Group trailPiece) {
|
||||
trailPiece.getTransforms().addAll(
|
||||
new Rotate(90, new Point3D(0,0,1))
|
||||
new Rotate(-90, new Point3D(0,0,1)),
|
||||
new Rotate(90, new Point3D(1,0,0))
|
||||
);
|
||||
return new Model(new Group(trailPiece), null);
|
||||
}
|
||||
@@ -225,4 +225,12 @@ public class ModelFactory {
|
||||
);
|
||||
return new Model(assets, null);
|
||||
}
|
||||
|
||||
private static Model makeArrow(Group assets) {
|
||||
assets.getTransforms().addAll(
|
||||
new Rotate(90, new Point3D(1,0,0)),
|
||||
new Scale(0.1, 0.1, 0.1)
|
||||
);
|
||||
return new Model(new Group(assets), null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ public enum ModelType {
|
||||
START_MARKER ("start_marker.dae"),
|
||||
PLAIN_MARKER ("plain_marker.dae"),
|
||||
MARK_AREA ("mark_area.dae"),
|
||||
OCEAN ("ocean.dae"),
|
||||
OCEAN (null),
|
||||
BORDER_PYLON ("barrier_pole.dae"),
|
||||
BORDER_BARRIER ("barrier_segment.dae"),
|
||||
FINISH_LINE ("finish_line.dae"),
|
||||
@@ -19,12 +19,14 @@ public enum ModelType {
|
||||
GATE_LINE ("gate_line.dae"),
|
||||
WAKE ("wake.dae"),
|
||||
TRAIL_SEGMENT ("trail_segment.dae"),
|
||||
PLAYER_IDENTIFIER ("player_identifier.dae");
|
||||
PLAYER_IDENTIFIER ("player_identifier.dae"),
|
||||
PLAIN_ARROW ("arrow.dae"),
|
||||
START_ARROW ("finish_arrow.dae"),
|
||||
FINISH_ARROW ("start_arrow.dae");
|
||||
|
||||
final String filename;
|
||||
|
||||
ModelType(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user