diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..24957dce42144cc115095b85bb08b4dcbdca5642 Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/Player.java b/src/Player.java new file mode 100644 index 0000000000000000000000000000000000000000..19885d79a8463130c6673f0eb9bed094c4786f6f --- /dev/null +++ b/src/Player.java @@ -0,0 +1,116 @@ +import bagel.DrawOptions; +import bagel.Font; +import bagel.Image; +import bagel.util.Colour; +import bagel.util.Point; +/** + * a movable entity: player + */ +public class Player{ + /** + * Distance per move + */ + private static final double STEPSIZE = 10; + /** + * energy level threshold + */ + private static final int ENERGYTHRE = 3; + /** + * set the font style for energy display + */ + private static final Font FONT = new Font("res/font/DejaVuSans-Bold.ttf", 20); + private static final DrawOptions OPT = new DrawOptions(); + /** + * the player's image displayed in the window + */ + private final Image image; + /** + * render position of the player in the window + */ + private Point pos; + /** + * Player's current energy value + */ + private int energy; + + /** + * constructor + * @param x abscissa + * @param y ordinate + * @param energy energy value + */ + public Player(double x, double y, int energy) { + this.image = new Image("res/images/player.png"); + this.pos = new Point(x,y); + this.energy = energy; + } + /** + * get the player's postion + * @return a Point object representing the player's position + */ + public Point getPos() { + return this.pos; + } + /** + * get the player's current energy value + * @return the player's current energy value + */ + public int getEnergy() { + return this.energy; + } + /** + * Move one step to the target point + * @param dest target point + */ + public void moveTo(Point dest){ + double x = dest.x-this.pos.x; + double y = dest.y-this.pos.y; + double length = Math.sqrt(x*x+y*y);//The distance between two points + //Update coordinate points according to direction and step size + this.pos = new Point(this.getPos().x+STEPSIZE*x/length,this.getPos().y+STEPSIZE*y/length); + } + /** + * Check if the player meets the Zombie and if so reduce energy by 3 and + * terminate. Otherwise if the player meets the Sandwich increase the energy + * an set the Sandwich to invisible.Then make players to the designated direction + * @param tomb need a shadowtree object to get zombies and sandwiches + */ + public void update(ShadowTreasure tomb){ + // set direction + if (this.energy >= ENERGYTHRE){ + moveTo(tomb.getZombie().getPos());// direction to zombie + } else{ + moveTo(tomb.getSandwich().getPos());// direction to sandwich + } + //meet zombies + if (tomb.getZombie().isMeet(this)) { + reachZombie();//reduce energy + tomb.setEndGame(true);//stop game + } + //meet sandwich + else if (tomb.getSandwich().isMeet(this)) { + eatSandwich();//increase energy + tomb.getSandwich().setVisible(false);//clear sandwich + } + } + /** + * draw player + */ + public void draw() { + image.drawFromTopLeft(pos.x, pos.y); + // also show energy level + FONT.drawString("energy: "+ energy,20,760, OPT.setBlendColour(Colour.BLACK)); + } + /** + * Meet a sandwich, increase energy + */ + public void eatSandwich(){ + energy += 5; + } + /** + * Encounter zombies, reduce energy + */ + public void reachZombie(){ + energy -= 3; + } +} diff --git a/src/Sandwich.java b/src/Sandwich.java new file mode 100644 index 0000000000000000000000000000000000000000..2fe14b9f7f86bc3bfd364584efc31c01e17e248a --- /dev/null +++ b/src/Sandwich.java @@ -0,0 +1,73 @@ +import bagel.Image; +import bagel.util.Point; +/** + * a stationary entity: sandwich + */ +public class Sandwich{ + /** + * the sandwich's image displayed in the window + */ + private Image image; + /** + * a Point object representing the position of the sandwich + */ + private Point pos; + /** + * if display sandwiches in the window + */ + private boolean visible; + /** + * constructor + * @param x abscissa + * @param y ordinate + */ + public Sandwich(double x, double y){ + this.image = new Image("res/images/sandwich.png"); + this.pos = new Point(x,y); + this.visible = true; + } + /** + * judge if display sandwiches in the window + * @return visible + */ + public boolean isVisible() { + return visible; + } + /** + * @return the Point object representing the position of the sandwich + */ + public Point getPos() { + return pos; + } + /** + * Change the visible state + * @param vis display-true, don't display-false + */ + public void setVisible(boolean vis) { + this.visible = vis; + } + /** + * render image, draw the sandwich in the specified location if needed + */ + public void draw() { + if (isVisible()) { + image.drawFromTopLeft(pos.x, pos.y); + } + } + /** + * judge whether the player encounters sandwich while the sandwich is exist + * @param player a object of Player + * @return if meet return true, else return false + */ + public boolean isMeet(Player player) { + if (isVisible()){ + if (player.getPos().distanceTo(pos) < ShadowTreasure.CLOSENESS) { + return true; + } else { + return false; + } + }else { + return false; + } + } +} diff --git a/src/ShadowTreasure.java b/src/ShadowTreasure.java new file mode 100644 index 0000000000000000000000000000000000000000..be64326ce6c9267f406b327a4eef207d0630b08a --- /dev/null +++ b/src/ShadowTreasure.java @@ -0,0 +1,149 @@ +import bagel.*; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +/** + * an example Bagel game. + */ +public class ShadowTreasure extends AbstractGame { + /** + * background image + */ + private final Image BACKGROUND = new Image("res/images/background.png"); + /** + * distance threshold. + * When the distance between the player and the stationery entity is less than this value, + * it is judged as meeting + */ + public static final int CLOSENESS = 50; + /** + * the window state is updated only when the number of frames is a multiple of 10 + */ + private final int maxCount = 10; + /** + * counter from 1 to maxCount + */ + private int counter; + /** + * the player entity of the game + */ + private Player player; + /** + * the sandwich entity of the game + */ + private Sandwich sandwich; + /** + * the zombie entity of the game + */ + private Zombie zombie; + /** + * end of game indicator + */ + private boolean isEndGame; + + /** + * Get zombie object in the game + * @return zombie object + */ + public Zombie getZombie() { + return this.zombie; + } + + /** + * Set game state (end or not) + * @param endOfGame game state + */ + public void setEndGame(boolean endOfGame) { + this.isEndGame = endOfGame; + } + /** + * Get sandwich object in the game + * @return sandwich object + */ + public Sandwich getSandwich() { + return sandwich; + } + + /** + * constructor + * @throws IOException + */ + public ShadowTreasure() throws IOException { + //load the initial position of entities + this.readInitialPos("res/IO/environment.csv"); + //Set the counter to one + this.counter = 1; + this.isEndGame = false; + //Print player information + System.out.println(player.getPos().x + "," + player.getPos().y + "," + player.getEnergy()); + } + + /** + * Load from input file + */ + private void readInitialPos(String filename){ + try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { + String line; + while ((line = reader.readLine()) != null) { + String[] parts = line.split(","); + //At this time, because of the problem of text coding, it can not be directly compared with the literal amount of string + String type = parts[0]; + // remove special characters dnd code according to Java + type = type.replaceAll("[^a-zA-Z0-9]", ""); + int x = Integer.parseInt(parts[1]); + int y = Integer.parseInt(parts[2]); + if(type.equals("Player")) { + this.player = new Player(x, y, Integer.parseInt(parts[3])); + } + else if(type.equals("Zombie")) { + this.zombie = new Zombie(x, y); + } + else if(type.equals("Sandwich")) { + this.sandwich = new Sandwich(x, y); + } + else { + throw new BagelError("Unknown type: " + type); + } + } + } catch (IOException e) { + e.printStackTrace(); + System.exit(-1); + } + } + + /** + * Performs a state update. + */ + @Override + public void update(Input input) + { + //game over + if (this.isEndGame || input.wasPressed(Keys.ESCAPE)) + { + Window.close(); + } + else + { + // Draw background + BACKGROUND.drawFromTopLeft(0, 0); + // Update status when the TICK_CYCLE is up + if (counter > maxCount) { + // update player status + player.update(this); + counter = 1; + System.out.println(String.format("%.2f",player.getPos().x) + "," + String.format("%.2f",player.getPos().y) + "," + player.getEnergy()); + } + counter++; + sandwich.draw(); + zombie.draw(); + player.draw(); + } + } + /** + * The entry point for the program. + */ + public static void main(String[] args) throws IOException { + ShadowTreasure game = new ShadowTreasure(); + game.run(); + } +} diff --git a/src/Zombie.java b/src/Zombie.java new file mode 100644 index 0000000000000000000000000000000000000000..8e5bc04d581145bc47af529211fcad4974c610b8 --- /dev/null +++ b/src/Zombie.java @@ -0,0 +1,48 @@ +import bagel.Image; +import bagel.util.Point; +/** + * a stationary entity: zombie + */ +public class Zombie{ + /** + * the zombie's image displayed in the window + */ + private Image image; + /** + * a Point object representing the position of the zombie + */ + private Point pos; + /** + * constructor + * @param x abscissa + * @param y ordinate + */ + public Zombie(double x, double y){ + this.image = new Image("res/images/zombie.png"); + this.pos = new Point(x,y); + } + /** + * @return the Point object representing the position of the zombie + */ + public Point getPos() { + return pos; + } + /** + * render image, draw the zombie in the specified location + */ + public void draw() { + image.drawFromTopLeft(pos.x, pos.y); + } + /** + * judge whether the player encounters zombie + * @param player a object of Player + * @return if meet return true, else return false + */ + public boolean isMeet(Player player) { + if (player.getPos().distanceTo(pos) < ShadowTreasure.CLOSENESS) { + return true; + } else { + return false; + } + } +}