Skip to content
Snippets Groups Projects
Commit 71b5c5e4 authored by jez04's avatar jez04
Browse files

feat: :tada: solution lab05

parent 4f79a76c
No related merge requests found
......@@ -22,26 +22,37 @@
<artifactId>javafx-fxml</artifactId>
<version>23</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<!--
https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
<!--
https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params -->
<!--
https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.reflections/reflections -->
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
package lab;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
/**
* Class <b>App</b> - extends class Application and it is an entry point of the program
* @author Java I
* Class <b>App</b> - extends class Application and it is an entry point of the
* program
*
* @author Java I
*/
public class App extends Application {
private GameController gameController;
public static void main(String[] args) {
launch(args);
}
private Canvas canvas;
private AnimationTimer timer;
@Override
public void start(Stage primaryStage) {
try {
//Construct a main window with a canvas.
Group root = new Group();
canvas = new Canvas(800, 400);
root.getChildren().add(canvas);
Scene scene = new Scene(root, 800, 400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
// Construct a main window with a canvas.
FXMLLoader gameLoader = new FXMLLoader(getClass().getResource("/lab/gameWindow.fxml"));
Parent root = gameLoader.load();
GameController gameController = gameLoader.getController();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.resizableProperty().set(false);
primaryStage.setTitle("Java 1 - 1th laboratory");
primaryStage.show();
//Exit program when main window is closed
// Exit program when main window is closed
primaryStage.setOnCloseRequest(this::exitProgram);
timer = new DrawingThread(canvas);
timer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void stop() throws Exception {
timer.stop();
gameController.stop();
super.stop();
}
private void exitProgram(WindowEvent evt) {
System.exit(0);
}
......
......@@ -28,4 +28,8 @@ public class DrawingThread extends AnimationTimer {
lastTime = now;
}
public Level getLevel() {
return level;
}
}
package lab;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.geometry.Point2D;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Slider;
public class GameController {
@FXML
private Slider angle;
private DrawingThread timer;
@FXML
private Canvas canvas;
@FXML
private Slider speed;
@FXML
void spawn(ActionEvent event) {
timer.getLevel().getPlayer().spawn();
}
@FXML
void initialize() {
assert angle != null : "fx:id=\"angle\" was not injected: check your FXML file 'gameWindow.fxml'.";
assert canvas != null : "fx:id=\"canvas\" was not injected: check your FXML file 'gameWindow.fxml'.";
assert speed != null : "fx:id=\"speed\" was not injected: check your FXML file 'gameWindow.fxml'.";
timer = new DrawingThread(canvas);
timer.start();
angle.valueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
timer.getLevel().getPlayer().setAngle(newValue.doubleValue());
}
});
speed.valueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
timer.getLevel().getPlayer().setSpeed(newValue.doubleValue());
}
});
}
public void stop() {
timer.stop();
}
}
......@@ -10,15 +10,17 @@ public class Level {
private double width;
private double height;
private DrawableSimulable[] entities;
private Player player;
public Level(double width, double height) {
this.width = width;
this.height = height;
player = new Player(this, new Point2D(20, 250), new Point2D(100, -20));
entities = new DrawableSimulable[9];
entities[0] = new NicerObstacle(this, new Point2D(20, 150));
entities[1] = new Obstacle(this, new Point2D(300, 200), new Dimension2D(80, 40));
entities[2] = new Obstacle(this);
entities[3] = new Player(this, new Point2D(20, 250), new Point2D(100, -20));
entities[3] = player;
for (int i = 4; i < entities.length; i++) {
entities[i] = new Monster(this);
}
......@@ -57,4 +59,9 @@ public class Level {
public double getHeight() {
return height;
}
public Player getPlayer() {
return player;
}
}
......@@ -12,6 +12,8 @@ import javafx.scene.transform.Rotate;
public class Player extends WorldEntity implements Collisionable {
private static final Random RANDOM = new Random();
private Point2D speed;
private double speedSize;
private double angle;
public Player(Level level, Point2D position, Point2D speed) {
super(level, position);
......@@ -58,4 +60,26 @@ public class Player extends WorldEntity implements Collisionable {
}
public void setSpeed(double speedSize) {
this.speedSize = speedSize;
updateSpeed();
}
private void updateSpeed() {
speed = new Point2D(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));
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.Cursor?>
<?import javafx.scene.canvas.Canvas?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.text.Font?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="459.0" prefWidth="824.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="lab.GameController">
<bottom>
<HBox alignment="TOP_CENTER" prefHeight="66.0" prefWidth="824.0" BorderPane.alignment="CENTER">
<children>
<Slider fx:id="speed" majorTickUnit="15.0" max="200.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" min="50.0" minorTickCount="5" prefHeight="68.0" prefWidth="736.0" showTickLabels="true" showTickMarks="true" HBox.hgrow="ALWAYS" />
<Button maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#spawn" prefHeight="46.0" prefWidth="147.0" style="-fx-background-color: blue;" text="Spawn" textAlignment="CENTER" textFill="WHITE" textOverrun="CLIP">
<font>
<Font name="System Bold" size="22.0" />
</font>
<cursor>
<Cursor fx:constant="CROSSHAIR" />
</cursor>
<opaqueInsets>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</opaqueInsets>
<HBox.margin>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</bottom>
<center>
<Canvas fx:id="canvas" height="385.0" width="749.0" BorderPane.alignment="CENTER">
<BorderPane.margin>
<Insets />
</BorderPane.margin>
</Canvas>
</center>
<left>
<Slider fx:id="angle" blockIncrement="25.0" majorTickUnit="30.0" max="360.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minorTickCount="5" orientation="VERTICAL" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER" />
</left>
</BorderPane>
package jez04.structure.test;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.reflections.Configuration;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
import org.reflections.util.ConfigurationBuilder;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.geometry.Rectangle2D;
import javafx.scene.canvas.GraphicsContext;
class ClassStructureTest {
private static final String drawableSimulableName = "DrawableSimulable";
private static final String collisionableName = "Collisionable";
Set<String> allClasses = getNameOfAllClasses();
@Test
void gameControllerExistenceTest() {
classExist("GameController");
Class<?> c = getClass("GameController");
hasPropertyWithAnnotation(c, ".*", FXML.class);
hasMethodRegexp(c, ".*", void.class, ActionEvent.class);
}
@Test
void gameControllerFxmlTest() {
classExist("GameController");
Class<?> c = getClass("GameController");
hasPropertyWithAnnotation(c, ".*", FXML.class);
}
@Test
void gameControllerActionEventTest() {
classExist("GameController");
Class<?> c = getClass("GameController");
hasMethodRegexp(c, ".*", void.class, ActionEvent.class);
}
@Test
void cannonExistenceTest() {
classExist("Player");
}
@Test
void cannonExistenceSetAngleTest() {
classExist("Player");
Class<?> c = getClass("Player");
hasMethod(c, "setAngle");
}
@Test
void cannonExistenceSetSpeedTest() {
classExist("Player");
Class<?> c = getClass("Player");
hasMethod(c, "setSpeed");
}
private void isInterface(Class<?> c) {
assertTrue(c.isInterface(), c.getName() + " have to be interface.");
}
private void classExist(String name) {
assertTrue(allClasses.stream().anyMatch(c -> c.endsWith(name)), "Interface " + name + " not found");
}
private Class<?> getClass(String name) {
String className = allClasses.stream().filter(c -> c.endsWith(name)).findAny().orElse(null);
if (className == null) {
Assertions.fail("Class " + name + " not found.");
}
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (PrintStream ps = new PrintStream(baos, true)) {
e.printStackTrace(ps);
} catch (Exception e2) {
Assertions.fail(e2.getMessage());
}
String stackTrace = baos.toString();
Assertions.fail("Class " + name + " not found.\n" + stackTrace);
return null;
}
}
private void hasProperty(Class<?> classDef, String propertyNameRegexp, Class<?> type, boolean array) {
List<Field> fields = Arrays.asList(classDef.getDeclaredFields());
assertTrue(fields.stream().anyMatch(f -> {
if (f.getName().matches(propertyNameRegexp)) {
if (array) {
return f.getType().isArray() && f.getType().getComponentType().equals(type);
} else {
return f.getType().equals(type);
}
}
return false;
}), "No field " + propertyNameRegexp + " of type " + type.getName() + " (is array " + array + ") in class "
+ classDef.getName());
}
private void hasPropertyWithAnnotation(Class<?> classDef, String propertyNameRegexp, Class<?> annotation) {
List<Field> fields = Arrays.asList(classDef.getDeclaredFields());
assertTrue(
fields.stream().filter(f -> f.getName().matches(propertyNameRegexp))
.flatMap(f -> Arrays.asList(
f.getAnnotations()).stream()).map(a -> a.annotationType()).anyMatch(a ->
a.equals(annotation)),
"No field " + propertyNameRegexp + " with annotation " + annotation.getName() + " in class "
+ classDef.getName());
}
private void hasMethod(Class<?> interfaceDef, String methodName, Class<?> returnType) {
List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName);
assertTrue(
methods.stream().filter(m -> m.getName().contains(methodName))
.anyMatch(m -> m.getReturnType().equals(returnType)),
"Method " + methodName + " not return " + returnType.getName());
}
private void hasMethod(Class<?> interfaceDef, String methodName, Class<?> returnType, Class<?>... params) {
List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName);
assertTrue(
methods.stream().filter(m -> m.getName().contains(methodName))
.filter(m -> m.getReturnType().equals(returnType))
.anyMatch(m -> Arrays.asList(m.getParameterTypes()).containsAll(Arrays.asList(params))),
"Method " + methodName + " has no all parrams:"
+ Arrays.asList(params).stream().map(Class::getName).collect(Collectors.joining(", ")));
}
private void hasMethodRegexp(Class<?> interfaceDef, String methodNameRegexp, Class<?> returnType, Class<?>... params) {
List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
assertTrue(methods.stream().anyMatch(m -> m.getName().matches(methodNameRegexp)), "No method " + methodNameRegexp);
assertTrue(
methods.stream().filter(m -> m.getName().matches(methodNameRegexp))
.filter(m -> m.getReturnType().equals(returnType))
.anyMatch(m ->
Arrays.asList(m.getParameterTypes()).containsAll(Arrays.asList(params))),
"Method " + methodNameRegexp + " has no all parrams:"
+ Arrays.asList(params).stream().map(Class::getName).collect(Collectors.joining(", ")));
}
private void hasMethod(Class<?> interfaceDef, boolean finalTag, boolean abstractTag, String methodName,
Class<?> returnType, Class<?>... params) {
List<Method> methods = Arrays.asList(interfaceDef.getDeclaredMethods());
assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName);
assertTrue(
methods.stream().filter(m -> m.getName().contains(methodName))
.filter(m -> m.getReturnType().equals(returnType)
&& (Modifier.isAbstract(m.getModifiers()) == abstractTag)
&& (Modifier.isFinal(m.getModifiers()) == finalTag))
.anyMatch(m -> Arrays.asList(m.getParameterTypes()).containsAll(Arrays.asList(params))),
"Method " + methodName + " has no all params:"
+ Arrays.asList(params).stream().map(Class::getName).collect(Collectors.joining(", ")));
}
private void hasImplements(Class<?> clazz, String... interfaceNames) {
List<Class<?>> interfaces = new ArrayList<>();
Arrays.asList(interfaceNames).stream().map(name -> getClass(name)).forEach(c -> interfaces.add(c));
assertTrue(Arrays.asList(clazz.getInterfaces()).containsAll(interfaces), "Class not implements all interfaces:"
+ interfaces.stream().map(Class::getName).collect(Collectors.joining(", ")));
}
private void hasExtends(Class<?> clazz, String parentName) {
Class<?> parent = getClass(parentName);
assertTrue(clazz.getSuperclass().equals(parent),
"Class " + clazz.getName() + " not extends class " + parentName);
}
private void hasMethod(Class<?> interfaceDef, String methodName) {
List<Method> methods = Arrays.asList(interfaceDef.getMethods());
assertTrue(methods.stream().anyMatch(m -> m.getName().contains(methodName)), "No method " + methodName);
}
private Set<String> getNameOfAllClasses() {
List<String> initClassesName = Arrays.asList("lab.Routines", "lab.App", "lab.DrawingThread");
for (String className : initClassesName) {
try {
Class.forName(className);
} catch (ClassNotFoundException e) {
System.out.println(String.format("Class '%s' cannot be loaded: %s", className, e.getMessage()));
}
}
Set<String> allClasses = new HashSet<>();
for (Package p : Package.getPackages()) {
if (p.getName().startsWith("java.") || p.getName().startsWith("com.") || p.getName().startsWith("jdk.")
|| p.getName().startsWith("javafx.") || p.getName().startsWith("org.")
|| p.getName().startsWith("sun.") || p.getName().startsWith("javax.")
|| p.getName().startsWith("javassist")) {
continue;
}
System.out.println(p.getName());
Configuration conf = new ConfigurationBuilder().addScanners(Scanners.SubTypes.filterResultsBy(pc -> true))
.forPackages(p.getName());
Reflections reflections = new Reflections(conf);
allClasses.addAll(reflections.getAll(Scanners.SubTypes.filterResultsBy(c -> {
System.out.println(c);
return true;
})));
}
return allClasses;
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment