Completed The main class, almost completed the project, ready for debug.

This commit is contained in:
2026-05-11 02:06:10 +03:30
parent a9937d2668
commit 50aa4c31a2
44 changed files with 508 additions and 37 deletions
+328 -5
View File
@@ -1,15 +1,338 @@
package org.project;
import org.project.location.Location;
import org.project.entity.players.*;
import org.project.entity.enemies.*;
import org.project.location.*;
import org.project.item.weapons.*;
import org.project.item.consumables.*;
import org.project.item.armors.*;
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<Location> locations = new ArrayList<>();
private static Scanner scanner = new Scanner(System.in);
private static Random random = new Random();
// TODO: IMPLEMENT GAMEPLAY
private static Player player;
//Collected keys
private static boolean hasGoblinKey = false;
private static boolean hasSkeletonKey = false;
private static boolean hasVampireKey = false;
private static boolean castleUnlocked = false;
public static void main(String[] args) {
System.out.println("⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️");
NarrativeConsole.printNormal(" JAVA KNIGHT - THE DRAGON'S CURSE");
System.out.println("⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️⚔️");
NarrativeConsole.printNormal("\nFor centuries, the land of Javanest lived in peace...");
NarrativeConsole.printNormal("Until a magical Dragon attacked, plunging the realm into darkness!");
NarrativeConsole.printNormal("You are the last hope. Gather the 3 keys and slay the Dragon!\n");
//Choosing a role
createPlayer();
gameLoop();
}
private static void createPlayer() {
System.out.println("=".repeat(20));
System.out.println("CHOOSE YOUR HERO:");
System.out.println("1. Knight ⚔️ - High damage, strong armor");
System.out.println("2. Wizard 🧙‍♂️ - High HP, healing spells");
System.out.println("3. Assassin 🗡️ - High mana, critical strikes");
System.out.print("\nEnter choice (1-3): ");
int choice = getIntInput();
scanner.nextLine();
System.out.print("Enter your hero's name: ");
String name = scanner.nextLine();
switch (choice) {
case 1:
player = new Knight(name);
break;
case 2:
player = new Wizard(name);
break;
case 3:
player = new Assassin(name);
break;
default:
System.out.println("Invalid choice! Defaulting to Knight.");
player = new Knight(name);
}
System.out.println("\n✨ " + player.getName() + " the " +
player.getClass().getSimpleName() + " has entered Javanest!");
NarrativeConsole.printHeal("💚 HP: " + player.getHp() + "/" + player.getMaxHP());
NarrativeConsole.printMana("💙 MP: " + player.getMp() + "/" + player.getMaxMP());
System.out.println("\nPress Enter to begin your journey...");
scanner.nextLine();
}
private static void gameLoop() {
boolean gameRunning = true;
boolean firstLocation = true;
while (gameRunning && player.isAlive()) {
//Entering a new location
if (!firstLocation) {
System.out.println("\n" + "=".repeat(30));
System.out.println("You move to a new location...");
}
firstLocation = false;
Enemy currentEnemy = spawnRandomEnemy();
NarrativeConsole.printWarning("\n⭕⭕⭕ A " +
currentEnemy.getName(currentEnemy).toUpperCase() + " appears before you! ⭕⭕⭕");
NarrativeConsole.printWarning("❤️ " + currentEnemy.getName(currentEnemy) + " HP: " +
currentEnemy.getHp() + "/" + currentEnemy.getMaxHP());
//Pre-battle menu
boolean locationExited = false;
while (!locationExited && player.isAlive() && gameRunning) {
displayMainMenu();
int choice = getIntInput();
if (choice == 1) {
//Option 1: Starting the battle
boolean victory = startBattle(currentEnemy);
if (victory) {
handleVictory(currentEnemy);
locationExited = true; //Moving on the next location
} else {
gameRunning = false; //Player's death
}
} else if (choice == 2) {
//Option 2: Move to another location1
System.out.println("\n🚶 You flee to another location...");
currentEnemy = spawnRandomEnemy();
NarrativeConsole.printWarning("⭕ A " + currentEnemy.getName(currentEnemy) +
" appears in this new location!");
} else if (choice == 3 && castleUnlocked) {
//Option 3: Going to the castle and fight the dragon (only with 3 keys)
System.out.println("\n🏰🏰🏰 YOU STAND BEFORE THE DRAGON'S CASTLE! 🏰🏰🏰");
System.out.println("The gates slowly open... A massive shadow emerges...\n");
boolean victory = startBattle(new Dragon());
if (victory) {
System.out.println("\n🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉");
NarrativeConsole.printSuccess(" THE DRAGON IS DEFEATED! YOU SAVED JAVANEST!");
System.out.println("🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉");
gameRunning = false;
} else {
NarrativeConsole.printError("\n💀 The Dragon's flames consume you... GAME OVER!");
gameRunning = false;
}
break;
}
//Checking the condition for opening the castle
if (hasAllKeys() && !castleUnlocked) {
castleUnlocked = true;
System.out.println("\n🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑");
NarrativeConsole.printSuccess(" YOU HAVE COLLECTED ALL 3 KEYS!");
NarrativeConsole.printSuccess("🏰 THE PATH TO THE DRAGON'S CASTLE IS NOW OPEN! 🏰");
System.out.println("🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑🔑");
}
displayKeyProgress();
//End game
if (!player.isAlive()) {
NarrativeConsole.printError("\n💀💀💀 GAME OVER! 💀💀💀");
NarrativeConsole.printError("Your journey ends here. The curse of Javanest remains unbroken...");
}
}
}
}
private static void displayMainMenu() {
System.out.println("\n" + "-".repeat(30));
System.out.println("WHAT WILL YOU DO?");
System.out.println("1. ⚔️ FIGHT the enemy");
System.out.println("2. 🚶 MOVE to another location");
if (castleUnlocked) {
System.out.println("3. 🏰 GO TO THE CASTLE (Fight the Dragon!)");
}
System.out.print("\nChoose: ");
}
private static boolean startBattle(Enemy enemy) {
System.out.println("\n" + "🔥".repeat(30));
System.out.println(" BATTLE BEGINS!");
System.out.println("🔥".repeat(30));
while (player.isAlive() && enemy.isAlive()) {
displayBattleStatus(enemy);
playerTurn(enemy);
if (!enemy.isAlive()) {
break;
}
enemyTurn(enemy);
}
return player.isAlive();
}
private static void playerTurn(Enemy enemy) {
System.out.println("\n" + "-".repeat(30));
System.out.println("YOUR TURN");
System.out.println("1. ⚔️ Light Attack (0 Mana)");
System.out.println("2. 💥 Heavy Attack (-8 Mana)");
System.out.println("3. 🛡️ Defend (-6 Mana)");
System.out.println("4. 💚 Heal (-12 Mana)");
System.out.println("5. ⭐ Special Ability (-15 Mana)");
System.out.print("Choose action: ");
int choice = getIntInput();
switch (choice) {
case 1:
player.lightAttack(enemy);
break;
case 2:
player.heavyAttack(enemy);
break;
case 3:
player.defend();
break;
case 4:
player.heal(12);
break;
case 5:
player.specialAbility(enemy);
break;
default:
NarrativeConsole.printWarning("❌ Invalid choice! You hesitate and lose your turn!");
}
//Checking the death of enemy
if (!enemy.isAlive()) {
NarrativeConsole.printSuccess("\n💀 " +
enemy.getName(enemy).toUpperCase() + " HAS BEEN DEFEATED! 💀");
}
}
private static void enemyTurn(Enemy enemy) {
System.out.println("\n" + "-".repeat(30));
System.out.println("ENEMY TURN");
enemy.attack(player);
}
private static void displayBattleStatus(Enemy enemy) {
System.out.println("\n" + "".repeat(45));
System.out.printf("❤️ %s: %d/%d HP | 💙 Mana: %d/%d%n",
player.getName(), player.getHp(), player.getMaxHP(),
player.getMp(), player.getMaxMP());
System.out.printf("👹 %s: %d/%d HP%n",
enemy.getName(enemy), enemy.getHp(), enemy.getMaxHP());
System.out.println("".repeat(45));
}
private static Enemy spawnRandomEnemy() {
int roll = random.nextInt(3); // 0, 1, 2
switch (roll) {
case 0:
return new Goblin();
case 1:
return new Skeleton();
default:
return new Vampire();
}
}
private static void handleVictory(Enemy defeatedEnemy) {
NarrativeConsole.printSuccess("\n✨✨✨ VICTORY! ✨✨✨");
NarrativeConsole.printSuccess(defeatedEnemy.getName(defeatedEnemy).toUpperCase() +
" has been defeated!");
//Getting Higher Max HP and MP
player.setMaxHP(player.getMaxHP() + getXpReward(defeatedEnemy)/5);
player.setMaxMP(player.getMaxMP() + getXpReward(defeatedEnemy)/5);
//Full HP and Mana Recovery (Post-Combat Recovery)
player.setHp(player.getMaxHP());
player.setMp(player.getMaxMP());
NarrativeConsole.printHeal("💚 HP and Mana fully restored in higher levels!");
//Key Drop (20% chance)
attemptKeyDrop(defeatedEnemy);
}
private static int getXpReward(Enemy enemy) {
if (enemy instanceof Goblin) return 50;
if (enemy instanceof Skeleton) return 65;
if (enemy instanceof Vampire) return 85;
if (enemy instanceof Dragon) return 300;
return 40;
}
private static void attemptKeyDrop(Enemy enemy) {
//Checking if we already have this key or not
if (enemy instanceof Goblin && hasGoblinKey) {
return;
}
if (enemy instanceof Skeleton && hasSkeletonKey) {
return;
}
if (enemy instanceof Vampire && hasVampireKey) {
return;
}
//Dropping the key (20% Chance)
int dropChance = random.nextInt(100);
if (dropChance > 80) {
if (enemy instanceof Goblin) {
hasGoblinKey = true;
NarrativeConsole.printSuccess("\n🔑🔑🔑 YOU FOUND THE GOBLIN KEY! (1/3) 🔑🔑🔑");
} else if (enemy instanceof Skeleton) {
hasSkeletonKey = true;
NarrativeConsole.printSuccess("\n🔑🔑🔑 YOU FOUND THE SKELETON KEY! (2/3) 🔑🔑🔑");
} else if (enemy instanceof Vampire) {
hasVampireKey = true;
NarrativeConsole.printSuccess("\n🔑🔑🔑 YOU FOUND THE VAMPIRE KEY! (3/3) 🔑🔑🔑");
}
} else {
System.out.println("🔑 No key dropped this time... Keep fighting!");
}
}
private static boolean hasAllKeys() {
return hasGoblinKey && hasSkeletonKey && hasVampireKey;
}
private static void displayKeyProgress() {
System.out.println("\n" + "-".repeat(40));
System.out.println("KEY PROGRESS:");
System.out.println(" " + (hasGoblinKey ? "👹" : "") + " Goblin Key " + (hasGoblinKey ? "(Obtained)" : "(Missing)"));
System.out.println(" " + (hasSkeletonKey ? "💀" : "") + " Skeleton Key " + (hasSkeletonKey ? "(Obtained)" : "(Missing)"));
System.out.println(" " + (hasVampireKey ? "🦇" : "") + " Vampire Key " + (hasVampireKey ? "(Obtained)" : "(Missing)"));
System.out.println("-".repeat(40));
}
private static int getIntInput() {
while (true) {
try {
int input = Integer.parseInt(scanner.nextLine().trim());
return input;
} catch (NumberFormatException e) {
NarrativeConsole.printWarning("❌ Invalid input! Please enter a number: ");
}
}
}
}
@@ -119,4 +119,8 @@ public abstract class Enemy implements Entity {
public void setHp(int newHp) {
hp = newHp;
}
public boolean isAlive() {
return (getHp() != 0);
}
}
@@ -1,17 +1,22 @@
package org.project.entity.players;
import org.project.entity.Entity;
import org.project.entity.enemies.Enemy;
import org.project.item.armors.Armor;
import org.project.item.armors.AssassinMask;
import org.project.item.weapons.Dagger;
import org.project.item.weapons.Weapon;
import org.project.location.NarrativeConsole;
public class Assassin extends Player implements Entity, ICombatActions {
public Assassin(String name, Weapon weapon, Armor armor) {
super(name, 45, 60, weapon, armor);
public Assassin(String name) {
super(name, 45, 60, new Dagger(), new AssassinMask());
setHp(getMaxHP());
setMp(getMaxMP());
}
@Override
public void specialAbility(Entity target) {
public void specialAbility(Enemy target) {
//Checking if the mana is enough of not
if (getMp() < 15) {
NarrativeConsole.printWarning("❌ Not enough mana for Devastating Spell!");
@@ -30,7 +35,7 @@ public class Assassin extends Player implements Entity, ICombatActions {
NarrativeConsole.printMana("💙 Mana left: " + getMp());
}
public void lightAttack(Entity target) {
public void lightAttack(Enemy target) {
int damage = 10;
//Critical Action (if enabled)
@@ -45,7 +50,7 @@ public class Assassin extends Player implements Entity, ICombatActions {
}
@Override
public void heavyAttack(Entity target) {
public void heavyAttack(Enemy target) {
if (getMp() < 8) {
NarrativeConsole.printWarning("❌ Not enough mana for Heavy Attack!");
return;
@@ -1,18 +1,19 @@
package org.project.entity.players;
import org.project.entity.Entity;
import org.project.entity.enemies.Enemy;
import java.util.ArrayList;
public interface ICombatActions {
void lightAttack(Entity target);
void lightAttack(Enemy target);
void heavyAttack(Entity target);
void heavyAttack(Enemy target);
void defend();
void heal();
void specialAbility(Entity target);
void specialAbility(Enemy target);
}
@@ -14,10 +14,12 @@ import java.util.ArrayList;
public class Knight extends Player implements ICombatActions {
public Knight(String name) {
super(name, 45, 45, new Sword(), new KnightArmor());
setHp(getMaxHP());
setMp(getMaxMP());
}
@Override
public void specialAbility(Entity target) {
public void specialAbility(Enemy target) {
//Checking if the mana is enough of not
if (getMp() < 15) {
NarrativeConsole.printWarning("❌ Mana is not enough for Shield Bash!");
@@ -35,14 +37,14 @@ public class Knight extends Player implements ICombatActions {
NarrativeConsole.printSpecial("💥 Shield Bash! Enemy is stunned!");
}
public void lightAttack(Entity target) {
public void lightAttack(Enemy target) {
int damage = 10;
target.takeDamage(damage);
NarrativeConsole.printCombat("⚔️ " + getName() + " used Light Attack! Dealt " + damage + " damage.");
}
@Override
public void heavyAttack(Entity target) {
public void heavyAttack(Enemy target) {
if (getMp() < 8) {
NarrativeConsole.printWarning("❌ Mana is not enough for Heavy Attack!");
return;
@@ -1,6 +1,7 @@
package org.project.entity.players;
import org.project.entity.Entity;
import org.project.entity.enemies.Enemy;
import org.project.item.armors.Armor;
import org.project.item.weapons.Weapon;
import org.project.location.NarrativeConsole;
@@ -22,15 +23,20 @@ public abstract class Player implements Entity {
private boolean isInvisible = false;
private boolean nextAttackCritical = false;
public Player(String name, int hp, int mp, Weapon weapon, Armor armor) {
public Player(String name, int maxHP, int maxMP, Weapon weapon, Armor armor) {
this.name = name;
this.hp = hp;
this.mp = mp;
this.maxMP = maxMP;
this.maxHP = maxHP;
this.weapon = weapon;
this.armor = armor;
}
public abstract void specialAbility(Enemy enemy);
public abstract void lightAttack(Enemy enemy);
public abstract void heavyAttack(Enemy enemy);
@Override
public void defend() {
//checking mana
@@ -152,6 +158,10 @@ public abstract class Player implements Entity {
public boolean isNextAttackCritical() { return nextAttackCritical; }
public boolean isAlive() {
return (getHp() != 0);
}
public void setInvisible(boolean invisible) { this.isInvisible = invisible; }
public void setNextAttackCritical(boolean critical) { this.nextAttackCritical = critical; }
@@ -167,4 +177,12 @@ public abstract class Player implements Entity {
public void setDefending(boolean defending) {
isDefending = defending;
}
public void setMaxHP(int maxHP) {
this.maxHP = maxHP;
}
public void setMaxMP(int maxMP) {
this.maxMP = maxMP;
}
}
@@ -3,18 +3,22 @@ package org.project.entity.players;
import org.project.entity.Entity;
import org.project.entity.enemies.Enemy;
import org.project.item.armors.Armor;
import org.project.item.armors.AssassinMask;
import org.project.item.armors.WizardRobe;
import org.project.item.weapons.Sword;
import org.project.item.weapons.Wand;
import org.project.item.weapons.Weapon;
import org.project.location.NarrativeConsole;
public class Wizard extends Player implements Entity,ICombatActions {
public Wizard (String name, Weapon weapon, Armor armor) {
super(name, 60, 45, new Wand(), armor);
public Wizard (String name) {
super(name, 60, 45, new Wand(), new WizardRobe());
setHp(getMaxHP());
setMp(getMaxMP());
}
@Override
public void specialAbility(Entity target) {
public void specialAbility(Enemy target) {
//Checking if the mana is enough of not
if (getMp() < 15) {
NarrativeConsole.printWarning("❌ Not enough mana for Devastating Spell!");
@@ -36,14 +40,14 @@ public class Wizard extends Player implements Entity,ICombatActions {
NarrativeConsole.printMana("💙 Mana left: " + getMp());
}
public void lightAttack(Entity target) {
public void lightAttack(Enemy target) {
int damage = 10;
target.takeDamage(damage);
NarrativeConsole.printCombat("⚔️ " + getName() + " used Light Attack! Dealt " + damage + " damage.");
}
@Override
public void heavyAttack(Entity target) {
public void heavyAttack(Enemy target) {
if (getMp() < 8) {
NarrativeConsole.printWarning("❌ Not enough mana for Heavy Attack!");
return;
@@ -1,28 +1,72 @@
package org.project.location;
import org.project.entity.enemies.Enemy;
import org.project.entity.enemies.*;
import java.util.ArrayList;
import java.util.Random;
public class Location {
private String name;
private String description;
private ArrayList<Enemy> possibleEnemies;
private Enemy currentEnemy;
private Random random;
private ArrayList<Enemy> enemies;
public Location(ArrayList<Location> locations, ArrayList<Enemy> enemies) {
this.locations = locations;
this.enemies = enemies;
public Location(String name, String description) {
this.name = name;
this.description = description;
this.possibleEnemies = new ArrayList<>();
this.random = new Random();
}
//Adding enemy to location
public void addEnemy(Enemy enemy) {
possibleEnemies.add(enemy);
}
//Spawning a random enemy from among the enemies in this location
public void spawnRandomEnemy() {
if (possibleEnemies.isEmpty()) {
//If no enemy was defined
addDefaultEnemies();
}
int index = random.nextInt(possibleEnemies.size());
currentEnemy = copyEnemy(possibleEnemies.get(index));
}
private void addDefaultEnemies() {
possibleEnemies.add(new Goblin());
possibleEnemies.add(new Skeleton());
possibleEnemies.add(new Vampire());
}
//Copying the enemy to have a new instance each time
private Enemy copyEnemy(Enemy original) {
if (original instanceof Goblin) return new Goblin();
if (original instanceof Skeleton) return new Skeleton();
if (original instanceof Vampire) return new Vampire();
return new Goblin();
}
public String getName() {
return name;
}
public ArrayList<Location> getLocations() {
return locations;
public String getDescription() {
return description;
}
public ArrayList<Enemy> getEnemies() {
return enemies;
public Enemy getCurrentEnemy() {
return currentEnemy;
}
}
public void setCurrentEnemy(Enemy enemy) {
this.currentEnemy = enemy;
}
public boolean hasEnemy() {
return currentEnemy != null && currentEnemy.isAlive();
}
}
@@ -0,0 +1,66 @@
package org.project.location;
import org.project.entity.enemies.*;
import java.util.ArrayList;
import java.util.Random;
public class LocationManager {
private ArrayList<Location> locations;
private Location currentLocation;
private Random random;
public LocationManager() {
locations = new ArrayList<>();
random = new Random();
createLocations();
}
private void createLocations() {
//Creating different game locations
Location forest = new Location("Dark Forest", "A mysterious forest filled with dangerous creatures");
forest.addEnemy(new Goblin());
forest.addEnemy(new Skeleton());
Location crypt = new Location("Ancient Crypt", "An old crypt where skeletons roam");
crypt.addEnemy(new Skeleton());
crypt.addEnemy(new Vampire());
Location castleGate = new Location("Castle Gate", "The entrance to the Dragon's castle");
castleGate.addEnemy(new Goblin());
castleGate.addEnemy(new Vampire());
locations.add(forest);
locations.add(crypt);
locations.add(castleGate);
}
public void moveToRandomLocation() {
int index = random.nextInt(locations.size());
currentLocation = locations.get(index);
currentLocation.spawnRandomEnemy();
}
public void moveToLocation(int index) {
if (index >= 0 && index < locations.size()) {
currentLocation = locations.get(index);
currentLocation.spawnRandomEnemy();
}
}
public Location getCurrentLocation() {
return currentLocation;
}
public void displayLocations() {
NarrativeConsole.printInfo("\n=== Available Locations ===");
for (int i = 0; i < locations.size(); i++) {
NarrativeConsole.printInfo((i + 1) + ". " + locations.get(i).getName());
NarrativeConsole.printInfo(" " + locations.get(i).getDescription());
}
}
public ArrayList<Location> getLocations() {
return locations;
}
}
@@ -1,6 +1,10 @@
package org.project.location;
public class NarrativeConsole {
//Normal
public static void printNormal(String message) {
System.out.println(AnsiColors.WHITE + "" + message + AnsiColors.RESET);
}
//Damage
public static void printDamage(String message) {
Binary file not shown.