From 2508029d87a19ac8f67426d31e606885db259ee7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Ko=C5=BEusznik?= <jan@kozusznik.cz>
Date: Wed, 6 Oct 2021 10:42:53 +0200
Subject: [PATCH] lab04-02-solution
---
src/main/java/lab/BulletAnimated.java | 39 +++++++++++-----------
src/main/java/lab/Cannon.java | 26 ++++++---------
src/main/java/lab/Collisionable.java | 15 +++++++++
src/main/java/lab/Dragon.java | 37 +++++++++++----------
src/main/java/lab/DrawableSimulable.java | 8 +++++
src/main/java/lab/World.java | 38 +++++++++++-----------
src/main/java/lab/WorldEntity.java | 41 ++++++++++++++++++++++++
7 files changed, 132 insertions(+), 72 deletions(-)
create mode 100644 src/main/java/lab/Collisionable.java
create mode 100644 src/main/java/lab/DrawableSimulable.java
create mode 100644 src/main/java/lab/WorldEntity.java
diff --git a/src/main/java/lab/BulletAnimated.java b/src/main/java/lab/BulletAnimated.java
index 294ad22..1546845 100644
--- a/src/main/java/lab/BulletAnimated.java
+++ b/src/main/java/lab/BulletAnimated.java
@@ -5,9 +5,8 @@ import javafx.geometry.Rectangle2D;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
-public class BulletAnimated {
+public class BulletAnimated extends WorldEntity implements Collisionable{
- private Point2D position;
private Point2D start;
private Point2D speed;
private Point2D initialSpeed;
@@ -22,7 +21,6 @@ public class BulletAnimated {
private double dragCoefficient = 0.47;
private Image image;
- private World world;
private Cannon cannon;
public BulletAnimated(World world, Cannon cannon) {
@@ -30,27 +28,20 @@ public class BulletAnimated {
}
public BulletAnimated(World world, Cannon cannon, Point2D start, Point2D speed, double size) {
+ super(start, world);
this.start = start;
- this.position = this.start;
this.initialSpeed = speed;
this.speed = speed;
this.size = size;
- this.world = world;
this.cannon = cannon;
image = new Image(getClass().getResourceAsStream("fireball-transparent.gif"), size, size,
true, true);
}
- public void draw(GraphicsContext gc) {
- gc.save();
- Point2D canvasPosition = world.getCanvasPoint(position);
- gc.drawImage(image, canvasPosition.getX(), canvasPosition.getY());
- gc.restore();
- }
-
+ @Override
public void simulate(double deltaT) {
double timeStep = deltaT * 1000;
- if (accelerate && start.distance(position) < cannonLength) {
+ if (accelerate && start.distance(getPosition()) < cannonLength) {
double cannonAngle = cannon.getAngle();
speed = speed
.add(new Point2D(Math.cos(cannonAngle) * strenghtOfCannon, Math.sin(cannonAngle) * strenghtOfCannon)
@@ -65,10 +56,10 @@ public class BulletAnimated {
speed = speed.add(acceleration.multiply(timeStep / 1000));
}
if (!hitToGround) {
- position = position.add(speed);
- if (!accelerate && position.getY() <= size / 2) {
+ setPosition(getPosition().add(speed));
+ if (!accelerate && getPosition().getY() <= size / 2) {
hitToGround = true;
- position = new Point2D(position.getX(), size / 2);
+ setPosition(new Point2D(getPosition().getX(), size / 2));
}
} else {
reload();
@@ -78,7 +69,12 @@ public class BulletAnimated {
}
public Rectangle2D getBoundingBox() {
- return new Rectangle2D(position.getX(), position.getY(), size, size);
+ return new Rectangle2D(getPosition().getX(), getPosition().getY(), size, size);
+ }
+
+ @Override
+ public void hitBy(Collisionable other) {
+ reload();
}
public boolean overlaps(Dragon dragon) {
@@ -86,10 +82,15 @@ public class BulletAnimated {
}
public void reload() {
- position = start;
+ setPosition(start);
speed = initialSpeed;
hitToGround = false;
accelerate = true;
}
-
+
+ @Override
+ protected void drawInternal(GraphicsContext gc) {
+ Point2D canvasPosition = getWorld().getCanvasPoint(getPosition());
+ gc.drawImage(image, canvasPosition.getX(), canvasPosition.getY());
+ }
}
diff --git a/src/main/java/lab/Cannon.java b/src/main/java/lab/Cannon.java
index b46745d..296ce0e 100644
--- a/src/main/java/lab/Cannon.java
+++ b/src/main/java/lab/Cannon.java
@@ -5,21 +5,15 @@ import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.transform.Affine;
-public class Cannon {
+public class Cannon extends WorldEntity{
private int direction=-1;
private double angle = 0;
- private Point2D position;
private Point2D size;
- private World world;
-
-
public Cannon(World world, Point2D position, Point2D size) {
- super();
- this.world = world;
- this.position = position;
+ super(position, world);
this.size = size;
}
@@ -30,9 +24,14 @@ public class Cannon {
}
}
- public void draw(GraphicsContext gc) {
- gc.save();
- Point2D worldPosition = world.getCanvasPoint(position);
+
+ public double getAngle() {
+ return (angle * -1) / 180 * Math.PI;
+ }
+
+ @Override
+ protected void drawInternal(GraphicsContext gc) {
+ Point2D worldPosition = getWorld().getCanvasPoint(getPosition());
gc.setFill(Color.BROWN);
gc.fillRect(worldPosition.getX()-10, worldPosition.getY()+size.getY(), size.getX()+20, size.getY()/2);
gc.fillOval(worldPosition.getX()-20, worldPosition.getY()+size.getY()/2, 40, 40);
@@ -40,10 +39,5 @@ public class Cannon {
gc.setTransform(new Affine(Affine.rotate(angle, worldPosition.getX(), worldPosition.getY()+size.getY()/2)));
gc.setFill(Color.BLACK);
gc.fillRect(worldPosition.getX(), worldPosition.getY(), size.getX(), size.getY());
- gc.restore();
- }
-
- public double getAngle() {
- return (angle * -1) / 180 * Math.PI;
}
}
diff --git a/src/main/java/lab/Collisionable.java b/src/main/java/lab/Collisionable.java
new file mode 100644
index 0000000..e95da10
--- /dev/null
+++ b/src/main/java/lab/Collisionable.java
@@ -0,0 +1,15 @@
+package lab;
+
+import javafx.geometry.Rectangle2D;
+
+public interface Collisionable {
+
+ void hitBy(Collisionable other);
+
+ default boolean intersects(Collisionable other) {
+ return getBoundingBox().intersects(other.getBoundingBox());
+ }
+
+ Rectangle2D getBoundingBox();
+
+}
diff --git a/src/main/java/lab/Dragon.java b/src/main/java/lab/Dragon.java
index 216628a..1945c37 100644
--- a/src/main/java/lab/Dragon.java
+++ b/src/main/java/lab/Dragon.java
@@ -4,49 +4,48 @@ import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.scene.canvas.GraphicsContext;
-public class Dragon {
+public class Dragon extends WorldEntity implements Collisionable {
- private Point2D position;
private Point2D speed;
- private final World world;
private final double size = 45;
public Dragon(World world, Point2D position, Point2D speed) {
- super();
- this.world = world;
- this.position = position;
+ super(position, world);
this.speed = speed;
}
- public void draw(GraphicsContext gc) {
- Point2D canvasPosition = world.getCanvasPoint(position);
+ protected void drawInternal(GraphicsContext gc) {
+ Point2D canvasPosition = getWorld().getCanvasPoint(getPosition());
gc.drawImage(Constants.DRAGON_IMAGE, canvasPosition.getX(), canvasPosition.getY(), size, size);
}
public void simulate(double timeDelta) {
double timeDeltaS = timeDelta;
- double newX = (position.getX() + speed.getX() * timeDeltaS + world.getWidth()) % world.getWidth();
- double newY = (position.getY() + speed.getY() * timeDeltaS + world.getHeight()) % world.getHeight();
- position = new Point2D(newX, newY);
+ double newX = (getPosition().getX() + speed.getX() * timeDeltaS + getWorld().getWidth()) % getWorld().getWidth();
+ double newY = (getPosition().getY() + speed.getY() * timeDeltaS + getWorld().getHeight()) % getWorld().getHeight();
+ setPosition(new Point2D(newX, newY));
}
-
+ @Override
public Rectangle2D getBoundingBox() {
- return new Rectangle2D(position.getX(), position.getY(), size, size);
- }
-
-
- public void hit() {
- speed = speed.multiply(-1.);
+ return new Rectangle2D(getPosition().getX(), getPosition().getY(), size, size);
}
-
+ @Override
+ public void hitBy(Collisionable other) {
+ if (!(other instanceof Dragon)) {
+ hit();
+ }
+ }
+ public void hit() {
+ speed = speed.multiply(-1.);
+ }
}
diff --git a/src/main/java/lab/DrawableSimulable.java b/src/main/java/lab/DrawableSimulable.java
new file mode 100644
index 0000000..f0925cd
--- /dev/null
+++ b/src/main/java/lab/DrawableSimulable.java
@@ -0,0 +1,8 @@
+package lab;
+
+import javafx.scene.canvas.GraphicsContext;
+
+public interface DrawableSimulable {
+ void draw(GraphicsContext gc);
+ void simulate(double deltaT);
+}
diff --git a/src/main/java/lab/World.java b/src/main/java/lab/World.java
index ce631f9..9baa756 100644
--- a/src/main/java/lab/World.java
+++ b/src/main/java/lab/World.java
@@ -7,19 +7,17 @@ import javafx.scene.canvas.GraphicsContext;
public class World {
private double width;
private double height;
- private BulletAnimated bulletAnimatted;
- private Cannon cannon;
- private Dragon[] dragons;
+ private DrawableSimulable[] entities;
public World(double width, double height) {
super();
this.width = width;
this.height = height;
- cannon = new Cannon(this, new Point2D(50, 50), new Point2D(100, 20));
- bulletAnimatted = new BulletAnimated(this, cannon, new Point2D(30, 60), new Point2D(0, 0), 40);
- dragons = new Dragon[] { new Dragon(this, new Point2D(50, 200), new Point2D(100, 5)),
+ Cannon cannon = new Cannon(this, new Point2D(50, 50), new Point2D(100, 20));
+ BulletAnimated bullet = new BulletAnimated(this, cannon, new Point2D(30, 60), new Point2D(0, 0), 40);
+ entities = new DrawableSimulable[] {cannon, bullet, new Dragon(this, new Point2D(50, 200), new Point2D(100, 5)),
new Dragon(this, new Point2D(50, 230), new Point2D(60, 5)),
- new Dragon(this, new Point2D(50, 270), new Point2D(-50, 20)) };
+ new Dragon(this, new Point2D(50, 270), new Point2D(-50, 20))};
}
public Point2D getCanvasPoint(Point2D worldPoint) {
@@ -29,22 +27,26 @@ public class World {
public void draw(Canvas canvas) {
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
- cannon.draw(gc);
- bulletAnimatted.draw(gc);
- for(Dragon dragon: dragons) {
- dragon.draw(gc);
+ for(DrawableSimulable entity: entities) {
+ entity.draw(gc);
}
}
public void simulate(double timeDelta) {
- bulletAnimatted.simulate(timeDelta);
- cannon.simulate(timeDelta);
- for(Dragon dragon: dragons) {
- if (bulletAnimatted.overlaps(dragon)) {
- dragon.hit();
- bulletAnimatted.reload();
+ for(DrawableSimulable entity: entities) {
+ entity.simulate(timeDelta);
+ if (entity instanceof Collisionable) {
+ Collisionable col1 = (Collisionable) entity;
+ for (DrawableSimulable entity2: entities) {
+ if (entity2 != entity && entity2 instanceof Collisionable) {
+ Collisionable col2 = (Collisionable) entity2;
+ if (col1.intersects(col2)) {
+ col1.hitBy(col2);
+ col2.hitBy(col1);
+ }
+ }
+ }
}
- dragon.simulate(timeDelta);
}
}
diff --git a/src/main/java/lab/WorldEntity.java b/src/main/java/lab/WorldEntity.java
new file mode 100644
index 0000000..040b621
--- /dev/null
+++ b/src/main/java/lab/WorldEntity.java
@@ -0,0 +1,41 @@
+package lab;
+
+import javafx.geometry.Point2D;
+import javafx.scene.canvas.GraphicsContext;
+
+public abstract class WorldEntity implements DrawableSimulable{
+
+ private Point2D position;
+
+ private final World world;
+
+ public WorldEntity(Point2D position, World world) {
+ this.position = position;
+ this.world = world;
+ }
+
+ @Override
+ public void draw(GraphicsContext gc) {
+ gc.save();
+ drawInternal(gc);
+ gc.restore();
+ }
+
+ protected abstract void drawInternal(GraphicsContext gc);
+
+ protected Point2D getPosition() {
+ return position;
+ }
+
+
+ protected void setPosition(Point2D position) {
+ this.position = position;
+ }
+
+ protected World getWorld() {
+ return world;
+ }
+
+
+
+}
--
GitLab