From 2936debad84dbaa41243d4ab9aaa1c3084ffb092 Mon Sep 17 00:00:00 2001 From: jez04 <david.jezek@post.cz> Date: Tue, 15 Apr 2025 23:39:37 +0200 Subject: [PATCH] feat: assignment lab 09 --- pom.xml | 4 +- src/main/java/lab/game/Level.java | 77 ++++++++++++++------- src/main/java/lab/game/Monster.java | 36 +++++----- src/main/java/lab/game/MyDimension.java | 16 +++++ src/main/java/lab/game/MyPoint.java | 58 ++++++++++++++++ src/main/java/lab/game/NicerObstacle.java | 17 +++-- src/main/java/lab/game/Obstacle.java | 12 ++-- src/main/java/lab/game/Player.java | 28 ++++---- src/main/java/lab/game/WorldEntity.java | 19 +++-- src/main/java/lab/gui/App.java | 28 +++----- src/main/java/lab/gui/GameController.java | 7 +- src/main/java/lab/storage/JpaConnector.java | 8 +-- 12 files changed, 204 insertions(+), 106 deletions(-) create mode 100644 src/main/java/lab/game/MyDimension.java create mode 100644 src/main/java/lab/game/MyPoint.java diff --git a/pom.xml b/pom.xml index 1d13de2..8ed4160 100644 --- a/pom.xml +++ b/pom.xml @@ -3,9 +3,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cz.vsb.fei.java2</groupId> - <artifactId>java2-lab05-v2</artifactId> + <artifactId>java2-lab09-v2</artifactId> <version>0.0.1-SNAPHOST</version> - <name>java2-lab05-v2</name> + <name>java2-lab09-v2</name> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/src/main/java/lab/game/Level.java b/src/main/java/lab/game/Level.java index 097818f..234c52e 100644 --- a/src/main/java/lab/game/Level.java +++ b/src/main/java/lab/game/Level.java @@ -6,8 +6,6 @@ import java.util.Comparator; import java.util.LinkedList; import java.util.List; -import javafx.geometry.Dimension2D; -import javafx.geometry.Point2D; import javafx.scene.canvas.GraphicsContext; import javafx.scene.paint.Color; import lab.Config; @@ -16,6 +14,8 @@ import lombok.extern.log4j.Log4j2; @Log4j2 public class Level { + private boolean viewMode; + private double width; private double height; private List<DrawableSimulable> entities; @@ -24,29 +24,49 @@ public class Level { private Player player; private List<MonsterDeadLog> deadLogs = new LinkedList<>(); - public Level(double width, double height, int monsterCount) { + public Level(double width, double height, int monsterCount, boolean viewMode) { this.width = width; this.height = height; - player = new Player(this, new Point2D(20, 250), new Point2D(100, -20)); + this.viewMode = viewMode; + player = new Player(this, new MyPoint(20, 250), new MyPoint(100, -20)); entities = new ArrayList<>(); - entities.add(new NicerObstacle(this, new Point2D(20, 150))); - entities.add(new Obstacle(this, new Point2D(300, 200), new Dimension2D(80, 40))); + entities.add(new NicerObstacle(this, new MyPoint(20, 150))); + entities.add(new Obstacle(this, new MyPoint(300, 200), new MyDimension(80, 40))); entities.add(new Obstacle(this)); entities.add(player); - for (int i = 0; i < monsterCount*Config.getInstance().getMonsterMultiplier(); i++) { - Monster monster = new Monster(this); + for (int i = 0; i < monsterCount * Config.getInstance().getMonsterMultiplier(); i++) { + Monster monster = new Monster(this); monster.addDeadListener(m -> deadLogs.add(new MonsterDeadLog(LocalDateTime.now(), m.getPosition()))); entities.add(monster); } + initServerOrViewMode(); + } + + public void initServerOrViewMode() { + if (!viewMode) { + startServer(); + } else { + connectToServer(); + } + } + + public void startServer() { + // TODO: + } + + public void connectToServer() { + // TODO: + } + + record MonsterDeadLog(LocalDateTime time, MyPoint position) { } - - record MonsterDeadLog(LocalDateTime time, Point2D position) {} public void printDeadLog() { for (MonsterDeadLog monsterDeadLog : deadLogs) { log.info(monsterDeadLog); } } + public void draw(GraphicsContext gc) { gc.setFill(Color.WHITE); gc.clearRect(0, 0, width, height); @@ -56,32 +76,31 @@ public class Level { } public void simulate(double delay) { + if (viewMode) { + return; + } for (DrawableSimulable entity : entities) { entity.simulate(delay); } + detectCollisions(); + entities.removeAll(entitiesToRemove); + entities.addAll(entitiesToAdd); + entitiesToAdd.clear(); + entitiesToRemove.clear(); + entities.sort(Comparator.comparing(DrawableSimulable::getZIndex)); + } + + private void detectCollisions() { for (int i = 0; i < entities.size(); i++) { if (entities.get(i) instanceof Collisionable c1) { for (int j = i + 1; j < entities.size(); j++) { - if (entities.get(j) instanceof Collisionable c2) { - if (c1.intersect(c2.getBoundingBox())) { - c1.hitBy(c2); - c2.hitBy(c1); - } + if (entities.get(j) instanceof Collisionable c2 && c1.intersect(c2.getBoundingBox())) { + c1.hitBy(c2); + c2.hitBy(c1); } } } } - entities.removeAll(entitiesToRemove); - entities.addAll(entitiesToAdd); - entitiesToAdd.clear(); - entitiesToRemove.clear(); - entities.sort(Comparator.comparing(DrawableSimulable::getZIndex)); -// entities.sort(new Comparator<DrawableSimulable>() { -// @Override -// public int compare(DrawableSimulable o1, DrawableSimulable o2) { -// return Integer.compare(o1.getZIndex(), o2.getZIndex()); -// } -// }); } public double getWidth() { @@ -97,10 +116,16 @@ public class Level { } public void add(DrawableSimulable entity) { + if (viewMode) { + return; + } entitiesToAdd.add(entity); } public void remove(DrawableSimulable entity) { + if (viewMode) { + return; + } entitiesToRemove.add(entity); } diff --git a/src/main/java/lab/game/Monster.java b/src/main/java/lab/game/Monster.java index d8955d6..d9c2788 100644 --- a/src/main/java/lab/game/Monster.java +++ b/src/main/java/lab/game/Monster.java @@ -7,8 +7,6 @@ import java.util.Random; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import javafx.geometry.Dimension2D; -import javafx.geometry.Point2D; import javafx.geometry.Rectangle2D; import javafx.scene.canvas.GraphicsContext; import javafx.scene.image.Image; @@ -20,26 +18,30 @@ public class Monster extends WorldEntity implements Collisionable { private static final Random RANDOM = new Random(); - private Image image; - private Point2D speed; + private static Image image; + private MyPoint speed; private List<DeadListener> deadListeners = new ArrayList<>(); public Monster(Level level) { - super(level, new Point2D(0, 0), 100); - image = new Image(getClass().getResourceAsStream("red-monster.gif")); - position = new Point2D(level.getWidth() * Config.getInstance().getMonsterMinXPopsition() - + RANDOM.nextDouble(level.getWidth() - image.getWidth()), RANDOM.nextDouble(level.getHeight())); - speed = new Point2D(0, RANDOM.nextDouble(Config.getInstance().getMonsterMinSpeed(), + super(level, new MyPoint(0, 0), 100); + position = new MyPoint(level.getWidth() * Config.getInstance().getMonsterMinXPopsition() + + RANDOM.nextDouble(level.getWidth() - getImage().getWidth()), RANDOM.nextDouble(level.getHeight())); + speed = new MyPoint(0, RANDOM.nextDouble(Config.getInstance().getMonsterMinSpeed(), Config.getInstance().getMonsterMaxSpeed())); } - public Monster(Level level, Point2D position) { + private static Image getImage() { + if(image == null) { + image = new Image(Monster.class.getResourceAsStream("red-monster.gif")); + } + return image; + } + public Monster(Level level, MyPoint position) { super(level, position); - image = new Image(getClass().getResourceAsStream("spike.gif")); } public void drawInternal(GraphicsContext gc) { - gc.drawImage(image, position.getX(), position.getY()); + gc.drawImage(getImage(), position.getX(), position.getY()); } public void changeDirection() { @@ -49,15 +51,15 @@ public class Monster extends WorldEntity implements Collisionable { public void simulate(double delay) { position = position.add(speed.multiply(delay / 1_000_000_000)); - position = new Point2D(position.getX(), position.getY() % level.getHeight()); - if (position.getY() + image.getHeight() < 0) { - position = new Point2D(position.getX(), level.getHeight()); + position = new MyPoint(position.getX(), position.getY() % level.getHeight()); + if (position.getY() + getImage().getHeight() < 0) { + position = new MyPoint(position.getX(), level.getHeight()); } } @Override public Rectangle2D getBoundingBox() { - return new Rectangle2D(position.getX(), position.getY(), image.getWidth(), image.getHeight()); + return new Rectangle2D(position.getX(), position.getY(), getImage().getWidth(), getImage().getHeight()); } @Override @@ -70,7 +72,7 @@ public class Monster extends WorldEntity implements Collisionable { log.trace("Moster hitted by {}.", another); if (another instanceof Player) { level.remove(this); - level.add(new Obstacle(level, getPosition(), new Dimension2D(Config.getInstance().getObstacleWidth(), + level.add(new Obstacle(level, getPosition(), new MyDimension(Config.getInstance().getObstacleWidth(), Config.getInstance().getObstacleHeight()))); fireMonsterDead(); } diff --git a/src/main/java/lab/game/MyDimension.java b/src/main/java/lab/game/MyDimension.java new file mode 100644 index 0000000..d76dfb2 --- /dev/null +++ b/src/main/java/lab/game/MyDimension.java @@ -0,0 +1,16 @@ +package lab.game; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class MyDimension { + + private double width; + + private double height; + +} diff --git a/src/main/java/lab/game/MyPoint.java b/src/main/java/lab/game/MyPoint.java new file mode 100644 index 0000000..721a676 --- /dev/null +++ b/src/main/java/lab/game/MyPoint.java @@ -0,0 +1,58 @@ +package lab.game; + +public class MyPoint { + + public double x; + public double y; + + public MyPoint(double x, double y) { + super(); + this.x = x; + this.y = y; + } + + public double getX() { + return x; + } + + public void setX(double x) { + this.x = x; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + public MyPoint multiply(double multiplier) { + return new MyPoint(x * multiplier, y * multiplier); + } + + public MyPoint add(MyPoint other) { + return new MyPoint(x + other.x, y + other.y); + } + public MyPoint add(double dx, double dy) { + return new MyPoint(x + dx, y + dy); + } + + public double angle(double x, double y) { + final double ax = getX(); + final double ay = getY(); + + final double delta = (ax * x + ay * y) / Math.sqrt( + (ax * ax + ay * ay) * (x * x + y * y)); + + if (delta > 1.0) { + return 0.0; + } + if (delta < -1.0) { + return 180.0; + } + + return Math.toDegrees(Math.acos(delta)); + } + +} diff --git a/src/main/java/lab/game/NicerObstacle.java b/src/main/java/lab/game/NicerObstacle.java index 02c4299..140412c 100644 --- a/src/main/java/lab/game/NicerObstacle.java +++ b/src/main/java/lab/game/NicerObstacle.java @@ -1,24 +1,29 @@ package lab.game; -import javafx.geometry.Point2D; import javafx.scene.canvas.GraphicsContext; import javafx.scene.image.Image; public class NicerObstacle extends WorldEntity { - private Image image; + private static Image image; - public NicerObstacle(Level level, Point2D position) { + public NicerObstacle(Level level, MyPoint position) { super(level, position); - image = new Image(getClass().getResourceAsStream("spike.gif")); + } + + private static Image getImage() { + if (image == null) { + image = new Image(NicerObstacle.class.getResourceAsStream("spike.gif")); + } + return image; } public void drawInternal(GraphicsContext gc) { - gc.drawImage(image, position.getX(), position.getY()); + gc.drawImage(getImage(), position.getX(), position.getY()); } public void simulate(double delay) { - + /* nothing to do */ } } diff --git a/src/main/java/lab/game/Obstacle.java b/src/main/java/lab/game/Obstacle.java index c623237..4bc5a98 100644 --- a/src/main/java/lab/game/Obstacle.java +++ b/src/main/java/lab/game/Obstacle.java @@ -1,21 +1,19 @@ package lab.game; -import javafx.geometry.Dimension2D; -import javafx.geometry.Point2D; import javafx.scene.canvas.GraphicsContext; import javafx.scene.paint.Color; import lab.Config; public class Obstacle extends WorldEntity { - private Dimension2D size; + private MyDimension size; public Obstacle(Level level) { - this(level, new Point2D(200, 100), - new Dimension2D(Config.getInstance().getObstacleWidth(), Config.getInstance().getObstacleHeight())); + this(level, new MyPoint(200, 100), + new MyDimension(Config.getInstance().getObstacleWidth(), Config.getInstance().getObstacleHeight())); } - public Obstacle(Level level, Point2D position, Dimension2D size) { + public Obstacle(Level level, MyPoint position, MyDimension size) { super(level, position); this.size = size; } @@ -29,7 +27,7 @@ public class Obstacle extends WorldEntity { } public void simulate(double delay) { - + /* nothing to do */ } } diff --git a/src/main/java/lab/game/Player.java b/src/main/java/lab/game/Player.java index b37c79a..1c84de4 100644 --- a/src/main/java/lab/game/Player.java +++ b/src/main/java/lab/game/Player.java @@ -2,32 +2,34 @@ package lab.game; import java.util.Random; -import javafx.geometry.Point2D; import javafx.geometry.Rectangle2D; import javafx.scene.canvas.GraphicsContext; import javafx.scene.paint.Color; import javafx.scene.transform.Affine; import javafx.scene.transform.Rotate; +import javafx.scene.transform.Transform; import lab.Config; public class Player extends WorldEntity implements Collisionable { + private static final Random RANDOM = new Random(); - private Point2D speed; + + private MyPoint speed; private double speedSize = Config.getInstance().getPlayerStartSpeed(); private double angle; - public Player(Level level, Point2D position, Point2D speed) { + public Player(Level level, MyPoint position, MyPoint speed) { super(level, position, 50); this.speed = speed; } public void drawInternal(GraphicsContext gc) { - Point2D center = position.add(10, 25); - double angle = speed.angle(1, 0); + MyPoint center = position.add(10, 25); + double angleToAxis = speed.angle(1, 0); if (speed.getY() < 0) { - angle = -angle; + angleToAxis = -angleToAxis; } - Rotate rotateMatrix = Affine.rotate(angle, center.getX(), center.getY()); + Rotate rotateMatrix = Transform.rotate(angleToAxis, center.getX(), center.getY()); gc.setTransform(new Affine(rotateMatrix)); gc.setFill(Color.AQUA); gc.setStroke(Color.GREEN); @@ -39,7 +41,6 @@ public class Player extends WorldEntity implements Collisionable { public void simulate(double delay) { position = position.add(speed.multiply(delay / 1_000_000_000)); -// speed = speed.multiply(0.9994); } @Override @@ -55,7 +56,7 @@ public class Player extends WorldEntity implements Collisionable { @Override public void hitBy(Collisionable another) { if (another instanceof Monster) { - position = new Point2D(RANDOM.nextDouble(0, level.getWidth() * 0.4), + position = new MyPoint(RANDOM.nextDouble(0, level.getWidth() * 0.4), RANDOM.nextDouble(level.getHeight() * 0.5, level.getHeight())); } @@ -68,18 +69,17 @@ public class Player extends WorldEntity implements Collisionable { } private void updateSpeed() { - speed = new Point2D(Math.cos(angle) * speedSize, Math.sin(angle) * speedSize); + speed = new MyPoint(Math.cos(angle) * speedSize, Math.sin(angle) * speedSize); } public void setAngle(double angle) { this.angle = Math.toRadians(angle); updateSpeed(); } - + public void spawn() { - position = new Point2D( - RANDOM.nextDouble(0, level.getWidth()*0.5), - RANDOM.nextDouble(level.getHeight()*0.5, level.getHeight()*0.9)); + position = new MyPoint(RANDOM.nextDouble(0, level.getWidth() * 0.5), + RANDOM.nextDouble(level.getHeight() * 0.5, level.getHeight() * 0.9)); } diff --git a/src/main/java/lab/game/WorldEntity.java b/src/main/java/lab/game/WorldEntity.java index 20d26ad..965ef45 100644 --- a/src/main/java/lab/game/WorldEntity.java +++ b/src/main/java/lab/game/WorldEntity.java @@ -1,35 +1,35 @@ package lab.game; -import javafx.geometry.Point2D; import javafx.scene.canvas.GraphicsContext; -public abstract class WorldEntity implements DrawableSimulable{ +public abstract class WorldEntity implements DrawableSimulable { protected final Level level; - protected Point2D position; + protected MyPoint position; private int zIndex; - public WorldEntity(Level level, Point2D position) { + public WorldEntity(Level level, MyPoint position) { this.level = level; this.position = position; - zIndex = 0; + zIndex = 0; } - public WorldEntity(Level level, Point2D position, int zIndex) { + public WorldEntity(Level level, MyPoint position, int zIndex) { this.level = level; this.position = position; - this.zIndex = zIndex; + this.zIndex = zIndex; } + @Override public final void draw(GraphicsContext gc) { gc.save(); drawInternal(gc); gc.restore(); } - + public abstract void drawInternal(GraphicsContext gc); - public Point2D getPosition() { + public MyPoint getPosition() { return position; } @@ -37,5 +37,4 @@ public abstract class WorldEntity implements DrawableSimulable{ return zIndex; } - } diff --git a/src/main/java/lab/gui/App.java b/src/main/java/lab/gui/App.java index ef7d8e9..bb20828 100644 --- a/src/main/java/lab/gui/App.java +++ b/src/main/java/lab/gui/App.java @@ -2,18 +2,18 @@ package lab.gui; import java.io.IOException; import java.net.URL; -import java.sql.SQLException; - -import org.h2.tools.Server; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonType; import javafx.stage.Stage; import javafx.stage.WindowEvent; import lab.Config; -import lab.storage.JpaConnector; +import lab.storage.FileStorage; import lombok.extern.log4j.Log4j2; /** @@ -28,31 +28,22 @@ public class App extends Application { private GameController gameController; + private boolean viewMode; + private Stage primaryStage; public static void main(String[] args) { log.info("Application lauched"); - Config.configure(Config.builder().scoreStorageInterface(new JpaConnector()).build()); - - startH2WebServerToInspectDb(); + Config.configure(Config.builder().scoreStorageInterface(new FileStorage()).build()); launch(args); } - private static void startH2WebServerToInspectDb() { - //Start HTTP server for access H2 DB for look inside - try { - Server server = Server.createWebServer(); - log.info(server.getURL()); - server.start(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - @Override public void start(Stage primaryStage) { try { + Alert alert = new Alert(AlertType.CONFIRMATION, "View Mode?", ButtonType.YES, ButtonType.NO); + alert.showAndWait().ifPresent(button -> viewMode = ButtonType.YES.equals(button)); this.primaryStage = primaryStage; switchToMenu(); primaryStage.setTitle("Java 2 - 2th laboratory"); @@ -69,6 +60,7 @@ public class App extends Application { FXMLLoader gameLoader = new FXMLLoader(getClass().getResource("/lab/gui/gameWindow.fxml")); Parent root = gameLoader.load(); gameController = gameLoader.getController(); + gameController.setViewMode(viewMode); Scene scene = new Scene(root); URL cssUrl = getClass().getResource("application.css"); scene.getStylesheets().add(cssUrl.toString()); diff --git a/src/main/java/lab/gui/GameController.java b/src/main/java/lab/gui/GameController.java index 85d85ec..2d47439 100644 --- a/src/main/java/lab/gui/GameController.java +++ b/src/main/java/lab/gui/GameController.java @@ -19,6 +19,7 @@ public class GameController { private AnimationTimer timer; private Level level; + private boolean viewMode; @FXML private Slider angle; @@ -65,9 +66,13 @@ public class GameController { log.info("Screeen initialized."); } + public void setViewMode(boolean viewMode) { + this.viewMode = viewMode; + } + public void startGame(String name, int numberOfMonsters) { playerName.setText(name); - level = new Level(canvas.getWidth(), canvas.getHeight(), numberOfMonsters); + level = new Level(canvas.getWidth(), canvas.getHeight(), numberOfMonsters, viewMode); timer = new DrawingThread(canvas, level); timer.start(); diff --git a/src/main/java/lab/storage/JpaConnector.java b/src/main/java/lab/storage/JpaConnector.java index 818aba9..47bdc1c 100644 --- a/src/main/java/lab/storage/JpaConnector.java +++ b/src/main/java/lab/storage/JpaConnector.java @@ -1,6 +1,5 @@ package lab.storage; -import java.util.Collections; import java.util.List; import java.util.function.Consumer; @@ -44,7 +43,7 @@ public class JpaConnector implements ScoreStorageInterface { } else { result = entityManager.merge(score); } - entityManager.getTransaction().commit();; + entityManager.getTransaction().commit(); return result; } @@ -54,7 +53,7 @@ public class JpaConnector implements ScoreStorageInterface { for (Score score : scores) { entityManager.remove(score); } - entityManager.getTransaction().commit();; + entityManager.getTransaction().commit(); } @Override @@ -64,7 +63,6 @@ public class JpaConnector implements ScoreStorageInterface { } public Object getEntityManager() { - //return entity manager. Type Object is there because of compilation of empty task assignment return entityManager; } @@ -76,7 +74,7 @@ public class JpaConnector implements ScoreStorageInterface { entityManager.getTransaction().begin(); Score score = entityManager.find(Score.class, id); motificator.accept(score); - entityManager.getTransaction().commit();; + entityManager.getTransaction().commit(); } -- GitLab