Kabosu - Creando cosas

Logo de la página. Gato esférico con colores verdoso.

Paella Pixel Dungeon (parte 4): modificando el código

Publicado: 2024-02-12 (actualizado 2024-10-04)

Etiquetas: Java, Juegos, Proyectos, Reto de la Paella


Actualizado el día 2024-10-04 para corregir unos pocos errores ortográficos.

Logo de Paella Pixel Dungeon

Una vez añadido el sprite de la paella al Shattered Pixel Dungeon tal y cómo expliqué en el artículo anterior. Lo siguiente es añadir el ítem al juego con su característica principal: solo aparece los domingos.

Crear un alimento parece sencillo. Hay que crear una clase que extienda Food. Eso hace que herede que todos los comportamientos de Ration, que es el alimento por defecto, así que sólo hay que cambiar el sprite. Aquí está la nueva clase core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/food/Paella.java

public class Paella extends Food {
  {
    image = ItemSpriteSheet.PAELLA;
  }
}

Para saber qué otros sitios hay que modificar hago una búsqueda rápida del código.

$ grep -r FOOD .

La mayoría de resultados están en el directorio de comida pero FOOD también aparecen el fichero Level.java. Parece que es la clase en la que se generan los niveles del juego en la función create:

public void create() {

  Random.pushGenerator( Dungeon.seedCurDepth() );
  if (!Dungeon.bossLevel() && Dungeon.branch == 0) {

    addItemToSpawn(Generator.random(Generator.Category.FOOD));
	...

Lo primero que hace la función es añadir un ítem de comida a cada nivel si no es un nivel de boss. Supongo que es para asegurar que cada nivel tiene al menos algo de comer.

Yo quiero que la paella solo salga en domingo así que hay que comprobar la fecha de alguna forma. Ojeando el código he visto que hay algunas comidas especiales que solo aparecen en determinadas fiestas: Pascua, el año nuevo lunar, la semana del Orgullo... Esos días o semanas están definidos en el fichero Holiday.java. Añado ahí mi función para saber si es domingo.

public static boolean isSunday() {
  LocalDate today = LocalDate.now();
  DayOfWeek dayOfWeek = today.getDayOfWeek();
  return DayOfWeek.SUNDAY.equals(dayOfWeek);
}

En el segundo artículo de este reto ya hablé de la clase Generator en la que hay un array llamado FOOD que contiene los alimentos que pueden salir en el juego. Voy a añadir ahí la paella pero solo si es domingo.

if (!Holiday.isSunday()) {
  FOOD.classes = new Class<?>[]{
    Food.class,
    Pasty.class,
    MysteryMeat.class};
  FOOD.defaultProbs = new float[]{ 4, 1, 0};
} else {
  FOOD.classes = new Class<?>[]{
    Food.class,
    Pasty.class,
    MysteryMeat.class,
    Paella.class };
  FOOD.defaultProbs = new float[]{ 4, 1, 0, 100 };
}

Entiendo que el array defaultProbs representa los pesos de cada ítem dentro del generador aleatorio. Yo quiero que la paella salga bastante si es domingo así que le he puesto un número bastante grande. Si no es domingo la paella no aparece, que no somos guiris.

Con los cambios que he hecho hasta ahora espero que, si es domingo, el alimento que aparece en cada nivel sea una paella con el 95% de probabilidad. Para poder probarlo mejor voy a hacer que si es domingo aparezcan en el nivel muchas paellas. Modifico el código de Level.java que he enseñado más arriba para que los domingos añada muchos alimentos a cada nivel.

public void create() {

  Random.pushGenerator( Dungeon.seedCurDepth() );
  if (!Dungeon.bossLevel() && Dungeon.branch == 0) {

    addItemToSpawn(Generator.random(Generator.Category.FOOD));

    if (Holiday.isSunday()) {
      addItemToSpawn(Generator.random(Generator.Category.FOOD));
      addItemToSpawn(Generator.random(Generator.Category.FOOD));
      addItemToSpawn(Generator.random(Generator.Category.FOOD));
      addItemToSpawn(Generator.random(Generator.Category.FOOD));
      addItemToSpawn(Generator.random(Generator.Category.FOOD));
      addItemToSpawn(Generator.random(Generator.Category.FOOD));
      addItemToSpawn(Generator.random(Generator.Category.FOOD));
    }

    ...

Pues ya estaría el ítem. Ahora a probar y ver que todo funciona. Esta vez sí que he guardado los cambios en los ficheros.

La paella aparece múltiples veces en cada nivel. A veces varias de ellas en la misma habitación. ¡Misión cumplida!

Captura de pantalla de Shattered Pixel Dungeon. Muestra una habitación en la que aparecen 3 paellas

Captura de pantalla de Shattered Pixel Dungeon. Muestra una habitación en la que aparece una paella

Justo cuando iba a dar el reto por concluido me he dado cuenta de que al mostrar la información de la paella aparece la descripción de Ration. Claro, se me ha olvidado añadir el texto propio de la paella.

Captura de pantalla de Shattered Pixel Dungeon. Muestra la descripción de la paella pero el texto es del alimento por defecto

No parece que se definan los textos en la clase Paella así que busco la cadena que me ha aparecido para encontrar el fichero que necesito modificar:

$ grep -r "Nothing fancy" .
./core/src/main/assets/messages/items/items.properties:items.food.food.desc=Nothing fancy here: dried meat, some biscuits - things like that.

En properties.items están todas las cadenas de texto relativas a los ítems. Incluyendo descripciones de todos los alimentos. Basándome en las cadenas de stewedmeat creo las de la paella.

items.food.paella.name=Paella
items.food.paella.eat_msg=You ate best paella in the whole dungeon. It even had socarrat!
items.food.paella.desc=A paella with bomba rice, chicken, garrofó, bachoqueta and all the standard ingredients. No chorizo or peas allowed.

Ahora, tras recompilar el juego, ya aparece la descripción de la paella en el inventario y el mensaje personalizado al comerla.

Captura de pantalla de Shattered Pixel Dungeon. Muestra la descripción de la paella: A paella with bomba rice, chicken, garrofó, bachoqueta and all the standard ingredients. No chorizo or peas allowed.

Captura de pantalla de Shattered Pixel Dungeon. Muestra el panel de mensajes del juego con la frase que aparece al comer la paella: You ate best paella in the whole dungeon. It even had socarrat!

Un detalle del que me he dado cuenta: el juego permite guardar partida y parece que genera los niveles al iniciarse así que realmente mi ítem no va aparecer solo los domingos si no que va a aparecer en partidas empezadas en domingo. Es una sutil diferencia.

Los artículos de este reto son estos:


Artículo siguiente: Paella Pixel Dungeon (parte 5): probando el resultado y conclusiones
Artículo anterior: Paella Pixel Dungeon (parte 3): visualizando el sprite