merge gitlab to github

This commit is contained in:
nessar committed 2023-03-25 04:17:56 +01:00
1 parent df9e0192d7
commit 735cd185b1
41 files changed
+719 -413

No files matched your search

@@ -4,30 +4,30 @@ import fr.ubx.poo.ubomb.launcher.Entity;
public class Grid {
private final int width;
private final int height;
private final Entity[][] grid;
private final int width;
private final int height;
private final Entity[][] grid;
public Grid(int width, int height) {
this.width = width;
this.height = height;
this.grid = new Entity[height][width];
}
public Grid(int width, int height) {
this.width = width;
this.height = height;
this.grid = new Entity[height][width];
}
public int getWidth() {
return width;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getHeight() {
return height;
}
public Entity get(int i, int j) {
return grid[j][i];
}
public Entity get(int i, int j) {
return grid[j][i];
}
public void set(int i, int j, Entity entity) {
grid[j][i] = entity;
}
public void set(int i, int j, Entity entity) {
grid[j][i] = entity;
}
}
@@ -1,9 +1,9 @@
package fr.ubx.poo.ubomb.editor.model;
public interface GridRepo {
Grid load(String string);
Grid load(String string);
String export(Grid grid);
String export(Grid grid);
Grid create(int height, int width);
Grid create(int height, int width);
}
@@ -55,17 +55,16 @@ public class GridRepoStringRLE implements GridRepo, GridRepoIO {
StringBuilder s = new StringBuilder();
int cpt = 0;
char last = 0;
char actual = 0;
char actual;
for (int j = 0; j < grid.getHeight(); j++) {
for (int i = 0; i < grid.getWidth(); i++) {
actual = grid.get(i, j).getCode();
if (cpt == 9 || last != actual) {
if (cpt != 0)
if (cpt < 3)
for (int tmp = cpt; tmp > 0; tmp--)
s.append(last);
s.append(String.valueOf(last).repeat(Math.max(0, cpt)));
else
s.append(last + String.valueOf(cpt));
s.append(last).append(cpt);
cpt = 1;
last = actual;
} else
@@ -73,11 +72,10 @@ public class GridRepoStringRLE implements GridRepo, GridRepoIO {
}
if (cpt != 0)
if (cpt < 3) {
for (int tmp = cpt; tmp > 0; tmp--)
s.append(last);
s.append(String.valueOf(last).repeat(Math.max(0, cpt)));
s.append(EOL);
} else
s.append(last + String.valueOf(cpt) + EOL);
s.append(last).append(cpt).append(EOL);
cpt = 0;
last = 0;
}
@@ -101,6 +99,6 @@ public class GridRepoStringRLE implements GridRepo, GridRepoIO {
}
@Override
public void export(Properties p, Writer out) throws IOException {
public void export(Properties p, Writer out) {
}
}
@@ -3,67 +3,61 @@ package fr.ubx.poo.ubomb.editor.model;
import fr.ubx.poo.ubomb.view.ImageResource;
import fr.ubx.poo.ubomb.editor.view.PickerView;
import fr.ubx.poo.ubomb.editor.view.Tile;
import fr.ubx.poo.ubomb.game.Position;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.layout.BorderPane;
public class GridView extends BorderPane {
private final Grid grid;
private final PickerView pickerView;
private final Grid grid;
private final PickerView pickerView;
public GridView(Grid grid, PickerView pickerView) {
this.grid = grid;
this.pickerView = pickerView;
setPrefSize(grid.getWidth() * ImageResource.SIZE,
grid.getHeight() * ImageResource.SIZE);
for (int i = 0; i < this.grid.getWidth(); i++) {
for (int j = 0; j < this.grid.getHeight(); j++) {
createTile(i, j);
}
}
}
public GridView(Grid grid, PickerView pickerView) {
this.grid = grid;
this.pickerView = pickerView;
setPrefSize(grid.getWidth() * ImageResource.SIZE,
grid.getHeight() * ImageResource.SIZE);
for (int i = 0; i < this.grid.getWidth(); i++) {
for (int j = 0; j < this.grid.getHeight(); j++) {
createTile(i, j);
}
}
}
private void createTile(int i, int j) {
int layoutX = i * ImageResource.SIZE;
int layoutY = j * ImageResource.SIZE;
Tile tile = new Tile(ImageResource.get(this.grid.get(i, j)), layoutX,
layoutY);
getChildren().add(tile);
tile.setOnMouseClicked(e -> update(tile, i, j));
tile.setOnMouseEntered(e -> {
if (e.isShiftDown()) {
update(tile, i, j);
}
});
ColorAdjust colorAdjust = new ColorAdjust();
colorAdjust.setBrightness(-0.2);
tile.setOnMouseEntered(e -> {
if (e.isShiftDown()) {
update(tile, i, j);
}
tile.setEffect(colorAdjust);
});
tile.setOnMouseExited(e -> {
tile.setEffect(null);
});
tile.setOnContextMenuRequested(e -> {
ContextMenu contextMenu = new ContextMenu();
MenuItem itemMark = new MenuItem("Get coordinates");
contextMenu.getItems().addAll(itemMark);
itemMark.setOnAction(e2 -> {
System.out.println(new Position(i, j));
});
contextMenu.show(tile, e.getScreenX(), e.getScreenY());
});
}
private void createTile(int i, int j) {
int layoutX = i * ImageResource.SIZE;
int layoutY = j * ImageResource.SIZE;
Tile tile = new Tile(ImageResource.get(this.grid.get(i, j)), layoutX,
layoutY);
getChildren().add(tile);
tile.setOnMouseClicked(e -> update(tile, i, j));
tile.setOnMouseEntered(e -> {
if (e.isShiftDown()) {
update(tile, i, j);
}
});
ColorAdjust colorAdjust = new ColorAdjust();
colorAdjust.setBrightness(-0.2);
tile.setOnMouseEntered(e -> {
if (e.isShiftDown()) {
update(tile, i, j);
}
tile.setEffect(colorAdjust);
});
tile.setOnMouseExited(e -> tile.setEffect(null));
tile.setOnContextMenuRequested(e -> {
ContextMenu contextMenu = new ContextMenu();
MenuItem itemMark = new MenuItem("Get coordinates");
contextMenu.getItems().addAll(itemMark);
contextMenu.show(tile, e.getScreenX(), e.getScreenY());
});
}
private void update(Tile tile, int i, int j) {
if (pickerView.getSelected() != null && pickerView.getSelected() != grid.get(i, j)) {
getChildren().remove(tile);
grid.set(i, j, pickerView.getSelected());
createTile(i, j);
}
}
private void update(Tile tile, int i, int j) {
if (pickerView.getSelected() != null && pickerView.getSelected() != grid.get(i, j)) {
getChildren().remove(tile);
grid.set(i, j, pickerView.getSelected());
createTile(i, j);
}
}
}
@@ -15,8 +15,6 @@ import fr.ubx.poo.ubomb.editor.model.GridView;
import fr.ubx.poo.ubomb.engine.GameEngine;
import fr.ubx.poo.ubomb.game.Game;
import fr.ubx.poo.ubomb.launcher.GameLauncher;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
@@ -25,7 +23,6 @@ import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.FileChooser.ExtensionFilter;
public class EditorView extends BorderPane {
private final Stage stage;
@@ -70,7 +67,7 @@ public class EditorView extends BorderPane {
MenuItem loadItemF = new MenuItem("Import from file");
MenuItem addToProperties = new MenuItem("Add grid to properties file");
MenuItem setPlayerLives = new MenuItem("Set player lives");
MenuItem setbombBagCapacity = new MenuItem("Set bomb Bag Capacity");
MenuItem setBombBagCapacity = new MenuItem("Set bomb Bag Capacity");
MenuItem setMonsterVelo = new MenuItem("Set monster velocity");
MenuItem setPlayerInvin = new MenuItem("Set Player invincibility");
MenuItem setMonsterInvin = new MenuItem("Set Monster invincibility");
@@ -84,7 +81,7 @@ public class EditorView extends BorderPane {
exitItem.setAccelerator(KeyCombination.keyCombination("Ctrl+Q"));
fileMenu.getItems().addAll(newItem, new SeparatorMenuItem(), loadItemS, loadItemSZ, loadItemF,
new SeparatorMenuItem(), addToProperties, setPlayerLives, setbombBagCapacity, setMonsterVelo,
new SeparatorMenuItem(), addToProperties, setPlayerLives, setBombBagCapacity, setMonsterVelo,
setPlayerInvin, setMonsterInvin, setPlayerSpawn, playProp, deleteLastLevel, exportItemF,
new SeparatorMenuItem(), exportItemSZ, exportItemS, new SeparatorMenuItem(), exitItem);
menuBar.getMenus().add(fileMenu);
@@ -100,8 +97,7 @@ public class EditorView extends BorderPane {
int y = Integer.parseInt(parts[1]);
this.grid = gridRepoString.create(x, y);
updateGrid(grid);
} catch (NumberFormatException numberFormatException) {
return;
} catch (NumberFormatException ignored) {
}
});
@@ -129,7 +125,7 @@ public class EditorView extends BorderPane {
this.pro.setProperty("monsterInvisibilityTime", String.valueOf(value));
});
setbombBagCapacity.setOnAction(e -> {
setBombBagCapacity.setOnAction(e -> {
Form form = new Form(stage, "Bomb bad capacity:");
int value = Integer.parseInt(form.getText());
this.pro.setProperty("bombBagCapacity", String.valueOf(value));
@@ -144,8 +140,7 @@ public class EditorView extends BorderPane {
Integer.parseInt(parts[0]);
Integer.parseInt(parts[1]);
pro.setProperty("player", form.getText().replaceAll("\\s+", ""));
} catch (NumberFormatException exep) {
return;
} catch (NumberFormatException ignored) {
}
});
@@ -177,14 +172,12 @@ public class EditorView extends BorderPane {
playProp.setOnAction(e -> {
File file = new File("tmp.properties");
if (file != null) {
writeToFile(file);
Stage stagePlay = new Stage();
Game game = GameLauncher.load(file.getPath());
file.delete();
GameEngine engine = new GameEngine(game, stagePlay);
engine.start();
}
writeToFile(file);
Stage stagePlay = new Stage();
Game game = GameLauncher.load(file.getPath());
file.delete();
GameEngine engine = new GameEngine(game, stagePlay);
engine.start();
});
// Export to file
@@ -204,9 +197,7 @@ public class EditorView extends BorderPane {
});
// Export as String
exportItemS.setOnAction(e -> {
exportDialog(gridRepoString.export(grid));
});
exportItemS.setOnAction(e -> exportDialog(gridRepoString.export(grid)));
// Load from compressed String
loadItemSZ.setOnAction(e -> {
@@ -216,9 +207,7 @@ public class EditorView extends BorderPane {
});
// Export as compressed String
exportItemSZ.setOnAction(e -> {
exportDialog(gridRepoStringRLE.export(grid));
});
exportItemSZ.setOnAction(e -> exportDialog(gridRepoStringRLE.export(grid)));
// Exit
exitItem.setOnAction(e -> System.exit(0));
@@ -9,33 +9,33 @@ import javafx.stage.Modality;
import javafx.stage.Stage;
public class Form {
private final TextField gridString;
private final TextField gridString;
public Form(Stage stage, String title) {
GridPane pane = new GridPane();
gridString = new TextField();
gridString.setPrefWidth(300);
pane.setPadding(new Insets(25));
pane.add(gridString, 0, 0);
public Form(Stage stage, String title) {
GridPane pane = new GridPane();
gridString = new TextField();
gridString.setPrefWidth(300);
pane.setPadding(new Insets(25));
pane.add(gridString, 0, 0);
Stage dialog = new Stage();
Scene scene = new Scene(pane);
dialog.setTitle(title);
dialog.setScene(scene);
dialog.initOwner(stage);
dialog.initModality(Modality.APPLICATION_MODAL);
Stage dialog = new Stage();
Scene scene = new Scene(pane);
dialog.setTitle(title);
dialog.setScene(scene);
dialog.initOwner(stage);
dialog.initModality(Modality.APPLICATION_MODAL);
gridString.setOnKeyPressed(e -> {
if (e.getCode().equals(KeyCode.ENTER)) {
dialog.close();
}
});
gridString.setOnKeyPressed(e -> {
if (e.getCode().equals(KeyCode.ENTER)) {
dialog.close();
}
});
dialog.showAndWait();
dialog.showAndWait();
}
}
public String getText() {
return gridString.getText();
}
public String getText() {
return gridString.getText();
}
}
@@ -10,24 +10,24 @@ import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
public class PickerView extends GridPane {
private final ToggleGroup group = new ToggleGroup();
private final ToggleGroup group = new ToggleGroup();
public PickerView() {
this.setPadding(new Insets(15));
int rows = 0, cols = 0;
for (Entity e : Entity.values()) {
ToggleButton btn = new ToggleButton();
btn.setToggleGroup(group);
btn.setUserData(e);
btn.setGraphic(new ImageView(ImageResource.get(e)));
this.add(btn, cols++ % 2, rows++ / 2);
}
}
public PickerView() {
this.setPadding(new Insets(15));
int rows = 0, cols = 0;
for (Entity e : Entity.values()) {
ToggleButton btn = new ToggleButton();
btn.setToggleGroup(group);
btn.setUserData(e);
btn.setGraphic(new ImageView(ImageResource.get(e)));
this.add(btn, cols++ % 2, rows++ / 2);
}
}
public Entity getSelected() {
Toggle toggle = group.getSelectedToggle();
if (toggle == null)
return null;
return (Entity) toggle.getUserData();
}
public Entity getSelected() {
Toggle toggle = group.getSelectedToggle();
if (toggle == null)
return null;
return (Entity) toggle.getUserData();
}
}
@@ -5,13 +5,13 @@ import javafx.scene.image.ImageView;
public class Tile extends ImageView {
public Tile(Image image) {
super(image);
}
public Tile(Image image) {
super(image);
}
public Tile(Image image, int x, int y) {
this(image);
this.setLayoutX(x);
this.setLayoutY(y);
}
public Tile(Image image, int x, int y) {
this(image);
this.setLayoutX(x);
this.setLayoutY(y);
}
}
@@ -11,14 +11,17 @@ import java.util.Set;
import fr.ubx.poo.ubomb.game.Direction;
import fr.ubx.poo.ubomb.game.Game;
import fr.ubx.poo.ubomb.game.NonStaticObject;
import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.go.character.Monster;
import fr.ubx.poo.ubomb.go.character.Player;
import fr.ubx.poo.ubomb.go.decor.Bomb;
import fr.ubx.poo.ubomb.go.decor.Box;
import fr.ubx.poo.ubomb.go.decor.Decor;
import fr.ubx.poo.ubomb.view.ImageResource;
import fr.ubx.poo.ubomb.view.sprite.Sprite;
import fr.ubx.poo.ubomb.view.sprite.SpriteFactory;
import fr.ubx.poo.ubomb.view.sprite.SpriteMonster;
import fr.ubx.poo.ubomb.view.sprite.SpritePlayer;
import fr.ubx.poo.ubomb.view.sprite.SpriteChara;
import javafx.animation.AnimationTimer;
import javafx.animation.TranslateTransition;
import javafx.application.Platform;
@@ -64,11 +67,11 @@ public final class GameEngine {
decor.setModified(true);
}
sprites.add(new SpritePlayer(layer, player));
sprites.add(new SpriteChara(layer, player));
// create monsters sprites
for (var monster : game.getMonsters().getObjects(game.getLevel())) {
sprites.add(new SpriteMonster(layer, monster));
sprites.add(new SpriteChara(layer, monster));
monster.setModified(true);
}
@@ -78,6 +81,12 @@ public final class GameEngine {
boxes.setModified(true);
}
// create bombs sprites
for (var bombs : game.getBombs().getObjects(game.getLevel())) {
sprites.add(SpriteFactory.create(layer, bombs));
bombs.setModified(true);
}
}
private void initGroup() {
@@ -115,12 +124,11 @@ public final class GameEngine {
gameLoop = new AnimationTimer() {
public void handle(long now) {
// Check keyboard actions
processInput(now);
processInput();
// Do actions
update(now);
createNewBombs(now);
checkCollision(now);
checkCollision();
checkExplosions();
// Graphic update
@@ -131,8 +139,69 @@ public final class GameEngine {
};
}
private int explodeThingsOnExplosion(Position pos, int sizeExplosion, Direction dir, int level) {
NonStaticObject<Box> boxes = this.game.getBoxes();
NonStaticObject<Monster> monsters = this.game.getMonsters();
NonStaticObject<Bomb> bombs = this.game.getBombs();
boolean stopped = false;
for (int i = 0; i <= sizeExplosion; i++) {
Decor decor = this.game.grid(level).get(pos);
int indexBox = boxes.isThereObject(pos, level);
int indexMonster = monsters.isThereObject(pos, level);
int indexbomb = bombs.isThereObject(pos, level);
if (this.game.getLevel() == level && player.getPosition().equals(pos)) {
if (!player.isInvincible()) {
player.addLives(-1);
player.getInvincibilityTimer().start();
}
}
if (indexMonster != -1) {
Monster monster = monsters.getObjects(level).get(indexMonster);
if (!monster.isInvincible()) {
monster.addLives(-1);
monster.getInvincibilityTimer().start();
}
}
if (indexbomb != -1) {
bombs.getObjects(level).get(indexbomb).explode();
}
if (decor != null && !decor.isDeleted()) {
decor.explode();
stopped = true;
}
if (indexBox != -1) {
boxes.getObjects(level).get(indexBox).explode();
stopped = true;
}
if (stopped)
return i;
pos = dir.nextPosition(pos);
}
return sizeExplosion;
}
private void checkExplosions() {
// Check explosions of bombs
for (int level = 0; level <= this.game.getLevels(); level++) {
List<Bomb> bombs = this.game.getBombs().getObjects(level);
for (Bomb bomb : bombs) {
if (bomb.isExploded()) {
Position src = bomb.getPosition();
for (Direction direction : Direction.values()) {
int exploSize = explodeThingsOnExplosion(bomb.getPosition(),
bomb.getRangeExplosion(),
direction, level);
Position dst = new Position(bomb.getPosition());
for (int j = 0; j < exploSize; j++) {
dst = direction.nextPosition(dst);
}
if (this.game.getLevel() == level)
animateExplosion(src, dst);
}
bomb.remove();
player.addAvailableBombs(1);
}
}
}
}
private void animateExplosion(Position src, Position dst) {
@@ -147,12 +216,21 @@ public final class GameEngine {
tt.play();
}
private void createNewBombs(long now) {
// Create a new Bomb is needed
private void createNewBombs() {
Position playerPos = this.player.getPosition();
int level = this.game.getLevel();
if (this.player.getAvailableBombs() > 0) {
if (this.game.getBombs().isThereObject(playerPos, level) == -1) {
Bomb newBomb = new Bomb(playerPos, this.player.getBombRange());
this.game.getBombs().add(newBomb, level);
sprites.add(SpriteFactory.create(layer, newBomb));
this.player.addAvailableBombs(-1);
}
}
}
private void checkCollision(long now) {
if (!this.player.isInvisible(now)) {
private void checkCollision() {
if (!this.player.isInvincible()) {
Position playerPosition = this.player.getPosition();
for (Monster m : this.game.getMonsters().getObjects(this.game.getLevel())) {
if (m.getPosition().equals(playerPosition)) {
@@ -163,7 +241,7 @@ public final class GameEngine {
}
}
private void processInput(long now) {
private void processInput() {
if (input.isExit()) {
gameLoop.stop();
Platform.exit();
@@ -178,7 +256,8 @@ public final class GameEngine {
player.requestMove(Direction.UP);
} else if (input.isKey()) {
player.openDoor();
}
} else if (input.isBomb())
createNewBombs();
input.clear();
}
@@ -197,7 +276,7 @@ public final class GameEngine {
stage.show();
new AnimationTimer() {
public void handle(long now) {
processInput(now);
processInput();
}
}.start();
}
@@ -208,6 +287,9 @@ public final class GameEngine {
m.requestMove(m.getNextDirection());
m.update(now);
}
for (Bomb bomb : this.game.getBombs().getObjects()) {
bomb.update(now);
}
player.update(now);
// End Game
if (player.getLives() <= 0) {
@@ -20,19 +20,22 @@ public class StatusBar {
public static final int height = 55;
private final Game game;
private final DropShadow ds = new DropShadow();
private final HBox hBox = new HBox();
private final Text lives = new Text();
private final Text availableBombs = new Text();
private final Text bombRange = new Text();
private final Text keys = new Text();
private final HBox level = new HBox();
public StatusBar(Group root, int sceneWidth, int sceneHeight, Game game) {
// Status bar
this.game = game;
HBox level = new HBox();
level.getStyleClass().add("level");
level.getChildren().add(new ImageView(ImageResourceFactory.digit(game.getLevel() + 1).getImage()));
int gameLevel = 0;
if (game.getLevel() + 1 < 10)
gameLevel = game.getLevel() + 1;
level.getChildren().add(new ImageView(ImageResourceFactory.digit(gameLevel).getImage()));
ds.setRadius(5.0);
ds.setOffsetX(3.0);
@@ -48,6 +51,7 @@ public class StatusBar {
status.setSpacing(40.0);
status.getChildren().addAll(live, bombs, range, key);
HBox hBox = new HBox();
hBox.getChildren().addAll(level, status);
hBox.getStyleClass().add("statusBar");
hBox.relocate(0, sceneHeight);
@@ -55,10 +59,6 @@ public class StatusBar {
root.getChildren().add(hBox);
}
public void updateWidth(int width) {
this.hBox.setPrefSize(width, height);
}
private HBox statusGroup(Image kind, Text number) {
HBox group = new HBox();
ImageView img = new ImageView(kind);
@@ -2,9 +2,4 @@ package fr.ubx.poo.ubomb.game;
public record Configuration(Position playerPosition, int bombBagCapacity, int playerLives, long playerInvisibilityTime,
int monsterVelocity, long monsterInvisibilityTime) {
}
/*
if lives == 0 -> Lives = 5
if NbBombMax == 0 -> NbBombMax = 3
if availableBombs == 0 -> availableBombs = NbBombMax
*/
}
+13 -22
View File
@@ -1,9 +1,9 @@
package fr.ubx.poo.ubomb.game;
import fr.ubx.poo.ubomb.go.GameObject;
import fr.ubx.poo.ubomb.go.character.Chara;
import fr.ubx.poo.ubomb.go.character.Monster;
import fr.ubx.poo.ubomb.go.character.Player;
import fr.ubx.poo.ubomb.go.decor.Bomb;
import fr.ubx.poo.ubomb.go.decor.Box;
import fr.ubx.poo.ubomb.go.decor.Decor;
import fr.ubx.poo.ubomb.go.decor.doors.DoorNext;
@@ -11,9 +11,6 @@ import fr.ubx.poo.ubomb.go.decor.doors.DoorPrev;
import fr.ubx.poo.ubomb.graph.Graph;
import fr.ubx.poo.ubomb.launcher.MapException;
import java.util.LinkedList;
import java.util.List;
public class Game {
private final Configuration configuration;
@@ -21,11 +18,13 @@ public class Game {
private final Grid[] grid;
private final NonStaticObject<Monster> monsters;
private final NonStaticObject<Box> boxes;
private final NonStaticObject<Bomb> bombs;
private int level;
private final int levels;
public Game(Configuration configuration, Grid grid) {
this(configuration, grid, new NonStaticObject<Monster>(), new NonStaticObject<>());
this(configuration, grid, new NonStaticObject<>(), new NonStaticObject<>(), new NonStaticObject<>());
}
public Game(Configuration config, Grid[] grid) {
@@ -34,11 +33,13 @@ public class Game {
this.levels = grid.length - 1;
this.grid = grid;
player = new Player(this, configuration.playerPosition());
this.monsters = new NonStaticObject<Monster>();
this.boxes = new NonStaticObject<Box>();
this.monsters = new NonStaticObject<>();
this.boxes = new NonStaticObject<>();
this.bombs = new NonStaticObject<>();
}
public Game(Configuration config, Grid gridToAdd, NonStaticObject<Monster> monsters, NonStaticObject<Box> boxes) {
public Game(Configuration config, Grid gridToAdd, NonStaticObject<Monster> monsters, NonStaticObject<Box> boxes,
NonStaticObject<Bomb> bombs) {
this.configuration = config;
this.grid = new Grid[1];
this.grid[0] = gridToAdd;
@@ -47,6 +48,7 @@ public class Game {
player = new Player(this, configuration.playerPosition());
this.monsters = monsters;
this.boxes = boxes;
this.bombs = bombs;
}
public Configuration configuration() {
@@ -57,26 +59,14 @@ public class Game {
return monsters;
}
public List<Monster> getThisLevelMonsters() {
return monsters.getObjects(this.level);
public NonStaticObject<Bomb> getBombs() {
return bombs;
}
public NonStaticObject<Box> getBoxes() {
return this.boxes;
}
public List<Box> getThisLevelBoxes() {
return this.boxes.getObjects(this.level);
}
// Returns the player, monsters and bomb at a given position
public List<GameObject> getGameObjects(Position position) {
List<GameObject> gos = new LinkedList<>();
if (player().getPosition().equals(position))
gos.add(player);
return gos;
}
public Grid grid() {
return this.grid[this.level];
}
@@ -96,6 +86,7 @@ public class Game {
public void addLevel(int delta) {
this.level += delta;
this.player.setPosition(new Position(this.getLevelDoor(delta > 0)));
this.player.setMovedFrom(null);
}
public int getLevels() {
@@ -15,19 +15,16 @@ public class Level implements Grid {
private final int height;
private final MapLevel entities;
private final Map<Position, Decor> elements = new HashMap<>();
public Level(MapLevel entities) {
this.entities = entities;
this.width = this.entities.width();
this.height = this.entities.height();
this.width = entities.width();
this.height = entities.height();
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++) {
Position position = new Position(i, j);
Entity entity = this.entities.get(i, j);
Entity entity = entities.get(i, j);
if (entity == null)
continue;
switch (entity) {
@@ -12,25 +12,27 @@ public class NonStaticObject<T extends GameObject> {
private final Map<Integer, List<T>> objectsByLevel = new LinkedHashMap<>();
public int isThereObject(Position pos, int level) {
if (!this.objectsByLevel.containsKey(Integer.valueOf(level)))
if (!this.objectsByLevel.containsKey(level))
return -1;
for (int i = 0; i < this.objectsByLevel.get(Integer.valueOf(level)).size(); i++) {
if (this.objectsByLevel.get(Integer.valueOf(level)).get(i).getPosition().equals(pos))
for (int i = 0; i < this.getObjects(level).size(); i++) {
if (this.getObjects(level).get(i).getPosition().equals(pos))
return i;
}
return -1;
}
public void add(T m, int level) {
if (!this.objectsByLevel.containsKey(Integer.valueOf(level)))
this.objectsByLevel.put(Integer.valueOf(level), new ArrayList<>());
this.objectsByLevel.get(Integer.valueOf(level)).add(m);
if (!this.objectsByLevel.containsKey(level))
this.objectsByLevel.put(level, new ArrayList<>());
this.objectsByLevel.get(level).add(m);
}
public List<T> getObjects(int level) {
if (!this.objectsByLevel.containsKey(Integer.valueOf(level)))
this.objectsByLevel.put(Integer.valueOf(level), new ArrayList<>());
return this.objectsByLevel.get(Integer.valueOf(level));
if (!this.objectsByLevel.containsKey(level))
this.objectsByLevel.put(level, new ArrayList<>());
List<T> ret = this.objectsByLevel.get(level);
ret.removeIf(GameObject::isDeleted);
return ret;
}
public List<T> getObjects() {
@@ -38,6 +40,7 @@ public class NonStaticObject<T extends GameObject> {
for (Entry<Integer, List<T>> t : this.objectsByLevel.entrySet()) {
ret.addAll(t.getValue());
}
ret.removeIf(GameObject::isDeleted);
return ret;
}
@@ -12,9 +12,9 @@ public interface Takeable {
default void takenBy(Player player) {
}
default void takenBy(Monster mosnter) {
default void takenBy(Monster monster) {
}
default void takenBy(Chara monster) {
default void takenBy(Chara character) {
}
}
@@ -7,13 +7,19 @@ import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.go.GameObject;
import fr.ubx.poo.ubomb.go.Movable;
import fr.ubx.poo.ubomb.go.TakeVisitor;
import fr.ubx.poo.ubomb.go.Takeable;
import fr.ubx.poo.ubomb.go.WalkVisitor;
public abstract class Chara extends GameObject implements Movable, WalkVisitor, TakeVisitor {
private final static long DURATION_BLINKING = 500;
private Direction direction;
private final Timer blinkingTimer = new Timer(DURATION_BLINKING);
private final Timer notBlinkingTimer = new Timer(DURATION_BLINKING);
private boolean blinking = false;
private boolean moveRequested = false;
private final Timer invincibilityTimer;
private int lives;
private Position movedFrom = null;
public Chara(Game game, Position position, int lives, Timer timer) {
super(game, position);
@@ -30,6 +36,10 @@ public abstract class Chara extends GameObject implements Movable, WalkVisitor,
moveRequested = true;
}
public boolean isInvincible() {
return this.getInvincibilityTimer().isRunning();
}
public Timer getInvincibilityTimer() {
return invincibilityTimer;
}
@@ -43,19 +53,53 @@ public abstract class Chara extends GameObject implements Movable, WalkVisitor,
lives += delta;
}
public Position getMovedFrom() {
return movedFrom;
}
public void setMovedFrom(Position movedFrom) {
this.movedFrom = movedFrom;
}
@Override
public void doMove(Direction direction) {
// This method is called only if the move is possible, do not check again
this.movedFrom = this.getPosition();
Position nextPos = direction.nextPosition(getPosition());
setPosition(nextPos);
GameObject next = game.grid().get(nextPos);
if (next instanceof Takeable taken)
taken.takenBy(this);
}
public Direction getDirection() {
return direction;
}
public boolean isBlinking() {
return blinking;
}
public void update(long now) {
if (lives <= 0)
this.remove();
this.invincibilityTimer.update(now);
this.blinkingTimer.update(now);
this.notBlinkingTimer.update(now);
if (invincibilityTimer.isRunning()) {
if (!this.blinking && !this.notBlinkingTimer.isRunning() && !this.blinkingTimer.isRunning()) {
this.blinkingTimer.start();
this.blinking = true;
this.setModified(true);
} else if (this.blinking && !this.blinkingTimer.isRunning() && !this.notBlinkingTimer.isRunning()) {
this.notBlinkingTimer.start();
this.blinking = false;
this.setModified(true);
}
} else if (blinking) {
this.blinking = false;
this.setModified(true);
}
if (moveRequested && canMove(direction)) {
doMove(direction);
}
@@ -6,8 +6,6 @@ import fr.ubx.poo.ubomb.engine.Timer;
import fr.ubx.poo.ubomb.game.Direction;
import fr.ubx.poo.ubomb.game.Game;
import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.go.GameObject;
import fr.ubx.poo.ubomb.go.Takeable;
import fr.ubx.poo.ubomb.go.decor.Decor;
import fr.ubx.poo.ubomb.go.decor.bonus.Princess;
import fr.ubx.poo.ubomb.go.decor.doors.DoorNext;
@@ -20,9 +18,9 @@ public class Monster extends Chara {
private final int level;
public Monster(Game game, Position position, int level) {
super(game, position, 1 + level / 2, new Timer(game.configuration().monsterInvisibilityTime()));
super(game, position, 1 + level, new Timer(game.configuration().monsterInvisibilityTime()));
this.level = level;
this.velocityTimer = new Timer(game.configuration().monsterVelocity() * 1000 / (level + 1));
this.velocityTimer = new Timer(game.configuration().monsterVelocity() * 1000L / (level + 1));
}
@Override
@@ -62,16 +60,6 @@ public class Monster extends Chara {
this.velocityTimer.start();
}
@Override
public void doMove(Direction direction) {
// This method is called only if the move is possible, do not check again
Position nextPos = direction.nextPosition(getPosition());
GameObject next = game.grid().get(nextPos);
setPosition(nextPos);
if (next instanceof Takeable taken)
taken.takenBy((Chara) this);
}
public Timer getVelocityTimer() {
return velocityTimer;
}
@@ -8,8 +8,6 @@ import fr.ubx.poo.ubomb.engine.Timer;
import fr.ubx.poo.ubomb.game.Direction;
import fr.ubx.poo.ubomb.game.Game;
import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.go.*;
import fr.ubx.poo.ubomb.go.decor.Box;
import fr.ubx.poo.ubomb.go.decor.Decor;
import fr.ubx.poo.ubomb.go.decor.bonus.*;
import fr.ubx.poo.ubomb.go.decor.doors.DoorNext;
@@ -32,13 +30,8 @@ public class Player extends Chara {
this.keys = 0;
}
public boolean isInvisible(long now) {
return this.getInvincibilityTimer().isRunning();
}
@Override
public void take(Key key) {
System.out.println("Take the key ...");
this.addKeys(1);
key.remove();
}
@@ -49,34 +42,29 @@ public class Player extends Chara {
}
public void take(BombNumberInc BNI) {
System.out.println("bomb number +");
this.addAvailableBombs(1);
this.addNbBombsMax(1);
BNI.remove();
}
public void take(BombNumberDec BND) {
System.out.println("bomb number -");
if (getNbBombsMax() > 1)
this.addNbBombsMax(-1);
BND.remove();
}
public void take(BombRangeInc BRI) {
System.out.println("bomb range +");
this.addBombRange(1);
BRI.remove();
}
public void take(BombRangeDec BRD) {
System.out.println("bomb number -");
if (getBombRange() > 1)
this.addBombRange(-1);
BRD.remove();
}
public void take(Heart heart) {
System.out.println("healing");
this.addLives(1);
heart.remove();
}
@@ -119,15 +107,11 @@ public class Player extends Chara {
@Override
public void doMove(Direction direction) {
// This method is called only if the move is possible, do not check again
Position nextPos = direction.nextPosition(getPosition());
GameObject next = game.grid().get(nextPos);
int indexBox = this.game.getBoxes().isThereObject(nextPos, this.game.getLevel());
if (indexBox != -1)
this.game.getBoxes().getObjects(this.game.getLevel()).get(indexBox).doMove(direction);
setPosition(nextPos);
if (next instanceof Takeable taken)
taken.takenBy((Chara) this);
super.doMove(direction);
}
@Override
@@ -159,14 +143,6 @@ public class Player extends Chara {
this.game.addLevel(-1);
}
public boolean canBoxMove(Box box, Direction direction) {
Position nextPos = direction.nextPosition(box.getPosition());
if (!game.grid().inside(nextPos))
return false;
Decor tmp = game.grid().get(nextPos);
return tmp != null && tmp.walkableBy(box);
}
public void openDoor() {
if (this.keys <= 0)
return;
@@ -0,0 +1,62 @@
package fr.ubx.poo.ubomb.go.decor;
import fr.ubx.poo.ubomb.engine.Timer;
import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.go.GameObject;
public class Bomb extends GameObject {
public final static long DURATIONBEFOREEXPLOTION = 4000;
public static final int NBIMAGE = 4;
private final Timer timerExplosion = new Timer(DURATIONBEFOREEXPLOTION);
private final int rangeExplosion;
private int lastImageId;
private boolean exploded = false;
public Bomb(Position position, int rangeExplosion) {
super(null, position);
this.rangeExplosion = rangeExplosion;
this.timerExplosion.start();
}
public Timer getTimerExplosion() {
return timerExplosion;
}
public int getRangeExplosion() {
return rangeExplosion;
}
@Override
public void explode() {
this.exploded = true;
}
public int getImageId() {
long durationEachImage = Bomb.DURATIONBEFOREEXPLOTION / NBIMAGE;
int imageId = NBIMAGE - 1;
for (; imageId > 0; imageId--) {
if (this.getTimerExplosion().remaining() > durationEachImage * imageId)
break;
}
return imageId;
}
public boolean isExploded() {
return exploded;
}
public void update(long now) {
this.timerExplosion.update(now);
if (!this.timerExplosion.isRunning()) {
this.exploded = true;
} else {
int imageId = this.getImageId();
if (imageId != this.lastImageId) {
this.lastImageId = imageId;
this.setModified(true);
}
}
}
}
@@ -15,6 +15,11 @@ public class Box extends Decor implements Movable {
super(game, position);
}
@Override
public void explode() {
this.remove();
}
@Override
public void doMove(Direction direction) {
Position nextPos = direction.nextPosition(getPosition());
@@ -25,10 +30,12 @@ public class Box extends Decor implements Movable {
public boolean canMove(Direction direction) {
Position nextPos = direction.nextPosition(getPosition());
int indexMonster = this.game.getMonsters().isThereObject(nextPos, this.game.getLevel());
int indexBomb = this.game.getBombs().isThereObject(nextPos, this.game.getLevel());
int indexBox = this.game.getBoxes().isThereObject(nextPos, this.game.getLevel());
Decor tmp = game.grid().get(nextPos);
boolean inside = game.grid().inside(nextPos);
return inside && indexMonster == -1 && indexBox == -1 && (tmp == null || tmp.walkableBy(this));
boolean nonStaticObject = indexBomb == -1 && indexMonster == -1 && indexBox == -1;
return inside && nonStaticObject && (tmp == null || tmp.walkableBy(this));
}
@Override
@@ -4,27 +4,27 @@ import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.go.character.Chara;
public class BombNumberDec extends Bonus {
public BombNumberDec(Position position) {
super(position);
}
public BombNumberDec(Position position) {
super(position);
}
@Override
public void explode() {
remove();
}
@Override
public void explode() {
remove();
}
@Override
public void takenBy(Chara c) {
c.take(this);
}
@Override
public void takenBy(Chara c) {
c.take(this);
}
@Override
public boolean walkableBy(Chara c) {
return c.walk(this);
}
@Override
public boolean walkableBy(Chara c) {
return c.walk(this);
}
@Override
public boolean equals(Object arg0) {
return arg0 instanceof BombNumberDec && super.equals(arg0);
}
@Override
public boolean equals(Object arg0) {
return arg0 instanceof BombNumberDec && super.equals(arg0);
}
}
@@ -4,27 +4,27 @@ import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.go.character.Chara;
public class BombNumberInc extends Bonus {
public BombNumberInc(Position position) {
super(position);
}
public BombNumberInc(Position position) {
super(position);
}
@Override
public void explode() {
remove();
}
@Override
public void explode() {
remove();
}
@Override
public void takenBy(Chara c) {
c.take(this);
}
@Override
public void takenBy(Chara c) {
c.take(this);
}
@Override
public boolean walkableBy(Chara c) {
return c.walk(this);
}
@Override
public boolean walkableBy(Chara c) {
return c.walk(this);
}
@Override
public boolean equals(Object arg0) {
return arg0 instanceof BombNumberInc && super.equals(arg0);
}
@Override
public boolean equals(Object arg0) {
return arg0 instanceof BombNumberInc && super.equals(arg0);
}
}
@@ -4,27 +4,27 @@ import fr.ubx.poo.ubomb.go.character.Chara;
import fr.ubx.poo.ubomb.game.Position;
public class BombRangeDec extends Bonus {
public BombRangeDec(Position position) {
super(position);
}
public BombRangeDec(Position position) {
super(position);
}
@Override
public void explode() {
remove();
}
@Override
public void explode() {
remove();
}
@Override
public void takenBy(Chara c) {
c.take(this);
}
@Override
public void takenBy(Chara c) {
c.take(this);
}
@Override
public boolean walkableBy(Chara c) {
return c.walk(this);
}
@Override
public boolean walkableBy(Chara c) {
return c.walk(this);
}
@Override
public boolean equals(Object arg0) {
return arg0 instanceof BombRangeDec && super.equals(arg0);
}
@Override
public boolean equals(Object arg0) {
return arg0 instanceof BombRangeDec && super.equals(arg0);
}
}
@@ -4,27 +4,27 @@ import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.go.character.Chara;
public class BombRangeInc extends Bonus {
public BombRangeInc(Position position) {
super(position);
}
public BombRangeInc(Position position) {
super(position);
}
@Override
public void explode() {
remove();
}
@Override
public void explode() {
remove();
}
@Override
public void takenBy(Chara c) {
c.take(this);
}
@Override
public void takenBy(Chara c) {
c.take(this);
}
@Override
public boolean walkableBy(Chara c) {
return c.walk(this);
}
@Override
public boolean walkableBy(Chara c) {
return c.walk(this);
}
@Override
public boolean equals(Object arg0) {
return arg0 instanceof BombRangeInc && super.equals(arg0);
}
@Override
public boolean equals(Object arg0) {
return arg0 instanceof BombRangeInc && super.equals(arg0);
}
}
@@ -4,27 +4,27 @@ import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.go.character.Chara;
public class Heart extends Bonus {
public Heart(Position position) {
super(position);
}
public Heart(Position position) {
super(position);
}
@Override
public void explode() {
remove();
}
@Override
public void explode() {
remove();
}
@Override
public void takenBy(Chara c) {
c.take(this);
}
@Override
public void takenBy(Chara c) {
c.take(this);
}
@Override
public boolean walkableBy(Chara c) {
return c.walk(this);
}
@Override
public boolean walkableBy(Chara c) {
return c.walk(this);
}
@Override
public boolean equals(Object arg0) {
return arg0 instanceof Heart && super.equals(arg0);
}
@Override
public boolean equals(Object arg0) {
return arg0 instanceof Heart && super.equals(arg0);
}
}
@@ -11,7 +11,6 @@ public class Princess extends Bonus {
@Override
public void explode() {
remove();
}
@Override
@@ -13,6 +13,10 @@ public abstract class Door extends Decor implements Takeable {
this.open = open;
}
@Override
public void explode() {
}
@Override
public boolean equals(Object arg0) {
return (arg0 instanceof Door d) && d.isOpen() == this.isOpen() && super.equals(arg0);
@@ -11,29 +11,11 @@ public class Graph<T> {
}
public void addNode(T data) {
this.nodes.add(new Node<T>(data));
this.nodes.add(new Node<>(data));
}
public Node<T> getNode(T data) {
return this.nodes.stream().filter(n -> n.getData().equals(data)).findFirst().get();
}
public Set<Node<T>> getNodes() {
return this.nodes;
}
public boolean isConnected() {
Set<Node<T>> marked = new HashSet<>();
Node<T> node = nodes.iterator().next();
neighbours(node, marked);
return marked.size() == nodes.size();
}
private void neighbours(Node<T> n, Set<Node<T>> marked) {
marked.add(n);
for (Node<T> node : n.getNeighbours()) {
if (!marked.contains(node))
neighbours(node, marked);
}
}
}
@@ -23,13 +23,12 @@ public class GameLauncher {
/**
* @param string string to decode
* @param onlyThisEntity if non null, will only return a {@code MapLevel} of
* @param onlyThisEntity if non-null, will only return a {@code MapLevel} of
* {@code onlyThisEntity}
* @param compression tells if {@code string} is compressed or not
* @return a {@code MapLevel} of all decoded entity of {@code string} according
* to {@code onlyThisEntity} and {@code compression}
*/
private static MapLevel stringDecode(String string, Entity onlyThisEntity, boolean compression) {
private static MapLevel stringDecode(String string, Entity onlyThisEntity) {
char EOL = 'x';
int firstEOL = string.indexOf(EOL);
String strWithoutEOL = string.replaceAll(String.valueOf(EOL), "");
@@ -80,12 +79,14 @@ public class GameLauncher {
Reader in = new FileReader(path);
Properties properties = new Properties();
properties.load(in);
boolean compression = Boolean.parseBoolean(properties.getProperty("compression", "false"));
int nbLevel = Integer.parseInt(properties.getProperty("levels", "1"));
String levels[] = new String[nbLevel];
String[] levels = new String[nbLevel];
for (int i = 1; i <= nbLevel; i++) {
levels[i - 1] = properties.getProperty("level" + i);
}
int playerLives = Integer.parseInt(properties.getProperty("playerLives", "3"));
int monsterVelocity = Integer.parseInt(properties.getProperty("monsterVelocity", "5"));
long playerInvisibilityTime = Long.parseLong(properties.getProperty("playerInvisibilityTime", "4000"));
@@ -93,6 +94,7 @@ public class GameLauncher {
int bombBagCapacity = Integer.parseInt(properties.getProperty("bombBagCapacity", "3"));
String[] parts = properties.getProperty("player").replaceAll("\\s+", "").split("x");
Position playerPos;
if (parts.length != 2)
return null;
try {
@@ -103,16 +105,16 @@ public class GameLauncher {
return null;
}
in.close();
Configuration config = new Configuration(playerPos, bombBagCapacity, playerLives, playerInvisibilityTime,
monsterVelocity, monsterInvisibilityTime);
// TODO read levelX with RLE and without
Grid[] grids = new Grid[nbLevel];
MapLevel[] monstersMap = new MapLevel[nbLevel];
MapLevel[] boxesMap = new MapLevel[nbLevel];
for (int i = 0; i < nbLevel; i++) {
grids[i] = new Level(stringDecode(levels[i], null, compression));
monstersMap[i] = stringDecode(levels[i], Entity.Monster, compression);
boxesMap[i] = stringDecode(levels[i], Entity.Box, compression);
grids[i] = new Level(stringDecode(levels[i], null));
monstersMap[i] = stringDecode(levels[i], Entity.Monster);
boxesMap[i] = stringDecode(levels[i], Entity.Box);
}
Game gameRet = new Game(config, grids);
NonStaticObject<Monster> monsters = gameRet.getMonsters();
@@ -10,20 +10,19 @@ import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.graph.Node;
public class PathFinder {
private PathNode start;
private Position target;
private ConcurrentSkipListSet<PathNode> notEvaluated;
private HashSet<PathNode> Evaluated;
private final Position target;
private final ConcurrentSkipListSet<PathNode> notEvaluated;
private final HashSet<PathNode> Evaluated;
public PathFinder(Node<Position> start, Position target) {
this.start = new PathNode(start, null, target);
PathNode start1 = new PathNode(start, null, target);
this.target = target;
this.notEvaluated = new ConcurrentSkipListSet<>(
Comparator.comparingDouble(PathNode::getDistanceStartTarget)
.thenComparingDouble(PathNode::getDistanceTarget).thenComparingInt(PathNode::getX)
.thenComparingInt(PathNode::getY));
this.Evaluated = new HashSet<>();
this.notEvaluated.add(this.start);
this.notEvaluated.add(start1);
}
private List<Position> getPathParent(PathNode p, List<Position> ret) {
@@ -51,22 +50,22 @@ public class PathFinder {
return getPathParent(current, new ArrayList<>());
for (Node<Position> neighbour : current.getNeighbours()) {
PathNode newone = new PathNode(neighbour, current, target);
PathNode newOne = new PathNode(neighbour, current, target);
boolean isAlreadyEvaluated = false;
for (PathNode eva : Evaluated) {
if (eva.equals(newone)) {
if (eva.equals(newOne)) {
isAlreadyEvaluated = true;
break;
}
}
if (isAlreadyEvaluated)
continue;
PathNode alreadyKnow = getElementNotEvaluated(newone);
PathNode alreadyKnow = getElementNotEvaluated(newOne);
if (alreadyKnow == null) {
notEvaluated.add(newone);
} else if (alreadyKnow.getDistanceStartTarget() > newone.getDistanceStartTarget()) {
notEvaluated.add(newOne);
} else if (alreadyKnow.getDistanceStartTarget() > newOne.getDistanceStartTarget()) {
notEvaluated.remove(alreadyKnow);
notEvaluated.add(newone);
notEvaluated.add(newOne);
}
}
}
@@ -4,7 +4,7 @@ import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.graph.Node;
public class PathNode extends Node<Position> {
private PathNode parent;
private final PathNode parent;
private double distanceStart;
private double distanceTarget;
private double distanceStartTarget;
@@ -14,8 +14,8 @@ public class PathNode extends Node<Position> {
this.parent = parent;
updateDistanceStart();
updateDistanceTarget(target);
for (Node<Position> neig : start.getNeighbours()) {
this.addEdge(neig);
for (Node<Position> neighbour : start.getNeighbours()) {
this.addEdge(neighbour);
}
}
@@ -23,10 +23,6 @@ public class PathNode extends Node<Position> {
this.distanceStartTarget = this.distanceStart + this.distanceTarget;
}
public double getDistanceStart() {
return distanceStart;
}
public int getX() {
return this.getData().x();
}
@@ -6,6 +6,7 @@ package fr.ubx.poo.ubomb.view.sprite;
import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.go.GameObject;
import javafx.animation.TranslateTransition;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
@@ -17,6 +18,7 @@ public class Sprite {
private final GameObject gameObject;
private ImageView imageView;
private Image image;
private double opacity = 1.0;
public Sprite(Pane layer, Image image, GameObject gameObject) {
this.layer = layer;
@@ -42,6 +44,10 @@ public class Sprite {
return getGameObject().getPosition();
}
public TranslateTransition animate(GameObject gameObj, ImageView img) {
return null;
}
public final void render() {
if (gameObject.isModified()) {
if (imageView != null) {
@@ -49,11 +55,20 @@ public class Sprite {
}
updateImage();
imageView = new ImageView(this.image);
imageView.setX((double) getPosition().x() * SIZE);
imageView.setY((double) getPosition().y() * SIZE);
imageView.setOpacity(this.opacity);
TranslateTransition tt = this.animate(gameObject, imageView);
if (tt == null) {
imageView.setX((double) getPosition().x() * SIZE);
imageView.setY((double) getPosition().y() * SIZE);
}
layer.getChildren().add(imageView);
gameObject.setModified(false);
}
}
public void setOpacity(double opacity) {
this.opacity = opacity;
}
public final void remove() {
@@ -0,0 +1,21 @@
package fr.ubx.poo.ubomb.view.sprite;
import fr.ubx.poo.ubomb.go.decor.Bomb;
import fr.ubx.poo.ubomb.view.ImageResourceFactory;
import javafx.scene.image.Image;
import javafx.scene.layout.Pane;
public class SpriteBomb extends Sprite {
public SpriteBomb(Pane layer, Bomb bomb) {
super(layer, null, bomb);
updateImage();
}
@Override
public void updateImage() {
Bomb bomb = (Bomb) this.getGameObject();
Image image = ImageResourceFactory.getBomb(bomb.getImageId()).getImage();
setImage(image);
}
}
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2020. Laurent Réveillère
*/
package fr.ubx.poo.ubomb.view.sprite;
import fr.ubx.poo.ubomb.game.Position;
import fr.ubx.poo.ubomb.go.GameObject;
import fr.ubx.poo.ubomb.go.character.Chara;
import fr.ubx.poo.ubomb.go.character.Monster;
import fr.ubx.poo.ubomb.go.character.Player;
import fr.ubx.poo.ubomb.view.ImageResourceFactory;
import javafx.animation.TranslateTransition;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.util.Duration;
public class SpriteChara extends Sprite {
public SpriteChara(Pane layer, Chara c) {
super(layer, null, c);
updateImage();
}
@Override
public void updateImage() {
Chara c = (Chara) getGameObject();
Image image = null;
if (c instanceof Player)
image = ImageResourceFactory.getPlayer(c.getDirection()).getImage();
if (c instanceof Monster)
image = ImageResourceFactory.getMonster(c.getDirection()).getImage();
if (c.isInvincible() && c.isBlinking()) {
this.setOpacity(0.3);
} else {
this.setOpacity(1.0);
}
setImage(image);
}
@Override
public TranslateTransition animate(GameObject gameObj, ImageView img) {
Chara c = (Chara) gameObj;
Position src = c.getMovedFrom();
if (src != null) {
img.setX(src.x() * SpriteChara.SIZE);
img.setY(src.y() * SpriteChara.SIZE);
TranslateTransition tt = new TranslateTransition(Duration.millis(200), img);
switch (c.getDirection()) {
case UP -> tt.setByY(-SpriteChara.SIZE);
case DOWN -> tt.setByY(SpriteChara.SIZE);
case RIGHT -> tt.setByX(SpriteChara.SIZE);
case LEFT -> tt.setByX(-SpriteChara.SIZE);
}
tt.play();
c.setMovedFrom(null);
return tt;
}
return null;
}
}
@@ -1,6 +1,5 @@
package fr.ubx.poo.ubomb.view.sprite;
import fr.ubx.poo.ubomb.go.GameObject;
import fr.ubx.poo.ubomb.go.decor.doors.Door;
import javafx.scene.image.Image;
import javafx.scene.layout.Pane;
@@ -10,7 +9,7 @@ import static fr.ubx.poo.ubomb.view.ImageResource.*;
public class SpriteDoor extends Sprite {
public SpriteDoor(Pane layer, Door door) {
super(layer, null, (GameObject) door);
super(layer, null, door);
updateImage();
}
@@ -31,7 +31,7 @@ public final class SpriteFactory {
if (gameObject instanceof Princess)
return new Sprite(layer, PRINCESS.getImage(), gameObject);
if (gameObject instanceof Monster)
return new SpriteMonster(layer, (Monster) gameObject);
return new SpriteChara(layer, (Monster) gameObject);
if (gameObject instanceof BombRangeInc)
return new Sprite(layer, BONUS_BOMB_RANGE_INC.getImage(), gameObject);
if (gameObject instanceof BombRangeDec)
@@ -46,6 +46,8 @@ public final class SpriteFactory {
return new SpriteDoor(layer, dn);
if (gameObject instanceof DoorNext || gameObject instanceof DoorPrev)
return new SpriteDoor(layer, (Door) gameObject);
if (gameObject instanceof Bomb)
return new SpriteBomb(layer, (Bomb) gameObject);
throw new RuntimeException("Unsupported sprite for decor " + gameObject);
}
}
+18
View File
@@ -0,0 +1,18 @@
compression=true
levels=4
level1=_SM_T3++xBS__T3__x_9xS6B3xT>_3B3_xT5B3_xT_8xT_M_M_M__xT__M_M_3xTNT_4H_xT9x
level2=_9_9__x_T9T9_x_9_3T_7xT9TT_T_T6xT9TT_T_7xTT_9_T7_xTT_TT<T-T_T3_7xTT_TT>T-T_T_3T6xTT_T4+TMT_TT_3TMMxTT_TT+-_T_T_4TBT__xTT_T6_T6_4xTT_T6nTT_3T_T3xTTVTTKB3_TT_T_T_4xT9_4T_T4_xT9T5_6x
level3=_M_M_M_MSM_MS3T5xMSM_M_MSM_M_MSST5x_MSM_MSM_MSM_MST5xM_MSM_M_MSM_M__T5x_MSMSM_MSM_M_M_6xMSM_MSMSM_M_M_3>_H_x_S_M_MS5M_M_3K__xMSMSM_M_M_MSM_3>_H_x_S_MSM_M_M_MSM_6xMSM_MS_7S_T5x_S_MSS__H3__SST5xM_M_SS_6nSST5xS7__V__S3T5x
level4=__H4__x_3HH_3x_V_HH_W_x_3HH_3x__H4__x
player=0x0
playerDirection=down
playerMoveTime=150
playerLives=5
playerInvincibilityTime=2000
bombBagCapacity=1
bombRange=1
bombBurningTime=4000
bmobExplosionTime=200
monsterMoveTime=300
monsterInvincibilityTime=1000
monsterVelocity=5
+21
View File
@@ -0,0 +1,21 @@
compression=false
levels=7
level1=___T_____________x___T____M_M_M__K_x_W_T_____M_M_____x___T____M_M_M_SSSx___TTT___M_M__SSSxTTTTTTT__________xTTTTTTTTTTT____n_xTTTTTTTTTTTT_____xTTTTTTTTTTTTTTTTTx
level2=TTTTTTTTTTTTTTTTTTxT_________T_____TTxT_n_______T_H_H_TTxT___M_M___T__W__TTxT__M_M_M__T_H_H_TTxT_M_____M_T_____TTxTT_M_M_M_TTTTTTTTTxT_M_____M_TT___TTTxT__M_M_M__TT_K_TTTxT___M_M__________TxT__B_______+>+>+_TxTT_______________TxTTT__V__TTTTTTTTTTxTTTT___TTTTTTTTTTTxTTTTTTTTTTTTTTTTTTx
level3=____TTTTT_B_B___x_V__T___TB_B__N_x____T_H_T_B_B___xBBB_T___TB_B_B_Bx____TTTTT_B_B_B_x_____TTT___B_B_Bx____M_T_M___B_B_x__M___M_____SSSSx____M___M___S___x__M_T_M_____S_W_x___TTT______S___x
level4=_____STT______x__WK_STT__K___x_____STT______xSSSSSSTT______xTTTTTTTT____M_x______TT__M__Mx_V__n_TT_M_M__x______TT__M__Mx___SSSS__M__M_x__SSSS__M__M__x_SSSS__M_M___MxBB_________M__xSSSSSSSS______x
level5=_______SSSx_N____SSSSx_____SSSSSx____SSSSSSx__H_SSSWSSx____SSSSSSx_____SSSSSx_V____SSSSx_______SSSx
level6=______________x_M_______V____x____M_______H_x_______M______x_M_M________M_x______M_M_____x____M__M__M___x_N_______M__M_x_______M______x_____M____M___x
level7=______x_V__W_x______x
player=5x1
playerDirection=down
playerMoveTime=150
playerLives=3
playerInvincibilityTime=2000
bombBagCapacity=1
bombRange=1
bombBurningTime=4000
bmobExplosionTime=200
monsterMoveTime=300
monsterInvincibilityTime=1000
monsterVelocity=5
+16
View File
@@ -0,0 +1,16 @@
compression=true
levels=2
level1=S5B3SB3S_3xS5BSBSBSBS_N_xS__B3SBSBSBS_3xS_3S3BSBSBS_3xS_3S3B3SB3SSxS_S9BS4x_9_7x_6M_M_M_M_3x_5M_M_M_M_M__x_6M_M_M_M_3xHBH__M_M_M_M_M__x_6M_M_M_M_3x_5M_M_M_M_M__x_6M_M_M_M_3x_9_7x
level2=_9_9_6x_T_3T_T4_3T_3T_3T_x__T_T__T_5T_T__T_3T_x_3T_3T3__T5_T5_x_3T_3T_4T_3T_T_3T_x_3T_3T_4T_3T_T_3T_x_3T_3T4_T_3T_T_3T_x_9_9_6x_9_9_6x__V_9_9W__x_9_9_6x
player=1x12
playerDirection=right
playerMoveTime=150
playerLives=3
playerInvincibilityTime=2000
bombBagCapacity=1
bombRange=1
bombBurningTime=4000
bmobExplosionTime=200
monsterMoveTime=300
monsterInvincibilityTime=1000
monsterVelocity=10
+10
View File
@@ -0,0 +1,10 @@
compression=true
levels=3
level1=_4B_9_x_T_9_4x_<__SBBS5_3x_T__SBBS_3S_3x_T__SH+S_3S_>_x_4S4_3S_3x_9__S_3x_5N_9xMT_5T3_5x_TT_T__T__B_4x__T3BTTHB<S_+_x_5<HTTK_S_3x__B__BBS4T_3x_9_4T_x_9_5Tx
level2=_7T+_3x_n_5TT_T_x_3B5_4x_SSBBHBBT3_x_3BH3B_4xSS_BBHBB__TTx__MB5_4x_S8_3x__S_3MSV_T_xS_3S_7x
level3=_9_5x__TMMS_S_6x_6VMM>_4x_T_3S_S_3H__x_3T_6TT--x_6T_T5MxBTB__>__TT_4xBHBT-T__TMMWMMxBTB_5TT_4x_M_6<M_4x
playerLives=30
monsterVelocity=5
playerInvincibilityTime=4000
monsterInvincibilityTime=10000
player=0x0
+34
View File
@@ -0,0 +1,34 @@
compression=true
levels=20
level1=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_9_4x_9_4x_9_4x
level2=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level3=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level4=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level5=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level6=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level7=T4_9xTK_T_9xT__T__n_6xTT__T_8x__T_9_x_9_4x_9_4x_6V_6x_9_4x_9_4x
level8=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level9=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level10=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level11=_K_B4_TT_8x_3B4_TT_8xT3B4_TT_8xTTSB4_TT_4TT__xTTS5__B_3TT_3x_6T__B__TT_4x__n_3TT_B_T_4TTx_7T4_5T_x_9_6T__x__M_9_TT_3x_9_9x_9_9x_9V_8x_9_9x_9_9x
level12=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level13=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level14=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level15=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level16=_9_5x_9_5x__M_9__x_9_5x_9_5x_9_5x_9_5x_9_5x_9__N__x_9_5x_5V_8x_9_5x_9_5x
level17=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level18=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level19=_9_4x_9_4x_6N_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
level20=_9_4x_9_4x_6W_6x_9_4x_9_4x_9_4x_9_4x_6V_6x_9_4x_9_4x
player=6x7
playerDirection=up
playerMoveTime=150
playerLives=10
playerInvincibilityTime=800
bombBagCapacity=10
bombRange=5
bombBurningTime=4000
bmobExplosionTime=200
monsterMoveTime=100
monsterInvincibilityTime=10000
monsterVelocity=200