diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/minigames/games/TimeInputsGame.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/minigames/games/TimeInputsGame.java new file mode 100644 index 0000000..85aabc9 --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/minigames/games/TimeInputsGame.java @@ -0,0 +1,168 @@ +package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.minigames.games; + +import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement; +import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.minigames.GameGimmick; +import edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.minigames.MiniGamesActions; +import java.util.Random; +import java.util.function.IntConsumer; +import javafx.scene.Node; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.input.KeyCode; +import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; + +/** + * Timed clicks game found in the + * {@link edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.minigames.MiniGamesView}. + * + *
Extends {@link edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement}
+ * + *Implements {@link GameGimmick}
+ * */ +public final class TimeInputsGame + extends ViewElementCalculates the normalized angle of the current hit section (white part). + * Then, checks if that angle is within the success zone defined by a start + * and length. Then adds or subtracts points based on result, + * and generates a new success zone.
+ * */ + private void evaluateHit() { + // Due to indicator angle being decreased instead of increased, + // We need to increase it by 360 to normalize it. + double normalizedAngle = (indicatorAngle + 360) % 360; + + // -10 due to some visual latency causing invalid hits to appear valid. + if (normalizedAngle >= successZoneStart - 10 && normalizedAngle <= (successZoneStart + successZoneExtent)) { + scoreModifier.accept(6); + } else { + scoreModifier.accept(-2); + } + + // Changes target area. + this.successZoneStart = generateRandomAngle(); + + // Resets indicator angle. + indicatorAngle = 90; + } + + /** + * Generates a new random number based on the area of a success zone. + */ + private double generateRandomAngle() { + return random.nextDouble() * (360.0 - successZoneExtent); + } + + /** + * Renders the canvas, updating the current indicator and success zone. + * */ + private void renderCanvas() { + GraphicsContext gc = canvas.getGraphicsContext2D(); + gc.clearRect(0, 0, 300, 300); + + double centerX = 150; + double centerY = 150; + double radius = 100; + + // Draws circle. + gc.setStroke(Color.BLACK); + gc.setLineWidth(6); + gc.strokeOval(centerX - radius, centerY - radius, radius * 2, radius * 2); + + // Draws an arc representing the success zone. + gc.setStroke(Color.CHARTREUSE); + gc.setLineWidth(12); + gc.strokeArc(centerX - radius, centerY - radius, radius * 2, radius * 2, successZoneStart, successZoneExtent, javafx.scene.shape.ArcType.OPEN); + + // Calculates and draws the indicator line based on radius and angle. + double rad = Math.toRadians(-indicatorAngle); + double startX = centerX + (radius - 15) * Math.cos(rad); + double startY = centerY + (radius - 15) * Math.sin(rad); + double endX = centerX + (radius + 15) * Math.cos(rad); + double endY = centerY + (radius + 15) * Math.sin(rad); + + gc.setStroke(Color.WHITE); + gc.setLineWidth(4); + gc.strokeLine(startX, startY, endX, endY); + } + + @Override + protected void initLayout() { + canvas = new Canvas(300,300); + random = new Random(); + successZoneStart = generateRandomAngle(); + getRootPane().getChildren().add(canvas); + } + + @Override + protected void initStyling() { + getRootPane().getStyleClass().add("time-inputs-minigame-root"); + } + + @Override + public Node getCanvasNode() { + return getRootPane(); + } + + @Override + public void initialize(final IntConsumer scoreModifier) { + this.scoreModifier = scoreModifier; + + getRootPane().setOnKeyPressed(e -> { + if (e.getCode() == KeyCode.SPACE || e.getCode() == KeyCode.ENTER) { + evaluateHit(); + } + }); + getRootPane().requestFocus(); + renderCanvas(); + } + + @Override + public void updateTick() { + indicatorAngle = (indicatorAngle - 8) % 360; + renderCanvas(); + } +}