diff --git a/.idea/misc.xml b/.idea/misc.xml index be3fc8d..46d8359 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -8,7 +8,5 @@ - - - + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 00e0d01..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/GameState.java b/Java-Knight/src/main/java/org/project/GameState.java new file mode 100644 index 0000000..9e016a2 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/GameState.java @@ -0,0 +1,25 @@ +package org.project; + +import org.project.entity.players.Player; +import org.project.location.Location; +import java.io.Serializable; + +public class GameState implements Serializable { + private static final long serialVersionUID = 1L; + + private Player player; + private Location currentLocation; + + public GameState(Player player, Location currentLocation) { + this.player = player; + this.currentLocation = currentLocation; + } + + public Player getPlayer() { + return player; + } + + public Location getCurrentLocation() { + return currentLocation; + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/Main.java b/Java-Knight/src/main/java/org/project/Main.java index 6bde20e..e8e4180 100644 --- a/Java-Knight/src/main/java/org/project/Main.java +++ b/Java-Knight/src/main/java/org/project/Main.java @@ -1,15 +1,301 @@ package org.project; +import org.project.combat.CombatSystem; +import org.project.entity.Entity; +import org.project.entity.enemies.Dragon; +import org.project.entity.enemies.Goblin; +import org.project.entity.enemies.Skeleton; +import org.project.entity.enemies.Vampire; +import org.project.entity.players.*; import org.project.location.Location; -import java.util.ArrayList; -import java.util.List; +import java.util.Random; +import java.util.Scanner; public class Main { - public static void main(String[] args) { - // TODO: ADD LOCATIONS TO YOUR GAME - List locations = new ArrayList<>(); - // TODO: IMPLEMENT GAMEPLAY + private static final Scanner scanner = new Scanner(System.in); + private static Location currentLocation; + + public static final String RESET = "\u001B[0m"; + public static final String RED = "\u001B[31m"; + public static final String GREEN = "\u001B[32m"; + public static final String YELLOW = "\u001B[33m"; + public static final String BLUE = "\u001B[34m"; + public static final String PURPLE = "\u001B[35m"; + public static final String CYAN = "\u001B[36m"; + + public static void main(String[] args) { + + initializeMap(); + + while (true) { + + System.out.println(CYAN + "\n===============================" + RESET); + System.out.println(YELLOW + " โš” JAVA KNIGHT โš”" + RESET); + System.out.println(CYAN + "===============================" + RESET); + + System.out.println("1. Start Game"); + System.out.println("2. How To Play"); + System.out.println("3. Exit"); + + System.out.print("> "); + int option = scanner.nextInt(); + + switch (option) { + case 1 -> startGame(); + case 2 -> showHelpMenu(); + case 3 -> { + System.out.println(GREEN + "Farewell hero!" + RESET); + System.exit(0); + } + default -> System.out.println(RED + "Invalid option!" + RESET); + } + } + } + + + private static void startGame() + { + + showIntro(); + + System.out.print("Enter your name: "); + String name = scanner.next(); + + System.out.println("\nChoose your class:"); + System.out.println(BLUE + "1. Knight ๐Ÿ›ก" + RESET); + System.out.println(PURPLE + "2. Wizard ๐Ÿ”ฎ" + RESET); + System.out.println(YELLOW + "3. Assassin ๐Ÿ—ก" + RESET); + + int choice = scanner.nextInt(); + Player player; + + switch (choice) { + case 1 -> player = new Knight(name); + case 2 -> player = new Wizard(name); + case 3 -> player = new Assassin(name); + default -> player = new Knight(name); + } + + player.resetKeys(); + System.out.println(GREEN + "\nWelcome " + name + " to Javanest!" + RESET); + + currentLocation.enter(); + gameLoop(player); + } + + private static void gameLoop(Player player) + { + + Random random = new Random(); + + + while (player.isAlive()) + { + + showPlayerStatus(player); + + System.out.println(CYAN + "\n===== LOCATION: " + currentLocation.getName() + " =====" + RESET); + System.out.println("1. Fight Enemy"); + System.out.println("2. Move Location"); + + if (player.hasAllKeys() && currentLocation.getName().equals("Vampire Crypt")) + { + System.out.println(RED + "3. Enter Dragon Castle ๐Ÿ‰" + RESET); + } + + System.out.print("> "); + int option = scanner.nextInt(); + + if (option == 1) { + Entity enemy = currentLocation.spawnEnemy(); + + System.out.println(RED + "\nA wild " + enemy.getName() + " appears!" + RESET); + + CombatSystem combat = new CombatSystem(); + combat.startBattle(player, enemy); + + if (!player.isAlive()) { + System.out.println(RED + "\nYou have fallen..." + RESET); + break; + } + + tryToDropKey(player, enemy, random); + recoverPlayer(player); + + } else if (option == 2) { + + moveLocation(); + + } else if (option == 3 && + player.hasAllKeys() && + currentLocation.getName().equals("Vampire Crypt")) { + + System.out.println(RED + "\nYou enter the Dragon Castle..." + RESET); + + CombatSystem combat = new CombatSystem(); + combat.startBattle(player, new Dragon()); + + if (player.isAlive()) { + System.out.println(GREEN + "\n๐Ÿ† YOU SAVED JAVANEST!" + RESET); + } else { + System.out.println(RED + "\nThe Dragon has defeated you..." + RESET); + } + + showProjectFeatures(); + break; + + } else { + System.out.println(RED + "Invalid option!" + RESET); + } + } + } + + private static void showPlayerStatus(Player player) { + + System.out.println(YELLOW + "\n===== PLAYER STATUS =====" + RESET); + + printBar("HP ", player.getHP(), player.getMaxHP(), RED); + printBar("MP ", player.getMP(), player.getMaxMP(), BLUE); + System.out.println("XP: " + player.getXP()); + } + + private static void printBar(String label, int value, int max, String color) + { + + int totalBars = 20; + int filled = (int)((double)value / max * totalBars); + + StringBuilder bar = new StringBuilder(); + + for (int i = 0; i < filled; i++) bar.append("โ–ˆ"); + for (int i = filled; i < totalBars; i++) bar.append("โ–‘"); + + System.out.println(label + " " + color + bar + RESET + " " + value + "/" + max); + } + + private static void moveLocation() + { + + System.out.println(YELLOW + "\nWhere do you want to go?" + RESET); + + int index = 1; + for (Location loc : currentLocation.getConnectedLocations()) + { + System.out.println(index + ". " + loc.getName()); + index++; + } + + System.out.print("> "); + int choice = scanner.nextInt(); + + if (choice < 1 || choice > currentLocation.getConnectedLocations().size()) + { + System.out.println(RED + "Invalid location!" + RESET); + return; + } + + currentLocation = currentLocation.getConnectedLocations().get(choice - 1); + currentLocation.enter(); + } + + private static void tryToDropKey(Player player, Entity enemy, Random random) + { + + int chance = random.nextInt(100) + 1; + + if (chance <= 20) + { + + if (enemy instanceof Goblin && !player.hasGoblinKey()) + { + player.obtainGoblinKey(); + System.out.println(YELLOW + "You obtained the Goblin Key!" + RESET); + } else if (enemy instanceof Skeleton && !player.hasSkeletonKey()) { + player.obtainSkeletonKey(); + System.out.println(YELLOW + "You obtained the Skeleton Key!" + RESET); + } else if (enemy instanceof Vampire && !player.hasVampireKey()) { + player.obtainVampireKey(); + System.out.println(YELLOW + "You obtained the Vampire Key!" + RESET); + } + } + } + + private static void recoverPlayer(Player player) + { + player.setHealth(player.getMaxHP()); + player.setMana(player.getMaxMP()); + System.out.println(GREEN + "You recovered your HP and Mana." + RESET); + } + + private static void showIntro() + { + System.out.println(PURPLE + "\n====================================" + RESET); + System.out.println(YELLOW + " LEGEND OF JAVANEST" + RESET); + System.out.println(PURPLE + "====================================" + RESET); + System.out.println("Defeat enemies, collect keys,"); + System.out.println("and face the mighty Dragon!"); + } + + private static void showHelpMenu() + { + System.out.println(YELLOW + "\nHOW TO PLAY:" + RESET); + System.out.println("- Fight enemies to gain XP."); + System.out.println("- Collect 3 keys."); + System.out.println("- Unlock Dragon Castle."); + System.out.println("- Defeat the Dragon to win."); + } + + private static void showProjectFeatures() + { + + System.out.println(CYAN + "\n====================================" + RESET); + System.out.println(YELLOW + " PROJECT FEATURES" + RESET); + System.out.println(CYAN + "====================================" + RESET); + + System.out.println(GREEN + "โœ” Multiple Player Classes" + RESET); + System.out.println(GREEN + "โœ” Location System" + RESET); + System.out.println(GREEN + "โœ” Key Collection System" + RESET); + System.out.println(GREEN + "โœ” Combat System" + RESET); + System.out.println(GREEN + "โœ” Final Boss Battle" + RESET); + } + + private static void initializeMap() + { + + Location forest = new Location( + "Forest", + "A dark forest full of goblins.", + 1 + ); + + Location graveyard = new Location( + "Graveyard", + "An abandoned graveyard with skeletons.", + 2 + ); + + Location vampireCrypt = new Location( + "Vampire Crypt", + "A cursed crypt where vampires sleep.", + 3 + ); + + Location dragonCastle = new Location( + "Dragon Castle", + "The castle of the ancient dragon.", + 4 + ); + + forest.connectLocation(graveyard); + graveyard.connectLocation(forest); + + graveyard.connectLocation(vampireCrypt); + vampireCrypt.connectLocation(graveyard); + + vampireCrypt.connectLocation(dragonCastle); + + currentLocation = forest; } } \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/combat/CombatSystem.java b/Java-Knight/src/main/java/org/project/combat/CombatSystem.java new file mode 100644 index 0000000..705ddc1 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/combat/CombatSystem.java @@ -0,0 +1,166 @@ +package org.project.combat; + +import org.project.entity.players.Player; +import org.project.entity.Entity; +import org.project.entity.enemies.Goblin; +import org.project.entity.enemies.Skeleton; +import org.project.entity.enemies.Vampire; + +import java.util.Scanner; + +public class CombatSystem +{ + + private static final String RESET = "\u001B[0m"; + private static final String RED = "\u001B[31m"; + private static final String GREEN = "\u001B[32m"; + private static final String YELLOW = "\u001B[33m"; + private static final String BLUE = "\u001B[34m"; + + private Scanner scanner = new Scanner(System.in); + + public void startBattle(Player player, Entity enemy) + { + + System.out.println(RED + "\nโš”๏ธ A battle has started!" + RESET); + System.out.println(YELLOW + "Enemy: " + enemy.getName() + RESET); + + while (player.isAlive() && enemy.isAlive()) + { + + System.out.println("\n" + BLUE + "----- YOUR TURN -----" + RESET); + System.out.println("1. Light Attack"); + System.out.println("2. Heavy Attack"); + System.out.println("3. Defend"); + System.out.println("4. Heal"); + System.out.println("5. Special Ability"); + System.out.println("6. Exit Game"); + + while (!scanner.hasNextInt()) + { + scanner.next(); + System.out.println("โŒ Please enter a number between 1-6"); + } + + int choice = scanner.nextInt(); + + switch (choice) + { + + case 1: + player.lightAttack(enemy); + break; + + case 2: + player.heavyAttack(enemy); + break; + + case 3: + player.defend(); + break; + + case 4: + player.specialAbility(enemy); + break; + + case 5: + if (player.getMP() >= 6) + { + player.heal(10); + player.fillMana(-6); + System.out.println("๐Ÿ’š You restored 10 HP at the cost of 6 MP!"); + } else { + System.out.println("โŒ Not enough MP to heal!"); + } + break; + + case 6: + if (player.getXP() >= 10) + { + player.gainXP(-10); + player.fillMana(20); + System.out.println("๐Ÿ”ฎ +20 MP restored (Cost: 10 XP)"); + } else { + System.out.println("โŒ Not enough XP to restore mana!"); + } + break; + + case 7: + if (player.getXP() >= 50) + { + player.gainXP(-50); + player.heal(30); + System.out.println("โค๏ธ +30 HP restored (Cost: 50 XP)"); + } else { + System.out.println("โŒ Not enough XP to restore HP!"); + } + break; + + case 8: + System.out.println("๐Ÿ‘‹ Exiting game..."); + System.exit(0); + + default: + System.out.println("โŒ Invalid choice!"); + } + + if (!enemy.isAlive()) + { + + System.out.println(GREEN + "\nโœ… Enemy defeated!" + RESET); + + player.gainXP(50); + + dropKey(player, enemy); + + recoverPlayer(player); + + break; + } + + System.out.println(RED + "\n๐Ÿ‘น ENEMY TURN!" + RESET); + + enemy.attack(player); + + if (!player.isAlive()) + { + System.out.println(RED + "\n๐Ÿ’€ You were defeated..." + RESET); + } + } + } + + private void dropKey(Player player, Entity enemy) + { + + double chance = Math.random(); + + if (chance > 0.20) return; + + if (enemy instanceof Goblin && !player.hasGoblinKey()) + { + System.out.println(YELLOW + "๐Ÿ—๏ธ Goblin Key obtained!" + RESET); + player.obtainGoblinKey(); + } + + else if (enemy instanceof Skeleton && !player.hasSkeletonKey()) + { + System.out.println(YELLOW + "๐Ÿ—๏ธ Skeleton Key obtained!" + RESET); + player.obtainSkeletonKey(); + } + + else if (enemy instanceof Vampire && !player.hasVampireKey()) + { + System.out.println(YELLOW + "๐Ÿ—๏ธ Vampire Key obtained!" + RESET); + player.obtainVampireKey(); + } + } + + private void recoverPlayer(Player player) + { + + player.setHealth(player.getMaxHP()); + player.setMana(player.getMaxMP()); + + System.out.println("\u001B[32mโœจ Your HP and Mana have been fully restored!\u001B[0m"); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/Entity.java b/Java-Knight/src/main/java/org/project/entity/Entity.java index 2a060f9..4146ce7 100644 --- a/Java-Knight/src/main/java/org/project/entity/Entity.java +++ b/Java-Knight/src/main/java/org/project/entity/Entity.java @@ -1,6 +1,7 @@ package org.project.entity; -public interface Entity { +public interface Entity +{ void attack(Entity target); void defend(); @@ -11,9 +12,22 @@ public interface Entity { void takeDamage(int damage); + int getHP(); + int getMP(); int getMaxHP(); - int getMaxMP(); + int getLevel(); + String getName(); + + void setStunned(boolean value); + boolean isStunned(); + + void setInvisible(boolean value); + boolean isInvisible(); + + boolean isAlive(); + + void gainXP(int xp); /* TODO: ADD OTHER REQUIRED AND BONUS METHODS diff --git a/Java-Knight/src/main/java/org/project/entity/enemies/Dragon.java b/Java-Knight/src/main/java/org/project/entity/enemies/Dragon.java new file mode 100644 index 0000000..dbc1e57 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Dragon.java @@ -0,0 +1,38 @@ +package org.project.entity.enemies; + +import org.project.entity.Entity; +import org.project.item.weapons.BasicWeapon; + +import java.util.Random; + +public class Dragon extends Enemy +{ + + private Random random = new Random(); + + public Dragon() + { + super("Dragon", 200, 50, new BasicWeapon("Flame Breath", 25)); + } + + @Override + public void attack(Entity target) + { + + int damage; + + if (random.nextBoolean()) + { + damage = weapon.getDamage() + 20; + System.out.println(RED + "๐Ÿ”ฅ Dragon uses FIRE BREATH!" + RESET); + } else { + damage = weapon.getDamage(); + System.out.println(YELLOW + "๐Ÿ‰ Dragon claws viciously!" + RESET); + } + + target.takeDamage(damage); + + System.out.println(RED + "๐Ÿ’ฅ Dragon deals " + + damage + " damage!" + RESET); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/enemies/Enemy.java b/Java-Knight/src/main/java/org/project/entity/enemies/Enemy.java index e019acb..a10e2fe 100644 --- a/Java-Knight/src/main/java/org/project/entity/enemies/Enemy.java +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Enemy.java @@ -1,34 +1,140 @@ package org.project.entity.enemies; +import org.project.entity.Entity; import org.project.item.weapons.Weapon; -// TODO: UPDATE IMPLEMENTATION -public abstract class Enemy { - Weapon weapon; - private int hp; - private int mp; +public abstract class Enemy implements Entity +{ - public Enemy(int hp, int mp, Weapon weapon) { + protected String name; + protected int hp; + protected int mp; + protected int maxHp; + protected int maxMp; + protected int level; + protected boolean stunned; + protected boolean invisible; + protected Weapon weapon; + + protected static final String RESET = "\u001B[0m"; + protected static final String RED = "\u001B[31m"; + protected static final String YELLOW = "\u001B[33m"; + protected static final String PURPLE = "\u001B[35m"; + + public Enemy(String name, int hp, int mp, Weapon weapon) + { + this.name = name; this.hp = hp; this.mp = mp; - + this.maxHp = hp; + this.maxMp = mp; + this.level = 1; + this.stunned = false; + this.invisible = false; this.weapon = weapon; } @Override - public void takeDamage(int damage) { - hp -= damage; + public void defend() + { + System.out.println(name + " defends."); } - public int getHp() { + @Override + public void heal(int health) + { + if (health <= 0) return; + hp += health; + if (hp > maxHp) hp = maxHp; + } + + @Override + public void fillMana(int mana) + { + if (mana <= 0) return; + mp += mana; + if (mp > maxMp) mp = maxMp; + } + + @Override + public void takeDamage(int damage) + { + if (damage <= 0) return; + hp -= damage; + if (hp < 0) hp = 0; + } + + @Override + public int getHP() + { return hp; } - public int getMp() { + @Override + public int getMP() + { return mp; } - public Weapon getWeapon() { - return weapon; + @Override + public int getMaxHP() + { + return maxHp; } + + @Override + public int getMaxMP() + { + return maxMp; + } + + @Override + public int getLevel() + { + return level; + } + + @Override + public String getName() + { + return name; + } + + @Override + public void setStunned(boolean value) + { + this.stunned = value; + } + + @Override + public boolean isStunned() + { + return stunned; + } + + @Override + public void setInvisible(boolean value) + { + this.invisible = value; + } + + @Override + public boolean isInvisible() + { + return invisible; + } + + @Override + public boolean isAlive() + { + return hp > 0; + } + + @Override + public void gainXP(int xp) + { + } + + @Override + public abstract void attack(Entity target); } diff --git a/Java-Knight/src/main/java/org/project/entity/enemies/Goblin.java b/Java-Knight/src/main/java/org/project/entity/enemies/Goblin.java new file mode 100644 index 0000000..af0fc86 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Goblin.java @@ -0,0 +1,37 @@ +package org.project.entity.enemies; + +import org.project.entity.Entity; +import org.project.item.weapons.BasicWeapon; + +import java.util.Random; + +public class Goblin extends Enemy +{ + + private Random random = new Random(); + + private static final String RESET = "\u001B[0m"; + private static final String RED = "\u001B[31m"; + private static final String PURPLE = "\u001B[35m"; + + public Goblin() { + super("Goblin", 60, 20, new BasicWeapon("Rusty Dagger", 12)); + } + + @Override + public void attack(Entity target) + { + + int damage = weapon.getDamage(); + + if (random.nextInt(100) < 25) + { + damage *= 2; + System.out.println(PURPLE + "๐Ÿ’€ Goblin CRITICAL strike!" + RESET); + } + + target.takeDamage(damage); + + System.out.println(RED + "๐Ÿ‘น Goblin attacks for " + damage + " damage!" + RESET); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/enemies/Skeleton.java b/Java-Knight/src/main/java/org/project/entity/enemies/Skeleton.java index 8a6a555..600faa5 100644 --- a/Java-Knight/src/main/java/org/project/entity/enemies/Skeleton.java +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Skeleton.java @@ -1,6 +1,46 @@ package org.project.entity.enemies; -// TODO: UPDATE IMPLEMENTATION -public class Skeleton { - // TODO: DESIGN ENEMY AND IMPLEMENT THE CONSTRUCTOR -} +import org.project.entity.Entity; +import org.project.item.weapons.BasicWeapon; + +public class Skeleton extends Enemy +{ + + private boolean revived = false; + + private static final String RESET = "\u001B[0m"; + private static final String RED = "\u001B[31m"; + private static final String YELLOW = "\u001B[33m"; + + public Skeleton() + { + super("Skeleton", 70, 10, new BasicWeapon("Bone Sword", 15)); + } + + @Override + public void attack(Entity target) + { + + int damage = weapon.getDamage(); + + target.takeDamage(damage); + + System.out.println(RED + "โ˜  Skeleton slashes for " + damage + " damage!" + RESET); + } + + @Override + public void takeDamage(int damage) + { + + super.takeDamage(damage); + + if (!isAlive() && !revived) + { + + revived = true; + this.hp = 40; + + System.out.println(YELLOW + "โš  Skeleton reassembles itself!" + RESET); + } + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/enemies/Vampire.java b/Java-Knight/src/main/java/org/project/entity/enemies/Vampire.java new file mode 100644 index 0000000..b9c01e0 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Vampire.java @@ -0,0 +1,30 @@ +package org.project.entity.enemies; + +import org.project.entity.Entity; +import org.project.item.weapons.BasicWeapon; + +public class Vampire extends Enemy +{ + + public Vampire() + { + super("Vampire", 90, 30, new BasicWeapon("Dark Claws", 18)); + } + + @Override + public void attack(Entity target) + { + + int damage = weapon.getDamage(); + target.takeDamage(damage); + + int healAmount = damage / 2; + this.hp += healAmount; + + System.out.println(RED + "๐Ÿง› Vampire drains " + + damage + " HP!" + RESET); + + System.out.println(YELLOW + "๐Ÿฉธ Vampire heals " + + healAmount + " HP!" + RESET); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/players/Assassin.java b/Java-Knight/src/main/java/org/project/entity/players/Assassin.java new file mode 100644 index 0000000..9fef985 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/players/Assassin.java @@ -0,0 +1,99 @@ +package org.project.entity.players; + +import org.project.entity.Entity; +import org.project.item.weapons.BasicWeapon; + +import java.util.Random; + +public class Assassin extends Player +{ + + private static final int HEAVY_COST = 15; + private static final int SPECIAL_COST = 25; + + private static final String RESET = "\u001B[0m"; + private static final String RED = "\u001B[31m"; + private static final String GREEN = "\u001B[32m"; + private static final String YELLOW = "\u001B[33m"; + private static final String BLUE = "\u001B[34m"; + private static final String PURPLE = "\u001B[35m"; + + private Random random = new Random(); + + public Assassin(String name) { + super(name, 90, 80, new BasicWeapon("Dagger", 18)); + } + + @Override + public void lightAttack(Entity target) + { + + int dmg = weapon.getDamage() + 12; + + // 25% critical chance + if (random.nextInt(100) < 25) + { + dmg *= 2; + System.out.println(PURPLE + "๐Ÿ’€ CRITICAL HIT!" + RESET); + } + + target.takeDamage(dmg); + + System.out.println(YELLOW + "๐Ÿ—ก๏ธ " + name + + " strikes for " + dmg + " damage!" + RESET); + } + + @Override + public void heavyAttack(Entity target) + { + if (mp < HEAVY_COST) { + System.out.println(RED + "โŒ Not enough MP!" + RESET); + return; + } + + mp -= HEAVY_COST; + int dmg = weapon.getDamage() + 30; + target.takeDamage(dmg); + + System.out.println(PURPLE + "โšก Shadow Slash deals " + + dmg + " damage!" + RESET); + } + + @Override + public void defendAction() + { + defend(); + System.out.println(BLUE + "๐Ÿ›ก๏ธ Quick dodge stance!" + RESET); + } + + @Override + public void healAction() + { + heal(20); + System.out.println(GREEN + "๐Ÿ’– " + name + + " uses bandage restoring 20 HP!" + RESET); + } + + @Override + public void specialAbility(Entity target) + { + if (mp < SPECIAL_COST) + { + System.out.println(RED + "โŒ Not enough MP!" + RESET); + return; + } + + mp -= SPECIAL_COST; + + setInvisible(true); + + int dmg = weapon.getDamage() + 50; + target.takeDamage(dmg); + + System.out.println(BLUE + "๐ŸŒ‘ SHADOW STRIKE deals " + + dmg + " damage!" + RESET); + + System.out.println(YELLOW + "๐Ÿ‘ค " + name + + " becomes INVISIBLE!" + RESET); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/players/ICombatActions.java b/Java-Knight/src/main/java/org/project/entity/players/ICombatActions.java new file mode 100644 index 0000000..d06a014 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/players/ICombatActions.java @@ -0,0 +1,22 @@ +package org.project.entity.players; + +import org.project.entity.Entity; + +public interface ICombatActions +{ + + // 1. Light Attack + void lightAttack(Entity target); + + // 2. Heavy Attack + void heavyAttack(Entity target); + + // 3. Defend + void defendAction(); + + // 4. Heal + void healAction(); + + // 5. Special Ability + void specialAbility(Entity target); +} diff --git a/Java-Knight/src/main/java/org/project/entity/players/Knight.java b/Java-Knight/src/main/java/org/project/entity/players/Knight.java index 14d8fa2..fe46714 100644 --- a/Java-Knight/src/main/java/org/project/entity/players/Knight.java +++ b/Java-Knight/src/main/java/org/project/entity/players/Knight.java @@ -1,6 +1,101 @@ package org.project.entity.players; -// TODO: UPDATE IMPLEMENTATION -public class Knight { - // TODO: DESIGN KNIGHT'S WEAPON AND ARMOR AND IMPLEMENT THE CONSTRUCTOR -} +import org.project.entity.Entity; +import org.project.item.armors.KnightArmor; +import org.project.item.weapons.Sword; + +public class Knight extends Player { + + private static final int LIGHT_BONUS = 15; + private static final int HEAVY_COST = 10; + private static final int SPECIAL_COST = 25; + + private static final String RESET = "\u001B[0m"; + private static final String RED = "\u001B[31m"; + private static final String GREEN = "\u001B[32m"; + private static final String YELLOW = "\u001B[33m"; + private static final String BLUE = "\u001B[34m"; + private static final String PURPLE = "\u001B[35m"; + + public Knight(String name) + { + super(name, 150, 40, new Sword()); + new KnightArmor(); + } + + @Override + public void lightAttack(Entity target) + { + int dmg = weapon.getDamage() + LIGHT_BONUS; + target.takeDamage(dmg); + + ((Sword) weapon).addCharge(1); + + System.out.println( + YELLOW + "โš”๏ธ " + name + + " slashes the enemy for " + dmg + " damage!" + + RESET + ); + } + + @Override + public void heavyAttack(Entity target) + { + if (mp < HEAVY_COST) + { + System.out.println(RED + "โŒ Not enough MP for heavy attack!" + RESET); + return; + } + + mp -= HEAVY_COST; + int dmg = weapon.getDamage() + 30; + target.takeDamage(dmg); + + ((Sword) weapon).addCharge(2); + + System.out.println(PURPLE + "๐Ÿ’ฅ " + name + + " performs a HEAVY STRIKE for " + dmg + " damage!" + RESET); + } + + @Override + public void defendAction() + { + defend(); + System.out.println(BLUE + "๐Ÿ›ก๏ธ " + name + + " raises his shield!" + RESET); + } + + @Override + public void healAction() + { + heal(30); + System.out.println(GREEN + "๐Ÿ’– " + name + + " heals for 30 HP!" + RESET); + } + + @Override + public void specialAbility(Entity target) + { + if (mp < SPECIAL_COST) + { + System.out.println(RED + "โŒ Not enough MP!" + RESET); + return; + } + + mp -= SPECIAL_COST; + + int dmg = weapon.getDamage() + 45; + target.takeDamage(dmg); + target.setStunned(true); + + ((Sword) weapon).addCharge(3); + + System.out.println( + BLUE + "๐ŸŒ‹ " + name + + " uses EARTH SHATTERING STRIKE dealing " + dmg + " damage!" + + RESET + ); + + System.out.println(YELLOW + "โš ๏ธ The enemy is STUNNED!" + RESET); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/players/Player.java b/Java-Knight/src/main/java/org/project/entity/players/Player.java index ff5385c..f5ec8e0 100644 --- a/Java-Knight/src/main/java/org/project/entity/players/Player.java +++ b/Java-Knight/src/main/java/org/project/entity/players/Player.java @@ -1,89 +1,159 @@ package org.project.entity.players; import org.project.entity.Entity; -import org.project.item.armors.Armor; import org.project.item.weapons.Weapon; -// TODO: UPDATE IMPLEMENTATION -public abstract class Player { +import java.io.Serializable; + +public abstract class Player implements Entity, ICombatActions, Serializable +{ + private static final long serialVersionUID = 1L; + protected String name; - Weapon weapon; - Armor armor; - private int hp; - private int maxHP; - private int mp; - private int maxMP; + protected int hp, maxHP; + protected int mp, maxMP; + protected int level = 1; + protected int xp = 0; - public Player(String name, int hp, int mp, Weapon weapon, Armor armor) { + protected boolean stunned = false; + protected boolean invisible = false; + protected boolean defending = false; + + private boolean goblinKey = false; + private boolean skeletonKey = false; + private boolean vampireKey = false; + + protected Weapon weapon; + + private static final String RESET = "\u001B[0m"; + private static final String RED = "\u001B[31m"; + private static final String GREEN = "\u001B[32m"; + private static final String YELLOW = "\u001B[33m"; + private static final String BLUE = "\u001B[34m"; + private static final String PURPLE = "\u001B[35m"; + + public Player(String name, int maxHP, int maxMP, Weapon weapon) + { this.name = name; - this.hp = hp; - this.mp = mp; - + this.maxHP = maxHP; + this.hp = maxHP; + this.maxMP = maxMP; + this.mp = maxMP; this.weapon = weapon; - this.armor = armor; } @Override - public void attack(Entity target) { - target.takeDamage(weapon.getDamage()); + public void attack(Entity target) + { + lightAttack(target); } @Override - public void defend() { - // TODO - } - - - @Override - public void takeDamage(int damage) { - hp -= damage - armor.getDefense(); + public void defend() + { + defending = true; + System.out.println(BLUE + "๐Ÿ›ก๏ธ " + name + " is defending!" + RESET); } @Override - public void heal(int health) { - hp += health; - if (hp > maxHP) { + public void heal(int amount) + { + hp = Math.min(maxHP, hp + amount); + } + + @Override + public void fillMana(int amount) + { + mp = Math.min(maxMP, mp + amount); + } + + @Override + public void takeDamage(int damage) + { + if (defending) + { + damage /= 2; + defending = false; + } + hp = Math.max(0, hp - damage); + System.out.println(RED + "๐Ÿ’ฅ " + name + " took " + damage + " damage!" + RESET); + } + + @Override + public int getHP() { return hp; } + @Override + public int getMP() { return mp; } + @Override + public int getMaxHP() { return maxHP; } + @Override + public int getMaxMP() { return maxMP; } + @Override + public int getLevel() { return level; } + @Override + public String getName() { return name; } + + @Override + public void setStunned(boolean v) { stunned = v; } + @Override + public boolean isStunned() { return stunned; } + + @Override + public void setInvisible(boolean v) { invisible = v; } + @Override + public boolean isInvisible() { return invisible; } + + @Override + public boolean isAlive() { return hp > 0; } + + @Override + public void gainXP(int xp) + { + this.xp += xp; + if (this.xp >= level * 100) + { + level++; + this.xp = 0; + maxHP += 10; + maxMP += 5; hp = maxHP; - } - } - - @Override - public void fillMana(int mana) { - mp += mana; - if (mp > maxMP) { mp = maxMP; + + System.out.println(GREEN + "โญ " + name + " leveled up to level " + level + "!" + RESET); } } + public boolean hasGoblinKey() { return goblinKey; } + public boolean hasSkeletonKey() { return skeletonKey; } + public boolean hasVampireKey() { return vampireKey; } - public String getName() { - return name; + public void obtainGoblinKey() { goblinKey = true; } + public void obtainSkeletonKey() { skeletonKey = true; } + public void obtainVampireKey() { vampireKey = true; } + + public boolean hasAllKeys() + { + return goblinKey && skeletonKey && vampireKey; } - public int getHp() { - return hp; + public void resetKeys() + { + goblinKey = false; + skeletonKey = false; + vampireKey = false; } - @Override - public int getMaxHP() { - return maxHP; + public void setHealth(int hp) + { + this.hp = Math.min(hp, maxHP); } - public int getMp() { - return mp; + public void setMana(int mp) + { + this.mp = Math.min(mp, maxMP); } - @Override - public int getMaxMP() { - return maxMP; + public int getXP() + { + return xp; } - - public Weapon getWeapon() { - return weapon; - } - - public Armor getArmor() { - return armor; - } - -} +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/entity/players/Wizard.java b/Java-Knight/src/main/java/org/project/entity/players/Wizard.java new file mode 100644 index 0000000..d3decf5 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/players/Wizard.java @@ -0,0 +1,96 @@ +package org.project.entity.players; + +import org.project.entity.Entity; +import org.project.item.weapons.BasicWeapon; + +public class Wizard extends Player +{ + + private static final int LIGHT_COST = 5; + private static final int HEAVY_COST = 15; + private static final int SPECIAL_COST = 30; + + private static final String RESET = "\u001B[0m"; + private static final String RED = "\u001B[31m"; + private static final String GREEN = "\u001B[32m"; + private static final String YELLOW = "\u001B[33m"; + private static final String BLUE = "\u001B[34m"; + private static final String PURPLE = "\u001B[35m"; + + public Wizard(String name) { + super(name, 100, 120, new BasicWeapon("Magic Staff", 20)); + } + + @Override + public void lightAttack(Entity target) + { + if (mp < LIGHT_COST) + { + System.out.println(RED + "โŒ Not enough MP!" + RESET); + return; + } + + mp -= LIGHT_COST; + int dmg = weapon.getDamage() + 10; + target.takeDamage(dmg); + + System.out.println(YELLOW + "โœจ " + name + " casts Magic Bolt for " + dmg + " damage!" + RESET); + } + + @Override + public void heavyAttack(Entity target) + { + if (mp < HEAVY_COST) + { + System.out.println(RED + "โŒ Not enough MP!" + RESET); + return; + } + + mp -= HEAVY_COST; + int dmg = weapon.getDamage() + 35; + target.takeDamage(dmg); + + System.out.println(PURPLE + "๐Ÿ”ฅ " + name + + " casts FIREBALL for " + dmg + " damage!" + RESET); + } + + @Override + public void defendAction() + { + defend(); + System.out.println(BLUE + "๐Ÿ”ฎ Magical barrier activated!" + RESET); + } + + @Override + public void healAction() + { + if (mp < 20) + { + System.out.println(RED + "โŒ Not enough MP to heal!" + RESET); + return; + } + + mp -= 20; + heal(40); + System.out.println(GREEN + "๐Ÿ’– " + name + + " casts HEAL restoring 40 HP!" + RESET); + } + + @Override + public void specialAbility(Entity target) + { + if (mp < SPECIAL_COST) + { + System.out.println(RED + "โŒ Not enough MP!" + RESET); + return; + } + + mp -= SPECIAL_COST; + + int dmg = weapon.getDamage() + 60; + target.takeDamage(dmg); + + System.out.println(BLUE + "๐ŸŒช๏ธ ARCANE BURST hits for " + + dmg + " damage!" + RESET); + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/Item.java b/Java-Knight/src/main/java/org/project/item/Item.java index 6d6b5ad..13d746e 100644 --- a/Java-Knight/src/main/java/org/project/item/Item.java +++ b/Java-Knight/src/main/java/org/project/item/Item.java @@ -2,10 +2,14 @@ package org.project.item; import org.project.entity.Entity; -public interface Item { +public interface Item +{ void use(Entity target); - /* - TODO: ADD OTHER REQUIRED AND BONUS METHODS - */ + String getName(); + + String getDescription(); + + int getValue(); + } diff --git a/Java-Knight/src/main/java/org/project/item/armors/Armor.java b/Java-Knight/src/main/java/org/project/item/armors/Armor.java index 7ca8774..640d60d 100644 --- a/Java-Knight/src/main/java/org/project/item/armors/Armor.java +++ b/Java-Knight/src/main/java/org/project/item/armors/Armor.java @@ -7,36 +7,67 @@ public abstract class Armor { private int durability; private int maxDurability; - private boolean isBroke; + private boolean isBroken; public Armor(int defense, int durability) { this.defense = defense; + this.maxDefense = defense; this.durability = durability; + this.maxDurability = durability; + this.isBroken = false; } - public void checkBreak() { + public void takeHit(int damage) + { + durability -= damage; + + if (durability < 0) + { + durability = 0; + } + + checkBroken(); + } + + public void checkBroken() { if (durability <= 0) { - isBroke = true; + isBroken = true; defense = 0; } } // TODO: (BONUS) UPDATE THE REPAIR METHOD - public void repair() { - isBroke = false; + public void repair() + { + isBroken = false; defense = maxDefense; durability = maxDurability; } - public int getDefense() { + public int getDefense() + { return defense; } - public int getDurability() { + public int getDurability() + { return durability; } - public boolean isBroke() { - return isBroke; + public int getMaxDefense() + { + return maxDefense; } + + public int getMaxDurability() + { + return maxDurability; + } + + public boolean isBroken() + { + return isBroken; + } + + public abstract String getArmorName(); } diff --git a/Java-Knight/src/main/java/org/project/item/armors/KnightArmor.java b/Java-Knight/src/main/java/org/project/item/armors/KnightArmor.java index eb59a46..5601b45 100644 --- a/Java-Knight/src/main/java/org/project/item/armors/KnightArmor.java +++ b/Java-Knight/src/main/java/org/project/item/armors/KnightArmor.java @@ -1,6 +1,16 @@ package org.project.item.armors; -// TODO: UPDATE IMPLEMENTATION -public class KnightArmor { - // TODO: DESIGN ARMOR'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR -} \ No newline at end of file +public class KnightArmor extends Armor +{ + + public KnightArmor() + { + super(30, 100); + } + + @Override + public String getArmorName() + { + return "Knight's Plate Armor"; + } +} diff --git a/Java-Knight/src/main/java/org/project/item/consumables/Consumable.java b/Java-Knight/src/main/java/org/project/item/consumables/Consumable.java index 028e13d..c5b964b 100644 --- a/Java-Knight/src/main/java/org/project/item/consumables/Consumable.java +++ b/Java-Knight/src/main/java/org/project/item/consumables/Consumable.java @@ -1,8 +1,50 @@ package org.project.item.consumables; -// TODO: UPDATE IMPLEMENTATION -public abstract class Consumable { - /* - TODO: ADD OTHER REQUIRED AND BONUS METHODS - */ +import org.project.entity.Entity; + +public abstract class Consumable +{ + + protected String name; + protected String description; + protected int restoreAmount; + protected boolean percentageBased; + + public Consumable(String name, String description, int restoreAmount, boolean percentageBased) + { + this.name = name; + this.description = description; + this.restoreAmount = restoreAmount; + this.percentageBased = percentageBased; + } + + + public abstract void use(Entity target); + + + public String getName() + { + return name; + } + + public int getRestoreAmount() + { + return restoreAmount; + } + + public String getDescription() + { + return description; + } + + public boolean isPercentageBased() + { + return percentageBased; + } + + @Override + public String toString() + { + return name + " (" + description + ")"; + } } diff --git a/Java-Knight/src/main/java/org/project/item/consumables/Flask.java b/Java-Knight/src/main/java/org/project/item/consumables/Flask.java index c0e7a6d..75cbc48 100644 --- a/Java-Knight/src/main/java/org/project/item/consumables/Flask.java +++ b/Java-Knight/src/main/java/org/project/item/consumables/Flask.java @@ -2,15 +2,44 @@ package org.project.item.consumables; import org.project.entity.Entity; -// TODO: UPDATE IMPLEMENTATION -public class Flask { - /* - THIS IS AN EXAMPLE OF A CONSUMABLE DESIGN. - */ +public class Flask extends Consumable +{ + + private static final int HEAL_AMOUNT = 30; + + public Flask() + { + super( + "Health Flask", + "A small flask that restores health.", + HEAL_AMOUNT, + false + ); + } - // TODO: UPDATE USE METHOD @Override - public void use(Entity target) { - target.heal(target.getMaxHP() / 10); + public void use(Entity target) + { + + int healValue; + + if (percentageBased) + { + healValue = target.getMaxHP() * restoreAmount / 100; + } else + { + healValue = restoreAmount; + } + + target.heal(healValue); + + System.out.println( + target.getName() + + " used " + + name + + " and restored " + + healValue + + " HP!" + ); } } diff --git a/Java-Knight/src/main/java/org/project/item/weapons/BasicWeapon.java b/Java-Knight/src/main/java/org/project/item/weapons/BasicWeapon.java new file mode 100644 index 0000000..5d66de1 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/item/weapons/BasicWeapon.java @@ -0,0 +1,20 @@ +package org.project.item.weapons; + +import org.project.entity.Entity; +import java.util.ArrayList; +import java.io.Serializable; + +public class BasicWeapon extends Weapon implements Serializable +{ + + private static final long serialVersionUID = 1L; + + public BasicWeapon(String name, int damage) + { + super(name, damage, 0); + } + + @Override + public void uniqueAbility(ArrayList targets) { + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/weapons/Sword.java b/Java-Knight/src/main/java/org/project/item/weapons/Sword.java index 96226ee..57602f7 100644 --- a/Java-Knight/src/main/java/org/project/item/weapons/Sword.java +++ b/Java-Knight/src/main/java/org/project/item/weapons/Sword.java @@ -1,26 +1,64 @@ package org.project.item.weapons; import org.project.entity.Entity; - import java.util.ArrayList; +import java.io.Serializable; -// TODO: UPDATE IMPLEMENTATION -public class Sword { - /* - THIS IS AN EXAMPLE OF A WEAPON DESIGN. - */ +public class Sword extends Weapon implements Serializable +{ - int abilityCharge; + private static final long serialVersionUID = 1L; - public Sword() { - // TODO: DESIGN SWORD'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR + private int abilityCharge; + private static final int MAX_CHARGE = 10; + private static final int REQUIRED_CHARGE = 5; + + public Sword() + { + super("Knight Sword", 20, 0); + this.abilityCharge = 0; } - // TODO: (BONUS) UPDATE THE UNIQUE ABILITY - public void uniqueAbility(ArrayList targets) { - abilityCharge += 2; - for (Entity target : targets) { - target.takeDamage(getDamage()); + @Override + public void uniqueAbility(ArrayList targets) + { + if (abilityCharge < REQUIRED_CHARGE) + { + System.out.println("โš ๏ธ Not enough charge for special ability! (" + abilityCharge + "/" + REQUIRED_CHARGE + ")"); + return; } + + if (isBroken) + { + System.out.println("โš ๏ธ " + name + " is broken and can't use its special ability!"); + return; + } + + System.out.println("โš”๏ธ " + name + " special ability: Cleave!"); + for (Entity target : targets) + { + if (target != null && target.isAlive()) + { + target.takeDamage((int) (getDamage() * 1.5)); + } + } + + abilityCharge = 0; + reduceDurability(5); } -} + + public void addCharge(int amount) + { + this.abilityCharge = Math.min(this.abilityCharge + amount, MAX_CHARGE); + } + + public int getAbilityCharge() + { + return abilityCharge; + } + + public int getMaxCharge() + { + return MAX_CHARGE; + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/item/weapons/Weapon.java b/Java-Knight/src/main/java/org/project/item/weapons/Weapon.java index cb9fcf2..e84d5c2 100644 --- a/Java-Knight/src/main/java/org/project/item/weapons/Weapon.java +++ b/Java-Knight/src/main/java/org/project/item/weapons/Weapon.java @@ -1,35 +1,87 @@ package org.project.item.weapons; import org.project.entity.Entity; +import java.util.ArrayList; +import java.io.Serializable; -// TODO: UPDATE IMPLEMENTATION -public abstract class Weapon { - private int damage; - private int manaCost; +public abstract class Weapon implements Serializable +{ - /* - TODO: ADD OTHER REQUIRED AND BONUS ATTRIBUTES - */ + private static final long serialVersionUID = 1L; - public Weapon(int damage, int manaCost) { + protected String name; + protected int damage; + protected int manaCost; + protected int level; + protected int durability; + protected boolean isBroken; + + public Weapon(String name, int damage, int manaCost) + { + this.name = name; this.damage = damage; this.manaCost = manaCost; + this.level = 1; + this.durability = 100; + this.isBroken = false; } - @Override - public void use(Entity target) { + public void use(Entity target) + { + if (isBroken) + { + System.out.println("โš ๏ธ " + name + " is broken and can't be used!"); + return; + } + target.takeDamage(damage); + reduceDurability(1); } - public int getDamage() { + public abstract void uniqueAbility(ArrayList targets); + + protected void reduceDurability(int amount) + { + durability = Math.max(0, durability - amount); + if (durability == 0) + { + isBroken = true; + } + } + + public void upgrade() + { + level++; + damage += 5; + System.out.println("๐Ÿ› ๏ธ " + name + " upgraded to level " + level + "!"); + } + + public String getName() { + return name; + } + + public int getDamage() + { return damage; } - public int getManaCost() { + public int getManaCost() + { return manaCost; } - /* - TODO: ADD OTHER REQUIRED AND BONUS METHODS - */ -} + public int getLevel() + { + return level; + } + + public int getDurability() + { + return durability; + } + + public boolean isBroken() + { + return isBroken; + } +} \ No newline at end of file diff --git a/Java-Knight/src/main/java/org/project/location/Location.java b/Java-Knight/src/main/java/org/project/location/Location.java index b0b4b98..d55781f 100644 --- a/Java-Knight/src/main/java/org/project/location/Location.java +++ b/Java-Knight/src/main/java/org/project/location/Location.java @@ -1,28 +1,64 @@ package org.project.location; -import org.project.entity.enemies.Enemy; - +import org.project.entity.enemies.*; +import java.io.Serializable; import java.util.ArrayList; -public class Location { +public class Location implements Serializable +{ + private static final long serialVersionUID = 1L; + private String name; + private String description; + private int difficulty; // 1 = easy, 2 = medium, 3 = hard + private ArrayList connectedLocations; - private ArrayList enemies; - - public Location(ArrayList locations, ArrayList enemies) { - this.locations = locations; - this.enemies = enemies; + public Location(String name, String description, int difficulty) + { + this.name = name; + this.description = description; + this.difficulty = difficulty; + this.connectedLocations = new ArrayList<>(); } - public String getName() { + public void connectLocation(Location location) + { + connectedLocations.add(location); + } + + public ArrayList getConnectedLocations() + { + return connectedLocations; + } + + public String getName() + { return name; } - public ArrayList getLocations() { - return locations; + public int getDifficulty() + { + return difficulty; } - public ArrayList getEnemies() { - return enemies; + public void enter() + { + System.out.println("\n=============================="); + System.out.println("๐Ÿ“ You arrived at: " + name); + System.out.println(description); + System.out.println("Difficulty: " + difficulty); + System.out.println("==============================\n"); + } + + public Enemy spawnEnemy() + { + return switch (name) + { + case "Forest" -> new Goblin(); + case "Graveyard" -> new Skeleton(); + case "Vampire Crypt" -> new Vampire(); + case "Dragon Castle" -> new Dragon(); + default -> new Goblin(); + }; } } diff --git a/Java-Knight/src/main/java/org/project/utils/SaveLoadManager.java b/Java-Knight/src/main/java/org/project/utils/SaveLoadManager.java new file mode 100644 index 0000000..491d61d --- /dev/null +++ b/Java-Knight/src/main/java/org/project/utils/SaveLoadManager.java @@ -0,0 +1,27 @@ +package org.project.utils; + +import org.project.GameState; +import java.io.*; + +public class SaveLoadManager { + + public static void saveGame(GameState gameState, String filename) { + try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) { + oos.writeObject(gameState); + System.out.println("\u001B[34m\u2714\u001B[0m Game saved successfully."); + } catch (IOException e) { + System.out.println("\u001B[31m\u2716\u001B[0m Error saving game: " + e.getMessage()); + } + } + + public static GameState loadGame(String filename) { + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) { + GameState loadedState = (GameState) ois.readObject(); + System.out.println("\u001B[32m\u2714\u001B[0m Game loaded successfully."); + return loadedState; + } catch (IOException | ClassNotFoundException e) { + System.out.println("\u001B[31m\u2716\u001B[0m Error loading game: " + e.getMessage()); + return null; + } + } +} \ No newline at end of file diff --git a/Java-Knight/target/classes/org/project/GameState.class b/Java-Knight/target/classes/org/project/GameState.class new file mode 100644 index 0000000..c62b3ec Binary files /dev/null and b/Java-Knight/target/classes/org/project/GameState.class differ diff --git a/Java-Knight/target/classes/org/project/Main.class b/Java-Knight/target/classes/org/project/Main.class new file mode 100644 index 0000000..6f7bf47 Binary files /dev/null and b/Java-Knight/target/classes/org/project/Main.class differ diff --git a/Java-Knight/target/classes/org/project/combat/CombatSystem.class b/Java-Knight/target/classes/org/project/combat/CombatSystem.class new file mode 100644 index 0000000..160abbe Binary files /dev/null and b/Java-Knight/target/classes/org/project/combat/CombatSystem.class differ diff --git a/Java-Knight/target/classes/org/project/entity/Entity.class b/Java-Knight/target/classes/org/project/entity/Entity.class new file mode 100644 index 0000000..6d6853d Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/Entity.class differ diff --git a/Java-Knight/target/classes/org/project/entity/enemies/Dragon.class b/Java-Knight/target/classes/org/project/entity/enemies/Dragon.class new file mode 100644 index 0000000..ed569b1 Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/enemies/Dragon.class differ diff --git a/Java-Knight/target/classes/org/project/entity/enemies/Enemy.class b/Java-Knight/target/classes/org/project/entity/enemies/Enemy.class new file mode 100644 index 0000000..f247d0a Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/enemies/Enemy.class differ diff --git a/Java-Knight/target/classes/org/project/entity/enemies/Goblin.class b/Java-Knight/target/classes/org/project/entity/enemies/Goblin.class new file mode 100644 index 0000000..2319d28 Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/enemies/Goblin.class differ diff --git a/Java-Knight/target/classes/org/project/entity/enemies/Skeleton.class b/Java-Knight/target/classes/org/project/entity/enemies/Skeleton.class new file mode 100644 index 0000000..ff52539 Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/enemies/Skeleton.class differ diff --git a/Java-Knight/target/classes/org/project/entity/enemies/Vampire.class b/Java-Knight/target/classes/org/project/entity/enemies/Vampire.class new file mode 100644 index 0000000..73dcc22 Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/enemies/Vampire.class differ diff --git a/Java-Knight/target/classes/org/project/entity/players/Assassin.class b/Java-Knight/target/classes/org/project/entity/players/Assassin.class new file mode 100644 index 0000000..7b7d492 Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/players/Assassin.class differ diff --git a/Java-Knight/target/classes/org/project/entity/players/ICombatActions.class b/Java-Knight/target/classes/org/project/entity/players/ICombatActions.class new file mode 100644 index 0000000..8f1cdee Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/players/ICombatActions.class differ diff --git a/Java-Knight/target/classes/org/project/entity/players/Knight.class b/Java-Knight/target/classes/org/project/entity/players/Knight.class new file mode 100644 index 0000000..3ed14f7 Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/players/Knight.class differ diff --git a/Java-Knight/target/classes/org/project/entity/players/Player.class b/Java-Knight/target/classes/org/project/entity/players/Player.class new file mode 100644 index 0000000..5663e67 Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/players/Player.class differ diff --git a/Java-Knight/target/classes/org/project/entity/players/Wizard.class b/Java-Knight/target/classes/org/project/entity/players/Wizard.class new file mode 100644 index 0000000..233a7ba Binary files /dev/null and b/Java-Knight/target/classes/org/project/entity/players/Wizard.class differ diff --git a/Java-Knight/target/classes/org/project/item/Item.class b/Java-Knight/target/classes/org/project/item/Item.class new file mode 100644 index 0000000..f4b4c63 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/Item.class differ diff --git a/Java-Knight/target/classes/org/project/item/armors/Armor.class b/Java-Knight/target/classes/org/project/item/armors/Armor.class new file mode 100644 index 0000000..fbe477e Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/armors/Armor.class differ diff --git a/Java-Knight/target/classes/org/project/item/armors/KnightArmor.class b/Java-Knight/target/classes/org/project/item/armors/KnightArmor.class new file mode 100644 index 0000000..5c0336c Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/armors/KnightArmor.class differ diff --git a/Java-Knight/target/classes/org/project/item/consumables/Consumable.class b/Java-Knight/target/classes/org/project/item/consumables/Consumable.class new file mode 100644 index 0000000..dcbf719 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/consumables/Consumable.class differ diff --git a/Java-Knight/target/classes/org/project/item/consumables/Flask.class b/Java-Knight/target/classes/org/project/item/consumables/Flask.class new file mode 100644 index 0000000..f2ab205 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/consumables/Flask.class differ diff --git a/Java-Knight/target/classes/org/project/item/weapons/BasicWeapon.class b/Java-Knight/target/classes/org/project/item/weapons/BasicWeapon.class new file mode 100644 index 0000000..5a42d70 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/weapons/BasicWeapon.class differ diff --git a/Java-Knight/target/classes/org/project/item/weapons/Sword.class b/Java-Knight/target/classes/org/project/item/weapons/Sword.class new file mode 100644 index 0000000..69b4011 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/weapons/Sword.class differ diff --git a/Java-Knight/target/classes/org/project/item/weapons/Weapon.class b/Java-Knight/target/classes/org/project/item/weapons/Weapon.class new file mode 100644 index 0000000..bc426d9 Binary files /dev/null and b/Java-Knight/target/classes/org/project/item/weapons/Weapon.class differ diff --git a/Java-Knight/target/classes/org/project/location/Location.class b/Java-Knight/target/classes/org/project/location/Location.class new file mode 100644 index 0000000..eea067f Binary files /dev/null and b/Java-Knight/target/classes/org/project/location/Location.class differ diff --git a/Java-Knight/target/classes/org/project/utils/SaveLoadManager.class b/Java-Knight/target/classes/org/project/utils/SaveLoadManager.class new file mode 100644 index 0000000..a9b5a35 Binary files /dev/null and b/Java-Knight/target/classes/org/project/utils/SaveLoadManager.class differ diff --git a/README1.md b/README1.md new file mode 100644 index 0000000..dd351dd --- /dev/null +++ b/README1.md @@ -0,0 +1,162 @@ +# โš”๏ธ Java Knight: The Legend of Javanest + +![Java Version](https://img.shields.io/badge/Java-17%2B-orange?style=for-the-badge&logo=java) +![License](https://img.shields.io/badge/License-MIT-green?style=for-the-badge) +![Game Type](https://img.shields.io/badge/Game-Text--Based%20RPG-blue?style=for-the-badge) + +**Java Knight** is a text-based RPG game developed in Java. +Embark on an epic adventure through the lands of **Javanest**, battle dangerous enemies, collect ancient keys, and face the ultimate **Dragon Boss** to save the kingdom. + +--- + +## ๐ŸŒŸ Core Features + +- ๐ŸŽญ **Multiple Playable Classes** (Knight, Wizard, Assassin) +- ๐Ÿ—บ๏ธ **Location-Based Exploration System** +- โš”๏ธ **Turn-Based Combat Mechanics** +- ๐Ÿ”‘ **Key Collection & Progression System** +- ๐Ÿ’พ **Save / Load Ready (Java Serialization)** +- ๐Ÿ“Š **RPG Systems**: HP, MP, XP, Levels +- ๐Ÿ›ก๏ธ **Weapons, Armor & Durability** +- ๐Ÿ‰ **Final Boss Battle** + +--- + +## ๐Ÿ›ก๏ธ Playable Classes + +| Class | HP | MP | Starting Weapon | Playstyle | +|------|----|----|----------------|-----------| +| **Knight** | High | Low | Sword | Tank / Physical Damage | +| **Wizard** | Medium | High | Magic Staff | Magic & Healing | +| **Assassin** | Medium | Medium | Daggers | Stealth & Burst Damage | + +Each class has **unique abilities**, different mana costs, and a distinct combat style. + +--- + +## ๐Ÿ—บ๏ธ World Map + +Explore the dangerous regions of Javanest: + +1. **Forest (Difficulty 1)** + _A dark forest full of Goblins._ + +2. **Graveyard (Difficulty 2)** + _An abandoned graveyard haunted by Skeletons._ + +3. **Vampire Crypt (Difficulty 3)** + _A cursed crypt ruled by Vampires._ + +4. **Dragon Castle (Difficulty 4)** + _The final destination and home of the Dragon._ + +Locations are connected, allowing the player to move freely between unlocked areas. + +--- + +## ๐ŸŽฎ Game Flow + +1. Start the game +2. Enter your player name +3. Choose a class +4. Begin in the **Forest** +5. Fight enemies and gain XP +6. Collect special keys +7. Unlock the **Dragon Castle** +8. Defeat the Dragon and save Javanest + +--- + +## ๐Ÿงญ Main Menu + +At launch, the player is presented with the main menu: +```text +=============================== +โš” JAVA KNIGHT โš” +=============================== +1. Start Game +2. How To Play +3. Exit +Menu Options +Start Game โ€“ Begin a new adventure +How To Play โ€“ Learn the rules and objective +Exit โ€“ Close the game +๐Ÿฐ In-Game Menu +While exploring a location, the player can choose: + +text +1. Fight Enemy +2. Move Location +3. Enter Dragon Castle (if unlocked) +Fight Enemy โ€“ Starts a battle based on the current location +Move Location โ€“ Travel to connected locations +Enter Dragon Castle โ€“ Available only after collecting all keys +โš”๏ธ Combat System +Combat is turn-based and class-dependent. + +Available Actions +Light Attack +Heavy Attack +Defend +Heal +Special Ability +Exit Battle +Combat Rules +Attacks may consume MP +Special abilities are unique per class +Enemies attack after the playerโ€™s turn +Winning a battle grants XP +Enemies may drop keys +๐Ÿ”‘ Key System +To unlock the final area, the player must collect: + +๐Ÿ—๏ธ Goblin Key +๐Ÿ—๏ธ Skeleton Key +๐Ÿ—๏ธ Vampire Key +Each key drops from enemies in its respective location. + +Once all keys are collected, the Dragon Castle becomes accessible. + +๐Ÿ“ˆ Progression System +HP (Health Points) +MP (Mana Points) +XP (Experience Points) +Level System +Weapon Durability +Progression rewards strategic combat and exploration. + +๐Ÿ’พ Save & Load System +The project is prepared for game saving using Java Serialization. + +Serializable Components +Player +Location +Weapon +GameState +This allows the game to be saved and restored at any point. + +๐Ÿš€ Getting Started +Requirements +Java JDK 17 or higher +Terminal or Java IDE (IntelliJ IDEA, Eclipse, VS Code) +Run the Game +bash +javac -d out src/org/project/**/*.java +java -cp out org.project.Main +Or simply run Main.java from your IDE. + +๐Ÿ› ๏ธ Project Architecture +Object-Oriented Design +Clean separation of concerns +Interfaces & abstract classes +Easily extendable structure +Console-based UI with ANSI colors +๐Ÿ”ฎ Future Improvements +Inventory management menu +More weapons and consumables +Enhanced armor mechanics +Expanded world map +Graphical UI (JavaFX / Swing) +๐Ÿ“œ License +This project is licensed under the MIT License. +