From 4bd9823445cacb4294a05485a1d904566efb4fad Mon Sep 17 00:00:00 2001 From: mohammadreza Date: Sun, 17 May 2026 06:39:28 -0700 Subject: [PATCH] add GameLoop.java --- .../src/main/java/org/project/GameLoop.java | 312 ++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 Java-Knight/src/main/java/org/project/GameLoop.java diff --git a/Java-Knight/src/main/java/org/project/GameLoop.java b/Java-Knight/src/main/java/org/project/GameLoop.java new file mode 100644 index 0000000..564bde3 --- /dev/null +++ b/Java-Knight/src/main/java/org/project/GameLoop.java @@ -0,0 +1,312 @@ +package org.project; + +import org.project.combat.*; +import org.project.entity.enemies.*; +import org.project.entity.players.*; +import org.project.location.Location; +import org.project.managers.*; + +import java.util.*; + +public class GameLoop { + + private final Scanner scanner = new Scanner(System.in); + + private final ActionDecisionManager actionManager = new ActionDecisionManager(); + private final StatusEffectManager statusManager = new StatusEffectManager(); + private final SpecialAbilityManager abilityManager = new SpecialAbilityManager(); + private final ManaCostManager manaManager = new ManaCostManager(); + + private final TotalAttackCalculator attackCalculator = + new TotalAttackCalculator(statusManager, abilityManager, manaManager); + + private Player player; + private Enemy currentEnemy; + + private boolean gameRunning = true; + + private boolean hasGoblinKey; + private boolean hasSkeletonKey; + private boolean hasVampireKey; + + private Location currentLocation; + private final List locations = new ArrayList<>(); + + + public GameLoop() { + initializeLocations(); + } + + private void initializeLocations() { + + Location valhalla = new Location("Valhalla"); + Location elysium = new Location("Elysium"); + Location niflheim = new Location("Niflheim"); + Location castle = new Location("Castle"); + + valhalla.connect(elysium); + valhalla.connect(niflheim); + elysium.connect(niflheim); + niflheim.connect(castle); + + locations.add(valhalla); + locations.add(elysium); + locations.add(niflheim); + locations.add(castle); + + currentLocation = valhalla; + } + + public void start() { + + System.out.println("====== JAVA KNIGHT ======"); + + chooseClass(); + spawnEnemy(); + + while (gameRunning) { + showMenu(); + } + + System.out.println("Game Ended."); + } + + private void chooseClass() { + + System.out.println(""" + Choose class: + 1. Knight (HP:150 MP:80 DMG:12) + 2. Wizard (HP:80 MP:200 DMG:10) + 3. Assassin (HP:90 MP:120 DMG:15) + """); + + int choice = scanner.nextInt(); + + switch (choice) { + case 2 -> player = new Wizard("Merlin"); + case 3 -> player = new Assassin("Shadow"); + default -> player = new Knight("Sir Duncan"); + } + } + + private void showMenu() { + + System.out.println("====" + Colors.YELLOW + " GAME MENU " + Colors.RESET + "===="); + System.out.println("Location: " + currentLocation.getName()); + + if (currentEnemy != null) + System.out.println("Enemy: " + currentEnemy); + + System.out.println(""" + \n1. Fight + 2. Inventory + 3. Move + 0. Exit + """); + + if (hasAllKeys()) + System.out.println("4. Fight Dragon"); + + int choice = scanner.nextInt(); + + switch (choice) { + case 1 -> startCombat(); + case 2 -> new InventoryManager().displayInventory(player); + case 3 -> move(); + case 4 -> { + if (hasAllKeys()) + fightDragon(); + } + case 0 -> gameRunning = false; + } + } + + private void move() { + + List connected = currentLocation.getConnectedLocations(); + + if (connected.isEmpty()) { + System.out.println("No paths from here."); + return; + } + + System.out.println("Choose destination:"); + + for (int i = 0; i < connected.size(); i++) + System.out.println((i + 1) + ". " + connected.get(i).getName()); + + int choice = scanner.nextInt(); + + if (choice < 1 || choice > connected.size()) + return; + + currentLocation = connected.get(choice - 1); + + spawnEnemy(); + } + + private void spawnEnemy() { + + Enemy[] enemies = { + new Goblin(), + new Skeleton(), + new Vampire() + }; + + currentEnemy = enemies[(int) (Math.random() * enemies.length)]; + } + + private void startCombat() { + + if (currentEnemy == null) { + System.out.println("No enemy here."); + return; + } + + System.out.println(Colors.RED_BRIGHT + "⚔ COMBAT STARTED! ⚔" + Colors.RESET); + + + while (player.isLive() && currentEnemy.isLive()) { + + statusManager.tick(player); + statusManager.tick(currentEnemy); + + abilityManager.tick(currentEnemy, player); + abilityManager.tick(player, currentEnemy); + + if (!player.isLive() || !currentEnemy.isLive()) + break; + + playerTurn(); + currentEnemy.resetTurnState(); + + if (currentEnemy.isLive()) + enemyTurn(); + player.resetTurnState(); + } + + if (player.isLive()) + victory(); + else + gameRunning = false; + } + + + private void playerTurn() { + System.out.println("====" + Colors.YELLOW + " YOUR TURN " + Colors.RESET + "===="); + System.out.println(player.getName() + "-> HP: " + player.getHp() + " | MP: " + player.getMp() + " | level: " + player.getLevel() + " | XP: " + player.getXp()); + System.out.println(currentEnemy.getName() + "-> HP: " + currentEnemy.getHp() + " | MP: " + currentEnemy.getMp()); + System.out.println("\n"); + var action = actionManager.userChooseAction(); + + AttackResult result = attackCalculator.calculate(player, currentEnemy, action); + + int totalDamage = result.getDamageToTarget(); + int healAmount = result.getHealSelf(); + boolean isDefend = result.isDefended(); + + if (totalDamage > 0) { + System.out.println(currentEnemy.getName() + " got " + totalDamage + " damage"); + currentEnemy.takeDamage(totalDamage); + } + + if (healAmount > 0) { + player.heal(healAmount); + if (player.getHp() < player.getMaxHP()) + System.out.println(player.getName() + "healed " + healAmount + " HP"); + } + + if (isDefend) { + player.defend(); + System.out.println(player.getName() + " will defend (50% damage)"); + } + System.out.println("\n"); + } + + private void enemyTurn() { + System.out.println("====" + Colors.YELLOW + " ENEMY TURN " + Colors.RESET + "====\n"); + var action = actionManager.botChooseAction(); + + System.out.println("enemy random choose action: " + Colors.RED + action + Colors.RESET); + + AttackResult result = attackCalculator.calculate(currentEnemy, player, action); + + int totalDamage = result.getDamageToTarget(); + int healAmount = result.getHealSelf(); + boolean isDefend = result.isDefended(); + + + if (totalDamage > 0) { + System.out.println(player.getName() + " got " + totalDamage + " damage"); + player.takeDamage(totalDamage); + } + + if (healAmount > 0) { + currentEnemy.heal(healAmount); + if (currentEnemy.getHp() < currentEnemy.getMaxHP()) + System.out.println(currentEnemy.getName() + " healed " + healAmount + " HP"); + + } + + if (isDefend) { + currentEnemy.defend(); + System.out.println(currentEnemy.getName() + " will defend (50% damage)"); + } + + + System.out.println("\n"); + + } + + private void victory() { + + System.out.println(Colors.GREEN + "Victory!" + Colors.RESET); + + currentEnemy.rewardXp(player); + + checkKeyDrop(); + + player.restore(); + + currentEnemy = null; + } + + private void checkKeyDrop() { + + if (Math.random() * 100 > 20) + return; + + if (currentEnemy instanceof Goblin && !hasGoblinKey) { + hasGoblinKey = true; + System.out.println("Goblin Key obtained!"); + } + + else if (currentEnemy instanceof Skeleton && ! hasSkeletonKey) { + hasSkeletonKey = true; + System.out.println("Skeleton Key obtained!"); + } + + else if (currentEnemy instanceof Vampire && !hasVampireKey) { + hasVampireKey = true; + System.out.println("Vampire Key obtained!"); + } + } + + private boolean hasAllKeys() { + return hasGoblinKey && hasSkeletonKey && hasVampireKey; + } + + private void fightDragon() { + + currentEnemy = new Dragon(); + + System.out.println("The Dragon Appears!"); + + startCombat(); + + if (player.isLive()) + System.out.println("YOU SAVED JAVANEST!"); + else + System.out.println("The Dragon has defeated you..."); + } +}