From 0fb22c9db1e42e78063582ba938b5f46fec0ac4a Mon Sep 17 00:00:00 2001 From: Romina Date: Tue, 12 May 2026 00:48:33 +0330 Subject: [PATCH] Java-Knight --- .../src/main/java/org/project/Main.java | 382 +++++++++++++++++- .../main/java/org/project/entity/Entity.java | 20 +- .../org/project/entity/enemies/Dragon.java | 30 ++ .../org/project/entity/enemies/Enemy.java | 81 +++- .../org/project/entity/enemies/Goblin.java | 30 ++ .../org/project/entity/enemies/Skeleton.java | 16 +- .../org/project/entity/enemies/Vampire.java | 24 ++ .../org/project/entity/players/Knight.java | 15 +- .../org/project/entity/players/Player.java | 143 ++++--- .../src/main/java/org/project/item/Item.java | 9 +- .../java/org/project/item/armors/Armor.java | 68 +++- .../org/project/item/armors/KnightArmor.java | 27 +- .../project/item/consumables/Consumable.java | 33 +- .../org/project/item/consumables/Flask.java | 19 +- .../java/org/project/item/weapons/Sword.java | 45 ++- .../java/org/project/item/weapons/Weapon.java | 81 +++- .../java/org/project/location/Location.java | 45 ++- Readme_Pictures/MyREADME.md | 188 +++++++++ 18 files changed, 1058 insertions(+), 198 deletions(-) create mode 100644 Java-Knight/src/main/java/org/project/entity/enemies/Dragon.java create mode 100644 Java-Knight/src/main/java/org/project/entity/enemies/Goblin.java create mode 100644 Java-Knight/src/main/java/org/project/entity/enemies/Vampire.java create mode 100644 Readme_Pictures/MyREADME.md diff --git a/Java-Knight/src/main/java/org/project/Main.java b/Java-Knight/src/main/java/org/project/Main.java index 6bde20e..46ddd15 100644 --- a/Java-Knight/src/main/java/org/project/Main.java +++ b/Java-Knight/src/main/java/org/project/Main.java @@ -1,15 +1,379 @@ -package org.project; +package org.project.main; -import org.project.location.Location; +import org.project.entity.Entity; +import org.project.entity.players.Knight; +import org.project.entity.enemies.*; // import همه دشمنان +import org.project.location.Location; // import کلاس Location -import java.util.ArrayList; -import java.util.List; +import java.util.*; -public class Main { - public static void main(String[] args) { - // TODO: ADD LOCATIONS TO YOUR GAME - List locations = new ArrayList<>(); +public class Main +{ + private static final Scanner scanner = new Scanner(System.in); + private static final Random random = new Random(); + private static Knight player; + private static List gameLocations = new ArrayList<>(); + private static Location currentLocation; + private static Set keys = new HashSet<>(); + private static boolean castleUnlocked = false; - // TODO: IMPLEMENT GAMEPLAY + public static void main(String[] args) + { + System.out.println("Welcome to Java Knight RPG!"); + System.out.print("Enter your hero's name: "); + String name = scanner.nextLine(); + player = new Knight(name); + + initializeLocations(); + if (!gameLocations.isEmpty()) + { + currentLocation = gameLocations.get(0); + System.out.println("Your adventure begins in the " + currentLocation.getName() + "!"); + } + else + { + System.out.println("Error: No locations initialized. Exiting."); + System.exit(1); + } + + gameLoop(); + } + + private static void initializeLocations() + { + Location forest = new Location(new ArrayList<>(), new ArrayList<>()); + forest.setName("Dark Forest"); + + Location cave = new Location(new ArrayList<>(), new ArrayList<>()); + cave.setName("Mysterious Cave"); + + Location castle = new Location(new ArrayList<>(), new ArrayList<>()); + castle.setName("Dragon's Castle"); + + forest.addEnemy(new Goblin()); + forest.addEnemy(new Skeleton()); + + cave.addEnemy(new Vampire()); + cave.addEnemy(new Skeleton()); + + forest.addAdjacentLocation(cave); + cave.addAdjacentLocation(forest); + cave.addAdjacentLocation(castle); + castle.addAdjacentLocation(cave); + + gameLocations.add(forest); + gameLocations.add(cave); + gameLocations.add(castle); + } + + private static void gameLoop() + { + while (true) + { + if (currentLocation != null && currentLocation.hasLivingEnemies()) + { + System.out.println("\n\u001B[33mEnemies detected in " + currentLocation.getName() + "!\u001B[0m"); + } + + System.out.println("\n====== Main Menu ======"); + if (currentLocation != null) + { + System.out.println("Current Location: " + currentLocation.getName()); + } + else + { + System.out.println("Current Location: Unknown"); + } + System.out.println("1. Fight enemy"); + System.out.println("2. Move to another location"); + if (castleUnlocked) + { + System.out.println("3. Enter the Castle (Final Boss)"); + } + else + { + System.out.println("3. Enter the Castle (Locked - Collect all keys!)"); + } + System.out.println("4. Show player info"); + System.out.println("5. Exit game"); + System.out.print("Choose an option: "); + + int choice = readInt(1, 5); + switch (choice) + { + case 1 -> + { + if (currentLocation != null && currentLocation.hasLivingEnemies()) + { + fightEnemy(); + } + else + { + System.out.println("No enemies here to fight."); + } + } + case 2 -> moveLocation(); + case 3 -> + { + if (currentLocation != null && currentLocation.getName().equals("Dragon's Castle") && castleUnlocked) + { + fightBoss(); + } + else if (castleUnlocked) + { + System.out.println("You must be at the Castle entrance to enter."); + } + else + { + System.out.println("You need to collect all keys before entering the Castle."); + } + } + case 4 -> showPlayerInfo(); + case 5 -> + { + System.out.println("Thanks for playing! Goodbye."); + scanner.close(); + System.exit(0); + } + } + } + } + + private static void fightEnemy() + { + if (currentLocation == null || !currentLocation.hasLivingEnemies()) + { + System.out.println("No enemies here to fight."); + return; + } + + Enemy enemy = null; + for (Enemy e : currentLocation.getEnemies()) + { + if (e.isAlive()) + { + enemy = e; + break; + } + } + + if (enemy == null) + { + System.out.println("No living enemies found."); + return; + } + + System.out.println("\nA wild " + enemy.getName() + " appears!"); + + boolean playerTurn = true; + while (player.isAlive() && enemy.isAlive()) + { + printStatus(player, enemy); + if (playerTurn) + { + System.out.println("\nYour turn! Choose action:"); + System.out.println("1. Attack"); + System.out.println("2. Defend"); + System.out.print("Option: "); + int act = readInt(1, 2); + if (act == 1) + { + player.attack(enemy); + } + else + { + player.defend(); + } + } + else + { + enemy.attack(player); + } + playerTurn = !playerTurn; + } + + if (!player.isAlive()) + { + System.out.println("\u001B[31mYou died! Game over.\u001B[0m"); + scanner.close(); + System.exit(0); + } + else + { + System.out.println("\u001B[32mYou defeated " + enemy.getName() + "!\u001B[0m"); + + tryDropKey(enemy); + + int xpGain = getXPGain(enemy); + player.addXP(xpGain); + player.checkLevelUp(); + + player.setHP(player.getMaxHP()); + player.setMP(player.getMaxMP()); + System.out.println("\u001B[36mYour HP and MP are fully restored.\u001B[0m"); + + currentLocation.getEnemies().remove(enemy); + } + } + + private static void moveLocation() + { + if (currentLocation == null) + { + System.out.println("You are in an unknown location."); + return; + } + + ArrayList adjacent = currentLocation.getLocations(); + if (adjacent == null || adjacent.isEmpty()) + { + System.out.println("There are no other locations connected to this place."); + return; + } + + System.out.println("\nAvailable locations to move:"); + for (int i = 0; i < adjacent.size(); i++) + { + System.out.println((i + 1) + ". " + adjacent.get(i).getName()); + } + System.out.print("Choose a location to move to (or 0 to cancel): "); + int choice = readInt(0, adjacent.size()); + if (choice == 0) + { + System.out.println("Movement cancelled."); + return; + } + + currentLocation = adjacent.get(choice - 1); + System.out.println("You moved to " + currentLocation.getName()); + + if (currentLocation.hasLivingEnemies()) + { + System.out.println("\u001B[33mWatch out! There are enemies here.\u001B[0m"); + } + } + + private static void fightBoss() + { + if (currentLocation == null || !currentLocation.getName().equals("Dragon's Castle")) + { + System.out.println("You must be in the Dragon's Castle to fight the boss."); + return; + } + + Dragon dragon = new Dragon(); + System.out.println("\nYou enter the Dragon's Lair!"); + + boolean playerTurn = true; + while (player.isAlive() && dragon.isAlive()) + { + printStatus(player, dragon); + if (playerTurn) + { + System.out.println("\nYour turn! Choose action:"); + System.out.println("1. Attack"); + System.out.println("2. Defend"); + System.out.print("Option: "); + int act = readInt(1, 2); + if (act == 1) + { + player.attack(dragon); + } + else + { + player.defend(); + } + } + else + { + dragon.attack(player); + } + playerTurn = !playerTurn; + } + + if (player.isAlive()) + { + System.out.println("\u001B[32mCongratulations! You defeated the Dragon and won the game!\u001B[0m"); + scanner.close(); + System.exit(0); + } + else + { + System.out.println("\u001B[31mYou died fighting the Dragon. Game over.\u001B[0m"); + scanner.close(); + System.exit(0); + } + } + + private static void showPlayerInfo() + { + System.out.println("\n--- Player Info ---"); + System.out.println("Name: " + player.getName()); + System.out.println("Level: " + player.level); + System.out.println("XP: " + player.xp + " / " + player.xpToNextLevel); + System.out.println("HP: " + player.getHP() + "/" + player.getMaxHP()); + System.out.println("MP: " + player.getMP() + "/" + player.getMaxMP()); + System.out.println("Keys collected: " + keys); + } + + private static int readInt(int min, int max) + { + int input; + while (true) + { + try + { + input = Integer.parseInt(scanner.nextLine()); + if (input < min || input > max) + { + throw new NumberFormatException("Input out of bounds."); + } + break; + } + catch (NumberFormatException e) + { + System.out.print("Invalid input. Please enter a number between " + min + " and " + max + ": "); + } + } + return input; + } + + private static void tryDropKey(Entity enemy) + { + double dropChance = 0.20; + String enemyName = enemy.getName(); + + if (keys.contains(enemyName + " Key")) {return;} + + if (random.nextDouble() < dropChance) + { + keys.add(enemyName + " Key"); + System.out.println("\u001B[36mYou obtained the " + enemyName + " Key!\u001B[0m"); + } + + if (keys.contains("Goblin Key") && keys.contains("Skeleton Key") && keys.contains("Vampire Key")) + { + castleUnlocked = true; + System.out.println("\u001B[35mAll keys collected! The Castle is now unlocked!\u001B[0m"); + } + } + + private static int getXPGain(Entity enemy) + { + return switch (enemy.getName()) + { + case "Goblin" -> 50; + case "Skeleton" -> 40; + case "Vampire" -> 60; + case "Dragon" -> 500; + default -> 50; + }; + } + + private static void printStatus(Entity player, Entity enemy) + { + System.out.println("\n[player HP: " + player.getHP() + " / " + player.getMaxHP() + + " | MP: " + player.getMP() + " / " + player.getMaxMP() + "]"); + System.out.println("[enemy HP: " + enemy.getHP() + " / " + enemy.getMaxHP() + "]"); } } \ 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..87a553f 100644 --- a/Java-Knight/src/main/java/org/project/entity/Entity.java +++ b/Java-Knight/src/main/java/org/project/entity/Entity.java @@ -1,21 +1,15 @@ package org.project.entity; -public interface Entity { +public interface Entity +{ void attack(Entity target); - void defend(); - - void heal(int health); - - void fillMana(int mana); - void takeDamage(int damage); - + boolean isAlive(); + int getHP(); int getMaxHP(); - + void setHP(int hp); + int getMP(); int getMaxMP(); - - /* - TODO: ADD OTHER REQUIRED AND BONUS METHODS - */ + void setMP(int mp); } 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..5446379 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Dragon.java @@ -0,0 +1,30 @@ +package org.project.entity.enemies; + +public class Dragon extends Enemy +{ + + public Dragon() + { + super("Dragon", 200, 100); + } + + @Override + public void attack(Entity target) + { + int damage = 40; + System.out.println(name + " breathes fire for " + damage + " damage ignoring defense!"); + + if (target instanceof Player) + { + Player p = (Player) target; + p.setHP(p.getHP() - damage); + if (p.getHP() < 0) + p.setHP(0); + System.out.println(target.getName() + " takes " + damage + " damage!"); + } + else + { + target.takeDamage(damage); + } + } +} \ 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..160eefa 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,75 @@ package org.project.entity.enemies; -import org.project.item.weapons.Weapon; +import org.project.entity.Entity; -// TODO: UPDATE IMPLEMENTATION -public abstract class Enemy { - Weapon weapon; - private int hp; - private int mp; +public abstract class Enemy implements Entity +{ + protected String name; - public Enemy(int hp, int mp, Weapon weapon) { - this.hp = hp; - this.mp = mp; + protected int hp; + protected int maxHP; + protected int mp; + protected int maxMP; + protected boolean defending; - this.weapon = weapon; + public Enemy(String name, int maxHP, int maxMP) + { + this.name = name; + this.maxHP = maxHP; + this.hp = maxHP; + this.maxMP = maxMP; + this.mp = maxMP; + this.defending = false; } @Override - public void takeDamage(int damage) { + public boolean isAlive() {return hp > 0;} + + @Override + public int getHP() {return hp;} + + @Override + public int getMaxHP() {return maxHP;} + + @Override + public void setHP(int hp) {this.hp = Math.min(hp, maxHP);} + + @Override + public int getMP() {return mp;} + + @Override + public int getMaxMP() {return maxMP;} + + @Override + public void setMP(int mp) {this.mp = Math.min(mp, maxMP);} + + @Override + public void defend() + { + defending = true; + System.out.println(name + " is defending and will reduce damage next turn."); + } + + @Override + public void takeDamage(int damage) + { + if (defending) + { + damage /= 2; + System.out.println(name + " defended and reduced damage to " + damage); + defending = false; + } hp -= damage; + if (hp < 0) hp = 0; } - public int getHp() { - return hp; + @Override + public void attack(Entity target) + { + int damage = 8; + System.out.println(name + " attacks for " + damage + " damage!"); + target.takeDamage(damage); } - public int getMp() { - return mp; - } - - public Weapon getWeapon() { - return weapon; - } + public String getName() {return name;} } 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..f5f85a7 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Goblin.java @@ -0,0 +1,30 @@ +package org.project.entity.enemies; + +import java.util.Random; + +public class Goblin extends Enemy +{ + private static final Random random = new Random(); + + public Goblin() + { + super("Goblin", 50, 20); + } + + @Override + public void attack(Entity target) + { + // Goblin has 25% chance for critical hit (1.5x damage) + int baseDamage = 10; + double critChance = 0.25; + int damage = baseDamage; + + if (random.nextDouble() < critChance) + { + damage = (int) (baseDamage * 1.5); + System.out.println(name + " lands a critical hit!"); + } + System.out.println(name + " attacks for " + damage + " damage!"); + target.takeDamage(damage); + } +} \ 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..0977db9 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,14 @@ -package org.project.entity.enemies; +public class Skeleton extends Enemy +{ + public Skeleton() + { + super("Skeleton", 60, 15); + } -// TODO: UPDATE IMPLEMENTATION -public class Skeleton { - // TODO: DESIGN ENEMY AND IMPLEMENT THE CONSTRUCTOR + @Override + public void attack(Entity target) + { + System.out.println(name + " shoots a bone arrow!"); + super.attack(target); + } } 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..a8abcc3 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/entity/enemies/Vampire.java @@ -0,0 +1,24 @@ +package org.project.entity.enemies; + +public class Vampire extends Enemy +{ + + public Vampire() + { + super("Vampire", 60, 30); + } + + @Override + public void attack(Entity target) + { + int damage = 12; + + System.out.println(name + " attacks for " + damage + " damage and absorbs health!"); + target.takeDamage(damage); + + int healAmount = damage / 2; + hp += healAmount; + if (hp > maxHP) hp = maxHP; + System.out.println(name + " heals for " + healAmount + " HP."); + } +} \ No newline at end of file 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..631d1e6 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,13 @@ -package org.project.entity.players; +public class Knight extends Player +{ + public Knight(String name) + { + super(name, 150, 50, new Sword(), new HeavyArmor()); + } -// TODO: UPDATE IMPLEMENTATION -public class Knight { - // TODO: DESIGN KNIGHT'S WEAPON AND ARMOR AND IMPLEMENT THE CONSTRUCTOR + @Override + public void defend() + { + System.out.println(name + " raises shield! Defense is highly increased."); + } } 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..5f5b081 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,104 @@ 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 { +public abstract class Player implements Entity +{ protected String name; - Weapon weapon; - Armor armor; - private int hp; - private int maxHP; - private int mp; - private int maxMP; + protected int level; + protected int xp; + protected int xpToNextLevel; - public Player(String name, int hp, int mp, Weapon weapon, Armor armor) { + protected int hp; + protected int maxHP; + protected int mp; + protected int maxMP; + + protected boolean defending; + + public Player(String name, int maxHP, int maxMP) + { this.name = name; - this.hp = hp; - this.mp = mp; - - this.weapon = weapon; - this.armor = armor; + this.level = 1; + this.xp = 0; + this.xpToNextLevel = 100; + this.maxHP = maxHP; + this.hp = maxHP; + this.maxMP = maxMP; + this.mp = maxMP; + this.defending = false; } - @Override - public void attack(Entity target) { - target.takeDamage(weapon.getDamage()); - } + public abstract void specialAbility(Entity target); - @Override - public void defend() { - // TODO - } - - - @Override - public void takeDamage(int damage) { - hp -= damage - armor.getDefense(); - } - - @Override - public void heal(int health) { - hp += health; - if (hp > maxHP) { + public boolean checkLevelUp() + { + if (xp >= xpToNextLevel) + { + level++; + xp -= xpToNextLevel; + xpToNextLevel *= 1.5; + maxHP += 10; + maxMP += 5; hp = maxHP; - } - } - - @Override - public void fillMana(int mana) { - mp += mana; - if (mp > maxMP) { mp = maxMP; + + System.out.println("\u001B[32m[LEVEL UP] Congratulations! You reached Level " + level + ".\u001B[0m"); + return true; } + return false; } + public void addXP(int amount) {xp += amount;} - public String getName() { - return name; - } + @Override + public boolean isAlive() {return hp > 0;} - public int getHp() { - return hp; + @Override + public int getHP() {return hp;} + + @Override + public int getMaxHP() {return maxHP;} + + @Override + public void setHP(int hp) {this.hp = Math.min(hp, maxHP);} + + @Override + public int getMP() {return mp;} + + @Override + public int getMaxMP() {return maxMP;} + + @Override + public void setMP(int mp) {this.mp = Math.min(mp, maxMP);} + + @Override + public void defend() + { + defending = true; + System.out.println(name + " is defending and will reduce damage next turn."); } @Override - public int getMaxHP() { - return maxHP; - } - - public int getMp() { - return mp; + public void takeDamage(int damage) + { + if (defending) + { + damage /= 2; + System.out.println(name + " defended and reduced damage to " + damage); + defending = false; + } + hp -= damage; + if (hp < 0) hp = 0; } @Override - public int getMaxMP() { - return maxMP; + public void attack(Entity target) + { + int damage = 10 + level * 2; + System.out.println(name + " attacks for " + damage + " damage!"); + target.takeDamage(damage); } - public Weapon getWeapon() { - return weapon; - } - - public Armor getArmor() { - return armor; - } - -} + public String getName() {return name;} +} \ 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..340a90b 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,9 @@ 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(); } 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..b056558 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 @@ -1,42 +1,68 @@ package org.project.item.armors; -// TODO: UPDATE IMPLEMENTATION -public abstract class Armor { +public abstract class Armor +{ private int defense; private int maxDefense; private int durability; private int maxDurability; - private boolean isBroke; - public Armor(int defense, int durability) { + public Armor(int defense, int durability) + { this.defense = defense; + this.maxDefense = defense; this.durability = durability; + this.maxDurability = durability; + this.isBroke = false; } - public void checkBreak() { - if (durability <= 0) { - isBroke = true; - defense = 0; + public void takeHit(int damageToDurability) + { + if (!isBroke) + { + durability -= damageToDurability; + if (durability < 0) durability = 0; + checkBreak(); } } - // TODO: (BONUS) UPDATE THE REPAIR METHOD - public void repair() { - isBroke = false; - defense = maxDefense; - durability = maxDurability; + public void checkBreak() + { + if (durability <= 0) + { + isBroke = true; + defense = 0; + } + else + { + isBroke = false; + defense = maxDefense; + } } - public int getDefense() { - return defense; + public void repair() + { + if (isBroke) + { + isBroke = false; + defense = maxDefense; + durability = maxDurability; + System.out.println("Armor repaired successfully!"); + } + else + { + System.out.println("Armor is still intact. No repair needed."); + } } - public int getDurability() { - return durability; - } + public int getDefense() {return defense;} - public boolean isBroke() { - return isBroke; - } + public int getDurability() {return durability;} + + public boolean isBroke() {return isBroke;} + + public int getMaxDefense() {return maxDefense;} + + public int getMaxDurability() {return maxDurability;} } 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..2373264 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,27 @@ package org.project.item.armors; -// TODO: UPDATE IMPLEMENTATION -public class KnightArmor { - // TODO: DESIGN ARMOR'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR +public class KnightArmor extends Armor +{ + + public KnightArmor() + { + super(40, 100); + } + + @Override + public void checkBreak() + { + super.checkBreak(); + if (isBroke()) + { + System.out.println("Knight's armor is shattered!"); + } + } + + @Override + public void repair() + { + super.repair(); + System.out.println("Knight's armor has been reforged by the royal blacksmith!"); + } } \ No newline at end of file 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..39ce1ca 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,29 @@ 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 +{ + private String name; + private int amount; + + public Consumable(String name, int amount) + { + this.name = name; + this.amount = amount; + } + + public String getName() {return name;} + + public int getAmount() {return amount;} + + public void setAmount(int amount) {this.amount = amount;} + + public abstract void use(Entity target); + + @Override + public String toString() + { + return name + " (Effect amount: " + amount + ")"; + } +} \ No newline at end of file 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..fb96fb9 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,18 @@ 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 +{ + public Flask() + { + super("Flask", 0); + } - // TODO: UPDATE USE METHOD @Override - public void use(Entity target) { - target.heal(target.getMaxHP() / 10); + public void use(Entity target) + { + int healAmount = target.getMaxHP() / 10; + target.heal(healAmount); + System.out.println(target.getName() + " used " + getName() + " and recovered " + healAmount + " HP."); } } 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..b02b72f 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 @@ -4,23 +4,42 @@ import org.project.entity.Entity; import java.util.ArrayList; -// TODO: UPDATE IMPLEMENTATION -public class Sword { - /* - THIS IS AN EXAMPLE OF A WEAPON DESIGN. - */ +public class Sword extends Weapon +{ - int abilityCharge; + private int abilityCharge; - public Sword() { - // TODO: DESIGN SWORD'S ATTRIBUTES IMPLEMENT THE CONSTRUCTOR + public Sword() + { + super(25, 10, 1.2, 0.15, 100); + this.abilityCharge = 0; } - // TODO: (BONUS) UPDATE THE UNIQUE ABILITY - public void uniqueAbility(ArrayList targets) { + @Override + public String getName() + { + return "Basic Sword"; + } + + @Override + public String getDescription() + { + return "A sharp melee weapon with balanced damage and good critical chance."; + } + + @Override + public void uniqueAbility(Entity... targets) + { abilityCharge += 2; - for (Entity target : targets) { - target.takeDamage(getDamage()); + + System.out.println("Sword's unique ability activated! Hitting " + targets.length + " targets."); + + for (Entity target : targets) + { + if (target != null && target.isAlive()) + { + target.takeDamage(getDamage() + 10); + } } } -} +} \ 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..d453181 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,78 @@ package org.project.item.weapons; import org.project.entity.Entity; +import org.project.item.Item; -// TODO: UPDATE IMPLEMENTATION -public abstract class Weapon { - private int damage; - private int manaCost; +public abstract class Weapon implements Item +{ + private final int damage; + private final int manaCost; + private final double attackSpeed; + private final double critChance; + private final int durability; + private int currentDurability; - /* - TODO: ADD OTHER REQUIRED AND BONUS ATTRIBUTES - */ - - public Weapon(int damage, int manaCost) { + public Weapon(int damage, int manaCost, double attackSpeed, double critChance, int durability) + { this.damage = damage; this.manaCost = manaCost; + this.attackSpeed = attackSpeed; + this.critChance = critChance; + this.durability = durability; + this.currentDurability = durability; } @Override - public void use(Entity target) { - target.takeDamage(damage); + public void use(Entity target) + { + if (currentDurability <= 0) + { + System.out.println(getName() + " is broken and cannot be used."); + return; + } + + if (target == null) + { + System.out.println("No target to attack."); + return; + } + + int finalDamage = damage; + if (Math.random() < critChance) + { + finalDamage *= 2; + System.out.println("Critical hit!"); + } + + target.takeDamage(finalDamage); + currentDurability--; + + System.out.println(getName() + " used on " + (target.getClass().getSimpleName()) + ", damage: " + finalDamage + ", durability left: " + currentDurability); + if (currentDurability == 0) + System.out.println(getName() + " is now broken!"); } - public int getDamage() { - return damage; + public void repair() + { + currentDurability = durability; + System.out.println(getName() + " repaired to full durability!"); } - public int getManaCost() { - return manaCost; - } + public int getDamage() {return damage;} - /* - TODO: ADD OTHER REQUIRED AND BONUS METHODS - */ + public int getManaCost() {return manaCost;} + + public double getAttackSpeed() {return attackSpeed;} + + public double getCritChance() {return critChance;} + + public int getDurability() {return durability;} + + public int getCurrentDurability() {return currentDurability;} + + public abstract String getName(); + + public abstract String getDescription(); + + public void uniqueAbility(Entity... targets) {} } 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..118847d 100644 --- a/Java-Knight/src/main/java/org/project/location/Location.java +++ b/Java-Knight/src/main/java/org/project/location/Location.java @@ -4,25 +4,52 @@ import org.project.entity.enemies.Enemy; import java.util.ArrayList; -public class Location { +public class Location +{ private String name; - + private ArrayList locations; private ArrayList enemies; - public Location(ArrayList locations, ArrayList enemies) { + public Location(ArrayList locations, ArrayList enemies) + { this.locations = locations; this.enemies = enemies; } - public String getName() { - return name; + public String getName() {return name;} + + public ArrayList getLocations() {return locations;} + + public ArrayList getEnemies() {return enemies;} + + public void setName(String name) {this.name = name;} + + public void addAdjacentLocation(Location location) + { + if (this.locations == null) + { + this.locations = new ArrayList<>(); + } + this.locations.add(location); } - public ArrayList getLocations() { - return locations; + public void addEnemy(Enemy enemy) + { + if (this.enemies == null) + { + this.enemies = new ArrayList<>(); + } + this.enemies.add(enemy); } - public ArrayList getEnemies() { - return enemies; + public boolean hasLivingEnemies() + { + if (this.enemies == null) {return false;} + + for (Enemy enemy : enemies) + { + if (enemy.isAlive()) {return true;} + } + return false; } } diff --git a/Readme_Pictures/MyREADME.md b/Readme_Pictures/MyREADME.md new file mode 100644 index 0000000..c201cd5 --- /dev/null +++ b/Readme_Pictures/MyREADME.md @@ -0,0 +1,188 @@ +# ⚔️ Java Knight RPG + +## 🎮 Introduction +Java Knight is a text-based RPG game developed in Java using Object-Oriented Programming principles. +The player explores different locations, fights enemies, collects keys, gains experience, and becomes stronger throughout the adventure. +Each enemy has unique abilities, and the final goal is to defeat the Dragon Boss and complete the quest. + +--- + +# 🛠️ Compile & Run + +## ✅ Compile +Open the terminal in the project folder and run: + +```bash +javac *.java +``` + +## ▶️ Run +After compiling, start the game using: + +```bash +java Main +``` + +--- + +# 🧩 Classes & OOP Design + +## 🧱 Entity +The base class of all living characters in the game. +It contains common attributes such as: +- Name +- Health +- Damage +- Defense + +This class demonstrates: +- Inheritance +- Encapsulation + +--- + +## 🛡️ Player +Represents the main playable character. +The player can: +- Fight enemies +- Gain XP +- Level up +- Collect keys +- Move between locations + +Concepts used: +- Encapsulation +- Method overriding +- State management + +--- + +## ⚔️ Knight +A specialized version of the Player class with stronger combat abilities and better starting stats. + +Concepts used: +- Inheritance +- Polymorphism + +--- + +## 👾 Enemy +Base class for all enemy types in the game. +Defines common enemy behavior such as: +- Attacking +- Taking damage +- Health management + +Concepts used: +- Abstraction +- Inheritance + +--- + +## 💀 Skeleton +A simple enemy with balanced combat stats. + +--- + +## 👹 Goblin +A fast enemy with a chance to deal critical damage. + +--- + +## 🧛 Vampire +An enemy capable of stealing health from the player during combat. + +--- + +## 🐉 Dragon +The final boss of the game with powerful attacks that can ignore defense. + +--- + +## 📍 Location +Handles the world map and movement system. +Each location contains: +- Enemies +- Connected locations +- Exploration logic + +Concepts used: +- Object relationships +- Composition + +--- + +## 🎒 Item +Represents collectible and usable objects inside the game. +Items can help the player by: +- Restoring health +- Increasing power +- Supporting progression + +Concepts used: +- Encapsulation +- Object interaction + +--- + +# 🧠 OOP Principles Used + +- ✅ Inheritance +- ✅ Encapsulation +- ✅ Polymorphism +- ✅ Abstraction + +The project is fully designed using Object-Oriented Programming to make the code modular, reusable, and easier to maintain. + +--- + +# 🎯 How to Play + +## 🎮 Controls +The game is menu-based. +Players select actions by entering numbers in the terminal. + +Example actions: +- Attack enemy +- View stats +- Move to another location +- Continue exploration + +--- + +## 📊 Player Stats + +### ❤️ Health +Determines how much damage the player can survive. + +### ⚔️ Damage +Controls attack power against enemies. + +### 🛡️ Defense +Reduces incoming damage. + +### ✨ XP +Earned after defeating enemies and used for leveling up. + +### 🔑 Keys +Required to unlock progression and reach the final boss. + +--- + +## 🌍 Gameplay Flow + +1. Start the game +2. Explore locations +3. Fight enemies +4. Gain XP and level up +5. Collect keys +6. Reach the Dragon Castle +7. Defeat the Dragon Boss + +--- + +# 👩‍💻 Credits + +Developed with Java and Object-Oriented Programming concepts. + +Made by Romina