From 1d271afe2487eca64b7370dda2392a0a0ae7598e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20M=C3=A9ndez?= <45081533+FerMdez@users.noreply.github.com> Date: Thu, 17 Sep 2020 20:06:49 +0200 Subject: [PATCH] Space Invaders The classic game Space Invaders, without GUI. --- SpaceInvaders/src/tp/p2/Level.java | 79 ++++++ SpaceInvaders/src/tp/p2/Main.java | 71 +++++ .../Commands/BuySuperMissileCommand.java | 40 +++ .../tp/p2/controller/Commands/Command.java | 40 +++ .../controller/Commands/CommandGenerator.java | 63 +++++ .../p2/controller/Commands/ExitCommand.java | 33 +++ .../p2/controller/Commands/HelpCommand.java | 43 +++ .../p2/controller/Commands/ListCommand.java | 39 +++ .../Commands/ListPrintersCommand.java | 39 +++ .../p2/controller/Commands/LoadCommand.java | 99 +++++++ .../p2/controller/Commands/MoveCommand.java | 59 ++++ .../p2/controller/Commands/ResetCommand.java | 33 +++ .../p2/controller/Commands/SaveCommand.java | 63 +++++ .../controller/Commands/ShockwaveCommand.java | 39 +++ .../p2/controller/Commands/ShotCommand.java | 41 +++ .../controller/Commands/StringifyCommand.java | 47 ++++ .../Commands/SuperShootCommand.java | 41 +++ .../p2/controller/Commands/UpdateCommand.java | 31 ++ .../src/tp/p2/controller/Controller.java | 97 +++++++ .../Exceptions/CommandExecuteException.java | 21 ++ .../Exceptions/CommandParseException.java | 22 ++ .../Exceptions/FileContentsException.java | 24 ++ .../src/tp/p2/game/BoardPrinter.java | 76 +++++ .../src/tp/p2/game/FileContentsVerifier.java | 224 +++++++++++++++ SpaceInvaders/src/tp/p2/game/Game.java | 265 ++++++++++++++++++ .../src/tp/p2/game/GameObjectGenerator.java | 46 +++ .../src/tp/p2/game/GameObjects/AlienShip.java | 130 +++++++++ .../p2/game/GameObjects/BoardInitializer.java | 61 ++++ .../src/tp/p2/game/GameObjects/Bomb.java | 74 +++++ .../p2/game/GameObjects/DestroyerAlien.java | 86 ++++++ .../src/tp/p2/game/GameObjects/EnemyShip.java | 23 ++ .../tp/p2/game/GameObjects/GameObject.java | 73 +++++ .../game/GameObjects/Interfaces/IAttack.java | 16 ++ .../Interfaces/IExecuteRandomActions.java | 18 ++ .../Interfaces/IPlayerController.java | 20 ++ .../GameObjects/Lists/GameObjectBoard.java | 129 +++++++++ .../src/tp/p2/game/GameObjects/Ovni.java | 88 ++++++ .../tp/p2/game/GameObjects/RegularAlien.java | 115 ++++++++ .../src/tp/p2/game/GameObjects/Ship.java | 22 ++ .../src/tp/p2/game/GameObjects/Shockwave.java | 55 ++++ .../tp/p2/game/GameObjects/SuperMissile.java | 69 +++++ .../tp/p2/game/GameObjects/UCMMissile.java | 67 +++++ .../src/tp/p2/game/GameObjects/UCMShip.java | 186 ++++++++++++ .../src/tp/p2/game/GameObjects/Weapon.java | 36 +++ SpaceInvaders/src/tp/p2/game/GamePrinter.java | 11 + .../src/tp/p2/game/PrinterGenerator.java | 29 ++ .../src/tp/p2/game/PrinterTypes.java | 45 +++ SpaceInvaders/src/tp/p2/game/Stringifier.java | 34 +++ .../src/tp/p2/util/MyStringUtils.java | 24 ++ 49 files changed, 3086 insertions(+) create mode 100644 SpaceInvaders/src/tp/p2/Level.java create mode 100644 SpaceInvaders/src/tp/p2/Main.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/BuySuperMissileCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/Command.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/CommandGenerator.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/ExitCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/HelpCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/ListCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/ListPrintersCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/LoadCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/MoveCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/ResetCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/SaveCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/ShockwaveCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/ShotCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/StringifyCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/SuperShootCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Commands/UpdateCommand.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Controller.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Exceptions/CommandExecuteException.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Exceptions/CommandParseException.java create mode 100644 SpaceInvaders/src/tp/p2/controller/Exceptions/FileContentsException.java create mode 100644 SpaceInvaders/src/tp/p2/game/BoardPrinter.java create mode 100644 SpaceInvaders/src/tp/p2/game/FileContentsVerifier.java create mode 100644 SpaceInvaders/src/tp/p2/game/Game.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjectGenerator.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/AlienShip.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/BoardInitializer.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/Bomb.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/DestroyerAlien.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/EnemyShip.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/GameObject.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/Interfaces/IAttack.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/Interfaces/IExecuteRandomActions.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/Interfaces/IPlayerController.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/Lists/GameObjectBoard.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/Ovni.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/RegularAlien.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/Ship.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/Shockwave.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/SuperMissile.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/UCMMissile.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/UCMShip.java create mode 100644 SpaceInvaders/src/tp/p2/game/GameObjects/Weapon.java create mode 100644 SpaceInvaders/src/tp/p2/game/GamePrinter.java create mode 100644 SpaceInvaders/src/tp/p2/game/PrinterGenerator.java create mode 100644 SpaceInvaders/src/tp/p2/game/PrinterTypes.java create mode 100644 SpaceInvaders/src/tp/p2/game/Stringifier.java create mode 100644 SpaceInvaders/src/tp/p2/util/MyStringUtils.java diff --git a/SpaceInvaders/src/tp/p2/Level.java b/SpaceInvaders/src/tp/p2/Level.java new file mode 100644 index 0000000..3381872 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/Level.java @@ -0,0 +1,79 @@ +package tp.p2; + +/** + * @author Fernando Méndez Torrubiano; DNI: 02723009Q + * @clase TP1, GRUPO D. + * + */ +public enum Level { + EASY(4, 2, 0.2, 3, 0.5, 1), + HARD(8, 4, 0.3, 2, 0.2, 2), + INSANE(12, 4, 0.5, 1, 0.1, 3); + + private int numRegularAliens; + private int numDestroyerAliens; + private int numCyclesToMoveOneCell; + private double ovniFrequency; + private double shootFrequency; + private int numRowsOfRegularAliens; + private double turnExplodeFrequency = 0.05; // actualmente no depende del nivel + + private Level( + int numRegularAliens, + int numDestroyerAliens, + double shootFrequency, + int numCyclesToMoveOneCell, + double ovniFrequency, + int numRowsOfRegularAliens) + { + this.numRegularAliens = numRegularAliens; + this.numDestroyerAliens = numDestroyerAliens; + this.shootFrequency = shootFrequency; + this.numCyclesToMoveOneCell = numCyclesToMoveOneCell; + this.ovniFrequency = ovniFrequency; + this.numRowsOfRegularAliens = numRowsOfRegularAliens; + } + + + public int getNumRegularAliens() { + return numRegularAliens; + } + + public int getNumDestroyerAliens() { + return numDestroyerAliens; + } + + public double getShootFrequency() { + return shootFrequency; + } + + public int getNumCyclesToMoveOneCell() { + return numCyclesToMoveOneCell; + } + + public double getOvniFrequency() { + return ovniFrequency; + } + public int getNumRowsOfRegularAliens() { + return numRowsOfRegularAliens; + } + + public int getNumRegularAliensPerRow() { + return numRegularAliens / numRowsOfRegularAliens; + } + + public int getNumDestroyerAliensPerRow() { + return getNumDestroyerAliens(); + } + + public static Level parse(String cadenaEntrada) { + for (Level level : Level.values()) + if (level.name().equalsIgnoreCase(cadenaEntrada)) + return level; + return EASY; + } + + public double getTurnExplodeFrequency(){ + return turnExplodeFrequency; + } +} diff --git a/SpaceInvaders/src/tp/p2/Main.java b/SpaceInvaders/src/tp/p2/Main.java new file mode 100644 index 0000000..ec29cde --- /dev/null +++ b/SpaceInvaders/src/tp/p2/Main.java @@ -0,0 +1,71 @@ +/** + * @author Fernando M�ndez Torrubiano + * + */ +package tp.p2; + +import java.util.Random; +import java.util.Scanner; +import java.lang.NumberFormatException; +import tp.p2.Level; +import tp.p2.controller.Controller; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano; DNI: 02723009Q + * @clase TP1, GRUPO D. + * + */ + +public class Main { + + public static void main(String[] args) { + Game game; + Level level = null; + Scanner in = null; + int seed = 0; + Random rnd = null; + + //Selecci�n de nivel: + if(args.length >= 1) { + level = Level.parse(args[0]); + } + else { + level = Level.EASY; + } + + //Selecci�n de semilla: + if(args.length == 2) { + try { + seed = Integer.parseInt(args[1]); + } + catch (NumberFormatException ex){ + System.err.format(ex.getMessage() + " %n %n"); + } + finally { + rnd = new Random(seed); + } + } + else { + rnd = new Random(System.currentTimeMillis()); + } + + game = new Game(level, rnd); + Controller controlador = new Controller(game, in); + controlador.run(game); + } + +} + +/* +//Selecci�n de nivel: + if(args[0].contentEquals("EASY")) { + nivel = Level.EASY; + } else if(args[0].contentEquals("HARD")){ + nivel = Level.HARD; + } else if(args[0].contentEquals("INSANE")) { + nivel = Level.INSANE; + }else { + nivel = Level.EASY; + } +*/ \ No newline at end of file diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/BuySuperMissileCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/BuySuperMissileCommand.java new file mode 100644 index 0000000..8157b24 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/BuySuperMissileCommand.java @@ -0,0 +1,40 @@ +package tp.p2.controller.Commands; + +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class BuySuperMissileCommand extends Command { + + public BuySuperMissileCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + } + + @Override + public boolean execute(Game game) throws CommandExecuteException { + boolean exe = true; + + if(!game.buySuperMissile()) { + System.err.println("Error, you can't buy a Super Missile right now."); + exe = false; + } + + return exe; + } + + @Override + public Command parse(String[] commandWords) { + Command cmd = null; + + if(commandWords[0].equals("buy") || commandWords[0].equals("b")) { + cmd = this; + } + + return cmd; + } + +} diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/Command.java b/SpaceInvaders/src/tp/p2/controller/Commands/Command.java new file mode 100644 index 0000000..5820608 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/Command.java @@ -0,0 +1,40 @@ +package tp.p2.controller.Commands; + +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.controller.Exceptions.CommandParseException; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public abstract class Command { + //Atributos: + protected final String name; + protected final String shortcut; + private final String details; + private final String help; + protected static final String incorrectNumArgsMsg = "Incorrect number of arguments"; + protected static final String incorrectArgsMSg = "Incorrect argument format"; + + //Constructor: + public Command(String name, String shortcut, String details, String help) { + this.name = name; + this.shortcut = shortcut; + this.details = details; + this.help = help; + } + + //M�todos: + public abstract boolean execute(Game game) throws CommandExecuteException; + public abstract Command parse(String[] commandWords) throws CommandParseException; + + protected boolean matchCommandName(String name) { + return this.shortcut.equalsIgnoreCase(name) || this.name.equalsIgnoreCase(name); + } + + public String helpText() { + return this.details + ": " + this.help + "\n"; + } +} diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/CommandGenerator.java b/SpaceInvaders/src/tp/p2/controller/Commands/CommandGenerator.java new file mode 100644 index 0000000..ef5a5f4 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/CommandGenerator.java @@ -0,0 +1,63 @@ +package tp.p2.controller.Commands; + +import tp.p2.controller.Exceptions.CommandParseException; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class CommandGenerator { + //Atributos: + private static final int MAXCOMMANDS = 14; + private static Command[] avaliableCommands = { + new MoveCommand("move", "m", "Move <1|2>", "Moves UCM-Ship to the indicated direction."), + new ShotCommand("shoot", "s", "Shoot", "UCM-Ship launches a missile."), + new ShockwaveCommand("shockwave", "w", "ShockWave", "UCM-Ship releases a shock wave."), + new ListCommand("list", "l", "List", "Prints the list of available ships."), + new ResetCommand("reset", "r", "Reset", "Starts a new game."), + new HelpCommand("help", "h", "Help", "Prints this help message."), + new ExitCommand("exit", "e", "Exit", "Terminates the program."), + new UpdateCommand("none", "", "[none]", "Skips one cycle."), + new BuySuperMissileCommand("buy", "b", "Buy", "Buy a Super Missile."), + new StringifyCommand("stringify", "sf", "Stringify", "Serialize the board."), + new ListPrintersCommand("listPrinters", "lp", "ListPrinters", "Prints the list of available printers."), + new SuperShootCommand("supermissile", "sm", "SuperMissile", "UCM-Ship launches a super-missile."), + new SaveCommand("save", "g", "Save", "Save the game on a file."), + new LoadCommand("load", "c", "Load", "Load the game of a file.") + }; + + //M�todos: + + //Invoca al m�todo "parse" de cada subclase de Command. + public static Command parseCommand(String[] commandWords) throws CommandParseException { + boolean encontrado = false; + int i = 0; + Command cmd = null; + + while(!encontrado && i < MAXCOMMANDS) { + if(avaliableCommands[i].parse(commandWords) != null) { + cmd = avaliableCommands[i]; + encontrado = true; + } + else { + i++; + } + } + if(cmd == null) { throw new CommandParseException(Command.incorrectArgsMSg); } + + return cmd; + } + + //Invoca al m�todo helpText() de cada subclase de Command. + //Este m�todo es invocado por el m�todo "execute" de la clase HelpCommand. + public static String commandHelp(){ + String help = ""; + + for (int i = 0; i < avaliableCommands.length; i++) { + help += avaliableCommands[i].helpText(); + } + + return help; + } +} diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/ExitCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/ExitCommand.java new file mode 100644 index 0000000..2d05aff --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/ExitCommand.java @@ -0,0 +1,33 @@ +package tp.p2.controller.Commands; + +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class ExitCommand extends Command { + + public ExitCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + // TODO Auto-generated constructor stub + } + + @Override + public boolean execute(Game game) { + game.exit(); + return true; + } + + @Override + public Command parse(String[] commandWords) { + Command cmd = null; + + if(commandWords[0].equals("exit") || commandWords[0].equals("e")) { + cmd = this; + } + return cmd; + } + +} diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/HelpCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/HelpCommand.java new file mode 100644 index 0000000..871ebb1 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/HelpCommand.java @@ -0,0 +1,43 @@ +package tp.p2.controller.Commands; + +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class HelpCommand extends Command { + + public HelpCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + // TODO Auto-generated constructor stub + } + + @Override + public boolean execute(Game game) throws CommandExecuteException { + String help = CommandGenerator.commandHelp(); + + if(help != "") { + System.out.println(help); + } + else { + throw new CommandExecuteException("No description available."); + } + + return false; + } + + @Override + public Command parse(String[] commandWords) { + Command cmd = null; + + if(commandWords[0].equals("help") || commandWords[0].equals("h")) { + cmd = this; + } + + return cmd; + } + +} diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/ListCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/ListCommand.java new file mode 100644 index 0000000..996404a --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/ListCommand.java @@ -0,0 +1,39 @@ +package tp.p2.controller.Commands; + +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class ListCommand extends Command { + + public ListCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + // TODO Auto-generated constructor stub + } + + @Override + public boolean execute(Game game) { + System.out.println( + "[R]egular ship: Points: 5 - Harm: 0 - Shield: 2 \n" + + "[D]estroyer ship: Points: 10 - Harm: 1 - Shield: 1 \n" + + "[E]xplosive destroyer ship: Points: 10 - Harm: 1 - Shield: 1 \n" + + "[O]vni: Points: 25 - Harm: 0 - Shield: 1 \n" + + "^__^: Harm: 1 - Shield: 3\n"); + return false; + } + + @Override + public Command parse(String[] commandWords) { + Command cmd = null; + + if(commandWords[0].equals("list") || commandWords[0].equals("l")) { + cmd = this; + } + + return cmd; + } + +} diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/ListPrintersCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/ListPrintersCommand.java new file mode 100644 index 0000000..641b478 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/ListPrintersCommand.java @@ -0,0 +1,39 @@ +package tp.p2.controller.Commands; + +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.game.Game; +import tp.p2.game.PrinterTypes; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class ListPrintersCommand extends Command { + + public ListPrintersCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + // TODO Auto-generated constructor stub + } + + @Override + public boolean execute(Game game) throws CommandExecuteException { + System.out.println(PrinterTypes.printerHelp(game)); + if(PrinterTypes.printerHelp(game) == "") { + throw new CommandExecuteException("No printers avaliable."); + } + return false; + } + + @Override + public Command parse(String[] commandWords) { + Command cmd = null; + + if(commandWords[0].equals("listPrinters") || commandWords[0].equals("lp")) { + cmd = this; + } + + return cmd; + } + +} diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/LoadCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/LoadCommand.java new file mode 100644 index 0000000..ad5e5ef --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/LoadCommand.java @@ -0,0 +1,99 @@ +package tp.p2.controller.Commands; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.Scanner; +import tp.p2.Level; +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.controller.Exceptions.CommandParseException; +import tp.p2.controller.Exceptions.FileContentsException; +import tp.p2.game.FileContentsVerifier; +import tp.p2.game.Game; +import tp.p2.game.GameObjects.AlienShip; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class LoadCommand extends Command { + private Scanner in; + + public LoadCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + this.in = new Scanner(System.in); + } + + @Override + public boolean execute(Game game) throws CommandExecuteException { + BufferedReader inStream = null; + FileContentsVerifier verifier = new FileContentsVerifier(); + String gameString = ""; + int restCycles = 0; + + System.out.println("File name > "); + String fileName = in.nextLine() + ".dat"; + + try { + inStream = new BufferedReader( + new InputStreamReader( + new FileInputStream(fileName), "UTF-8")); + try { + //Read from the archive until we find the game line: + do { + gameString = inStream.readLine().trim(); + } while(!verifier.verifyGameString(gameString)); + String[] words = gameString.split(FileContentsVerifier.separator1); + restCycles = Integer.parseInt(words[1]); + + //Read the level: + String levelString = inStream.readLine().trim(); + verifier.verifyLevelString(levelString); + Level level = Level.parse(levelString); + + //Load the game information: + game.load(inStream); + AlienShip.setNumAliens(level.getNumRegularAliens()+level.getNumDestroyerAliens()); + game = new Game(level, restCycles); + System.out.println("Game successfully loaded from file " + fileName + "\n"); + } + catch (FileContentsException e) { + e.printStackTrace(); + } + catch (IOException e) { + e.printStackTrace(); + } + finally { + try { + inStream.close(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + } + catch (FileNotFoundException e) { + e.printStackTrace(); + } + catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return true; + } + + @Override + public Command parse(String[] commandWords) throws CommandParseException { + Command cmd = null; + + if(commandWords[0].equals("load") || commandWords[0].equals("c")) { + cmd = this; + } + + return cmd; + } + +} diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/MoveCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/MoveCommand.java new file mode 100644 index 0000000..0bf5224 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/MoveCommand.java @@ -0,0 +1,59 @@ +package tp.p2.controller.Commands; + +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.controller.Exceptions.CommandParseException; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class MoveCommand extends Command{ + //Atributos: + private String moveDir; + private int nCasillas; + + //Constructor: + public MoveCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + } + + //M�todos: + public boolean execute(Game game) throws CommandExecuteException{ + boolean exe = false; + + if(game.move(this.moveDir, this.nCasillas)) { + exe = true; + } + + return exe; + } + + public Command parse(String[] commandWords) throws CommandParseException { + Command cmd = null; + + if(commandWords.length > 3) { + throw new CommandParseException(Command.incorrectNumArgsMsg); + } + if(commandWords[0].equals("move") || commandWords[0].equals("m")) { + cmd = this; + if(commandWords[1].equals("left") || commandWords[1].equals("right")) { + this.moveDir = commandWords[1]; + if(Integer.parseInt(commandWords[2]) > 0 && Integer.parseInt(commandWords[2]) <= 2) { + this.nCasillas = Integer.parseInt(commandWords[2]); + } + else { + throw new CommandParseException("The number of cells is not correct."); + } + } + else { + throw new CommandParseException("Error reading the direction."); + } + } + + + return cmd; + } + +} diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/ResetCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/ResetCommand.java new file mode 100644 index 0000000..e712e58 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/ResetCommand.java @@ -0,0 +1,33 @@ +package tp.p2.controller.Commands; + +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ +public class ResetCommand extends Command { + + public ResetCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + // TODO Auto-generated constructor stub + } + + @Override + public boolean execute(Game game) { + game.reset(); + return true; + } + + @Override + public Command parse(String[] commandWords) { + Command cmd = null; + + if(commandWords[0].equals("reset") || commandWords[0].equals("r")) { + cmd = this; + } + + return cmd; + } + +} diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/SaveCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/SaveCommand.java new file mode 100644 index 0000000..e919e42 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/SaveCommand.java @@ -0,0 +1,63 @@ +package tp.p2.controller.Commands; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Scanner; +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.controller.Exceptions.CommandParseException; +import tp.p2.game.Game; +import tp.p2.game.GamePrinter; +import tp.p2.game.Stringifier; + +/** + * @author Fernando M�ndez Torrubiano + * + */ +public class SaveCommand extends Command { + + private Scanner in; + + public SaveCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + this.in = new Scanner(System.in); + } + + @Override + public boolean execute(Game game) throws CommandExecuteException { + GamePrinter printer = new Stringifier(); + + System.out.println("File name > "); + String fileName = in.nextLine() + ".dat"; + + BufferedWriter outChars = null; + + try { + outChars = new BufferedWriter(new FileWriter(fileName)); + outChars.write(printer.toString(game)); + outChars.close(); + } + catch (IOException e) { + e.printStackTrace(); + } + finally { + if(outChars == null) { throw new CommandExecuteException("No se pudo guardar el juego."); } + else { System.out.println("Game successfully saved in file " + fileName + ". Use the 'load' command to reload it.\n"); } + } + + return false; + } + + @Override + public Command parse(String[] commandWords) throws CommandParseException { + Command cmd = null; + + if(commandWords[0].equals("save") || commandWords[0].equals("g")) { + cmd = this; + } + + return cmd; + } + +} + diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/ShockwaveCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/ShockwaveCommand.java new file mode 100644 index 0000000..b626eb2 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/ShockwaveCommand.java @@ -0,0 +1,39 @@ +package tp.p2.controller.Commands; + +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class ShockwaveCommand extends Command { + //Atributos: + + public ShockwaveCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + } + + public boolean execute(Game game) throws CommandExecuteException { + boolean exe = true; + + if(!game.shockWave()) { + exe = false; + throw new CommandExecuteException("El ShockWave no est� disponible."); + } + + return exe; + } + + public Command parse(String[] commandWords) { + Command cmd = null; + + if(commandWords[0].equals("shockwave") || commandWords[0].equals("w")) { + cmd = this; + } + + return cmd; + } + +} diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/ShotCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/ShotCommand.java new file mode 100644 index 0000000..fa04489 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/ShotCommand.java @@ -0,0 +1,41 @@ +package tp.p2.controller.Commands; + +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class ShotCommand extends Command { + //Atributos: + + //Constructor: + public ShotCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + } + + //M�todos: + public boolean execute(Game game) throws CommandExecuteException { + boolean exe = true; + + if(!game.shootLaser()) { + exe = false; + throw new CommandExecuteException("You can't launch two missiles at once."); + } + + return exe; + } + + public Command parse(String[] commandWords) { + Command cmd = null; + + if(commandWords[0].equals("shot") || commandWords[0].equals("s")) { + //cmd = new ShotCommand(commandWords[0], "m", "Realiza un disparo", null); + cmd = this; + } + + return cmd; + } +} diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/StringifyCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/StringifyCommand.java new file mode 100644 index 0000000..9aa1932 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/StringifyCommand.java @@ -0,0 +1,47 @@ +package tp.p2.controller.Commands; + +import tp.p2.controller.Commands.Command; +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.game.Game; +import tp.p2.game.GamePrinter; +import tp.p2.game.Stringifier; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class StringifyCommand extends Command{ + + public StringifyCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + // TODO Auto-generated constructor stub + } + + @Override + public boolean execute(Game game) throws CommandExecuteException { + GamePrinter printer = new Stringifier(); + + if(printer != null) { + System.out.println(printer.toString(game)); + } + /* + else { + throw new CommandExecuteException("The board could not be serializable."); + }*/ + + return false; + } + + @Override + public Command parse(String[] commandWords) { + Command cmd = null; + + if (commandWords[0].equals("stringify") || commandWords[0].equals("sf")) { + cmd = this; + } + + return cmd; + } + +} \ No newline at end of file diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/SuperShootCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/SuperShootCommand.java new file mode 100644 index 0000000..0766700 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/SuperShootCommand.java @@ -0,0 +1,41 @@ +package tp.p2.controller.Commands; + +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class SuperShootCommand extends Command { + + public SuperShootCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + } + + public boolean execute(Game game) throws CommandExecuteException { + boolean exe = true; + + if(!game.shootSuperLaser()) { + exe = false; + throw new CommandExecuteException("You don't have super-missiles."); + } + + return exe; + } + + public Command parse(String[] commandWords) { + Command cmd = null; + + if(commandWords[0].equals("supermissile") || commandWords[0].equals("sm")) { + cmd = this; + } + + return cmd; + } + +} + + + diff --git a/SpaceInvaders/src/tp/p2/controller/Commands/UpdateCommand.java b/SpaceInvaders/src/tp/p2/controller/Commands/UpdateCommand.java new file mode 100644 index 0000000..ac94796 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Commands/UpdateCommand.java @@ -0,0 +1,31 @@ +package tp.p2.controller.Commands; + +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ +public class UpdateCommand extends Command { + public UpdateCommand(String name, String shortcut, String details, String help) { + super(name, shortcut, details, help); + // TODO Auto-generated constructor stub + } + + @Override + public boolean execute(Game game) { + return true; + } + + @Override + public Command parse(String[] commandWords) { + Command cmd = null; + + if(commandWords[0].equals("none") || commandWords[0].equals("n") || commandWords[0].equals("")) { + cmd = this; + } + + return cmd; + } + +} diff --git a/SpaceInvaders/src/tp/p2/controller/Controller.java b/SpaceInvaders/src/tp/p2/controller/Controller.java new file mode 100644 index 0000000..fd09f13 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Controller.java @@ -0,0 +1,97 @@ +/** + * + */ +package tp.p2.controller; + +import java.util.Scanner; +import tp.p2.controller.Commands.Command; +import tp.p2.controller.Commands.CommandGenerator; +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.controller.Exceptions.CommandParseException; +import tp.p2.game.BoardPrinter; +import tp.p2.game.Game; +import tp.p2.game.GamePrinter; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class Controller { + //Atributos: + Scanner in; + + //Constructor: + public Controller(Game game, Scanner in) { + this.in = new Scanner(System.in); + } + + //M�todos: + + //Ejecuta el bucle del juego hasta que termina: + public void run(Game game) { + GamePrinter printer = new BoardPrinter(Game.MAXFIL, Game.MAXCOL); + System.out.println(game + printer.toString(game)); + + do { + System.out.println("Command > "); + String[] words = in.nextLine().toLowerCase().trim().split("\\s+"); + + try { + Command command = CommandGenerator.parseCommand(words); + if (command != null) { + if (command.execute(game)) { + game.update(); + System.out.println(game + printer.toString(game)); + } + } + else { + System.out.format("Command " + words[0] + " not found. \n"); + } + } + catch (CommandParseException | CommandExecuteException ex) { + System.out.format(ex.getMessage() + " %n %n"); + } + } while (!game.isFinished()); + game.update(); + System.out.println(game + printer.toString(game)); + System.out.println(game.getWinnerMessage()); + } + +} + +//TPpr2v2: +/* +public class Controller { +//Atributos: +Scanner in; + +//Constructor: +public Controller(Game game, Scanner in) { + this.in = new Scanner(System.in); +} + +//M�todos: + +//Ejecuta el bucle del juego hasta que termina: +public void run(Game game) { + System.out.println(game); + do { + System.out.println("Command > "); + String[] words = in.nextLine().toLowerCase().trim().split("\\s+"); + + Command command = CommandGenerator.parseCommand(words); + if (command != null) { + if (command.execute(game)) { + game.update(); + System.out.println(game); + } + } + else { + System.out.format("Command " + words[0] + " not found. \n"); + } + } while (!game.isFinished()); +} + +} +*/ diff --git a/SpaceInvaders/src/tp/p2/controller/Exceptions/CommandExecuteException.java b/SpaceInvaders/src/tp/p2/controller/Exceptions/CommandExecuteException.java new file mode 100644 index 0000000..1d66e84 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Exceptions/CommandExecuteException.java @@ -0,0 +1,21 @@ +package tp.p2.controller.Exceptions; +/** + * @author Fernando M�ndez Torrubiano + * + */ +public class CommandExecuteException extends Exception { + + private static final long serialVersionUID = 1L; + + private String message; + + public CommandExecuteException(String string) { + this.message = "Failed to run command.\n" + + "Cause of exception: \n" + + this + ": " + string; + } + + public String getMessage() { + return this.message; + } +} diff --git a/SpaceInvaders/src/tp/p2/controller/Exceptions/CommandParseException.java b/SpaceInvaders/src/tp/p2/controller/Exceptions/CommandParseException.java new file mode 100644 index 0000000..82f21e9 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Exceptions/CommandParseException.java @@ -0,0 +1,22 @@ +package tp.p2.controller.Exceptions; +/** + * @author Fernando M�ndez Torrubiano + * + */ +public class CommandParseException extends Exception { + + private static final long serialVersionUID = 1L; + + private String message; + + public CommandParseException(String string) { + this.message = "Command can�t be parse.\n" + + "Cause of exception: \n" + + this + ": " + string; + } + + public String getMessage() { + return this.message; + } + +} diff --git a/SpaceInvaders/src/tp/p2/controller/Exceptions/FileContentsException.java b/SpaceInvaders/src/tp/p2/controller/Exceptions/FileContentsException.java new file mode 100644 index 0000000..1c10a5e --- /dev/null +++ b/SpaceInvaders/src/tp/p2/controller/Exceptions/FileContentsException.java @@ -0,0 +1,24 @@ +package tp.p2.controller.Exceptions; +/** + * @author Fernando M�ndez Torrubiano + * + */ +public class FileContentsException extends Exception { + public static final String wrongPrefixMsg = "unknown game attribute: "; + public static final String lineTooLongMsg = "too many words on line commencing: "; + public static final String lineTooShortMsg = "missing data on line commencing: "; + + private static final long serialVersionUID = 1L; + + private String string; + + public FileContentsException(String string) { + this.string = "Contend not found.\n" + + "Cause of exception: \n" + + this + ": " + string; + } + + public String toString() { + return this.string; + } +} diff --git a/SpaceInvaders/src/tp/p2/game/BoardPrinter.java b/SpaceInvaders/src/tp/p2/game/BoardPrinter.java new file mode 100644 index 0000000..fca6e64 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/BoardPrinter.java @@ -0,0 +1,76 @@ +package tp.p2.game; + +import tp.p2.util.MyStringUtils; +/** + * @author Fernando M�ndez Torrubiano + * + */ +public class BoardPrinter implements GamePrinter { + private int numRows; + private int numCols; + private String[][] board; + private final String space = " "; + + public BoardPrinter(int maxfil, int maxcol) { + this.numRows = maxfil; + this.numCols = maxcol; + } + + @Override + public String toString(Game game) { + encodeGame(game); + + int cellSize = 7; + int marginSize = 2; + String vDelimiter = "|"; + String hDelimiter = "-"; + + String rowDelimiter = MyStringUtils.repeat(hDelimiter, (numCols * (cellSize + 1)) - 1); + String margin = MyStringUtils.repeat(space, marginSize); + String lineDelimiter = String.format("%n%s%s%n", margin + space, rowDelimiter); + + StringBuilder str = new StringBuilder(); + + str.append(lineDelimiter); + + for(int i=0; i 0; + } + + public static boolean verifyCoords(int x, int y, Game game) { + return game.isOnBoard(x, y); + } + + public static boolean verifyCurrentCycle(int currentCycle) { + return currentCycle >= 0; + } + + public static boolean verifyLevel(Level level) { + return level != null; + } + + public static boolean verifyDir(String dir) { + return dir != null; + } + + public static boolean verifyLives(int live, int armour) { + return 0 < live && live <= armour; + } + + public static boolean verifyPoints(int points) { + return points >= 0; + } + + public static boolean verifyCycleToNextAlienMove(int cycle, Level level) { + return 0 <= cycle && cycle <= level.getNumCyclesToMoveOneCell(); + } + + // parseBoolean converts any string different from "true" to false. + public static boolean verifyBool(String boolString) { + return boolString.equals("true") || boolString.equals("false"); + } + + public boolean isMissileOnLoadedBoard() { + return foundInFileString.toUpperCase().contains("M"); + } + + // Use a regular expression to verify the string of concatenated prefixes found + public boolean verifyLines() { + // TO DO: compare foundInFileString with a regular expression + return true; + } + + // text explaining allowed concatenated prefixes + public String toString() { + // TO DO + return ""; + } + + public boolean verifyGameString(String gameString) { + String[] words = gameString.split(";"); + appendToFoundInFileString(words[0]); + if (words.length != 2) + return false; + return true; + } +} + diff --git a/SpaceInvaders/src/tp/p2/game/Game.java b/SpaceInvaders/src/tp/p2/game/Game.java new file mode 100644 index 0000000..cd6a457 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/Game.java @@ -0,0 +1,265 @@ +package tp.p2.game; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.Random; +import tp.p2.Level; +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.controller.Exceptions.FileContentsException; +import tp.p2.game.GameObjects.BoardInitializer; +import tp.p2.game.GameObjects.GameObject; +import tp.p2.game.GameObjects.Ovni; +import tp.p2.game.GameObjects.AlienShip; +import tp.p2.game.GameObjects.Shockwave; +import tp.p2.game.GameObjects.SuperMissile; +import tp.p2.game.GameObjects.UCMMissile; +import tp.p2.game.GameObjects.UCMShip; +import tp.p2.game.GameObjects.Interfaces.IPlayerController; +import tp.p2.game.GameObjects.Lists.GameObjectBoard; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class Game implements IPlayerController{ + //Constantes: + public final static int MAXFIL = 9; + public final static int MAXCOL = 8; + public final static int DAMAGE = 1; + public final static int COSTSUPERMISSILE = 20; + + //Atributos + private int currentCycle; + private Random rand; + private Level level; + private int restCycles; + + GameObjectBoard board; + + private UCMShip player; + + private boolean doExit; + private BoardInitializer initializer; + + //Constructor: + public Game (Level level, Random random){ + this.rand = random; + this.level = level; + this.restCycles = this.level.getNumCyclesToMoveOneCell(); + initializer = new BoardInitializer(); + initGame(); + } + + public Game (Level level, int restCycles){ + this.rand = new Random(System.currentTimeMillis()); + this.level = level; + this.restCycles = restCycles; + this.currentCycle = restCycles; + initializer = null; + } + + //M�todos: + public void initGame () { + currentCycle = 0; + board = initializer.initialize(this, level); + player = new UCMShip(this, MAXFIL - 1, MAXCOL / 2); + board.add(player); + } + + public Random getRandom() { + return rand; + } + + public Level getLevel() { + return level; + } + + public int getCurrentCycle() { + return this.currentCycle; + } + + public void reset() { + initGame(); + } + + public void addObject(GameObject object) { + board.add(object); + } + + public String positionToString(int fila, int columna) { + return board.toString(fila, columna); + } + + public boolean isFinished() { + return playerWin() || aliensWin() || doExit; + } + + public boolean aliensWin() { + return !player.isAlive() || AlienShip.haveLanded(); + } + + private boolean playerWin () { + return AlienShip.allDead(); + } + + public void update() { + board.computerAction(); + board.update(); + currentCycle += 1; + if(this.restCycles == 0) { + this.restCycles = this.level.getNumCyclesToMoveOneCell(); + } + else { + restCycles--; + } + } + + public boolean isOnBoard(int fila, int columna) { + return MAXFIL > fila && MAXCOL > columna; + } + + public void exit() { + doExit = true; + } + + public String infoToString() { + return "Life: " + this.player.getLive() + "\n" + + "Number of cycles: " + this.currentCycle + "\n" + + "Points: " + this.player.getPoints() + "\n" + + "Remaining aliens: " + AlienShip.numAliens() + "\n" + + "ShockWave: " + this.player.getShockWave() + "\n" + + "Number of SuperMissiles: " + this.player.getNumSuperMissiles() + "\n"; + } + + public String toString() { + //BoardPrinter gp = new BoardPrinter(MAXFIL, MAXCOL); + //String tablero = this.infoToString() + gp.toString(this); + //return tablero; + + return this.infoToString(); + } + + public String serialize() { + return "--SPACE INVADERS v2.0--\n\n" + + "G;" + this.restCycles + "\n" + + "L;" + this.level + "\n" + + this.board.serialize() + "\n"; + } + + public String getWinnerMessage () { + if (playerWin()) return "Player win!"; + else if (aliensWin()) return "Aliens win!"; + else if (doExit) return "Player exits the game"; + else return "This should not happen"; + } + + @Override + public boolean move(String dir, int numCells) throws CommandExecuteException{ + boolean move = false; + + if(this.player.move(dir, numCells)) { + move = true; + } + + return move; + } + + @Override + public boolean shootLaser() { + boolean shoot = false; + + if(this.player.getMisile()) { + this.enableMissile(); + shoot = true; + } + return shoot; + } + + @Override + public boolean shockWave() { + boolean sw = false; + + if(this.player.getShockWave()) { + sw = true; + this.board.swAttack(); + this.player.deleteSW(); + GameObject ovni = new Ovni(this, 0, Game.MAXCOL, 1); + this.board.add(ovni); + } + + return sw; + } + + @Override + public boolean shootSuperLaser() { + boolean shoot = false; + + if(this.player.getSuperMisile() || this.player.getMisile()) { + this.enableSuperMissile(); + shoot = true; + } + + return shoot; + } + + @Override + public void receivePoints(int points) { + this.player.addPoints(points); + } + + @Override + public void enableShockWave() { + Shockwave sw = new Shockwave(this, this.player.getFila(), this.player.getColumna(), 1); + this.player.activeSW(sw); + this.board.add(sw); + } + + @Override + public void enableMissile() { + UCMMissile misil = new UCMMissile(this, this.player.getFila(), this.player.getColumna(), 1); + this.player.activeMisile(misil); + this.board.add(misil); + } + + @Override + public void enableSuperMissile() { + SuperMissile misil = new SuperMissile(this, this.player.getFila(), this.player.getColumna(), 1); + this.player.activeSuperMisile(misil); + this.board.add(misil); + } + + public boolean buySuperMissile() throws CommandExecuteException { + boolean buy = false; + + if (this.player.getPoints() >= COSTSUPERMISSILE) { + this.player.subtractPoints(COSTSUPERMISSILE); + this.player.getSuperMissile(); + buy = true; + } + if(!buy) { + throw new CommandExecuteException("You don't have enough points."); + } + + return buy; + } + + public int getRestCycles() { + return this.restCycles; + } + + public void load(BufferedReader inStream) throws IOException, FileContentsException { + this.board.setCurrentObjects(0); + String line = inStream.readLine().trim(); + while (line != null && !line.isEmpty()) { + FileContentsVerifier verifier = new FileContentsVerifier(); + GameObject gameObject = GameObjectGenerator.parse(line, this, verifier); + if(gameObject == null) { + throw new FileContentsException("invalid file, unrecognised line prefix"); + } + board.add(gameObject); + line = inStream.readLine().trim(); + } + } + +} \ No newline at end of file diff --git a/SpaceInvaders/src/tp/p2/game/GameObjectGenerator.java b/SpaceInvaders/src/tp/p2/game/GameObjectGenerator.java new file mode 100644 index 0000000..0d5bb33 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjectGenerator.java @@ -0,0 +1,46 @@ +package tp.p2.game; + +import java.util.Random; +import tp.p2.Level; +import tp.p2.controller.Exceptions.FileContentsException; +import tp.p2.game.GameObjects.Bomb; +import tp.p2.game.GameObjects.DestroyerAlien; +import tp.p2.game.GameObjects.GameObject; +import tp.p2.game.GameObjects.Ovni; +import tp.p2.game.GameObjects.RegularAlien; +import tp.p2.game.GameObjects.Shockwave; +import tp.p2.game.GameObjects.SuperMissile; +import tp.p2.game.GameObjects.UCMMissile; +import tp.p2.game.GameObjects.UCMShip; +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class GameObjectGenerator { + private static Game otherGame = new Game(Level.EASY, new Random(System.currentTimeMillis())); + private static GameObject[] availableGameObjects = { + new UCMShip(otherGame, 0, 0), + new Ovni(otherGame, 0, 0, 0), + new RegularAlien(otherGame, 0, 0, 0), + new DestroyerAlien(otherGame, 0, 0, 0), + new Shockwave(otherGame, 0, 0, 0), + new Bomb(otherGame, 0, 0, 0), + new UCMMissile(otherGame, 0, 0, 0), + new SuperMissile(otherGame, 0, 0, 0) + }; + + + public static GameObject parse(String stringFromFile, Game game, FileContentsVerifier verifier) throws FileContentsException { + GameObject gameObject = null; + for (GameObject go: availableGameObjects) { + gameObject = go.parse(stringFromFile, game, verifier); + if (gameObject != null) break; + } + return gameObject; + } +} + +/* + +*/ \ No newline at end of file diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/AlienShip.java b/SpaceInvaders/src/tp/p2/game/GameObjects/AlienShip.java new file mode 100644 index 0000000..3008a77 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/AlienShip.java @@ -0,0 +1,130 @@ +package tp.p2.game.GameObjects; + +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public abstract class AlienShip extends EnemyShip { + //Atributos est�ticos: + protected static boolean down = false; //Variable est�tica booleana para indicar si los Aliens tienen que bajar o no. + protected static String direction = "left"; //Variable est�tica que indica la direcci�n en la que se mueve los aliens. + protected static boolean isLanded = false; + protected static boolean allDead = false; + protected static int numAliens = 0; //Variable est�tica que indica el n�mero de Aliens que hay en el tablero actualmente. + protected static int contAliens = 0; //Variable est�tica que ind�ca (si down == true), cu�ntos aliens han bajado. + + + //Constructor: + public AlienShip(Game game, int fila, int col, int live) { + super(game, fila, col, live); + } + + //M�todos: + public static boolean haveLanded() { + return isLanded; + } + + public static boolean allDead() { + return allDead; + } + + public static int numAliens() { + return numAliens; + } + + public static void setNumAliens(int aliens) { + numAliens = aliens; + } + + public void move() { + if(this.game.getRestCycles() == 0) { + if(direction == "left") { + this.columna--; + if(this.columna == 0) { + down = true; + } + } + else if(direction == "right") { + this.columna++; + if(this.columna == Game.MAXCOL-1) { + down = true; + } + } + } + if(down && this.game.getRestCycles() == this.level.getNumCyclesToMoveOneCell()) { + this.fila++; + if(this.fila == Game.MAXFIL-1) { isLanded = true; } + contAliens++; + if(contAliens >= numAliens) { + contAliens = 0; + down = false; + if(direction == "left") { + direction = "right"; + } + else { + direction = "left"; + } + } + } + } + + public boolean receiveMissileAttack(int damage) { + this.getDamage(damage); + return true; + } + + public boolean receiveShockWaveAttack(int damage) { + this.getDamage(damage); + return true; + } + + public boolean recibeExplodeAttack(int damage) { //Para recibir da�o de una nave explosiva. + this.getDamage(damage); + return true; + } + + public abstract void computerAction(); + public abstract void onDelete(); + public abstract String toString(); +} + + + +/* +public void move() { + if(this.game.getCurrentCycle() % this.level.getNumCyclesToMoveOneCell() == 0) { + if(direction == "left") { + this.columna--; + if(this.columna == 0) { + down = true; + } + } + else if(direction == "right") { + this.columna++; + if(this.columna == Game.MAXCOL-1) { + down = true; + } + } + } + if(down == true && this.game.getCurrentCycle() % this.level.getNumCyclesToMoveOneCell() != 0) { + this.fila++; + if(this.fila == Game.MAXFIL-1) { isLanded = true; } + contAliens++; + if(contAliens == numAliens) { + contAliens = 0; + down = false; + if(direction == "left") { + direction = "right"; + } + else { + direction = "left"; + } + } + } + } +*/ + + diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/BoardInitializer.java b/SpaceInvaders/src/tp/p2/game/GameObjects/BoardInitializer.java new file mode 100644 index 0000000..ec15c7f --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/BoardInitializer.java @@ -0,0 +1,61 @@ +package tp.p2.game.GameObjects; + +import tp.p2.Level; +import tp.p2.game.Game; +import tp.p2.game.GameObjects.Lists.GameObjectBoard; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class BoardInitializer { + + private Level level; + private GameObjectBoard board; + private Game game; + + public GameObjectBoard initialize(Game game, Level level) { + this.level = level; + this.game = game; + board = new GameObjectBoard(Game.MAXFIL, Game.MAXCOL); + + initializeOvni(); + initializeRegularAliens(); + initializeDestroyerAliens(); + return board; + } + + private void initializeOvni () { + GameObject ovni = new Ovni(game, 0, Game.MAXCOL, 1); + board.add(ovni); + } + + private void initializeRegularAliens () { + int fila=2, col=3; + for (int i = 0; i < this.level.getNumRowsOfRegularAliens(); i++) { + for (int j = 0; j < this.level.getNumRegularAliensPerRow(); j++) { + GameObject regular = new RegularAlien(this.game, fila, col, 2); + board.add(regular); + col++; + } + fila++; + col = 3; + } + } + + private void initializeDestroyerAliens() { + int fila, col; + switch (level) { + case EASY: fila = 3; col = 4; break; + case HARD: fila = 4; col = 3; break; + default: fila = 5; col = 3; break; + } + for (int i = 0; i < this.level.getNumDestroyerAliensPerRow(); i++) { + GameObject destroyer = new DestroyerAlien(this.game, fila, col, 1); + board.add(destroyer); + col++; + } + } +} + diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/Bomb.java b/SpaceInvaders/src/tp/p2/game/GameObjects/Bomb.java new file mode 100644 index 0000000..8e09a69 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/Bomb.java @@ -0,0 +1,74 @@ +package tp.p2.game.GameObjects; + +import tp.p2.game.FileContentsVerifier; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class Bomb extends Weapon{ + //Atributos: + private String letra; + + //Constructor: + public Bomb(Game game, int fila, int col, int live) { + super(game, fila, col, live); + this.letra = "oo"; + } + + public Bomb() { + super(null, 0, 0, 0); + this.letra = "oo"; + } + + public void weaponAttack(GameObject other) { + other.receiveBombAttack(Game.DAMAGE); + //this.live--; + this.getDamage(Game.DAMAGE); + } + + public boolean recibeMissileAttack(int damage) { + //this.live--; + this.getDamage(damage); + return true; + } + + @Override + public void computerAction() {} + + @Override + public void onDelete() { + if(this.getLive() <= 0 || this.getFila() > Game.MAXFIL-1) { // + this.isAlive = false; + } + } + + @Override + public void move() { + this.fila++; + } + + @Override + public String toString() { + return this.letra; + } + + @Override + public String serializer() { + return "B;" + + this.fila + "," + + this.columna + "," + + this.live; + } + + @Override + public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) { + String[] words = stringFromFile.split(FileContentsVerifier.separator1); + String[] coords = words[1].split(FileContentsVerifier.separator2); + return verifier.verifyWeaponString(stringFromFile, game2) ? + new Bomb(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2])):null; + } + +} diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/DestroyerAlien.java b/SpaceInvaders/src/tp/p2/game/GameObjects/DestroyerAlien.java new file mode 100644 index 0000000..3f3a50e --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/DestroyerAlien.java @@ -0,0 +1,86 @@ +package tp.p2.game.GameObjects; + +import tp.p2.game.FileContentsVerifier; +import tp.p2.game.Game; +import tp.p2.game.GameObjects.Interfaces.IExecuteRandomActions; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class DestroyerAlien extends AlienShip implements IExecuteRandomActions{ + //Atributos: + private Bomb bomb; + private String letra; + + //Constructor: + public DestroyerAlien(Game game, int fila, int col, int live) { + super(game, fila, col, live); + this.bomb = null; + this.letra = "D"; + numAliens++; + } + + public DestroyerAlien() { + super(null, 0, 0, 1); + this.bomb = null; + this.letra = "D"; + numAliens++; + } + + //M�todos: + public void deleteBomb() { + this.bomb = null; + } + + public boolean getBomb() { + return this.bomb != null ? true : false; + } + + @Override + public void computerAction() { + if(this.bomb == null && IExecuteRandomActions.canGenerateRandomBomb(game)) { + this.bomb = new Bomb(game, this.fila, this.columna, 1); + this.game.addObject(this.bomb); + } + } + + @Override + public void onDelete() { + if(this.bomb != null && !this.bomb.isAlive) { + this.deleteBomb(); + } + if(this.live <= 0) { + this.isAlive = false; + numAliens--; + this.game.receivePoints(10); + if(numAliens == 0) { allDead = true; } + } + } + + @Override + public String toString() { + return this.letra + "[" + this.live + "]"; + } + + @Override + public String serializer() { + return "D;" + + this.fila + "," + + this.columna + ";" + + this.live + ";" + //+ this.getBomb() + ";" + + this.game.getRestCycles() + ";" + + this.direction; + } + + @Override + public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) { + String[] words = stringFromFile.split(FileContentsVerifier.separator1); + String[] coords = words[1].split(FileContentsVerifier.separator2); + return verifier.verifyDestroyerShipString(stringFromFile, game2, 2) ? + new DestroyerAlien(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2])):null; + } + +} diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/EnemyShip.java b/SpaceInvaders/src/tp/p2/game/GameObjects/EnemyShip.java new file mode 100644 index 0000000..d8a0f97 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/EnemyShip.java @@ -0,0 +1,23 @@ +package tp.p2.game.GameObjects; + +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public abstract class EnemyShip extends Ship { + + //Constructor: + public EnemyShip(Game game, int fila, int col, int live) { + super(game, fila, col, live); + // TODO Auto-generated constructor stub + } + + //M�todos: + public abstract void computerAction(); + public abstract void onDelete(); + public abstract void move(); + public abstract String toString(); +} diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/GameObject.java b/SpaceInvaders/src/tp/p2/game/GameObjects/GameObject.java new file mode 100644 index 0000000..277ddf2 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/GameObject.java @@ -0,0 +1,73 @@ +package tp.p2.game.GameObjects; + +import tp.p2.Level; +import tp.p2.game.FileContentsVerifier; +import tp.p2.game.Game; +import tp.p2.game.GameObjects.Interfaces.IAttack; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public abstract class GameObject implements IAttack { + //Atributos est�ticos: + protected int fila, columna; + protected int live; + protected boolean isAlive; + protected Game game; + protected Level level; + + //Constrcutor: + public GameObject(Game game, int fila, int col, /*Coordenadas iniciales*/ int live) { + this.fila = fila; + this.columna = col; + this.game = game; + this.level = this.game.getLevel(); + this.live = live; + this.isAlive = true; + } + + //M�todos: + public int getFila() { + return this.fila; + } + + public int getColumna() { + return this.columna; + } + + public boolean isAlive() { + return this.isAlive; + } + + public int getLive() { + return this.live; + } + + public boolean isOnPosition(int x, int y) { + return this.fila == x && this.columna == y; + } + + public void getDamage (int damage) { + this.live = damage >= this.live ? 0 : this.live - damage; + } + + public boolean isOut() { + return !game.isOnBoard(this.fila, this.columna); + } + + public void update() { + this.move(); + if(this.isAlive != false) { this.onDelete(); } + } + + public abstract void computerAction(); + public abstract void onDelete(); + public abstract void move(); + public abstract String toString(); + public abstract String serializer(); + public abstract GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier); + +} + diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/Interfaces/IAttack.java b/SpaceInvaders/src/tp/p2/game/GameObjects/Interfaces/IAttack.java new file mode 100644 index 0000000..bdf7ca5 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/Interfaces/IAttack.java @@ -0,0 +1,16 @@ +package tp.p2.game.GameObjects.Interfaces; + +import tp.p2.game.GameObjects.GameObject; +/** + * @author Fernando M�ndez Torrubiano + * + */ +public interface IAttack { + default boolean performAttack(GameObject other) {return false;}; + + default boolean receiveMissileAttack(int damage) {return false;}; + default boolean receiveBombAttack(int damage) {return false;}; + default boolean receiveShockWaveAttack(int damage) {return false;}; + default boolean recibeExplodeAttack(int damage) {return false;}; +} + diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/Interfaces/IExecuteRandomActions.java b/SpaceInvaders/src/tp/p2/game/GameObjects/Interfaces/IExecuteRandomActions.java new file mode 100644 index 0000000..832509f --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/Interfaces/IExecuteRandomActions.java @@ -0,0 +1,18 @@ +package tp.p2.game.GameObjects.Interfaces; + +import tp.p2.game.Game; +/** + * @author Fernando M�ndez Torrubiano + * + */ +public interface IExecuteRandomActions { + + static boolean canGenerateRandomOvni(Game game){ + return game.getRandom().nextDouble() < game.getLevel().getOvniFrequency(); + } + + static boolean canGenerateRandomBomb(Game game){ + return game.getRandom().nextDouble() < game.getLevel().getShootFrequency(); + } + +} \ No newline at end of file diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/Interfaces/IPlayerController.java b/SpaceInvaders/src/tp/p2/game/GameObjects/Interfaces/IPlayerController.java new file mode 100644 index 0000000..250b248 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/Interfaces/IPlayerController.java @@ -0,0 +1,20 @@ +package tp.p2.game.GameObjects.Interfaces; + +import tp.p2.controller.Exceptions.CommandExecuteException; +/** + * @author Fernando M�ndez Torrubiano + * + */ +public interface IPlayerController { + // PLAYER ACTIONS + public boolean move (String dir, int numCells) throws CommandExecuteException; + public boolean shootLaser(); + public boolean shockWave(); + public boolean shootSuperLaser(); + + // CALLBACKS + public void receivePoints(int points); + public void enableShockWave(); + public void enableMissile(); + public void enableSuperMissile(); +} diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/Lists/GameObjectBoard.java b/SpaceInvaders/src/tp/p2/game/GameObjects/Lists/GameObjectBoard.java new file mode 100644 index 0000000..344b284 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/Lists/GameObjectBoard.java @@ -0,0 +1,129 @@ +package tp.p2.game.GameObjects.Lists; + +import tp.p2.game.Game; +//import tp.p2.game.Game; +import tp.p2.game.GameObjects.GameObject; +/** + * @author Fernando M�ndez Torrubiano + * + */ +public class GameObjectBoard { + //Atributos: + private GameObject[] objects; + private int currentObjects; + + //Constructor: + public GameObjectBoard (int width, int height) { + this.objects = new GameObject[width * height]; + this.currentObjects = 0; + } + + //M�todos: + private int getCurrentObjects() { + return this.currentObjects; + } + + public void setCurrentObjects(int currentObjects) { + this.currentObjects = currentObjects; + } + + public void add (GameObject object) { + this.objects[this.currentObjects] = object; + this.currentObjects++; + } + + /* + private GameObject getObjectInPosition(int fila, int columna) { + int pos = getIndex(fila, columna); + return this.objects[pos]; + } + */ + + private int getIndex(int fila, int columna) { + boolean encontrado = false; + int i = this.getCurrentObjects()-1; + + while(!encontrado && i >= 0) { + if(this.objects[i].getFila() == fila && this.objects[i].getColumna() == columna) { + encontrado = true; + } + else { + i--; + } + } + + return i; + } + + private void remove(GameObject object) { + int pos = getIndex(object.getFila(), object.getColumna()); + + this.objects[pos] = null; + for (int i = pos; i < this.getCurrentObjects(); i++) { + this.objects[i] = this.objects[i+1]; + } + this.currentObjects--; + } + + public void update() { + for (int i = 0; i < this.getCurrentObjects(); i++) { + this.objects[i].update(); + this.checkAttacks(this.objects[i]); + } + this.removeDead(); + } + + private void checkAttacks(GameObject object) { + for (int i = 0; i < this.getCurrentObjects(); i++) { + if (object != this.objects[i]) { + if(object.performAttack(this.objects[i])) { + object.onDelete(); + this.objects[i].onDelete(); + } + } + } + } + + public void computerAction() { + for (int i = 0; i < this.getCurrentObjects(); i++) { + this.objects[i].computerAction(); + } + } + + private void removeDead() { + for (int i = 0; i < this.getCurrentObjects(); i++) { + if(!this.objects[i].isAlive()) { + remove(this.objects[i]); + } + } + } + + public void swAttack() { + for (int i = 0; i < this.getCurrentObjects(); i++) { + this.objects[i].receiveShockWaveAttack(Game.DAMAGE); + } + } + + public String toString(int fila, int columna) { + String print = ""; + + for (int i = 0; i < this.getCurrentObjects(); i++) { + if(this.objects[i].getFila() == fila && this.objects[i].getColumna() == columna) { + print += this.objects[i].toString(); + } + } + + return print; + } + + public String serialize() { + String serialize = ""; + + for (int i = 0; i < this.getCurrentObjects(); i++) { + serialize += this.objects[i].serializer() + "\n"; + } + + return serialize; + } + +} \ No newline at end of file diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/Ovni.java b/SpaceInvaders/src/tp/p2/game/GameObjects/Ovni.java new file mode 100644 index 0000000..0f48e2f --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/Ovni.java @@ -0,0 +1,88 @@ +package tp.p2.game.GameObjects; + +import tp.p2.game.FileContentsVerifier; +import tp.p2.game.Game; +import tp.p2.game.GameObjects.Interfaces.IExecuteRandomActions; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class Ovni extends EnemyShip{ + //Atributos: + private String letra; + private boolean enabble; + + //Constructor: + public Ovni(Game game, int fila, int col, int live) { + super(game, fila, col, live); + this.letra = "O"; + this.enabble = false; + } + + public Ovni() { + super(null, 0, 0, 1); + this.letra = "O"; + this.enabble = false; + } + + //M�todos: + public String toString() { + return this.letra + "[" + this.live + "]"; + } + + @Override + public void computerAction() { + if(IExecuteRandomActions.canGenerateRandomOvni(game)) { + this.enabble = true; + } + } + + public boolean receiveMissileAttack(int damage) { + this.live -= damage; + this.game.enableShockWave(); + this.game.receivePoints(25); + return true; + } + + public boolean receiveShockWaveAttack(int damage) { + this.live -= damage; + return true; + } + + @Override + public void onDelete() { + if(this.columna < 0) { + this.enabble = false; + this.columna = Game.MAXCOL; + } + else if(this.live <= 0) { + this.isAlive = false; + } + } + + @Override + public void move() { + if(this.enabble) { //QUITAR LA CONDICI�N DE LA COLUMNA, ES S�LO PARA PRUEBAS. && this.columna >= Game.MAXCOL + this.columna--; + } + } + + @Override + public String serializer() { + return "O;" + + this.fila + "," + + this.columna + ";" + + this.live; + } + + @Override + public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) { + String[] words = stringFromFile.split(FileContentsVerifier.separator1); + String[] coords = words[1].split(FileContentsVerifier.separator2); + return verifier.verifyOvniString(stringFromFile, game2, 1) ? + new Ovni(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2])):null; + } + +} \ No newline at end of file diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/RegularAlien.java b/SpaceInvaders/src/tp/p2/game/GameObjects/RegularAlien.java new file mode 100644 index 0000000..1a53e3b --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/RegularAlien.java @@ -0,0 +1,115 @@ +package tp.p2.game.GameObjects; + +import tp.p2.game.FileContentsVerifier; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ +public class RegularAlien extends AlienShip { + //Atributos: + private String letra; + private boolean explosive; + + //Constructor: + public RegularAlien(Game game, int fila, int col, int live) { + super(game, fila, col, live); + this.letra = "C"; + this.explosive = false; + numAliens++; + } + + public RegularAlien() { + super(null, 0, 0, 2); + this.letra = "C"; + this.explosive = false; + numAliens++; + } + + public RegularAlien(Game game, int fila, int col, int live, String letra) { + super(game, fila, col, live); + this.letra = letra; + this.explosive = false; + numAliens++; + } + + public int getLive() { + return this.live; + } + + public boolean isDead() { + return this.getLive() > 0; + } + + @Override + public void computerAction() { + if((!this.explosive) && (this.game.getRandom().nextDouble() < this.level.getTurnExplodeFrequency())) { + this.explosive = true; + this.letra = "E"; + } + } + + @Override + public void onDelete() { + if(this.live == 0) { + if(!this.explosive) { this.isAlive = false; } + numAliens--; + if(numAliens == 0) { allDead = true; } + + this.game.receivePoints(5); + } + } + + @Override + public String toString() { + return this.letra + "[" + this.live + "]"; + } + + @Override + public String serializer() { + String letra = "R"; + if(explosive) {letra = this.letra;} + return letra + ";" + + this.fila + "," + + this.columna + ";" + + this.live + ";" + + this.game.getRestCycles() + ";" + + this.direction; + } + + //M�todos si la nave es explosiva: + public void explodeAttack(GameObject other) { + other.recibeExplodeAttack(Game.DAMAGE); + } + + public boolean performAttack(GameObject other) { + boolean attack = false; + + if(this.explosive && this.live == 0) { + if(other.isAlive()) { + if(other.isOnPosition(fila-1, columna) || other.isOnPosition(fila+1, columna) || other.isOnPosition(fila, columna-1) || other.isOnPosition(fila, columna+1)) { + this.explodeAttack(other); //restar vida + attack = true; + } + } + this.isAlive = false; + } + + return attack; + } + + @Override + public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) { + String[] words = stringFromFile.split(FileContentsVerifier.separator1); + String[] coords = words[1].split(FileContentsVerifier.separator2); + if(words[0].equals("R")) { + return verifier.verifyRegularShipString(stringFromFile, game2, 2) ? + new RegularAlien(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2])):null; + } + else { + return verifier.verifyExplosiveShipString(stringFromFile, game2, 2) ? + new RegularAlien(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2]), words[0]):null; + } + } +} diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/Ship.java b/SpaceInvaders/src/tp/p2/game/GameObjects/Ship.java new file mode 100644 index 0000000..97e41e2 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/Ship.java @@ -0,0 +1,22 @@ +package tp.p2.game.GameObjects; + +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public abstract class Ship extends GameObject { + + //Constructor: + public Ship(Game game, int fila, int col, int live) { + super(game, fila, col, live); + } + + //M�todos: + public abstract void computerAction(); + public abstract void onDelete(); + public abstract void move(); + public abstract String toString(); +} diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/Shockwave.java b/SpaceInvaders/src/tp/p2/game/GameObjects/Shockwave.java new file mode 100644 index 0000000..a9a3a63 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/Shockwave.java @@ -0,0 +1,55 @@ +package tp.p2.game.GameObjects; + +import tp.p2.game.FileContentsVerifier; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class Shockwave extends Weapon { + + public Shockwave(Game game, int fila, int col, int live) { + super(game, fila, col, live); + } + + public Shockwave() { + super(null, 0, 0, 1); + } + + @Override + protected void weaponAttack(GameObject other) { + other.receiveShockWaveAttack(Game.DAMAGE); + this.getDamage(Game.DAMAGE); + } + + @Override + public void computerAction() {} + + @Override + public void onDelete() { + if(this.live == 0) { + this.isAlive = false; + } + } + + @Override + public void move() {} + + @Override + public String toString() { + return ""; + } + + @Override + public String serializer() { + return ""; + } + + @Override + public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) { + return verifier.verifyWeaponString(stringFromFile, game2) ? new Shockwave(game2, 0, 0, 1):null; + } + +} diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/SuperMissile.java b/SpaceInvaders/src/tp/p2/game/GameObjects/SuperMissile.java new file mode 100644 index 0000000..05d3d12 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/SuperMissile.java @@ -0,0 +1,69 @@ +package tp.p2.game.GameObjects; + +import tp.p2.game.FileContentsVerifier; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class SuperMissile extends Weapon { + //Atributos: + private String letra; + + //Constructor: + public SuperMissile(Game game, int fila, int col, int live) { + super(game, fila, col, live); + this.letra = "||"; + } + + public SuperMissile() { + super(null, 0, 0, 1); + this.letra = "||"; + } + + //M�todos: + @Override + protected void weaponAttack(GameObject other) { + other.receiveMissileAttack(Game.DAMAGE*2); + this.getDamage(Game.DAMAGE); + } + + @Override + public void computerAction() {} + + @Override + public void onDelete() { + if(this.live <= 0 || this.fila < 0) { + this.isAlive = false; + } + } + + @Override + public void move() { + this.fila--; + + } + + @Override + public String toString() { + return this.letra; + } + + @Override + public String serializer() { + return "M;" + + this.fila + "," + + this.columna; + } + + @Override + public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) { + String[] words = stringFromFile.split(FileContentsVerifier.separator1); + String[] coords = words[1].split(FileContentsVerifier.separator2); + return verifier.verifyWeaponString(stringFromFile, game2) ? + new SuperMissile(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2])):null; + } + +} diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/UCMMissile.java b/SpaceInvaders/src/tp/p2/game/GameObjects/UCMMissile.java new file mode 100644 index 0000000..9f274d5 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/UCMMissile.java @@ -0,0 +1,67 @@ +package tp.p2.game.GameObjects; + +import tp.p2.game.FileContentsVerifier; +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class UCMMissile extends Weapon{ + //Atributos: + private String letra; + + //Constructor: + public UCMMissile(Game game, int fila, int col, int live) { + super(game, fila, col, live); + this.letra = "|"; + } + + public UCMMissile() { + super(null, 0, 0, 1); + this.letra = "|"; + } + + @Override + protected void weaponAttack(GameObject other) { + other.receiveMissileAttack(Game.DAMAGE); + //this.live--; + this.getDamage(Game.DAMAGE); + } + + @Override + public void computerAction() {} + + @Override + public void onDelete() { + if(this.live <= 0 || this.fila < 0) { + this.isAlive = false; + } + } + + @Override + public void move() { + this.fila--; + } + + @Override + public String toString() { + return this.letra; + } + + @Override + public String serializer() { + return "M;" + + this.fila + "," + + this.columna; + } + + @Override + public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) { + String[] words = stringFromFile.split(FileContentsVerifier.separator1); + String[] coords = words[1].split(FileContentsVerifier.separator2); + return verifier.verifyWeaponString(stringFromFile, game2) ? + new UCMMissile(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(words[2])):null; + } +} diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/UCMShip.java b/SpaceInvaders/src/tp/p2/game/GameObjects/UCMShip.java new file mode 100644 index 0000000..e48b3e2 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/UCMShip.java @@ -0,0 +1,186 @@ +package tp.p2.game.GameObjects; + +import tp.p2.controller.Exceptions.CommandExecuteException; +import tp.p2.game.FileContentsVerifier; +//import tp.p2.controller.ShockwaveCommand; +import tp.p2.game.Game; +//import tp.p2.util.MyStringUtils; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class UCMShip extends Ship { + //Atributos: + private Weapon misil; + private Shockwave shockwave; + private String letra; + private int points; + private int numSuperMissiles; + + //Constructor: + public UCMShip(Game game, int fila, int col) { + super(game, fila, col, 3); + this.misil = null; + this.shockwave = null; + this.letra = "^__^"; + this.points = 0; + this.numSuperMissiles = 0; + } + + public UCMShip() { + super(null, Game.MAXFIL-1, 4, 3); + this.misil = null; + this.shockwave = null; + this.letra = "^__^"; + this.points = 0; + this.numSuperMissiles = 0; + } + + public void activeMisile(UCMMissile misil) { + this.misil = misil; + } + + public void activeSW(Shockwave sw) { + this.shockwave = sw; + } + + public void activeSuperMisile(SuperMissile supermisil) { + if(this.numSuperMissiles > 0) { this.misil = supermisil; } + } + + public void deleteMisil() { + if(this.getSuperMisile()) { this.numSuperMissiles--; } + this.misil = null; + } + + public void deleteSW() { + this.shockwave = null; + } + + public boolean receiveBombAttack(int damage) { + this.live -= damage; + return true; + } + + @Override + public void computerAction() {} + + @Override + public void onDelete() { + if((this.misil != null) && (!this.misil.isAlive)) { //(this.misil.getLive() == 0 || this.misil.getFila() < 0) + this.deleteMisil(); + } + + if(this.live <= 0) { + this.isAlive = false; + } + } + public boolean move(String dir, int nCasillas) throws CommandExecuteException{ + boolean move = false; + + switch(dir) { + case "right": + if(this.columna + nCasillas < Game.MAXCOL) { + switch(nCasillas) { + case 1: this.columna++; move = true; break; + case 2: this.columna += 2; move = true; break; + default: break; + } + } + break; + case "left": + if(this.columna - nCasillas >= 0) { + switch(nCasillas) { + case 1: this.columna--; move = true; break; + case 2: this.columna -= 2; move = true; break; + default: this.columna += 0; move = false; break; + } + } + break; + } + if(!move) { + throw new CommandExecuteException("You'd come out of the limits of the board."); + } + + return move; + } + + public void addPoints(int points) { + this.points += points; + } + + public void subtractPoints(int points) { + this.points -= points; + } + + public int getPoints() { + return this.points; + } + + public boolean getMisile() { + boolean misilEnable = false; + + if(this.misil == null) { + misilEnable = true; + } + + return misilEnable; + } + + public boolean getShockWave() { + boolean sw = false; + + if(this.shockwave != null) { + sw = true; + } + + return sw; + } + + public boolean getSuperMisile() { + boolean smEnable = false; + + if(this.numSuperMissiles > 0) { + smEnable = true; + } + + return smEnable; + } + + public void getSuperMissile() { + this.numSuperMissiles++; + } + + public int getNumSuperMissiles() { + return this.numSuperMissiles; + } + + @Override + public void move() {} + + @Override + public String toString() { + return this.letra /*+ "[" + this.live + "]"*/; + } + + @Override + public String serializer() { + return "P;" + + this.fila + "," + + this.columna + ";" + + this.live + ";" + + this.points + ";" + + this.getShockWave() + ";" + + this.numSuperMissiles; + } + + @Override + public GameObject parse(String stringFromFile, Game game2, FileContentsVerifier verifier) { + String[] words = stringFromFile.split(FileContentsVerifier.separator1); + String[] coords = words[1].split(FileContentsVerifier.separator2); + return verifier.verifyPlayerString(stringFromFile, game2, 3) ? + new UCMShip(game2, Integer.parseInt(coords[0]), Integer.parseInt(coords[1])):null; + } +} \ No newline at end of file diff --git a/SpaceInvaders/src/tp/p2/game/GameObjects/Weapon.java b/SpaceInvaders/src/tp/p2/game/GameObjects/Weapon.java new file mode 100644 index 0000000..4114598 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GameObjects/Weapon.java @@ -0,0 +1,36 @@ +package tp.p2.game.GameObjects; + +import tp.p2.game.Game; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public abstract class Weapon extends GameObject { + + public Weapon(Game game, int fila, int col, int live) { + super(game, fila, col, live); + // TODO Auto-generated constructor stub + } + + public boolean performAttack(GameObject other) { + boolean attack = false; + + if(isAlive() && other.isAlive()) { + if(other.isOnPosition(this.fila, this.columna)) { //x, y de weapon + this.weaponAttack(other); //restar vida + attack = true; + } + } + + return attack; + } + + protected abstract void weaponAttack(GameObject other); + public abstract void computerAction(); + public abstract void onDelete(); + public abstract void move(); + public abstract String toString(); + +} diff --git a/SpaceInvaders/src/tp/p2/game/GamePrinter.java b/SpaceInvaders/src/tp/p2/game/GamePrinter.java new file mode 100644 index 0000000..302e487 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/GamePrinter.java @@ -0,0 +1,11 @@ +package tp.p2.game; +/** + * @author Fernando M�ndez Torrubiano + * + */ +public interface GamePrinter { + String toString(Game game); + public GamePrinter parse(String name); + public String helpText(); + void setGame(Game game); //A�adido en la versi�n 3. +} diff --git a/SpaceInvaders/src/tp/p2/game/PrinterGenerator.java b/SpaceInvaders/src/tp/p2/game/PrinterGenerator.java new file mode 100644 index 0000000..f2d17e1 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/PrinterGenerator.java @@ -0,0 +1,29 @@ +package tp.p2.game; +/** + * @author Fernando M�ndez Torrubiano + * + */ +public class PrinterGenerator { + private static GamePrinter[] availablePrinters = { + new BoardPrinter(Game.MAXFIL, Game.MAXCOL), + new Stringifier(), + }; + + public static GamePrinter parse(String name) { + GamePrinter printer = null; + for (GamePrinter p: availablePrinters) { + printer = p.parse(name); + if (printer != null) break; + } + return printer; + } + + public static String printerHelp() { + StringBuilder printers = new StringBuilder(); + for (GamePrinter p: availablePrinters) + printers.append(p.helpText()); + return printers.toString(); + } + +} + diff --git a/SpaceInvaders/src/tp/p2/game/PrinterTypes.java b/SpaceInvaders/src/tp/p2/game/PrinterTypes.java new file mode 100644 index 0000000..ecfcf90 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/PrinterTypes.java @@ -0,0 +1,45 @@ +package tp.p2.game; + +import tp.p2.controller.Exceptions.CommandExecuteException; +/** + * @author Fernando M�ndez Torrubiano + * + */ +public enum PrinterTypes { + + BOARDPRINTER("boardprinter", + "prints the game formatted as a board of dimension: ", + new BoardPrinter(Game.MAXFIL, Game.MAXCOL)), + STRINGIFIER("stringifier", + "prints the game as plain text", + new Stringifier()); + + private String printerName; + private String helpText; + private GamePrinter printerObject; + + private PrinterTypes(String name, String text, GamePrinter printer) { + printerName = name; + helpText = text; + printerObject = printer; + } + + public static String printerHelp(Game game) throws CommandExecuteException { + String helpString = ""; + for (PrinterTypes printer : PrinterTypes.values()) + helpString += String.format("%s : %s%s%n", printer.printerName, printer.helpText, + (printer == BOARDPRINTER ? Game.MAXFIL + " x " + Game.MAXCOL : "") ); + + if(helpString == "") {throw new CommandExecuteException("No hay tableros disponibles.");} + return helpString; + } + + // Assumes a max of one object of each printer type is needed (otherwise return copy) + public GamePrinter getObject(Game game) { + printerObject.setGame(game); + return printerObject; + } + + +} + diff --git a/SpaceInvaders/src/tp/p2/game/Stringifier.java b/SpaceInvaders/src/tp/p2/game/Stringifier.java new file mode 100644 index 0000000..d5b6043 --- /dev/null +++ b/SpaceInvaders/src/tp/p2/game/Stringifier.java @@ -0,0 +1,34 @@ +package tp.p2.game; +/** + * @author Fernando M�ndez Torrubiano + * + */ +public class Stringifier implements GamePrinter{ + + @Override + public String toString(Game game) { + return game.serialize(); + } + + @Override + public GamePrinter parse(String name) { + GamePrinter tablero = null; + + if(name.equals("serializer") || name.equals("stringifier")) { + tablero = this; + } + + return tablero; + } + + @Override + public String helpText() { + return "prints the game as plain text"; + } + + @Override + public void setGame(Game game) { + // TODO Auto-generated method stub + + } +} diff --git a/SpaceInvaders/src/tp/p2/util/MyStringUtils.java b/SpaceInvaders/src/tp/p2/util/MyStringUtils.java new file mode 100644 index 0000000..e30f87f --- /dev/null +++ b/SpaceInvaders/src/tp/p2/util/MyStringUtils.java @@ -0,0 +1,24 @@ +package tp.p2.util; + +/** + * @author Fernando M�ndez Torrubiano + * + */ + +public class MyStringUtils { + public static String repeat(String elmnt, int length) { + String result = ""; + for (int i = 0; i < length; i++) { + result += elmnt; + } + return result; + } + + public static String centre(String text, int len){ + String out = String.format(" %"+len+"s %s %"+len+"s", "",text,""); + float mid = (out.length()/2); + float start = mid - (len/2); + float end = start + len; + return out.substring((int)start, (int)end); + } +} \ No newline at end of file