import javafx.scene.text.Font; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.Menu; import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; import javafx.scene.control.TextField; import javafx.scene.input.MouseEvent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.scene.text.Text; import javafx.stage.Screen; import javafx.stage.Stage; import javafx.scene.shape.Arc; import javafx.scene.shape.Ellipse; /** * A simple 2D tile game to find hidden treasure by clicking on squares to * determine where it is hidden. * @author Sarah Larkin * CS3090, Spring 2018 * Date Last Modified: March 26, 2018 * */ public class ShamrockTreasureHunt extends Application { private int rows = 5; private int cols = 6; private double width = 3 * Screen.getPrimary().getBounds().getWidth()/4; private double height = 3 * Screen.getPrimary().getBounds().getHeight()/4; private int [][] board = new int [rows][cols]; private int treasX = 0; private int treasY = 0; private Group group1 = new Group(); public static void main(String[] args) { launch(args);// run the app } @Override /** * Starts up the whole display process. */ public void start(Stage primaryStage) throws Exception { Scene scene = newGame(primaryStage); primaryStage.setScene(scene); primaryStage.sizeToScene(); primaryStage.show(); } /** * Handle the mouse input to the game board * @param table the board displayed * @param window the container for all the content in the window */ public void mouseInput(Group table, BorderPane window) { table.setOnMouseClicked(new EventHandler() { @Override /** * Handle mouse-clicks on game tiles. */ public void handle(MouseEvent event) { double mouseX = event.getSceneX(); double mouseY = event.getSceneY() - 45; System.out.println(mouseY); // Determine which tile the mouse clicked int r = (int)(mouseY/(height/rows)); // Calculate which row int c = (int)(mouseX/(width/cols)); // Calculate which column if (board[r][c] == -1) { // The pot 'o gold is discovered //group1 = new Group(); // uncomment to remove double rainbow effect displayEndScreen(group1); window.setBottom(group1); } else { // A normal tile is clicked drawTile(c * width/cols, r * height/rows, width/cols, board[r][c], table); } } }); } /** * Create a new scene to display a new game board. * @param stage the window in which to display the scene * @return the new scene */ public Scene newGame(Stage stage) { if (cols * height/rows < 3 * Screen.getPrimary().getBounds().getWidth()/4) { width = cols * height/rows; } else { height = rows * width/cols; } BorderPane big = new BorderPane(); Group group = new Group(); MenuBar bar = makeMenu(stage); setup(group); mouseInput(group, big); big.setBottom(group); big.setTop(bar); return new Scene(big, width, height + 45); } /** * Set up the data representation of the game board. * @param g the display panel for the board */ public void setup(Group g) { hideTreasure(); fillTable(g); } /** * Chooses the tile behind which to hide the treasure */ public void hideTreasure() { treasX = (int) (Math.random() * cols); treasY = (int) (Math.random() * rows); System.out.println("x, y: " + treasX + ", " + treasY); System.out.println("rows, cols: " + rows + ", " + cols); board = new int[rows][cols]; board[treasY][treasX] = -1; } /** * Fill the table with distance calculations to the treasure and draw the tiles * @param g the visual representation of the table */ public void fillTable(Group g) { for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { if (board[row][col] != -1) { board[row][col] = Math.max(Math.abs(row - treasY), Math.abs(col - treasX)); } drawTile(col * width/cols, row * height/rows, width/cols, -1, g); } } } /** * Makes a menu bar to hold game options * @param stage the home window of the menu * @return the menu bar */ public MenuBar makeMenu(Stage stage) { MenuBar bar = new MenuBar(); Menu game = new Menu("Game"); MenuItem newGame = newGameItem(stage); MenuItem level = newLevelItem(stage); MenuItem exit = newExitItem(); game.getItems().addAll(newGame, level, exit); bar.getMenus().add(game); return bar; } /** * Makes a new menu item that closes the program when clicked * @return the new menu item */ private MenuItem newExitItem() { MenuItem exit = new MenuItem("Exit"); exit.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { System.exit(0); } }); return exit; } /** * Makes and returns a new menu item that displays options to change the * game level when clicked. * @param stage the home window for the menu item * @return the new menu item */ private MenuItem newLevelItem(Stage stage) { MenuItem level = new MenuItem("Change Level"); level.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { // Call the methods to change the level of the game Stage chooseLevel = levelChooser(stage); chooseLevel.show(); } }); return level; } /** * Makes and returns a new menu item that creates a new game when clicked. * @param stage the home window for the menu item * @return the new menu item */ private MenuItem newGameItem(Stage stage) { MenuItem newGame = new MenuItem("New Game"); newGame.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { // create a new game stage.setScene(newGame(stage)); } }); return newGame; } /** * Display a window to ask the number of columns and rows for the new level * @param stage the initial window * @return a new window displaying the options */ private Stage levelChooser(Stage stage) { Stage chooseLevel = new Stage(); TextField r = new TextField(); TextField c = new TextField(); Label ro = new Label("Rows: "); Label co = new Label("Columns: "); BorderPane bor = new BorderPane(); GridPane grid = new GridPane(); grid.add(ro, 0, 0); grid.add(co, 0, 1); grid.add(r, 1, 0); grid.add(c, 1, 1); Button ok = new Button("OK"); ok.setOnAction(new EventHandler () { @Override public void handle(ActionEvent arg0) { // Choose the level chooseLevel(r, c); chooseLevel.hide(); // Update the window Scene scene = newGame(stage); // Make a new game stage.setScene(scene); // Set the scene stage.sizeToScene(); // Resize the window } }); bor.setTop(grid); bor.setBottom(ok); Scene s = new Scene(bor, 400, 400); chooseLevel.setScene(s); return chooseLevel; } /** * Parse the input to set the number of rows and columns * @param r text field containing the new number of rows * @param c text field containing the new number of columns */ private void chooseLevel(TextField r, TextField c) { rows = Integer.parseInt(r.getText()); cols = Integer.parseInt(c.getText()); } /** * * @param x x-value of the top left corner of the tile * @param y y-value of the top left corner of the tile * @param s length of the sides of the tile * @param i distance from the treasure * @param g the group container for shapes drawn. */ public void drawTile(double x, double y, double s, int dist, Group g) { Rectangle r = new Rectangle(x, y, s, s); r.setFill(Color.rgb(205, 235, 205)); r.setStroke(Color.BLACK); g.getChildren().add(r); drawShamrock(x + s * 0.1, y + s * 0.05, s * 0.75, s * 0.75, Color.rgb(0, 200, 0), g); if (dist > 0) { Text text = new Text(x, y + 3 * s/5 - 5, "" + dist); text.setFill(Color.rgb(255, 195, 0)); text.setFont(new Font(s/3)); if ( dist < 10) { text.setX(x + s/2 - s/9); } else { text.setX(x + s/2 - s/6); } g.getChildren().add(text); } } /** * Draw a shamrock * @param x x-value of top left corner of the shamrock's bounding rectangle * @param y y-value of top left corner of the shamrock's bounding rectangle * @param w width of the shamrock * @param h height of the shamrock * @param c color of the shamrock * @param g the group container for the shapes drawn */ public void drawShamrock(double x, double y, double w, double h, Color c, Group g) { Ellipse e1 = new Ellipse(x + w / 2, y + h / 4, w / 4, h / 4); e1.setStroke(c); e1.setFill(c); Ellipse e2 = new Ellipse(x + w/4, y + (h * 3/5), w/4, h/4); e2.setStroke(c); e2.setFill(c); Ellipse e3 = new Ellipse(x + 3 * w / 4, y + (h * 3/5), w/4, h/4); e3.setStroke(c); e3.setFill(c); Rectangle rect = new Rectangle(x + (w * 7/16), y + h/3, w/8, h * 3/5); rect.setStroke(c); rect.setFill(c); g.getChildren().addAll(e1, e2, e3, rect); } /** * Display the end screen following a win * @param g the group container for shapes drawn */ public void displayEndScreen(Group g) { drawRainbow2(width/2, height/4, width * 0.35, height * 0.35, g); drawPotOGold(g); } /** * Draw a pot of gold image * @param g the group container for shapes drawn */ public void drawPotOGold(Group g) { Rectangle rect = new Rectangle(1000, 300, 200, 200); rect.setFill(Color.YELLOW); rect.setStroke(Color.rgb(255, 205, 0)); Arc arc = new Arc(1100, 500, 100, 25, 180, 180); arc.setFill(Color.YELLOW); arc.setStroke(Color.rgb(255, 205, 0)); Ellipse ellipse = new Ellipse(1100, 300, 100, 50); ellipse.setFill(Color.YELLOW); ellipse.setStroke(Color.rgb(255, 205, 0)); Rectangle r = new Rectangle(1000, 700, 0, 0); r.setFill(Color.rgb(245, 245, 245)); g.getChildren().addAll(rect, arc, ellipse, r); } /** * Draw a rainbow * @param x the x-coordinate for the center of the rainbow's ellipse * @param y the y-coordinate for the center of the rainbow's ellipse * @param w the width of the rainbow * @param h the height of the rainbow * @param g the group container for shapes drawn */ public void drawRainbow(double x, double y, double w, double h, Group g) { double wid = w / 12; Arc red = new Arc(x + width/2, y, w, h, 0, 180); red.setFill(Color.rgb(255, 0, 0)); Arc orange = new Arc(x + width/2, y, w - wid, h - wid, 0, 180); orange.setFill(Color.rgb(255, 195, 0)); Arc yellow = new Arc(x + width/2, y, w - (2 * wid), h - (2 * wid), 0, 180); yellow.setFill(Color.rgb(255, 255, 0)); Arc green = new Arc(x + width/2, y, w - (3 * wid), h - (3 * wid), 0, 180); green.setFill(Color.rgb(190, 255, 190)); Arc blue = new Arc(x + width/2, y, w - (4 * wid), h - (4 * wid), 0, 180); blue.setFill(Color.rgb(0, 190, 255)); Arc purple = new Arc(x + width/2, y, w - (5 * wid), h - (5 * wid), 0, 180); purple.setFill(Color.rgb(85, 85, 200)); Arc none = new Arc(x + width/2, y, w - (6 * wid), h - (6 * wid), 0, 180); none.setFill(Color.rgb(240, 240, 240)); g.getChildren().addAll(red, orange, yellow, green, blue, purple, none); } /** * Draw a rainbow * @param x the x-coordinate for the center of the rainbow's ellipse * @param y the y-coordinate for the center of the rainbow's ellipse * @param w the width of the rainbow * @param h the height of the rainbow * @param g the group container for shapes drawn */ public void drawRainbow2(double x, double y, double w, double h, Group g) { double wid = w / 12; Color [] rainbow = { Color.rgb(255, 0, 0), Color.rgb(255, 195, 0), Color.rgb(255, 255, 0), Color.rgb(190, 255, 190), Color.rgb(0, 190, 255), Color.rgb(85, 85, 200), Color.rgb(240, 240, 240) }; for (int i = 0; i < 7; i++) { Arc arc = new Arc(x + width/2, y, w - (i * wid), h - (i * wid), 0, 180); arc.setFill(rainbow[i]); g.getChildren().add(arc); } } }