Autor Tema: Cómo programar un juego por turnos en Java con personajes y niveles dificultad  (Leído 17079 veces)

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
Con la clase BufferedWriter se puede ir añadiendo líneas de texto a un fichero.

Hay que tener en cuenta que en este programa, estamos publicando líneas desde distintas clases, no solo desde la clase main.
Cuando un personaje ataca, lo que sale en pantalla se está publicando desde la clase Personaje

O si un mago usa el hechizo de sanación, esto se publica desde la clase Mago

Así que habría que añadir un objeto BufferedWriter a todas las clases.

Aunque, si somos un poco listos  ;D, en lugar de eso, lo que haremos será crear una nueva clase que incluya ese objeto BufferedWriter y un método estático que se encargue de escribir en fichero el mensaje String que le indiquemos.
Así podemos llamar a esta clase desde las otras, sin tener que ir una por una declarando y configurando un BufferedWriter

Eso si solo somos un poco listos, pero si resulta que somos muy listos  8), lo que además vamos hacer es que esta nueva clase, también se encargue de mostrar el mensaje en pantalla.
Porque si no, vamos a tener que estar repitiendo dos veces cada mensaje que queramos publicar, una para el fichero y otra para la pantalla.
Pues en lugar de eso, que esta nueva clase se encargue de publicar el mensaje en ambos sitios.
Así que en el resto de clases, ya no usaremos la instrucción System.out.println(), a no ser que se trate de algún mensaje destinado únicamente para pantalla.
Para los que queramos publicar en ambos medios, se los pasaremos a la nueva clase, que podemos llamar Publicador
Código: [Seleccionar]
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class Publicador {

public static void publicar(String mensaje) {

//Publicamos en pantalla
System.out.println(mensaje);
//Publicamos en fichero
try {
BufferedWriter escritor = new BufferedWriter(new FileWriter("d:/log/combate.txt", true));
escritor.write(mensaje);
escritor.newLine();
escritor.close();
} catch (IOException e) {
System.err.println("No se pudo escribir en fichero");
}
}

}
Importante escoger una ruta de archivo donde sepamos que no vamos a tener problemas de permisos de escritura y tal.

Ahora, en el resto de clases, vamos sustituyendo los system.out por llamadas al Publicador

Por ejemplo, en el método atacar() de Personaje, lo que antes publicábamos en pantalla:
Citar
   public int atacar() {
      System.out.println(nombre + " ataca.");
      Random azar = new Random();
      //Ataque mínimo: 1, Maximo: según nivel de ataque
      int puntosAtaque = azar.nextInt(ataque) + 1;
      
      //Damos un 10% de posibilidad de obtener un "Ataque Crítico"
      int valor = azar.nextInt(100);

      if (valor%10 == 0) { //Comprobamos si es multiplo de 10
         System.out.println("¡" + nombre + " consigue un Ataque Crítico!");
         //Un "Ataque Crítico" duplica el daño del ataque
         return puntosAtaque * 2;
      }
      else
         return puntosAtaque;
   }

Ahora lo hacemos con el Publicador en ambos soportes:
Citar
   public int atacar() {
      Publicador.publicar(nombre + " ataca.");
      Random azar = new Random();
      //Ataque mínimo: 1, Maximo: según nivel de ataque
      int puntosAtaque = azar.nextInt(ataque) + 1;
      
      //Damos un 10% de posibilidad de obtener un "Ataque Crítico"
      int valor = azar.nextInt(100);

      if (valor%10 == 0) { //Comprobamos si es multiplo de 10
         Publicador.publicar("¡" + nombre + " consigue un Ataque Crítico!");
         //Un "Ataque Crítico" duplica el daño del ataque
         return puntosAtaque * 2;
      }
      else
         return puntosAtaque;
   }


En las clases Personaje, Caballero y Mago, cambiaremos todos los system.out por el "publicador".

En la clase Combate, puede que no queramos sustituirlos todos.
Por ejemplo, los del método para crearPersonaje() donde nos sale un menú para elegir personaje, nombre, nivel de ataque, etc... pues eso no hace falta que salga reflejado en el fichero de texto.
Aunque eso ya va a gusto de cada uno.

Una cosa necesaria que sí vamos a tener que hacer en Combate es añadir un método para "preparar el fichero".
Más que prepararlo, en realidad lo que hará será comprobar si ya existe. Si existe, lo elimina y creará uno nuevo.
Esto es para que cada vez que ejecutemos el juego, el fichero se renueve y solo salgan los datos de la última partida.

Código: [Seleccionar]
private static void prepararFichero() {
File fichero = new File("d:/log/combate.txt");
if (fichero.exists()) {
fichero.delete();
try {
fichero.createNewFile();
} catch (IOException e) {
System.err.println("No se pudo crear fichero: " + "d:/log/combate.txt");
}
}
}

Y es al primer método que llamaremos en el main()
Código: [Seleccionar]
public static void main(String[] args) {

prepararFichero();

crearPersonaje();

elegirDificultad();

//Comienza el combate...
while(jugador.getVida() > 0 && CPU.getVida() > 0) {


A no ser que quieras que se guarden TODAS las partidas.
En ese caso, se podría cambiar y hacer que por ejemplo se añada una línea con la fecha y hora actuales, para separar las líneas de cada partida.


En fin, si se ha hecho todo esto bien, podemos ver que ahora los mensajes de la terminal, quedan reflejados también en un fichero de texto




Y eso es todo, cualquier duda, solo hay que preguntar.
Un saludo
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

ALPER

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 1
    • Ver Perfil
Adjunto un zip en este mensaje con el código.
Por cierto, aunque este tema es largo, es interesante leerlo para ver como fue la evolución de la creación del programa y entenderlo mejor.

Si surge alguna duda, consultadla por aquí.

Un saludo.

me gustaria saber si se podria realizar simplemente en un archivo con multiples funciones

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
me gustaria saber si se podria realizar simplemente en un archivo con multiples funciones

¿Te refieres a hacerlo todo en un único archivo .java?

Sí, se puede hacer. Pero no es nada recomendable. Sería totalmente opuesto a las "buenas costumbres" de programación.

Un programa con tantas clases, aunque algunas clases sean de pocas líneas, siempre mejor "modularlo" en distintos archivos .java, e incluso lo correcto sería separarlos en distintos packages

A lo sumo, se podrían agrupar en un mismo archivo .java la clase Personaje y el resto de sus clases "hijas".

Pero juntarlo TODO en un único archivo .java..., no interesa tener un archivo gigantesco de cientos de líneas.
Si necesitamos hacer un cambio concreto en la clase Mago, es más fácil localizar la línea que queremos modificar si la clase está escrita en su propio archivo que si está entre todo el barullo de clases en un único archivo.

Además, puede que luego queramos escribir otro programa similar y reutilizar únicamente la clase Personaje
Si está en su propio archivo, podremos hacer un import solo de esta clase. Pero si está todo junto en un único archivo, el import tendrá que ser de TODAS las clases, lo cuál no es óptimo y además nos puede generar duplicidades si en nuestro "nuevo" programa queremos escribir clases con el mismo nombre que las clases del programa "antiguo" que en realidad no queríamos utilizar, pero que hemos importado innecesariamente.

"Divide y vencerás" suele decirse en programación. Y se refiere a esto, a modular los programas en distintos segmentos y archivos
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Esta interesante tu proyecto, con un poco de trabajo puede convertirse de juego por consola a un videojuego grafico, se podria usar casi todo el codigo ya implementado, de hecho tal vez lo haga

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Consegui convertir el juego en un videojuego, pero al final si tuve que reescribir bastante codigo( unas 8 clases mas), si quieren se los comparto, pero no se si se pueda por las imagenes y la restriccion de tamaño

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
Sería interesante, pero como dices, probablemente no puedas colgar un zip en tu mensaje por el peso de las imágenes que estés usando.

Quizás puedas subirlo a Google Drive o similar y compartir el enlace.


Un saludo.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Igual tal.vez en partes se pueda, aunque aclaro que el codigo cambio bastante, las acciones ahora se definen en clases y no en metodos, y Mago y Caballero ahora solo tienen constructor, ya que toda la funcionalidad viene de Personaje, el sistema usado para consola era muy dificil de adaptar a graficos, ya que habia que sincronizar la logica del combate con las animaciones, ademas , el juego se ejecuta en dos threads(el awt, que se encarga de la parte grafica, y otro que se encarga de la logica de combate)

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Ya esta, aqui va el codigo, las imagenes las enviaré separadas, les toca a ustedes colocar cada una en su carpeta, consegui reducir el tamaño total reemplazando la imagen de fondo por un fondo renderizado dinamicamente, escriban por cualquier duda
« Última modificación: 19 de Marzo 2024, 22:16 por YoanPupo »

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Las imagenes del Caballero, coloquenlas en la carpeta Caballero, las del Mago en Mago, ahi van las del Caballero

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Y aca las del Mago

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Como dato la clase Battle, que se encarga de la logica de batalla, y BattlePanel, que se encarga de la visualizacion, no saben que tipo es cada personaje, ni quien los controla, perfectamente pueden ser dos jugadores, o dos CPU.
Como demostracion des-comenten esta linea dentro del metodo reset de la clase visual

//jugador.setActionSelector(new CPUActionSelector());

Y comenten esta

jugador.setActionSelector(new PlayerActionSelector().setPanel(actionListPane));

Luego vean lo que pasa, usen el mago en modo dificil o su personaje no vivirá mucho



Ahi va el codigo
« Última modificación: 19 de Marzo 2024, 22:19 por YoanPupo »

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".