Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Commits on Source (10)
......@@ -3,24 +3,24 @@
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>vsb-cs-java1</groupId>
<artifactId>lab04</artifactId>
<artifactId>lab06</artifactId>
<version>0.0.1-SNAPHOST</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
<version>17.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11</version>
<version>17.0.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
......
package lab;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
......@@ -17,17 +17,16 @@ public class App extends Application {
launch(args);
}
private Canvas canvas;
private GameController controller;
@Override
public void start(Stage primaryStage) {
try {
//Construct a main window with a canvas.
FXMLLoader loader = new FXMLLoader(this.getClass().getResource("GameView.fxml"));
BorderPane root = loader.load();
Group root = new Group();
canvas = new Canvas(800, 600);
root.getChildren().add(canvas);
Scene scene = new Scene(root);
......@@ -35,7 +34,7 @@ public class App extends Application {
primaryStage.resizableProperty().set(false);
primaryStage.setTitle("Java 1 - 6th laboratory");
primaryStage.show();
controller = new GameController(canvas);
controller = loader.getController();
controller.startGame();
//Exit program when main window is closed
primaryStage.setOnCloseRequest(this::exitProgram);
......
......@@ -7,15 +7,16 @@ import javafx.scene.image.Image;
public class BulletAnimated implements DrawableSimulable, Collisionable{
private static final double STRENGTH_CANNON_COEFICIENT = 1.;
private Point2D position;
private Point2D start;
private Point2D speed;
private Point2D initialSpeed;
private double size;
private double mass = 2;
private double strenghtOfCannon = 2;
private double cannonLength = 100;
private boolean accelerate = true;
private boolean accelerate = false;
private boolean hitToGround = false;
private double crossSectionalArea;
......@@ -24,7 +25,10 @@ public class BulletAnimated implements DrawableSimulable, Collisionable{
private Image image;
private World world;
private Cannon cannon;
private boolean fired;
private HitListener hitListener = new EmptyHitListener();
public BulletAnimated(World world, Cannon cannon) {
this(world, cannon, new Point2D(0, 0), new Point2D(0, 0), 10);
}
......@@ -32,7 +36,7 @@ public class BulletAnimated implements DrawableSimulable, Collisionable{
public BulletAnimated(World world, Cannon cannon, Point2D start, Point2D speed, double size) {
this.start = start;
this.position = this.start;
this.initialSpeed = speed;
this.initialSpeed = Point2D.ZERO;
this.speed = speed;
this.size = size;
this.world = world;
......@@ -49,12 +53,15 @@ public class BulletAnimated implements DrawableSimulable, Collisionable{
}
public void simulate(double deltaT) {
double timeStep = deltaT * 1000;
if (!fired) {
return;
}
if (accelerate && start.distance(position) < cannonLength) {
double cannonAngle = cannon.getAngle();
double strenghtOfCannon = cannon.getStrength() * STRENGTH_CANNON_COEFICIENT;
speed = speed
.add(new Point2D(Math.cos(cannonAngle) * strenghtOfCannon, Math.sin(cannonAngle) * strenghtOfCannon)
.multiply(1 / mass));
.multiply(deltaT / mass));
} else if (!hitToGround) {
accelerate = false;
Point2D airResistanceforce = new Point2D(
......@@ -62,10 +69,10 @@ public class BulletAnimated implements DrawableSimulable, Collisionable{
-1. / 2 * crossSectionalArea * Constants.AIR_DENSITY * 0.47 * Math.pow(speed.getY(), 2));
Point2D acceleration = new Point2D(-airResistanceforce.getX() * mass,
(-Constants.GRAVITATIONAL_ACCELERATION + airResistanceforce.getY()) * mass);
speed = speed.add(acceleration.multiply(timeStep / 1000));
speed = speed.add(acceleration.multiply(deltaT));
}
if (!hitToGround) {
position = position.add(speed);
position = position.add(speed.multiply(deltaT*100));
if (!accelerate && position.getY() <= size / 2) {
hitToGround = true;
position = new Point2D(position.getX(), size / 2);
......@@ -74,11 +81,10 @@ public class BulletAnimated implements DrawableSimulable, Collisionable{
reload();
}
}
public Rectangle2D getBoundingBox() {
return new Rectangle2D(position.getX(), position.getY(), size, size);
return new Rectangle2D(position.getX() - size, position.getY(), size, size);
}
public boolean overlaps(Dragon dragon) {
......@@ -86,14 +92,29 @@ public class BulletAnimated implements DrawableSimulable, Collisionable{
}
public void hitBy(Collisionable other) {
hitListener.hit();
reload();
}
public void reload() {
position = start;
speed = initialSpeed;
speed = Point2D.ZERO;
hitToGround = false;
accelerate = false;
fired = false;
}
public void fire() {
if (fired) {
return;
}
fired = true;
accelerate = true;
speed = initialSpeed;
}
public void setHitListener(HitListener hitListener) {
this.hitListener = hitListener;
}
}
......@@ -7,13 +7,14 @@ import javafx.scene.transform.Affine;
public class Cannon implements DrawableSimulable {
private int direction=-1;
private double angle = 0;
private double strength = 50.;
private Point2D position;
private Point2D size;
private World world;
public Cannon(World world, Point2D position, Point2D size) {
......@@ -24,10 +25,11 @@ public class Cannon implements DrawableSimulable {
}
public void simulate(double timeStep) {
angle = angle + direction*0.8;
/*angle = angle + direction*0.8;
if(angle <=-90 || angle >= 0) {
direction*=-1;
}
{*/
}
public void draw(GraphicsContext gc) {
......@@ -46,4 +48,17 @@ public class Cannon implements DrawableSimulable {
public double getAngle() {
return (angle * -1) / 180 * Math.PI;
}
public void setAngle(double doubleValue) {
angle = doubleValue;
}
public double getStrength() {
return strength;
}
public void setStrength(double doubleValue) {
this.strength = doubleValue;
}
}
......@@ -37,7 +37,7 @@ public class Dragon implements DrawableSimulable, Collisionable{
public Rectangle2D getBoundingBox() {
return new Rectangle2D(position.getX(), position.getY(), size, size);
return new Rectangle2D(position.getX() - size, position.getY(), size, size);
}
......
package lab;
import javafx.animation.AnimationTimer;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
public class DrawingThread extends AnimationTimer {
private final Canvas canvas;
private final GraphicsContext gc;
private final World world;
private long lasttime = -1;
public DrawingThread(Canvas canvas, World world) {
this.canvas = canvas;
this.gc = canvas.getGraphicsContext2D();
this.world = world;
}
/**
* Draws objects into the canvas. Put you code here.
*/
@Override
public void handle(long now) {
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
world.draw(gc);
if (lasttime > 0) {
//time are in nanoseconds and method simulate expects seconds
world.simulate((now - lasttime) / 1e9);
}
lasttime = now;
}
}
package lab;
public class EmptyGameListener implements GameListener {
@Override
public void stateChanged(int shoots, int hits) {
}
@Override
public void gameOver() {
}
}
package lab;
public class EmptyHitListener implements HitListener {
@Override
public void hit() {
}
}
package lab;
package lab;
import javafx.animation.AnimationTimer;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
public class GameController {
private World world;
@FXML
private Slider angleSlider;
@FXML
private Slider strengthSlider;
@FXML
private Canvas canvas;
@FXML
private Label shoots;
@FXML
private Label hits;
private AnimationTimer animationTimer;
public GameController(Canvas canvas) {
this.canvas = canvas;
public GameController() {
}
public void startGame() {
this.world = new World(canvas.getWidth(), canvas.getHeight());
//Draw scene on a separate thread to avoid blocking UI.
animationTimer = new AnimationTimer() {
private Long previous;
@Override
public void handle(long now) {
if (previous == null) {
previous = now;
} else {
drawScene((now - previous)/1e9);
previous = now;
}
}
};
animationTimer = new DrawingThread(canvas, world);
angleSlider.valueProperty().addListener(this::angleChanged);
world.setCannonAngle(angleSlider.getValue());
strengthSlider.valueProperty().addListener(this::strenghtChanged);
world.setCannonStrength(strengthSlider.getValue());
animationTimer.start();
}
......@@ -37,10 +48,19 @@ public class GameController {
animationTimer.stop();
}
private void drawScene(double deltaT) {
world.draw(canvas);
world.simulate(deltaT);
@FXML
private void firePressed() {
world.fire();
}
private void angleChanged(ObservableValue<? extends Number> observable
, Number oldValue, Number newValue) {
world.setCannonAngle(newValue.doubleValue());
}
private void strenghtChanged(ObservableValue<? extends Number> observable
, Number oldValue, Number newValue) {
world.setCannonStrength(newValue.doubleValue());
}
}
package lab;
public interface GameListener {
void stateChanged(int shoots, int hits);
void gameOver();
}
package lab;
public interface HitListener {
void hit();
}
package lab;
import java.util.Random;
import javafx.geometry.Point2D;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
public class World {
private final static int NUMBER_OF_DRAGONS = 2;
private double width;
private double height;
private GameListener gameListener = new EmptyGameListener();
private int hits = 0;
private int shoots = 0;
private DrawableSimulable []entities;
public World(double width, double height) {
......@@ -14,20 +25,26 @@ public class World {
this.width = width;
this.height = height;
Cannon cannon = new Cannon(this, new Point2D(50, 50), new Point2D(100, 20));
entities = new DrawableSimulable[] { cannon,
new BulletAnimated(this, cannon, new Point2D(30, 60), new Point2D(0, 0), 40),
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)) };
entities = new DrawableSimulable[2 + NUMBER_OF_DRAGONS];
entities[0] = cannon;
entities[1] = new BulletAnimated(this, cannon, new Point2D(30, 60), new Point2D(0, 0), 40);
Random rnd = new Random();
for (int i = 2; i < entities.length; i++) {
int x = rnd.nextInt((int) width);
int y = rnd.nextInt((int) height);
int vel_x = (rnd.nextInt(10) - 5) * 10;
int vel_y = (rnd.nextInt(10) - 5) * 10;
entities[i] = new Dragon(this, new Point2D(x, y), new Point2D(vel_x, vel_y));
}
}
public Point2D getCanvasPoint(Point2D worldPoint) {
return new Point2D(worldPoint.getX(), height - worldPoint.getY());
}
public void draw(Canvas canvas) {
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
public void draw(GraphicsContext gc) {
gc.clearRect(0, 0, getWidth(), getHeight());
for(DrawableSimulable entity: entities) {
entity.draw(gc);
}
......@@ -49,16 +66,6 @@ public class World {
}
}
}
/*bulletAnimatted.simulate(timeDelta);
cannon.simulate(timeDelta);
for(Dragon dragon: dragons) {
if (bulletAnimatted.overlaps(dragon)) {
dragon.hit();
bulletAnimatted.reload();
}
dragon.simulate(timeDelta);
}*/
}
public double getWidth() {
......@@ -77,4 +84,39 @@ public class World {
this.height = height;
}
public void setCannonAngle(double doubleValue) {
for (DrawableSimulable d: entities) {
if (d instanceof Cannon) {
Cannon cannon = (Cannon) d;
cannon.setAngle(doubleValue);
}
}
}
public void setCannonStrength(double doubleValue) {
for (DrawableSimulable d: entities) {
if (d instanceof Cannon) {
Cannon cannon = (Cannon) d;
cannon.setStrength(doubleValue);
}
}
}
public void fire() {
for (DrawableSimulable e: entities) {
if (e instanceof BulletAnimated) {
BulletAnimated ba = (BulletAnimated) e;
ba.fire();
shoots++;
gameListener.stateChanged(shoots, hits);
}
}
}
public void setGameListener(GameListener listener) {
this.gameListener = listener;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.Group?>
<?import javafx.scene.canvas.Canvas?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="lab.GameController">
<bottom>
<HBox alignment="CENTER" BorderPane.alignment="CENTER_LEFT">
<children>
<Slider fx:id="angleSlider" max="0.0" min="-90.0" showTickLabels="true" showTickMarks="true" value="-45.0" HBox.hgrow="ALWAYS" />
<Button mnemonicParsing="false" onAction="#firePressed" text="Fire" HBox.hgrow="ALWAYS">
<HBox.margin>
<Insets bottom="11.0" left="14.0" right="11.0" top="12.0" />
</HBox.margin></Button>
<Slider fx:id="strengthSlider" showTickLabels="true" showTickMarks="true" value="50.0" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</bottom>
<center>
<Group BorderPane.alignment="CENTER">
<children>
<GridPane layoutX="20.0" layoutY="20.0" prefHeight="61.0" prefWidth="167.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="79.0" minWidth="10.0" prefWidth="51.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="124.0" minWidth="10.0" prefWidth="116.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="Shoots:" />
<Label fx:id="shoots" text="0" GridPane.columnIndex="1" />
<Label text="Hits:" GridPane.rowIndex="1" />
<Label fx:id="hits" text="0" GridPane.rowIndex="1" GridPane.columnIndex="1" />
</children>
</GridPane>
<Canvas fx:id="canvas" height="400.0" width="600.0" />
</children>
</Group>
</center>
</BorderPane>