From 0332264735bb0fee2cee5b7964e6321de5752fd0 Mon Sep 17 00:00:00 2001 From: Prasad1997 Date: Wed, 24 May 2017 17:13:07 +1000 Subject: [PATCH 1/2] Add files via upload --- BlockType.java | 4 + CachedLevels.java | 43 ++++ CachedSearch.java | 156 +++++++++++++ FileInput.java | 30 +++ GUI.java | 555 +++++++++++++++++++++++++++++++++++++++++++++ Generator.java | 188 +++++++++++++++ GeneratorUser.java | 236 +++++++++++++++++++ IGenerator.java | 28 +++ IngameMenu.java | 135 +++++++++++ Menu.java | 398 ++++++++++++++++++++++++++++++++ Notification.java | 64 ++++++ Record.java | 23 ++ State.java | 129 +++++++++++ Tile.java | 31 +++ UserGrid.java | 192 ++++++++++++++++ Vector2.java | 66 ++++++ sample.txt | 13 ++ 17 files changed, 2291 insertions(+) create mode 100644 BlockType.java create mode 100644 CachedLevels.java create mode 100644 CachedSearch.java create mode 100644 FileInput.java create mode 100644 GUI.java create mode 100644 Generator.java create mode 100644 GeneratorUser.java create mode 100644 IGenerator.java create mode 100644 IngameMenu.java create mode 100644 Menu.java create mode 100644 Notification.java create mode 100644 Record.java create mode 100644 State.java create mode 100644 Tile.java create mode 100644 UserGrid.java create mode 100644 Vector2.java create mode 100644 sample.txt diff --git a/BlockType.java b/BlockType.java new file mode 100644 index 0000000..7fe71c5 --- /dev/null +++ b/BlockType.java @@ -0,0 +1,4 @@ + +public enum BlockType { + wall, floor, box, goal, player +} diff --git a/CachedLevels.java b/CachedLevels.java new file mode 100644 index 0000000..ad8d546 --- /dev/null +++ b/CachedLevels.java @@ -0,0 +1,43 @@ +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Scanner; + +public class CachedLevels { + private String player; + + public CachedLevels(String player) { + this.player = player; + } + + public Record getRecord() { + Record c = null; + try { + HttpURLConnection conn = (HttpURLConnection) new URL("http://sokoban.heliohost.org/levelEdit.php?player=" + player).openConnection(); + conn.setDoOutput(true); + Scanner s = new Scanner(new InputStreamReader(conn.getInputStream())); + if(s.hasNext()) c = new Record(s.nextLong(), s.next(), s.nextLong()); + s.close(); + conn.disconnect(); + } catch (IOException e) { + e.printStackTrace(); + } + return c; + } + + public boolean setRecord(long seed, long time) { + boolean recordHolder = false; + try { + HttpURLConnection conn = (HttpURLConnection) new URL("http://sokoban.heliohost.org/levelEdit.php?player=" + player + "&seed=" + seed + "&time=" + time).openConnection(); + conn.setDoOutput(true); + Scanner s = new Scanner(new InputStreamReader(conn.getInputStream())); + if(s.hasNextInt() && s.nextInt() == 1) recordHolder = true; + s.close(); + conn.disconnect(); + } catch (IOException e) { + e.printStackTrace(); + } + return recordHolder; + } +} diff --git a/CachedSearch.java b/CachedSearch.java new file mode 100644 index 0000000..a87a5d4 --- /dev/null +++ b/CachedSearch.java @@ -0,0 +1,156 @@ +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.PriorityQueue; +import java.util.Queue; +import java.util.Set; +//TODO search for nearest globalTraversed then to goal + +/** + * Stores past search information to optimize successive searches from the same point + * @author KW + */ +public class CachedSearch { + /** + * Stores a series of ordered positions + * @author KW + */ + private class GridState { + private GridState parent; + private Vector2 position; + private int cost; + + public GridState(GridState parent, Vector2 position, int cost) { + this.cost = cost; + if((this.parent = parent) != null) this.cost += parent.getCost(); + this.position = position; + } + + public GridState(Vector2 position) { + this(null, position, 0); + } + + public GridState getParent() { + return parent; + } + + public Vector2 getPosition() { + return position; + } + + public int getCost() { + return cost; + } + + @Override + public boolean equals(Object o) { + if(o == null || !(o instanceof GridState)) return false; + GridState s = (GridState)o; + return s.position.equals(position); + } + + @Override + public int hashCode() { + return 21 + position.hashCode(); + } + } + + + private Vector2 start; + private Collection obsticals; + private Set successPaths; + + /** + * Instantiates a new CachedSearch + * @param start constant start of search + * @param obsticals constant locations search must avoid + */ + public CachedSearch(Vector2 start, Collection obsticals) { + this.start = start; + this.obsticals = obsticals; + + successPaths = new HashSet(); + successPaths.add(start); + } + + /** + * Attempts to find a path to the given end point + * @param end the location to search for + * @return true if end is accessible from start + */ + public boolean hasPath(Vector2 end) { + return search(end, null, 1); + + } + + public boolean hasObstical(Vector2 obstical) { + return obsticals.contains(obstical); + } + + public boolean addMinimumPath(Vector2 end, Collection floor, int newFloorCost) { + return search(end, floor, newFloorCost); + } + + /** + * Attempts to find a path to the given end point + * @param end the location to search for + * @param floor a subset of locations to search within + * @param subOptimality number of unnecessary twists in path + * @return path an ordered continuous collection from start to end or null if no path exists + */ + private boolean search(Vector2 end, Collection floor, int newFloorCost) { + if(obsticals.contains(end)) return false; + + int minX = Math.min(start.x, end.x); + int maxX = Math.max(start.x, end.x); + int minY = Math.min(start.y, end.y); + int maxY = Math.max(start.y, end.y); + + for(Vector2 v : floor != null ? floor : obsticals) { + if(v.x < minX) minX = v.x; + if(v.x > maxX) maxX = v.x; + if(v.y < minY) minY = v.y; + if(v.y > maxY) maxY = v.y; + } + + Queue pathQueue = new PriorityQueue((a, b)-> a.getCost() + Vector2.manDistance(a.getPosition(), start) - b.getCost() - Vector2.manDistance(b.getPosition(), start)); + pathQueue.add(new GridState(end)); + List closed = new ArrayList(); + + while(!pathQueue.isEmpty()) { + GridState parent = pathQueue.poll(); + closed.add(parent); + + if(floor != null ? parent.getPosition().equals(start) : successPaths.contains(parent.getPosition())) { + if(floor != null) for(GridState g = parent; g != null; g = g.getParent()) floor.add(g.getPosition()); + else for(GridState g : closed) successPaths.add(g.getPosition()); + return true; + } + + for(Vector2 childDir : Vector2.directions) { + Vector2 childPos = Vector2.add(parent.getPosition(), childDir); + if(childPos.x >= minX-1 && childPos.x <= maxX+1 && childPos.y >= minY-1 && childPos.y <= maxY+1) { + GridState child = new GridState(parent, childPos, (floor != null && floor.contains(childPos)) ? 1 : newFloorCost); + if(!obsticals.contains(childPos)) { + int prevIndex = 0; + if((prevIndex = closed.indexOf(child)) != -1) { + if(child.getCost() < closed.get(prevIndex).getCost()) { + closed.remove(prevIndex); + pathQueue.add(child); + } + } else if(pathQueue.removeIf(a -> child.equals(a) && child.getCost() < a.getCost())) { + pathQueue.add(child); + } else { + pathQueue.add(child); + } + } + } + } + } + return false; + } +} + + + diff --git a/FileInput.java b/FileInput.java new file mode 100644 index 0000000..a326b6e --- /dev/null +++ b/FileInput.java @@ -0,0 +1,30 @@ +import java.io.File; +import java.io.FileNotFoundException; + +import javafx.application.Application; +import javafx.stage.FileChooser; +import javafx.stage.Stage; + +/** + * + * @author AM + * Last Edited 24/05/2017 : Antony.J + */ +public final class FileInput extends Application { + File file; + public void start(Stage stage) throws FileNotFoundException { + final FileChooser fileChooser = new FileChooser(); + + String userDirectoryString = System.getProperty("user.dir"); + userDirectoryString += "/gameFiles"; + File userDirectory = new File(userDirectoryString); + + fileChooser.setInitialDirectory(userDirectory); + + file = fileChooser.showOpenDialog(stage); + } + + public File getFile(){ + return file; + } +} \ No newline at end of file diff --git a/GUI.java b/GUI.java new file mode 100644 index 0000000..43b7634 --- /dev/null +++ b/GUI.java @@ -0,0 +1,555 @@ +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; +import javafx.animation.FadeTransition; +import javafx.animation.Interpolator; +import javafx.animation.KeyFrame; +import javafx.animation.KeyValue; +import javafx.animation.Timeline; +import javafx.animation.TranslateTransition; +import javafx.application.Application; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.geometry.Point3D; +import javafx.scene.Camera; +import javafx.scene.Group; +import javafx.scene.Parent; +import javafx.scene.PerspectiveCamera; +import javafx.scene.PointLight; +import javafx.scene.Scene; +import javafx.scene.SceneAntialiasing; +import javafx.scene.SubScene; +import javafx.scene.image.Image; +import javafx.scene.input.KeyEvent; +import javafx.scene.input.MouseEvent; +import javafx.scene.input.SwipeEvent; +import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; +import javafx.scene.paint.PhongMaterial; +import javafx.scene.shape.Box; +import javafx.scene.shape.DrawMode; +import javafx.scene.text.Font; +import javafx.scene.text.Text; +import javafx.scene.text.TextAlignment; +import javafx.scene.transform.Rotate; +import javafx.stage.Stage; +import javafx.util.Duration; + +/** + * + * Last Edited 24/05/2017 04:00 : Antony.J + * Last Edited 24/05/2017 12:35 : Antony.J + * + */ +public class GUI extends Application { + private final int sceneScale = 100; + private final Vector2 sceneDimensions = new Vector2(500, 500); + private final int cameraHeight = 10; + private final float cameraAngle = 20; + private final float edgeHeight = 20; + + private String type = ""; + private boolean canPlay = true; + + private Box[] boxes; + private Group playerGroup; + private IGenerator g; + + IngameMenu im = new IngameMenu(); + Parent root = im.createContent(); + private int themeNum = 1; + + public int getThemeNum() { + return themeNum; + } + + public void setThemeNum(int themeNum) { + this.themeNum = themeNum; + } + + private PhongMaterial box; + private PhongMaterial floor; + private PhongMaterial goal; + private PhongMaterial player; + private PhongMaterial edge; + + private TranslateTransition cameraTransition; + private FadeTransition textTransition; + private Timeline playerTransition; + private Rotate rotation = new Rotate(); + + private PerspectiveCamera camera; + private Group level; + private Text text; + + private CachedLevels cachedLevels; + private Text time; + private final DateFormat formatter = new SimpleDateFormat("mm:ss"); + + private Timer timer; + private boolean settingRecord; + private Timeline timeline; + private Record record; + private long currTime; + private long startTime; + + @Override + public void start(Stage stage) throws IOException { + + if(getType().equals("PLAY")){ + g = new Generator(); + + } + if(getType().equals("USER")){ + g = new GeneratorUser(); + } + + text = new Text(""); + text.setFill(Color.WHITE); + text.setFont(new Font(20)); + textTransition = new FadeTransition(); + textTransition.setNode(text); + textTransition.setDuration(Duration.millis(2000)); + textTransition.setInterpolator(Interpolator.EASE_IN); + textTransition.setFromValue(1); + textTransition.setToValue(0); + + time = new Text(); + time.setFont(new Font(50)); + time.setFill(Color.WHITE); + time.setTranslateY(200); + time.setTextAlignment(TextAlignment.LEFT); + time.setVisible(false); + Notification notification = new Notification(); + cachedLevels = new CachedLevels(System.getProperty("user.name")); + timer = new Timer(); + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + if(!settingRecord) { + Record r = cachedLevels.getRecord(); + if(r != null && !r.equals(record)) { + record = r; + notification.showAlert(record.opponent + " challenged you"); + } + } + } + }, 10000, 10000); + + notification.onClick(new EventHandler() { + @Override + public void handle(MouseEvent m) { + if(!settingRecord) { // is the user is playing his generated game, then desable this + newLevel(record.seed); + text.setText(""); + settingRecord = true; + time.setVisible(true); + notification.hideAlert(); + + currTime = record.time; + timeline = new Timeline(); + timeline.setCycleCount(Timeline.INDEFINITE); + timeline.getKeyFrames().add( + new KeyFrame(Duration.millis(10), new EventHandler() { + public void handle(ActionEvent event) { + Date date = new Date(currTime -= 10); + time.setText(formatter.format(date)); + if (currTime < 10) { + currTime = 0; + timeline.stop(); + lost(); + } + } + })); + timeline.playFromStart(); + } + } + }); + + camera = new PerspectiveCamera(false); + camera.setTranslateZ(-sceneScale * cameraHeight); + camera.setRotationAxis(new Point3D(1, 0, 0)); + camera.setRotate(cameraAngle); + cameraTransition = new TranslateTransition(); + cameraTransition.setNode(camera); + cameraTransition.setDuration(Duration.millis(400)); + cameraTransition.setInterpolator(Interpolator.EASE_OUT); + + level = new Group(); + setupMaterials(); + newLevel(); + + //Group 3D nodes into a sub-scene with perspective camera + Group root3D = new Group(camera, text, level); + SubScene subScene = new SubScene(root3D, sceneDimensions.x, sceneDimensions.y, true, SceneAntialiasing.DISABLED); + subScene.setCamera(camera); + subScene.setFill(Color.BLACK); + + //Group sub-scene and 2D elements into stack pane + StackPane pane = new StackPane(); + pane.getChildren().addAll(subScene, notification, time, text); + + //Create main scene + Scene scene = new Scene(pane); + + setupKeyEvents(scene, stage, pane); + setupSwipeEvents(scene); + + + // Set up engine events + g.setOnPlayerMove(new EventHandler() { + @Override + public void handle(ActionEvent event) { + + movePlayer(g.getPlayerLocation(), camera); + } + }); + g.setOnBoxMove(new EventHandler() { + @Override + public void handle(ActionEvent event) { + moveBox(g.getBoxMovedBox(), g.getBoxLocations()[g.getBoxMovedBox()]); + } + }); + g.setOnWin(new EventHandler() { + @Override + public void handle(ActionEvent event) { + newLevel(); + won(); + System.out.println("You won"); + } + }); + g.setOnLose(new EventHandler() { + @Override + public void handle(ActionEvent event) { + newLevel(); + System.out.println("You lost"); + } + }); + + stage.setTitle("Project"); + stage.setScene(scene); + stage.show(); + } + + @Override + public void stop() { + timer.cancel(); + } + + private void won() { + if(settingRecord) { + timeline.stop(); + text.setText((cachedLevels.setRecord(record.seed, record.time - currTime) ? "You beat " : "You lost to ") + record.opponent); + time.setVisible(false); + record = null; + } else { + text.setText("You " + (cachedLevels.setRecord(g.getSeed(), System.currentTimeMillis() - startTime) ? "set a record!" : "won!")); + } + newLevel(); + } + + private void lost() { + if(settingRecord) { + timeline.stop(); + text.setText("You lost to " + record.opponent); + time.setVisible(false); + + cachedLevels.setRecord(record.seed, record.time); + record = null; + + } else { + text.setText("You lost!"); + } + newLevel(); + } + + private void newLevel() { + if(getType().equals("PLAY")){ + // g = new Generator(); + g.generateLevel(5, 20, 100); + } + if(getType().equals("USER")){ + g.generateLevel(); + } + drawLevel(); + } + + private void newLevel(long seed) { + // g = new Generator(); + g.generateLevel(5, 20, 100, seed); + drawLevel(); + System.out.println("Game Got created......."); + } + + public void drawLevel() { + settingRecord = false; + startTime = System.currentTimeMillis(); + + createPlayerGroup(g.getPlayerLocation()); + createBoxes(); + level.getChildren().clear(); + level.getChildren().add(playerGroup); + level.getChildren().addAll(boxes); + addFloor(level); + addGoals(level); + addEdges(level); + centreCamera(g.getPlayerLocation()); + + textTransition.playFromStart(); + } + + private void centreCamera(Vector2 pos) { + cameraTransition.stop(); + cameraTransition.setToX(sceneScale * pos.x - sceneDimensions.x/2.0 * camera.getScaleX()); + cameraTransition.setToY(sceneScale * pos.y - sceneDimensions.y/2.0 * camera.getScaleY() + (cameraAngle*cameraHeight*sceneScale)/(90 - cameraAngle)); + cameraTransition.play(); + } + + + private void createPlayerGroup(Vector2 start) { + Box p = new Box(sceneScale, sceneScale, sceneScale); + p.setMaterial(player); + + PointLight l = new PointLight(); + l.setColor(Color.LIGHTGOLDENRODYELLOW); + l.setTranslateZ(-sceneScale); + + playerGroup = new Group(p); + playerGroup.setTranslateX(sceneScale * start.x); + playerGroup.setTranslateY(sceneScale * start.y); + + playerTransition = new Timeline(new KeyFrame(Duration.ZERO, new KeyValue(rotation.angleProperty(), -90)), new KeyFrame(Duration.millis(150), new KeyValue(rotation.angleProperty(), 0))); + + } + + public void createBoxes() { + Vector2[] positions = g.getBoxLocations(); + boxes = new Box[positions.length]; + for(int i=0; i() { + @Override + public void handle(KeyEvent key) { + if (canPlay == true) { + switch (key.getCode()) { + case LEFT: + g.moveCharacter(Vector2.LEFT); + break; + case UP: + g.moveCharacter(Vector2.DOWN); + break; + case RIGHT: + g.moveCharacter(Vector2.RIGHT); + break; + case DOWN: + g.moveCharacter(Vector2.UP); + break; + case BACK_SPACE: + g.undo(); + break; + case ENTER: + newLevel(); + break; + case ESCAPE: + try { + + pane.getChildren().add(root); + canPlay = false; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + break; + default: + break; + + } + } else if (canPlay == false) { + + switch (key.getCode()) { + case UP: + try { + im.moveItem(1, stage); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + break; + case DOWN: + try { + im.moveItem(-1, stage); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + break; + case ENTER: + try { + im.moveItem(0, stage); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + break; + + case ESCAPE: + pane.getChildren().remove(root); + canPlay = true; + break; + + default: + break; + + } + } + } + }); + } + + public void setG(String type) { + this.type = type; + } + + private String getType(){ + return type; + } + + private void setupSwipeEvents(Scene scene) { + scene.setOnSwipeDown(new EventHandler() { + @Override + public void handle(SwipeEvent event) { + g.moveCharacter(Vector2.DOWN); + } + }); + + scene.setOnSwipeUp(new EventHandler() { + @Override + public void handle(SwipeEvent event) { + g.moveCharacter(Vector2.UP); + } + }); + + scene.setOnSwipeLeft(new EventHandler() { + @Override + public void handle(SwipeEvent event) { + g.moveCharacter(Vector2.LEFT); + } + }); + + scene.setOnSwipeRight(new EventHandler() { + @Override + public void handle(SwipeEvent event) { + g.moveCharacter(Vector2.RIGHT); + } + }); + } +} diff --git a/Generator.java b/Generator.java new file mode 100644 index 0000000..c850c06 --- /dev/null +++ b/Generator.java @@ -0,0 +1,188 @@ +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import java.util.Set; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; + +/** + * + * Last Edited 24/05/2017 : Antony.J + * + */ +public class Generator implements IGenerator { + public static Random random = new Random(); + + private State start; + private State goal; + private State curr; + private List next; + + private int movedBox; + private long seed; + + private Vector2 playerPosition; + private Set floor; + private Set edge; + + private EventHandler positionHandler; + private EventHandler boxHandler; + private EventHandler winHandler; + private EventHandler loseHandler; + + + public void moveCharacter(int dir) { + Vector2 newPos = Vector2.add(playerPosition, Vector2.directions[dir]); + for(int i=0; i no lose + loseHandler.handle(null); + } else if(hasGoal(s.getMovedBoxLocation())) { + for(Vector2 box : curr.getBoxLocations()) if(!hasGoal(box)) return; + winHandler.handle(null); + } + return; + } + } + return; + } + } + if(floor.contains(newPos)) { + playerPosition = newPos; + System.out.println("Player Location: " + playerPosition.toString()); + positionHandler.handle(null); + } + } + + public void generateLevel(int numBoxes, int numIterations, int difficulty) { + generateLevel(numBoxes, numIterations, difficulty, System.currentTimeMillis()); + } + + public void generateLevel(int numBoxes, int numIterations, int difficulty, long seed) { + this.seed = seed; + random.setSeed(seed); + + floor = new HashSet(); + edge = new HashSet(); + goal = new State(randomPositions(numBoxes)); + start = goal; + for(int i=0; i getFloor() { + return floor; + } + + public Vector2[] getGoals() { + return goal.getBoxLocations(); + } + + public boolean hasGoal(Vector2 g) { + for(Vector2 v : goal.getBoxLocations()) if(v.equals(g)) return true; + return false; + } + + public Set getEdges() { + return edge; + } + + private Vector2[] randomPositions(int num) { + Vector2[] positions = new Vector2[num]; + int[] xRandom = randomSequence(1, num + 1); + int[] yRandom = randomSequence(1, num + 1); + for(int i=0; i 0; i--) { + int index = Generator.random.nextInt(i + 1); + int a = array[index]; + array[index] = array[i]; + array[i] = a; + } + return array; + } + + public void setOnPlayerMove(EventHandler eventHandler) { + positionHandler = eventHandler; + } + + public void setOnBoxMove(EventHandler eventHandler) { + boxHandler = eventHandler; + } + + public void setOnWin(EventHandler eventHandler) { + winHandler = eventHandler; + } + + public void setOnLose(EventHandler eventHandler) { + loseHandler = eventHandler; + } + + public long getSeed() { + return seed; + } + + public void undo() { + if(!curr.equals(start)) { + movedBox = curr.getMovedBox(); + + curr = curr.getParent(); + next = curr.getStates(false); + playerPosition = curr.getPlayerLocation(); + + positionHandler.handle(null); + boxHandler.handle(null); + } + } + + @Override + public void generateLevel() { + + } +} diff --git a/GeneratorUser.java b/GeneratorUser.java new file mode 100644 index 0000000..60af891 --- /dev/null +++ b/GeneratorUser.java @@ -0,0 +1,236 @@ +import java.util.Set; + +import javafx.event.ActionEvent; +import javafx.event.EventHandler; + +/** + * + * @author AM + * + */ +public class GeneratorUser implements IGenerator { + private UserGrid userGrid; + + + private int movedBox; + private int prevDir; + private boolean boxMoved; + private Vector2 playerPosition; + Vector2[] boxLocations; + Vector2[] goalLocations; + + private Set floor; + private Set edge; + + private EventHandler positionHandler; + private EventHandler boxHandler; + private EventHandler winHandler; +// private EventHandler loseHandler; + + public GeneratorUser() { + prevDir = 5; // define undefine Dir + boxMoved = false; + userGrid = new UserGrid(); + + } + + // + // RELATED TO WEAREHOUSE GRID + // + + @Override + public void generateLevel() { + userGrid.createUserDefinedGrid(); + boxLocations = userGrid.getBoxLoctions(); + goalLocations = userGrid.getGoals(); + } + + @Override + public Vector2 getPlayerLocation() { + playerPosition = userGrid.getPlayerLocation(); + return playerPosition; + } + + @Override + public Set getFloor() { + this.floor = userGrid.getFloorSet(); + return floor; + } + + @Override + public Set getEdges() { + this.edge = userGrid.getEdgesSet(); + return edge; + } + + @Override + public Vector2[] getGoals() { + return goalLocations; + } + + @Override + public Vector2[] getBoxLocations() { + return boxLocations; + } + + // + // GET MOVED LOCATIONS + // + + + @Override + public void moveCharacter(int dir) { + prevDir = dir; + + Vector2 newPos = Vector2.add(playerPosition, Vector2.directions[dir]); + + if(floor.contains(newPos) && !userGrid.getUserDefinedGrid()[newPos.x][newPos.y].getBlockType().equals(BlockType.box)) { + userGrid.getUserDefinedGrid()[playerPosition.x][playerPosition.y].setBlockType(BlockType.floor); + userGrid.getUserDefinedGrid()[newPos.x][newPos.y].setBlockType(BlockType.player); + playerPosition = newPos; + positionHandler.handle(null); + boxMoved = false; + + }else { + for(int i=0; i < boxLocations.length; i++) { + if(boxLocations[i].equals(newPos)){ + Vector2 newBoxPos = Vector2.add(boxLocations[i], Vector2.directions[dir]); + if(floor.contains(newBoxPos) && !userGrid.getUserDefinedGrid()[newBoxPos.x][newBoxPos.y].getBlockType().equals(BlockType.box)) { + userGrid.getUserDefinedGrid()[playerPosition.x][playerPosition.y].setBlockType(BlockType.floor); + userGrid.getUserDefinedGrid()[newPos.x][newPos.y].setBlockType(BlockType.player); + userGrid.getUserDefinedGrid()[newBoxPos.x][newBoxPos.y].setBlockType(BlockType.box); + playerPosition = newPos; + movedBox = i; + boxLocations[i] = newBoxPos; + positionHandler.handle(null); + boxHandler.handle(null); + boxMoved = true; + } + int numWins = 0; + for(Vector2 goal: goalLocations) { + if(userGrid.getUserDefinedGrid()[goal.x][goal.y].getBlockType().equals(BlockType.box)) { + numWins++; + } + } + if(userGrid.getGoals().length == numWins) { + winHandler.handle(null); + } + } + } + } + } + + + @Override + public void undo() { + if(getOppositeDir() == 5) { + System.out.println("no undo"); + positionHandler.handle(null); + }else { + Vector2 newPos = Vector2.add(playerPosition, Vector2.directions[getOppositeDir()]); + if(!boxMoved) { + userGrid.getUserDefinedGrid()[playerPosition.x][playerPosition.y].setBlockType(BlockType.floor); + userGrid.getUserDefinedGrid()[newPos.x][newPos.y].setBlockType(BlockType.player); + playerPosition = newPos; + positionHandler.handle(null); + prevDir = 5; // assigning to be undefined dirr + }else { + Vector2 newBoxPos = Vector2.add(boxLocations[this.getBoxMovedBox()], Vector2.directions[getOppositeDir()]); + userGrid.getUserDefinedGrid()[boxLocations[this.getBoxMovedBox()].x][boxLocations[this.getBoxMovedBox()].y].setBlockType(BlockType.floor); + userGrid.getUserDefinedGrid()[playerPosition.x][playerPosition.y].setBlockType(BlockType.floor); + userGrid.getUserDefinedGrid()[newPos.x][newPos.y].setBlockType(BlockType.player); + userGrid.getUserDefinedGrid()[newBoxPos.x][newBoxPos.y].setBlockType(BlockType.box); + playerPosition = newPos; + boxLocations[this.getBoxMovedBox()] = newBoxPos; + positionHandler.handle(null); + boxHandler.handle(null); + prevDir = 5; // assigning to be undefined dirr + } + } + } + + @Override + public int getBoxMovedBox() { + return movedBox; + } + + + @Override + public boolean hasGoal(Vector2 g) { + Vector2[] goalLocs = getGoals(); + for(Vector2 goal: goalLocs) { + if(goal.equals(g)) + return true; + } + return false; + } + + + + // + // RELATED TO MOVEMENT IN GRID + // + + @Override + public void setOnPlayerMove(EventHandler eventHandler) { + positionHandler = eventHandler; + } + + @Override + public void setOnBoxMove(EventHandler eventHandler) { + boxHandler = eventHandler; + } + + @Override + public void setOnWin(EventHandler eventHandler) { + winHandler = eventHandler; + } + + @Override + public void setOnLose(EventHandler eventHandler) { + //loseHandler = eventHandler; + } + + + + private int getOppositeDir() { + int oppDir = 5; // assigning undefined Direction + switch(prevDir){ + case Vector2.LEFT: + oppDir = Vector2.RIGHT; + break; + case Vector2.RIGHT: + oppDir = Vector2.LEFT; + break; + case Vector2.UP: + oppDir = Vector2.DOWN; + break; + case Vector2.DOWN: + oppDir = Vector2.UP; + break; + default : + break; + } + return oppDir; + } + + + // + // PROBABLY NOT NEED THEM, SINCE THESE ARENT NECESSARY FOR USER + // + @Override + public void generateLevel(int numBoxes, int numIterations, int difficulty, long seed) { + // TODO Auto-generated method stub + } + @Override + public void generateLevel(int numBoxes, int numIterations, int difficulty) { + // TODO Auto-generated method stub + } + + @Override + public long getSeed() { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/IGenerator.java b/IGenerator.java new file mode 100644 index 0000000..0593285 --- /dev/null +++ b/IGenerator.java @@ -0,0 +1,28 @@ +import java.util.Set; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; + +/** + * + * Last Edited 24/05/2017 : Antony.J + * + */ +public interface IGenerator { + public void moveCharacter(int dir); + public void generateLevel(int numBoxes, int numIterations, int difficulty, long seed); + public void generateLevel(int numBoxes, int numIterations, int difficulty); + public void generateLevel(); + public int getBoxMovedBox(); + public Vector2[] getBoxLocations(); + public Vector2 getPlayerLocation(); + public Set getFloor(); + public Vector2[] getGoals(); + public boolean hasGoal(Vector2 g); + public Set getEdges(); + public void undo(); + public long getSeed(); + public void setOnPlayerMove(EventHandler eventHandler); + public void setOnBoxMove(EventHandler eventHandler); + public void setOnWin(EventHandler eventHandler); + public void setOnLose(EventHandler eventHandler); +} diff --git a/IngameMenu.java b/IngameMenu.java new file mode 100644 index 0000000..665b0e2 --- /dev/null +++ b/IngameMenu.java @@ -0,0 +1,135 @@ + +import javafx.animation.TranslateTransition; +import javafx.application.Application; +import javafx.geometry.Pos; +import javafx.geometry.Side; +import javafx.scene.Node; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.image.Image; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; +import javafx.scene.layout.Background; +import javafx.scene.layout.BackgroundImage; +import javafx.scene.layout.BackgroundPosition; +import javafx.scene.layout.BackgroundRepeat; +import javafx.scene.layout.BackgroundSize; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javafx.scene.text.Font; +import javafx.scene.text.FontWeight; +import javafx.scene.text.Text; +import javafx.stage.FileChooser; +import javafx.stage.Stage; +import javafx.stage.StageStyle; +import javafx.util.Duration; + +public class IngameMenu extends Application { + private static final Font FONT = Font.font("", FontWeight.BOLD, 20); + + final FileChooser fileChooser = new FileChooser(); + private VBox menuBox; + private int currentItem = 0; + + public static void main(String[] args) { + launch(args); + } + + public void start(Stage stage) throws Exception { + stage.initStyle(StageStyle.TRANSPARENT); + stage.setAlwaysOnTop(true); + Scene scene = new Scene(createContent()); + stage.setScene(scene); + + stage.show(); + } + + public Parent createContent() { + StackPane root = new StackPane(); + root.setPrefSize(200, 300); + + MenuItem exit = new MenuItem("EXIT"); + MenuItem menu = new MenuItem("MENU"); + MenuItem sandbox = new MenuItem("SANDBOX MODE"); + MenuItem options = new MenuItem("OPTIONS"); + + menuBox = new VBox(30, menu, sandbox, options, exit); + menuBox.setAlignment(Pos.CENTER); + getMenuItem(0).setActive(true); + + root.getChildren().addAll(menuBox); + + return root; + } + + private static class MenuItem extends HBox { + private Text text; + private String name; + + public MenuItem(String name) { + + // constructor for distance between sprite and text + super(15); + this.name = name; + setAlignment(Pos.CENTER_LEFT); + + text = new Text(name); + text.setFont(FONT); + + getChildren().addAll(text); + setActive(false); + + } + + public String getMenuName() { + return name; + } + + public void setActive(boolean b) { + text.setFill(b ? Color.WHITE : Color.BISQUE); + } + } + + public void moveItem(int code, Stage stage) throws Exception { + if(code == 1) { + if (currentItem > 0) { + getMenuItem(currentItem).setActive(false); + getMenuItem(--currentItem).setActive(true); + + } + } + + if (code == -1) { + if (currentItem < menuBox.getChildren().size() - 1) { + getMenuItem(currentItem).setActive(false); + getMenuItem(++currentItem).setActive(true); + + } + } + + if (code == 0) { + switch (getMenuItem(currentItem).getMenuName()) { + case "MENU" : + Menu m = new Menu(); + m.start(stage); + case "OPTIONS": + break; + + case "EXIT": + System.exit(0); + } + + } + } + + private MenuItem getMenuItem(int index) { + if (index < 0) + return null; + return (MenuItem) menuBox.getChildren().get(index); + } +} \ No newline at end of file diff --git a/Menu.java b/Menu.java new file mode 100644 index 0000000..24beed2 --- /dev/null +++ b/Menu.java @@ -0,0 +1,398 @@ + +import java.awt.Desktop; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.logging.Level; +import java.util.logging.Logger; + +//import Menu.MenuItem; +import javafx.animation.FadeTransition; +import javafx.animation.TranslateTransition; +import javafx.application.Application; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.geometry.Side; +import javafx.scene.Node; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.image.Image; +import javafx.scene.input.KeyCode; +import javafx.scene.layout.Background; +import javafx.scene.layout.BackgroundImage; +import javafx.scene.layout.BackgroundPosition; +import javafx.scene.layout.BackgroundRepeat; +import javafx.scene.layout.BackgroundSize; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javafx.scene.text.Font; +import javafx.scene.text.FontWeight; +import javafx.scene.text.Text; +import javafx.stage.FileChooser; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.util.Duration; + + +/** + * + * Last Edited 24/05/2017 12:35 : Antony.J + * + */ +public class Menu extends Application { + + public static void main(String[] args) { + launch(args); + } + + + private static final Font FONT = Font.font("", FontWeight.BOLD, 18); +// final FileChooser fileChooser = new FileChooser(); + private VBox menuBox; + // navigator of the menu + private int currentItem = 0; + private Stage stage; + GUI gui = new GUI(); + + public void start(Stage stage) throws Exception { + Scene scene = new Scene(createContent()); + + scene.setOnKeyPressed(event -> { + int temp; + if (event.getCode() == KeyCode.UP) { + if (currentItem > 0) { + temp = currentItem; + getMenuItem(currentItem - 1).setPrevActive(false); + getMenuItem(currentItem).setActive(false); + getMenuItem(--currentItem).setActive(true); + getMenuItem(temp).setPrevActive(true); + // depends on how many choices there are on menu + if (temp <= 2) + getMenuItem(++temp).setPrevActive(false); + + } + } + + if (event.getCode() == KeyCode.DOWN) { + if (currentItem < menuBox.getChildren().size() - 1) { + temp = currentItem; + getMenuItem(currentItem + 1).setPrevActive(false); + getMenuItem(currentItem).setActive(false); + getMenuItem(++currentItem).setActive(true); + getMenuItem(temp).setPrevActive(true); + if (temp >= 1) + getMenuItem(--temp).setPrevActive(false); + + } + } + + if (event.getCode() == KeyCode.ENTER) { + switch (getMenuItem(currentItem).getMenuName()) { + case "PLAY": + + gui.setG("PLAY"); + try { + gui.start(stage); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + break; + + case "SANDBOX MODE": + gui.setG("USER"); + try { + gui.start(stage); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + + } + break; + + case "OPTIONS": + + try { + + // stage.initModality(Modality.APPLICATION_MODAL); + // stage.initOwner(stage); + Parent themeRoot = createTheme(); + Scene themeScene = new Scene (themeRoot); + + themeScene.setOnKeyPressed(themeEvent -> { + int themeTemp; + if (themeEvent.getCode() == KeyCode.UP) { + if (currentItem > 0) { + themeTemp = currentItem; + getMenuItem(currentItem - 1).setPrevActive(false); + getMenuItem(currentItem).setActive(false); + getMenuItem(--currentItem).setActive(true); + getMenuItem(themeTemp).setPrevActive(true); + // depends on how many choices there are on menu + if (themeTemp <= 2) + getMenuItem(++themeTemp).setPrevActive(false); + + } + } + + if (themeEvent.getCode() == KeyCode.DOWN) { + if (currentItem < menuBox.getChildren().size() - 1) { + themeTemp = currentItem; + getMenuItem(currentItem + 1).setPrevActive(false); + getMenuItem(currentItem).setActive(false); + getMenuItem(++currentItem).setActive(true); + getMenuItem(themeTemp).setPrevActive(true); + if (themeTemp >= 1) + getMenuItem(--themeTemp).setPrevActive(false); + + } + } + + if (themeEvent.getCode() == KeyCode.ENTER) { + + switch (getMenuItem(currentItem).getMenuName()) { + + case "THEME 1" : + System.out.println("Theme set to 1"); + gui.setThemeNum(1); + break; + + case "THEME 2" : + System.out.println("Theme set to 2"); + gui.setThemeNum(2); + break; + + case "THEME 3" : + + gui.setThemeNum(3); + break; + + case "THEME 4" : + + gui.setThemeNum(4); + break; + + + case "RETURN" : + try { + start(stage); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + break; + } + + } + }); + // System.out.println("how many"); + stage.setScene(themeScene); + stage.show(); + + } catch (Exception e) { + + e.printStackTrace(); + } + + break; + + case "EXIT": + System.exit(0); + } + } + }); + stage.setScene(scene); + + stage.show(); + } + + + private Parent createTheme() { + + Pane root = new Pane (); + root.setPrefSize(900,600); + + // new Image(url) + Image image = new Image("http://i.imgur.com/AGTcz1a.jpg"); + BackgroundImage background = new BackgroundImage(image, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, + new BackgroundPosition(Side.LEFT, 0, true, Side.BOTTOM, 0, true), BackgroundSize.DEFAULT); + +// ContentFrame frame = new ContentFrame(createMiddleContent()); + +// HBox hbox = new HBox(frame); + // space inbetween frames +// hbox.setTranslateX(120); +// hbox.setTranslateY(50); + + MenuItem t1 = new MenuItem("THEME 1"); + MenuItem t2 = new MenuItem("THEME 2"); + MenuItem t3 = new MenuItem("THEME 3"); + MenuItem t4 = new MenuItem("THEME 4"); + MenuItem back = new MenuItem("RETURN"); + + menuBox = new VBox(10, t1, t2, t3, t4, back); + menuBox.setAlignment(Pos.TOP_CENTER); + menuBox.setTranslateX(360); + menuBox.setTranslateY(300); + +// Text about = new Text("COMP2911 \nMenu Prototype"); +// about.setTranslateX(50); +// about.setTranslateY(500); +// about.setFill(Color.WHITE); +// about.setFont(FONT); +// about.setOpacity(0.2); + + getMenuItem(0).setActive(true); + root.setBackground(new Background(background)); + root.getChildren().addAll(menuBox); + + return root; + } + // main layout of the menu with UI + private Parent createContent() { + Pane root = new Pane(); + root.setPrefSize(900, 600); + + // new Image(url) + Image image = new Image("http://www.relumination.com/wp-content/uploads/2016/07/warehouse-led.jpg"); + BackgroundImage background = new BackgroundImage(image, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, + new BackgroundPosition(Side.LEFT, 0, true, Side.BOTTOM, 0, true), BackgroundSize.DEFAULT); + + ContentFrame frame = new ContentFrame(createMiddleContent()); + + HBox hbox = new HBox(frame); + // space inbetween frames + hbox.setTranslateX(120); + hbox.setTranslateY(50); + + MenuItem exit = new MenuItem("EXIT"); + MenuItem play = new MenuItem("PLAY"); + MenuItem sandbox = new MenuItem("SANDBOX MODE"); + MenuItem options = new MenuItem("OPTIONS"); + + menuBox = new VBox(10, play, sandbox, options, exit); + menuBox.setAlignment(Pos.TOP_CENTER); + menuBox.setTranslateX(360); + menuBox.setTranslateY(300); + + Text about = new Text("COMP2911 \nMenu Prototype"); + about.setTranslateX(50); + about.setTranslateY(500); + about.setFill(Color.WHITE); + about.setFont(FONT); + about.setOpacity(0.2); + + getMenuItem(0).setActive(true); + root.setBackground(new Background(background)); + root.getChildren().addAll(hbox, menuBox, about); + return root; + } + + // middle panel content + private Node createMiddleContent() { + String title = "Box Pusher"; + HBox letters = new HBox(0); + letters.setAlignment(Pos.CENTER); + for (int i = 0; i < title.length(); i++) { + Text letter = new Text(title.charAt(i) + ""); + letter.setFont(FONT); + letter.setFill(Color.WHITE); + letters.getChildren().add(letter); + + TranslateTransition tt = new TranslateTransition(Duration.seconds(2), letter); + tt.setDelay(Duration.millis(i * 50)); + tt.setToY(-25); + tt.setAutoReverse(true); + tt.setCycleCount(TranslateTransition.INDEFINITE); + tt.play(); + } + + return letters; + } + + private MenuItem getMenuItem(int index) { + if (index < 0) + return null; + return (MenuItem) menuBox.getChildren().get(index); + } + + // pane with smoothed out edges + // took this design from the internet + private static class ContentFrame extends StackPane { + public ContentFrame(Node content) { + setAlignment(Pos.CENTER); + + Rectangle frame = new Rectangle(200, 200); + frame.setArcWidth(25); + frame.setArcHeight(25); + frame.setStroke(Color.WHITESMOKE); + + getChildren().addAll(frame, content); + } + } + + private static class MenuItem extends HBox { + + private Box bbLeft = new Box(40, 40, "PLAYER"); + private Box boxLeft = new Box(40, 40, "BOX"); + private Text text; + private String name; + + public MenuItem(String name) { + + // constructor for distance between sprite and text + super(15); + this.name = name; + setAlignment(Pos.CENTER_LEFT); + + text = new Text(name); + text.setFont(FONT); + + getChildren().addAll(bbLeft, boxLeft, text); + setPrevActive(false); + setActive(false); + + } + + public String getMenuName() { + return name; + } + + public void setPrevActive(boolean b) { + bbLeft.setVisible(b); + } + + public void setActive(boolean b) { + boxLeft.managedProperty().bind(boxLeft.visibleProperty()); + boxLeft.setVisible(b); + text.setFill(b ? Color.WHITE : Color.BISQUE); + } + } + + private static class Box extends Parent { + Rectangle r; + + public Box(int x, int y, String type) { + r = new Rectangle(x, y); + r.setStroke(Color.WHITE); + if (type.equals("BOX")) { + r.setFill(Color.BROWN); + } else if (type.equals("PLAYER")) + r.setFill(Color.BLUE); + + getChildren().add(r); + } + + } + + + +} \ No newline at end of file diff --git a/Notification.java b/Notification.java new file mode 100644 index 0000000..a998f08 --- /dev/null +++ b/Notification.java @@ -0,0 +1,64 @@ +import javafx.animation.Interpolator; +import javafx.animation.TranslateTransition; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.scene.Group; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.MouseEvent; +import javafx.scene.paint.Color; +import javafx.scene.text.Text; +import javafx.util.Duration; + +public class Notification extends Group { + private TranslateTransition tt = new TranslateTransition(); + private Text t = new Text(); + private ImageView i = new ImageView(); + private final Vector2 in = new Vector2(400, 200); + private final Vector2 out = new Vector2(150, 200); + private final Vector2 mid = new Vector2(295, 200); + + public Notification() { + tt.setNode(this); + tt.setDuration(Duration.millis(2000)); + tt.setInterpolator(Interpolator.EASE_BOTH); + t.setX(50); + t.setY(20); + t.setFill(Color.BLACK); + t.setStroke(Color.WHITE); + + i.setImage(new Image("https://lh3.googleusercontent.com/3Ofcop0iBUBDcxHk_-fB3-Y9xaeIv9Tt6Mvvnv6W8085GbqUrJiLOZR35yLpaR3VqTR1ocG9YSwCVvt5MkeN3mA=s0")); + i.setPreserveRatio(true); + i.setFitWidth(40); + + + this.getChildren().addAll(i, t); + this.setTranslateX(in.x); + this.setTranslateY(in.y); + + tt.setOnFinished(new EventHandler() { + @Override + public void handle(ActionEvent event) { + if(tt.getToX() == out.x) { + tt.setToX(mid.x); + tt.play(); + } + } + }); + } + + public void onClick(EventHandler onClick) { + i.setOnMouseClicked(onClick); + } + + public void showAlert(String text) { + t.setText(text); + tt.setToX(out.x); + tt.playFromStart(); + } + + public void hideAlert() { + tt.setToX(in.x); + tt.playFromStart(); + } +} diff --git a/Record.java b/Record.java new file mode 100644 index 0000000..def73ec --- /dev/null +++ b/Record.java @@ -0,0 +1,23 @@ +public class Record { + public final long seed; + public final String opponent; + public final long time; + + public Record(long seed, String opponent, long time) { + this.seed = seed; + this.opponent = opponent; + this.time = time; + } + + @Override + public String toString() { + return seed + " " + opponent + " " + time; + } + + @Override + public boolean equals(Object o) { + if(o == null || !(o instanceof Record)) return false; + Record r = (Record)o; + return r.seed == seed && r.opponent.equals(opponent) && r.time == time; + } +} diff --git a/State.java b/State.java new file mode 100644 index 0000000..3fcb78c --- /dev/null +++ b/State.java @@ -0,0 +1,129 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +public class State { + private State parent; + private Vector2[] boxLocations; + private Vector2 playerStart; + private int boxMoved; + private int dirMoved; + + private State(State parent, Vector2[] boxLocations, Vector2 playerStart, int boxMoved, int dirMoved) { + this.parent = parent; + this.boxLocations = boxLocations; + this.playerStart = playerStart; + this.boxMoved = boxMoved; + this.dirMoved = dirMoved; + } + + public State(Vector2[] boxLocations, Vector2 playerStart) { + this(null, boxLocations, playerStart, -1, -1); + } + + public State(Vector2[] boxLocations) { + this(null, boxLocations, Vector2.zero, -1, -1); + } + + public State getParent() { + return parent; + } + + public Vector2 getPlayerLocation() { + return playerStart; + } + + public Vector2[] getBoxLocations() { + return boxLocations; + } + + public Vector2 getBoxLocation(int index) { + return boxLocations[index]; + } + + public Vector2 getMovedBoxLocation() { + return boxMoved == -1 ? null : boxLocations[boxMoved]; + } + + public int getMovedBox() { + return boxMoved; + } + + public int getMovedDirection() { + return dirMoved; + } + + public List getStates(boolean reverse) { + List states = new ArrayList(boxLocations.length << 2); + CachedSearch search = new CachedSearch(getPlayerLocation(), Arrays.asList(boxLocations)); + + for(int box = 0; box < boxLocations.length; box++) { + for(int dir = 0; dir < Vector2.directions.length; dir++) { + State found = (reverse ? getPreviousBoxState(search, box, dir, null, 1) : getNextBoxState(search, box, dir, null, 1)); + if(found != null) states.add(found); + } + } + return states; + } + + public State getRandomState(Set floor, boolean reverse, int newFloorCost) { + CachedSearch search = new CachedSearch(getPlayerLocation(), Arrays.asList(boxLocations)); + for(int box : Generator.randomSequence(0, boxLocations.length)) { + for(int dir : Generator.randomSequence(0, Vector2.directions.length)) { + State s = reverse ? getPreviousBoxState(search, box, dir, floor, newFloorCost) : getNextBoxState(search, box, dir, floor, newFloorCost); + if(s != null) return s; + } + } + return null; + } + + public void print() { + for(Vector2 v : boxLocations) System.out.print("box(" + v.x + " " + v.y + ") "); + System.out.println(); + } + + private State getNextBoxState(CachedSearch search, int box, int dir, Set floor, int newFloorCost) { + Vector2 newBoxLocation = Vector2.add(boxLocations[box], Vector2.directions[dir]); + Vector2 playerAccess = Vector2.subtract(boxLocations[box], Vector2.directions[dir]); + + if(!search.hasObstical(newBoxLocation) && search.addMinimumPath(playerAccess, floor, newFloorCost)) { + Vector2[] newBoxLocations = boxLocations.clone(); + newBoxLocations[box] = newBoxLocation; + return new State(this, newBoxLocations, boxLocations[box], box, dir); + } + return null; + } + + private State getPreviousBoxState(CachedSearch search, int box, int dir, Set floor, int newFloorCost) { + Vector2 newBoxLocation = Vector2.add(boxLocations[box], Vector2.directions[dir]); + Vector2 playerAccess = Vector2.add(boxLocations[box], Vector2.scale(Vector2.directions[dir], 2)); + + if(!search.hasObstical(newBoxLocation) && search.addMinimumPath(playerAccess, floor, newFloorCost)) { + floor.add(boxLocations[box]); + floor.add(newBoxLocation); + Vector2[] newBoxLocations = boxLocations.clone(); + newBoxLocations[box] = newBoxLocation; + return new State(this, newBoxLocations, playerAccess, box, dir); + } + return null; + } + + public boolean boxHasNextState(boolean reverse, Set floor, int box) { + CachedSearch search = new CachedSearch(getPlayerLocation(), Arrays.asList(boxLocations)); + for(int dir=0; dir getFloorSet() { + Set floorVector = new HashSet(); + for (int r = 0; r < GRID_ROW_SIZE; r++) { + for (int c = 0; c < GRID_COL_SIZE; c++) { + if (!userDefinedGrid[r][c].getBlockType().equals(BlockType.wall)) + floorVector.add(userDefinedGrid[r][c]); + } + } + return floorVector; + } + + public Set getEdgesSet() { + Set wallVector = new HashSet(); + for (int r = 0; r < GRID_ROW_SIZE; r++) { + for (int c = 0; c < GRID_COL_SIZE; c++) { + if (userDefinedGrid[r][c].getBlockType().equals(BlockType.wall)) + wallVector.add(userDefinedGrid[r][c]); + } + } + return wallVector; + } + + public Vector2[] getGoals() { + Vector2[] goals = new Vector2[numGoals]; + int i = 0; + for (int r = 0; r < GRID_ROW_SIZE; r++) { + for (int c = 0; c < GRID_COL_SIZE; c++) { + if (userDefinedGrid[r][c].getBlockType().equals(BlockType.goal)) { + goals[i] = userDefinedGrid[r][c]; + i++; + } + } + } + return goals; + } + + public Vector2[] getBoxLoctions() { + Vector2[] boxes = new Vector2[numBoxes]; // numGoals must be equal to + // num ofBoxes + int i = 0; + for (int r = 0; r < GRID_ROW_SIZE; r++) { + for (int c = 0; c < GRID_COL_SIZE; c++) { + if (userDefinedGrid[r][c].getBlockType().equals(BlockType.box)) { + boxes[i] = userDefinedGrid[r][c]; + i++; + } + } + } + return boxes; + } + + public int getNumGoals() { + return numGoals; + } + + public int getNumBoxes() { + return numBoxes; + } +} diff --git a/Vector2.java b/Vector2.java new file mode 100644 index 0000000..e4c6d0e --- /dev/null +++ b/Vector2.java @@ -0,0 +1,66 @@ +/** + * + * Last Edited 24/05/2017 : Antony.J + * + */ +public class Vector2 { + public final int x; + public final int y; + + public static final Vector2 zero = new Vector2(0, 0); + + public static final int LEFT = 0; + public static final int UP = 1; + public static final int RIGHT = 2; + public static final int DOWN = 3; + private BlockType blockType; + + public static final Vector2[] directions = {new Vector2(-1, 0), new Vector2(0, 1), new Vector2(1, 0), new Vector2(0, -1)}; + + public Vector2(int x, int y) { + this.x = x; + this.y = y; + } + + public BlockType getBlockType() { + return this.blockType; + } + + public void setBlockType(BlockType type) { + this.blockType = type; + } + + public static Vector2 add(Vector2 v1, Vector2 v2) { + return new Vector2(v1.x + v2.x, v1.y + v2.y); + } + + public static Vector2 subtract(Vector2 v1, Vector2 v2) { + return new Vector2(v1.x - v2.x, v1.y - v2.y); + } + + public static Vector2 scale(Vector2 v, int scale) { + return new Vector2(v.x * scale, v.y * scale); + } + + public static int manDistance(Vector2 v1, Vector2 v2) { + return Math.abs(v1.x - v2.x) + Math.abs(v1.y - v2.y); + } + + + @Override + public boolean equals(Object o) { + if(o == null || !(o instanceof Vector2)) return false; + Vector2 v = (Vector2)o; + return x == v.x && y == v.y; + } + + @Override + public int hashCode() { + return 7 * x + 13 * y; + } + + @Override + public String toString() { + return "(" + x + ", " + y + ")"; + } +} diff --git a/sample.txt b/sample.txt new file mode 100644 index 0000000..70dcbb0 --- /dev/null +++ b/sample.txt @@ -0,0 +1,13 @@ +############ +##### #### +## #G B # # +## # G # +## G GBB # +### # +## G B # +# ## +# B B # +# B ### +# GB GP # +## #### +############ From abd647a6ef4e3f9fcc1a643d740583a44823d1fd Mon Sep 17 00:00:00 2001 From: Prasad1997 Date: Wed, 24 May 2017 19:37:34 +1000 Subject: [PATCH 2/2] Add files via upload --- Menu.java | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/Menu.java b/Menu.java index 24beed2..a9adcdf 100644 --- a/Menu.java +++ b/Menu.java @@ -57,8 +57,10 @@ public static void main(String[] args) { private static final Font FONT = Font.font("", FontWeight.BOLD, 18); // final FileChooser fileChooser = new FileChooser(); private VBox menuBox; + private VBox themeBox; // navigator of the menu private int currentItem = 0; + private int themeItem = 0; private Stage stage; GUI gui = new GUI(); @@ -130,12 +132,12 @@ public void start(Stage stage) throws Exception { themeScene.setOnKeyPressed(themeEvent -> { int themeTemp; if (themeEvent.getCode() == KeyCode.UP) { - if (currentItem > 0) { - themeTemp = currentItem; - getMenuItem(currentItem - 1).setPrevActive(false); - getMenuItem(currentItem).setActive(false); - getMenuItem(--currentItem).setActive(true); - getMenuItem(themeTemp).setPrevActive(true); + if (themeItem > 0) { + themeTemp = themeItem; + getThemeItem(themeItem - 1).setPrevActive(false); + getThemeItem(themeItem).setActive(false); + getThemeItem(--themeItem).setActive(true); + getThemeItem(themeTemp).setPrevActive(true); // depends on how many choices there are on menu if (themeTemp <= 2) getMenuItem(++themeTemp).setPrevActive(false); @@ -144,21 +146,21 @@ public void start(Stage stage) throws Exception { } if (themeEvent.getCode() == KeyCode.DOWN) { - if (currentItem < menuBox.getChildren().size() - 1) { - themeTemp = currentItem; - getMenuItem(currentItem + 1).setPrevActive(false); - getMenuItem(currentItem).setActive(false); - getMenuItem(++currentItem).setActive(true); - getMenuItem(themeTemp).setPrevActive(true); + if (themeItem < themeBox.getChildren().size() - 1) { + themeTemp = themeItem; + getThemeItem(themeItem + 1).setPrevActive(false); + getThemeItem(themeItem).setActive(false); + getThemeItem(++themeItem).setActive(true); + getThemeItem(themeTemp).setPrevActive(true); if (themeTemp >= 1) - getMenuItem(--themeTemp).setPrevActive(false); + getThemeItem(--themeTemp).setPrevActive(false); } } if (themeEvent.getCode() == KeyCode.ENTER) { - switch (getMenuItem(currentItem).getMenuName()) { + switch (getThemeItem(themeItem).getMenuName()) { case "THEME 1" : System.out.println("Theme set to 1"); @@ -183,6 +185,7 @@ public void start(Stage stage) throws Exception { case "RETURN" : try { + start(stage); } catch (Exception e) { // TODO Auto-generated catch block @@ -238,10 +241,10 @@ private Parent createTheme() { MenuItem t4 = new MenuItem("THEME 4"); MenuItem back = new MenuItem("RETURN"); - menuBox = new VBox(10, t1, t2, t3, t4, back); - menuBox.setAlignment(Pos.TOP_CENTER); - menuBox.setTranslateX(360); - menuBox.setTranslateY(300); + themeBox = new VBox(10, t1, t2, t3, t4, back); + themeBox.setAlignment(Pos.TOP_CENTER); + themeBox.setTranslateX(360); + themeBox.setTranslateY(300); // Text about = new Text("COMP2911 \nMenu Prototype"); // about.setTranslateX(50); @@ -250,9 +253,9 @@ private Parent createTheme() { // about.setFont(FONT); // about.setOpacity(0.2); - getMenuItem(0).setActive(true); + getThemeItem(0).setActive(true); root.setBackground(new Background(background)); - root.getChildren().addAll(menuBox); + root.getChildren().addAll(themeBox); return root; } @@ -323,6 +326,11 @@ private MenuItem getMenuItem(int index) { return null; return (MenuItem) menuBox.getChildren().get(index); } + private MenuItem getThemeItem(int index) { + if (index < 0) + return null; + return (MenuItem) themeBox.getChildren().get(index); + } // pane with smoothed out edges // took this design from the internet