Desarrollo de personajes de videojuegos
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy. Lección 86 de 87.
Este desafío te pide construir un sistema de desarrollo de personajes de juego que muestre el poder de la POO para modelar entidades complejas e interactivas.
Diseña una jerarquía de personajes en la que una clase base Character defina atributos comunes como salud, nombre y nivel. Las clases especializadas, como Warrior, Mage y Archer, extienden esta base con habilidades únicas y estilos de combate.
Las interfaces funcionan de forma natural aquí: Attackable podría definir métodos de combate, mientras que Healable gestiona las habilidades de restauración. Un Mage podría implementar ambas, mientras que un Warrior se centra únicamente en atacar.
Considera usar el patrón Strategy para diferentes comportamientos de ataque, lo que permite que los personajes cambien dinámicamente de estilo de combate. El patrón State podría gestionar condiciones de los personajes, como los estados normal, envenenado o aturdido, que afectan al comportamiento.
Piensa en la composición para sistemas de equipamiento donde los personajes «tienen» armas y armaduras en lugar de heredar de ellas. Usa enumeraciones para las clases de personajes o los tipos de daño, y aplica la encapsulación para proteger las estadísticas de modificaciones no válidas.
Desafío
Fácil¡Construyamos un sistema de desarrollo de personajes de juego que muestre el poder de la POO para modelar entidades de juego complejas e interactivas! Crearás una jerarquía de personajes con diferentes estilos de combate, habilidades especiales y un sistema de estados que afecta a la forma en que se comportan los personajes.
Organizarás tu código en siete archivos:
DamageType.java: Crea un enum que represente diferentes tipos de daño en el juego. Incluye los valoresPHYSICAL,MAGICALyRANGED. Añade un campo privadodescription(String), un constructor que lo establezca y un getter. El daño físico debe tener la descripción "brute force", el daño mágico debe tener "arcane energy" y el daño a distancia debe tener "precision strike".Attackable.java: Crea una interfaz que defina las capacidades de combate. Declara los métodosattack(Character target), que devuelve un String que describe el ataque, ygetDamageType(), que devuelve un DamageType.Healable.java: Crea una interfaz para las habilidades de restauración. Declara un métodoheal(int amount)que devuelva un String que describa la acción de curación.Character.java: Crea una clase base abstracta para todos los personajes del juego. Incluye campos privados paraname(String),health(int),maxHealth(int) ylevel(int). El constructor recibe name, maxHealth y level, y establece inicialmente health igual a maxHealth. Incluye getters para todos los campos. Añade un método protegidosetHealth(int health)que garantice que health se mantenga entre 0 y maxHealth. Crea un métodotakeDamage(int damage)que reduzca health y devuelva"[name] takes [damage] damage! Health: [health]/[maxHealth]". Añade un métodoisAlive()que devuelva true si health es mayor que 0. Declara un método abstractogetCharacterClass()que devuelva un String.Warrior.java: Crea una clase que extienda Character e implemente Attackable. Añade un campo privadostrength(int). El constructor recibe name, maxHealth, level y strength. ImplementagetCharacterClass()para que devuelva"Warrior". ImplementagetDamageType()para que devuelvaPHYSICAL. Implementaattack(Character target)para infligir un daño igual a strength más level, llamar al método takeDamage del objetivo y devolver"[name] strikes with [damageType description] for [damage] damage!", seguido de un salto de línea y del resultado de takeDamage.Mage.java: Crea una clase que extienda Character e implemente tanto Attackable como Healable. Añade los campos privadosintelligence(int) ymana(int). El constructor recibe name, maxHealth, level, intelligence y mana. ImplementagetCharacterClass()para que devuelva"Mage". ImplementagetDamageType()para que devuelvaMAGICAL. Implementaattack(Character target)para infligir un daño igual a intelligence multiplicado por 2, siguiendo el mismo formato que Warrior. Implementaheal(int amount)para restaurar health (usando setHealth) y devolver"[name] channels healing magic! Health: [health]/[maxHealth]".Main.java: ¡Da vida a tu sistema de juego! Recibirás un String de comandos separados por comas:CREATE_WARRIOR:name:maxHealth:level:strengthCREATE_MAGE:name:maxHealth:level:intelligence:manaATTACK:attackerName:targetNameHEAL:mageName:amountSTATUS:characterName
Mantén una colección de personajes. Procesa cada comando e imprime:
- CREATE_WARRIOR/CREATE_MAGE:
[name] the [characterClass] joins the battle! - ATTACK: Imprime el resultado del ataque (el String devuelto por el método attack)
- HEAL: Imprime el resultado de la curación, o
[name] cannot healsi el personaje no es un Mage - STATUS:
[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]
Después de todos los comandos, imprime
--- Battle Summary ---seguido del estado de cada personaje.
Recibirás una entrada: el String de comandos separados por comas.
Por ejemplo, con la entrada CREATE_WARRIOR:Thorin:100:5:15,CREATE_MAGE:Gandalf:80:7:12:50,ATTACK:Thorin:Gandalf,HEAL:Gandalf:25,STATUS:Gandalf, tu salida sería:
Thorin the Warrior joins the battle!
Gandalf the Mage joins the battle!
Thorin strikes with brute force for 20 damage!
Gandalf takes 20 damage! Health: 60/80
Gandalf channels healing magic! Health: 80/80
Gandalf (Mage) - Level 7 - Health: 80/80 - Alive
--- Battle Summary ---
Thorin (Warrior) - Level 5 - Health: 100/100 - Alive
Gandalf (Mage) - Level 7 - Health: 80/80 - Alive¡Este desafío combina la herencia (jerarquía de Character), la implementación de múltiples interfaces (Mage implementa tanto Attackable como Healable), los enums con métodos (DamageType), el polimorfismo (tratar de forma uniforme distintos tipos de personajes) y la encapsulación (gestión protegida de health) en un sistema de juego atractivo!
Pruébalo tú mismo
import java.util.Scanner;
import java.util.HashMap;
import java.util.Map;
import java.util.LinkedHashMap;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: Usa una colección para mantener los personajes (LinkedHashMap preserva el orden de inserción)
// LinkedHashMap<String, Character> characters = new LinkedHashMap<>();
// TODO: Divide la entrada por comas para obtener los comandos individuales
// String[] commands = input.split(",");
// TODO: Procesa cada comando:
// - CREATE_WARRIOR:name:maxHealth:level:strength
// Print: "[name] the Warrior joins the battle!"
//
// - CREATE_MAGE:name:maxHealth:level:intelligence:mana
// Print: "[name] the Mage joins the battle!"
//
// - ATTACK:attackerName:targetName
// Imprime el resultado del ataque del método attack
//
// - HEAL:mageName:amount
// Imprime el resultado de la curación, o "[name] cannot heal" si no es un Mage
//
// - STATUS:characterName
// Imprime: "[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]"
// TODO: After all commands, print "--- Battle Summary ---"
// Luego imprime el estado de cada personaje
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy14Desafíos finales
Plataforma de E-LearningSistema bancarioDesarrollo de personajes de videojuegosServicio de alquiler de vehículos3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón IteratorPractica por tu cuenta: Compilador de Java online