diff --git a/chip/interim Deliverable/Chip.java b/chip/interim Deliverable/Chip.java new file mode 100644 index 00000000..7e225534 --- /dev/null +++ b/chip/interim Deliverable/Chip.java @@ -0,0 +1,42 @@ +import java.awt.Point; +import java.util.Arraylist; + +public class Chip +{ + Point position = new Point(); + private int xPos; + private int yPos; + + public Chip() + { + currentLocation.setLocation(12, 12); + } + + public void goRight() + { + if (position.getX()+1 <= 24) + position.setLocation(position.getX()+1, position.getY()); + xPos++; + } + + public void goWest() + { + if (position.getX()-1 >= 0) + position.setLocation(position.getX()-1, position.getY()); + xPos--; + } + + public void goNorth() + { + if (position.getX()-1 >= 0) + position.setLocation(position.getX(), position.getY()-1); + yPos--; + } + + public void goSouth() + { + if (position.getY()+1 <= 24) + position.setLocation(position.getX(), position.getY()+1); + yPos++; + } +} diff --git a/chip/interim Deliverable/Chips UML.pdf b/chip/interim Deliverable/Chips UML.pdf new file mode 100644 index 00000000..936d34d5 Binary files /dev/null and b/chip/interim Deliverable/Chips UML.pdf differ diff --git a/chip/interim Deliverable/Game.java b/chip/interim Deliverable/Game.java new file mode 100644 index 00000000..a8280992 --- /dev/null +++ b/chip/interim Deliverable/Game.java @@ -0,0 +1,31 @@ +import javafx.application.Application; +import javafx.event.EventHandler; +import javafx.stage.Stage; +import javafx.scene.Scene; +import javafx.scene.layout.*; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.KeyEvent; + +public class Game extends Application +{ + final int scale = 25; + public static void main(String[] args) + { + launch(args); + } + + @Override + public void start(Stage chipStage) throws Exception + { + // Generate New Pane + AnchorPane root = new AnchorPane(); + Scene scene = new Scene(root, 625, 625); + chipStage.setScene(scene); + chipStage.setTitle("My Chip Game"); + + GridMap map = new GridMap(); + map.drawMap(root.getChildren(), scale); + GridMap.drawMap(); + } +} diff --git a/chip/interim Deliverable/GridMap.java b/chip/interim Deliverable/GridMap.java new file mode 100644 index 00000000..bd89626c --- /dev/null +++ b/chip/interim Deliverable/GridMap.java @@ -0,0 +1,51 @@ +import javafx.collections.ObservableList; +import javafx.scene.shape.Rectangle; +import javafx.scene.Node; +import javafx.scene.paint.Color; +import java.util.Random; + +public class GridMap +{ + int[][] gridMap = new int[25][25]; + final int dimensions = 25; + + public void drawMap(ObservableList root, int scale) + { + for (int x = 0; x < dimensions; x++) + { + for (int y = 0; y < dimensions; y++) + { + Rectangle rect = new Rectangle(x * scale, y * scale, scale, scale); + rect.setStroke(Color.BLACK); + oceanGrid[x][y] = 0; + rect.setFill(Color.DARKGREY); + root.add(rect); + } + } + } + + public int getStatus(int x, int y) + { + return gridMap[x][y]; + } + + public void setLevel(int lvl) + { + // a block with value '1' will be an untraversable block + // note that this could be a water block, in which case + // if a sand block is pushed over it, its value will flip + + if (lvl == 1) + { + + } + else if (lvl == 2) + { + + } + else + { + + } + } +} diff --git a/chip/interim Deliverable/Status.md b/chip/interim Deliverable/Status.md new file mode 100644 index 00000000..5e9583e5 --- /dev/null +++ b/chip/interim Deliverable/Status.md @@ -0,0 +1,5 @@ +As of now, a simple grid is all that is functionally complete. I am currently working on implementing chip so that he +can appropriately move around, as well as working on a sand block: the next logical steps from here would be to test +sandblock and add necessary code to have it interact properly when it would hit a water tile. The plan from here would +be to implement the bug and key classes in either order, and once these are all ultimately in place and working properly, +I will move on to designing the level structure via the interace and then wrap up the project from there diff --git a/chip/src/Block.java b/chip/src/Block.java new file mode 100644 index 00000000..57963ff6 --- /dev/null +++ b/chip/src/Block.java @@ -0,0 +1,9 @@ +import javafx.scene.image.ImageView; + +public interface Block +{ + public ImageView getImageView(); + public void setX(int x); + public void setY(int y); + public void setPosition(int x, int y); +} \ No newline at end of file diff --git a/chip/src/Chip.java b/chip/src/Chip.java new file mode 100644 index 00000000..b7d1eca0 --- /dev/null +++ b/chip/src/Chip.java @@ -0,0 +1,60 @@ +import java.awt.Point; +import java.util.ArrayList; + +public class Chip +{ + Point position = new Point(); + private int xPos; + private int yPos; + ArrayList keys = new ArrayList(); + + public Chip() + { + position.setLocation(13, 13); + xPos = 13; + yPos = 13; + } + + public void goRight() + { + if (position.getX()+1 <= 26) + position.setLocation(position.getX()+1, position.getY()); + xPos++; + } + + public void goLeft() + { + if (position.getX()-1 > 0) + position.setLocation(position.getX()-1, position.getY()); + xPos--; + } + + public void goUp() + { + if (position.getX()-1 > 0) + position.setLocation(position.getX(), position.getY()-1); + yPos--; + } + + public void goDown() + { + if (position.getY()+1 <= 26) + position.setLocation(position.getX(), position.getY()+1); + yPos++; + } + + public Point getPosition() + { + return this.position; + } + + public ArrayList getKeys() + { + return keys; + } + + public void addKey(int key) + { + keys.add(key-1); + } +} diff --git a/chip/src/Game.java b/chip/src/Game.java new file mode 100644 index 00000000..8acc0be3 --- /dev/null +++ b/chip/src/Game.java @@ -0,0 +1,351 @@ +import javafx.application.Application; +import javafx.collections.ObservableList; +import javafx.event.EventHandler; +import javafx.stage.Stage; +import javafx.scene.Node; +import javafx.scene.Scene; +import javafx.scene.layout.*; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.KeyEvent; + + +public class Game extends Application +{ + final int scale = 25; + public static void main(String[] args) + { + launch(args); + } + + @Override + public void start(Stage chipStage) throws Exception + { + // Generate New Pane + AnchorPane root = new AnchorPane(); + Scene scene = new Scene(root, 675, 675); + Stage level1 = new Stage(); + level1 = chipStage; + + // Initialize Level 1 + level1.setScene(scene); + level1.setTitle("My Chip Game Level 1"); + + GridMap map = new GridMap(); + map.drawMap(root.getChildren(), scale, 1); + + level1.show(); + + Chip chip = new Chip(); + + // Draw Chip + Image chipImage = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/chipDown.png", scale, scale, true, true); + ImageView chipImageView = new ImageView(chipImage); + chipImageView.setX(chip.getPosition().getX()); + chipImageView.setY(chip.getPosition().getY()); + root.getChildren().add(chipImageView); + + // Play Level 1 + playChips(scene, chip, chipImageView, map, root.getChildren(), level1); + + // Initialize Level 2 + Stage level2 = new Stage(); + level2 = chipStage; + + level2.setScene(scene); + level2.setTitle("My Chip Game Level 2"); + + GridMap map2 = new GridMap(); + map2.drawMap(root.getChildren(), scale, 1); + + level2.show(); + + Chip chip2 = new Chip(); + + // Draw Chip + Image chipImage2 = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/chipDown.png", scale, scale, true, true); + ImageView chipImageView2 = new ImageView(chipImage2); + chipImageView2.setX(chip2.getPosition().getX()); + chipImageView2.setY(chip2.getPosition().getY()); + root.getChildren().add(chipImageView2); + + // Play Level 1 + playChips(scene, chip2, chipImageView2, map2, root.getChildren(), level2); + + } + + public void playChips(Scene scene, Chip chip, ImageView chipImageView, GridMap map, ObservableList root, Stage gameStage) + { + /// + Image chipRight = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/chipRight.png", scale, scale, true, true); + Image chipLeft = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/chipLeft.png", scale, scale, true, true); + Image chipUp = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/chipUp.png", scale, scale, true, true); + Image chipDown = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/chipDown.png", scale, scale, true, true); + //int positionValue = 0; + + scene.setOnKeyPressed(new EventHandler() + { + //@Override + public void handle(KeyEvent ke) + { + switch (ke.getCode()) + { + case RIGHT: + int positionValue = map.getStatus((int)chip.getPosition().getX()+1, (int)chip.getPosition().getY()); + if (positionValue == 1) + { + chip.goRight(); + chipImageView.setImage(chipRight); + } + else if (positionValue == 3) + { + chip.goRight(); + map.removeKey((int)chip.getPosition().getX()+1, (int)chip.getPosition().getY(), 3); + chip.addKey(3); + chipImageView.setImage(chipRight); + chipImageView.toFront(); + } + else if (positionValue == 5) + { + chip.goRight(); + map.removeKey((int)chip.getPosition().getX()+1, (int)chip.getPosition().getY(), 5); + chip.addKey(5); + chipImageView.setImage(chipRight); + chipImageView.toFront(); + } + else if (positionValue == 7) + { + chip.goRight(); + map.removeKey((int)chip.getPosition().getX()+1, (int)chip.getPosition().getY(), 7); + chip.addKey(7); + chipImageView.setImage(chipRight); + chipImageView.toFront(); + } + else if (positionValue == 9) + { + chip.goRight(); + map.removeKey((int)chip.getPosition().getX()+1, (int)chip.getPosition().getY(), 9); + chip.addKey(9); + chipImageView.setImage(chipRight); + chipImageView.toFront(); + } + else if (positionValue == 10) + { + chip.goRight(); + chipImageView.setImage(chipRight); + foundPortal(gameStage); + } + else if (positionValue % 2 == 0) + { + if (chip.getKeys().contains(positionValue)) + { + openWall((int)chip.getPosition().getX()+1, (int)chip.getPosition().getY(), map, root); + chip.goRight(); + chipImageView.setImage(chipRight); + chipImageView.toFront(); + } + } + break; + + case LEFT: + int positionValue1 = map.getStatus((int)chip.getPosition().getX()-1, (int)chip.getPosition().getY()); + if (positionValue1 == 1) + { + chip.goLeft(); + chipImageView.setImage(chipLeft); + } + else if (positionValue1 == 3) + { + chip.goLeft(); + map.removeKey((int)chip.getPosition().getX()-1, (int)chip.getPosition().getY(), 3); + chip.addKey(3); + chipImageView.setImage(chipLeft); + chipImageView.toFront(); + } + else if (positionValue1 == 5) + { + chip.goLeft(); + map.removeKey((int)chip.getPosition().getX()-1, (int)chip.getPosition().getY(), 5); + chip.addKey(5); + chipImageView.setImage(chipLeft); + chipImageView.toFront(); + + } + else if (positionValue1 == 7) + { + chip.goLeft(); + map.removeKey((int)chip.getPosition().getX()-1, (int)chip.getPosition().getY(), 7); + chip.addKey(7); + chipImageView.setImage(chipLeft); + chipImageView.toFront(); + } + else if (positionValue1 == 9) + { + chip.goLeft(); + map.removeKey((int)chip.getPosition().getX()-1, (int)chip.getPosition().getY(), 9); + chip.addKey(9); + chipImageView.setImage(chipLeft); + chipImageView.toFront(); + + } + else if (positionValue1 == 10) + { + chip.goLeft(); + chipImageView.setImage(chipLeft); + foundPortal(gameStage); + } + else if (positionValue1 % 2 == 0) + { + if (chip.getKeys().contains(positionValue1)) + { + openWall((int)chip.getPosition().getX()-1, (int)chip.getPosition().getY(), map, root); + chip.goLeft(); + chipImageView.setImage(chipLeft); + chipImageView.toFront(); + } + } + break; + + case UP: + int positionValue2 = map.getStatus((int)chip.getPosition().getX(), (int)chip.getPosition().getY()-1); + if (positionValue2 == 1) + { + chip.goUp(); + chipImageView.setImage(chipUp); + } + else if (positionValue2 == 3) + { + chip.goUp(); + map.removeKey((int)chip.getPosition().getX(), (int)chip.getPosition().getY()-1, 3); + chip.addKey(3); + chipImageView.setImage(chipUp); + chipImageView.toFront(); + } + else if (positionValue2 == 5) + { + chip.goUp(); + map.removeKey((int)chip.getPosition().getX(), (int)chip.getPosition().getY()-1, 5); + chip.addKey(5); + chipImageView.setImage(chipUp); + chipImageView.toFront(); + } + else if (positionValue2 == 7) + { + chip.goUp(); + map.removeKey((int)chip.getPosition().getX(), (int)chip.getPosition().getY()-1, 7); + chip.addKey(7); + chipImageView.setImage(chipUp); + chipImageView.toFront(); + } + else if (positionValue2 == 9) + { + chip.goUp(); + map.removeKey((int)chip.getPosition().getX(), (int)chip.getPosition().getY()-1, 9); + chip.addKey(9); + chipImageView.setImage(chipUp); + chipImageView.toFront(); + } + else if (positionValue2 == 10) + { + chip.goUp(); + chipImageView.setImage(chipUp); + foundPortal(gameStage); + } + else if (positionValue2 % 2 == 0) + { + if (chip.getKeys().contains(positionValue2)) + { + openWall((int)chip.getPosition().getX(), (int)chip.getPosition().getY()-1, map, root); + chip.goUp(); + chipImageView.setImage(chipUp); + chipImageView.toFront(); + } + } + break; + + case DOWN: + int positionValue3 = map.getStatus((int)chip.getPosition().getX(), (int)chip.getPosition().getY()+1); + if (positionValue3 == 1) + { + chip.goDown(); + chipImageView.setImage(chipDown); + } + else if (positionValue3 == 3) + { + chip.goDown(); + map.removeKey((int)chip.getPosition().getX(), (int)chip.getPosition().getY()+1, 3); + chip.addKey(3); + chipImageView.setImage(chipDown); + chipImageView.toFront(); + } + else if (positionValue3 == 5) + { + chip.goDown(); + map.removeKey((int)chip.getPosition().getX(), (int)chip.getPosition().getY()+1, 5); + chip.addKey(5); + chipImageView.setImage(chipDown); + chipImageView.toFront(); + } + else if (positionValue3 == 7) + { + chip.goDown(); + map.removeKey((int)chip.getPosition().getX(), (int)chip.getPosition().getY()+1, 7); + chip.addKey(7); + chipImageView.setImage(chipDown); + chipImageView.toFront(); + } + else if (positionValue3 == 9) + { + chip.goDown(); + map.removeKey((int)chip.getPosition().getX(), (int)chip.getPosition().getY()+1, 9); + chip.addKey(9); + chipImageView.setImage(chipDown); + chipImageView.toFront(); + } + else if (positionValue3 == 10) + { + chip.goDown(); + chipImageView.setImage(chipDown); + foundPortal(gameStage); + } + else if (positionValue3 % 2 == 0) + { + if (chip.getKeys().contains(positionValue3)) + { + openWall((int)chip.getPosition().getX(), (int)chip.getPosition().getY()+1, map, root); + chip.goDown(); + chipImageView.setImage(chipDown); + chipImageView.toFront(); + } + } + break; + + case ESCAPE: + gameStage.close(); + break; + + default: + break; + } + chipImageView.setX(chip.getPosition().getX()*scale); + chipImageView.setY(chip.getPosition().getY()*scale); + } + }); + } + + public void openWall(int x, int y, GridMap map, ObservableList root) + { + map.setStatus(x, y, 1); + blankBlock tile = new blankBlock(); + tile.setPosition(x * scale, y * scale); + root.add(tile.getImageView()); + tile.getImageView().toFront(); + //map.drawMap(root, scale, 0); + + } + + public void foundPortal(Stage gameStage) + { + gameStage.close(); + } +} \ No newline at end of file diff --git a/chip/src/GridMap.java b/chip/src/GridMap.java new file mode 100644 index 00000000..e26767fd --- /dev/null +++ b/chip/src/GridMap.java @@ -0,0 +1,179 @@ +import javafx.collections.ObservableList; +import javafx.scene.Node; +//import java.util.Random; + +public class GridMap +{ + int[][] gridMap = new int[27][27]; + final int dimensions = 27; + private int scale = 25; + private ObservableList root; + + public void drawMap(ObservableList root, int scale, int Level) + { + this.root = root; + if (Level == 1) + buildLevel1(); + else if (Level == 2) + buildLevel2(); + + for (int x = 0; x < dimensions; x++) + { + for (int y = 0; y < dimensions; y++) + { + if (gridMap[x][y] == 0) + { + WallBlock wall = new WallBlock(); + wall.setPosition(x * scale, y * scale); + root.add(wall.getImageView()); + } + else if (gridMap[x][y] == 1) + { + blankBlock tile = new blankBlock(); + tile.setPosition(x * scale, y * scale); + root.add(tile.getImageView()); + } + else if (gridMap[x][y] == 2) + { + yellowKeyWall yellowLock = new yellowKeyWall(); + yellowLock.setPosition(x * scale, y * scale); + root.add(yellowLock.getImageView()); + } + else if (gridMap[x][y] == 3) + { + yellowKey yKey = new yellowKey(); + yKey.setPosition(x * scale, y * scale); + root.add(yKey.getImageView()); + } + else if (gridMap[x][y] == 4) + { + greenKeyWall greenLock = new greenKeyWall(); + greenLock.setPosition(x * scale, y * scale); + root.add(greenLock.getImageView()); + } + else if (gridMap[x][y] == 5) + { + greenKey gKey = new greenKey(); + gKey.setPosition(x * scale, y * scale); + root.add(gKey.getImageView()); + } + else if (gridMap[x][y] == 6) + { + blueKeyWall blueLock = new blueKeyWall(); + blueLock.setPosition(x * scale, y * scale); + root.add(blueLock.getImageView()); + } + else if (gridMap[x][y] == 7) + { + blueKey bKey = new blueKey(); + bKey.setPosition(x * scale, y * scale); + root.add(bKey.getImageView()); + } + else if (gridMap[x][y] == 8) + { + redKeyWall redLock = new redKeyWall(); + redLock.setPosition(x * scale, y * scale); + root.add(redLock.getImageView()); + } + else if (gridMap[x][y] == 9) + { + redKey rKey = new redKey(); + rKey.setPosition(x * scale, y * scale); + root.add(rKey.getImageView()); + } + else if (gridMap[x][y] == 10) + { + Portal portal = new Portal(); + portal.setPosition(x * scale, y * scale); + root.add(portal.getImageView()); + } + } + } + } + + public void buildLevel1() + { + for (int x = 0; x < dimensions; x++) + { + for (int y = 0; y < dimensions; y++) + { + if (x == 0 || y == 0 || x == 26 || y == 26) + gridMap[x][y] = 0; + else + gridMap[x][y] = 1; + } + } + + for (int x = 1; x < 26; x++) + { + gridMap[x][3] = 0; + } + + for (int x = 1; x < 4; x++) + { + gridMap[x][1] = 0; + gridMap[x][3] = 0; + gridMap[x][23] = 0; + gridMap[x][25] = 0; + gridMap[x+22][1] = 0; + gridMap[x+22][3] = 0; + gridMap[x+22][23] = 0; + gridMap[x+22][25] = 0; + } + + // Build inaccessible areas + gridMap[1][2] = 0; + gridMap[1][24] = 0; + gridMap[3][24] = 0; + gridMap[23][2] = 0; + gridMap[25][2] = 0; + gridMap[23][24] = 0; + gridMap[25][24] = 0; + + // build lock pathways + gridMap[2][3] = 2; + gridMap[3][2] = 1; + gridMap[2][23] = 4; + gridMap[23][24] = 6; + gridMap[24][3] = 8; + + // places keys + gridMap[24][2] = 5; + gridMap[2][24] = 7; + gridMap[24][24] = 3; + gridMap[3][5] = 9; + + // place portal + gridMap[13][1] = 10; + } + + public void buildLevel2() + { + for (int x = 0; x < dimensions; x++) + { + for (int y = 0; y < dimensions; y++) + { + if (x == 0 || y == 0 || x == 26 || y == 26) + gridMap[x][y] = 0; + else + gridMap[x][y] = 1; + } + } + } + + public int getStatus(int x, int y) + { + return gridMap[x][y]; + } + + public void setStatus(int x, int y, int status) + { + gridMap[x][y] = status; + } + + public void removeKey(int x, int y, int keyNum) + { + gridMap[x][y] = 1; + drawMap(this.root, this.scale, 0); + } +} diff --git a/chip/src/Key.java b/chip/src/Key.java new file mode 100644 index 00000000..1056c315 --- /dev/null +++ b/chip/src/Key.java @@ -0,0 +1,9 @@ +import javafx.scene.image.ImageView; + +public interface Key +{ + public ImageView getImageView(); + public void setX(int x); + public void setY(int y); + public void setPosition(int x, int y); +} \ No newline at end of file diff --git a/chip/src/Portal.java b/chip/src/Portal.java new file mode 100644 index 00000000..81448fe8 --- /dev/null +++ b/chip/src/Portal.java @@ -0,0 +1,37 @@ +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class Portal implements Block +{ + int scale = 25; + int x = 0; + int y = 0; + Image blockImage = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/portal.png", scale, scale, true, true); + ImageView blockImageView = new ImageView(blockImage); + + @Override + public ImageView getImageView() + { + return blockImageView; + } + + @Override + public void setX(int x) { + this.x = x; + this.blockImageView.setX(x); + } + + @Override + public void setY(int y) { + this.y = y; + this.blockImageView.setY(y); + } + + @Override + public void setPosition(int x, int y) { + this.x = x; + this.blockImageView.setX(x); + this.y = y; + this.blockImageView.setY(y); + } +} \ No newline at end of file diff --git a/chip/src/WallBlock.java b/chip/src/WallBlock.java new file mode 100644 index 00000000..e7737c62 --- /dev/null +++ b/chip/src/WallBlock.java @@ -0,0 +1,37 @@ +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class WallBlock implements Block +{ + int scale = 25; + int x = 0; + int y = 0; + Image blockImage = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/BlockTile.png", scale, scale, true, true); + ImageView blockImageView = new ImageView(blockImage); + + @Override + public ImageView getImageView() + { + return blockImageView; + } + + @Override + public void setX(int x) { + this.x = x; + this.blockImageView.setX(x); + } + + @Override + public void setY(int y) { + this.y = y; + this.blockImageView.setY(y); + } + + @Override + public void setPosition(int x, int y) { + this.x = x; + this.blockImageView.setX(x); + this.y = y; + this.blockImageView.setY(y); + } +} \ No newline at end of file diff --git a/chip/src/blankBlock.java b/chip/src/blankBlock.java new file mode 100644 index 00000000..3998b60c --- /dev/null +++ b/chip/src/blankBlock.java @@ -0,0 +1,37 @@ +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class blankBlock implements Block +{ + int scale = 25; + int x = 0; + int y = 0; + Image blockImage = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/BlankTile.png", scale, scale, true, true); + ImageView blockImageView = new ImageView(blockImage); + + @Override + public ImageView getImageView() + { + return blockImageView; + } + + @Override + public void setX(int x) { + this.x = x; + this.blockImageView.setX(x); + } + + @Override + public void setY(int y) { + this.y = y; + this.blockImageView.setY(y); + } + + @Override + public void setPosition(int x, int y) { + this.x = x; + this.blockImageView.setX(x); + this.y = y; + this.blockImageView.setY(y); + } +} \ No newline at end of file diff --git a/chip/src/blueKey.java b/chip/src/blueKey.java new file mode 100644 index 00000000..8cf117bd --- /dev/null +++ b/chip/src/blueKey.java @@ -0,0 +1,37 @@ +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class blueKey implements Key +{ + int scale = 25; + int x = 0; + int y = 0; + Image blockImage = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/blueKey.png", scale, scale, true, true); + ImageView blockImageView = new ImageView(blockImage); + + @Override + public ImageView getImageView() + { + return blockImageView; + } + + @Override + public void setX(int x) { + this.x = x; + this.blockImageView.setX(x); + } + + @Override + public void setY(int y) { + this.y = y; + this.blockImageView.setY(y); + } + + @Override + public void setPosition(int x, int y) { + this.x = x; + this.blockImageView.setX(x); + this.y = y; + this.blockImageView.setY(y); + } +} \ No newline at end of file diff --git a/chip/src/blueKeyWall.java b/chip/src/blueKeyWall.java new file mode 100644 index 00000000..abfc8e40 --- /dev/null +++ b/chip/src/blueKeyWall.java @@ -0,0 +1,37 @@ +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class blueKeyWall implements Block +{ + int scale = 25; + int x = 0; + int y = 0; + Image blockImage = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/blueKeyWall.png", scale, scale, true, true); + ImageView blockImageView = new ImageView(blockImage); + + @Override + public ImageView getImageView() + { + return blockImageView; + } + + @Override + public void setX(int x) { + this.x = x; + this.blockImageView.setX(x); + } + + @Override + public void setY(int y) { + this.y = y; + this.blockImageView.setY(y); + } + + @Override + public void setPosition(int x, int y) { + this.x = x; + this.blockImageView.setX(x); + this.y = y; + this.blockImageView.setY(y); + } +} \ No newline at end of file diff --git a/chip/src/chips UML final.pdf b/chip/src/chips UML final.pdf new file mode 100644 index 00000000..b1e259ba Binary files /dev/null and b/chip/src/chips UML final.pdf differ diff --git a/chip/src/greenKey.java b/chip/src/greenKey.java new file mode 100644 index 00000000..e3d17397 --- /dev/null +++ b/chip/src/greenKey.java @@ -0,0 +1,37 @@ +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class greenKey implements Key +{ + int scale = 25; + int x = 0; + int y = 0; + Image blockImage = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/greenKey.png", scale, scale, true, true); + ImageView blockImageView = new ImageView(blockImage); + + @Override + public ImageView getImageView() + { + return blockImageView; + } + + @Override + public void setX(int x) { + this.x = x; + this.blockImageView.setX(x); + } + + @Override + public void setY(int y) { + this.y = y; + this.blockImageView.setY(y); + } + + @Override + public void setPosition(int x, int y) { + this.x = x; + this.blockImageView.setX(x); + this.y = y; + this.blockImageView.setY(y); + } +} \ No newline at end of file diff --git a/chip/src/greenKeyWall.java b/chip/src/greenKeyWall.java new file mode 100644 index 00000000..683003e4 --- /dev/null +++ b/chip/src/greenKeyWall.java @@ -0,0 +1,37 @@ +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class greenKeyWall implements Block +{ + int scale = 25; + int x = 0; + int y = 0; + Image blockImage = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/greenKeyWall.png", scale, scale, true, true); + ImageView blockImageView = new ImageView(blockImage); + + @Override + public ImageView getImageView() + { + return blockImageView; + } + + @Override + public void setX(int x) { + this.x = x; + this.blockImageView.setX(x); + } + + @Override + public void setY(int y) { + this.y = y; + this.blockImageView.setY(y); + } + + @Override + public void setPosition(int x, int y) { + this.x = x; + this.blockImageView.setX(x); + this.y = y; + this.blockImageView.setY(y); + } +} \ No newline at end of file diff --git a/chip/src/pattern designs.pdf b/chip/src/pattern designs.pdf new file mode 100644 index 00000000..966f6a2a Binary files /dev/null and b/chip/src/pattern designs.pdf differ diff --git a/chip/src/redKey.java b/chip/src/redKey.java new file mode 100644 index 00000000..66e32a6c --- /dev/null +++ b/chip/src/redKey.java @@ -0,0 +1,37 @@ +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class redKey implements Key +{ + int scale = 25; + int x = 0; + int y = 0; + Image blockImage = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/redKey.png", scale, scale, true, true); + ImageView blockImageView = new ImageView(blockImage); + + @Override + public ImageView getImageView() + { + return blockImageView; + } + + @Override + public void setX(int x) { + this.x = x; + this.blockImageView.setX(x); + } + + @Override + public void setY(int y) { + this.y = y; + this.blockImageView.setY(y); + } + + @Override + public void setPosition(int x, int y) { + this.x = x; + this.blockImageView.setX(x); + this.y = y; + this.blockImageView.setY(y); + } +} \ No newline at end of file diff --git a/chip/src/redKeyWall.java b/chip/src/redKeyWall.java new file mode 100644 index 00000000..5a1fabe1 --- /dev/null +++ b/chip/src/redKeyWall.java @@ -0,0 +1,37 @@ +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class redKeyWall implements Block +{ + int scale = 25; + int x = 0; + int y = 0; + Image blockImage = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/redKeyWall.png", scale, scale, true, true); + ImageView blockImageView = new ImageView(blockImage); + + @Override + public ImageView getImageView() + { + return blockImageView; + } + + @Override + public void setX(int x) { + this.x = x; + this.blockImageView.setX(x); + } + + @Override + public void setY(int y) { + this.y = y; + this.blockImageView.setY(y); + } + + @Override + public void setPosition(int x, int y) { + this.x = x; + this.blockImageView.setX(x); + this.y = y; + this.blockImageView.setY(y); + } +} \ No newline at end of file diff --git a/chip/src/reflection.MD b/chip/src/reflection.MD new file mode 100644 index 00000000..ed5a6162 --- /dev/null +++ b/chip/src/reflection.MD @@ -0,0 +1,13 @@ +The main mindset behind my design was to have most of the “work” done in a concise area without much repeated work/logic (isn’t that the +point of every clean coded project?) elsewhere, and while towards the end of the design building this seemed to break down a bit, I feel +it held true throughout most of my design process. I tried to implement the factory design method in order to produce the layout of the +game (i.e. the tiles and different keys) as well as use it to handle certain events (ex. Opening a lock), and for the most part this +worked, but for some reason the keys did not properly move off the board when collected (the keys are “picked up”, but the key tiles +remain on the board regardless) while the locks did, which I would have to guess had something to do with the way the two different +interfaces would interact with the grid, hence the difference. Moreover, Iimplemented the State pattern (Chip's image was the state) as +well as utilized the Strategy pattern for the actual game levels. The issue with the later was that I was unable to accurately, or really +at all, properly implement the Strategy pattern, as I could not make the game flip levels or redraw a new level without completely exiting +or having a manually hard coded switch. I certainly would have liked to have changed that last aspect if I were able to redo the project, +and I wish I could have figured out a way to encapsulate the levels such that "exiting" or completing level 1 would automatically bring +up level 2. additionally, I would have loved to have incorporated more elements, such as water blocks or bugs, into the game, as I feel +like my game is fairly primitive (unfortunately I was swamped with interviews during this period of time, hence the 11th hour submission. This is not to make an excuse but rather just give context, as I genuinely enjoyed the project, but I just wish I had more time to complete it!). diff --git a/chip/src/textures/BlankTile.png b/chip/src/textures/BlankTile.png new file mode 100644 index 00000000..c594f20d Binary files /dev/null and b/chip/src/textures/BlankTile.png differ diff --git a/chip/src/textures/BlockTile.png b/chip/src/textures/BlockTile.png new file mode 100644 index 00000000..32956acc Binary files /dev/null and b/chip/src/textures/BlockTile.png differ diff --git a/chip/src/textures/blueKey.png b/chip/src/textures/blueKey.png new file mode 100644 index 00000000..2c6b249b Binary files /dev/null and b/chip/src/textures/blueKey.png differ diff --git a/chip/src/textures/blueKeyWall.png b/chip/src/textures/blueKeyWall.png new file mode 100644 index 00000000..70480b9c Binary files /dev/null and b/chip/src/textures/blueKeyWall.png differ diff --git a/chip/src/textures/bugUp.png b/chip/src/textures/bugUp.png new file mode 100644 index 00000000..cfd8bb06 Binary files /dev/null and b/chip/src/textures/bugUp.png differ diff --git a/chip/src/textures/chipDown.png b/chip/src/textures/chipDown.png new file mode 100644 index 00000000..1d06deb1 Binary files /dev/null and b/chip/src/textures/chipDown.png differ diff --git a/chip/src/textures/chipItem.png b/chip/src/textures/chipItem.png new file mode 100644 index 00000000..bc087bee Binary files /dev/null and b/chip/src/textures/chipItem.png differ diff --git a/chip/src/textures/chipLeft.png b/chip/src/textures/chipLeft.png new file mode 100644 index 00000000..243a4400 Binary files /dev/null and b/chip/src/textures/chipLeft.png differ diff --git a/chip/src/textures/chipRight.png b/chip/src/textures/chipRight.png new file mode 100644 index 00000000..ec669d27 Binary files /dev/null and b/chip/src/textures/chipRight.png differ diff --git a/chip/src/textures/chipUp.png b/chip/src/textures/chipUp.png new file mode 100644 index 00000000..fdfb383c Binary files /dev/null and b/chip/src/textures/chipUp.png differ diff --git a/chip/src/textures/greenKey.png b/chip/src/textures/greenKey.png new file mode 100644 index 00000000..c6b4dfe4 Binary files /dev/null and b/chip/src/textures/greenKey.png differ diff --git a/chip/src/textures/greenKeyWall.png b/chip/src/textures/greenKeyWall.png new file mode 100644 index 00000000..6c9660b8 Binary files /dev/null and b/chip/src/textures/greenKeyWall.png differ diff --git a/chip/src/textures/hold.md b/chip/src/textures/hold.md new file mode 100644 index 00000000..d59825fe --- /dev/null +++ b/chip/src/textures/hold.md @@ -0,0 +1 @@ +hold diff --git a/chip/src/textures/portal.png b/chip/src/textures/portal.png new file mode 100644 index 00000000..600ff4c6 Binary files /dev/null and b/chip/src/textures/portal.png differ diff --git a/chip/src/textures/redKey.png b/chip/src/textures/redKey.png new file mode 100644 index 00000000..3bb88b4b Binary files /dev/null and b/chip/src/textures/redKey.png differ diff --git a/chip/src/textures/redKeyWall.png b/chip/src/textures/redKeyWall.png new file mode 100644 index 00000000..8ac73e32 Binary files /dev/null and b/chip/src/textures/redKeyWall.png differ diff --git a/chip/src/textures/tiles.png b/chip/src/textures/tiles.png new file mode 100644 index 00000000..e633013a Binary files /dev/null and b/chip/src/textures/tiles.png differ diff --git a/chip/src/textures/yellowKey.png b/chip/src/textures/yellowKey.png new file mode 100644 index 00000000..b537de26 Binary files /dev/null and b/chip/src/textures/yellowKey.png differ diff --git a/chip/src/textures/yellowKeyWall.png b/chip/src/textures/yellowKeyWall.png new file mode 100644 index 00000000..d6a5ea1a Binary files /dev/null and b/chip/src/textures/yellowKeyWall.png differ diff --git a/chip/src/yellowKey.java b/chip/src/yellowKey.java new file mode 100644 index 00000000..39ae217a --- /dev/null +++ b/chip/src/yellowKey.java @@ -0,0 +1,37 @@ +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class yellowKey implements Key +{ + int scale = 25; + int x = 0; + int y = 0; + Image blockImage = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/yellowKey.png", scale, scale, true, true); + ImageView blockImageView = new ImageView(blockImage); + + @Override + public ImageView getImageView() + { + return blockImageView; + } + + @Override + public void setX(int x) { + this.x = x; + this.blockImageView.setX(x); + } + + @Override + public void setY(int y) { + this.y = y; + this.blockImageView.setY(y); + } + + @Override + public void setPosition(int x, int y) { + this.x = x; + this.blockImageView.setX(x); + this.y = y; + this.blockImageView.setY(y); + } +} \ No newline at end of file diff --git a/chip/src/yellowKeyWall.java b/chip/src/yellowKeyWall.java new file mode 100644 index 00000000..eb21a031 --- /dev/null +++ b/chip/src/yellowKeyWall.java @@ -0,0 +1,37 @@ +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class yellowKeyWall implements Block +{ + int scale = 25; + int x = 0; + int y = 0; + Image blockImage = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/chip/chipsChallenge/src/textures/yellowKeyWall.png", scale, scale, true, true); + ImageView blockImageView = new ImageView(blockImage); + + @Override + public ImageView getImageView() + { + return blockImageView; + } + + @Override + public void setX(int x) { + this.x = x; + this.blockImageView.setX(x); + } + + @Override + public void setY(int y) { + this.y = y; + this.blockImageView.setY(y); + } + + @Override + public void setPosition(int x, int y) { + this.x = x; + this.blockImageView.setX(x); + this.y = y; + this.blockImageView.setY(y); + } +} \ No newline at end of file diff --git a/hw5/application/Images/Train.png b/hw5/application/Images/Train.png new file mode 100644 index 00000000..b8b7386d Binary files /dev/null and b/hw5/application/Images/Train.png differ diff --git a/hw5/application/Images/bluecar.png b/hw5/application/Images/bluecar.png new file mode 100644 index 00000000..c6934564 Binary files /dev/null and b/hw5/application/Images/bluecar.png differ diff --git a/hw5/application/Images/graycar.png b/hw5/application/Images/graycar.png new file mode 100644 index 00000000..fc3c4020 Binary files /dev/null and b/hw5/application/Images/graycar.png differ diff --git a/hw5/application/Images/greencar.png b/hw5/application/Images/greencar.png new file mode 100644 index 00000000..3678ad33 Binary files /dev/null and b/hw5/application/Images/greencar.png differ diff --git a/hw5/application/Images/redcar.png b/hw5/application/Images/redcar.png new file mode 100644 index 00000000..d8729e97 Binary files /dev/null and b/hw5/application/Images/redcar.png differ diff --git a/hw5/application/Reflection.md b/hw5/application/Reflection.md new file mode 100644 index 00000000..fd658e67 --- /dev/null +++ b/hw5/application/Reflection.md @@ -0,0 +1,2 @@ +For the design process, I added a second rail line and subsequently a second train which would, instead of moving east to west like the original train, move west to east. This design mimicked the design of the previous track and train, adding the two gates currently in use as observers of the new rail that was located below the previous rail/train. I am sure many people feel this same way, but I do not particularly enjoy working with other people’s code: it seems to be a bit more difficult for me to try and piece together what someone else has done, especially when I was not there for the actual genesis of the code (i.e. not being able to work through the thought process of the author in the same way that they did seemed to be a hindrance to me). I would certainly like to improve upon my car design (I was not able to properly implement a working solution for the cars to have a state change and move across the meridian, and the solution I developed actually degraded the train movement and gate recognition, so I needed to revert to a code state before those changes) as well as a few issues with the new track (the train movement was awkward and buggy initially, an issue which had to be worked around with more hardcoded numbers than I would have liked). +With this in mind, I do not think that my model would scale particularly well: it is very obviously still full of bugs, as well as the issues with the cars. Since the cars changing lanes degraded the railway recognition system, it would not scale well to include, say, a real-time monitoring system of multiple stops for the railway, or a simulation of actual daily traffic (since the car movement was not properly implemented fully on my behalf). diff --git a/hw5/application/bin/edu/nd/sarec/railwaycrossing/Simulation.java b/hw5/application/bin/edu/nd/sarec/railwaycrossing/Simulation.java new file mode 100644 index 00000000..56d87993 --- /dev/null +++ b/hw5/application/bin/edu/nd/sarec/railwaycrossing/Simulation.java @@ -0,0 +1,111 @@ +package application.bin.edu.nd.sarec.railwaycrossing; + +import java.util.ArrayList; +import java.util.Collection; + +import application.model.infrastructure.MapBuilder; +import application.model.infrastructure.RailwayTracks; +import application.model.infrastructure.Road; +import application.model.infrastructure.gate.CrossingGate; +import application.model.vehicles.Car; +import application.model.vehicles.Train; +import application.view.MapDisplay; +import javafx.animation.AnimationTimer; +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.layout.Pane; +import javafx.stage.Stage; + +public class Simulation extends Application{ + + private Pane root; + private Scene scene; + private MapBuilder mapBuilder; + private MapDisplay mapDisplay; + + @Override + public void start(Stage stage) throws Exception { + + root = new Pane(); + + // Build infrastructure + mapBuilder = new MapBuilder(); + mapDisplay = new MapDisplay(root, mapBuilder.getRoads(), mapBuilder.getTracks(),mapBuilder.getAllGates()); + mapDisplay.drawTracks(); + mapDisplay.drawRoad(); + mapDisplay.drawGate(); + + scene = new Scene(root,1200,1000); + stage.setTitle("Railways"); + stage.setScene(scene); + stage.show(); + + // Train + RailwayTracks track = mapBuilder.getTrack("Royal"); + Train train = new Train(track.getEndX()+100,track.getEndY()-25); + root.getChildren().add(train.getImageView()); + // Train2 + RailwayTracks track2 = mapBuilder.getTrack("Reading"); + Train train2 = new Train(track2.getStartX()-200, track2.getEndY()+75); + train2.setDirection(1); + root.getChildren().add(train2.getImageView()); + + + for(CrossingGate gate: mapBuilder.getAllGates()) { + train.addObserver(gate); + train2.addObserver(gate); + } + + + // Sets up a repetitive loop i.e., in handle that runs the actual simulation + new AnimationTimer(){ + + @Override + public void handle(long now) { + + createCar(); + train.move(); + train2.moveEast(); + + for(CrossingGate gate: mapBuilder.getAllGates()) + gate.operateGate(); + + if (train.offScreen()) + train.reset(); + if (train2.offScreenEast()) + train2.reset(); + + clearCars(); + } + }.start(); + } + + // Clears cars as they leave the simulation + private void clearCars(){ + Collection roads = mapBuilder.getRoads(); + for(Road road: roads){ + if (road.getCarFactory()!= null){ + ArrayList junkCars = road.getCarFactory().removeOffScreenCars(); + mapDisplay.removeCarImages(junkCars); + } + } + } + + private void createCar(){ + Collection roads = mapBuilder.getRoads(); + for(Road road: roads){ + if (road.getCarFactory() != null){ + if ((int)(Math.random() * 100) == 15){ + Car car = road.getCarFactory().buildCar(); + if (car != null){ + root.getChildren().add(car.getImageView()); + } + } + } + } + } + + public static void main(String[] args){ + launch(args); + } +} diff --git a/hw5/application/model/infrastructure/Direction.java b/hw5/application/model/infrastructure/Direction.java new file mode 100644 index 00000000..3113aee0 --- /dev/null +++ b/hw5/application/model/infrastructure/Direction.java @@ -0,0 +1,9 @@ +package application.model.infrastructure; + +public enum Direction { + NORTH, + SOUTH, + EAST, + WEST, + CUSTOM; +} diff --git a/hw5/application/model/infrastructure/MapBuilder.java b/hw5/application/model/infrastructure/MapBuilder.java new file mode 100644 index 00000000..43603507 --- /dev/null +++ b/hw5/application/model/infrastructure/MapBuilder.java @@ -0,0 +1,71 @@ +package application.model.infrastructure; + +import java.awt.Point; +import java.util.Collection; +import java.util.HashMap; + +import application.model.infrastructure.gate.CrossingGate; + +/** + * Creates all infrastructure for the simulation + * @author jane + * + */ +public class MapBuilder { + HashMap roads; + HashMap gates; + HashMap tracks; + + public MapBuilder(){ + roads = new HashMap(); + gates = new HashMap(); + tracks = new HashMap(); + buildRoads(); + buildCrossingGates(); + buildTracks(); + assignGatesToRoads(); + buildCarFactories(); + } + + private void buildRoads(){ + roads.put("Western Highway",new Road(new Point(800,0),new Point (800,1000),Direction.SOUTH,true,false)); + roads.put("Skyway",new Road(new Point(400,0),new Point (400,1000),Direction.SOUTH,true,false)); + roads.put("EastWest",new Road(new Point(415,800),new Point (785,800),Direction.EAST,true,true)); + } + + private void buildCrossingGates(){ + gates.put("Gate1", new CrossingGate(780,480, "Gate1")); + gates.put("Gate2", new CrossingGate(380,480, "Gate2")); + } + + private void buildTracks(){ + tracks.put("Royal", new RailwayTracks(new Point(0,500),new Point(1200,500))); + tracks.put("Reading", new RailwayTracks(new Point(0,600),new Point(1200,600))); + } + + private void assignGatesToRoads(){ + roads.get("Western Highway").assignGate(gates.get("Gate1")); + roads.get("Skyway").assignGate(gates.get("Gate2")); + } + + private void buildCarFactories(){ + roads.get("Western Highway").addCarFactory(); + roads.get("Skyway").addCarFactory(); + } + + public Collection getAllGates(){ + return gates.values(); + } + + public Collection getTracks(){ + return tracks.values(); + } + + public Collection getRoads(){ + return roads.values(); + } + + public RailwayTracks getTrack(String name){ + return tracks.get("Royal"); + } +} diff --git a/hw5/application/model/infrastructure/RailwayTracks.java b/hw5/application/model/infrastructure/RailwayTracks.java new file mode 100644 index 00000000..14e65136 --- /dev/null +++ b/hw5/application/model/infrastructure/RailwayTracks.java @@ -0,0 +1,46 @@ +package application.model.infrastructure; + +import java.awt.Point; + +/** + * Railway Tracks (Entity Object) + * @author Jane Cleland-Huang + * + */ +public class RailwayTracks { + + private int startX; + private int endX; + private int startY; + private int endY; + + public RailwayTracks(){} + + public RailwayTracks(Point startPoint, Point endPoint){ + startX = startPoint.x; + startY = startPoint.y; + endX = endPoint.x; + endY = endPoint.y; + } + + public int getStartX(){ + return startX; + } + + public int getEndX(){ + return endX; + } + + public int getStartY(){ + return startY; + } + + public int getEndY(){ + return endY; + } + + @Override + public String toString(){ + return "Tracks from (" + startX + "," + startY + ") to (" + endX + "," + endY + ")"; + } +} diff --git a/hw5/application/model/infrastructure/Road.java b/hw5/application/model/infrastructure/Road.java new file mode 100644 index 00000000..5defd03a --- /dev/null +++ b/hw5/application/model/infrastructure/Road.java @@ -0,0 +1,86 @@ +package application.model.infrastructure; + +import java.awt.Point; +import java.util.Collection; +import java.util.Vector; + +import application.model.infrastructure.gate.CrossingGate; +import application.model.vehicles.CarFactory; + +/** + * Represents a single road + * @author jane + * + */ +public class Road { + private int startX; + private int endX; + private int startY; + private int endY; + private CarFactory carFactory; + Direction direction; + Collection gates; + boolean clearEnds = false; + int roadSize; + + public Road(){} + + public Road(Point start, Point end, Direction direction, boolean buildCarFactory, boolean clearEnds){ + startX = start.x; + startY = start.y; + endX = end.x; + endY = end.y; + roadSize = 18; + + this.direction = direction; + gates = new Vector(); + this.clearEnds = clearEnds; + + } + + // Adds a gate to a road + // In case a new gate is added after the factory is assigned, we reassign factory + // The factory needs to know all gates on the road in order to register each car as an observer. + public void assignGate(CrossingGate gate){ + gates.add(gate); + if (carFactory != null) + carFactory = new CarFactory(direction, new Point(startX-roadSize/2,startY), gates); // allows additional gates. Needs fixing + } + + public void addCarFactory(){ + if (carFactory == null) // We only allow one + carFactory = new CarFactory(direction, new Point(startX-roadSize/2,startY), gates); + } + + public CarFactory getCarFactory(){ + return carFactory; + } + + public int getStartX(){ + return startX; + } + + public int getEndX(){ + return endX; + } + + public int getStartY(){ + return startY; + } + + public int getEndY(){ + return endY; + } + + public Direction getDirection(){ + return direction; + } + + public boolean getClearEnds(){ + return clearEnds; + } + + public int getRoadWidth(){ + return roadSize; + } +} diff --git a/hw5/application/model/infrastructure/gate/CrossingGate.java b/hw5/application/model/infrastructure/gate/CrossingGate.java new file mode 100644 index 00000000..f54f6da6 --- /dev/null +++ b/hw5/application/model/infrastructure/gate/CrossingGate.java @@ -0,0 +1,138 @@ +package application.model.infrastructure.gate; + +import java.util.Observable; +import java.util.Observer; + +import application.model.vehicles.Train; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Line; + +/** + * Context class for Crossing Gate + * @author jane + * + */ +public class CrossingGate extends Observable implements Observer{ + + // Crossing Gate location and its trigger & exit points + private int anchorX; + private int anchorY; + private int movingX; + private int movingY; + private int triggerPoint; + private int exitPoint; + + private IGateState gateClosed; + private IGateState gateOpen; + private IGateState gateClosing; + private IGateState gateOpening; + private IGateState currentGateState; + private Line line; + private Pane root; + + String gateName; + + public CrossingGate(){} + + public CrossingGate(int xPosition, int yPosition, String crossingGate){ + anchorX = xPosition; + anchorY = yPosition; + movingX = anchorX; + movingY = anchorY-60; + triggerPoint = anchorX+350; + exitPoint = anchorX-350; + + // Gate elements + line = new Line(anchorX, anchorY,movingX,movingY); + line.setStroke(Color.RED); + line.setStrokeWidth(10); + + // Gate States + gateClosed = new GateClosed(this); + gateOpen = new GateOpen(this); + gateOpening = new GateOpening(this); + gateClosing = new GateClosing(this); + currentGateState = gateOpen; + gateName = crossingGate; + } + + public Line getGateLine(){ + return line; + } + + public void operateGate(){ + currentGateState.operate(); + } + + public void close(){ + if (movingYanchorX){ + movingX-=1; + movingY-=1; + line.setStartX(anchorX); + line.setStartY(anchorY); + line.setEndX(movingX); + line.setEndY(movingY); + } else { + currentGateState.gateFinishedOpening(); + } + } + + // State getters and setters + public IGateState getGateClosedState(){ + return gateClosed; + } + public IGateState getGateOpenState(){ + return gateOpen; + } + public IGateState getGateClosingState(){ + return gateClosing; + } + public IGateState getGateOpeningState(){ + return gateOpening; + } + + public void setGateState(IGateState newState){ + currentGateState = newState; + setChanged(); + notifyObservers(); + } + + public String getTrafficCommand(){ + return currentGateState.getTrafficAction(); + } + + @Override + public void update(Observable o, Object arg) { + if (o instanceof Train){ + Train train = (Train)o; + if (train.getDirection() == 0) { + if (train.getVehicleX() < exitPoint) + currentGateState.leaveStation(); + else if(train.getVehicleX() < triggerPoint){ + currentGateState.approachStation(); + } + } + else { + if (train.getVehicleX() > triggerPoint) + currentGateState.leaveStation(); + else if(train.getVehicleX() > exitPoint){ + currentGateState.approachStation(); + } + } + } + } +} diff --git a/hw5/application/model/infrastructure/gate/GateClosed.java b/hw5/application/model/infrastructure/gate/GateClosed.java new file mode 100644 index 00000000..fa37cfc7 --- /dev/null +++ b/hw5/application/model/infrastructure/gate/GateClosed.java @@ -0,0 +1,49 @@ +package application.model.infrastructure.gate; + +/** + * Gate in CLOSED state + * @author jane + * + */ +public class GateClosed implements IGateState { + + private CrossingGate gate; + + protected GateClosed(CrossingGate gate){ + this.gate = gate; + } + + @Override + public void approachStation() { + // Do nothing. Gate is already closed. + // IF there were two tracks we would have to keep track of how many trains were in the station! + } + + @Override + public void leaveStation() { + gate.setGateState(gate.getGateOpeningState()); + } + + @Override + public void gateFinishedOpening() { + // not applicable + } + + @Override + public void gateFinishedClosing() { + // not applicable. Gate is already closed. + } + + @Override + public void operate() { + // Flash lights + + } + + @Override + public String getTrafficAction() { + return "STOP"; + } + + +} diff --git a/hw5/application/model/infrastructure/gate/GateClosing.java b/hw5/application/model/infrastructure/gate/GateClosing.java new file mode 100644 index 00000000..5440da67 --- /dev/null +++ b/hw5/application/model/infrastructure/gate/GateClosing.java @@ -0,0 +1,50 @@ +package application.model.infrastructure.gate; + +/** + * Gate in closing state + * @author jane + * + */ +public class GateClosing implements IGateState{ + + private CrossingGate gate; + + protected GateClosing(CrossingGate gate){ + this.gate = gate; + } + + @Override + public void approachStation() { + // Gate is already closing + } + + @Override + public void leaveStation() { + // This was an unwanted event. The gate wasn't fully closed when the train was in the station. + // Nevertheless we will open the gate. + gate.setGateState(gate.getGateOpeningState()); + } + + @Override + public void gateFinishedOpening() { + // n/a + } + + @Override + public void gateFinishedClosing() { + gate.setGateState(gate.getGateClosedState()); + } + + @Override + public void operate() { + gate.close(); + // flash lights + } + + @Override + public String getTrafficAction() { + return "STOP"; + } + + +} diff --git a/hw5/application/model/infrastructure/gate/GateOpen.java b/hw5/application/model/infrastructure/gate/GateOpen.java new file mode 100644 index 00000000..67ffd42c --- /dev/null +++ b/hw5/application/model/infrastructure/gate/GateOpen.java @@ -0,0 +1,46 @@ +package application.model.infrastructure.gate; + +/** + * Gate in open state + * @author jane + * + */ +public class GateOpen implements IGateState { + + private CrossingGate gate; + + protected GateOpen(CrossingGate gate){ + this.gate = gate; + } + + @Override + public void approachStation() { + gate.setGateState(gate.getGateClosingState()); + } + + @Override + public void leaveStation() { + // n/a gate already open + } + + @Override + public void gateFinishedOpening() { + // n/a gate already open + } + + @Override + public void gateFinishedClosing() { + // n/a can't be closing and opened. + } + + @Override + public void operate() { + // Normal operation. Do nothing. + } + + @Override + public String getTrafficAction() { + return "GO"; + } + +} diff --git a/hw5/application/model/infrastructure/gate/GateOpening.java b/hw5/application/model/infrastructure/gate/GateOpening.java new file mode 100644 index 00000000..0a78588d --- /dev/null +++ b/hw5/application/model/infrastructure/gate/GateOpening.java @@ -0,0 +1,48 @@ +package application.model.infrastructure.gate; + +/** + * Gate in opening state + * @author jane + * + */ +public class GateOpening implements IGateState{ + + CrossingGate gate; + + protected GateOpening(CrossingGate gate){ + this.gate = gate; + } + + @Override + public void approachStation() { + gate.setGateState(gate.getGateClosingState()); + } + + @Override + public void leaveStation() { + // Already opening. + } + + @Override + public void gateFinishedOpening() { + gate.setGateState(gate.getGateOpenState()); + } + + @Override + public void gateFinishedClosing() { + // not reachable except through error. + // Raise an alarm!! + } + + @Override + public void operate() { + gate.open(); + // Flash lights.. + } + + @Override + public String getTrafficAction() { + return "STOP"; + } + +} diff --git a/hw5/application/model/infrastructure/gate/IGateState.java b/hw5/application/model/infrastructure/gate/IGateState.java new file mode 100644 index 00000000..e5ac514b --- /dev/null +++ b/hw5/application/model/infrastructure/gate/IGateState.java @@ -0,0 +1,15 @@ +package application.model.infrastructure.gate; + +/** + * Declares all operations that GateState classes must implement + * @author jane + * + */ +public interface IGateState { + public void approachStation(); + public void leaveStation(); + public void gateFinishedOpening(); + public void gateFinishedClosing(); + public void operate(); + public String getTrafficAction(); +} diff --git a/hw5/application/model/infrastructure/vehicles/Car.java b/hw5/application/model/infrastructure/vehicles/Car.java new file mode 100644 index 00000000..bfa13496 --- /dev/null +++ b/hw5/application/model/infrastructure/vehicles/Car.java @@ -0,0 +1,118 @@ +package application.model.vehicles; + +import java.util.Observable; +import java.util.Observer; + +import application.model.infrastructure.gate.CrossingGate; +import application.view.CarImageSelector; +import javafx.scene.Node; +import javafx.scene.image.ImageView; + +/** + * Represents Car object + * @author jane + * + */ +public class Car extends Observable implements IVehicle, Observer{ + private ImageView ivCar; + private double currentX = 0; + private double currentY = 0; + private double originalY = 0; + private boolean gateDown = false; + private double leadCarY = -1; // Current Y position of car directly infront of this one + private double speed = 0.5; + + /** + * Constructor + * @param x initial x coordinate of car + * @param y initial y coordinate of car + */ + public Car(int x, int y){ + this.currentX = x; + this.currentY = y; + originalY = y; + ivCar = new ImageView(CarImageSelector.getImage()); + ivCar.setX(getVehicleX()); + ivCar.setY(getVehicleY()); + } + + @Override + public Node getImageView() { + return ivCar; + } + + public boolean gateIsClosed(){ + return gateDown; + } + + public double getVehicleX(){ + return currentX; + } + public double getVehicleY(){ + return currentY; + } + + public void move(){ + boolean canMove = true; + + // First case. Car is at the front of the stopping line. + if (gateDown && getVehicleY() < 430 && getVehicleY()> 390) + canMove = false; + + // Second case. Car is too close too other car. + if (leadCarY != -1 && getDistanceToLeadCar() < 50) + canMove = false; + + if (canMove){ + currentY+=speed; + ivCar.setY(currentY); + setChanged(); + notifyObservers(); + } + } + + public void setSpeed(double speed){ + this.speed = speed; + } + + public void setGateDownFlag(boolean gateDown){ + this.gateDown = gateDown; + } + + public boolean offScreen(){ + if (currentY > 1020) + return true; + else + return false; + } + + public void reset(){ + currentY = originalY; + } + + public double getDistanceToLeadCar(){ + return Math.abs(leadCarY-getVehicleY()); + } + + public void removeLeadCar(){ + leadCarY = -1; + } + + @Override + public void update(Observable o, Object arg1) { + if (o instanceof Car){ + leadCarY = (((Car)o).getVehicleY()); + if (leadCarY > 1020) + leadCarY = -1; + } + + if (o instanceof CrossingGate){ + CrossingGate gate = (CrossingGate)o; + if(gate.getTrafficCommand()=="STOP") + gateDown = true; + else + gateDown = false; + + } + } +} diff --git a/hw5/application/model/infrastructure/vehicles/CarFactory.java b/hw5/application/model/infrastructure/vehicles/CarFactory.java new file mode 100644 index 00000000..28f3e0c5 --- /dev/null +++ b/hw5/application/model/infrastructure/vehicles/CarFactory.java @@ -0,0 +1,75 @@ +package application.model.vehicles; + +import java.awt.Point; +import java.util.ArrayList; +import java.util.Collection; + +import application.model.infrastructure.Direction; +import application.model.infrastructure.gate.CrossingGate; + + +/** + * Very basic car factory. Creates the car and registers it with the crossing gate and the car infront of it. + * @author jane + * + */ +public class CarFactory { + + private Collection gates = null; + private Car previousCar = null; + private ArrayList cars = new ArrayList(); + Direction direction; + Point location; + + public CarFactory(){} + + public CarFactory(Direction direction, Point location, Collection gates){ + this.direction = direction; + this.location = location; + this.gates = gates; + } + + + // Most code here is to create random speeds + public Car buildCar(){ + if (previousCar == null || location.y < previousCar.getVehicleY()-100){ + Car car = new Car(location.x,location.y); + double speedVariable = (Math.random() * 10)/10; + car.setSpeed((2-speedVariable)*.75); + + // All cars created by this factory must be aware of crossing gates in the road + for(CrossingGate gate: gates){ + gate.addObserver(car); + if(gate != null && gate.getTrafficCommand()=="STOP") + car.setGateDownFlag(false); + } + + // Each car must observe the car infront of it so it doesn't collide with it. + if (previousCar != null) + previousCar.addObserver(car); + previousCar = car; + + cars.add(car); + return car; + } else + return null; + } + + // We will get a concurrency error if we try to delete cars whilst iterating through the array list + // so we perform this in two stages. + // 1. Loop through the list and identify which cars are off the screen. Add them to 'toDelete' array. + // 2. Iterate through toDelete and remove the cars from the original arrayList. + public ArrayList removeOffScreenCars() { + // Removing cars from the array list. + ArrayList toDelete = new ArrayList(); + for(Car car: cars){ + car.move(); + if (car.offScreen()) + toDelete.add(car); + + } + for (Car car: toDelete) + cars.remove(car); + return toDelete; + } +} diff --git a/hw5/application/model/infrastructure/vehicles/IVehicle.java b/hw5/application/model/infrastructure/vehicles/IVehicle.java new file mode 100644 index 00000000..5f84eae0 --- /dev/null +++ b/hw5/application/model/infrastructure/vehicles/IVehicle.java @@ -0,0 +1,13 @@ +package application.model.vehicles; + +import javafx.scene.Node; + + +public interface IVehicle { + public Node getImageView(); + public double getVehicleX(); + public double getVehicleY(); + public void move(); + public boolean offScreen(); + public void reset(); +} diff --git a/hw5/application/model/infrastructure/vehicles/Train.java b/hw5/application/model/infrastructure/vehicles/Train.java new file mode 100644 index 00000000..4b9f6a41 --- /dev/null +++ b/hw5/application/model/infrastructure/vehicles/Train.java @@ -0,0 +1,86 @@ +package application.model.vehicles; + +import java.util.Observable; + +import javafx.scene.Node; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +/** + * Represents the train entity object + * @author jane + * + */ +public class Train extends Observable implements IVehicle{ + private double currentX = 0; + private double currentY = 0; + private double originalX = 0; + private Image img; + private ImageView imgView; + private int trainLength = 35; + + private int direction = 0; + + public Train(int x, int y){ + this.currentX = x; + this.currentY = y; + originalX = x; + img = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/hw5/application/Images/Train.PNG",120,trainLength,false,false); + imgView = new ImageView(img); + imgView.setX(currentX); + imgView.setY(currentY); + } + + public double getVehicleX(){ + return currentX; + } + + public double getVehicleY(){ + return currentY; + } + + public void move(){ + currentX-=2; + imgView.setX(currentX); + setChanged(); + notifyObservers(); + } + + public void moveEast() { + currentX+=2; + imgView.setX(currentX); + setChanged(); + notifyObservers(); + } + + public boolean offScreen(){ + if (currentX < -200) + return true; + else + return false; + } + + public boolean offScreenEast() { + if (currentX > 1200) + return true; + else + return false; + } + + public void reset(){ + currentX = originalX; + } + + //@Override + public Node getImageView() { + return imgView; + } + + public void setDirection(int direct) { + this.direction = direct; + } + + public int getDirection() { + return this.direction; + } +} diff --git a/hw5/application/view/CarImageSelector.java b/hw5/application/view/CarImageSelector.java new file mode 100644 index 00000000..c6441a24 --- /dev/null +++ b/hw5/application/view/CarImageSelector.java @@ -0,0 +1,23 @@ +package application.view; + +import javafx.scene.image.Image; + +public class CarImageSelector { + + + public static Image getImage(){ + int imageSize = 20; + int pickNum = (int)(Math.random() * 4); + Image img; + switch(pickNum){ + case 0: img = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/hw5/application/Images/bluecar.PNG",imageSize,imageSize,false,true); + break; + case 2: img = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/hw5/application/Images/graycar.PNG",imageSize,imageSize,false,true); + break; + case 3: img = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/hw5/application/Images/greencar.PNG",imageSize,imageSize,false,true); + break; + default: img = new Image("file:/Users/Dchao88/git/SoftwareEngineering2018/hw5/application/Images/redcar.PNG",imageSize,imageSize,false,true); + } + return img; + } +} diff --git a/hw5/application/view/IDisplay.java b/hw5/application/view/IDisplay.java new file mode 100644 index 00000000..a165366b --- /dev/null +++ b/hw5/application/view/IDisplay.java @@ -0,0 +1,5 @@ +package application.view; + +public interface IDisplay { + public void draw(); +} diff --git a/hw5/application/view/MapDisplay.java b/hw5/application/view/MapDisplay.java new file mode 100644 index 00000000..e73b453b --- /dev/null +++ b/hw5/application/view/MapDisplay.java @@ -0,0 +1,53 @@ +package application.view; + +import java.util.ArrayList; +import java.util.Collection; + +import application.model.infrastructure.RailwayTracks; +import application.model.infrastructure.Road; +import application.model.infrastructure.gate.CrossingGate; +import application.model.vehicles.Car; +import javafx.scene.layout.Pane; + +/** + * Called by JavaFX main UI thread to help display elements on the UI + * @author jane + * + */ +public class MapDisplay { + Pane root; + IDisplay roadDisplay, tracksDisplay; + Collection roads; + Collection track; + Collection gates; + + + public MapDisplay(Pane root, Collection roads, Collection tracks, Collection gates){ + this.root = root; + this.roads= roads; + this.track = tracks; + this.gates = gates; + roadDisplay = new RoadDisplay(roads,root); + tracksDisplay = new TracksDisplay(tracks,root); + } + + public void drawTracks(){ + tracksDisplay.draw(); + } + + public void drawRoad(){ + roadDisplay.draw(); + } + + public void drawGate(){ + for (CrossingGate gate: gates) + root.getChildren().add(gate.getGateLine()); + } + + + public void removeCarImages(ArrayList junkCars) { + for(Car car: junkCars) + root.getChildren().remove(car.getImageView()); + + } +} diff --git a/hw5/application/view/RoadDisplay.java b/hw5/application/view/RoadDisplay.java new file mode 100644 index 00000000..d70a8bd6 --- /dev/null +++ b/hw5/application/view/RoadDisplay.java @@ -0,0 +1,50 @@ +package application.view; + +import java.util.Collection; + +import application.model.infrastructure.Direction; +import application.model.infrastructure.Road; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Line; + + +/** + * Draws a road + * @author jane + * + */ +public class RoadDisplay implements IDisplay { + Pane root; + Collection roads; + int roadSize; + + + public RoadDisplay(Collection roads, Pane root){ + this.root = root; + this.roads = roads; + + } + + @Override + public void draw() { + for(Road road: roads){ + roadSize = road.getRoadWidth(); + if (road.getDirection() == Direction.NORTH || road.getDirection() == Direction.SOUTH) { + root.getChildren().add(new Line(road.getStartX()-roadSize,road.getStartY(),road.getEndX()-roadSize,road.getEndY())); + root.getChildren().add(new Line(road.getStartX()+roadSize,road.getStartY(),road.getEndX()+roadSize,road.getEndY())); + } else { + root.getChildren().add(new Line(road.getStartX(),road.getStartY()-roadSize,road.getEndX(),road.getEndY()-roadSize)); + root.getChildren().add(new Line(road.getStartX(),road.getStartY()+roadSize,road.getEndX(),road.getEndY()+roadSize)); + if (road.getClearEnds()){ + Line line = new Line(road.getStartX(),road.getStartY()-roadSize,road.getStartX(),road.getStartY()+roadSize); + line.setStroke(Color.WHITE); + root.getChildren().add(line); + Line line2 = new Line(road.getEndX(),road.getEndY()-roadSize,road.getEndX(),road.getEndY()+roadSize); + line2.setStroke(Color.WHITE); + root.getChildren().add(line2); + } + } + } + } +} diff --git a/hw5/application/view/TracksDisplay.java b/hw5/application/view/TracksDisplay.java new file mode 100644 index 00000000..ec2931ed --- /dev/null +++ b/hw5/application/view/TracksDisplay.java @@ -0,0 +1,35 @@ +package application.view; + +import java.util.Collection; + +import application.model.infrastructure.RailwayTracks; +import javafx.scene.layout.Pane; +import javafx.scene.shape.Line; + + +/** + * Draws a track + * @author jane + * + */ +public class TracksDisplay implements IDisplay { + Pane root; + Collection tracks; + int trackSize = 16; + + public TracksDisplay(Collection tracks, Pane root){ + this.root = root; + this.tracks = tracks; + } + + @Override + public void draw() { + for(RailwayTracks track: tracks){ + root.getChildren().add(new Line(track.getStartX(),track.getStartY()-trackSize,track.getEndX(),track.getEndY()-trackSize)); + root.getChildren().add(new Line(track.getStartX(),track.getStartY()+trackSize,track.getEndX(),track.getEndY()+trackSize)); + for(int j = track.getStartX()+(trackSize/2); j < track.getEndX(); j+=trackSize){ + root.getChildren().add(new Line(j,track.getStartY()-trackSize - 2,j,track.getEndY()+trackSize+2)); + } + } + } +} diff --git a/src/edu/nd/se2018/homework/ColumbusGame/Images/ColumbusShip.png b/src/edu/nd/se2018/homework/ColumbusGame/Images/ColumbusShip.png new file mode 100644 index 00000000..ab23f309 Binary files /dev/null and b/src/edu/nd/se2018/homework/ColumbusGame/Images/ColumbusShip.png differ diff --git a/src/edu/nd/se2018/homework/ColumbusGame/Images/pirateship.gif b/src/edu/nd/se2018/homework/ColumbusGame/Images/pirateship.gif new file mode 100644 index 00000000..c3bbfa28 Binary files /dev/null and b/src/edu/nd/se2018/homework/ColumbusGame/Images/pirateship.gif differ diff --git a/src/edu/nd/se2018/homework/ColumbusGame/Reflection.md b/src/edu/nd/se2018/homework/ColumbusGame/Reflection.md new file mode 100644 index 00000000..4865742e --- /dev/null +++ b/src/edu/nd/se2018/homework/ColumbusGame/Reflection.md @@ -0,0 +1,14 @@ +Much of what I liked about the design of my solution really revolves around actually enjoying the deployment of the game itself: +although it is a very simple event driven program, with a simpler yet GUI, it still gives me the same childhood happiness that I +had when I wrote my first hello world. A lot of this stems from how quickly you can see and update changes, and how much video +games drove my love for coding. Though that does not speak directly to the actual design of the classes, I think it more so +speaks to my learning process: these designs are still novel to me and they feel like they are being discovered, and that’s still +incredibly fun to me. As far as the actual designs are concerned, I really liked the communication between observer and observed +objects (although this wasn’t truly implemented by me): the modularity of the events (i.e. the observer simply knows to update +and a separate event queue need not be implemented (at least directly) by me) is very nice, and the event loop contained within +OceanExplorer was straight forward enough because of the modularity of the underlying “pieces” (i.e. Ship, PirateShip, OceanMap). +As far as the first stretch is concerned, the implementation would be simple enough in containing it all within two while loops, +that when the button is pressed, breaks out of the first loop, causing the outer loop to iterate and recall the initialization +methods for the game and creating a new game. The replacement of ocean/land tiles with ocean/land images would also be fairly +straightforward, as instead of them simple being a rectangle class we could add an imageview class of that size, and then +subsequently utilize the same methods used to initialize the ship images and do the same in the board initialization loop. diff --git a/src/edu/nd/se2018/homework/ColumbusGame/homework3 UML.pdf b/src/edu/nd/se2018/homework/ColumbusGame/homework3 UML.pdf new file mode 100644 index 00000000..65d79f58 Binary files /dev/null and b/src/edu/nd/se2018/homework/ColumbusGame/homework3 UML.pdf differ diff --git a/src/edu/nd/se2018/homework/ColumbusGame/src/OceanExplorer.java b/src/edu/nd/se2018/homework/ColumbusGame/src/OceanExplorer.java new file mode 100644 index 00000000..8d62c656 --- /dev/null +++ b/src/edu/nd/se2018/homework/ColumbusGame/src/OceanExplorer.java @@ -0,0 +1,94 @@ +import javafx.application.Application; +import javafx.event.EventHandler; +import javafx.stage.Stage; +import javafx.scene.Scene; +import javafx.scene.layout.*; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.KeyEvent; + +public class OceanExplorer extends Application +{ + final int scale = 25; + public static void main(String[] args) + { + // TODO Auto-generated method stub + launch(args); + } + + @Override + public void start(Stage oceanStage) throws Exception + { + // Generate New Pane + AnchorPane root = new AnchorPane(); + Scene scene = new Scene(root, 625, 625); + oceanStage.setScene(scene); + oceanStage.setTitle("My Island"); + + OceanMap map = new OceanMap(); + map.drawMap(root.getChildren(), scale); + oceanStage.show(); + + // Instantiate Ship + Ship ship = new Ship(); + + // Draw the Ship + Image shipImage = new Image("file:/Users/Dchao88/Documents/Software Engineering/ColumbusGame/src/Images/ColumbusShip.png", 25, 25, true, true); + ImageView shipImageView = new ImageView(shipImage); + shipImageView.setX(ship.getShipLocation().getX()); + shipImageView.setY(ship.getShipLocation().getY()); + root.getChildren().add(shipImageView); + + // Generate Pirates + PirateShip pirate1 = new PirateShip(scale); + PirateShip pirate2 = new PirateShip(scale); + + ship.addObserver(pirate1); + ship.addObserver(pirate2); + root.getChildren().add(pirate1.getImageView()); + root.getChildren().add(pirate2.getImageView()); + + + startSailing(scene, ship, shipImageView, map); + } + + private void startSailing(Scene scene, Ship ship, ImageView shipImageView, OceanMap map) + { + scene.setOnKeyPressed(new EventHandler() + { + //@Override + public void handle(KeyEvent ke) + { + switch (ke.getCode()) + { + case RIGHT: + if (map.getStatus((int)ship.getShipLocation().getX()+1, (int)ship.getShipLocation().getY()) != 1) + ship.goEast(); + break; + + case LEFT: + if (map.getStatus((int)ship.getShipLocation().getX()-1, (int)ship.getShipLocation().getY()) != 1) + ship.goWest(); + break; + + case UP: + if (map.getStatus((int)ship.getShipLocation().getX(), (int)ship.getShipLocation().getY()-1) != 1) + ship.goNorth(); + break; + + case DOWN: + if (map.getStatus((int)ship.getShipLocation().getX(), (int)ship.getShipLocation().getY()+1) != 1) + ship.goSouth(); + break; + + default: + break; + } + shipImageView.setX(ship.getShipLocation().getX()*scale); + shipImageView.setY(ship.getShipLocation().getY()*scale); + } + }); + + } + +} diff --git a/src/edu/nd/se2018/homework/ColumbusGame/src/OceanMap.java b/src/edu/nd/se2018/homework/ColumbusGame/src/OceanMap.java new file mode 100644 index 00000000..54d22243 --- /dev/null +++ b/src/edu/nd/se2018/homework/ColumbusGame/src/OceanMap.java @@ -0,0 +1,46 @@ +import javafx.collections.ObservableList; +import javafx.scene.shape.Rectangle; +import javafx.scene.Node; +import javafx.scene.paint.Color; +import java.util.Random; + +public class OceanMap +{ + int[][] oceanGrid = new int[25][25]; + final int dimensions = 25; + + public void drawMap(ObservableList root, int scale) + { + for (int z = 0; z < 10; z++) + { + Random rand = new Random(); + int x = rand.nextInt(dimensions); + int y = rand.nextInt(dimensions); + + oceanGrid[x][y] = 1; + } + + for (int x = 0; x < dimensions; x++) + { + for (int y = 0; y < dimensions; y++) + { + Rectangle rect = new Rectangle(x * scale, y * scale, scale, scale); + rect.setStroke(Color.BLACK); + if (oceanGrid[x][y] != 1) + { + oceanGrid[x][y] = 0; + rect.setFill(Color.PALETURQUOISE); + } + else + rect.setFill(Color.FORESTGREEN); + + root.add(rect); + } + } + } + + public int getStatus(int x, int y) + { + return oceanGrid[x][y]; + } +} diff --git a/src/edu/nd/se2018/homework/ColumbusGame/src/PirateShip.java b/src/edu/nd/se2018/homework/ColumbusGame/src/PirateShip.java new file mode 100644 index 00000000..4875b937 --- /dev/null +++ b/src/edu/nd/se2018/homework/ColumbusGame/src/PirateShip.java @@ -0,0 +1,68 @@ +import java.util.Observable; +import java.util.Observer; +import java.awt.Point; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import java.util.Random; +import java.lang.Math; + +public class PirateShip implements Observer +{ + Point piratePosition; + Point columbusPosition; + Random rand = new Random(); + ImageView pirateImageView; + Image pirateImage; + int scale; + + public PirateShip(int Scale) + { + piratePosition = new Point(Math.floorDiv(rand.nextInt(625), 25), Math.floorDiv(rand.nextInt(625), 25)); + pirateImage = new Image("file:/Users/Dchao88/Documents/Software Engineering/ColumbusGame/src/Images/pirateship.gif", 25, 25, true, true); + pirateImageView = new ImageView(pirateImage); + pirateImageView.setX(24); + pirateImageView.setY(24); + scale = Scale; + } + + public void setPosition(int x, int y) + { + pirateImageView.setX(x); + piratePosition.x = x; + pirateImageView.setY(y); + piratePosition.y = y; + } + + public ImageView getImageView() + { + return pirateImageView; + } + + public void movePirate() + { + if (columbusPosition.getX() - piratePosition.getX() > 0) + piratePosition.x += 1*scale; + else + piratePosition.x += 1*scale; + if (columbusPosition.getY() - piratePosition.getY() > 0) + piratePosition.y += 1*scale; + else + piratePosition.y += 1*scale; + + pirateImageView.setX(piratePosition.getX()); + pirateImageView.setX(piratePosition.getY()); + + } + + @Override + public void update(Observable o, Object arg) + { + // TODO Auto-generated method stub + if (o instanceof Ship) + { + columbusPosition = ((Ship)o).getShipLocation(); + movePirate(); + } + } + +} diff --git a/src/edu/nd/se2018/homework/ColumbusGame/src/Ship.java b/src/edu/nd/se2018/homework/ColumbusGame/src/Ship.java new file mode 100644 index 00000000..8faa38e5 --- /dev/null +++ b/src/edu/nd/se2018/homework/ColumbusGame/src/Ship.java @@ -0,0 +1,50 @@ +import java.awt.Point; +import java.util.Observable; +import java.util.Observer; + +public class Ship extends Observable +{ + Point currentLocation = new Point(); + + public Ship() + { + currentLocation.setLocation(0, 0);; + } + + public Point getShipLocation() + { + return currentLocation; + } + + public void goEast() + { + if (currentLocation.getX()+1 <= 24) + currentLocation.setLocation(currentLocation.getX()+1, currentLocation.getY()); + setChanged(); + notifyObservers(); + } + + public void goWest() + { + if (currentLocation.getX()-1 >= 0) + currentLocation.setLocation(currentLocation.getX()-1, currentLocation.getY()); + setChanged(); + notifyObservers(); + } + + public void goNorth() + { + if (currentLocation.getY()-1 >= 0) + currentLocation.setLocation(currentLocation.getX(), currentLocation.getY()-1); + setChanged(); + notifyObservers(); + } + + public void goSouth() + { + if (currentLocation.getY()+1 <= 24) + currentLocation.setLocation(currentLocation.getX(), currentLocation.getY()+1); + setChanged(); + notifyObservers(); + } +} diff --git a/src/edu/nd/se2018/homework/hwk1/Question1.java b/src/edu/nd/se2018/homework/hwk1/Question1.java index d990b3b1..332c9fac 100644 --- a/src/edu/nd/se2018/homework/hwk1/Question1.java +++ b/src/edu/nd/se2018/homework/hwk1/Question1.java @@ -1,10 +1,21 @@ package edu.nd.se2018.homework.hwk1; +import java.util.HashSet; + public class Question1 { public Question1(){} public int getSumWithoutDuplicates(int[] numbers){ - return 0; + int sum = 0; + HashSet checked = new HashSet(); + + for (int x = 0; x < numbers.length; x++) + { + if (checked.add(numbers[x])) + sum += numbers[x]; + } + + return sum; } } diff --git a/src/edu/nd/se2018/homework/hwk1/Question2.java b/src/edu/nd/se2018/homework/hwk1/Question2.java index b04a7f86..726c6a24 100644 --- a/src/edu/nd/se2018/homework/hwk1/Question2.java +++ b/src/edu/nd/se2018/homework/hwk1/Question2.java @@ -1,10 +1,47 @@ package edu.nd.se2018.homework.hwk1; +import java.util.HashMap; + public class Question2 { public Question2(){} public String getMostFrequentWord(String input, String stopwords){ - return ""; + HashMap frequencies = new HashMap(); + int max = 0; + String mostFrequent = null; + + for (String word: input.split(" ")) + { + if (!frequencies.containsKey(word)) + frequencies.put(word, 1); + else + frequencies.put(word, frequencies.get(word) + 1); + } + + for (String stopWord: stopwords.split(" ")) + { + for (String word: frequencies.keySet()) + { + if (word.equals(stopWord) && frequencies.get(word) != 0) + { + frequencies.put(word, 0); + break; + } + } + } + + for (String word: frequencies.keySet()) + { + if (frequencies.get(word) > max) + { + max = frequencies.get(word); + mostFrequent = word; + } + else if (frequencies.get(word) == max) + mostFrequent = null; + } + + return mostFrequent; } } diff --git a/src/edu/nd/se2018/homework/hwk1/Question3.java b/src/edu/nd/se2018/homework/hwk1/Question3.java index 740d282c..3d621829 100644 --- a/src/edu/nd/se2018/homework/hwk1/Question3.java +++ b/src/edu/nd/se2018/homework/hwk1/Question3.java @@ -4,6 +4,28 @@ public class Question3 { public Question3(){} public int getMirrorCount(int[] numbers){ - return 0; + int front = 0; + int back = numbers.length - 1; + + if (numbers.length == 0) + return 0; + + int mirrorCount = 0; + + while (front < numbers.length && back >= 0) + { + if (numbers[front] == numbers[back]) + mirrorCount++; + else + break; + + front++; + back--; + } + + if (mirrorCount == 0) + return 1; + else + return mirrorCount; } } diff --git a/src/edu/nd/se2018/homework/hwk2/EarlySprinter.java b/src/edu/nd/se2018/homework/hwk2/EarlySprinter.java new file mode 100644 index 00000000..01f39d38 --- /dev/null +++ b/src/edu/nd/se2018/homework/hwk2/EarlySprinter.java @@ -0,0 +1,13 @@ +package edu.nd.se2018.homework.hwk2; + +public class EarlySprinter implements Strategy +{ + @Override + public double runLap(double maxSpeed, int lapsRun) + { + if (lapsRun < 2) + return (double)maxSpeed; + else + return (double)maxSpeed*.75; + } +} \ No newline at end of file diff --git a/src/edu/nd/se2018/homework/hwk2/Horse.java b/src/edu/nd/se2018/homework/hwk2/Horse.java new file mode 100644 index 00000000..58a471c2 --- /dev/null +++ b/src/edu/nd/se2018/homework/hwk2/Horse.java @@ -0,0 +1,29 @@ +package edu.nd.se2018.homework.hwk2; + +public class Horse +{ + private Strategy strategy; + private String name; + private double maxSpeed; + + public Horse(String Name, int speed) + { + this.maxSpeed = (double)speed/3600; + this.name = Name; + } + + public void setStrategy(Strategy Strategy) + { + this.strategy = Strategy; + } + + public double run(int lapsRun) + { + return strategy.runLap(this.maxSpeed, lapsRun); + } + + public String getName() + { + return this.name; + } +} \ No newline at end of file diff --git a/src/edu/nd/se2018/homework/hwk2/Main.java b/src/edu/nd/se2018/homework/hwk2/Main.java new file mode 100644 index 00000000..46ecf83d --- /dev/null +++ b/src/edu/nd/se2018/homework/hwk2/Main.java @@ -0,0 +1,16 @@ +package edu.nd.se2018.homework.hwk2; + +public class Main +{ + + public static void main(String args[]) + { + Race race = new Race(); + + race.addHorse("Equestrian 1", 20, "EarlySprinter"); + race.addHorse("Equestrian 2", 20, "SteadyRunner"); + race.addHorse("Equestrian 3", 22, "SlowStarter"); + + race.runRace(); + } +} \ No newline at end of file diff --git a/src/edu/nd/se2018/homework/hwk2/Race.java b/src/edu/nd/se2018/homework/hwk2/Race.java new file mode 100644 index 00000000..b30d6b75 --- /dev/null +++ b/src/edu/nd/se2018/homework/hwk2/Race.java @@ -0,0 +1,96 @@ +package edu.nd.se2018.homework.hwk2; +import java.util.HashMap; +import java.lang.*; +import java.text.DecimalFormat; + +public class Race +{ + public Race(){} + private int totalHorses = 0; + private HashMap distanceRan = new HashMap(); + private HashMap Horses = new HashMap(); + + + public void addHorse(String name, int maxSpeed, String Strategy) + { + if (this.totalHorses < 5) + { + if (maxSpeed == 0) + { + System.out.println(name + " doesn\'t want to run!"); + return; + } + else if (maxSpeed <= 0) + { + System.out.println(name + " is running backwards off the track!"); + return; + } + Horse newHorse = new Horse(name, maxSpeed); + if (Strategy.equals("EarlySprinter")) + { + EarlySprinter horseStrategy = new EarlySprinter(); + newHorse.setStrategy(horseStrategy); + } + else if (Strategy.equals("SteadyRunner")) + { + SteadyRunner horseStrategy = new SteadyRunner(); + newHorse.setStrategy(horseStrategy); + } + else if (Strategy.equals("SlowStarter")) + { + SlowStarter horseStrategy = new SlowStarter(); + newHorse.setStrategy(horseStrategy); + } + this.totalHorses += 1; + distanceRan.put(newHorse.getName(), 0.0); + Horses.put(newHorse.getName(), newHorse); + } + } + + public void runRace() + { + int seconds = 1; + boolean finished = false; + boolean tie = false; + String winner = ""; + + + while (!finished) + { + for (String horse: Horses.keySet()) + { + int lapCounter = (int)Math.floor(distanceRan.get(horse)); + double newDistance = distanceRan.get(horse) + Horses.get(horse).run(lapCounter); + distanceRan.put(horse, newDistance); + + if (newDistance >= 10) + { + if (finished || tie) + { + winner = winner + " and " + Horses.get(horse).getName(); + tie = true; + } + else + winner = Horses.get(horse).getName(); + finished = true; + } + } + + if ((seconds % 150) == 0) + { + for (String horse: Horses.keySet()) + { + String output = new DecimalFormat("#.##").format(distanceRan.get(horse)); + System.out.println(horse + " has run " + output + " miles"); + } + + } + seconds += 1; + } + + if (tie) + System.out.println("It's a tie! " + winner + " are the winners!"); + else + System.out.println(winner + " is the winner!"); + } +} \ No newline at end of file diff --git a/src/edu/nd/se2018/homework/hwk2/SlowStarter.java b/src/edu/nd/se2018/homework/hwk2/SlowStarter.java new file mode 100644 index 00000000..bb69aaee --- /dev/null +++ b/src/edu/nd/se2018/homework/hwk2/SlowStarter.java @@ -0,0 +1,15 @@ +package edu.nd.se2018.homework.hwk2; + +public class SlowStarter implements Strategy +{ + @Override + public double runLap(double maxSpeed, int lapsRun) + { + if (lapsRun < 5) + return (double)maxSpeed*.6; + else if (lapsRun < 9) + return (double)maxSpeed*.9; + else + return (double)maxSpeed*1; + } +} \ No newline at end of file diff --git a/src/edu/nd/se2018/homework/hwk2/SteadyRunner.java b/src/edu/nd/se2018/homework/hwk2/SteadyRunner.java new file mode 100644 index 00000000..7b2e6467 --- /dev/null +++ b/src/edu/nd/se2018/homework/hwk2/SteadyRunner.java @@ -0,0 +1,10 @@ +package edu.nd.se2018.homework.hwk2; + +public class SteadyRunner implements Strategy +{ + @Override + public double runLap(double maxSpeed, int lapsRun) + { + return (double)maxSpeed*.8; + } +} \ No newline at end of file diff --git a/src/edu/nd/se2018/homework/hwk2/Strategy.java b/src/edu/nd/se2018/homework/hwk2/Strategy.java new file mode 100644 index 00000000..440583a7 --- /dev/null +++ b/src/edu/nd/se2018/homework/hwk2/Strategy.java @@ -0,0 +1,6 @@ +package edu.nd.se2018.homework.hwk2; + +public interface Strategy +{ + public double runLap(double maxSpeed, int lapsRun); +} \ No newline at end of file diff --git a/src/edu/nd/se2018/homework/hwk2/TestRace.java b/src/edu/nd/se2018/homework/hwk2/TestRace.java new file mode 100644 index 00000000..9a2055a5 --- /dev/null +++ b/src/edu/nd/se2018/homework/hwk2/TestRace.java @@ -0,0 +1,40 @@ +package edu.nd.se2018.homework.hwk2; +import org.junit.Test; + +public class TestRace +{ + @Test + public void Test() + { + Race case1 = new Race(); // Standard test case to assess functionality + + case1.addHorse("Divine Providence", 25, "EarlySprinter"); + case1.addHorse("Speed Demon", 25, "SteadyRunner"); + case1.addHorse("American Pharoah", 28, "SlowStarter"); + case1.addHorse("Sea Biscuit", 25, "SlowStarter"); + case1.addHorse("Rear Gunner", 25, "EarlySprinter"); + + case1.runRace(); + System.out.println(""); + + Race case2 = new Race(); // Test case for tie event + + case2.addHorse("War Admiral", 25, "EarlySprinter"); + case2.addHorse("Circus Act", 24, "SlowStarter"); + case2.addHorse("American Pharoah", 25, "EarlySprinter"); + case2.addHorse("Sea Biscuit", 23, "SlowStarter"); + case2.addHorse("Secretariat", 25, "EarlySprinter"); + + case2.runRace(); + + System.out.println(""); + Race case3 = new Race(); // Test case for "null rider", or 0/negative initial speed + + case3.addHorse("2Sigma", 25, "EarlySprinter"); + case3.addHorse("Pariveda", 25, "SteadyRunner"); + case3.addHorse("Jane Street", 0, "SlowStarter"); + case3.addHorse("Deloitte", -25, "SlowStarter"); + + case3.runRace(); + } +} \ No newline at end of file diff --git a/src/edu/nd/se2018/homework/hwk2/hwk2 UML Diagram.pdf b/src/edu/nd/se2018/homework/hwk2/hwk2 UML Diagram.pdf new file mode 100644 index 00000000..3f556bee Binary files /dev/null and b/src/edu/nd/se2018/homework/hwk2/hwk2 UML Diagram.pdf differ diff --git a/src/edu/nd/se2018/homework/hwk2/reflection.md b/src/edu/nd/se2018/homework/hwk2/reflection.md new file mode 100644 index 00000000..b00739ef --- /dev/null +++ b/src/edu/nd/se2018/homework/hwk2/reflection.md @@ -0,0 +1,12 @@ +When designing my solution, I wanted to keep the actual racer (horse) implementation/code as simple as possible, having it be a modular +piece utilized by race rather than doing a majority of the work in that class. I chose to implement a strategy interface (Strategy) +with a context class (Horse) in order to limit both duplicated code and “workload” done within the actual racer class. I then had +a worker, or overseer, class (Race) which would manage the actual running of the simulation, and which would house the control loop +for the race. In housing this control loop separate of the racer classes, I felt it logically mimicked what was actually happening +in a real race: each racer operates on its own (individual instances of a class) but are all participating in the same race context +(control class Race) and are subject to that race and that race only (i.e. not all horses need finish before the race is concluded). +In order to quickly handle distance tracking and speed manipulation, I utilized two HashMaps, linked by their key sets (both maps were +linked to the same horse name as their key), in order to update overall position based on elapsed time, and access the strategy and +subsequently the “advance” method (runLap). Since the workload (control loop, strategy parsing/setting, etc.) was all contained to +the Race class, the implementation of the strategies and subsequently the context class was minimal, allowing for easy understanding +and manipulation to properly run the race within the control class.