Java Knight #2

Open
Romina wants to merge 3 commits from develop into main
18 changed files with 1057 additions and 197 deletions
+372 -8
View File
@@ -1,15 +1,379 @@
package org.project;
package org.project.main;
import org.project.entity.Entity;
import org.project.entity.players.Knight;
import org.project.entity.enemies.*;
import org.project.location.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<Location> 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<Location> gameLocations = new ArrayList<>();
private static Location currentLocation;
private static Set<String> 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<Location> 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() + "]");
}
}
@@ -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);
}
@@ -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);
}
}
}
@@ -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;}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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.");
}
}
@@ -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.");
}
}
@@ -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 Weapon getWeapon() {
return weapon;
}
public Armor getArmor() {
return armor;
public void attack(Entity target)
{
int damage = 10 + level * 2;
System.out.println(name + " attacks for " + damage + " damage!");
target.takeDamage(damage);
}
public String getName() {return name;}
}
@@ -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();
}
@@ -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;}
}
@@ -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!");
}
}
@@ -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 + ")";
}
}
@@ -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.");
}
}
@@ -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<Entity> 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);
}
}
}
}
@@ -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) {}
}
@@ -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<Location> locations;
private ArrayList<Enemy> enemies;
public Location(ArrayList<Location> locations, ArrayList<Enemy> enemies) {
public Location(ArrayList<Location> locations, ArrayList<Enemy> enemies)
{
this.locations = locations;
this.enemies = enemies;
}
public String getName() {
return name;
public String getName() {return name;}
public ArrayList<Location> getLocations() {return locations;}
public ArrayList<Enemy> 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<Location> getLocations() {
return locations;
public void addEnemy(Enemy enemy)
{
if (this.enemies == null)
{
this.enemies = new ArrayList<>();
}
this.enemies.add(enemy);
}
public ArrayList<Enemy> getEnemies() {
return enemies;
public boolean hasLivingEnemies()
{
if (this.enemies == null) {return false;}
for (Enemy enemy : enemies)
{
if (enemy.isAlive()) {return true;}
}
return false;
}
}
+188
View File
@@ -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