Componente de personaje de juego
Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy — lección 69 de 70.
Desafío
Fácil¡Vamos a construir un sistema de personajes de juego utilizando el patrón de arquitectura basado en componentes! En lugar de crear jerarquías de herencia rígidas, compondrás personajes adjuntando componentes independientes que manejan comportamientos específicos, un enfoque flexible ampliamente utilizado en el desarrollo de videojuegos.
Organizarás tu código en cinco archivos:
IComponent.cs: Define una interfazIComponenten el espacio de nombresGame.Components. Cada componente debe tener un métodoUpdate()que imprima lo que el componente está haciendo.HealthComponent.cs: Crea una claseHealthComponentque implementeIComponent. Debe rastrear los puntos de salud actuales y máximos, con métodos paraTakeDamage(int amount)yHeal(int amount). La salud nunca debe bajar de 0 ni superar el máximo. Incluye unevent Action<int> HealthChangedque se dispare cada vez que la salud cambie, pasando el nuevo valor de salud. El métodoUpdate()debe imprimir el estado de salud actual.InventoryComponent.cs: Crea una claseInventoryComponentque implementeIComponent. Gestiona una lista de nombres de objetos con los métodosAddItem(string item)yRemoveItem(string item)(devuelve unboolindicando el éxito). El métodoUpdate()debe imprimir el contenido del inventario.Character.cs: Crea una claseCharacteren el espacio de nombresGameque contenga una colección de componentes. Tu personaje necesita una propiedadNamey estos métodos:AddComponent(IComponent component)- adjunta un componente al personajeGetComponent<T>()donde T : IComponent - devuelve el primer componente de tipo T, o null si no se encuentraUpdateAll()- llama aUpdate()en cada componente adjunto
Program.cs: Une todo creando un personaje, adjuntando componentes y procesando comandos.
Recibirás las siguientes entradas:
- Nombre del personaje
- Salud máxima inicial para el HealthComponent
- Número de comandos a procesar
- Para cada comando: la acción seguida de los datos relevantes
Formatos de comando:
damage
{amount}
heal
{amount}
add_item
{itemName}
remove_item
{itemName}
updateFormatos de salida:
- Cuando la salud cambia (vía evento):
Health changed: {newHealth} - Al añadir un objeto:
Added: {itemName} - Al eliminar un objeto:
Removed: {itemName}oItem not found: {itemName} Update()de HealthComponent:Health: {current}/{max}Update()de InventoryComponent:Inventory: {item1}, {item2}, ...oInventory: empty
Por ejemplo, si las entradas son:
Hero
100
7
add_item
Sword
add_item
Shield
damage
30
heal
10
remove_item
Potion
remove_item
Sword
updateLa salida debería ser:
Added: Sword
Added: Shield
Health changed: 70
Health changed: 80
Item not found: Potion
Removed: Sword
Health: 80/100
Inventory: ShieldObserva cómo el personaje no hereda de nada especial; simplemente contiene componentes que proporcionan comportamiento. El método GetComponent<T>() utiliza genéricos para una recuperación segura de tipos, y los eventos notifican cuando la salud cambia. ¡Este enfoque de composición te permite mezclar y combinar componentes libremente!
Pruébalo tú mismo
using System;
using Game;
using Game.Components;
class Program
{
public static void Main(string[] args)
{
// Leer el nombre del personaje
string characterName = Console.ReadLine();
// Leer la salud máxima inicial
int maxHealth = Convert.ToInt32(Console.ReadLine());
// Leer el número de comandos
int numCommands = Convert.ToInt32(Console.ReadLine());
// TODO: Crear un Character con el nombre dado
// TODO: Crear HealthComponent con maxHealth e InventoryComponent
// TODO: Suscribirse al evento HealthChanged para imprimir: Health changed: {newHealth}
// TODO: Agregar ambos componentes al personaje
// TODO: Procesar cada comando
for (int i = 0; i < numCommands; i++)
{
string command = Console.ReadLine();
// TODO: Manejar cada tipo de comando:
// - "damage": leer la cantidad, llamar a TakeDamage en el componente de salud
// - "heal": leer la cantidad, llamar a Heal en el componente de salud
// - "add_item": leer el nombre del objeto, llamar a AddItem en el componente de inventario
// - "remove_item": leer el nombre del objeto, llamar a RemoveItem en el componente de inventario
// - "update": llamar a UpdateAll en el personaje
}
}
}
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosNamespaces y directivasIntro a clases y objetosLa palabra clave 'this'Métodos y parámetrosCampos vs PropiedadesConstructoresInicializadores de objetosResumen - Calculadora simple4Herencia
Sintaxis básica de herencia (:)La palabra clave 'base'Palabras clave Virtual y OverrideClases selladas (Sealed)La clase base 'object'Resumen: Jerarquía de empleados7Características avanzadas
Sobrecarga de operadoresIndexadores (this[])Sobrescritura de ToString()Métodos de extensiónResumen - Lista personalizada10Patrones de diseño - Parte 1
Introducción a los patrones de diseñoSingleton Thread-SafePatrón FactoryPatrón Observer (Eventos)Patrón Strategy13Desafíos finales
Plataforma de e-learningComponente de personaje de juegoServicio de alquiler de vehículos2Propiedades y miembros estáticos
Propiedades autoimplementadasPropiedades de solo lectura y escrituraCampos y métodos estáticosClases estáticasMiembros con cuerpo de expresión5Polimorfismo e Interfaces
Polimorfismo: Compilación vs. EjecuciónInterfaz vs. Clase AbstractaInterfaces MúltiplesInterfaces ExplícitasUpcasting y DowncastingRepaso: Calculadora de Figuras8Conceptos avanzados de POO
Composición sobre herenciaGenéricos (clases y métodos)Delegados y eventosAtributos y ReflexiónIDisposable y la sentencia usingFundamentos de Inyección de dependencias11Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite3Arquitectura de clases
Datos de instancia vs. estáticosPalabras clave 'readonly' y 'const'Campos de respaldoResumen - Gestor de cuentas bancarias6Encapsulamiento
Modificadores de accesoPropiedades para el encapsulamientoImplementación de ocultamiento de datosPatrones de inmutabilidadRepaso - Registros de estudiantes