diff --git a/UML.png b/UML.png new file mode 100644 index 0000000..5069a5b Binary files /dev/null and b/UML.png differ diff --git a/src/main/java/fr/sae/terraria/Terraria.java b/src/main/java/fr/sae/terraria/Terraria.java index 2de8c97..c6e2d52 100644 --- a/src/main/java/fr/sae/terraria/Terraria.java +++ b/src/main/java/fr/sae/terraria/Terraria.java @@ -1,20 +1,28 @@ package fr.sae.terraria; -import fr.sae.terraria.controller.Controller; +import fr.sae.terraria.controller.GameController; +import fr.sae.terraria.controller.MenuController; import javafx.application.Application; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; import javafx.fxml.FXMLLoader; +import javafx.scene.Cursor; import javafx.scene.Scene; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; import javafx.stage.Stage; import java.io.File; import java.io.IOException; +import java.net.MalformedURLException; import java.net.URL; +import java.util.Objects; public class Terraria extends Application { // Constants - public static final String srcPath = "src/main/resources/fr/sae/terraria/"; + public static final String SRC_PATH = "src/main/resources/fr/sae/terraria/"; public static final double TARGET_FPS = .017; public static final int DISPLAY_RENDERING_WIDTH = 465; public static final int DISPLAY_RENDERING_HEIGHT = 256; @@ -26,22 +34,74 @@ public class Terraria extends Application public static void main(String[] args) { launch(); } + private FXMLLoader loadFXML(String path) + { + URL pathGameFxml = Terraria.class.getResource(path); + if (Objects.isNull(pathGameFxml)) try { + pathGameFxml = new File(Terraria.SRC_PATH + path).toURI().toURL(); + } catch (MalformedURLException e) { throw new RuntimeException(e); } + + return new FXMLLoader(pathGameFxml); + } + public void start(Stage stage) throws IOException { - URL pathFxml = Terraria.class.getResource("vue/game.fxml"); - if (pathFxml == null) - pathFxml = new File(srcPath + "vue/game.fxml").toURI().toURL(); - - FXMLLoader fxmlLoader = new FXMLLoader(pathFxml); - Controller ctrl = new Controller(stage); - fxmlLoader.setController(ctrl); - Scene scene = new Scene(fxmlLoader.load(), this.widthWindow, this.heightWindow); - + GameController gameController = new GameController(stage); + MenuController menuController = new MenuController(stage); + + FXMLLoader fxmlLoader = this.loadFXML("vue/game.fxml"); + fxmlLoader.setController(gameController); + Scene game = new Scene(fxmlLoader.load(), this.widthWindow, this.heightWindow); + game.setCursor(Cursor.NONE); + + fxmlLoader = this.loadFXML("vue/menu.fxml"); + fxmlLoader.setController(menuController); + Scene menu = new Scene(fxmlLoader.load(), this.widthWindow, this.heightWindow); + stage.setTitle(this.titleWindow); stage.setResizable(false); - stage.setScene(scene); + + BooleanProperty switchScene = new SimpleBooleanProperty(); + // Change de scènes suivant les valeurs boolean + switchScene.addListener((obs, oldB, newB) -> stage.setScene(newB.equals(Boolean.TRUE) ? game : menu)); + + stage.setScene(game); + int[] timePressedKey = new int[1]; // Permet que le menu ne clignote pas et reste afficher même si le bouton 'M' est encore enfoncer. + stage.addEventFilter(KeyEvent.KEY_PRESSED, key -> { + if (key.getCode() == KeyCode.M && timePressedKey[0] <= 1) + switchScene.set(!switchScene.get()); + + timePressedKey[0]++; + key.consume(); + }); + stage.addEventFilter(KeyEvent.KEY_RELEASED, key -> timePressedKey[0] = 1); stage.sizeToScene(); + // Sync les changements du joueur entre les contrôleurs. + stage.sceneProperty().addListener(((obs, oldScene, newScene) -> { + if (switchScene.get()) { + if (!Objects.isNull(menuController.player)) { + gameController.player = menuController.player; + menuController.loop.stop(); + gameController.environment.getLoop().play(); + } + } else { + if (!Objects.isNull(gameController.player)) { + menuController.player = gameController.player; + menuController.loop.play(); + gameController.environment.getLoop().stop(); + } + } + })); + stage.widthProperty().addListener((obs, oldV, newV) -> { + gameController.scaleMultiplicatorWidth = (newV.intValue() / Terraria.DISPLAY_RENDERING_WIDTH); + menuController.scaleMultiplicatorWidth = (newV.intValue() / Terraria.DISPLAY_RENDERING_WIDTH); + }); + stage.heightProperty().addListener((obs, oldV, newV) -> { + gameController.scaleMultiplicatorHeight = ((newV.intValue()-gameController.title.getPrefHeight()) / Terraria.DISPLAY_RENDERING_HEIGHT); + menuController.scaleMultiplicatorHeight = ((newV.intValue()-gameController.title.getPrefHeight()) / Terraria.DISPLAY_RENDERING_HEIGHT); + }); + stage.show(); } } \ No newline at end of file diff --git a/src/main/java/fr/sae/terraria/controller/Controller.java b/src/main/java/fr/sae/terraria/controller/Controller.java deleted file mode 100644 index 5bbc3ae..0000000 --- a/src/main/java/fr/sae/terraria/controller/Controller.java +++ /dev/null @@ -1,190 +0,0 @@ -package fr.sae.terraria.controller; - -import fr.sae.terraria.Terraria; -import fr.sae.terraria.modele.Environment; -import fr.sae.terraria.modele.TileMaps; -import fr.sae.terraria.modele.blocks.Dirt; -import fr.sae.terraria.modele.blocks.Stone; -import fr.sae.terraria.modele.entities.Player; -import fr.sae.terraria.modele.entities.entity.Entity; -import fr.sae.terraria.modele.entities.entity.StowableObjectType; -import fr.sae.terraria.vue.View; -import javafx.fxml.FXML; -import javafx.fxml.Initializable; -import javafx.geometry.Rectangle2D; -import javafx.scene.Node; -import javafx.scene.input.KeyEvent; -import javafx.scene.input.MouseButton; -import javafx.scene.input.MouseEvent; -import javafx.scene.input.ScrollEvent; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Pane; -import javafx.stage.Stage; - -import java.net.URL; -import java.util.Objects; -import java.util.ResourceBundle; - - -public class Controller implements Initializable -{ - @FXML - private HBox title; - @FXML - private BorderPane root; - @FXML - private Pane displayHUD; - @FXML - private Pane displayTiledMap; - - private Stage primaryStage; - private Environment environment; - - // TODO: plutot mettre un DoubleProperty a c'est deux variables - private double scaleMultiplicatorWidth = .0; // Permet de scale correctement une image selon la largeur de l'écran - private double scaleMultiplicatorHeight = .0; // Permet de scale correctement une image selon la hauteur de l'écran - - - public Controller(Stage primaryStage) - { - this.primaryStage = primaryStage; - - primaryStage.widthProperty().addListener((obs, oldV, newV) -> scaleMultiplicatorWidth = (newV.intValue() / Terraria.DISPLAY_RENDERING_WIDTH)); - primaryStage.heightProperty().addListener((obs, oldV, newV) -> scaleMultiplicatorHeight = ((newV.intValue()-title.getPrefHeight()) / Terraria.DISPLAY_RENDERING_HEIGHT)); - } - - public void initialize(URL location, ResourceBundle resources) - { - scaleMultiplicatorWidth = (root.getPrefWidth() / Terraria.DISPLAY_RENDERING_WIDTH); - scaleMultiplicatorHeight = ((root.getPrefHeight()-title.getPrefHeight()) / Terraria.DISPLAY_RENDERING_HEIGHT); - - this.environment = new Environment(scaleMultiplicatorWidth, scaleMultiplicatorHeight); - new View(environment, displayTiledMap, displayHUD, scaleMultiplicatorWidth, scaleMultiplicatorHeight); - - this.addKeysEventListener(primaryStage); - } - - /** - * Ajoute la fonctionnalité des listeners des event du clavier - * @param stage Specifier l'application - */ - private void addKeysEventListener(Stage stage) - { - Player player = this.environment.getPlayer(); - - stage.addEventFilter(KeyEvent.KEY_PRESSED, key -> { - player.getKeysInput().put(key.getCode(), true); - key.consume(); - }); - - stage.addEventFilter(KeyEvent.KEY_RELEASED, key -> { - player.getKeysInput().put(key.getCode(), false); - key.consume(); - }); - - stage.addEventFilter(ScrollEvent.SCROLL, scroll -> { - boolean scrollUp = scroll.getDeltaY() > 0; - if (scrollUp) - player.positionOfCursorInventoryBar.setValue(player.positionOfCursorInventoryBar.get() + 1); - boolean scrollDown = scroll.getDeltaY() < 0; - if (scrollDown) - player.positionOfCursorInventoryBar.setValue(player.positionOfCursorInventoryBar.get() - 1); - - if (player.positionOfCursorInventoryBar.get() > 8) - player.positionOfCursorInventoryBar.setValue(0); - if (player.positionOfCursorInventoryBar.get() < 0) - player.positionOfCursorInventoryBar.setValue(8); - }); - - stage.addEventFilter(MouseEvent.MOUSE_CLICKED, click -> { - double scaleMultiplicativeWidth = (root.getPrefWidth() / Terraria.DISPLAY_RENDERING_WIDTH); - double scaleMultiplicativeHeight = ((root.getPrefHeight()-title.getPrefHeight()) / Terraria.DISPLAY_RENDERING_HEIGHT); - int tileWidth = (int) (TileMaps.TILE_DEFAULT_SIZE * scaleMultiplicativeWidth); - int tileHeight = (int) (TileMaps.TILE_DEFAULT_SIZE * scaleMultiplicativeHeight); - // La position correcte sur le Pane - double mouseX = click.getSceneX(); - double mouseY = click.getSceneY()-title.getPrefHeight(); - Rectangle2D rectangle = new Rectangle2D(mouseX, mouseY, scaleMultiplicativeWidth, scaleMultiplicativeHeight); - // Le bloc où la souris à clicker - int xBlock = (int) (mouseX/tileWidth); - int yBlock = (int) (mouseY/tileHeight); - // La position du joueur - int xPlayer = (int) ((player.getX()+(tileWidth/2))/tileWidth); - int yPlayer = (int) ((player.getY()+(tileHeight/2))/tileHeight); - // La distance entre le bloc et le joueur - int distanceBetweenBlockPlayerAxisX = Math.abs(xPlayer - xBlock); - int distanceBetweenBlockPlayerAxisY = Math.abs(yPlayer - yBlock); - - boolean isOneBlockDistance = distanceBetweenBlockPlayerAxisY >= 0 && distanceBetweenBlockPlayerAxisY <= Player.BREAK_BLOCK_DISTANCE && distanceBetweenBlockPlayerAxisX >= 0 && distanceBetweenBlockPlayerAxisX <= Player.BREAK_BLOCK_DISTANCE; - if (isOneBlockDistance) - { - // Casse les blocs - if (click.getButton().equals(MouseButton.PRIMARY)) - // Commence a cherché l'entité ciblée - for (Entity entity : environment.getEntities()) { - // La position de l'entité - int xEntity = (int) (entity.getRect().get().getMinX()); - int yEntity = (int) (entity.getRect().get().getMinY()); - - if (entity.getRect().collideRect(rectangle)) { - player.pickup((StowableObjectType) entity); - - Node nodeAtDelete = null; int i = 0; - // Tant qu'on n'a pas trouvé l'objet sur le Pane, il continue la boucle. - do { - Node node = displayTiledMap.getChildren().get(i); - int xNode = (int) (node.getTranslateX()); - int yNode = (int) (node.getTranslateY()); - - if (xNode == xEntity && yNode == yEntity) { - nodeAtDelete = node; - environment.getTileMaps().setTile(TileMaps.SKY, yNode/tileHeight, xNode/tileWidth); - // Supprime dans le modele et dans la vue - environment.getEntities().remove(entity); - displayTiledMap.getChildren().remove(nodeAtDelete); - } - i++; - } while (i < displayTiledMap.getChildren().size() && Objects.isNull(nodeAtDelete)); - - // Quand tous c'est bien déroulés, aprés avoir trouvé l'entité et l'objet sur l'écran, il arrête de chercher d'autre entité d'où le break - break; - } - } - - // Pose les blocs - if (click.getButton().equals(MouseButton.SECONDARY)) { - boolean haveAnItemOnHand = !Objects.isNull(player.getItemSelected()); - if (haveAnItemOnHand) { - Entity entity = null; - if (player.getItemSelected() instanceof Dirt) { - entity = new Dirt(xBlock*tileWidth, yBlock*tileHeight); - environment.getTileMaps().setTile(TileMaps.DIRT, yBlock, xBlock); - } else if (player.getItemSelected() instanceof Stone) { - entity = new Stone(xBlock*tileWidth, yBlock*tileHeight); - environment.getTileMaps().setTile(TileMaps.STONE, yBlock, xBlock); - } - - if(!Objects.isNull(entity)) { - entity.setRect(tileWidth, tileHeight); - environment.getEntities().add(0, entity); - - // Si on le pose sur le joueur - boolean isIntoABlock = player.getRect().collideRect(entity.getRect()); - if (isIntoABlock) { - // Place le joueur au-dessus du block posé. - player.setY(entity.getY() - player.getRect().getHeight()); - player.getGravity().yInit = player.getY(); - player.getGravity().xInit = player.getX(); - } - - player.getInventory().get(player.positionOfCursorInventoryBar.get()).remove(player.getItemSelected()); - if (player.getInventory().get(player.positionOfCursorInventoryBar.get()).size()-1 >= 0) - player.setItemSelected(player.getInventory().get(player.positionOfCursorInventoryBar.get()).get(player.getInventory().get(player.positionOfCursorInventoryBar.get()).size()-1)); - } - } - } - } - }); - } -} \ No newline at end of file diff --git a/src/main/java/fr/sae/terraria/controller/GameController.java b/src/main/java/fr/sae/terraria/controller/GameController.java new file mode 100644 index 0000000..024d8e4 --- /dev/null +++ b/src/main/java/fr/sae/terraria/controller/GameController.java @@ -0,0 +1,172 @@ +package fr.sae.terraria.controller; + +import fr.sae.terraria.Terraria; +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.TileMaps; +import fr.sae.terraria.modele.entities.entity.*; +import fr.sae.terraria.modele.entities.player.Player; +import fr.sae.terraria.modele.entities.player.inventory.Inventory; +import fr.sae.terraria.vue.Camera; +import fr.sae.terraria.vue.View; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.geometry.Rectangle2D; +import javafx.scene.input.*; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.StackPane; +import javafx.scene.shape.Rectangle; +import javafx.stage.Stage; + +import java.net.URL; +import java.util.Objects; +import java.util.ResourceBundle; + + +public class GameController implements Initializable +{ + @FXML public HBox title; + @FXML public BorderPane root; + @FXML public Pane displayHUD; + @FXML public Pane displayTiledMap; + @FXML public Pane displayHostileBeings; + @FXML public Pane filter; + @FXML public Pane displayCursorMouse; + @FXML public StackPane paneHadCamera; + + public final Stage primaryStage; + + public Environment environment; + public Player player = null; + + // TODO plutot mettre un DoubleProperty a c'est deux variables + public double scaleMultiplicatorWidth = .0; // Permet de scale correctement une image selon la largeur de l'écran + public double scaleMultiplicatorHeight = .0; // Permet de scale correctement une image selon la hauteur de l'écran + + + public GameController(final Stage primaryStage) + { + super(); + this.primaryStage = primaryStage; + + primaryStage.widthProperty().addListener((obs, oldV, newV) -> this.scaleMultiplicatorWidth = (newV.intValue() / Terraria.DISPLAY_RENDERING_WIDTH)); + primaryStage.heightProperty().addListener((obs, oldV, newV) -> this.scaleMultiplicatorHeight = ((newV.intValue()-this.title.getPrefHeight()) / Terraria.DISPLAY_RENDERING_HEIGHT)); + } + + @Override public void initialize(URL location, ResourceBundle resources) + { + this.scaleMultiplicatorWidth = (this.root.getPrefWidth() / Terraria.DISPLAY_RENDERING_WIDTH); + this.scaleMultiplicatorHeight = ((this.root.getPrefHeight()-this.title.getPrefHeight()) / Terraria.DISPLAY_RENDERING_HEIGHT); + + this.environment = new Environment(this.scaleMultiplicatorWidth, this.scaleMultiplicatorHeight); + this.player = this.environment.getPlayer(); + + new View(this); + new Camera(this.environment, this.paneHadCamera); + + this.addKeysEventListener(this.primaryStage); + } + + /** + * Ajoute la fonctionnalité des listeners des event du clavier + * @param stage Specifier l'application + */ + private void addKeysEventListener(final Stage stage) + { + final Inventory inventory = this.player.getInventory(); + + stage.addEventFilter(KeyEvent.KEY_PRESSED, key -> { + this.player.getKeysInput().put(key.getCode(), true); + inventory.getKeysInput().put(key.getCode(), true); + + // DEBUG ZONE + // Met la nuit + if (key.isShiftDown() && key.isControlDown() && key.getCode().equals(KeyCode.N)) + this.environment.getGameClock().setMinutes(1_000); + if (key.isShiftDown() && key.isControlDown() && key.getCode().equals(KeyCode.J)) + this.environment.getGameClock().setMinutes(400); + + key.consume(); + }); + + stage.addEventFilter(KeyEvent.KEY_RELEASED, key -> { + this.player.getKeysInput().put(key.getCode(), false); + inventory.getKeysInput().put(key.getCode(), false); + key.consume(); + }); + + stage.addEventFilter(MouseEvent.MOUSE_CLICKED, mouse -> { + this.player.getMouseInput().put(mouse.getButton(), true); + mouse.consume(); + }); + + stage.addEventFilter(MouseEvent.MOUSE_RELEASED, mouse -> { + this.player.getMouseInput().put(mouse.getButton(), false); + mouse.consume(); + }); + + stage.addEventFilter(ScrollEvent.SCROLL, scroll -> { + inventory.setScroll((int) scroll.getDeltaY()); + scroll.consume(); + }); + + stage.addEventFilter(MouseEvent.MOUSE_CLICKED, click -> { + final double scaleMultiplicativeWidth = (this.root.getPrefWidth() / Terraria.DISPLAY_RENDERING_WIDTH); + final double scaleMultiplicativeHeight = ((this.root.getPrefHeight()-this.title.getPrefHeight()) / Terraria.DISPLAY_RENDERING_HEIGHT); + final int tileWidth = (int) (TileMaps.TILE_DEFAULT_SIZE * scaleMultiplicativeWidth); + final int tileHeight = (int) (TileMaps.TILE_DEFAULT_SIZE * scaleMultiplicativeHeight); + // La position correcte sur le Pane + double mouseX = click.getSceneX()+((Rectangle) this.displayTiledMap.getParent().getClip()).getX(); + double mouseY = (click.getSceneY()-this.title.getPrefHeight())+((Rectangle) this.displayTiledMap.getParent().getClip()).getY(); + // Le bloc où la souris à clicker + int xBlock = (int) (mouseX/tileWidth); + int yBlock = (int) (mouseY/tileHeight); + Rectangle2D rectangle = new Rectangle2D(mouseX, mouseY, scaleMultiplicativeWidth, scaleMultiplicativeHeight); + // La position du joueur + int xPlayer = (int) ((this.player.getX()+(tileWidth/2))/tileWidth); + int yPlayer = (int) ((this.player.getY()+(tileHeight/2))/tileHeight); + // La distance entre le bloc et le joueur + int distanceBetweenBlockPlayerAxisX = Math.abs(xPlayer - xBlock); + int distanceBetweenBlockPlayerAxisY = Math.abs(yPlayer - yBlock); + + boolean isOneBlockDistance = distanceBetweenBlockPlayerAxisY >= 0 && distanceBetweenBlockPlayerAxisY <= Player.BREAK_BLOCK_DISTANCE && distanceBetweenBlockPlayerAxisX >= 0 && distanceBetweenBlockPlayerAxisX <= Player.BREAK_BLOCK_DISTANCE; + if (this.player.getStackSelected() instanceof EatableObjectType) { + ((EatableObjectType) this.player.getStackSelected()).eat(); + } else if (isOneBlockDistance) { + if (click.getButton().equals(MouseButton.PRIMARY)) + this.breakBlock(rectangle); + if (click.getButton().equals(MouseButton.SECONDARY)) + this.placeBlock(xBlock, yBlock); + } + }); + } + + private void breakBlock(final Rectangle2D rectangle) + { + // Commence a cherché l'entité ciblée + for (Entity entity : this.environment.getEntities()) if (entity.getRect().collideRect(rectangle)) { + if (entity instanceof BreakableObjectType) + ((BreakableObjectType) entity).breaks(); + if (entity instanceof CollapsibleObjectType) // TODO TEMP, à déplacer + ((CollapsibleObjectType) entity).hit(); + + // Quand tous c'est bien déroulés, aprés avoir trouvé l'entité et l'objet sur l'écran, il arrête de chercher d'autre entité d'où le break + break; + } + } + + private void placeBlock(int xBlock, int yBlock) + { + boolean haveAnItemOnHand = !Objects.isNull(this.player.getStackSelected()); + boolean goodPlace = this.environment.getTileMaps().getTile(xBlock, yBlock) == TileMaps.SKY; + + if (haveAnItemOnHand && goodPlace) { + if (!(this.player.getStackSelected().getItem() instanceof PlaceableObjectType) && !(this.player.getStackSelected() instanceof EatableObjectType)) + return; + + if (this.player.getStackSelected().getItem() instanceof PlaceableObjectType) + ((PlaceableObjectType) this.player.getStackSelected().getItem()).place(xBlock, yBlock); + } + } +} \ No newline at end of file diff --git a/src/main/java/fr/sae/terraria/controller/MenuController.java b/src/main/java/fr/sae/terraria/controller/MenuController.java new file mode 100644 index 0000000..e8c3855 --- /dev/null +++ b/src/main/java/fr/sae/terraria/controller/MenuController.java @@ -0,0 +1,57 @@ +package fr.sae.terraria.controller; + +import fr.sae.terraria.Terraria; +import fr.sae.terraria.modele.entities.player.Player; +import javafx.animation.Animation; +import javafx.animation.KeyFrame; +import javafx.animation.Timeline; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.stage.Stage; +import javafx.util.Duration; + +import java.net.URL; +import java.util.Objects; +import java.util.ResourceBundle; + + +public class MenuController implements Initializable +{ + @FXML public Pane root; + @FXML public Pane displayInventory; + @FXML public Pane displayLexique; + @FXML public HBox HBoxText; + + public Timeline loop; + private Stage stage; + public Player player = null; + public double scaleMultiplicatorWidth; + public double scaleMultiplicatorHeight; + + + public MenuController(final Stage stage) + { + super(); + this.stage = stage; + } + + @Override public void initialize(URL location, ResourceBundle resources) + { + this.scaleMultiplicatorWidth = (this.root.getPrefWidth() / Terraria.DISPLAY_RENDERING_WIDTH); + this.scaleMultiplicatorHeight = ((this.root.getPrefHeight()-this.HBoxText.getPrefHeight()) / Terraria.DISPLAY_RENDERING_HEIGHT); + + this.loop = new Timeline(); + this.loop.setCycleCount(Animation.INDEFINITE); + + KeyFrame keyFrame = new KeyFrame(Duration.seconds(Terraria.TARGET_FPS), (ev -> { + if (!Objects.isNull(this.player)) { + System.out.println(this.player.getInventory()); + } + })); + + this.loop.getKeyFrames().add(keyFrame); + this.loop.play(); + } +} diff --git a/src/main/java/fr/sae/terraria/modele/Clock.java b/src/main/java/fr/sae/terraria/modele/Clock.java index 631fa97..a15c226 100644 --- a/src/main/java/fr/sae/terraria/modele/Clock.java +++ b/src/main/java/fr/sae/terraria/modele/Clock.java @@ -6,32 +6,38 @@ public class Clock { public static final int ONE_MINUTE_INGAME = 37; - public static final int ONE_DAY_INGAME = 1440; + public static final int MINUTES_IN_A_DAY = 1440; + public static final int EIGHT_AM_INGAME = 480; + private final SimpleIntegerProperty minutes; private final SimpleIntegerProperty days; public Clock() { - minutes = new SimpleIntegerProperty(0); - days = new SimpleIntegerProperty(0); + super(); + + this.minutes = new SimpleIntegerProperty(Clock.EIGHT_AM_INGAME); + this.days = new SimpleIntegerProperty(1); } public void updates(int ticks) { // si environ 1 minute passe irl, le timer dans le jeu augmente de 10 minutes if (ticks%Clock.ONE_MINUTE_INGAME == 0) { - if (getMinutes()+1 == ONE_DAY_INGAME) { - days.setValue(getDays()+1); - minutes.setValue(0); - } else minutes.setValue(getMinutes()+1); + if (this.getMinutes()+1 == Clock.MINUTES_IN_A_DAY) { + this.days.setValue(getDays()+1); + this.minutes.setValue(0); + } else this.minutes.setValue(getMinutes()+1); } } - public SimpleIntegerProperty minutesProperty() { return minutes; } - public SimpleIntegerProperty daysProperty() { return days; } + public SimpleIntegerProperty minutesProperty() { return this.minutes; } + public SimpleIntegerProperty daysProperty() { return this.days; } + + public int getMinutes() { return this.minutes.get(); } + public int getDays() { return this.days.get(); } - public int getMinutes() { return minutes.get(); } - public int getDays() { return days.get(); } + public void setMinutes(int newMinutes) { this.minutes.set(newMinutes); } } diff --git a/src/main/java/fr/sae/terraria/modele/Environment.java b/src/main/java/fr/sae/terraria/modele/Environment.java index dc0d692..1943e2d 100644 --- a/src/main/java/fr/sae/terraria/modele/Environment.java +++ b/src/main/java/fr/sae/terraria/modele/Environment.java @@ -1,86 +1,126 @@ package fr.sae.terraria.modele; import fr.sae.terraria.Terraria; -import fr.sae.terraria.modele.blocks.TallGrass; -import fr.sae.terraria.modele.entities.Player; import fr.sae.terraria.modele.entities.Rabbit; +import fr.sae.terraria.modele.entities.Slime; +import fr.sae.terraria.modele.entities.blocks.Torch; import fr.sae.terraria.modele.entities.entity.CollideObjectType; import fr.sae.terraria.modele.entities.entity.Entity; import fr.sae.terraria.modele.entities.entity.ReproductiveObjectType; -import fr.sae.terraria.vue.View; +import fr.sae.terraria.modele.entities.items.Meat; +import fr.sae.terraria.modele.entities.player.Player; +import fr.sae.terraria.modele.entities.tools.Pickaxe; import javafx.animation.Animation; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; -import javafx.scene.image.Image; import javafx.util.Duration; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class Environment { - private Clock clock; + // Permet d'update toutes les entités en une seule boucle. private final ObservableList entities; + // Range des entities en plus pour permettre facilement de savoir combien son t-il sur la carte pour limiter leur apparition + private final ObservableList rabbits; + private final ObservableList slimes; + // Permet update facilement les lumières des torches sur le filtre + private final ObservableList torches; private final TileMaps tileMaps; private final Player player; + private final Clock clock; + private Timeline loop; public double scaleMultiplicatorWidth; public double scaleMultiplicatorHeight; + private int previousDays; public int widthTile; public int heightTile; - private int ticks = 0; + private int ticks; public Environment(double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) { + super(); + this.scaleMultiplicatorWidth = scaleMultiplicatorWidth; this.scaleMultiplicatorHeight = scaleMultiplicatorHeight; + this.widthTile = (int) (scaleMultiplicatorWidth * TileMaps.TILE_DEFAULT_SIZE); + this.heightTile = (int) (scaleMultiplicatorHeight * TileMaps.TILE_DEFAULT_SIZE); this.tileMaps = new TileMaps(); - this.tileMaps.load(Terraria.srcPath + "maps/map_0.json"); + this.tileMaps.load(Terraria.SRC_PATH + "maps/map_0.json"); this.clock = new Clock(); + this.previousDays = -1; + this.ticks = 0; + this.entities = FXCollections.observableArrayList(); - this.widthTile = (int) (scaleMultiplicatorWidth * TileMaps.TILE_DEFAULT_SIZE); - this.heightTile = (int) (scaleMultiplicatorHeight * TileMaps.TILE_DEFAULT_SIZE); + this.rabbits = FXCollections.observableArrayList(); + this.slimes = FXCollections.observableArrayList(); + this.torches = FXCollections.observableArrayList(); - this.player = new Player(this, (5*widthTile), (3*heightTile)); + this.player = new Player(this); this.player.setVelocity(5); this.player.setPv(4); - Image image = View.loadAnImage("sprites/player/player_idle.png", scaleMultiplicatorWidth, scaleMultiplicatorHeight); - this.player.setRect((int) image.getWidth(), (int) image.getHeight()); - image.cancel(); + this.player.spawn(5*widthTile, 3*heightTile); + + // Détecte si le joueur n'est pas dans un bloc lorsque qu'il met un block au sol + this.entities.addListener((ListChangeListener) c -> { + while (c.next()) if (c.wasAdded()) { + Entity entity = c.getList().get(0); + + if (!Objects.isNull(entity.getRect())) { + // Si on le pose sur le joueur + boolean isIntoABlock = player.getRect().collideRect(entity.getRect()); + + if (entity instanceof CollideObjectType && isIntoABlock) { + // Place le joueur au-dessus du block posé. + player.setY(entity.getY() - player.getRect().getHeight()); + player.getGravity().yInit = player.getY(); + player.getGravity().xInit = player.getX(); + } + } + } + }); + Environment.playSound("sound/Bird_Sound.wav", true); gameLoop(); } - /** Evite que l'entité sort de la fenêtre. */ - private void worldLimit(Entity entity) - { - double widthScreen = (scaleMultiplicatorWidth * Terraria.DISPLAY_RENDERING_WIDTH); - - boolean exceedsScreenOnLeft = entity.offset[0] == Entity.IS_MOVING_LEFT && entity.getX() < 0; - boolean exceedsScreenOnRight = entity.offset[0] == Entity.IS_MOVING_RIGHT && entity.getX() > (widthScreen - entity.getRect().getWidth()); - if (exceedsScreenOnLeft || exceedsScreenOnRight) - entity.offset[0] = (entity instanceof Rabbit) ? ((-1) * entity.offset[0]) : Entity.IDLE; - } - /** La boucle principale du jeu */ private void gameLoop() { - Timeline loop = new Timeline(); - loop.setCycleCount(Animation.INDEFINITE); + // TODO TEST + boolean[] caught = new boolean[] { false }; + + this.loop = new Timeline(); + this.loop.setCycleCount(Animation.INDEFINITE); List entitiesAtAdded = new ArrayList<>(); KeyFrame keyFrame = new KeyFrame(Duration.seconds(Terraria.TARGET_FPS), (ev -> { - this.player.offset[0] = Entity.IDLE; - this.player.eventInput(); - this.worldLimit(this.player); + // TODO TEST + if (!caught[0]) { + Torch torch = new Torch(this, 0, 0); + this.player.pickup(torch); + Meat meat = new Meat(this); + this.player.pickup(meat); + + this.player.pickup(new Pickaxe()); + caught[0] = true; + } // Ajoute les entités ReproductiveObjectType for (Entity entity : entitiesAtAdded) @@ -88,51 +128,61 @@ private void gameLoop() entitiesAtAdded.clear(); // Génère aléatoirement des entités - GenerateEntity.tree(this); - GenerateEntity.tallGrass(this); - GenerateEntity.rabbit(this); - - for (Entity entity : entities) - { - // Fait sauter ou non le lapin - if (entity instanceof Rabbit) { - boolean mustJump = ticks%Rabbit.JUMP_FREQUENCY == 0; - if (mustJump) { - boolean jumpOrNot = Math.random() < Rabbit.LUCK_OF_JUMPING; - if (jumpOrNot && entity.offset[1] != Entity.IS_FALLING) - entity.jump(); - } - } - - if (entity instanceof CollideObjectType) { - this.worldLimit(entity); - ((CollideObjectType) entity).collide(); - } - - if (entity instanceof ReproductiveObjectType) { - // Reproduit les hautes herbes - boolean tallGrassMustReproduce = ticks%TallGrass.REPRODUCTION_RATE == 0; - if (entity instanceof TallGrass && tallGrassMustReproduce) - entitiesAtAdded.addAll(((ReproductiveObjectType) entity).reproduction(this)); - } + boolean dayTime = this.clock.getMinutes() < (Clock.MINUTES_IN_A_DAY/2); + boolean nightTime = this.clock.getMinutes() > (Clock.MINUTES_IN_A_DAY)/2; + boolean weHaveChangedDay = this.previousDays != this.clock.getDays(); + if (weHaveChangedDay) + for (int i = 0; i < 3; i++) // Génère par jour, 3 arbres + GenerateEntity.tree(this); + if (dayTime) { // Génère certaines entités uniquement pendant le jour + GenerateEntity.rabbit(this); + GenerateEntity.tallGrass(this); + } else if (nightTime) // Génère certaines entités uniquement pendant le soir + GenerateEntity.slime(this); + + // Updates toutes les entités + for (Entity entity : this.entities) { + // ajoute les enfants des entités parent. + if (entity instanceof ReproductiveObjectType) + entitiesAtAdded.addAll(((ReproductiveObjectType) entity).reproduction(this)); entity.updates(); } - - this.player.collide(); this.player.updates(); - this.clock.updates(ticks); + this.previousDays = this.clock.getDays(); + this.clock.updates(this.ticks); this.ticks++; })); - loop.getKeyFrames().add(keyFrame); - loop.play(); + this.loop.getKeyFrames().add(keyFrame); + this.loop.play(); + } + + public static Clip playSound(String path, boolean loop) + { + Clip clip = null; + try { + clip = AudioSystem.getClip(); + AudioInputStream inputStream = AudioSystem.getAudioInputStream(new File(Terraria.SRC_PATH + path).toURI().toURL()); + clip.open(inputStream); + } catch (Exception e) { e.printStackTrace(); } + + if (!Objects.isNull(clip)) { + clip.loop((loop) ? Clip.LOOP_CONTINUOUSLY : 0); + clip.start(); + } + + return clip; } public ObservableList getEntities() { return this.entities; } + public ObservableList getRabbits() { return rabbits; } + public ObservableList getTorches() { return torches; } + public ObservableList getSlimes() { return slimes; } public TileMaps getTileMaps() { return this.tileMaps; } public Player getPlayer() { return this.player; } public Clock getGameClock() { return this.clock; } + public Timeline getLoop() { return this.loop; } public int getTicks() { return this.ticks; } } \ No newline at end of file diff --git a/src/main/java/fr/sae/terraria/modele/GenerateEntity.java b/src/main/java/fr/sae/terraria/modele/GenerateEntity.java index 3dfd6f1..2e96b57 100644 --- a/src/main/java/fr/sae/terraria/modele/GenerateEntity.java +++ b/src/main/java/fr/sae/terraria/modele/GenerateEntity.java @@ -1,27 +1,35 @@ package fr.sae.terraria.modele; -import fr.sae.terraria.modele.blocks.TallGrass; -import fr.sae.terraria.modele.blocks.Tree; import fr.sae.terraria.modele.entities.Rabbit; +import fr.sae.terraria.modele.entities.Slime; +import fr.sae.terraria.modele.entities.blocks.TallGrass; +import fr.sae.terraria.modele.entities.blocks.Tree; import fr.sae.terraria.modele.entities.entity.Entity; +import fr.sae.terraria.modele.entities.entity.SpawnableObjectType; import java.util.ArrayList; import java.util.List; import java.util.Random; -import static fr.sae.terraria.modele.blocks.TallGrass.TALL_GRASS_SPAWN_RATE; -import static fr.sae.terraria.modele.blocks.TallGrass.WHEN_SPAWN_A_TALL_GRASS; -import static fr.sae.terraria.modele.blocks.Tree.TREE_SPAWN_RATE; -import static fr.sae.terraria.modele.blocks.Tree.WHEN_SPAWN_A_TREE; import static fr.sae.terraria.modele.entities.Rabbit.RABBIT_SPAWN_RATE; import static fr.sae.terraria.modele.entities.Rabbit.WHEN_SPAWN_A_RABBIT; +import static fr.sae.terraria.modele.entities.Slime.SLIME_SPAWN_RATE; +import static fr.sae.terraria.modele.entities.Slime.WHEN_SPAWN_A_SLIME; +import static fr.sae.terraria.modele.entities.blocks.TallGrass.TALL_GRASS_SPAWN_RATE; +import static fr.sae.terraria.modele.entities.blocks.TallGrass.WHEN_SPAWN_A_TALL_GRASS; +import static fr.sae.terraria.modele.entities.blocks.Tree.TREE_SPAWN_RATE; +import static fr.sae.terraria.modele.entities.blocks.Tree.WHEN_SPAWN_A_TREE; public class GenerateEntity { + public static final int MAX_SPAWN_RABBIT = 100; + public static final int MAX_SPAWN_SLIME = 100; private static final Random random = new Random(); + public GenerateEntity() { super(); } + /** * Génère une entité selon de quand il spawn et du pourcent de change qu'il spawn réellement. * @@ -29,7 +37,7 @@ public class GenerateEntity * @param whenSpawn Le nombre qui determine quand il doit spawn sur la carte * @param spawnRate Le pourcentage de chance qu'il spawn réellement à l'endroit qu'on souhaite le placer */ - private static void generateAnEntity(Environment environment, Entity e, int whenSpawn, double spawnRate) + private static void generateAnEntity(Environment environment, SpawnableObjectType e, int whenSpawn, double spawnRate) { List entities = environment.getEntities(); TileMaps maps = environment.getTileMaps(); @@ -52,18 +60,12 @@ private static void generateAnEntity(Environment environment, Entity e, int when // Verifies au cas où si le tile au-dessus de lui est bien une casse vide (Du ciel) if (maps.getTile(targetFloor, y - 1) == TileMaps.SKY) { for (Entity entity : entities) - if (entity instanceof Tree && xEntity == entity.getX() && yEntity == entity.getY()) - // Un arbre est déjà present ? Il ne le génère pas et arrête complétement la fonction + // Une entité est déjà present ? Il ne le génère pas et arrête complétement la fonction + if (xEntity == entity.getX() && yEntity == entity.getY()) return; - e.setX(xEntity); - e.setY(yEntity); - e.getGravity().setXInit(xEntity); - e.getGravity().setYInit(yEntity); - e.setRect(widthTile, heightTile); - // Une fois une position trouvée, on l'ajoute en tant qu'entité pour qu'il puisse ensuite l'affiché - entities.add(0, e); + e.spawn(xEntity, yEntity); } - // Une fois l'arbre généré, il arrête complétement toute la fonction + // Une fois l'entité générée, il arrête complétement toute la fonction return; } // Sinon on retourne vers la premiere boucle 'for' @@ -85,9 +87,21 @@ private static List findFloors(TileMaps maps, int y) } /** À un certain moment, grace au tick, il va générer des arbres +/- grand uniquement sur un sol */ - public static void tree(Environment environment) { generateAnEntity(environment, new Tree(), WHEN_SPAWN_A_TREE, TREE_SPAWN_RATE); } + public static void tree(Environment environment) { generateAnEntity(environment, new Tree(environment), WHEN_SPAWN_A_TREE, TREE_SPAWN_RATE); } /** À un certain moment, grace au tick, il va générer des hautes herbes sur un sol */ - public static void tallGrass(Environment environment) { generateAnEntity(environment, new TallGrass(), WHEN_SPAWN_A_TALL_GRASS, TALL_GRASS_SPAWN_RATE); } - /** À un certain moment, grace au tick, il va générer des lapins sur un sol */ - public static void rabbit(Environment environment) { generateAnEntity(environment, new Rabbit(environment), WHEN_SPAWN_A_RABBIT, RABBIT_SPAWN_RATE); } + public static void tallGrass(Environment environment) { generateAnEntity(environment, new TallGrass(environment), WHEN_SPAWN_A_TALL_GRASS, TALL_GRASS_SPAWN_RATE); } + + /** À un certain moment, grace au tick et à l'horloge du jeu, il va générer des lapins sur un sol */ + public static void rabbit(Environment environment) + { + if (environment.getRabbits().size() < MAX_SPAWN_RABBIT) + generateAnEntity(environment, new Rabbit(environment), WHEN_SPAWN_A_RABBIT, RABBIT_SPAWN_RATE); + } + + /** À un certain moment, grace au tick et à l'horloge du jeu, il va générer des lapins sur un sol */ + public static void slime(Environment environment) + { + if (environment.getSlimes().size() < MAX_SPAWN_SLIME) + generateAnEntity(environment, new Slime(environment), WHEN_SPAWN_A_SLIME, SLIME_SPAWN_RATE); + } } diff --git a/src/main/java/fr/sae/terraria/modele/TileMaps.java b/src/main/java/fr/sae/terraria/modele/TileMaps.java index a7696be..2a7f312 100644 --- a/src/main/java/fr/sae/terraria/modele/TileMaps.java +++ b/src/main/java/fr/sae/terraria/modele/TileMaps.java @@ -22,13 +22,15 @@ public class TileMaps private int h; + public TileMaps() { super(); } + /** * Compte la taille de la carte et ensuite la charge dans * la variable maps * * @param path Le chemin depuis le root (src) */ - public void load(String path) + public void load(final String path) { boolean widthSave = false; int i = 0; @@ -41,14 +43,14 @@ public void load(String path) // Déduit la taille de la carte. while (jsonReader.hasNext()) { - h++; + this.h++; jsonReader.nextName(); jsonReader.beginArray(); while (jsonReader.hasNext()) { jsonReader.nextInt(); - if (!widthSave) w++; + if (!widthSave) this.w++; } jsonReader.endArray(); @@ -61,7 +63,7 @@ public void load(String path) try (FileReader fileReader = new FileReader(path); JsonReader jsonReader = new JsonReader(fileReader)) { - maps = new int[h][w]; + this.maps = new int[this.h][this.w]; // Ecrit la carte dans la mémoire. jsonReader.beginObject(); while (jsonReader.hasNext()) @@ -70,7 +72,7 @@ public void load(String path) jsonReader.beginArray(); while (jsonReader.hasNext()) { - maps[i][j] = jsonReader.nextInt(); + this.maps[i][j] = jsonReader.nextInt(); j++; } jsonReader.endArray(); @@ -83,9 +85,9 @@ public void load(String path) } - public int getHeight() { return maps.length; } - public int getWidth() { return maps[0].length; } - public int getTile(int x, int y) { return maps[y][x]; } + public int getHeight() { return this.maps.length; } + public int getWidth() { return this.maps[0].length; } + public int getTile(int x, int y) { return this.maps[y][x]; } - public void setTile(int tileIndex, int y, int x) { maps[y][x] = tileIndex; } + public void setTile(int tileIndex, int y, int x) { this.maps[y][x] = tileIndex; } } diff --git a/src/main/java/fr/sae/terraria/modele/blocks/Block.java b/src/main/java/fr/sae/terraria/modele/blocks/Block.java deleted file mode 100644 index 659d28c..0000000 --- a/src/main/java/fr/sae/terraria/modele/blocks/Block.java +++ /dev/null @@ -1,14 +0,0 @@ -package fr.sae.terraria.modele.blocks; - -import fr.sae.terraria.modele.entities.entity.Entity; -import fr.sae.terraria.modele.entities.entity.StowableObjectType; - - -public abstract class Block extends Entity implements StowableObjectType -{ - - - protected Block(int x, int y) { super(x, y); } - - public abstract void updates(); -} diff --git a/src/main/java/fr/sae/terraria/modele/blocks/Dirt.java b/src/main/java/fr/sae/terraria/modele/blocks/Dirt.java deleted file mode 100644 index 72db2af..0000000 --- a/src/main/java/fr/sae/terraria/modele/blocks/Dirt.java +++ /dev/null @@ -1,14 +0,0 @@ -package fr.sae.terraria.modele.blocks; - - -public class Dirt extends Block -{ - - - public Dirt(int x, int y) - { - super(x, y); - } - - public void updates() { } -} diff --git a/src/main/java/fr/sae/terraria/modele/blocks/Grass.java b/src/main/java/fr/sae/terraria/modele/blocks/Grass.java deleted file mode 100644 index 605996b..0000000 --- a/src/main/java/fr/sae/terraria/modele/blocks/Grass.java +++ /dev/null @@ -1,15 +0,0 @@ -package fr.sae.terraria.modele.blocks; - -public class Grass extends Block -{ - public Grass(int x, int y){ - super(x, y); - - } - - @Override - public void updates() - { - - } -} diff --git a/src/main/java/fr/sae/terraria/modele/blocks/Stone.java b/src/main/java/fr/sae/terraria/modele/blocks/Stone.java deleted file mode 100644 index a94ae39..0000000 --- a/src/main/java/fr/sae/terraria/modele/blocks/Stone.java +++ /dev/null @@ -1,23 +0,0 @@ -package fr.sae.terraria.modele.blocks; - - -public class Stone extends Block -{ - /* - TODO: Mettre en place un drop aléatoire de charbon - Si le joueur craft la Stone, il ne drop pas de charbon - Mettre une durabilité - Le nombre de pierre qui est drop est entre 1 et 4 - (Optionnel) Faire un bruitage lorsque le joueur le casse - (Optionnel) Faire des particules de pierre lorsque on est en train de le casser - */ - public Stone(int x, int y){ - super(x, y); - - } - - @Override - public void updates() - { - } -} diff --git a/src/main/java/fr/sae/terraria/modele/blocks/TallGrass.java b/src/main/java/fr/sae/terraria/modele/blocks/TallGrass.java deleted file mode 100644 index c93ff26..0000000 --- a/src/main/java/fr/sae/terraria/modele/blocks/TallGrass.java +++ /dev/null @@ -1,74 +0,0 @@ -package fr.sae.terraria.modele.blocks; - -import fr.sae.terraria.modele.Environment; -import fr.sae.terraria.modele.TileMaps; -import fr.sae.terraria.modele.entities.entity.Entity; -import fr.sae.terraria.modele.entities.entity.ReproductiveObjectType; -import javafx.beans.property.DoubleProperty; -import javafx.beans.property.SimpleDoubleProperty; - -import java.util.ArrayList; -import java.util.List; - - -public class TallGrass extends Block implements ReproductiveObjectType -{ - public static final int WHEN_SPAWN_A_TALL_GRASS = 2_500; - public static final double TALL_GRASS_SPAWN_RATE = .3; - public static final double REPRODUCTION_RATE = 500; - public static final double GROWTH_SPEED = .0005; - public static final int GROWTH_TALL_GRASS_STEP = 6; - public static final int LOOTS_FIBRE_MAX = 3; - - private DoubleProperty tallGrassGrowth; - - - public TallGrass(int x, int y) - { - super(x, y); - - this.tallGrassGrowth = new SimpleDoubleProperty(0); - } - - public TallGrass() { this(0, 0); } - - public void updates() - { - if (tallGrassGrowth.get() < GROWTH_TALL_GRASS_STEP) - tallGrassGrowth.set(tallGrassGrowth.get() + GROWTH_SPEED); - } - - public List reproduction(Environment environment) - { - List children = new ArrayList<>(); - List entities = environment.getEntities(); - - int left = 0; - int right = 0; - for (int x = 0; x < entities.size(); x++) { - if (entities.get(x).getX() == (getX() - environment.widthTile) && entities.get(x).getY() == getY()) - left++; - if (entities.get(x).getX() == (getX() + environment.widthTile) && entities.get(x).getY() == getY()) - right++; - } - - int x = -1; - int y = (int) (getY()/environment.heightTile)+1; - if (left == 0) - x = (int) (getX() - environment.widthTile)/environment.widthTile; - else if (right == 0) - x = (int) (getX() + environment.widthTile)/environment.widthTile; - - if ((x >= 0 && x < environment.getTileMaps().getWidth()) && (y >= 0 && y < environment.getTileMaps().getHeight())) { - if (environment.getTileMaps().getTile(x, y) != TileMaps.SKY) { - TallGrass tallGrassChildren = new TallGrass((int) ((left == 0) ? (getX() - environment.widthTile) : (getX() + environment.widthTile)), (int) getY()); - children.add(tallGrassChildren); - } - } - - return children; - } - - - public DoubleProperty getTallGrassGrowthProperty() { return this.tallGrassGrowth; } -} diff --git a/src/main/java/fr/sae/terraria/modele/blocks/Tree.java b/src/main/java/fr/sae/terraria/modele/blocks/Tree.java deleted file mode 100644 index 9f11d9e..0000000 --- a/src/main/java/fr/sae/terraria/modele/blocks/Tree.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.sae.terraria.modele.blocks; - - -public class Tree extends Block -{ - public static final int WHEN_SPAWN_A_TREE = 5_000; - public static final double TREE_SPAWN_RATE = .2; - - - public Tree(int x, int y) { super(x, y); } - public Tree() { this(0, 0); } - - public void updates() - { - - } -} diff --git a/src/main/java/fr/sae/terraria/modele/entities/Arrow.java b/src/main/java/fr/sae/terraria/modele/entities/Arrow.java index 1e5a702..40b9b46 100644 --- a/src/main/java/fr/sae/terraria/modele/entities/Arrow.java +++ b/src/main/java/fr/sae/terraria/modele/entities/Arrow.java @@ -1,19 +1,32 @@ package fr.sae.terraria.modele.entities; +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.entities.entity.CollideObjectType; import fr.sae.terraria.modele.entities.entity.Entity; +import fr.sae.terraria.modele.entities.entity.MovableObjectType; import fr.sae.terraria.modele.entities.entity.StowableObjectType; -public class Arrow extends Entity implements StowableObjectType +public class Arrow extends Entity implements StowableObjectType, MovableObjectType, CollideObjectType { + private final Environment environment; - public Arrow(int x, int y, int velocity) + public Arrow(final Environment environment, int x, int y, int velocity) { super(x, y); + this.environment = environment; this.velocity = velocity; } - public void updates() { } + @Override public void updates() { /* TODO document why this method is empty */ } + @Override public void move() { /* TODO document why this method is empty */ } + @Override public void collide() { /* TODO document why this method is empty */ } + + @Override public void moveRight() { super.moveRight(); } + @Override public void moveLeft() { super.moveLeft(); } + @Override public void jump() { /* UNE FLECHE NE PEUT SAUTER */ } + @Override public void fall() { super.fall(); } + @Override public void worldLimit() { super.worldLimit(this.environment); } } diff --git a/src/main/java/fr/sae/terraria/modele/entities/Player.java b/src/main/java/fr/sae/terraria/modele/entities/Player.java deleted file mode 100644 index 56474dd..0000000 --- a/src/main/java/fr/sae/terraria/modele/entities/Player.java +++ /dev/null @@ -1,242 +0,0 @@ -package fr.sae.terraria.modele.entities; - -import fr.sae.terraria.modele.Environment; -import fr.sae.terraria.modele.TileMaps; -import fr.sae.terraria.modele.blocks.Dirt; -import fr.sae.terraria.modele.blocks.Stone; -import fr.sae.terraria.modele.entities.entity.Animation; -import fr.sae.terraria.modele.entities.entity.CollideObjectType; -import fr.sae.terraria.modele.entities.entity.Entity; -import fr.sae.terraria.modele.entities.entity.StowableObjectType; -import javafx.beans.property.IntegerProperty; -import javafx.beans.property.SimpleIntegerProperty; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.input.KeyCode; - -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; - - -public class Player extends Entity implements CollideObjectType -{ - public static final int BREAK_BLOCK_DISTANCE = 1; - public static final int BLOCK_STACKING_MAX = 16; - public static final int NB_CASES_MAX_INVENTORY = 27; - public static final int NB_LINES_INVENTORY = 3; - - private final Map> inventory; - private final EnumMap keysInput; - - public IntegerProperty positionOfCursorInventoryBar; - - private StowableObjectType itemSelected; - - private Environment environment; - - - /** - * @param x La position du joueur en X - * @param y La position du joueur en Y - */ - public Player(Environment environment, int x, int y) - { - super(x, y); - this.environment = environment; - - this.animation = new Animation(); - this.keysInput = new EnumMap<>(KeyCode.class); - this.inventory = new HashMap<>(); - this.positionOfCursorInventoryBar = new SimpleIntegerProperty(0); - - for (int i = 0; i < NB_CASES_MAX_INVENTORY; i++) - this.inventory.put(i, FXCollections.observableArrayList()); - } - - public void updates() - { - // Applique les déplacements selon les valeurs de l'offset - // this.setX(this.x.get() + this.offset[0] * this.velocity); - - if (this.offset[1] == Entity.IDLE && !air) { - this.gravity.xInit = this.x.get(); - this.gravity.yInit = this.y.get(); - this.gravity.vInit = this.velocity; - this.gravity.degInit = -90; - - this.gravity.timer = .0; - } - - this.setX(this.getX() + this.offset[0] * this.getVelocity()); - - if (this.rect != null) - this.rect.updates(x.get(), y.get()); - animation.loop(); - } - - public void collide() - { - int widthTile = environment.widthTile; int heightTile = environment.heightTile; - TileMaps tileMaps = environment.getTileMaps(); - - // Detection vide en dessous - int yBottom = (int) (getY()+getRect().getHeight()-COLLISION_TOLERANCE)/heightTile; - int posX = (int) ((getX()+((offset[0] < 0) ? COLLISION_TOLERANCE : -COLLISION_TOLERANCE)) + ((offset[0] > 0) ? getRect().getWidth() : 0))/widthTile; - - boolean footInTheVoid = tileMaps.getTile(posX, yBottom+1) == TileMaps.SKY; - if (footInTheVoid) - this.air = true; - - // Detection collision gauche droite - if (this.offset[0] != Entity.IDLE) { - int yTop = (int) (getY()+COLLISION_TOLERANCE)/heightTile; - int futurePositionX = (int) ((getX()+((offset[0] < 0) ? COLLISION_TOLERANCE : -COLLISION_TOLERANCE)+(velocity*offset[0])) + ((offset[0] > 0) ? getRect().getWidth() : 0))/widthTile; - - // Il gère les deux car futurePositionX change dynamiquement suivant l'offset - boolean isCollideLeftOrRight = tileMaps.getTile(futurePositionX, yTop) != TileMaps.SKY || tileMaps.getTile(futurePositionX, yBottom) != TileMaps.SKY; - if (isCollideLeftOrRight) - this.offset[0] = Entity.IDLE; - } - - // Detection collision en bas et en haut - if (this.offset[1] != Entity.IDLE) { - int xLeft = (int) (getX()+COLLISION_TOLERANCE)/widthTile; - int xRight = (int) ((getX()+getRect().getWidth())-COLLISION_TOLERANCE)/widthTile; - - // Tombe - if (this.offset[1] == Entity.IS_FALLING) { - this.gravity.degInit = 0; - double futurePositionY = gravity.formulaOfTrajectory() + rect.getHeight(); - - boolean isCollideBottom = tileMaps.getTile(xLeft, (int) (futurePositionY + COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY || tileMaps.getTile(xRight, (int) (futurePositionY + COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY; - if (isCollideBottom) { - this.setJumpPosInit(); - this.gravity.timer = 0; - this.offset[1] = Entity.IDLE; - } else setY(futurePositionY); - // Saute - } else if (this.offset[1] == Entity.IS_JUMPING) { - double futurePositionY = gravity.formulaOfTrajectory(); - this.air = true; - - boolean isCollideTop = tileMaps.getTile(xLeft, (int) (futurePositionY + COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY || tileMaps.getTile(xRight, (int) (futurePositionY + COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY; - - // Quand le joueur monte - if ((gravity.flightTime/2) >= gravity.timer) { - if (isCollideTop) { - this.fall(); - } else setY(futurePositionY); - // Quand le joueur decent - } else { - boolean isCollideBottom = tileMaps.getTile(xLeft, (int) ((futurePositionY + rect.getHeight()) - COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY || tileMaps.getTile(xRight,(int) ((futurePositionY + rect.getHeight()) - COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY; - - if (isCollideTop) { - this.fall(); - } else if (isCollideBottom) { - this.setJumpPosInit(); - this.gravity.timer = 0; - this.offset[1] = Entity.IDLE; - this.air = false; - } else setY(futurePositionY); - } - } - } else if (this.air) { - this.gravity.degInit = 0; - int xLeft = (int) (getX()+COLLISION_TOLERANCE)/widthTile; - int xRight = (int) (getX()-COLLISION_TOLERANCE+getRect().getWidth())/widthTile; - double futurePositionY = this.gravity.formulaOfTrajectory() + this.rect.getHeight(); - - boolean isCollideBottom = tileMaps.getTile(xLeft, (int) (futurePositionY - COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY || tileMaps.getTile(xRight, (int) (futurePositionY - COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY; - if (isCollideBottom) { - this.setJumpPosInit(); - this.offset[1] = Entity.IDLE; - this.air = false; - } else setY(futurePositionY - this.rect.getHeight()); - } - } - - /** Lie les inputs au clavier à une ou des actions. */ - public void eventInput() - { - this.keysInput.forEach((key, value) -> { - if (Boolean.TRUE.equals(value)) { - if (key == KeyCode.Z || key == KeyCode.SPACE) - if (this.offset[1] != -1) this.jump(); - - if (key == KeyCode.D) - this.moveRight(); - else if (key == KeyCode.Q) - this.moveLeft(); - - if (key == KeyCode.DIGIT1) - this.positionOfCursorInventoryBar.set(0); - else if (key == KeyCode.DIGIT2) - this.positionOfCursorInventoryBar.set(1); - else if (key == KeyCode.DIGIT3) - this.positionOfCursorInventoryBar.set(2); - else if (key == KeyCode.DIGIT4) - this.positionOfCursorInventoryBar.set(3); - else if (key == KeyCode.DIGIT5) - this.positionOfCursorInventoryBar.set(4); - else if (key == KeyCode.DIGIT6) - this.positionOfCursorInventoryBar.set(5); - else if (key == KeyCode.DIGIT7) - this.positionOfCursorInventoryBar.set(6); - else if (key == KeyCode.DIGIT8) - this.positionOfCursorInventoryBar.set(7); - else if (key == KeyCode.DIGIT9) - this.positionOfCursorInventoryBar.set(8); - } - }); - } - - public int nbStacksIntoInventory() - { - int counter = 0; - for (int i = 0; i < inventory.size(); i++) - counter += (!this.inventory.get(i).isEmpty() && this.inventory.get(i).get(0) != null) ? 1 : 0; - - return counter; - } - - public void pickup(StowableObjectType pickupObject) - { - int nbStacksInventory = nbStacksIntoInventory(); - boolean estComplet = false; - - if (nbStacksInventory < NB_CASES_MAX_INVENTORY) { - int i = 0; - while (i < this.inventory.size()) { - int beforeSize = this.inventory.get(i).size(); - if (this.inventory.get(i).isEmpty()) { - this.inventory.get(i).add(pickupObject); - this.setItemSelected(pickupObject); - } - else if (this.inventory.get(i).size() == BLOCK_STACKING_MAX) - estComplet = true; - else if (this.inventory.get(i).get(0) instanceof Dirt && pickupObject instanceof Dirt) { - this.inventory.get(i).add(pickupObject); - estComplet = false; - } else if (this.inventory.get(i).get(0) instanceof Stone && pickupObject instanceof Stone) { - this.inventory.get(i).add(pickupObject); - estComplet = false; - } - - // Quand un objet a étais mise dans l'inventaire, il arrête la fonction - if (beforeSize != this.inventory.get(i).size()) return; - i++; - } - - if (estComplet) - this.inventory.get(nbStacksInventory).add(pickupObject); - } - } - - - public Map> getInventory() { return inventory; } - public Map getKeysInput() { return keysInput; } - public StowableObjectType getItemSelected() { return itemSelected; } - - public void setItemSelected(StowableObjectType itemSelected) { this.itemSelected = itemSelected; } -} diff --git a/src/main/java/fr/sae/terraria/modele/entities/Rabbit.java b/src/main/java/fr/sae/terraria/modele/entities/Rabbit.java index ba97c78..8d8d32f 100644 --- a/src/main/java/fr/sae/terraria/modele/entities/Rabbit.java +++ b/src/main/java/fr/sae/terraria/modele/entities/Rabbit.java @@ -1,17 +1,18 @@ package fr.sae.terraria.modele.entities; import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.GenerateEntity; import fr.sae.terraria.modele.TileMaps; -import fr.sae.terraria.modele.entities.entity.Animation; -import fr.sae.terraria.modele.entities.entity.CollideObjectType; -import fr.sae.terraria.modele.entities.entity.Entity; -import fr.sae.terraria.modele.entities.entity.ReproductiveObjectType; +import fr.sae.terraria.modele.entities.entity.*; +import fr.sae.terraria.modele.entities.items.Meat; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Objects; -public class Rabbit extends Entity implements CollideObjectType, ReproductiveObjectType +public class Rabbit extends Entity implements CollideObjectType, ReproductiveObjectType, MovableObjectType, CollapsibleObjectType, SpawnableObjectType { public static final int WHEN_SPAWN_A_RABBIT = 2_500; public static final double RABBIT_SPAWN_RATE = .2; @@ -20,26 +21,27 @@ public class Rabbit extends Entity implements CollideObjectType, ReproductiveObj public static final double LUCK_OF_JUMPING = .5; public static final int JUMP_FREQUENCY = 50; - private Environment environment; - private Animation animation; + private final Environment environment; + private final Animation animation; - public Rabbit(Environment environment, int x, int y) + public Rabbit(final Environment environment, int x, int y) { super(x, y); this.environment = environment; + this.setPv(3); this.animation = new Animation(); this.velocity = 1; this.offset[0] = (Math.random() <= .5) ? Entity.IS_MOVING_RIGHT : Entity.IS_MOVING_LEFT; this.gravity.amplitude = 40; } - public Rabbit(Environment environment) { this(environment, 0, 0); } + public Rabbit(final Environment environment) { this(environment, 0, 0); } - public void updates() + @Override public void updates() { - if (this.offset[1] == Entity.IDLE && !air) { + if (this.offset[1] == Entity.IDLE && !this.air) { this.gravity.xInit = this.x.get(); this.gravity.yInit = this.y.get(); this.gravity.vInit = this.velocity; @@ -48,111 +50,100 @@ public void updates() this.gravity.timer = .0; } - this.setX(this.x.get() + this.offset[0] * this.velocity); + this.collide(); + this.move(); + this.worldLimit(); - if (this.rect != null) + if (!Objects.isNull(this.rect)) this.rect.updates(x.get(), y.get()); this.animation.loop(); } - public List reproduction(Environment environment) + @Override public void move() { - List children = new ArrayList<>(); + this.setX(this.x.get() + this.offset[0] * this.velocity); - return children; + if (this.offset[1] == Entity.IDLE && this.offset[0] != Entity.IDLE) { + int xProbablyVoid = (int) ((getX()+((this.offset[0] == Entity.IS_MOVING_LEFT) ? 0 : this.environment.widthTile)) / this.environment.widthTile); + int yProbablyVoid = (int) (getY() / environment.heightTile); + + // Si du vide risque d'y avoir lors de son déplacement + if (environment.getTileMaps().getTile(xProbablyVoid, yProbablyVoid + 2) == TileMaps.SKY) { + this.offset[0] = (-1) * this.offset[0]; + } else { + boolean mustJump = this.environment.getTicks() % Rabbit.JUMP_FREQUENCY == 0; + if (mustJump) { + boolean jumpOrNot = Math.random() < Rabbit.LUCK_OF_JUMPING; + if (jumpOrNot) { + this.jump(); + this.gravity.degInit = -90; + } + } + } + } } - public void collide() + @Override public List reproduction(final Environment environment) { - int widthTile = environment.widthTile; int heightTile = environment.heightTile; - TileMaps tileMaps = environment.getTileMaps(); - - // Detection vide en dessous - int yBottom = (int) (getY()+getRect().getHeight()-COLLISION_TOLERANCE)/heightTile; - int posX = (int) ((getX()+((offset[0] < 0) ? COLLISION_TOLERANCE : -COLLISION_TOLERANCE)) + ((offset[0] > 0) ? getRect().getWidth() : 0))/widthTile; + List children = new ArrayList<>(); + if (environment.getRabbits().size() < GenerateEntity.MAX_SPAWN_RABBIT) { + // TODO les lapins doivent se reproduire + } - boolean footInTheVoid = tileMaps.getTile(posX, yBottom+1) == TileMaps.SKY; - if (footInTheVoid) - this.air = true; + return children; + } - // Detection collision gauche droite - if (this.offset[0] != Entity.IDLE) { - int yTop = (int) (getY()+COLLISION_TOLERANCE)/heightTile; - int futurePositionX = (int) ((getX()+((offset[0] < 0) ? COLLISION_TOLERANCE : -COLLISION_TOLERANCE)+(velocity*offset[0])) + ((offset[0] > 0) ? getRect().getWidth() : 0))/widthTile; + @Override public void collide() + { + Map whereCollide = super.collide(this.environment); - // Il gère les deux car futurePositionX change dynamiquement suivant l'offset - boolean isCollideLeftOrRight = tileMaps.getTile(futurePositionX, yTop) != TileMaps.SKY || tileMaps.getTile(futurePositionX, yBottom) != TileMaps.SKY; - if (isCollideLeftOrRight) + if (!whereCollide.isEmpty()) { + if (whereCollide.get("left").equals(Boolean.TRUE) || whereCollide.get("right").equals(Boolean.TRUE)) this.offset[0] = (-1) * this.offset[0]; } + } - // Detection collision en bas et en haut - if (this.offset[1] != Entity.IDLE) { - int xLeft = (int) (getX()+COLLISION_TOLERANCE)/widthTile; - int xRight = (int) ((getX()+getRect().getWidth())-COLLISION_TOLERANCE)/widthTile; - - // Tombe - if (this.offset[1] == Entity.IS_FALLING) { - this.gravity.degInit = 0; - double futurePositionY = gravity.formulaOfTrajectory() + rect.getHeight(); - - boolean isCollideBottom = tileMaps.getTile(xLeft, (int) (futurePositionY + COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY || tileMaps.getTile(xRight, (int) (futurePositionY + COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY; - if (isCollideBottom) { - this.setJumpPosInit(); - this.gravity.timer = 0; - this.offset[1] = Entity.IDLE; - } else setY(futurePositionY); - // Saute - } else if (this.offset[1] == Entity.IS_JUMPING) { - double futurePositionY = gravity.formulaOfTrajectory(); - this.air = true; - - boolean isCollideTop = tileMaps.getTile(xLeft, (int) (futurePositionY + COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY || tileMaps.getTile(xRight, (int) (futurePositionY + COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY; - - // Quand le joueur monte - if ((gravity.flightTime/2) >= gravity.timer) { - if (isCollideTop) { - this.fall(); - } else setY(futurePositionY); - // Quand le joueur decent - } else { - boolean isCollideBottom = tileMaps.getTile(xLeft, (int) ((futurePositionY + rect.getHeight()) - COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY || tileMaps.getTile(xRight,(int) ((futurePositionY + rect.getHeight()) - COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY; - - if (isCollideTop) { - this.fall(); - } else if (isCollideBottom) { - this.setJumpPosInit(); - this.gravity.timer = 0; - this.offset[1] = Entity.IDLE; - this.air = false; - } else setY(futurePositionY); - } - } - } else if (this.air) { - this.gravity.degInit = 0; - int xLeft = (int) (getX()+COLLISION_TOLERANCE)/widthTile; - int xRight = (int) (getX()-COLLISION_TOLERANCE+getRect().getWidth())/widthTile; - double futurePositionY = this.gravity.formulaOfTrajectory() + this.rect.getHeight(); - - boolean isCollideBottom = tileMaps.getTile(xLeft, (int) (futurePositionY - COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY || tileMaps.getTile(xRight, (int) (futurePositionY - COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY; - if (isCollideBottom) { - this.setJumpPosInit(); - this.offset[1] = Entity.IDLE; - this.air = false; - } else setY(futurePositionY - this.rect.getHeight()); - } + @Override public void hit() + { + Environment.playSound("sound/daggerswipe.wav", false); - // TODO: Ce n'est pas parfait - /* - if (environment.getPlayer().getRect().collideRect(rect)) - offset[0] = (-1) * offset[0]; - */ - } + if (this.getPv() <= 0) { + this.environment.getPlayer().pickup(new Meat(this.environment)); + this.environment.getRabbits().remove(this); + this.environment.getEntities().remove(this); + } + this.setPv(this.getPv() - 1); + } - public Animation getAnimation() { return animation; } -} + @Override public void spawn(final int x, final int y) + { + Environment.playSound("sound/Rabbit_Spawn.wav", false); + + this.setX(x); + this.setY(y); + this.getGravity().setXInit(x); + this.getGravity().setYInit(y); + this.setRect(environment.widthTile, environment.heightTile); + this.environment.getEntities().add(0, this); + this.environment.getRabbits().add(0, this); + } + /** Modifie l'offset qui permet de le déplacer vers la droite */ + @Override public void moveRight() { super.moveRight(); } + /** Modifie l'offset qui permet de le déplacer vers la gauche */ + @Override public void moveLeft() { super.moveLeft(); } + /** Modifie l'offset qui permet de le faire sauter */ + @Override public void jump() { super.jump(); } + /** Modifie l'offset qui permet de tomber */ + @Override public void fall() { super.fall(); } + @Override public void worldLimit() + { + if (super.worldLimit(this.environment)) + this.offset[0] = (-1) * this.offset[0]; + } + @Override public Animation getAnimation() { return this.animation; } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/Slime.java b/src/main/java/fr/sae/terraria/modele/entities/Slime.java index edb9664..721fd28 100644 --- a/src/main/java/fr/sae/terraria/modele/entities/Slime.java +++ b/src/main/java/fr/sae/terraria/modele/entities/Slime.java @@ -1,23 +1,99 @@ package fr.sae.terraria.modele.entities; -import fr.sae.terraria.modele.entities.entity.CollideObjectType; -import fr.sae.terraria.modele.entities.entity.Entity; -import javafx.beans.property.SimpleDoubleProperty; +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.entities.entity.*; +import java.util.Map; +import java.util.Objects; -public class Slime extends Entity implements CollideObjectType + +public class Slime extends Entity implements CollideObjectType, MovableObjectType, CollapsibleObjectType, SpawnableObjectType { + public static final int WHEN_SPAWN_A_SLIME = 2_500; + public static final double SLIME_SPAWN_RATE = .2; + + private final Environment environment; - public Slime(int x, int y, double pv, double velocity) + public Slime(Environment environment, int x, int y) { super(x, y); + this.environment = environment; + this.velocity = 2; + + this.setPv(3); + this.animation = new Animation(); + + this.gravity.amplitude = 25; + this.gravity.degInit = -90; + } + + public Slime(Environment environment) { this(environment, 0, 0); } + + @Override public void updates() { + if (this.offset[1] == Entity.IDLE && !this.air) { + this.gravity.xInit = this.x.get(); + this.gravity.yInit = this.y.get(); + this.gravity.vInit = this.velocity; + this.gravity.degInit = -90; + this.gravity.timer = .0; + } + + this.offset[0] = Entity.IDLE; + if (this.offset[1] == Entity.IS_JUMPING) { + if (environment.getPlayer().getX() > this.x.getValue()) + this.offset[0] = Entity.IS_MOVING_RIGHT; + else if (environment.getPlayer().getX() < this.x.getValue()) + this.offset[0] = Entity.IS_MOVING_LEFT; + } + + this.move(); + this.collide(); // FIXME: 08/06/2022 : idk pourquoi le collide pose probleme pour le saut du slime + this.worldLimit(); + + if (!Objects.isNull(this.rect)) + this.rect.updates(x.get(), y.get()); + this.animation.loop(); + } + + @Override public void collide() { + Map whereCollide = super.collide(this.environment); - this.pv = new SimpleDoubleProperty(pv); - this.velocity = velocity; + if (!whereCollide.isEmpty()) + if (whereCollide.get("left").equals(Boolean.TRUE) || whereCollide.get("right").equals(Boolean.TRUE)) + this.offset[0] = Entity.IDLE; } - public void updates() { } + @Override public void move() + { + if (((int) (this.animation.getFrame()) == 3)) + if (this.offset[1] != Entity.IS_FALLING) this.jump(); + this.setX(this.getX() + (this.offset[0] * this.velocity)); + } + + @Override public void hit() + { + Environment.playSound("sound/daggerswipe.wav", false); + } + + @Override public void spawn(int x, int y) + { + this.setX(x); + this.setY(y); + this.getGravity().setXInit(x); + this.getGravity().setYInit(y); + this.setRect(environment.widthTile, environment.heightTile); + this.environment.getEntities().add(0, this); + this.environment.getSlimes().add(0, this); + } + + @Override public void moveRight() { super.moveRight(); } + + @Override public void moveLeft() { super.moveLeft(); } + + @Override public void jump() { super.jump(); } + + @Override public void fall() { super.fall(); } - public void collide() { } + @Override public void worldLimit() { super.worldLimit(this.environment); } } diff --git a/src/main/java/fr/sae/terraria/modele/entities/blocks/Block.java b/src/main/java/fr/sae/terraria/modele/entities/blocks/Block.java new file mode 100644 index 0000000..90b82ba --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/blocks/Block.java @@ -0,0 +1,44 @@ +package fr.sae.terraria.modele.entities.blocks; + +import fr.sae.terraria.Terraria; +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.entities.entity.BreakableObjectType; +import fr.sae.terraria.modele.entities.entity.Entity; +import javafx.animation.KeyFrame; +import javafx.animation.Timeline; +import javafx.util.Duration; + + +public abstract class Block extends Entity implements BreakableObjectType +{ + + + protected Block(int x, int y) + { + super(x, y); + } + + protected void breakAnimation(final Environment environment, final Block block, double xOrigin, double yOrigin) + { + Timeline timeline = new Timeline(); + int animationCycleCount = 5; + int[] time = new int[1]; + // Animation de cassure du bloc + timeline.setCycleCount(animationCycleCount); + KeyFrame keyFrame = new KeyFrame(Duration.seconds(Terraria.TARGET_FPS), (ev -> { + block.setX(xOrigin + (Math.cos(time[0])*environment.scaleMultiplicatorWidth)); + block.setY(yOrigin + (-Math.sin(time[0]*environment.scaleMultiplicatorHeight))); + + time[0]++; + })); + timeline.getKeyFrames().add(keyFrame); + // Faire revenir le bloc à sa position initiale lorsque l'animation est arrêté + timeline.statusProperty().addListener(c -> { + block.setX(xOrigin); + block.setY(yOrigin); + }); + timeline.play(); + } + + @Override public abstract void updates(); +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/blocks/Dirt.java b/src/main/java/fr/sae/terraria/modele/entities/blocks/Dirt.java new file mode 100644 index 0000000..8cf8f06 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/blocks/Dirt.java @@ -0,0 +1,73 @@ +package fr.sae.terraria.modele.entities.blocks; + +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.TileMaps; +import fr.sae.terraria.modele.entities.entity.CollideObjectType; +import fr.sae.terraria.modele.entities.entity.Entity; +import fr.sae.terraria.modele.entities.entity.PlaceableObjectType; +import fr.sae.terraria.modele.entities.entity.StowableObjectType; +import fr.sae.terraria.modele.entities.player.Player; +import fr.sae.terraria.modele.entities.player.inventory.Inventory; + +import java.util.Objects; + + +public class Dirt extends Block implements StowableObjectType, CollideObjectType, PlaceableObjectType +{ + public static final int BREAK_RESISTANCE = 2; + + private final Environment environment; + + private final double xOrigin; + private final double yOrigin; + + + public Dirt(Environment environment, int x, int y) + { + super(x, y); + this.environment = environment; + + this.xOrigin = x; + this.yOrigin = y; + + this.pv.set(Dirt.BREAK_RESISTANCE); + } + + @Override public void updates() { /* TODO document why this method is empty */ } + + @Override public void collide() { /* NE RIEN REMPLIR */ } + + @Override public void breaks() + { + Environment.playSound("sound/grassyStep.wav", false); + this.breakAnimation(environment, this, xOrigin, yOrigin); + + if (this.getPv() <= 0) { + this.environment.getPlayer().pickup(this); + + int yIndexTile = (int) (getY()/environment.heightTile); + int xIndexTile = (int) (getX()/environment.widthTile); + this.environment.getTileMaps().setTile(TileMaps.SKY, yIndexTile, xIndexTile); + this.environment.getEntities().remove(this); + } + this.setPv(this.getPv() - 1); + } + + @Override public void place(final int x, final int y) + { + Environment.playSound("sound/axchop.wav", false); + int widthTile = this.environment.widthTile; + int heightTile = this.environment.heightTile; + + Entity entity = new Dirt(this.environment, x*widthTile, y*heightTile); + entity.setRect(widthTile, heightTile); + + Player player = this.environment.getPlayer(); + Inventory inventory = player.getInventory(); + if (!Objects.isNull(player.getStackSelected())) + inventory.get().get(inventory.getPosCursor()).remove(); + + this.environment.getTileMaps().setTile(TileMaps.DIRT, y, x); + this.environment.getEntities().add(0, entity); + } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/blocks/Grass.java b/src/main/java/fr/sae/terraria/modele/entities/blocks/Grass.java new file mode 100644 index 0000000..7e07df6 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/blocks/Grass.java @@ -0,0 +1,17 @@ +package fr.sae.terraria.modele.entities.blocks; + +import fr.sae.terraria.modele.Environment; + +public class Grass extends Block +{ + + + public Grass(int x, int y) { super(x, y); } + + @Override public void updates() { /* TODO document why this method is empty */ } + + @Override public void breaks() + { + Environment.playSound("sound/grassyStep.wav", false); + } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/blocks/Stone.java b/src/main/java/fr/sae/terraria/modele/entities/blocks/Stone.java new file mode 100644 index 0000000..c96fb32 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/blocks/Stone.java @@ -0,0 +1,84 @@ +package fr.sae.terraria.modele.entities.blocks; + +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.TileMaps; +import fr.sae.terraria.modele.entities.entity.CollideObjectType; +import fr.sae.terraria.modele.entities.entity.Entity; +import fr.sae.terraria.modele.entities.entity.PlaceableObjectType; +import fr.sae.terraria.modele.entities.entity.StowableObjectType; +import fr.sae.terraria.modele.entities.player.Player; +import fr.sae.terraria.modele.entities.player.inventory.Inventory; +import fr.sae.terraria.modele.entities.player.inventory.Stack; +import fr.sae.terraria.modele.entities.tools.Pickaxe; +import fr.sae.terraria.modele.entities.tools.Tool; + +import java.util.Objects; + + +public class Stone extends Block implements StowableObjectType, CollideObjectType, PlaceableObjectType +{ + public static final int BREAK_RESISTANCE = 5; + + private final Environment environment; + + private final double xOrigin; + private final double yOrigin; + + + public Stone(Environment environment, int x, int y) + { + super(x, y); + this.environment = environment; + + this.xOrigin = x; + this.yOrigin = y; + + this.pv.set(Stone.BREAK_RESISTANCE); + } + + @Override public void updates() { /* TODO document why this method is empty */ } + + @Override public void collide() { /* NE RIEN REMPLIR */ } + + @Override public void breaks() + { + Environment.playSound("sound/brick" + ((int) (Math.random()*2)+1) + ".wav", false); + this.breakAnimation(this.environment, this, this.xOrigin, this.yOrigin); + + // Une fois le bloc détruit, il donne la pierre et le supprime de la TileMaps + Player player = this.environment.getPlayer(); + if (this.getPv() <= 0) { + player.pickup(this); + + int yIndexTile = (int) (getY()/this.environment.heightTile); + int xIndexTile = (int) (getX()/this.environment.widthTile); + this.environment.getTileMaps().setTile(TileMaps.SKY, yIndexTile, xIndexTile); + this.environment.getEntities().remove(this); + } + + // S'il utilise le bon outil, il commencera à casser le bloc sinon use l'outil sans casser le bloc. + Stack stack = player.getStackSelected(); + if (stack.getItem() instanceof Pickaxe) + this.setPv(this.getPv() - 1); + if (stack.getItem() instanceof Tool) + ((Tool) stack.getItem()).use(); + } + + @Override public void place(int x, int y) + { + Environment.playSound("sound/axchop.wav", false); + int widthTile = this.environment.widthTile; + int heightTile = this.environment.heightTile; + + Entity entity = new Stone(this.environment, x*widthTile, y*heightTile); + entity.setRect(widthTile, heightTile); + + Player player = this.environment.getPlayer(); + Inventory inventory = player.getInventory(); + if (!Objects.isNull(player.getStackSelected())) + inventory.get().get(inventory.getPosCursor()).remove(); + + this.environment.getTileMaps().setTile(TileMaps.STONE, y, x); + this.environment.getEntities().add(0, entity); + } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/blocks/TallGrass.java b/src/main/java/fr/sae/terraria/modele/entities/blocks/TallGrass.java new file mode 100644 index 0000000..9fd6929 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/blocks/TallGrass.java @@ -0,0 +1,117 @@ +package fr.sae.terraria.modele.entities.blocks; + +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.TileMaps; +import fr.sae.terraria.modele.entities.entity.Entity; +import fr.sae.terraria.modele.entities.entity.ReproductiveObjectType; +import fr.sae.terraria.modele.entities.entity.SpawnableObjectType; +import fr.sae.terraria.modele.entities.items.Fiber; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.SimpleDoubleProperty; + +import java.util.ArrayList; +import java.util.List; + + +public class TallGrass extends Block implements ReproductiveObjectType, SpawnableObjectType +{ + public static final int WHEN_SPAWN_A_TALL_GRASS = 2_500; + public static final double TALL_GRASS_SPAWN_RATE = .3; + public static final double REPRODUCTION_RATE = 500; + public static final double GROWTH_SPEED = .0005; + public static final int GROWTH_TALL_GRASS_STEP = 6; + public static final int LOOTS_FIBRE_MAX = 3; + + private final DoubleProperty tallGrassGrowth; + + private final Environment environment; + + + public TallGrass(Environment environment, int x, int y) + { + super(x, y); + this.environment = environment; + + this.tallGrassGrowth = new SimpleDoubleProperty(0); + } + + public TallGrass(Environment environment) { this(environment, 0, 0); } + + @Override public void updates() + { + // L'animation de pousse + if (tallGrassGrowth.get() < GROWTH_TALL_GRASS_STEP) + tallGrassGrowth.set(tallGrassGrowth.get() + GROWTH_SPEED); + } + + /** Joue un son et donne au joueur entre 1 et 3 de fibre */ + @Override public void breaks() + { + Environment.playSound("sound/cut.wav", false); + + for (int loot = (int) (Math.random()*3)+1; loot < LOOTS_FIBRE_MAX; loot++) + this.environment.getPlayer().pickup(new Fiber()); + this.environment.getEntities().remove(this); + } + + /** Reproduit les hautes herbes à gauche et à droite de la haute herbe parente */ + @Override public List reproduction(Environment environment) + { + List children = new ArrayList<>(); + + boolean tallGrassMustReproduce = environment.getTicks()%TallGrass.REPRODUCTION_RATE == 0; + if (tallGrassMustReproduce) { + List entities = environment.getEntities(); + int heightTile = environment.heightTile; + int widthTile = environment.widthTile; + int widthMaps = environment.getTileMaps().getWidth(); + int heightMaps = environment.getTileMaps().getHeight(); + + int x = -1; + int y = (int) (getY()/heightTile)+1; + + // Check si personne à côté + int left = 0; int right = 0; + for (Entity entity : entities) { + boolean haveAnEntityOnLeft = entity.getX() == (getX() - widthTile) && entity.getY() == getY(); + boolean haveAnEntityOnRight = entity.getX() == (getX() + widthTile) && entity.getY() == getY(); + + if (haveAnEntityOnLeft) left++; + if (haveAnEntityOnRight) right++; + } + + // Si les casses à côté sont libres + boolean leftIsAvailable = (left == 0); + boolean rightIsAvailable = (right == 0); + if (leftIsAvailable) + x = (int) (getX() - widthTile)/widthTile; + else if (rightIsAvailable) + x = (int) (getX() + widthTile)/widthTile; + + // La place sur la carte + boolean isntOutTheMap = (x >= 0 && x < widthMaps) && (y >= 0 && y < heightMaps); + if (isntOutTheMap) { + boolean dontHaveTile = environment.getTileMaps().getTile(x, y) != TileMaps.SKY; + + if (dontHaveTile) { + int xTallGrassChildren = (int) ((left == 0) ? (getX() - widthTile) : (getX() + widthTile)); + int yTallGrassChildren = (int) getY(); + + children.add(new TallGrass(this.environment, xTallGrassChildren, yTallGrassChildren)); + } + } + } + + return children; + } + + @Override public void spawn(int x, int y) + { + this.setX(x); + this.setY(y); + this.environment.getEntities().add(0, this); + } + + + public DoubleProperty getTallGrassGrowthProperty() { return this.tallGrassGrowth; } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/blocks/Torch.java b/src/main/java/fr/sae/terraria/modele/entities/blocks/Torch.java new file mode 100644 index 0000000..84b5fe2 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/blocks/Torch.java @@ -0,0 +1,56 @@ +package fr.sae.terraria.modele.entities.blocks; + +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.entities.entity.PlaceableObjectType; +import fr.sae.terraria.modele.entities.entity.StowableObjectType; +import fr.sae.terraria.modele.entities.player.Player; +import fr.sae.terraria.modele.entities.player.inventory.Inventory; + +import java.util.Objects; + + +public class Torch extends Block implements StowableObjectType, PlaceableObjectType +{ + private final Environment environment; + + private double xOrigin; + private double yOrigin; + + + public Torch(Environment environment, int x, int y) + { + super(x, y); + this.environment = environment; + + this.xOrigin = x; + this.yOrigin = y; + } + + @Override public void updates() { /* TODO document why this method is empty */ } + + @Override public void breaks() + { + this.breakAnimation(environment, this, xOrigin, yOrigin); + + this.environment.getPlayer().pickup(this); + + this.environment.getEntities().remove(this); + this.environment.getTorches().remove(this); + } + + @Override public void place(int x, int y) + { + Environment.playSound("sound/axchop.wav", false); + + Torch entity = new Torch(this.environment, x*environment.widthTile, y*environment.heightTile); + entity.setRect(environment.widthTile, environment.heightTile); + + Player player = this.environment.getPlayer(); + Inventory inventory = player.getInventory(); + if (!Objects.isNull(player.getStackSelected())) + inventory.get().get(inventory.getPosCursor()).remove(); + + environment.getEntities().add(0, entity); + environment.getTorches().add(0, entity); + } +} \ No newline at end of file diff --git a/src/main/java/fr/sae/terraria/modele/entities/blocks/Tree.java b/src/main/java/fr/sae/terraria/modele/entities/blocks/Tree.java new file mode 100644 index 0000000..741add5 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/blocks/Tree.java @@ -0,0 +1,39 @@ +package fr.sae.terraria.modele.entities.blocks; + +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.entities.entity.SpawnableObjectType; +import fr.sae.terraria.modele.entities.items.Wood; + + +public class Tree extends Block implements SpawnableObjectType +{ + public static final int WHEN_SPAWN_A_TREE = 5_000; + public static final double TREE_SPAWN_RATE = .2; + + private final Environment environment; + + + public Tree(Environment environment, int x, int y) + { + super(x, y); + this.environment = environment; + } + + public Tree(Environment environment) { this(environment, 0, 0); } + + @Override public void updates() { /* TODO document why this method is empty */ } + + @Override public void breaks() + { + // Environment.playSound("sound/grassyStep.wav", false); + this.environment.getPlayer().pickup(new Wood()); + this.environment.getEntities().remove(this); + } + + @Override public void spawn(int x, int y) + { + this.setX(x); + this.setY(y); + this.environment.getEntities().add(0, this); + } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/Animation.java b/src/main/java/fr/sae/terraria/modele/entities/entity/Animation.java index 8b33311..6a77374 100644 --- a/src/main/java/fr/sae/terraria/modele/entities/entity/Animation.java +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/Animation.java @@ -4,6 +4,12 @@ import javafx.beans.property.SimpleDoubleProperty; +/** + *

Animation

+ *

Description:

+ *

Gére uniquement la valeurs du frame pour que la vue sachent sur quel frame doit afficher l'image.

+ * @see fr.sae.terraria.vue.PlayerView + */ public class Animation { public static final double FRAME_SPEED = .1; @@ -14,7 +20,9 @@ public class Animation public Animation() { - this.frame = new SimpleDoubleProperty(); + super(); + + this.frame = new SimpleDoubleProperty(0); this.endFrame = 3; } @@ -27,7 +35,7 @@ public void loop() } /** Revient au début du Sprite Sheet */ - public void reset() { frame.set(0); } + public void reset() { this.frame.set(0); } public double getFrame() { return this.frame.get(); } diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/BreakableObjectType.java b/src/main/java/fr/sae/terraria/modele/entities/entity/BreakableObjectType.java new file mode 100644 index 0000000..c986cc2 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/BreakableObjectType.java @@ -0,0 +1,26 @@ +package fr.sae.terraria.modele.entities.entity; + + +/** + *

Breakable Object Type

+ *

Interface utile à un objet qui hérite d'Entity

+ *

Description:

+ *

Determine un objet qui est cassable

+ * + * @see Entity + * @author CHRZASCZCZ Naulan + */ +public interface BreakableObjectType +{ + + + /** + * Fonction appelée lorsqu'une entité tante de casser une autre entité + * Permet de faire des actions personnalisées. + * + * @see fr.sae.terraria.modele.entities.blocks.Dirt + * @see fr.sae.terraria.modele.entities.blocks.TallGrass + * @see fr.sae.terraria.modele.entities.blocks.Stone + */ + void breaks(); +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/CollapsibleObjectType.java b/src/main/java/fr/sae/terraria/modele/entities/entity/CollapsibleObjectType.java new file mode 100644 index 0000000..9d57e40 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/CollapsibleObjectType.java @@ -0,0 +1,25 @@ +package fr.sae.terraria.modele.entities.entity; + + +/** + *

Collapsible Object Type

+ *

Interface utile à un objet qui hérite d'Entity

+ *

Description:

+ *

Determine les objets qui sont touchable par une autre entité

+ *

Il détermine surtout les objets qui sont touchable avec des flèches ou des outils qui inflige des dégâts, qui peuvent en général avoir des dégâts à cause de ses éléments

+ * + * @see Entity + * @author CHRZASZCZ Naulan + */ +public interface CollapsibleObjectType +{ + + + /** + * Fonction qui est appelée lorsqu'une entité touche un autre par n'importe quel manière en excluent les collisions entre collision + * Permet de faire des actions personnalisées par entité lorsque une entitée touche un autre + * + * @see fr.sae.terraria.modele.entities.Rabbit + */ + void hit(); +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/CollideObjectType.java b/src/main/java/fr/sae/terraria/modele/entities/entity/CollideObjectType.java index 3e18712..89efdb9 100644 --- a/src/main/java/fr/sae/terraria/modele/entities/entity/CollideObjectType.java +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/CollideObjectType.java @@ -2,14 +2,26 @@ /** - * Permet de regrouper et de connaitre les entités qui doivent avoir une collision entre eux - * et avec leurs environment + *

CollideObjectType

+ *

Interface utile à un objet qui hérite d'Entity

+ *

Description:

+ *

Permet de discerner les entités qui ne sont pas des objects qui doit rentré en collisions avec d'autre entité

+ *

Cela peut êtres utile sur les elements qui doit êtres au premier plan et d'autre element qui doit êtres à l'arrière plan

+ * + * @see Entity + * @author CHRZASZCZ Naulan */ public interface CollideObjectType { - int COLLISION_TOLERANCE = 3; + int COLLISION_TOLERANCE = 3; // Permet d'avoir une certaine tolerance avec le bloc qui va rencontrer, évite des bugs - /** Permet à chaque passage de boucle, d'appliquer une collision entre les entités et de son environment */ + /** + * Permet d'appliquer des collisions à l'entité qui l'utilise sur son environment. + * Pour pouvoir être fonctionnel, il doit faire appelle à "super.collide()" est de la rangé dans une variable + * de type Map pour permettre d'avoir des données relatif sur où il entre en collision + * + * @see Entity + */ void collide(); } diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/EatableObjectType.java b/src/main/java/fr/sae/terraria/modele/entities/entity/EatableObjectType.java new file mode 100644 index 0000000..5293bd8 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/EatableObjectType.java @@ -0,0 +1,24 @@ +package fr.sae.terraria.modele.entities.entity; + + +/** + *

Eatable Object Type

+ *

Interface utile sur les objets de type rangeable dans l'inventaire

+ *

Description:

+ *

Permet de discerner les objets qui sont mangeable par une entité ou ceux qui ne le sont pas

+ * + * @see fr.sae.terraria.modele.entities.items.Item + * @author CHRZASZCZ Naulan + */ +public interface EatableObjectType +{ + + + /** + * Permet d'appliquer des actions lorsque qu'il mange l'aliment qui est dans la main de l'entité. + * Permet de faire des actions personnalisées lorsque l'action manger est activé. + * + * @see fr.sae.terraria.modele.entities.items.Meat + */ + void eat(); +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/Entity.java b/src/main/java/fr/sae/terraria/modele/entities/entity/Entity.java index 4cb84cc..f96fd29 100644 --- a/src/main/java/fr/sae/terraria/modele/entities/entity/Entity.java +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/Entity.java @@ -1,9 +1,46 @@ package fr.sae.terraria.modele.entities.entity; +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.TileMaps; +import fr.sae.terraria.modele.entities.Slime; import javafx.beans.property.DoubleProperty; import javafx.beans.property.SimpleDoubleProperty; - +import java.util.HashMap; +import java.util.Map; + + +/** + *

La classes Entity

+ *

Description:

+ * + *

Correspond à un element physique qui doit avoir des coordonnées sur un environment.

+ *

contient des fonctions privates qui peuvent êtres implémenter grâce au interface mise à disposition au sain du même package

+ *

+ *

C'est interfaces agissent comme une sorte de pâte à modelé, ils permettent surtout de + * rendre public les fonctions de Entity qui sont eux protected

+ * + *

Comment l'utiliser ?

+ *

Il suffit d'extend des objects qui vous souhaitez êtres des entitées

+ *

Exemple de code qui hérite de Entity:

+ * + *

Donc sur cette exemple dans le jeu, le lapin est considèrer comme une entités.

+ *

+ *

Toutes les méthodes/fonctions protected sont appelable vers l'extérieur d'un classes qui l'hérite grâce à des interfaces.

+ *

Donc pour avoir correctement les fonctions:

+ * + *

Sont implementable grâce à l'interface MovableObjectType

+ * @see CollideObjectType + * @see MovableObjectType + * @see ReproductiveObjectType + * @see StowableObjectType + * @see BreakableObjectType + * @see CollapsibleObjectType + * @see PlaceableObjectType + * @see EatableObjectType + * + * @author CHRZASZCZ Naulan + */ public abstract class Entity { public static final int IS_FALLING = -1; @@ -12,18 +49,18 @@ public abstract class Entity public static final int IS_MOVING_RIGHT = 1; public static final int IDLE = 0; - protected DoubleProperty pv; - protected DoubleProperty x; - protected DoubleProperty y; + protected final DoubleProperty pv; + protected final DoubleProperty x; + protected final DoubleProperty y; protected final Gravity gravity = new Gravity(); protected Animation animation = null; protected Rect rect = null; - - protected double velocity = 1; + protected double velocity; protected double pvMax; - public boolean air = false; - public int[] offset; // offset[0] >= -1 && offset[0] <= 1 et offset[1] >= -1 && offset[1] <= 1 + protected boolean air; + + public int[] offset; /** @@ -32,31 +69,137 @@ public abstract class Entity */ protected Entity(int x, int y) { + super(); + this.x = new SimpleDoubleProperty(x); this.y = new SimpleDoubleProperty(y); this.pv = new SimpleDoubleProperty(0); - this.pvMax = pv.get(); + this.pvMax = this.pv.get(); + this.air = false; this.offset = new int[2]; + this.velocity = 1; } + protected Entity() { this(0, 0); } /** - * Permet de mettre à jour les valeurs qui concerne l'entité - * et qui doit rester au sain de l'objet + * Il permet à chaque passage de la boucle du jeu, de faire diverses fonctions liée à l'Entité. + * Certaine fonction qui sera implementé grâce à des interfaces sera probablement obligatoirement mise dans cette fonction. */ public abstract void updates(); - /** Modifie le xInit et le yInit pour modifier le point de départ du saut ou de là où il tombe */ - public void setJumpPosInit() { this.gravity.xInit = this.x.get(); this.gravity.yInit = this.y.get(); } - /** Modifie l'offset qui permet de le déplacer vers la droite */ - public void moveRight() { this.offset[0] = Entity.IS_MOVING_RIGHT; } - /** Modifie l'offset qui permet de le déplacer vers la gauche */ - public void moveLeft() { this.offset[0] = Entity.IS_MOVING_LEFT; } - /** Modifie l'offset qui permet de le faire sauter */ - public void jump() { offset[1] = Entity.IS_JUMPING; } - /** Modifie l'offset qui permet de tomber */ - public void fall() { this.offset[1] = Entity.IS_FALLING; } + /** + * Permet de detectés les collisions sur la carte et de son environment. + * + * @param environment Permet de savoir les tailles des tiles et d'avoir la matrixe de données de la carte. + * @return Il vas retourner une HashMap qui ne contiendra pas de clé ou 4 clés maximum + * left, right, top, bottom sera les clés qui peuvent être present lors d'une detection de collision. + * Il permettra de faire des actions personnalisées les actions faites par l'entité suivant d'où il rentre en collision avec son environment. + */ + protected Map collide(final Environment environment) + { + + int widthTile = environment.widthTile; int heightTile = environment.heightTile; + TileMaps tileMaps = environment.getTileMaps(); + Map whereCollide = new HashMap<>(); + + // Detection vide en dessous + int yBottom = (int) (this.getY()+getRect().getHeight()-CollideObjectType.COLLISION_TOLERANCE)/heightTile; + int posX = (int) ((this.getX()+((this.offset[0] < 0) ? CollideObjectType.COLLISION_TOLERANCE : -CollideObjectType.COLLISION_TOLERANCE)) + ((this.offset[0] > 0) ? getRect().getWidth() : 0))/widthTile; + + boolean footInTheVoid = tileMaps.getTile(posX, yBottom) == TileMaps.SKY; + if (footInTheVoid) + this.air = true; + + // Detection collision gauche droite + if (this.offset[0] != Entity.IDLE) { + int yTop = (int) (getY()+CollideObjectType.COLLISION_TOLERANCE)/heightTile; + int futurePositionXLeft = (int) ((getX()+CollideObjectType.COLLISION_TOLERANCE)+(velocity*offset[0]))/widthTile; + int futurePositionXRight = (int) ((getX()+(-CollideObjectType.COLLISION_TOLERANCE)+(velocity*offset[0])) + (getRect().getWidth()))/widthTile; + + whereCollide.put("right", tileMaps.getTile(futurePositionXRight, yTop) != TileMaps.SKY || tileMaps.getTile(futurePositionXRight, yBottom) != TileMaps.SKY); + whereCollide.put("left", tileMaps.getTile(futurePositionXLeft, yTop) != TileMaps.SKY || tileMaps.getTile(futurePositionXLeft, yBottom) != TileMaps.SKY); + } + + // Detection collision en bas et en haut + if (this.offset[1] != Entity.IDLE) { + int xLeft = (int) (getX()+CollideObjectType.COLLISION_TOLERANCE)/widthTile; + int xRight = (int) ((getX()+getRect().getWidth())-CollideObjectType.COLLISION_TOLERANCE)/widthTile; + + + // Tombe + if (this.offset[1] == Entity.IS_FALLING) { + this.gravity.degInit = 0; + double futurePositionY = gravity.formulaOfTrajectory() ; + boolean isCollideBottom = tileMaps.getTile(xLeft, (int) (futurePositionY + this.rect.getHeight())/heightTile) != TileMaps.SKY || tileMaps.getTile(xRight, (int) (futurePositionY + CollideObjectType.COLLISION_TOLERANCE +this.rect.getHeight())/heightTile) != TileMaps.SKY; + if (isCollideBottom) { + this.gravity.setJumpPosInit(this); + this.gravity.timer = 0; + this.offset[1] = Entity.IDLE; + } else setY(futurePositionY); + // Saute + } else if (this.offset[1] == Entity.IS_JUMPING) { + double futurePositionY = gravity.formulaOfTrajectory(); + + boolean isCollideTop = tileMaps.getTile(xLeft, (int) (futurePositionY + CollideObjectType.COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY || tileMaps.getTile(xRight, (int) (futurePositionY + CollideObjectType.COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY; + // Quand le joueur monte + if (this.gravity.flightTime >= this.gravity.timer ) { + if (isCollideTop) { + this.fall(); + this.gravity.timer = 0; + this.gravity.setJumpPosInit(this); + } else this.setY(futurePositionY); + // Quand le joueur decent + } else { + boolean isCollideBottom = tileMaps.getTile(xLeft, (int) ((futurePositionY + this.rect.getHeight()) - CollideObjectType.COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY || tileMaps.getTile(xRight,(int) ((futurePositionY + this.rect.getHeight()) - CollideObjectType.COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY; + + if (isCollideTop) { + this.fall(); + } else if (isCollideBottom) { + this.gravity.setJumpPosInit(this); + this.gravity.timer = 0; + this.offset[1] = Entity.IDLE; + this.air = false; + } else this.setY(futurePositionY); + } + } + } else if (this.air) { + this.gravity.degInit = 0; + int xLeft = (int) (getX()+CollideObjectType.COLLISION_TOLERANCE)/widthTile; + int xRight = (int) (getX()-CollideObjectType.COLLISION_TOLERANCE+getRect().getWidth())/widthTile; + double futurePositionY = this.gravity.formulaOfTrajectory() + this.rect.getHeight(); + + boolean isCollideBottom = tileMaps.getTile(xLeft, (int) (futurePositionY - CollideObjectType.COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY || tileMaps.getTile(xRight, (int) (futurePositionY - CollideObjectType.COLLISION_TOLERANCE)/heightTile) != TileMaps.SKY; + if (isCollideBottom) { + this.offset[1] = Entity.IDLE; + this.air = false; + this.gravity.setJumpPosInit(this); + } else setY(futurePositionY - this.rect.getHeight()); + } + + return whereCollide; + } + + protected void moveRight() { this.offset[0] = Entity.IS_MOVING_RIGHT; } + protected void moveLeft() { this.offset[0] = Entity.IS_MOVING_LEFT; } + protected void jump() { this.offset[1] = Entity.IS_JUMPING; } + protected void fall() { this.offset[1] = Entity.IS_FALLING; } + + /** + * Lorsque le joueur sort de l'ecran et/ou de la carte, la fonction retourne une valeurs boolean qui sera manipulable sur les classes qui l'héritera. + * @param environment Permet d'avoir les informations naicessaire sur la carte et l'écran pour que l'entité ne sorte pas. + * + * @return false = ne sort pas | true = sort de l'écran soit vers la droite ou soit vers le bas + */ + protected boolean worldLimit(final Environment environment) + { + double widthMap = (environment.getTileMaps().getWidth()*environment.scaleMultiplicatorWidth*TileMaps.TILE_DEFAULT_SIZE) ; + + boolean exceedsScreenOnLeft = offset[0] == Entity.IS_MOVING_LEFT && getX() < 0; + boolean exceedsScreenOnRight = offset[0] == Entity.IS_MOVING_RIGHT && getX() > (widthMap - getRect().getWidth()); + return (exceedsScreenOnLeft || exceedsScreenOnRight); + } public DoubleProperty getPvProperty() { return this.pv; } @@ -65,17 +208,17 @@ protected Entity(int x, int y) public Animation getAnimation() { return this.animation; } public Gravity getGravity() { return this.gravity; } public Rect getRect() { return this.rect; } + public double getVelocity() { return this.velocity; } public double getPvMax() { return this.pv.get(); } public double getPv() { return this.pv.get(); } public double getX() { return this.x.get(); } public double getY() { return this.y.get(); } - public double getVelocity() { return this.velocity; } - public void setPv(double pv) { this.pv.setValue(pv); this.pvMax = pv;} - public void setX(double x) { this.x.setValue(x); } - public void setY(double y) { this.y.setValue(y); } - public void setVelocity(double velocity) { this.velocity = velocity; } public void setRect(int width, int height) { this.rect = new Rect(x.get(), y.get(), width, height); } + public void setVelocity(double velocity) { this.velocity = velocity; } + public void setPv(double pv) { this.pv.set(pv); this.pvMax = pv;} + public void setX(double x) { this.x.set(x); } + public void setY(double y) { this.y.set(y); } } diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/Gravity.java b/src/main/java/fr/sae/terraria/modele/entities/entity/Gravity.java index 72447b9..d97b70d 100644 --- a/src/main/java/fr/sae/terraria/modele/entities/entity/Gravity.java +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/Gravity.java @@ -16,12 +16,14 @@ public class Gravity public int amplitude = 10; + public Gravity() { super(); } + public double formulaOfTrajectory() { - flightTime = calcFlightTime(); + this.flightTime = this.calcFlightTime(); // Formule de type ax²+bx+c ( c = yInit ) double yValue = (((Gravity.VALUE/2) * (timer * timer)) + ((Math.sin(degInit) * (vInit * amplitude)) * timer)) + yInit; - this.timer += SPEED; + this.timer += Gravity.SPEED; return yValue; } @@ -29,11 +31,15 @@ public double formulaOfTrajectory() private double calcFlightTime() { // résolution de l'équation f'(x) = 0 - if (degInit < 0) - return ((vInit * amplitude) * Math.sin(-degInit)) / Gravity.VALUE; - return ((vInit * amplitude) * Math.sin(degInit)) / Gravity.VALUE; + if (this.degInit < 0) + return ((this.vInit * this.amplitude) * Math.sin(-this.degInit)) / Gravity.VALUE; + return ((this.vInit * this.amplitude) * Math.sin(this.degInit)) / Gravity.VALUE; } + /** Modifie le xInit et le yInit pour modifier le point de départ du saut ou de là où il tombe */ + protected void setJumpPosInit(final Entity entity) { this.xInit = entity.getX(); this.yInit = entity.getY(); } + + public void setXInit(double newXInit) { xInit = newXInit; } public void setYInit(double newYInit) { yInit = newYInit; } } diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/MovableObjectType.java b/src/main/java/fr/sae/terraria/modele/entities/entity/MovableObjectType.java new file mode 100644 index 0000000..3202f79 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/MovableObjectType.java @@ -0,0 +1,66 @@ +package fr.sae.terraria.modele.entities.entity; + + +/** + *

Movable Object Type

+ *

Interface utile à un objet qui hérite d'Entity

+ * + *

Description:

+ *

Il permet d'implementer les fonctions qui correspond à une entité qui doit ou qui peut bouger.

+ *

Il permet surtout de rendre public les functions qui sont en protected donc pas accessible à l'extérieur de la classe

+ * @see Entity + * + * @author CHRZASZCZ Naulan + */ +public interface MovableObjectType +{ + + + /** + * Permet que l'entité bouge grâce aux offset modifier à chaque passage de la boucle du jeu. + * Donc, il doit être appelé dans "updates()" pour que le joueur puisse être déplacé. + * + * @see Entity + */ + void move(); + + /** + * Permet que l'entité lors de ses déplacements, qui ne sortent pas de la carte et aussi nis de l'écran. + * Pour l'utilisé dans une classe que vous avez récemment créé, vous devez appeler la fonction dans Entité grâce à "super.worldLimit()". + * + * @see Entity + */ + void worldLimit(); + + /** + * Modifie l'indice 0 dans la variable offset qui permet de le déplacer l'entité vers la droite. + * Pour l'utilisé dans une classe que vous avez récemment créé, vous devez appeler la fonction dans Entité grâce à "super.moveRight()". + * + * @see Entity + */ + void moveRight(); + + /** + * Modifie l'indice 0 dans la variable offset qui permet de le déplacer l'entité vers la gauche. + * Pour l'utilisé dans une classe que vous avez récemment créé, vous devez appeler la fonction dans Entité grâce à "super.moveLeft()". + * + * @see Entity + */ + void moveLeft(); + + /** + * Modifie l'indice 1 dans la variable offset qui permet d'informer l'entité qui est en train de sauter + * Pour l'utilisé dans une classe que vous avez récemment créé, vous devez appeler la fonction dans Entité grâce à "super.jump()". + * + * @see Entity + */ + void jump(); + + /** + * Modifie l'indice 1 dans la variable offset qui permet d'informer l'entité qui est en train de tomber + * Pour l'utilisé dans une classe que vous avez récemment créé, vous devez appeler la fonction dans Entité grâce à "super.fall()". + * + * @see Entity + */ + void fall(); +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/PlaceableObjectType.java b/src/main/java/fr/sae/terraria/modele/entities/entity/PlaceableObjectType.java new file mode 100644 index 0000000..c3a99df --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/PlaceableObjectType.java @@ -0,0 +1,25 @@ +package fr.sae.terraria.modele.entities.entity; + + +/** + *

Placeable Object Type

+ *

Interface utile sur les objets qui hérite de block

+ *

Description:

+ *

Permet de savoir si un block sera possable sur un sol ou non

+ * + * @see fr.sae.terraria.modele.entities.blocks.Stone + * @author CHRZASZCZ Naulan + */ +public interface PlaceableObjectType +{ + + + /** + * Permet d'appliquer des actions lorsque qu'il tante de poser un block + * + * @param x Les coordonnées du block en x lorsqu'il va êtres poser au sol + * @param y Les coordonnées du block en y lorsqu'il va êtres poser au sol + * @see fr.sae.terraria.modele.entities.blocks.Stone + */ + void place(final int x, final int y); +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/Rect.java b/src/main/java/fr/sae/terraria/modele/entities/entity/Rect.java index eab0fe6..694827c 100644 --- a/src/main/java/fr/sae/terraria/modele/entities/entity/Rect.java +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/Rect.java @@ -8,7 +8,12 @@ public class Rect private Rectangle2D value; - public Rect(double x, double y, int width, int height) { this.value = new Rectangle2D(x, y, width, height); } + public Rect(double x, double y, int width, int height) + { + super(); + + this.value = new Rectangle2D(x, y, width, height); + } /** * Mets à jour la position du rectangle géré par JavaFX @@ -24,9 +29,9 @@ public void updates(double x, double y) } /** Permet de savoir si deux rectangles sont en collision */ - public boolean collideRect(Rect rect) { return this.value.intersects(rect.get()) || this.value.contains(rect.get()); } + public boolean collideRect(final Rect rect) { return this.value.intersects(rect.get()) || this.value.contains(rect.get()); } /** Permet de savoir si deux rectangles sont en collision */ - public boolean collideRect(Rectangle2D rect) { return this.value.intersects(rect) || this.value.contains(rect); } + public boolean collideRect(final Rectangle2D rect) { return this.value.intersects(rect) || this.value.contains(rect); } /** Permet d'avoir le Rectangle qui est géré par JavaFX */ public Rectangle2D get() { return this.value; } diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/ReproductiveObjectType.java b/src/main/java/fr/sae/terraria/modele/entities/entity/ReproductiveObjectType.java index 23306fe..66818ec 100644 --- a/src/main/java/fr/sae/terraria/modele/entities/entity/ReproductiveObjectType.java +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/ReproductiveObjectType.java @@ -6,17 +6,23 @@ /** - * Permet de regrouper les entités qui peuvent se reproduire et d'implémenter cette fonctionnalité. + *

Reproduction Object Type

+ *

Interface utile à un objet qui hérite d'Entity

+ *

Description:

+ *

Il permet de savoir si l'entité qui implementer cette interface est une entité qui peut se reproduire entre eux.

* * @see fr.sae.terraria.modele.entities.Rabbit - * @see fr.sae.terraria.modele.blocks.TallGrass + * @see fr.sae.terraria.modele.entities.blocks.TallGrass + * @author CHRZASZCZ Naulan */ public interface ReproductiveObjectType { + /** * Reproduit les entités concernées. * @return Les enfants de l'entité + * @see fr.sae.terraria.modele.entities.blocks.TallGrass */ List reproduction(Environment environment); } diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/SpawnableObjectType.java b/src/main/java/fr/sae/terraria/modele/entities/entity/SpawnableObjectType.java new file mode 100644 index 0000000..467bed0 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/SpawnableObjectType.java @@ -0,0 +1,8 @@ +package fr.sae.terraria.modele.entities.entity; + +public interface SpawnableObjectType +{ + + + void spawn(final int x, final int y); +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/entity/StowableObjectType.java b/src/main/java/fr/sae/terraria/modele/entities/entity/StowableObjectType.java index 7aa87e9..c1ed649 100644 --- a/src/main/java/fr/sae/terraria/modele/entities/entity/StowableObjectType.java +++ b/src/main/java/fr/sae/terraria/modele/entities/entity/StowableObjectType.java @@ -2,9 +2,12 @@ /** - * Permet de regrouper les objets qui son stockable dans l'inventaire du joueur + *

Stowable Object Type

+ *

Interface utile à un objet qui hérite d'Entity

+ *

Description:

+ *

Il permet de regrouper les objets qui son stockable dans l'inventaire du joueur

* - * @see fr.sae.terraria.modele.blocks.Block - * @see fr.sae.terraria.modele.tools.Tool + * @see fr.sae.terraria.modele.entities.items.Item + * @see fr.sae.terraria.modele.entities.tools.Tool */ public interface StowableObjectType {} diff --git a/src/main/java/fr/sae/terraria/modele/entities/items/Coal.java b/src/main/java/fr/sae/terraria/modele/entities/items/Coal.java new file mode 100644 index 0000000..217ff53 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/items/Coal.java @@ -0,0 +1,4 @@ +package fr.sae.terraria.modele.entities.items; + + +public class Coal extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/entities/items/Fiber.java b/src/main/java/fr/sae/terraria/modele/entities/items/Fiber.java new file mode 100644 index 0000000..e817b90 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/items/Fiber.java @@ -0,0 +1,4 @@ +package fr.sae.terraria.modele.entities.items; + + +public class Fiber extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/entities/items/Iron.java b/src/main/java/fr/sae/terraria/modele/entities/items/Iron.java new file mode 100644 index 0000000..4d6796e --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/items/Iron.java @@ -0,0 +1,4 @@ +package fr.sae.terraria.modele.entities.items; + + +public class Iron extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/items/Item.java b/src/main/java/fr/sae/terraria/modele/entities/items/Item.java similarity index 72% rename from src/main/java/fr/sae/terraria/modele/items/Item.java rename to src/main/java/fr/sae/terraria/modele/entities/items/Item.java index d3cf6ea..31c59cf 100644 --- a/src/main/java/fr/sae/terraria/modele/items/Item.java +++ b/src/main/java/fr/sae/terraria/modele/entities/items/Item.java @@ -1,4 +1,4 @@ -package fr.sae.terraria.modele.items; +package fr.sae.terraria.modele.entities.items; import fr.sae.terraria.modele.entities.entity.StowableObjectType; diff --git a/src/main/java/fr/sae/terraria/modele/entities/items/Meat.java b/src/main/java/fr/sae/terraria/modele/entities/items/Meat.java new file mode 100644 index 0000000..63b1137 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/items/Meat.java @@ -0,0 +1,31 @@ +package fr.sae.terraria.modele.entities.items; + +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.entities.entity.EatableObjectType; +import fr.sae.terraria.modele.entities.player.Player; +import fr.sae.terraria.modele.entities.player.inventory.Inventory; + + +public class Meat extends Item implements EatableObjectType +{ + private final Environment environment; + + + public Meat(final Environment environment) + { + super(); + this.environment = environment; + } + + @Override public void eat() + { + Player player = environment.getPlayer(); + + if (player.getPv() < player.getPvMax()) { + Inventory inventory = player.getInventory(); + + player.setPv(player.getPv() + 1); + inventory.get().get(inventory.getPosCursor()).remove(); + } + } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/items/Pierre.java b/src/main/java/fr/sae/terraria/modele/entities/items/Pierre.java new file mode 100644 index 0000000..c481a70 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/items/Pierre.java @@ -0,0 +1,4 @@ +package fr.sae.terraria.modele.entities.items; + + +public class Pierre extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/entities/items/Silex.java b/src/main/java/fr/sae/terraria/modele/entities/items/Silex.java new file mode 100644 index 0000000..0efd689 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/items/Silex.java @@ -0,0 +1,4 @@ +package fr.sae.terraria.modele.entities.items; + + +public class Silex extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/entities/items/Wood.java b/src/main/java/fr/sae/terraria/modele/entities/items/Wood.java new file mode 100644 index 0000000..1a43066 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/items/Wood.java @@ -0,0 +1,3 @@ +package fr.sae.terraria.modele.entities.items; + +public class Wood extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/entities/player/Player.java b/src/main/java/fr/sae/terraria/modele/entities/player/Player.java new file mode 100644 index 0000000..d4bbf6d --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/player/Player.java @@ -0,0 +1,139 @@ +package fr.sae.terraria.modele.entities.player; + +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.entities.entity.*; +import fr.sae.terraria.modele.entities.player.inventory.Inventory; +import fr.sae.terraria.modele.entities.player.inventory.Stack; +import fr.sae.terraria.vue.View; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.image.Image; +import javafx.scene.input.KeyCode; +import javafx.scene.input.MouseButton; + +import java.util.EnumMap; +import java.util.Map; +import java.util.Objects; + + +public class Player extends Entity implements CollideObjectType, MovableObjectType, CollapsibleObjectType, SpawnableObjectType +{ + public static final int BREAK_BLOCK_DISTANCE = 1; + + private final EnumMap keysInput; + private final EnumMap mouseInput; + + private final ObjectProperty objectWasPickup; + + + private final Environment environment; + + private final Inventory inventory; + private Stack stackSelected; + + + public Player(final Environment environment) + { + super(); + this.environment = environment; + this.inventory = new Inventory(this); + + this.animation = new Animation(); + this.keysInput = new EnumMap<>(KeyCode.class); + this.mouseInput = new EnumMap<>(MouseButton.class); + + this.objectWasPickup = new SimpleObjectProperty(null); + this.objectWasPickup.addListener((obs, oldObject, newObject) -> this.inventory.put((StowableObjectType) newObject)); + } + + @Override public void updates() + { + // Applique les déplacements selon les valeurs de l'offset + // this.setX(this.x.get() + this.offset[0] * this.velocity); + + if (this.offset[1] == Entity.IDLE && !air) { + this.gravity.xInit = this.x.get(); + this.gravity.yInit = this.y.get(); + this.gravity.vInit = this.velocity; + this.gravity.degInit = -90; + + this.gravity.timer = .0; + } + + this.offset[0] = Entity.IDLE; + this.eventInput(); + this.collide(); + this.worldLimit(); + this.move(); + + if (!Objects.isNull(this.rect)) + this.rect.updates(x.get(), y.get()); + this.animation.loop(); + } + + @Override public void move() { this.setX(this.getX() + this.offset[0] * this.getVelocity()); } + + @Override public void collide() + { + Map whereCollide = super.collide(this.environment); + + if (!whereCollide.isEmpty()) { + if (whereCollide.get("left").equals(Boolean.TRUE) || whereCollide.get("right").equals(Boolean.TRUE)) + this.offset[0] = Entity.IDLE; + } + } + + @Override public void hit() { } + + @Override public void spawn(int x, int y) + { + this.setX(x); + this.setY(y); + + Image image = View.loadAnImage("sprites/player/player_idle.png", environment.scaleMultiplicatorWidth, environment.scaleMultiplicatorHeight); + this.setRect((int) image.getWidth(), (int) image.getHeight()); + image.cancel(); + + this.getGravity().setXInit(x); + this.getGravity().setYInit(y); + } + + @Override public void moveRight() { super.moveRight(); } + @Override public void moveLeft() { super.moveLeft(); } + @Override public void jump() { super.jump(); } + @Override public void fall() { super.fall(); } + + @Override public void worldLimit() + { + if (super.worldLimit(this.environment)) + this.offset[0] = Entity.IDLE; + } + + /** Lie les inputs au clavier à une ou des actions. */ + public void eventInput() + { + this.inventory.eventInput(); + + this.keysInput.forEach((key, value) -> { + if (Boolean.TRUE.equals(value)) { + if (key == KeyCode.Z || key == KeyCode.SPACE) + if (this.offset[1] != Entity.IS_FALLING) this.jump(); + + if (key == KeyCode.D) + this.moveRight(); + else if (key == KeyCode.Q) + this.moveLeft(); + } + }); + } + + public void pickup(StowableObjectType pickupObject) { this.objectWasPickup.set(pickupObject); } + + + public Map getMouseInput() { return this.mouseInput; } + public Map getKeysInput() { return this.keysInput; } + public Stack getStackSelected() { return this.stackSelected; } + public Inventory getInventory() { return this.inventory; } + + public void setStackSelected(Stack stackSelected) { this.stackSelected = stackSelected; } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/player/inventory/Inventory.java b/src/main/java/fr/sae/terraria/modele/entities/player/inventory/Inventory.java new file mode 100644 index 0000000..ac39b04 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/player/inventory/Inventory.java @@ -0,0 +1,154 @@ +package fr.sae.terraria.modele.entities.player.inventory; + +import fr.sae.terraria.modele.entities.entity.StowableObjectType; +import fr.sae.terraria.modele.entities.player.Player; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.scene.input.KeyCode; + +import java.util.EnumMap; +import java.util.Map; + + +public class Inventory +{ + public static final int NB_BOXES_MAX = 27; + public static final int NB_LINES = 3; + + private final EnumMap keysInput; + private final ObservableList value; + + private final IntegerProperty posCursor; + private final Player player; + private int scroll; + + + public Inventory(final Player player) + { + super(); + this.player = player; + + int nbElementOnOneLineOfInventory = (Inventory.NB_BOXES_MAX / Inventory.NB_LINES); + this.keysInput = new EnumMap<>(KeyCode.class); + this.value = FXCollections.observableArrayList(); + + this.posCursor = new SimpleIntegerProperty(0); + + // Change l'item de la main du joueur + this.posCursorProperty().addListener((obs, oldV, newV) -> { + boolean isntOutOfInventoryBar = newV.intValue() >= 0 && newV.intValue() < nbElementOnOneLineOfInventory; + + if (isntOutOfInventoryBar) { + Stack stack = null; + if (this.getPosCursor() < this.get().size()) + stack = this.get().get(this.getPosCursor()); + this.player.setStackSelected(stack); + } + }); + } + + private int nbStacksIntoInventory() { return this.value.size(); } + + /** + * Place des objets de type rangeable dans l'inventaire. + * @param item Un objet de type rangeable à mettre dans l'inventaire. + */ + public void put(StowableObjectType item) + { + int nbStacksInventory = this.nbStacksIntoInventory(); + + if (nbStacksInventory < NB_BOXES_MAX) { + if (nbStacksInventory == 0) { + Stack stack = new Stack(); + stack.nbItemsProperty().addListener((observable, oldValue, newValue) -> { + if (newValue.intValue() <= 0) { + this.value.remove(stack); + this.player.setStackSelected(null); + } + }); + stack.setItem(item); + stack.add(); + this.value.add(stack); + this.player.setStackSelected(stack); + } else { + for (Stack stack : this.value) { + int beforeSize = stack.getNbItems(); + if (!stack.isFull() && stack.isSameItem(item)) + stack.add(); + + // Quand un objet a été mise dans l'inventaire, il arrête la fonction + int afterSize = stack.getNbItems(); + if (beforeSize != afterSize) + return; + } + + // Si tous les stacks present sont pleins ou aucune ne correspond à l'objet qui à étais pris, il crée un nouveau stack + Stack stack = new Stack(); + stack.nbItemsProperty().addListener((observable, oldValue, newValue) -> { + if (newValue.intValue() <= 0) { + this.value.remove(stack); + this.player.setStackSelected(null); + } + }); + stack.setItem(item); + stack.add(); + this.value.add(stack); + this.player.setStackSelected(stack); + } + } + } + + /** Les évènements du clavier qui sont liée à l'inventaire. */ + public void eventInput() + { + boolean scrollUp = this.scroll > 0; + boolean scrollDown = this.scroll < 0; + if (scrollUp) + this.posCursor.set(this.getPosCursor() + 1); + else if (scrollDown) + this.posCursor.set(this.getPosCursor() - 1); + + boolean outOfInventoryBarOnRight = this.getPosCursor() > (NB_BOXES_MAX / NB_LINES)-1; + boolean outOfInventoryBarOnLeft = this.getPosCursor() < 0; + if (outOfInventoryBarOnRight) + this.posCursor.set(0); + else if (outOfInventoryBarOnLeft) + this.posCursor.set((NB_BOXES_MAX / NB_LINES)-1); + + this.keysInput.forEach((key, value) -> { + if (value.equals(Boolean.TRUE)) { + if (key.equals(KeyCode.DIGIT1)) + this.posCursor.set(0); + else if (key.equals(KeyCode.DIGIT2)) + this.posCursor.set(1); + else if (key.equals(KeyCode.DIGIT3)) + this.posCursor.set(2); + else if (key.equals(KeyCode.DIGIT4)) + this.posCursor.set(3); + else if (key.equals(KeyCode.DIGIT5)) + this.posCursor.set(4); + else if (key.equals(KeyCode.DIGIT6)) + this.posCursor.set(5); + else if (key.equals(KeyCode.DIGIT7)) + this.posCursor.set(6); + else if (key.equals(KeyCode.DIGIT8)) + this.posCursor.set(7); + else if (key.equals(KeyCode.DIGIT9)) + this.posCursor.set(8); + } + }); + + this.scroll = 0; + } + + public IntegerProperty posCursorProperty() { return this.posCursor; } + + + public int getPosCursor() { return this.posCursor.get(); } + public ObservableList get() { return this.value; } + public Map getKeysInput() { return this.keysInput; } + + public void setScroll(int newScroll) { this.scroll = newScroll; } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/player/inventory/Stack.java b/src/main/java/fr/sae/terraria/modele/entities/player/inventory/Stack.java new file mode 100644 index 0000000..df3565f --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/player/inventory/Stack.java @@ -0,0 +1,87 @@ +package fr.sae.terraria.modele.entities.player.inventory; + +import fr.sae.terraria.modele.entities.Arrow; +import fr.sae.terraria.modele.entities.blocks.Dirt; +import fr.sae.terraria.modele.entities.blocks.Stone; +import fr.sae.terraria.modele.entities.blocks.TallGrass; +import fr.sae.terraria.modele.entities.blocks.Torch; +import fr.sae.terraria.modele.entities.entity.StowableObjectType; +import fr.sae.terraria.modele.entities.items.*; +import fr.sae.terraria.modele.entities.tools.Axe; +import fr.sae.terraria.modele.entities.tools.Bow; +import fr.sae.terraria.modele.entities.tools.Pickaxe; +import fr.sae.terraria.modele.entities.tools.Sword; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.SimpleIntegerProperty; + + +/** + *

Stack

+ *

Objet de données lié à l'objet Inventaire.

+ *

Description:

+ * Cette dataclass est la pour avoir l'information sur combien il y a t-il d'objet du même type sur une case de l'inventaire + */ +public class Stack +{ + public static final int MAX = 16; + + private StowableObjectType item = null; + private IntegerProperty nbItems; + + + public Stack() + { + super(); + + this.nbItems = new SimpleIntegerProperty(0); + } + + public boolean isSameItem(StowableObjectType object) + { + if (object instanceof Dirt && this.item instanceof Dirt) + return true; + else if (object instanceof Stone && this.item instanceof Stone) + return true; + else if (object instanceof TallGrass && this.item instanceof TallGrass) + return true; + else if (object instanceof Torch && this.item instanceof Torch) + return true; + else if (object instanceof Coal && this.item instanceof Coal) + return true; + else if (object instanceof Fiber && this.item instanceof Fiber) + return true; + else if (object instanceof Iron && this.item instanceof Iron) + return true; + else if (object instanceof Meat && this.item instanceof Meat) + return true; + else if (object instanceof Pierre && this.item instanceof Pierre) + return true; + else if (object instanceof Silex && this.item instanceof Silex) + return true; + else if (object instanceof Wood && this.item instanceof Wood) + return true; + else if (object instanceof Axe && this.item instanceof Axe) + return true; + else if (object instanceof Bow && this.item instanceof Bow) + return true; + else if (object instanceof Pickaxe && this.item instanceof Pickaxe) + return true; + else if (object instanceof Sword && this.item instanceof Sword) + return true; + else if (object instanceof Arrow && this.item instanceof Arrow) + return true; + else return false; + } + + public IntegerProperty nbItemsProperty() { return this.nbItems; } + + public boolean isFull() { return this.getNbItems() >= Stack.MAX; } + public void add() { if (this.getNbItems() < Stack.MAX) this.nbItems.set(this.getNbItems() + 1); } + public void remove() { if (this.getNbItems() > 0) this.nbItems.set(this.getNbItems() - 1); } + + + public int getNbItems() { return this.nbItems.get(); } + public StowableObjectType getItem() { return this.item; } + + public void setItem(StowableObjectType newItem) { this.item = newItem; } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/tools/Axe.java b/src/main/java/fr/sae/terraria/modele/entities/tools/Axe.java new file mode 100644 index 0000000..c8fae8f --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/tools/Axe.java @@ -0,0 +1,17 @@ +package fr.sae.terraria.modele.entities.tools; + + +public class Axe extends Tool +{ + + + public Axe() + { + super(Tool.DEFAULT_DURABILITY); + } + + @Override public void use() + { + + } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/tools/Bow.java b/src/main/java/fr/sae/terraria/modele/entities/tools/Bow.java new file mode 100644 index 0000000..4ab6433 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/tools/Bow.java @@ -0,0 +1,14 @@ +package fr.sae.terraria.modele.entities.tools; + + +public class Bow extends Tool +{ + + + protected Bow(int durability) { super(durability); } + + @Override public void use() + { + + } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/tools/Pickaxe.java b/src/main/java/fr/sae/terraria/modele/entities/tools/Pickaxe.java new file mode 100644 index 0000000..a79a948 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/tools/Pickaxe.java @@ -0,0 +1,18 @@ +package fr.sae.terraria.modele.entities.tools; + + +public class Pickaxe extends Tool +{ + + + public Pickaxe() + { + super(Tool.DEFAULT_DURABILITY); + } + + @Override public void use() + { + if (this.durability.get() > 0) + this.durability.set(this.durability.get() - 1); + } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/tools/Sword.java b/src/main/java/fr/sae/terraria/modele/entities/tools/Sword.java new file mode 100644 index 0000000..ba09355 --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/tools/Sword.java @@ -0,0 +1,17 @@ +package fr.sae.terraria.modele.entities.tools; + + +public class Sword extends Tool +{ + + + protected Sword() + { + super(Tool.DEFAULT_DURABILITY); + } + + @Override public void use() + { + + } +} diff --git a/src/main/java/fr/sae/terraria/modele/entities/tools/Tool.java b/src/main/java/fr/sae/terraria/modele/entities/tools/Tool.java new file mode 100644 index 0000000..67dcddd --- /dev/null +++ b/src/main/java/fr/sae/terraria/modele/entities/tools/Tool.java @@ -0,0 +1,24 @@ +package fr.sae.terraria.modele.entities.tools; + +import fr.sae.terraria.modele.entities.entity.StowableObjectType; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.SimpleIntegerProperty; + + +public abstract class Tool implements StowableObjectType +{ + public static final int DEFAULT_DURABILITY = 100; + + protected final IntegerProperty durability; + + + + protected Tool(final int durability) + { + super(); + this.durability = new SimpleIntegerProperty(durability); + } + + /** Use l'outil */ + public abstract void use(); +} diff --git a/src/main/java/fr/sae/terraria/modele/items/Coal.java b/src/main/java/fr/sae/terraria/modele/items/Coal.java deleted file mode 100644 index 33fb620..0000000 --- a/src/main/java/fr/sae/terraria/modele/items/Coal.java +++ /dev/null @@ -1,3 +0,0 @@ -package fr.sae.terraria.modele.items; - -public class Coal extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/items/Fibre.java b/src/main/java/fr/sae/terraria/modele/items/Fibre.java deleted file mode 100644 index 8a27183..0000000 --- a/src/main/java/fr/sae/terraria/modele/items/Fibre.java +++ /dev/null @@ -1,4 +0,0 @@ -package fr.sae.terraria.modele.items; - - -public class Fibre extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/items/Iron.java b/src/main/java/fr/sae/terraria/modele/items/Iron.java deleted file mode 100644 index cf77836..0000000 --- a/src/main/java/fr/sae/terraria/modele/items/Iron.java +++ /dev/null @@ -1,4 +0,0 @@ -package fr.sae.terraria.modele.items; - - -public class Iron extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/items/Meat.java b/src/main/java/fr/sae/terraria/modele/items/Meat.java deleted file mode 100644 index 998f910..0000000 --- a/src/main/java/fr/sae/terraria/modele/items/Meat.java +++ /dev/null @@ -1,3 +0,0 @@ -package fr.sae.terraria.modele.items; - -public class Meat extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/items/Pierre.java b/src/main/java/fr/sae/terraria/modele/items/Pierre.java deleted file mode 100644 index 64a3df8..0000000 --- a/src/main/java/fr/sae/terraria/modele/items/Pierre.java +++ /dev/null @@ -1,4 +0,0 @@ -package fr.sae.terraria.modele.items; - - -public class Pierre extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/items/Silex.java b/src/main/java/fr/sae/terraria/modele/items/Silex.java deleted file mode 100644 index 8585133..0000000 --- a/src/main/java/fr/sae/terraria/modele/items/Silex.java +++ /dev/null @@ -1,4 +0,0 @@ -package fr.sae.terraria.modele.items; - - -public class Silex extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/items/Wood.java b/src/main/java/fr/sae/terraria/modele/items/Wood.java deleted file mode 100644 index 04a4b42..0000000 --- a/src/main/java/fr/sae/terraria/modele/items/Wood.java +++ /dev/null @@ -1,3 +0,0 @@ -package fr.sae.terraria.modele.items; - -public class Wood extends Item { } diff --git a/src/main/java/fr/sae/terraria/modele/tools/Axe.java b/src/main/java/fr/sae/terraria/modele/tools/Axe.java deleted file mode 100644 index 3901826..0000000 --- a/src/main/java/fr/sae/terraria/modele/tools/Axe.java +++ /dev/null @@ -1,4 +0,0 @@ -package fr.sae.terraria.modele.tools; - - -public class Axe extends Tool { } diff --git a/src/main/java/fr/sae/terraria/modele/tools/Bow.java b/src/main/java/fr/sae/terraria/modele/tools/Bow.java deleted file mode 100644 index d4e5f2b..0000000 --- a/src/main/java/fr/sae/terraria/modele/tools/Bow.java +++ /dev/null @@ -1,4 +0,0 @@ -package fr.sae.terraria.modele.tools; - - -public class Bow { } diff --git a/src/main/java/fr/sae/terraria/modele/tools/Pickaxe.java b/src/main/java/fr/sae/terraria/modele/tools/Pickaxe.java deleted file mode 100644 index c7c8bea..0000000 --- a/src/main/java/fr/sae/terraria/modele/tools/Pickaxe.java +++ /dev/null @@ -1,4 +0,0 @@ -package fr.sae.terraria.modele.tools; - - -public class Pickaxe extends Tool { } diff --git a/src/main/java/fr/sae/terraria/modele/tools/Sword.java b/src/main/java/fr/sae/terraria/modele/tools/Sword.java deleted file mode 100644 index b835bfe..0000000 --- a/src/main/java/fr/sae/terraria/modele/tools/Sword.java +++ /dev/null @@ -1,4 +0,0 @@ -package fr.sae.terraria.modele.tools; - - -public class Sword {} diff --git a/src/main/java/fr/sae/terraria/modele/tools/Tool.java b/src/main/java/fr/sae/terraria/modele/tools/Tool.java deleted file mode 100644 index 8656601..0000000 --- a/src/main/java/fr/sae/terraria/modele/tools/Tool.java +++ /dev/null @@ -1,6 +0,0 @@ -package fr.sae.terraria.modele.tools; - -import fr.sae.terraria.modele.entities.entity.StowableObjectType; - - -public class Tool implements StowableObjectType {} diff --git a/src/main/java/fr/sae/terraria/vue/Camera.java b/src/main/java/fr/sae/terraria/vue/Camera.java new file mode 100644 index 0000000..bdd0645 --- /dev/null +++ b/src/main/java/fr/sae/terraria/vue/Camera.java @@ -0,0 +1,81 @@ +package fr.sae.terraria.vue; + +import fr.sae.terraria.Terraria; +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.TileMaps; +import fr.sae.terraria.modele.entities.entity.Entity; +import fr.sae.terraria.modele.entities.player.Player; +import javafx.beans.binding.Bindings; +import javafx.scene.layout.StackPane; +import javafx.scene.shape.Rectangle; + + +public class Camera +{ + private final Environment environment; + private final Rectangle clip; + + + public Camera(final Environment environment, final StackPane paneHadCamera) + { + super(); + this.environment = environment; + + final TileMaps tileMaps = this.environment.getTileMaps(); + final Player player = this.environment.getPlayer(); + + int widthCamera = (int) (this.environment.scaleMultiplicatorWidth*Terraria.DISPLAY_RENDERING_WIDTH); + int heightCamera = (int) (this.environment.scaleMultiplicatorHeight*Terraria.DISPLAY_RENDERING_HEIGHT); + this.clip = new Rectangle(0, 0, widthCamera, heightCamera); + + int tileSize = (int) (environment.scaleMultiplicatorWidth*TileMaps.TILE_DEFAULT_SIZE); + int minScrollWidthCamera = 0; + int minScrollHeightCamera = 0; + int maxScrollWidthCamera = (tileMaps.getWidth()*tileSize) - widthCamera; + int scrollToleranceHeight = this.environment.heightTile*5; + int maxScrollHeightCamera = ((tileMaps.getHeight()*tileSize) - heightCamera) - scrollToleranceHeight; + + // Suit le joueur en 'x' + this.clip.xProperty().bind( + Bindings.createDoubleBinding( + () -> clampRange(player.getX() - this.clip.getWidth()/2, minScrollWidthCamera, maxScrollWidthCamera), + player.getXProperty(), paneHadCamera.widthProperty() + ) + ); + + // Evite que la caméra suit le joueur quand il saute sauf en cas de besoin + double midHeightCamera = (this.clip.getHeight()/2); + double[] centerPlayerOnYIntoCamera = new double[1]; + double[] gap = new double[1]; + player.getYProperty().addListener((obs, oldX, newX) -> { + // Suit le joueur + centerPlayerOnYIntoCamera[0] = player.getY() - midHeightCamera; + if (player.offset[1] == Entity.IS_JUMPING) { + gap[0] = player.getGravity().yInit - player.getY(); + centerPlayerOnYIntoCamera[0] = player.getGravity().yInit - midHeightCamera; + if (player.getGravity().timer > player.getGravity().flightTime*2 /* Légère bidouille */) + centerPlayerOnYIntoCamera[0] = player.getY() - midHeightCamera; + } + + // Décale "proprement" la caméra vers le haut + if (player.offset[1] == Entity.IDLE && gap[0] > 0) { + gap[0] /= 2; + centerPlayerOnYIntoCamera[0] = (player.getY() + gap[0]) - midHeightCamera; + } + }); + + // Suit le joueur en 'y' + this.clip.yProperty().bind( + Bindings.createDoubleBinding( + () -> clampRange(centerPlayerOnYIntoCamera[0], minScrollHeightCamera, maxScrollHeightCamera), + player.getYProperty(), paneHadCamera.heightProperty() + ) + ); + + paneHadCamera.setClip(this.clip); + paneHadCamera.translateXProperty().bind(this.clip.xProperty().multiply(-1)); + paneHadCamera.translateYProperty().bind(this.clip.yProperty().multiply(-1)); + } + + private double clampRange(double value, double min, double max) { return (value < min) ? min : (value > max) ? max : value; } +} diff --git a/src/main/java/fr/sae/terraria/vue/HUDView.java b/src/main/java/fr/sae/terraria/vue/HUDView.java deleted file mode 100644 index a1211ee..0000000 --- a/src/main/java/fr/sae/terraria/vue/HUDView.java +++ /dev/null @@ -1,225 +0,0 @@ -package fr.sae.terraria.vue; - -import fr.sae.terraria.Terraria; -import fr.sae.terraria.modele.Clock; -import fr.sae.terraria.modele.TileMaps; -import fr.sae.terraria.modele.blocks.Dirt; -import fr.sae.terraria.modele.blocks.Stone; -import fr.sae.terraria.modele.blocks.TallGrass; -import fr.sae.terraria.modele.entities.Player; -import fr.sae.terraria.modele.entities.entity.StowableObjectType; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; -import javafx.collections.ListChangeListener; -import javafx.geometry.Rectangle2D; -import javafx.scene.control.Label; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import javafx.scene.layout.Pane; -import javafx.scene.shape.Rectangle; -import javafx.scene.text.Font; -import javafx.scene.transform.Rotate; - -import java.util.Objects; - - -public class HUDView -{ - private final ImageView inventoryBarImgView; - private final ImageView cursorImgView; - - private final Image inventoryBarImg; - private final Image healthBarImg; - private final Image clockImg; - private final Image clockCursorImg; - - private final Rectangle frameInventoryBar; - - private final Clock gameTime; - private final Player player; - private final Pane display; - - private double scaleMultiplicatorWidth; - private double scaleMultiplicatorHeight; - private double windowWidth; - private double windowHeight; - private int tileWidth; - private int tileHeight; - - - /** - * Affiche tout ce qui concerne l'HUD - * - * @param gameTime Pour afficher l'horloge - * @param display Sur quel pane l'HUD doit s'afficher - */ - public HUDView(Player player, Clock gameTime, Pane display, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) - { - this.player = player; - this.display = display; - this.scaleMultiplicatorWidth = scaleMultiplicatorWidth; - this.scaleMultiplicatorHeight = scaleMultiplicatorHeight; - this.gameTime = gameTime; - - new ItemSelectedView(display, player, scaleMultiplicatorWidth, scaleMultiplicatorHeight); - - this.windowWidth = (scaleMultiplicatorWidth * Terraria.DISPLAY_RENDERING_WIDTH); - this.windowHeight = (scaleMultiplicatorHeight * Terraria.DISPLAY_RENDERING_HEIGHT); - this.tileWidth = (int) (scaleMultiplicatorWidth * TileMaps.TILE_DEFAULT_SIZE); - this.tileHeight = (int) (scaleMultiplicatorHeight * TileMaps.TILE_DEFAULT_SIZE); - - this.frameInventoryBar = new Rectangle(); - this.healthBarImg = View.loadAnImage("health.png", scaleMultiplicatorWidth, scaleMultiplicatorHeight); - this.inventoryBarImg = View.loadAnImage("inventoryBar.png", scaleMultiplicatorWidth, scaleMultiplicatorHeight); - Image cursorImg = View.loadAnImage("cursor.png", scaleMultiplicatorWidth, scaleMultiplicatorHeight); - this.clockImg = View.loadAnImage("clock.png",scaleMultiplicatorWidth,scaleMultiplicatorHeight); - this.clockCursorImg = View.loadAnImage("clock-cursor.png",scaleMultiplicatorWidth,scaleMultiplicatorHeight); - - this.inventoryBarImgView = new ImageView(inventoryBarImg); - this.cursorImgView = new ImageView(cursorImg); - - this.refreshItemsInventoryBar(); - } - - /** Applique une bordure de couleur noire autour de la barre d'inventaire */ - private Rectangle setFrameInventoryBar(ImageView inventoryBarImgView) - { - frameInventoryBar.setWidth(inventoryBarImg.getWidth() + (2*scaleMultiplicatorWidth)); - frameInventoryBar.setHeight(inventoryBarImg.getHeight() + (2*scaleMultiplicatorHeight)); - frameInventoryBar.setX(inventoryBarImgView.getX() - scaleMultiplicatorWidth); - frameInventoryBar.setY(inventoryBarImgView.getY() - scaleMultiplicatorHeight); - - return frameInventoryBar; - } - - /** Applique sur les toutes les cases de l'inventaire des écouteurs qui permet d'actualiser les images des items */ - private void refreshItemsInventoryBar() - { - for (int i = 0; i < this.player.getInventory().size(); i++) - this.player.getInventory().get(i).addListener((ListChangeListener) c -> { - while(c.next()) - this.displayItemIntoInventoryBar(); - }); - } - - /** Affiche ou supprime les items qui rentrent ou sort de la barre d'inventaire */ - private void displayItemIntoInventoryBar() - { - int itemInventoryWidth = (int) (tileWidth/1.5); - int itemInventoryHeight = (int) (tileHeight/1.5); - - int nbElementDisplayed = Player.NB_CASES_MAX_INVENTORY/Player.NB_LINES_INVENTORY; - if (this.player.nbStacksIntoInventory() <= Player.NB_CASES_MAX_INVENTORY/Player.NB_LINES_INVENTORY) - nbElementDisplayed = this.player.nbStacksIntoInventory(); - - int compteur = 0; - for (int integer = 0 ; integer < nbElementDisplayed; integer++) { - ImageView itemView = new ImageView(); - Image item = null; - - if (this.player.getInventory().get(integer).get(0) instanceof Dirt) - item = View.loadAnImage("tiles/floor-top.png", itemInventoryWidth, itemInventoryHeight); - else if (this.player.getInventory().get(integer).get(0) instanceof Stone) - item = View.loadAnImage("tiles/rock-fill.png", itemInventoryWidth, itemInventoryHeight); - else if (this.player.getInventory().get(integer).get(0) instanceof TallGrass) - item = View.loadAnImage("tiles/tall-grass.png", itemInventoryWidth, itemInventoryHeight); - - if (!Objects.isNull(item)) { - itemView.setImage(item); - itemView.setX(inventoryBarImgView.getX() + (((inventoryBarImgView.getImage().getWidth()/9) - item.getWidth())/2) + ((inventoryBarImgView.getImage().getWidth()/9)*compteur)); - itemView.setY(inventoryBarImgView.getY() + ((inventoryBarImgView.getImage().getHeight() - item.getHeight())/2)); - - int fontSize = (int) (5*scaleMultiplicatorWidth); - Label nbObjects = new Label(); - nbObjects.setId("textInventoryBar"); - nbObjects.setFont(new Font("Arial", fontSize)); - nbObjects.setText(String.valueOf(this.player.getInventory().get(integer).size())); - nbObjects.setLayoutX(itemView.getX()); - nbObjects.setLayoutY(itemView.getY() + item.getHeight() - fontSize); - - StringProperty stringProperty = new SimpleStringProperty(String.valueOf(this.player.getInventory().get(integer).size())); - this.player.getInventory().get(integer).addListener((ListChangeListener) c -> stringProperty.setValue(String.valueOf(c.getList().size()))); - nbObjects.textProperty().bind(stringProperty); - - display.getChildren().add(itemView); - display.getChildren().add(nbObjects); - compteur++; - } - } - } - - /** Affiche la barre d'inventaire */ - public void displayInventoryBar() - { - this.inventoryBarImgView.setX(((windowWidth - inventoryBarImg.getWidth())/2)); - this.inventoryBarImgView.setY((windowHeight - inventoryBarImg.getHeight()) - tileHeight); - - display.getChildren().add(setFrameInventoryBar(inventoryBarImgView)); - display.getChildren().add(inventoryBarImgView); - } - - /** Affiche un carré qui se superpose sur la barre d'inventaire qui permet de savoir où on se situe */ - public void displayCursorInventoryBar() - { - this.cursorImgView.setX(((windowWidth - inventoryBarImg.getWidth())/2 - scaleMultiplicatorWidth)); - this.cursorImgView.setY(((windowHeight - inventoryBarImg.getHeight()) - tileHeight) - scaleMultiplicatorHeight); - - this.player.positionOfCursorInventoryBar.addListener((obs, oldV, newV) -> { - this.cursorImgView.setX(((windowWidth - inventoryBarImg.getWidth())/2 + ((inventoryBarImg.getWidth()/9) * newV.intValue() - scaleMultiplicatorWidth))); - if (newV.intValue() >= 0 && newV.intValue() < (Player.NB_CASES_MAX_INVENTORY/Player.NB_LINES_INVENTORY)) - this.player.setItemSelected((!this.player.getInventory().get(newV.intValue()).isEmpty()) ? this.player.getInventory().get(newV.intValue()).get(0) : null); - }); - - display.getChildren().add(cursorImgView); - } - - /** Affiche la barre de vie du joueur */ - public void displayHealthBar() - { - // Crée et positionne les cœurs dans un tableau de longueur qui correspond à la vie max du joueur. - ImageView[] healths = new ImageView[(int) (player.getPvMax())]; - for (int i = 0; i < player.getPvMax(); i++) { - ImageView healthView = new ImageView(healthBarImg); - Rectangle2D viewPort = new Rectangle2D((healthView.getImage().getWidth()/3)*2, 0, (healthView.getImage().getWidth()/3), healthView.getImage().getHeight()); - - healthView.setViewport(viewPort); - healthView.setX(inventoryBarImgView.getX() + ((healthView.getImage().getWidth()/3)*i)); - healthView.setY((inventoryBarImgView.getY() - healthView.getImage().getHeight()) - (2*scaleMultiplicatorHeight)); - display.getChildren().add(healthView); - healths[i] = healthView; - } - - // Modifie le cœur selon la vie du joueur - player.getPvProperty().addListener((obs, oldPv, newPv) -> { - if (oldPv.intValue() >= 0) { - ImageView healthView = healths[oldPv.intValue()-1]; - - Rectangle2D viewPort = new Rectangle2D((healthView.getImage().getWidth()/3)*0, 0, (healthView.getImage().getWidth()/3), healthView.getImage().getHeight()); - healthView.setViewport(viewPort); - } - }); - } - - /** Affiche une horloge à aiguille visuelle à l'écran. */ - public void displayClock() - { - ImageView clockCursorView = new ImageView(clockCursorImg); - ImageView clockView = new ImageView(clockImg); - Rotate rotate = new Rotate(); - double yClock = inventoryBarImgView.getY() - clockImg.getHeight(); - double xClock = inventoryBarImgView.getX() + (inventoryBarImg.getWidth()/2 - clockImg.getWidth()/2); - - clockCursorView.setX(xClock + (clockImg.getWidth()/2) - (clockCursorImg.getWidth()/2)); - clockCursorView.setY(yClock); - clockView.setX(xClock); - clockView.setY(yClock); - - rotate.setPivotX(xClock + (clockImg.getWidth()/2) - (clockCursorImg.getWidth()/2) + (clockCursorImg.getWidth()/2)); - rotate.setPivotY(yClock + clockCursorImg.getHeight()); - gameTime.minutesProperty().addListener(((obs, oldV, newV) -> rotate.setAngle((newV.intValue()/8) - 90))); - clockCursorView.getTransforms().add(rotate); - - display.getChildren().add(clockView); - display.getChildren().add(clockCursorView); - } -} diff --git a/src/main/java/fr/sae/terraria/vue/ItemSelectedView.java b/src/main/java/fr/sae/terraria/vue/ItemSelectedView.java deleted file mode 100644 index 82122da..0000000 --- a/src/main/java/fr/sae/terraria/vue/ItemSelectedView.java +++ /dev/null @@ -1,79 +0,0 @@ -package fr.sae.terraria.vue; - -import fr.sae.terraria.modele.TileMaps; -import fr.sae.terraria.modele.blocks.Dirt; -import fr.sae.terraria.modele.blocks.Stone; -import fr.sae.terraria.modele.entities.Player; -import fr.sae.terraria.modele.entities.entity.StowableObjectType; -import fr.sae.terraria.modele.items.*; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import javafx.scene.input.MouseEvent; -import javafx.scene.layout.Pane; - - - -public class ItemSelectedView -{ - private ImageView itemSelectedImgView; - - private Image stoneItemImg; - private Image dirtItemImg; - private Image coalItemImg; - private Image fibreItemImg; - private Image ironItemImg; - private Image pierreItemImg; - private Image silexItemImg; - private Image meatItemImg; - private Image woodItemImg; - - - public ItemSelectedView(Pane display, Player player, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) - { - int widthTile = (int) (scaleMultiplicatorWidth * TileMaps.TILE_DEFAULT_SIZE); - int heightTile = (int) (scaleMultiplicatorHeight * TileMaps.TILE_DEFAULT_SIZE); - int widthItem = widthTile/2; - int heightItem = heightTile/2; - - this.itemSelectedImgView = new ImageView(); - this.dirtItemImg = View.loadAnImage("tiles/floor-top.png", widthItem, heightItem); - this.stoneItemImg = View.loadAnImage("tiles/rock-fill.png", widthItem, heightItem); - this.coalItemImg = View.loadAnImage("loots/coal.png", widthItem, heightItem); - this.fibreItemImg = View.loadAnImage("loots/fibre.png", widthItem, heightItem); - this.ironItemImg = View.loadAnImage("loots/iron.png", widthItem, heightItem); - this.pierreItemImg = View.loadAnImage("loots/pierre.png", widthItem, heightItem); - this.silexItemImg = View.loadAnImage("loots/silex.png", widthItem, heightItem); - this.meatItemImg = View.loadAnImage("loots/viande.png", widthItem, heightItem); - this.woodItemImg = View.loadAnImage("loots/wood.png", widthItem, heightItem); - - player.positionOfCursorInventoryBar.addListener((obs, oldItemSelected, newItemSelected) -> { - StowableObjectType item = player.getItemSelected(); - - if (item instanceof Dirt) - itemSelectedImgView.setImage(dirtItemImg); - else if (item instanceof Stone) - itemSelectedImgView.setImage(stoneItemImg); - else if (item instanceof Coal) - itemSelectedImgView.setImage(coalItemImg); - else if (item instanceof Fibre) - itemSelectedImgView.setImage(fibreItemImg); - else if (item instanceof Iron) - itemSelectedImgView.setImage(ironItemImg); - else if (item instanceof Pierre) - itemSelectedImgView.setImage(pierreItemImg); - else if (item instanceof Silex) - itemSelectedImgView.setImage(silexItemImg); - else if (item instanceof Meat) - itemSelectedImgView.setImage(meatItemImg); - else if (item instanceof Wood) - itemSelectedImgView.setImage(woodItemImg); - else itemSelectedImgView.setImage(null); - }); - - display.addEventFilter(MouseEvent.MOUSE_MOVED, mouse -> { - itemSelectedImgView.setX(mouse.getX()); - itemSelectedImgView.setY(mouse.getY()); - }); - display.getChildren().add(itemSelectedImgView); - } -} diff --git a/src/main/java/fr/sae/terraria/vue/LightView.java b/src/main/java/fr/sae/terraria/vue/LightView.java new file mode 100644 index 0000000..f80be65 --- /dev/null +++ b/src/main/java/fr/sae/terraria/vue/LightView.java @@ -0,0 +1,165 @@ +package fr.sae.terraria.vue; + +import fr.sae.terraria.modele.Clock; +import fr.sae.terraria.modele.Environment; +import fr.sae.terraria.modele.TileMaps; +import fr.sae.terraria.modele.entities.blocks.Torch; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.scene.layout.Pane; +import javafx.scene.paint.*; +import javafx.scene.shape.Circle; +import javafx.scene.shape.Rectangle; +import javafx.scene.shape.Shape; + +public class LightView { + private static final int CIRCLE_RAY = 3; + private static final Color NIGHT_COLOR = Color.web("#0d0d38"); + private static final Stop[] STOPS_FADE = new Stop[] { new Stop(0,new Color(0,0,0,0) ), new Stop(1, NIGHT_COLOR)}; + private static final LinearGradient GRADIENT_FADE = new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE, STOPS_FADE); + private static final Stop[] STOPS_TORCH = new Stop[] { new Stop(0, Color.RED),new Stop(0.1, Color.web("#fbff00")), new Stop(1,new Color(0.9843,1,0,0.05))}; + private static final RadialGradient GRADIENT_TORCH = new RadialGradient(0,0,.5,.5,0.3,true,CycleMethod.NO_CYCLE, STOPS_TORCH); + + private static int delimitationDirtStone; + private static int widthMap; + private static int tileSize; + + private final SimpleDoubleProperty opacityNightAir; + private final SimpleDoubleProperty opacityNightFade; + private final Environment environment; + private final TileMaps tileMaps; + private final Circle torchLight; + private final Pane filterPane; + private final Clock clock; + + private Shape actualAir; + private Shape actualFade; + private Shape actualTunnel; + + + public LightView(Clock clock, Pane filterPane, Environment env) { + this.clock = clock; + this.environment = env; + this.filterPane = filterPane; + this.tileMaps= env.getTileMaps(); + tileSize = (int) (env.scaleMultiplicatorHeight*TileMaps.TILE_DEFAULT_SIZE); + widthMap = (int) (env.scaleMultiplicatorWidth*TileMaps.TILE_DEFAULT_SIZE*tileMaps.getWidth()); + delimitationDirtStone = fullStoneArea(); + + this.opacityNightAir = new SimpleDoubleProperty(.0); + this.opacityNightFade = new SimpleDoubleProperty(.8143); + + this.torchLight = new Circle(this.tileSize*CIRCLE_RAY); + + this.resetShapes(); + this.addEffects(); + + this.clock.minutesProperty().addListener(((obs, oldV, newV) -> updateOpacity())); + + this.filterPane.getChildren().addAll(this.actualTunnel, this.actualFade, this.actualAir); + this.initTochListener(env.getTorches()); + } + + private void initTochListener(ObservableList torches) { + torches.addListener((ListChangeListener) c -> { + while(c.next()){ + this.filterPane.getChildren().clear(); + addTochLights(); + if (c.wasRemoved()){ + resetShapes(); + + for (int i = 0; i < this.environment.getTorches().size(); i++){ + this.torchLight.setLayoutX(this.environment.getTorches().get(i).getX() + (tileSize/2)); + this.torchLight.setLayoutY(this.environment.getTorches().get(i).getY() + (tileSize/3)); + + this.actualAir = Shape.subtract(this.actualAir, this.torchLight); + this.actualFade = Shape.subtract(this.actualFade, this.torchLight); + this.actualTunnel = Shape.subtract(this.actualTunnel, this.torchLight); + } + + } + else if (c.wasAdded()){ + + for (int i = 0; i < c.getAddedSubList().size(); i++) { + this.torchLight.setLayoutX(c.getAddedSubList().get(i).getX() + (tileSize/2)); + this.torchLight.setLayoutY(c.getAddedSubList().get(i).getY()+ (tileSize/3)); + + this.actualAir = Shape.subtract(this.actualAir, this.torchLight); + this.actualFade = Shape.subtract(this.actualFade, this.torchLight); + this.actualTunnel = Shape.subtract(this.actualTunnel, this.torchLight); + } + } + addEffects(); + + this.filterPane.getChildren().addAll(this.actualTunnel, this.actualAir, this.actualFade); + }}); + } + + private void updateOpacity() + { + if (this.clock.getMinutes() > Clock.MINUTES_IN_A_DAY/2) + this.opacityNightAir.set(((this.clock.getMinutes()*(2. /* Compensation temps */))/Clock.MINUTES_IN_A_DAY) - (1.1 /* Décallage */)); + else this.opacityNightAir.set(((Clock.MINUTES_IN_A_DAY - (this.clock.getMinutes()*(4. /* Compensation temps */)))/Clock.MINUTES_IN_A_DAY) - (.1 /* Décallage */)); + } + + + private int fullStoneArea() + { + int line = 0; + int column; + boolean found = false; + boolean wrongLine; + + while (line < this.tileMaps.getHeight() && !found) { + wrongLine = false; + column = 0; + + while (column < this.tileMaps.getWidth() && !found && !wrongLine) { + if (this.tileMaps.getTile(column, line) != TileMaps.STONE) + wrongLine = true; + else if (column == this.tileMaps.getWidth() - 1) + found = true; + column++; + } + line++; + } + return line - 1; + } + + private void resetShapes() + { + this.actualAir = new Rectangle(widthMap,tileSize*this.tileMaps.getHeight()); + this.actualFade = new Rectangle(widthMap,tileSize); + this.actualTunnel = new Rectangle(widthMap,tileSize* this.tileMaps.getHeight() - tileSize*delimitationDirtStone); + + this.actualTunnel.setLayoutY(tileSize*(delimitationDirtStone+1)); + this.actualFade.setLayoutY(this.actualTunnel.getLayoutY()-tileSize); + } + + private void addEffects() + { + this.actualFade.setFill(GRADIENT_FADE); + this.actualAir.setFill(NIGHT_COLOR); + this.actualTunnel.setFill(NIGHT_COLOR); + + this.actualTunnel.opacityProperty().bind(this.opacityNightFade); + this.actualFade.opacityProperty().bind(this.opacityNightFade); + this.actualAir.opacityProperty().bind(this.opacityNightAir); + } + + private void addTochLights() + { + for (int i = 0; i < this.environment.getTorches().size() ; i ++){ + Circle torchLight = new Circle(tileSize*CIRCLE_RAY); + + torchLight.setLayoutX(this.environment.getTorches().get(i).getX() + (tileSize/2)); + torchLight.setLayoutY(this.environment.getTorches().get(i).getY() + (tileSize/3)); + + torchLight.setFill(GRADIENT_TORCH); + torchLight.setOpacity(0.5); + + this.filterPane.getChildren().add(torchLight); + } + } +} diff --git a/src/main/java/fr/sae/terraria/vue/MouseCursorView.java b/src/main/java/fr/sae/terraria/vue/MouseCursorView.java deleted file mode 100644 index a763660..0000000 --- a/src/main/java/fr/sae/terraria/vue/MouseCursorView.java +++ /dev/null @@ -1,42 +0,0 @@ -package fr.sae.terraria.vue; - -import fr.sae.terraria.modele.TileMaps; -import javafx.scene.input.MouseEvent; -import javafx.scene.layout.Pane; -import javafx.scene.paint.Color; -import javafx.scene.shape.Rectangle; - - -public class MouseCursorView -{ - - - /** - * Un rectangle rouge qui suit la souris - * Permet de savoir où nous cliquons sur l'écran plus précisément sur quel tile - * - * @param display L'afficheur qui se gère du HUD - * @param scaleMultiplicatorWidth Scaling en largeur - * @param scaleMultiplicatorHeight Scaling en hauteur - */ - public MouseCursorView(Pane display, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) - { - int tileWidth = (int) (TileMaps.TILE_DEFAULT_SIZE * scaleMultiplicatorWidth); - int tileHeight = (int) (TileMaps.TILE_DEFAULT_SIZE * scaleMultiplicatorHeight); - Rectangle mouseCursorRect = new Rectangle(tileWidth, tileHeight); - - mouseCursorRect.setFill(Color.TRANSPARENT); - mouseCursorRect.setStroke(Color.RED); - mouseCursorRect.setStrokeWidth(2*scaleMultiplicatorWidth); - - display.addEventFilter(MouseEvent.MOUSE_MOVED, mouse -> { - int xCursor = (int) (mouse.getX()/tileWidth) * tileWidth; - int yCursor = (int) (mouse.getY()/tileHeight) * tileHeight; - - mouseCursorRect.setX(xCursor); - mouseCursorRect.setY(yCursor); - - }); - display.getChildren().add(mouseCursorRect); - } -} diff --git a/src/main/java/fr/sae/terraria/vue/PlayerView.java b/src/main/java/fr/sae/terraria/vue/PlayerView.java index e7ca455..6c612ec 100644 --- a/src/main/java/fr/sae/terraria/vue/PlayerView.java +++ b/src/main/java/fr/sae/terraria/vue/PlayerView.java @@ -1,6 +1,7 @@ package fr.sae.terraria.vue; -import fr.sae.terraria.modele.entities.Player; +import fr.sae.terraria.modele.entities.entity.Entity; +import fr.sae.terraria.modele.entities.player.Player; import javafx.geometry.Rectangle2D; import javafx.scene.image.Image; import javafx.scene.image.ImageView; @@ -48,10 +49,10 @@ private void setAnimation() player.getAnimation().getFrameProperty().addListener((obs, oldFrame, newFrame) -> { this.playerImgView.setViewport(new Rectangle2D(0, 0, widthPlayer, heightPlayer)); - if (player.offset[0] == 0 && player.offset[1] == 0) + if (player.offset[0] == Entity.IDLE && player.offset[1] == Entity.IDLE) this.playerImgView.setImage(this.playerIdleImg); - if (player.offset[0] == 1 || player.offset[0] == -1) { + if (player.offset[0] == Entity.IS_MOVING_RIGHT || player.offset[0] == Entity.IS_MOVING_LEFT) { Rectangle2D frameRect = new Rectangle2D((newFrame.intValue() * widthPlayer), 0, widthPlayer, heightPlayer); this.playerImgView.setViewport(frameRect); @@ -61,7 +62,7 @@ private void setAnimation() } /** Synchronise les coordonnées en x et y du joueur avec l'image et ensuite l'affiche sur le Pane */ - public void displayPlayer(Pane display) + public void displayPlayer(final Pane display) { this.setAnimation(); display.getChildren().add(playerImgView); diff --git a/src/main/java/fr/sae/terraria/vue/RabbitView.java b/src/main/java/fr/sae/terraria/vue/RabbitView.java index e511271..0c9e533 100644 --- a/src/main/java/fr/sae/terraria/vue/RabbitView.java +++ b/src/main/java/fr/sae/terraria/vue/RabbitView.java @@ -2,6 +2,7 @@ import fr.sae.terraria.modele.TileMaps; import fr.sae.terraria.modele.entities.Rabbit; +import fr.sae.terraria.modele.entities.entity.Entity; import javafx.geometry.Rectangle2D; import javafx.scene.image.Image; import javafx.scene.image.ImageView; @@ -21,8 +22,9 @@ public class RabbitView private int heightTile; - public RabbitView(Rabbit rabbit, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) + public RabbitView(final Rabbit rabbit, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) { + super(); this.rabbit = rabbit; this.widthTile = (int) (scaleMultiplicatorWidth * TileMaps.TILE_DEFAULT_SIZE); @@ -37,26 +39,26 @@ private void setAnimation() { // Change la limite de frame de l'animation selon le sprite sheet chargé this.rabbitImgView.imageProperty().addListener((obs, oldImg, newImg) -> { - int newEndFrame = (int) (newImg.getWidth() / widthTile); + int newEndFrame = (int) (newImg.getWidth() / this.widthTile); if (this.rabbit.getAnimation().getFrame() >= newEndFrame) this.rabbit.getAnimation().reset(); this.rabbit.getAnimation().setEndFrame(newEndFrame); }); this.rabbit.getAnimation().getFrameProperty().addListener((obs, oldFrame, newFrame) -> { - this.rabbitImgView.setViewport(new Rectangle2D(0, 0, widthTile, heightTile)); - if (rabbit.offset[0] == 1 || rabbit.offset[0] == -1) { - Rectangle2D frameRect = new Rectangle2D((newFrame.intValue() * widthTile), 0, widthTile, heightTile); + this.rabbitImgView.setViewport(new Rectangle2D(0, 0, this.widthTile, this.heightTile)); + if (this.rabbit.offset[0] == Entity.IS_MOVING_RIGHT || this.rabbit.offset[0] == Entity.IS_MOVING_LEFT) { + Rectangle2D frameRect = new Rectangle2D((newFrame.intValue() * this.widthTile), 0, this.widthTile, this.heightTile); - rabbitImgView.setViewport(frameRect); - rabbitImgView.setImage((rabbit.offset[0] == -1) ? rabbitLeftImg : rabbitRightImg); + this.rabbitImgView.setViewport(frameRect); + this.rabbitImgView.setImage((this.rabbit.offset[0] == -1) ? this.rabbitLeftImg : this.rabbitRightImg); } }); } - public void displayRabbit(Pane display) + public void displayRabbit(final Pane display) { this.setAnimation(); - display.getChildren().add(rabbitImgView); + display.getChildren().add(this.rabbitImgView); } } diff --git a/src/main/java/fr/sae/terraria/vue/SlimeView.java b/src/main/java/fr/sae/terraria/vue/SlimeView.java new file mode 100644 index 0000000..88df45c --- /dev/null +++ b/src/main/java/fr/sae/terraria/vue/SlimeView.java @@ -0,0 +1,48 @@ +package fr.sae.terraria.vue; + +import fr.sae.terraria.modele.TileMaps; +import fr.sae.terraria.modele.entities.Slime; +import fr.sae.terraria.modele.entities.entity.Entity; +import javafx.geometry.Rectangle2D; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.Pane; + + +public class SlimeView +{ + private final ImageView slimeImgView; + + private final Image slimeImg; + + private final Slime slime; + private int widthTile; + private int heightTile; + + + public SlimeView(final Slime slime, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) + { + super(); + this.slime = slime; + + this.widthTile = (int) (scaleMultiplicatorWidth * TileMaps.TILE_DEFAULT_SIZE); + this.heightTile = (int) (scaleMultiplicatorHeight * TileMaps.TILE_DEFAULT_SIZE); + + this.slimeImg = View.loadAnImage("sprites/slimes/green_slime.png", widthTile*4, heightTile); + this.slimeImgView = View.createImageView(slime, slimeImg); + } + + private void setAnimation() + { + this.slime.getAnimation().getFrameProperty().addListener((obs, oldV, newV) -> { + Rectangle2D frameRect = new Rectangle2D(newV.intValue() * this.widthTile, 0, this.widthTile, this.heightTile); + this.slimeImgView.setViewport(frameRect); + }); + } + + public void displaySlime(final Pane display) + { + this.setAnimation(); + display.getChildren().add(this.slimeImgView); + } +} diff --git a/src/main/java/fr/sae/terraria/vue/TileMapsView.java b/src/main/java/fr/sae/terraria/vue/TileMapsView.java index 1c0fa09..eb01e53 100644 --- a/src/main/java/fr/sae/terraria/vue/TileMapsView.java +++ b/src/main/java/fr/sae/terraria/vue/TileMapsView.java @@ -2,46 +2,55 @@ import fr.sae.terraria.modele.Environment; import fr.sae.terraria.modele.TileMaps; -import fr.sae.terraria.modele.blocks.Dirt; -import fr.sae.terraria.modele.blocks.Stone; -import fr.sae.terraria.modele.blocks.TallGrass; -import fr.sae.terraria.modele.blocks.Tree; import fr.sae.terraria.modele.entities.Rabbit; +import fr.sae.terraria.modele.entities.Slime; +import fr.sae.terraria.modele.entities.blocks.*; import fr.sae.terraria.modele.entities.entity.Entity; import javafx.collections.ListChangeListener; import javafx.geometry.Rectangle2D; +import javafx.scene.Node; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; -import java.time.Clock; import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class TileMapsView { - private Pane display; + private final Image torchImg; + private final Image floorTopImg; + private final Image floorLeftImg; + private final Image floorRightImg; + private final Image treeImg; + private final Image stoneImg; + private final Image dirtImg; + private final Image tallGrassImg; - private Environment environment; + private final Pane display; + + private final Environment environment; private int tileWidth; private int tileHeight; - private Clock clock; - - private Image floorTopImg; - private Image floorLeftImg; - private Image floorRightImg; - private Image treeImg; - private Image stoneImg; - private Image dirtImg; - private Image tallGrassImg; - public TileMapsView(Environment environment, Pane display, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) + /** + * @param environment Avoir des infos relatives à son environment + * @param displayTileMap Affiche la carte tuilée + * @param displayHostileBeings Affiche les êtres hostile (Animal, Joueur, ...) + */ + public TileMapsView(Environment environment, + Pane displayTileMap, + Pane displayHostileBeings, + double scaleMultiplicatorWidth, + double scaleMultiplicatorHeight) { + super(); this.environment = environment; - this.display = display; + this.display = displayTileMap; this.tileHeight = (int) (TileMaps.TILE_DEFAULT_SIZE * scaleMultiplicatorHeight); this.tileWidth = (int) (TileMaps.TILE_DEFAULT_SIZE * scaleMultiplicatorWidth); @@ -51,30 +60,59 @@ public TileMapsView(Environment environment, Pane display, double scaleMultiplic this.floorRightImg = View.loadAnImage("tiles/floor-right.png", tileWidth, tileHeight); this.stoneImg = View.loadAnImage("tiles/rock-fill.png", tileWidth, tileHeight); this.dirtImg = View.loadAnImage("tiles/dirt-top.png", tileWidth, tileHeight); + this.torchImg = View.loadAnImage("tiles/torch.png", tileWidth, tileHeight); this.treeImg = View.loadAnImage("sprites/tree-sheet.png", scaleMultiplicatorWidth, scaleMultiplicatorHeight); this.tallGrassImg = View.loadAnImage("tiles/tall-grass.png",tileWidth,tileHeight); - - - + // Lorsqu'un élément est ajouté, il le dessine automatiquement à l'écran environment.getEntities().addListener((ListChangeListener) c -> { + while (c.next()) { + if (c.wasAdded()) { + if (c.getList().get(0) instanceof Tree) + this.createTree((Tree) c.getList().get(0)); + if (c.getList().get(0) instanceof TallGrass) + this.createTallGrass((TallGrass) c.getList().get(0)); + if (c.getList().get(0) instanceof Rabbit) { + RabbitView rabbitView = new RabbitView((Rabbit) c.getList().get(0), scaleMultiplicatorWidth, scaleMultiplicatorHeight); + rabbitView.displayRabbit(displayHostileBeings); + } + if (c.getList().get(0) instanceof Slime) { + SlimeView slimeView = new SlimeView((Slime) c.getList().get(0), scaleMultiplicatorWidth, scaleMultiplicatorHeight); + slimeView.displaySlime(displayHostileBeings); + } + + if (c.getList().get(0) instanceof Torch) + createTorch((Torch) c.getList().get(0)); + if (c.getList().get(0) instanceof Dirt) + displayTileMap.getChildren().add(View.createImageView(c.getList().get(0), floorTopImg)); + if (c.getList().get(0) instanceof Stone) + displayTileMap.getChildren().add(View.createImageView(c.getList().get(0), stoneImg)); + } - while (c.next()) if (c.wasAdded()) { - if (c.getList().get(0) instanceof Tree) - createTree((Tree) c.getList().get(0)); - if (c.getList().get(0) instanceof TallGrass) - createTallGrass((TallGrass) c.getList().get(0)); - if (c.getList().get(0) instanceof Rabbit) { - RabbitView rabbitView = new RabbitView((Rabbit) c.getList().get(0), scaleMultiplicatorWidth, scaleMultiplicatorHeight); - rabbitView.displayRabbit(display); - } if (c.getList().get(0) instanceof Dirt) - display.getChildren().add(View.createImageView(c.getList().get(0), floorTopImg)); - if (c.getList().get(0) instanceof Stone) - display.getChildren().add(View.createImageView(c.getList().get(0), stoneImg)); + if (c.wasRemoved()) { + // La position de l'entité + int xEntity = (int) (c.getRemoved().get(0).getRect().get().getMinX()); + int yEntity = (int) (c.getRemoved().get(0).getRect().get().getMinY()); + + // Tant qu'on n'a pas trouvé l'objet sur le Pane, il continue la boucle. + Node nodeAtDelete = null; int i = 0; + do { + Node node = display.getChildren().get(i); + int xNode = (int) (node.getTranslateX()); + int yNode = (int) (node.getTranslateY()); + + if (xNode == xEntity && yNode == yEntity) { + nodeAtDelete = node; + display.getChildren().remove(nodeAtDelete); + } + i++; + } while (i < display.getChildren().size() && Objects.isNull(nodeAtDelete)); + } } }); } + /** Decompose la carte pour afficher un à un les tiles à l'écran */ public void displayMaps(TileMaps tiles) { for (int y = 0; y < tiles.getHeight() ; y++) @@ -98,106 +136,127 @@ public void displayMaps(TileMaps tiles) } } - private void createTree(Tree tree) + /** Crée et affiche un block de type arbre, il sera +/- grand */ + private void createTree(final Tree tree) { List imagesTree = new ArrayList<>(); int nbFoliage = ((int) (Math.random()*2))+1; int nbTrunk = ((int) (Math.random()*3))+1; - Rectangle2D viewportFirstFrame = new Rectangle2D(0, 0, tileWidth, tileHeight); + Rectangle2D viewportFirstFrame = new Rectangle2D(0, 0, this.tileWidth, this.tileHeight); ImageView firstFrameView = new ImageView(); - firstFrameView.setImage(treeImg); + firstFrameView.setImage(this.treeImg); firstFrameView.setViewport(viewportFirstFrame); imagesTree.add(firstFrameView); for (int f = 0; f < nbFoliage; f++) { - Rectangle2D viewportSecondFrame = new Rectangle2D(0, tileHeight, tileWidth, tileHeight); + Rectangle2D viewportSecondFrame = new Rectangle2D(0, this.tileHeight, this.tileWidth, this.tileHeight); ImageView secondFrameView = new ImageView(); - secondFrameView.setImage(treeImg); + secondFrameView.setImage(this.treeImg); secondFrameView.setViewport(viewportSecondFrame); imagesTree.add(secondFrameView); } if (nbTrunk > 1) { - Rectangle2D viewportEndTrunk = new Rectangle2D(0, (tileHeight*2), tileWidth, tileHeight); + Rectangle2D viewportEndTrunk = new Rectangle2D(0, (this.tileHeight*2), this.tileWidth, this.tileHeight); ImageView endTrunkView = new ImageView(); - endTrunkView.setImage(treeImg); + endTrunkView.setImage(this.treeImg); endTrunkView.setViewport(viewportEndTrunk); imagesTree.add(endTrunkView); for (int t = 0; t < nbTrunk-1; t++) { - Rectangle2D viewportTrunk = new Rectangle2D(tileWidth, (tileHeight*2), tileWidth, tileHeight); + Rectangle2D viewportTrunk = new Rectangle2D(this.tileWidth, (this.tileHeight*2), this.tileWidth, this.tileHeight); ImageView trunkView = new ImageView(); - trunkView.setImage(treeImg); + trunkView.setImage(this.treeImg); trunkView.setViewport(viewportTrunk); imagesTree.add(trunkView); } } else { - Rectangle2D viewportTrunk = new Rectangle2D(0, (tileHeight*2), tileWidth, tileHeight); + Rectangle2D viewportTrunk = new Rectangle2D(0, (this.tileHeight*2), this.tileWidth, this.tileHeight); ImageView trunkView = new ImageView(); - trunkView.setImage(treeImg); + trunkView.setImage(this.treeImg); trunkView.setViewport(viewportTrunk); imagesTree.add(trunkView); } - Rectangle2D viewportTrunkFoot = new Rectangle2D(0, (tileHeight*3), tileWidth, tileHeight); + Rectangle2D viewportTrunkFoot = new Rectangle2D(0, (this.tileHeight*3), this.tileWidth, this.tileHeight); ImageView trunkFootView = new ImageView(); - trunkFootView.setImage(treeImg); + trunkFootView.setImage(this.treeImg); trunkFootView.setViewport(viewportTrunkFoot); imagesTree.add(trunkFootView); for (int i = 0; i < imagesTree.size(); i++) { ImageView treeView = imagesTree.get(i); - treeView.setY((int) (((tree.getY() + tileHeight) + (i * tileHeight)) - (tileHeight * imagesTree.size()))); + treeView.setY((int) (((tree.getY() + this.tileHeight) + (i * this.tileHeight)) - (this.tileHeight * imagesTree.size()))); treeView.setX((int) tree.getX()); - display.getChildren().add(treeView); + this.display.getChildren().add(treeView); } - tree.setRect(tileWidth, (2+nbFoliage+nbTrunk)*tileHeight); + tree.setRect(this.tileWidth, (2+nbFoliage+nbTrunk)*this.tileHeight); } - private void createTallGrass(TallGrass tallGrass) + /** + * Crée et affiche un block de type Haute Herbe. + * Applique une animation de pousse à la haute herbe + */ + private void createTallGrass(final TallGrass tallGrass) { - ImageView tallGrassView = new ImageView(tallGrassImg); - tallGrass.setRect(tileWidth, tileHeight); + ImageView tallGrassView = new ImageView(this.tallGrassImg); + tallGrass.setRect(this.tileWidth, this.tileHeight); tallGrassView.setX(tallGrass.getX()); tallGrassView.setY(tallGrass.getY()); // L'animation de la pousse de la haute herbe tallGrass.getTallGrassGrowthProperty().addListener(((observable, oldValue, newValue) -> { - tallGrassView.setViewport(new Rectangle2D(0, 0, tallGrassImg.getWidth(), (newValue.intValue() < 1) ? 1 : (tallGrassImg.getHeight()/TallGrass.GROWTH_TALL_GRASS_STEP)*newValue.intValue())); - tallGrassView.setY((tallGrass.getY() - (tallGrassImg.getHeight()/TallGrass.GROWTH_TALL_GRASS_STEP)*newValue.intValue()) + tileHeight); + tallGrassView.setViewport(new Rectangle2D(0, 0, this.tallGrassImg.getWidth(), (newValue.intValue() < 1) ? 1 : (this.tallGrassImg.getHeight()/TallGrass.GROWTH_TALL_GRASS_STEP)*newValue.intValue())); + tallGrassView.setY((tallGrass.getY() - (this.tallGrassImg.getHeight()/TallGrass.GROWTH_TALL_GRASS_STEP)*newValue.intValue()) + this.tileHeight); })); - display.getChildren().add(tallGrassView); + this.display.getChildren().add(tallGrassView); } + /** Crée et affiche un tile de type pierre */ private void createStone(int x, int y) { - Stone stoneEntity = new Stone(x*tileWidth, y*tileHeight); - stoneEntity.setRect(tileWidth, tileHeight); - display.getChildren().add(View.createImageView(stoneEntity, stoneImg)); - environment.getEntities().add(stoneEntity); + Stone stoneEntity = new Stone(this.environment, x*this.tileWidth, y*this.tileHeight); + stoneEntity.setRect(this.tileWidth, this.tileHeight); + + this.display.getChildren().add(View.createImageView(stoneEntity, this.stoneImg)); + this.environment.getEntities().add(stoneEntity); + } + + /** Crée et affiche un block de type Torch */ + private void createTorch(final Torch torch) + { + torch.setRect(this.tileWidth, this.tileHeight); + this.display.getChildren().add(View.createImageView(torch, this.torchImg)); } + /** Crée et affiche un tile de type terre */ private void createDirt(int x, int y) { - Dirt dirtSprite = new Dirt(x*tileWidth, y*tileHeight); - dirtSprite.setRect(tileWidth, tileHeight); - display.getChildren().add(View.createImageView(dirtSprite, dirtImg)); - environment.getEntities().add(dirtSprite); + Dirt dirtSprite = new Dirt(this.environment, x*this.tileWidth, y*this.tileHeight); + dirtSprite.setRect(this.tileWidth, this.tileHeight); + + this.display.getChildren().add(View.createImageView(dirtSprite, this.dirtImg)); + this.environment.getEntities().add(dirtSprite); } + /** + * Crée et affiche un tile de type sol + * @param typeOfFloor Quel face du tile doit être affiché + */ private void createFloor(int typeOfFloor, int x, int y) { - Dirt floorEntity = new Dirt(x*tileWidth, y*tileHeight); - Image floorImg = (typeOfFloor == TileMaps.FLOOR_TOP) ? floorTopImg : (typeOfFloor == TileMaps.FLOOR_RIGHT) ? floorRightImg : floorLeftImg; - floorEntity.setRect(tileWidth, tileHeight); - display.getChildren().add(View.createImageView(floorEntity, floorImg)); + Dirt floorEntity = new Dirt(this.environment, x*this.tileWidth, y*this.tileHeight); + Image floorImg = (typeOfFloor == TileMaps.FLOOR_TOP) ? this.floorTopImg : (typeOfFloor == TileMaps.FLOOR_RIGHT) ? this.floorRightImg : this.floorLeftImg; + floorEntity.setRect(this.tileWidth, this.tileHeight); - environment.getEntities().add(floorEntity); + this.display.getChildren().add(View.createImageView(floorEntity, floorImg)); + this.environment.getEntities().add(floorEntity); } - private void errorTile(int tile) { if (tile != TileMaps.SKY) System.out.println("Le tile '" + tile + "' n'est pas reconnu."); } + /** Affiche une erreur au cas où si un developer a fait une erreur lors de la saisie d'un tile sur le fichier .json */ + private void errorTile(final int tile) { if (tile != TileMaps.SKY) System.out.println("Le tile '" + tile + "' n'est pas reconnu."); } } diff --git a/src/main/java/fr/sae/terraria/vue/View.java b/src/main/java/fr/sae/terraria/vue/View.java index f87de40..8463ccb 100644 --- a/src/main/java/fr/sae/terraria/vue/View.java +++ b/src/main/java/fr/sae/terraria/vue/View.java @@ -1,70 +1,75 @@ package fr.sae.terraria.vue; import fr.sae.terraria.Terraria; +import fr.sae.terraria.controller.GameController; import fr.sae.terraria.modele.Environment; import fr.sae.terraria.modele.entities.entity.Entity; +import fr.sae.terraria.vue.hud.HUDView; +import fr.sae.terraria.vue.hud.MouseCursorView; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; import java.io.File; import java.net.URL; +import java.util.Objects; public class View { + private static Environment environment; /** * Cette classe lors de l'initialisation, crée et génére toutes les views du jeux * Contient des fonctions essentiels au chargement des images et des creations de vue - * - * @param environment - - * @param displayTiledMap Le pane qui se charge d'afficher la carte - * @param displayHUD Le pane qui se charge d'afficher les elements du HUD - * @param scaleMultiplicatorWidth Le multiplicateur en largeur qui permet de redimensionner les images - * @param scaleMultiplicatorHeight Le multiplicateur en hauteur qui permet de redimensionner les images */ - public View(Environment environment, - Pane displayTiledMap, - Pane displayHUD, - double scaleMultiplicatorWidth, - double scaleMultiplicatorHeight) + public View(final GameController gameController) { - TileMapsView tileMapsView = new TileMapsView(environment, displayTiledMap, scaleMultiplicatorWidth, scaleMultiplicatorHeight); + super(); + + environment = gameController.environment; + final Pane displayTiledMap = gameController.displayTiledMap; + final Pane displayHostileBeings = gameController.displayHostileBeings; + final Pane displayHUD = gameController.displayHUD; + final Pane displayCursorMouse = gameController.displayCursorMouse; + final Pane filter = gameController.filter; + double scaleMultiplicatorWidth = gameController.scaleMultiplicatorWidth; + double scaleMultiplicatorHeight = gameController.scaleMultiplicatorHeight; + + TileMapsView tileMapsView = new TileMapsView(environment, displayTiledMap, displayHostileBeings, scaleMultiplicatorWidth, scaleMultiplicatorHeight); tileMapsView.displayMaps(environment.getTileMaps()); PlayerView playerView = new PlayerView(environment.getPlayer(), scaleMultiplicatorWidth, scaleMultiplicatorHeight); - playerView.displayPlayer(displayHUD); + playerView.displayPlayer(displayHostileBeings); - HUDView hudView = new HUDView(environment.getPlayer(), environment.getGameClock(), displayHUD, scaleMultiplicatorWidth, scaleMultiplicatorHeight); - hudView.displayInventoryBar(); - hudView.displayCursorInventoryBar(); - hudView.displayHealthBar(); - hudView.displayClock(); + LightView lightView = new LightView(environment.getGameClock(),filter,environment); - new MouseCursorView(displayHUD, scaleMultiplicatorWidth, scaleMultiplicatorHeight); + HUDView HUDView = new HUDView(environment.getPlayer(), environment.getGameClock(), displayHUD, scaleMultiplicatorWidth, scaleMultiplicatorHeight); + HUDView.display(); + + new MouseCursorView(displayHUD, displayCursorMouse, scaleMultiplicatorWidth, scaleMultiplicatorHeight); } /** Essaye de trouver et de charger l'image sinon renvoie null */ - private static Image foundImage(String path) + private static Image foundImage(final String path) { Image img = null; try { URL pathImg = Terraria.class.getResource(path).toURI().toURL(); - if (pathImg == null) - pathImg = new File(Terraria.srcPath + path).toURI().toURL(); + if (Objects.isNull(pathImg)) + pathImg = new File(Terraria.SRC_PATH + path).toURI().toURL(); img = new Image(pathImg.toString()); - } catch (Exception ignored) {} + } catch (Exception ignored) { } return img; } /** Charge une image avec une resolution carré (Ex: 16x16) */ - public static Image loadAnImage(String path, int tileWidth, int tileHeight) { return new Image(View.foundImage(path).getUrl(), tileWidth, tileHeight, false, false, false); } + public static Image loadAnImage(final String path, int tileWidth, int tileHeight) { return new Image(View.foundImage(path).getUrl(), tileWidth, tileHeight, false, false, false); } /** Charge une image avec une resolution non carrée */ - public static Image loadAnImage(String path, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) + public static Image loadAnImage(final String path, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) { Image img = View.foundImage(path); double width = img.getWidth(); @@ -76,7 +81,7 @@ public static Image loadAnImage(String path, double scaleMultiplicatorWidth, dou return new Image(img.getUrl(), widthScaled, heightScaled, false, false, false); } - public static ImageView createImageView(Entity entity, Image img) + public static ImageView createImageView(final Entity entity, final Image img) { ImageView imageView = new ImageView(img); imageView.translateXProperty().bind(entity.getXProperty()); diff --git a/src/main/java/fr/sae/terraria/vue/hud/ClockView.java b/src/main/java/fr/sae/terraria/vue/hud/ClockView.java new file mode 100644 index 0000000..e1ccbce --- /dev/null +++ b/src/main/java/fr/sae/terraria/vue/hud/ClockView.java @@ -0,0 +1,56 @@ +package fr.sae.terraria.vue.hud; + +import fr.sae.terraria.modele.Clock; +import fr.sae.terraria.vue.View; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.Pane; +import javafx.scene.transform.Rotate; + +public class ClockView +{ + private final Image clockCursorImg; + private final Image clockImg; + private final Clock gameTime; + private final Pane display; + + private double scaleMultiplicatorWidth; + private double scaleMultiplicatorHeight; + + + public ClockView(Clock gameTime, Pane display, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) + { + this.gameTime = gameTime; + this.display = display; + this.scaleMultiplicatorWidth = scaleMultiplicatorWidth; + this.scaleMultiplicatorHeight = scaleMultiplicatorHeight; + + this.clockImg = View.loadAnImage("clock.png",scaleMultiplicatorWidth,scaleMultiplicatorHeight); + this.clockCursorImg = View.loadAnImage("clock-cursor.png",scaleMultiplicatorWidth,scaleMultiplicatorHeight); + } + + /** Affiche une horloge à aiguille visuelle à l'écran. */ + private void displayClock(Image inventoryBarImg, double inventoryBarX, double inventoryBarY) + { + ImageView clockCursorView = new ImageView(clockCursorImg); + ImageView clockView = new ImageView(clockImg); + Rotate rotate = new Rotate(); + double yClock = inventoryBarY - clockImg.getHeight(); + double xClock = inventoryBarX + (inventoryBarImg.getWidth()/2 - clockImg.getWidth()/2); + + clockCursorView.setX(xClock + (clockImg.getWidth()/2) - (clockCursorImg.getWidth()/2)); + clockCursorView.setY(yClock); + clockView.setX(xClock); + clockView.setY(yClock); + + rotate.setPivotX(xClock + (clockImg.getWidth()/2) - (clockCursorImg.getWidth()/2) + (clockCursorImg.getWidth()/2)); + rotate.setPivotY(yClock + clockCursorImg.getHeight()); + gameTime.minutesProperty().addListener(((obs, oldV, newV) -> rotate.setAngle((newV.intValue()/8) - 90))); + clockCursorView.getTransforms().add(rotate); + + display.getChildren().add(clockView); + display.getChildren().add(clockCursorView); + } + + public void display(Image inventoryBarImg, double inventoryBarX, double inventoryBarY) { this.displayClock(inventoryBarImg, inventoryBarX, inventoryBarY); } +} diff --git a/src/main/java/fr/sae/terraria/vue/hud/HUDView.java b/src/main/java/fr/sae/terraria/vue/hud/HUDView.java new file mode 100644 index 0000000..acbaa8c --- /dev/null +++ b/src/main/java/fr/sae/terraria/vue/hud/HUDView.java @@ -0,0 +1,47 @@ +package fr.sae.terraria.vue.hud; + +import fr.sae.terraria.modele.Clock; +import fr.sae.terraria.modele.entities.player.Player; +import javafx.scene.layout.Pane; + + +public class HUDView +{ + private final Clock gameTime; + private final Player player; + private final Pane display; + + private double scaleMultiplicatorWidth; + private double scaleMultiplicatorHeight; + + + /** + * Affiche tout ce qui concerne l'HUD + * + * @param gameTime Pour afficher l'horloge + * @param display Sur quel pane l'HUD doit s'afficher + */ + public HUDView(Player player, Clock gameTime, Pane display, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) + { + this.player = player; + this.gameTime = gameTime; + this.display = display; + this.scaleMultiplicatorWidth = scaleMultiplicatorWidth; + this.scaleMultiplicatorHeight = scaleMultiplicatorHeight; + } + + public void display() + { + ItemSelectedView itemSelectedView = new ItemSelectedView(display, player, scaleMultiplicatorWidth, scaleMultiplicatorHeight); + itemSelectedView.display(); + + InventoryView inventoryView = new InventoryView(player.getInventory(), display, scaleMultiplicatorWidth, scaleMultiplicatorHeight); + inventoryView.display(); + + HealthBarView healthBarView = new HealthBarView(player, display, scaleMultiplicatorWidth, scaleMultiplicatorHeight); + healthBarView.display(inventoryView.getX(), inventoryView.getY()); + + ClockView clockView = new ClockView(gameTime, display, scaleMultiplicatorWidth, scaleMultiplicatorHeight); + clockView.display(inventoryView.getInventoryBarImg(), inventoryView.getX(), inventoryView.getY()); + } +} diff --git a/src/main/java/fr/sae/terraria/vue/hud/HealthBarView.java b/src/main/java/fr/sae/terraria/vue/hud/HealthBarView.java new file mode 100644 index 0000000..e50f58d --- /dev/null +++ b/src/main/java/fr/sae/terraria/vue/hud/HealthBarView.java @@ -0,0 +1,58 @@ +package fr.sae.terraria.vue.hud; + +import fr.sae.terraria.modele.entities.player.Player; +import fr.sae.terraria.vue.View; +import javafx.geometry.Rectangle2D; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.Pane; + +public class HealthBarView +{ + private final Image healthBarImg; + private Player player; + private Pane display; + + private double scaleMultiplicatorWidth; + private double scaleMultiplicatorHeight; + + + public HealthBarView(Player player, Pane display, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) + { + this.player = player; + this.display = display; + this.scaleMultiplicatorWidth = scaleMultiplicatorWidth; + this.scaleMultiplicatorHeight = scaleMultiplicatorHeight; + + this.healthBarImg = View.loadAnImage("health.png", scaleMultiplicatorWidth, scaleMultiplicatorHeight); + } + + /** Affiche la barre de vie du joueur */ + private void displayHealthBar(double inventoryBarX, double inventoryBarY) + { + // Crée et positionne les cœurs dans un tableau de longueur qui correspond à la vie max du joueur. + ImageView[] healths = new ImageView[(int) (player.getPvMax())]; + for (int i = 0; i < player.getPvMax(); i++) { + ImageView healthView = new ImageView(healthBarImg); + Rectangle2D viewPort = new Rectangle2D((healthBarImg.getWidth()/3)*2, 0, (healthBarImg.getWidth()/3), healthBarImg.getHeight()); + + healthView.setViewport(viewPort); + healthView.setX(inventoryBarX + ((healthView.getImage().getWidth()/3)*i)); + healthView.setY((inventoryBarY - healthView.getImage().getHeight()) - (2*scaleMultiplicatorHeight)); + display.getChildren().add(healthView); + healths[i] = healthView; + } + + // Modifie le cœur selon la vie du joueur + player.getPvProperty().addListener((obs, oldPv, newPv) -> { + if (oldPv.intValue() >= 0) { + ImageView healthView = healths[oldPv.intValue()-1]; + + Rectangle2D viewPort = new Rectangle2D((healthView.getImage().getWidth()/3)*0, 0, (healthView.getImage().getWidth()/3), healthView.getImage().getHeight()); + healthView.setViewport(viewPort); + } + }); + } + + public void display(double inventoryBarX, double inventoryBarY) { this.displayHealthBar(inventoryBarX, inventoryBarY); } +} diff --git a/src/main/java/fr/sae/terraria/vue/hud/InventoryView.java b/src/main/java/fr/sae/terraria/vue/hud/InventoryView.java new file mode 100644 index 0000000..801384c --- /dev/null +++ b/src/main/java/fr/sae/terraria/vue/hud/InventoryView.java @@ -0,0 +1,214 @@ +package fr.sae.terraria.vue.hud; + +import fr.sae.terraria.Terraria; +import fr.sae.terraria.modele.TileMaps; +import fr.sae.terraria.modele.entities.Arrow; +import fr.sae.terraria.modele.entities.blocks.Dirt; +import fr.sae.terraria.modele.entities.blocks.Stone; +import fr.sae.terraria.modele.entities.blocks.TallGrass; +import fr.sae.terraria.modele.entities.blocks.Torch; +import fr.sae.terraria.modele.entities.entity.StowableObjectType; +import fr.sae.terraria.modele.entities.items.*; +import fr.sae.terraria.modele.entities.player.inventory.Inventory; +import fr.sae.terraria.modele.entities.player.inventory.Stack; +import fr.sae.terraria.modele.entities.tools.Axe; +import fr.sae.terraria.modele.entities.tools.Bow; +import fr.sae.terraria.modele.entities.tools.Pickaxe; +import fr.sae.terraria.modele.entities.tools.Sword; +import fr.sae.terraria.vue.View; +import javafx.collections.ListChangeListener; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javafx.scene.text.Font; +import javafx.scene.text.Text; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + + +public class InventoryView +{ + private final ImageView inventoryBarImgView; + private final ImageView cursorImgView; + + private final Image inventoryBarImg; + + private final Rectangle frameInventoryBar; + private final Inventory inventory; + private final Pane display; + + private final List itemsView; + private final List texts; + + private double scaleMultiplicatorWidth; + private double scaleMultiplicatorHeight; + private double windowWidth; + private double windowHeight; + private int tileWidth; + private int tileHeight; + + + public InventoryView(Inventory inventory, Pane display, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) + { + this.inventory = inventory; + this.display = display; + this.scaleMultiplicatorHeight = scaleMultiplicatorHeight; + this.scaleMultiplicatorWidth = scaleMultiplicatorWidth; + + this.itemsView = new ArrayList<>(); + this.texts = new ArrayList<>(); + + this.windowWidth = (scaleMultiplicatorWidth * Terraria.DISPLAY_RENDERING_WIDTH); + this.windowHeight = (scaleMultiplicatorHeight * Terraria.DISPLAY_RENDERING_HEIGHT); + this.tileWidth = (int) (scaleMultiplicatorWidth * TileMaps.TILE_DEFAULT_SIZE); + this.tileHeight = (int) (scaleMultiplicatorHeight * TileMaps.TILE_DEFAULT_SIZE); + + this.frameInventoryBar = new Rectangle(); + this.inventoryBarImg = View.loadAnImage("inventoryBar.png", scaleMultiplicatorWidth, scaleMultiplicatorHeight); + this.inventoryBarImgView = new ImageView(inventoryBarImg); + Image cursorImg = View.loadAnImage("cursor.png", scaleMultiplicatorWidth, scaleMultiplicatorHeight); + this.cursorImgView = new ImageView(cursorImg); + } + + /** + * Applique une bordure de couleur noire autour de la barre d'inventaire + */ + private Rectangle setFrameInventoryBar() { + frameInventoryBar.setWidth(inventoryBarImg.getWidth() + (2 * scaleMultiplicatorWidth)); + frameInventoryBar.setHeight(inventoryBarImg.getHeight() + (2 * scaleMultiplicatorHeight)); + frameInventoryBar.setX(inventoryBarImgView.getX() - scaleMultiplicatorWidth); + frameInventoryBar.setY(inventoryBarImgView.getY() - scaleMultiplicatorHeight); + + return frameInventoryBar; + } + + /** + * Affiche ou supprime les items qui rentrent ou sort de la barre d'inventaire + */ + private void displayItemIntoInventoryBar() + { + int boxeInventoryWidth = (int) (this.inventoryBarImg.getWidth()/(Inventory.NB_BOXES_MAX/Inventory.NB_LINES)); + int itemInventoryWidth = (int) (tileWidth / 1.5); + int itemInventoryHeight = (int) (tileHeight / 1.5); + + this.inventory.get().addListener((ListChangeListener) c -> { + while (c.next()) { + if (c.wasAdded()) { + ImageView view = new ImageView(); + Stack stack = c.getAddedSubList().get(0); + StowableObjectType item = stack.getItem(); + + if (item instanceof Dirt) + view.setImage(View.loadAnImage("tiles/floor-top.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof Stone) + view.setImage(View.loadAnImage("tiles/rock-fill.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof TallGrass) + view.setImage(View.loadAnImage("tiles/tall-grass.png.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof Torch) + view.setImage(View.loadAnImage("tiles/torch.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof Coal) + view.setImage(View.loadAnImage("loots/coal.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof Fiber) + view.setImage(View.loadAnImage("loots/fiber.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof Iron) + view.setImage(View.loadAnImage("loots/iron.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof Meat) + view.setImage(View.loadAnImage("loots/meat.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof Pierre) + view.setImage(View.loadAnImage("loots/pierre.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof Silex) + view.setImage(View.loadAnImage("loots/silex.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof Wood) + view.setImage(View.loadAnImage("loots/wood.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof Axe) + view.setImage(null); // TODO + else if (item instanceof Bow) + view.setImage(null); // TODO + else if (item instanceof Pickaxe) + view.setImage(View.loadAnImage("tools/pickaxe.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof Sword) + view.setImage(View.loadAnImage("tools/sword.png", itemInventoryWidth, itemInventoryHeight)); + else if (item instanceof Arrow) + view.setImage(null); // TODO + + // Actualise le nombre d'item à l'écran + this.texts.get(c.getTo()-1).setText(String.valueOf(stack.getNbItems())); + stack.nbItemsProperty().addListener((obs, oldV, newV) -> this.texts.get(c.getTo()-1).setText(String.valueOf(newV.intValue()))); + + if (!Objects.isNull(view.getImage())) { + view.setX(this.inventoryBarImgView.getX() + ((c.getTo()-1) * boxeInventoryWidth)); + view.setY(this.inventoryBarImgView.getY()); + + this.itemsView.add(view); + this.display.getChildren().add(view); + } + } + + if (c.wasRemoved()) { + this.display.getChildren().remove(this.itemsView.get(c.getTo())); + this.itemsView.remove(c.getTo()); + + for (int i = c.getTo(); i < itemsView.size(); i++) + this.itemsView.get(i).setX(this.itemsView.get(i).getX() - boxeInventoryWidth); + } + } + }); + } + + /** + * Affiche la barre d'inventaire + */ + private void displayInventoryBar() + { + this.inventoryBarImgView.setX(((this.windowWidth - this.inventoryBarImg.getWidth()) / 2)); + this.inventoryBarImgView.setY((this.windowHeight - this.inventoryBarImg.getHeight()) - this.tileHeight); + + this.display.getChildren().add(setFrameInventoryBar()); + this.display.getChildren().add(this.inventoryBarImgView); + } + + /** + * Affiche un carré qui se superpose sur la barre d'inventaire qui permet de savoir où on se situe + */ + private void displayCursorInventoryBar() + { + this.cursorImgView.setX(((windowWidth - inventoryBarImg.getWidth()) / 2 - scaleMultiplicatorWidth)); + this.cursorImgView.setY(((windowHeight - inventoryBarImg.getHeight()) - tileHeight) - scaleMultiplicatorHeight); + this.inventory.posCursorProperty().addListener((obs, oldV, newV) -> this.cursorImgView.setX(((windowWidth - inventoryBarImg.getWidth()) / 2 + ((inventoryBarImg.getWidth() / 9) * newV.intValue() - scaleMultiplicatorWidth)))); + + this.display.getChildren().add(cursorImgView); + } + + public void display() + { + this.displayInventoryBar(); + this.displayCursorInventoryBar(); + + // Range et affiche tous les compteurs d'item de l'inventaire + int boxeInventoryWidth = (int) (this.inventoryBarImg.getWidth()/(Inventory.NB_BOXES_MAX/Inventory.NB_LINES)); + for (int i = 0; i < (Inventory.NB_BOXES_MAX/Inventory.NB_LINES); i++) { + Text text = new Text("0"); + text.setX(this.inventoryBarImgView.getX() + (boxeInventoryWidth*i)); + text.setY(this.inventoryBarImgView.getY() + boxeInventoryWidth); + text.setFont(new Font("Arial", 5*scaleMultiplicatorWidth)); + text.setStroke(Color.WHITE); // TODO Bizarre cette histoire de bordure qui fait la couleur final du Font + text.setStrokeWidth(1); + + this.texts.add(text); + this.display.getChildren().add(text); + } + + this.displayItemIntoInventoryBar(); + } + + + public double getX() { return this.inventoryBarImgView.getX(); } + + public double getY() { return this.inventoryBarImgView.getY(); } + + public Image getInventoryBarImg() { return inventoryBarImg; } +} diff --git a/src/main/java/fr/sae/terraria/vue/hud/ItemSelectedView.java b/src/main/java/fr/sae/terraria/vue/hud/ItemSelectedView.java new file mode 100644 index 0000000..3567ec8 --- /dev/null +++ b/src/main/java/fr/sae/terraria/vue/hud/ItemSelectedView.java @@ -0,0 +1,123 @@ +package fr.sae.terraria.vue.hud; + +import fr.sae.terraria.modele.TileMaps; +import fr.sae.terraria.modele.entities.Arrow; +import fr.sae.terraria.modele.entities.blocks.Dirt; +import fr.sae.terraria.modele.entities.blocks.Stone; +import fr.sae.terraria.modele.entities.blocks.TallGrass; +import fr.sae.terraria.modele.entities.blocks.Torch; +import fr.sae.terraria.modele.entities.entity.StowableObjectType; +import fr.sae.terraria.modele.entities.items.*; +import fr.sae.terraria.modele.entities.player.Player; +import fr.sae.terraria.modele.entities.player.inventory.Stack; +import fr.sae.terraria.modele.entities.tools.Axe; +import fr.sae.terraria.modele.entities.tools.Bow; +import fr.sae.terraria.modele.entities.tools.Pickaxe; +import fr.sae.terraria.modele.entities.tools.Sword; +import fr.sae.terraria.vue.View; +import javafx.collections.ListChangeListener; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.Pane; + +import java.util.Objects; + + +public class ItemSelectedView +{ + private final ImageView itemSelectedImgView; + + private final Image stoneItemImg; + private final Image dirtItemImg; + private final Image coalItemImg; + private final Image fibreItemImg; + private final Image ironItemImg; + private final Image pierreItemImg; + private final Image silexItemImg; + private final Image meatItemImg; + private final Image woodItemImg; + private final Image torchItemImg; + private final Image pickaxeItemImg; + + private final Pane display; + + + public ItemSelectedView(Pane display, Player player, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) + { + this.display = display; + + int widthTile = (int) (scaleMultiplicatorWidth * TileMaps.TILE_DEFAULT_SIZE); + int heightTile = (int) (scaleMultiplicatorHeight * TileMaps.TILE_DEFAULT_SIZE); + int widthItem = widthTile/2; + int heightItem = heightTile/2; + + this.itemSelectedImgView = new ImageView(); + this.dirtItemImg = View.loadAnImage("tiles/floor-top.png", widthItem, heightItem); + this.stoneItemImg = View.loadAnImage("tiles/rock-fill.png", widthItem, heightItem); + this.torchItemImg = View.loadAnImage("tiles/torch.png", widthItem, heightItem); + this.coalItemImg = View.loadAnImage("loots/coal.png", widthItem, heightItem); + this.fibreItemImg = View.loadAnImage("loots/fiber.png", widthItem, heightItem); + this.ironItemImg = View.loadAnImage("loots/iron.png", widthItem, heightItem); + this.pierreItemImg = View.loadAnImage("loots/pierre.png", widthItem, heightItem); + this.silexItemImg = View.loadAnImage("loots/silex.png", widthItem, heightItem); + this.meatItemImg = View.loadAnImage("loots/meat.png", widthItem, heightItem); + this.woodItemImg = View.loadAnImage("loots/wood.png", widthItem, heightItem); + this.pickaxeItemImg = View.loadAnImage("tools/pickaxe.png", widthItem, heightItem); + + // Reset + player.getInventory().get().addListener((ListChangeListener) c -> { + while (c.next()) { + if (c.wasRemoved()) + this.itemSelectedImgView.setImage(null); + } + }); + + player.getInventory().posCursorProperty().addListener((obs, oldItemSelected, newItemSelected) -> { + this.itemSelectedImgView.setImage(null); + if (!Objects.isNull(player.getStackSelected())) { + StowableObjectType item = player.getStackSelected().getItem(); + + if (item instanceof Dirt) + this.itemSelectedImgView.setImage(this.dirtItemImg); + else if (item instanceof Stone) + this.itemSelectedImgView.setImage(this.stoneItemImg); + else if (item instanceof TallGrass) + this.itemSelectedImgView.setImage(null); + else if (item instanceof Torch) + this.itemSelectedImgView.setImage(this.torchItemImg); + else if (item instanceof Coal) + this.itemSelectedImgView.setImage(this.coalItemImg); + else if (item instanceof Fiber) + this.itemSelectedImgView.setImage(this.fibreItemImg); + else if (item instanceof Iron) + this.itemSelectedImgView.setImage(this.ironItemImg); + else if (item instanceof Meat) + this.itemSelectedImgView.setImage(this.meatItemImg); + else if (item instanceof Pierre) + this.itemSelectedImgView.setImage(this.pierreItemImg); + else if (item instanceof Silex) + this.itemSelectedImgView.setImage(this.silexItemImg); + else if (item instanceof Wood) + this.itemSelectedImgView.setImage(this.woodItemImg); + else if (item instanceof Axe) + this.itemSelectedImgView.setImage(null); + else if (item instanceof Bow) + this.itemSelectedImgView.setImage(null); + else if (item instanceof Pickaxe) + this.itemSelectedImgView.setImage(this.pickaxeItemImg); + else if (item instanceof Sword) + this.itemSelectedImgView.setImage(null); + else if (item instanceof Arrow) + this.itemSelectedImgView.setImage(null); + } + }); + + display.addEventFilter(MouseEvent.MOUSE_MOVED, mouse -> { + itemSelectedImgView.setX(mouse.getX()); + itemSelectedImgView.setY(mouse.getY()); + }); + } + + public void display() { display.getChildren().add(itemSelectedImgView); } +} diff --git a/src/main/java/fr/sae/terraria/vue/hud/MouseCursorView.java b/src/main/java/fr/sae/terraria/vue/hud/MouseCursorView.java new file mode 100644 index 0000000..1a9edf8 --- /dev/null +++ b/src/main/java/fr/sae/terraria/vue/hud/MouseCursorView.java @@ -0,0 +1,64 @@ +package fr.sae.terraria.vue.hud; + +import fr.sae.terraria.Terraria; +import fr.sae.terraria.modele.TileMaps; +import javafx.animation.Animation; +import javafx.animation.KeyFrame; +import javafx.animation.Timeline; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javafx.util.Duration; + + +public class MouseCursorView +{ + private Rectangle mouseCursorRect; + private double scaleMultiplicatorWidth; + + + /** + * Un rectangle rouge qui suit la souris + * Permet de savoir où nous cliquons sur l'écran plus précisément sur quel tile + * + * @param display L'afficheur qui se gère du HUD + * @param scaleMultiplicatorWidth Scaling en largeur + * @param scaleMultiplicatorHeight Scaling en hauteur + */ + public MouseCursorView(Pane HUD, Pane display, double scaleMultiplicatorWidth, double scaleMultiplicatorHeight) + { + this.scaleMultiplicatorWidth = scaleMultiplicatorWidth; + + int tileWidth = (int) (TileMaps.TILE_DEFAULT_SIZE * scaleMultiplicatorWidth); + int tileHeight = (int) (TileMaps.TILE_DEFAULT_SIZE * scaleMultiplicatorHeight); + + mouseCursorRect = new Rectangle(tileWidth, tileHeight); + mouseCursorRect.setFill(Color.TRANSPARENT); + mouseCursorRect.setStroke(Color.RED); + this.setCursorAnimation(); + + HUD.addEventFilter(MouseEvent.MOUSE_MOVED, mouse -> { + int xCursor = (int) ((mouse.getX()+((Rectangle) display.getParent().getClip()).getX())/tileWidth) * tileWidth; + int yCursor = (int) ((mouse.getY()+((Rectangle) display.getParent().getClip()).getY())/tileHeight) * tileHeight; + + mouseCursorRect.setX(xCursor); + mouseCursorRect.setY(yCursor); + }); + display.getChildren().add(mouseCursorRect); + } + + private void setCursorAnimation() + { + Timeline loop = new Timeline(); + loop.setCycleCount(Animation.INDEFINITE); + + double[] time = new double[] {1}; + KeyFrame keyFrame = new KeyFrame(Duration.seconds(Terraria.TARGET_FPS), (ev -> { + mouseCursorRect.setStrokeWidth((Math.cos(time[0]) * scaleMultiplicatorWidth)+scaleMultiplicatorWidth); + time[0] += .05; + })); + loop.getKeyFrames().add(keyFrame); + loop.play(); + } +} diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index c9c616d..0b865f5 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -2,6 +2,7 @@ requires javafx.controls; requires javafx.fxml; requires com.google.gson; + requires java.desktop; opens fr.sae.terraria to javafx.fxml; @@ -14,4 +15,8 @@ opens fr.sae.terraria.modele.entities to javafx.fxml; exports fr.sae.terraria.modele.entities.entity; opens fr.sae.terraria.modele.entities.entity to javafx.fxml; + exports fr.sae.terraria.modele.entities.player; + opens fr.sae.terraria.modele.entities.player to javafx.fxml; + exports fr.sae.terraria.modele.entities.player.inventory; + opens fr.sae.terraria.modele.entities.player.inventory to javafx.fxml; } \ No newline at end of file diff --git a/src/main/resources/fr/sae/terraria/docs/ExampleExtendEntity.PNG b/src/main/resources/fr/sae/terraria/docs/ExampleExtendEntity.PNG new file mode 100644 index 0000000..55286a9 Binary files /dev/null and b/src/main/resources/fr/sae/terraria/docs/ExampleExtendEntity.PNG differ diff --git a/src/main/resources/fr/sae/terraria/docs/FonctionsMovable.PNG b/src/main/resources/fr/sae/terraria/docs/FonctionsMovable.PNG new file mode 100644 index 0000000..4b175b6 Binary files /dev/null and b/src/main/resources/fr/sae/terraria/docs/FonctionsMovable.PNG differ diff --git a/src/main/resources/fr/sae/terraria/loots/coal.png b/src/main/resources/fr/sae/terraria/loots/coal.png index d538fef..5fac266 100644 Binary files a/src/main/resources/fr/sae/terraria/loots/coal.png and b/src/main/resources/fr/sae/terraria/loots/coal.png differ diff --git a/src/main/resources/fr/sae/terraria/loots/fiber.png b/src/main/resources/fr/sae/terraria/loots/fiber.png new file mode 100644 index 0000000..c684039 Binary files /dev/null and b/src/main/resources/fr/sae/terraria/loots/fiber.png differ diff --git a/src/main/resources/fr/sae/terraria/loots/fibre.png b/src/main/resources/fr/sae/terraria/loots/fibre.png deleted file mode 100644 index c462063..0000000 Binary files a/src/main/resources/fr/sae/terraria/loots/fibre.png and /dev/null differ diff --git a/src/main/resources/fr/sae/terraria/loots/iron.png b/src/main/resources/fr/sae/terraria/loots/iron.png index c1bae97..1f98247 100644 Binary files a/src/main/resources/fr/sae/terraria/loots/iron.png and b/src/main/resources/fr/sae/terraria/loots/iron.png differ diff --git a/src/main/resources/fr/sae/terraria/loots/meat.png b/src/main/resources/fr/sae/terraria/loots/meat.png new file mode 100644 index 0000000..899c14b Binary files /dev/null and b/src/main/resources/fr/sae/terraria/loots/meat.png differ diff --git a/src/main/resources/fr/sae/terraria/loots/pierre.png b/src/main/resources/fr/sae/terraria/loots/pierre.png index c3d71d8..b6a559f 100644 Binary files a/src/main/resources/fr/sae/terraria/loots/pierre.png and b/src/main/resources/fr/sae/terraria/loots/pierre.png differ diff --git a/src/main/resources/fr/sae/terraria/loots/silex.png b/src/main/resources/fr/sae/terraria/loots/silex.png index 3134a55..e221d06 100644 Binary files a/src/main/resources/fr/sae/terraria/loots/silex.png and b/src/main/resources/fr/sae/terraria/loots/silex.png differ diff --git a/src/main/resources/fr/sae/terraria/loots/viande.png b/src/main/resources/fr/sae/terraria/loots/viande.png deleted file mode 100644 index 45a4aff..0000000 Binary files a/src/main/resources/fr/sae/terraria/loots/viande.png and /dev/null differ diff --git a/src/main/resources/fr/sae/terraria/loots/wood.png b/src/main/resources/fr/sae/terraria/loots/wood.png index 0f4a952..dca0b23 100644 Binary files a/src/main/resources/fr/sae/terraria/loots/wood.png and b/src/main/resources/fr/sae/terraria/loots/wood.png differ diff --git a/src/main/resources/fr/sae/terraria/maps/map_0.json b/src/main/resources/fr/sae/terraria/maps/map_0.json index cd875b6..ae68913 100644 --- a/src/main/resources/fr/sae/terraria/maps/map_0.json +++ b/src/main/resources/fr/sae/terraria/maps/map_0.json @@ -1,19 +1,103 @@ { - "0": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - "1": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - "2": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - "3": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - "4": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - "5": [0,0,0,0,0,0,4,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - "6": [0,0,0,0,0,4,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - "7": [0,0,0,0,0,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - "8": [0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], - "9": [0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,4,5,0,0,0,0,0,0,0,0,0,0,0,0,0], - "10": [3,5,0,0,0,0,0,0,0,0,0,0,0,0,4,2,2,5,0,0,0,0,0,0,0,0,0,0,0,0], - "11": [2,2,3,5,0,0,0,0,0,0,4,3,3,3,2,1,1,2,3,3,5,0,0,0,0,0,0,0,0,0], - "12": [1,1,2,2,3,3,3,3,3,3,2,2,2,2,1,1,1,1,2,2,2,3,3,3,5,0,4,3,3,3], - "13": [1,1,1,1,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,3,2,2,2,2], - "14": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1], - "15": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], - "16": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] + "0": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "1": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "2": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "3": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "4": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "5": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "6": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "7": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "8": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "9": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "10": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "11": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "12": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "13": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "14": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "15": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "16": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "17": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "18": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "19": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "20": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "21": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "22": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "23": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "24": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "25": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,3,3,3,3,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "26": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,3,3,3,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "27": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "28": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "29": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "30": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "31": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "32": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "33": [0,0,0,0,0,0,4,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "34": [0,0,0,0,0,4,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "35": [0,0,0,0,0,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "36": [0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "37": [0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,4,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "38": [3,5,0,0,0,0,0,0,0,0,0,0,0,0,4,2,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "39": [2,2,3,5,0,0,0,0,0,0,4,3,3,3,2,1,1,2,3,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], + "40": [1,1,2,2,3,3,3,3,3,3,2,2,2,2,1,1,1,1,2,2,2,3,3,3,5,0,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3], + "41": [1,1,1,1,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2], + "42": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "43": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "44": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "45": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "46": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "47": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "48": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "49": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "50": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "51": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "52": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "53": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "54": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "55": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "56": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "57": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "58": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "59": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "60": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "61": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "62": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "63": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "64": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "65": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "66": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "67": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "68": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "69": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "70": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "71": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "72": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "73": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "74": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "75": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "76": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "77": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "78": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "79": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "80": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "81": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "82": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "83": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "84": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "85": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "86": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "87": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "88": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "89": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "90": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "91": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "92": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "93": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "94": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "95": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "96": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "97": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "98": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "99": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], + "100": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] } \ No newline at end of file diff --git a/src/main/resources/fr/sae/terraria/sound/Bird_Sound.wav b/src/main/resources/fr/sae/terraria/sound/Bird_Sound.wav new file mode 100644 index 0000000..e3bbfdb Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sound/Bird_Sound.wav differ diff --git a/src/main/resources/fr/sae/terraria/sound/EarthMine.wav b/src/main/resources/fr/sae/terraria/sound/EarthMine.wav new file mode 100644 index 0000000..d5b2c74 Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sound/EarthMine.wav differ diff --git a/src/main/resources/fr/sae/terraria/sound/Rabbit_Spawn.wav b/src/main/resources/fr/sae/terraria/sound/Rabbit_Spawn.wav new file mode 100644 index 0000000..cca0ddb Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sound/Rabbit_Spawn.wav differ diff --git a/src/main/resources/fr/sae/terraria/sound/axchop.wav b/src/main/resources/fr/sae/terraria/sound/axchop.wav new file mode 100644 index 0000000..7b6b12e Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sound/axchop.wav differ diff --git a/src/main/resources/fr/sae/terraria/sound/brick1.wav b/src/main/resources/fr/sae/terraria/sound/brick1.wav new file mode 100644 index 0000000..63a6acd Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sound/brick1.wav differ diff --git a/src/main/resources/fr/sae/terraria/sound/brick2.wav b/src/main/resources/fr/sae/terraria/sound/brick2.wav new file mode 100644 index 0000000..48f2b9d Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sound/brick2.wav differ diff --git a/src/main/resources/fr/sae/terraria/sound/cut.wav b/src/main/resources/fr/sae/terraria/sound/cut.wav new file mode 100644 index 0000000..248095b Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sound/cut.wav differ diff --git a/src/main/resources/fr/sae/terraria/sound/daggerswipe.wav b/src/main/resources/fr/sae/terraria/sound/daggerswipe.wav new file mode 100644 index 0000000..0ae0a78 Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sound/daggerswipe.wav differ diff --git a/src/main/resources/fr/sae/terraria/sound/eat.wav b/src/main/resources/fr/sae/terraria/sound/eat.wav new file mode 100644 index 0000000..da25351 Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sound/eat.wav differ diff --git a/src/main/resources/fr/sae/terraria/sound/grassyStep.wav b/src/main/resources/fr/sae/terraria/sound/grassyStep.wav new file mode 100644 index 0000000..8b0015d Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sound/grassyStep.wav differ diff --git a/src/main/resources/fr/sae/terraria/sound/nightTime.wav b/src/main/resources/fr/sae/terraria/sound/nightTime.wav new file mode 100644 index 0000000..f3098ab Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sound/nightTime.wav differ diff --git a/src/main/resources/fr/sae/terraria/sound/toolSwap.wav b/src/main/resources/fr/sae/terraria/sound/toolSwap.wav new file mode 100644 index 0000000..1d34652 Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sound/toolSwap.wav differ diff --git a/src/main/resources/fr/sae/terraria/sprites/slimes/green_slime.png b/src/main/resources/fr/sae/terraria/sprites/slimes/green_slime.png new file mode 100644 index 0000000..465e86b Binary files /dev/null and b/src/main/resources/fr/sae/terraria/sprites/slimes/green_slime.png differ diff --git a/src/main/resources/fr/sae/terraria/tiles/torch.png b/src/main/resources/fr/sae/terraria/tiles/torch.png index b70b372..3f257de 100644 Binary files a/src/main/resources/fr/sae/terraria/tiles/torch.png and b/src/main/resources/fr/sae/terraria/tiles/torch.png differ diff --git a/src/main/resources/fr/sae/terraria/vue/game.css b/src/main/resources/fr/sae/terraria/vue/game.css index c81dcde..062bec5 100644 --- a/src/main/resources/fr/sae/terraria/vue/game.css +++ b/src/main/resources/fr/sae/terraria/vue/game.css @@ -19,4 +19,9 @@ #textInventoryBar { -fx-text-fill: white; +} + +#filter +{ + /*-fx-background-color: #0d0d38;*/ } \ No newline at end of file diff --git a/src/main/resources/fr/sae/terraria/vue/game.fxml b/src/main/resources/fr/sae/terraria/vue/game.fxml index d2279b7..7c4c3df 100644 --- a/src/main/resources/fr/sae/terraria/vue/game.fxml +++ b/src/main/resources/fr/sae/terraria/vue/game.fxml @@ -11,31 +11,34 @@ prefHeight="720" prefWidth="1280" xmlns="http://javafx.com/javafx/11" xmlns:fx="http://javafx.com/fxml/1"> - - - + + + - - - + + - - - + text="Groupe: BOUCHE Antoine, CHRZASZCZ Naulan, NARCISO Tiago"/> + + -
- - - +
+ + + + + + + - - -
+
+
diff --git a/src/main/resources/fr/sae/terraria/vue/menu.css b/src/main/resources/fr/sae/terraria/vue/menu.css new file mode 100644 index 0000000..36a5fe6 --- /dev/null +++ b/src/main/resources/fr/sae/terraria/vue/menu.css @@ -0,0 +1,27 @@ +#textArea +{ + -fx-background-color: black; + -fx-font-family: Impact; + -fx-alignment: center; +} + +#text +{ + -fx-fill: white; + -fx-font-size: 23px; +} + +#textInventoryBar +{ + -fx-text-fill: white; +} + +#notAvailable +{ + -fx-background-color: #ff7b7b; +} + +#available +{ + -fx-background-color: #91f086; +} diff --git a/src/main/resources/fr/sae/terraria/vue/menu.fxml b/src/main/resources/fr/sae/terraria/vue/menu.fxml new file mode 100644 index 0000000..0ed6d7f --- /dev/null +++ b/src/main/resources/fr/sae/terraria/vue/menu.fxml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + +
+ +
+
+
+
+