Datos personales

domingo, 10 de noviembre de 2024

DEV LOG #1 : replanteando.

Ayer por la noche decidí replantear absolutamente todo lo que tenia montado al rededor de mi supuesto juego en Java. Finalmente me he propsueto a realizar una aventura de texto con algunas interacciones sin subirme a las barbas de nada. Asi fue:

Empezando: La Configuración Inicial

 Lo primero que supe que necesitaba era algo de modularidad, por lo que estructuré el proyecto en categorías claras: game logic (lógica del juego), entities (entidades, como el jugador, las habitaciones y los objetos), y utilities (herramientas para formatear y mostrar texto).

Creé las primeras clases, sobre todo Main.java, donde comenzaría el ciclo del juego, y Game.java, que sería responsable de gestionar el flujo del juego. En este punto, todo estaba hecho "hardcoded", es decir, inicialicé y creé manualmente las habitaciones y los objetos dentro del código. No había archivos externos ni ningún sistema de carga de datos.

Introduciendo Habitaciones y Objetos

Una vez que tenía la estructura lista, me di cuenta de que el siguiente paso lógico era introducir algún tipo de sistema de habitaciones para hacer el juego más dinámico. Comencé con la clase Room, creando una implementación básica donde cada habitación tenía un nombre, descripción y una lista de objetos que se podían recoger.

Inicialmente implementé un método simple para que los jugadores pudieran mirar alrededor y ver la descripción de la habitación, pero no había interacciones complejas aún, solo datos estáticos dentro del código. Los objetos no eran dinámicos; estaban simplemente creados manualmente dentro de cada habitación.

La Necesidad de Room Data: Pasando a JSON

A medida que el juego avanzaba, quedó claro que poner todo el código en el archivo fuente no era la mejor solución para la escalabilidad a largo plazo. Quería poder cargar los datos de las habitaciones desde una fuente externa. Ahí fue cuando se me ocurrió usar archivos JSON.

No tenía mucha experiencia con esto al principio, pero después de investigar un poco, descubrí que la librería Gson sería perfecta. Así que la añadí a mi proyecto y ya estábamos en marcha. El siguiente desafío fue crear la clase RoomData, que almacenaría las propiedades de las habitaciones en un formato que pudiera ser fácilmente convertido en objetos Java mediante Gson.

Con la clase RoomData lista, creé el archivo JSON necesario (roomItems.json) donde se definirían las habitaciones y sus atributos. Este fue un gran paso adelante, porque ahora podía cargar los datos de las habitaciones de manera dinámica, sin tener que escribir todo manualmente en el código.

Construyendo el Flujo del Juego: Inicialización de Habitaciones

En este punto, necesitaba asegurarme de que mi juego leyera los datos JSON, creara las habitaciones y estableciera las salidas entre ellas. Modifiqué la clase Game.java para manejar la carga de las habitaciones desde el archivo JSON. Tardé un poco en hacerlo funcionar correctamente, asegurándome de que los objetos se asignaran correctamente a las habitaciones y las exits (salidas) se enlazaran adecuadamente con otras habitaciones.

La funcionalidad de look around también fue mejorada en esta etapa. Usando las descripciones de las habitaciones del archivo JSON, el jugador ahora podía obtener una sensación más rica de cada entorno. Y los objetos comenzaron a mostrarse junto con las descripciones de las habitaciones. Todos estos datos ahora eran externos, y ya no tenía que escribir todo dentro del código.

Mejorando la Experiencia: Descripciones de Habitaciones

A medida que avanzaba, me di cuenta de que simplemente mostrar una descripción estática de la habitación no era suficiente. Quería añadir más profundidad a las descripciones de las habitaciones para que el juego se sintiera más rico. Ahí fue cuando decidí añadir el campo enhancedDescription (descripción mejorada) a los datos de las habitaciones, que proporcionaría una descripción más vívida y atmosférica de la habitación cuando el jugador escribiera "look around".

Pero no me detuve ahí. Sabía que las descripciones largas serían difíciles de mostrar de una sola vez en la consola. Así que introdujimos saltos de línea (\n) para justificar las descripciones mejor en la consola. Esto requirió editar el texto cuidadosamente para asegurarme de que no se estirara demasiado, manteniéndolo legible sin cortar palabras.

Los Últimos Pasos: Justificando las Descripciones

A medida que finalizábamos las descripciones mejoradas, me aseguré de que todas las descripciones de las habitaciones, incluidas las mejoradas, estuvieran bien justificadas y formateadas para ser leídas en la consola. También me aseguré de que ninguna palabra se cortara de manera incómoda al final de una línea. Esto fue clave para hacer que el juego se sintiera más inmersivo y no como una sobrecarga de información que saturara la pantalla con texto.

Después de hacer que el texto fluyera de manera suave, el juego realmente comenzó a tomar forma. El jugador ahora podía interactuar con cada habitación, ver su descripción y los objetos, y explorar diferentes áreas. El mundo del juego se sentía vivo, dinámico y atractivo.

¿Qué Falta? Un Poco de Pulido

Ahora que teníamos todas las habitaciones, los objetos, las descripciones y las salidas funcionando con archivos JSON externos, lo único que quedaba era pulir la interfaz de usuario y agregar más características, como acciones adicionales para el jugador, manejo del inventario y mejorar el sistema de comandos. Pero el núcleo del juego—cargar datos de habitaciones, mostrar descripciones ricas y proporcionar una experiencia interactiva—estaba sólidamente establecido.

jueves, 24 de octubre de 2024

¿Qué ha pasado?

¿Qué ha pasado? - Actualización

Camino nefasto.

Después de todo este tiempo, no sé si quiera cuándo habrá sido el último día de actualización de este blog. Ni por darme cuenta. De todas formas, no he estado parado.

Claro está que no voy a hacer una actualización de mi vida personal, pero sí de la evolución de este proyecto mío, del world-builing y del desarrollo del supuesto RPG que pretendo crear.

Al final de la parrafada añadiré las imágenes pertinentes contextualizadoras o no completamente innecesarias.

El desarrollo.

Durante estos meses, por decir algo, en mi mente se iba gestando la fatidica idea del desarrollo de un videojuego RPG al más puro estilo japonés clásico por turnos, medieval, de fantasía, con equipo, aliniaciones de este, y un largo etc. Por el camino he aprendido a programar, más o menos, y sigo en ello, aún no soy nada, en Java. Aun me queda múchisimo, por no decir todo, como OOP y la implmenteación de interfaces, pero por el momento, con lo que llevo aprendido, quería ir formando lo que era el esqueleto (figura 1) del juego. Después de más o menos haber creído tenerlo hecho, me lancé de lleno al desarrollo de algún tipo de código pensando en la gran escala. Pensé "Minecraft está desarrollado en Java... Mi proyecto es diez mil veces más sencillo que el juego de Mojang, evidentemente. No creo que sea complicado empezár a desarrollar, por lo menos, algo en texto, si acaso con ASCII, aunque ahora no me preocupe eso.".

Y a ello me dispuse. Hice cosas como las siguientes:

        
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
// Game class
public class Game {
    
    // Attributes
    private String name;
    private int currentLevel;
    private Player player; // Player instance
    private NarrativeManager narrativeManager; // NarrativeManager instance
    private JFrame frame; // Main game window
    private JTextArea textArea; // Text area for game output
    private JTextField inputField; // Input field for user commands
 
    // Constructor
    public Game() {
        this.name = "--------[The Ruins of E'felone ]--------"; 
        this.currentLevel = 0; // Default level
        this.player = null; // No player loaded initially
        createAndShowGUI(); // Create the GUI
    }
 
    // Create and show the game GUI
    private void createAndShowGUI() {
        frame = new JFrame(name);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 400);
        frame.setLayout(new BorderLayout());
 
        textArea = new JTextArea();
        textArea.setEditable(false);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        JScrollPane scrollPane = new JScrollPane(textArea);
        frame.add(scrollPane, BorderLayout.CENTER);
 
        inputField = new JTextField();
        inputField.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String input = inputField.getText();
                handleUserInput(input);
                inputField.setText(""); // Clear input field
            }
        });
        frame.add(inputField, BorderLayout.SOUTH);
 
        frame.setVisible(true); // Show the window
        textArea.append("Welcome to --Arcana Magna --\n");
        mainMenu(); // Show the main menu
    }
 
    // Handle user input from the input field
    private void handleUserInput(String input) {
        switch (input.toLowerCase()) {
            case "1":
                createCharacter();
                break;
            case "2":
                credits();
                break;
            case "3":
                if (player != null) {
                    narrativeManager = new NarrativeManager(textArea, inputField); 
                    narrativeManager.startAdventure(player); // Start the adventure
                } else {
                    textArea.append("You shall create a character first.\n");
                }
                break;
            case "4":
                exit(); // Exit the game
                break;
            default:
                textArea.append("Invalid option. Please choose again.\n");
                break;
        }
    }
 
    // Start the game
    public void start() {
        textArea.append("Comencing adventure.\n");
        textArea.append(name + "\n");
    }
    
    // Show the main menu
    private void mainMenu() {
        textArea.append("Main Menu:\n");
        textArea.append("1. Create Character\n");
        textArea.append("2. View Credits\n");
        textArea.append("3. Start Adventure\n");
        textArea.append("4. Exit\n");
        textArea.append("Choose an option: \n");
    }
    
    // Create a character
    private void createCharacter() {
        String playerName = JOptionPane.showInputDialog(frame, "Enter your adventurer's name:");
        String[] options = {"Warrior", "Mage", "Rogue", "Cleric", "Scout"};
        int classChoice = JOptionPane.showOptionDialog(frame, "Choose thy occupation:", 
                "Character Class", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, 
                null, options, options[0]);
 
        CharacterClass characterClass = null;
 
        switch (classChoice) {
            case 0:
                characterClass = CharacterClass.WARRIOR;
                break;
            case 1:
                characterClass = CharacterClass.MAGE;
                break;
            case 2:
                characterClass = CharacterClass.ROGUE;
                break;
            case 3:
                characterClass = CharacterClass.CLERIC;
                break;
            case 4:
                characterClass = CharacterClass.SCOUT;
                break;
            default:
                textArea.append("Invalid class choice. Defaulting to Warrior.\n");
                characterClass = CharacterClass.WARRIOR;
        }
        
        // Create the player
        player = new Player(playerName, 1, characterClass); // Start at level 1
        textArea.append("You are: " + player.getName() + " the " + characterClass + "\n");
    }
    
    // Show credits
    public void credits() {
        textArea.append("Game developed by Qaffqa.\n");
    }
    
    // Exit game
    public void exit() {
        textArea.append("Exiting game...\n");
        // Save logic can be added here
        System.exit(0); // Exit application
    }
    
    // Main method
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Game game = new Game(); // Create a Game instance
            game.start(); // Start the game
        });
    }
}
        
    

Para el ojo inexperto podrá verse como una barahunda sin sentido de código y sintaxis que ni le va ni le viene. Pero para el ojo enterado o el amateur puede que vea cosas sin sentido de todas formas... Me subí a las barbas... del código, en general. Intenté sobrevenirme en cuanto a la cosas que comprendo y tengo control, y evidentemente, me abrumé.

Más aún cuando, con el ansia de ver algo físico reprensentado en la pantalla de mi ordenador (como se puede ver en el código) usé Swing para hacer la interfaz interactiva. Algo logré, sin saber bien muy cómo. Pero no es lo que quiero. En parte sí, pero mi falta de conocimiento y el auto-atosigamiento por el querer algo YA me ha hecho dar marcha atrás en el desarrollo en Java.


┌──────────────────────────────────────────────────────────────────┐
│                                                                  │
│  ┌───────────────────────────┐ ┌──────────────────────────────┐  │
│  │>.  narración _________    │ │                              │  │
│  │                           │ ┼──────────────────────────────┼  │
│  │ ____________              │ │                              │  │
│  │ ___________________       │ │                              │  │
│  │          _________        │ │                              │  │
│  │                           │ │                              │  │
│  │  1.                       │ │                              │  │
│  │  2.                       │ │                              │  │
│  │  3. (opciones del jugador)│ │                              │  │
│  │                           │ │                              │  │
│  │                           │ │                              │  │
│  │                           │ │                              │  │
│  │                           │ │                              │  │
│  │                           │ ┼──────────────────────────────┤  │
│  │                           │ │┌────────┐┌───────┐┌─────────┐│  │
│  │                           │ ││        ││       ││         ││  │
│  │┌─────────────────────────┐│ │└────────┘└───────┘└─────────┘│  │
│  ││>.   (input del jugador) ││ │┌────────┐┌────────┐┌───────┐ │  │
│  ││                         ││ ││        ││        ││       │ │  │
│  │└─────────────────────────┘│ │└────────┘└────────┘└───────┘ │  │
│  └───────────────────────────┘ └──────────────────────────────┘  │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘
    

Lo dibujado en los carácteres de arriba pretende representar, grosso modo, cómo pretendo que sea la GUI del juego. Algo sencillo.

  1. En el rectángulo de la izquierda se representa todos los elementos textuales de la narración o los menús.
  2. En el rectángulo de la derecha se presenta toda la información gráfica. Tiene, generalmente, dos funciones:
    1. Muestra del mapa de la mazmorra por donde se mueve el jugador. Diseñado en ASCII. Supone la única interacción directa con un espacio abierto.
    2. Muestra las imágenes pertinentes de los eventos que ocurran al interaccionar o ser interaccionado. p.e. Un combate, una tienda, una conversación, abrir un cofre ...
    3. Las secciones de abajo representan los perosnajes pertenecientes a la party del jugador (y el jugador), siendo seis el número máximo
  3. Todas las interacciones del jugador se representan mediante inputs de texto en la caja de comando en el rectángulo de la izquierda.


Hecho todo aquello, intenté volver a RPG Maker. Craso error. Jamás.

Y ahora estoy enfrascado en un proyecto secundario para intentar, de alguna manera, comprender los macros del Harlow en Twine 2... Deseenme suerte.

miércoles, 15 de mayo de 2024

Ilustraciones.

 Pues imagino que es hora de dejar registrado lo que llevo ilustrado.

No he seguido con el libro ... no me funciona el Indesing ... Esto es bastante jodido, la verdad.

En fin.

Maestra de la Cenizas

Un día normal en Aquilón.

Caballero maldito.

Portada.

Noble Drakmoriano - Elfo Pálido.

Guarda de feudo.

Estandartes de algunas de las Casas de Ciendercragg.

Necrófago.

Hechicera de Paraje de Olena.
Esta fue la primera página del cuaderno dedicado exclusivamente al worldbuilding de Kar'Dum.
De izquierda a derecha y de arriba a abajo: Mago de la Séptima Colmena, afueras de Sychia, explorador del lodazal, Caballero Real de Drakmore, Anciano del Concilio.
Texto sagrado cindercraggiano (aún no sé muy bien qué hacer con ello).
Mercenarios.
Mercader errante de las llanuras Sifflants, Zenderlmore - liche, Cordillera de Moungrise.
Aquilón: Sello Real, Canónigo de Arenyá, Castillo de Drakmore, Galeno Real, tendera de la capital.
Guarda de la Casa de Mirladin.
Casa de Mirladin, conocida como Casa de Tól (o Tool, como tengo escrito en inglés, no sé por qué empecé a escribirlo en inglés. Tól/Tool ambos significan herramienta, el primero es simplemente la etimologia de la palabra en inglés antiguo y del nórdico o del islandés etc etc, me he tomado la licencia de usarlo como palabra en Bajo Élfico).


miércoles, 8 de mayo de 2024

Notas para una mecánica de rol

 Dos atributos que sustituyen a la iniciativa o el hit-chance, no lo sé:

Preponderancia y Agallas.

Preponderancia, definición de la RAE: 

preponderancia

De preponderante y -ncia.

1. f. Exceso del pesoo mayor pesode algo respecto de otra cosa.

2. f. Superioridad de créditoconsideraciónautoridadfuerzaetc.

agalla
 

Del lat. galla

8. f. pl. coloq. Arrestos, valentía, audacia. Tener agallas.

Sin.:
  • corajevalorvalentíaánimoaudaciaosadíaredaños.
Ant.:
  • cobardía.

10. f. pl. Ec., Méx., P. Rico, R. Dom. y Ven. Codicia, ansia desmedida. 

O algo parecido.

Estos atributos se tomarían en un tanto de 100% y su media [(prep.+agallas)/2] debería superar el índice de Aura de Temor. Si el resultado es susperior al inidice de A.T, el PJ pasa la prueba.

La Preponderancia puede, por ejemplo, dependender del Carisma, y las Agallas del Poder, dado que este atributo domina la voluntad y la suerte. Si el número del CAR  y POD supera el 18 entonce se le agruega un 10% a el resultado final, o sea: [(prep.+agallas)/2]+10%.



Ejemplo:

Al salir de la posada El Dragón y la Ninfa el Aventurero tropieza con un hombre encapuchado. Muy facilmente sobrepasaba los dos metros de altura y sus anchas espaldas con facilidad ayudaban a que su porte fuera considerable. Mirándolo por encima, como abalanzándose sobre la figura del Aventurero, este declamó: "Suelta absolutamente todo lo que tengas encima, piltrafa."

Aura de Temor a superar: 80%
Atributos del Aventurero: 

  • Poder: 12
    • Agallas: +0
  • Carisma: 9
    • Prepondernacia: +0
  • POD+CAR: 21

El 2d100 respectivametne fueron 72 y 50, por lo que quedaría el resultado final así: [(72+50)/2]+10%=71, por lo que no pasaría la prueba. El DM puede hacer que el PJ responda de la manera que queira, o darle las pautas al jugador para que responda de maenra correspondiente a el estado, que dependiendo del ínidice de Salud Mental del PJ puede ser una o otra.

martes, 7 de mayo de 2024

Dev-Log 0 - 08/05/24

    Bueno, pues entre pitos y flautas he remodelado completament el TTRPG, ya no es un 2d6 ni OSR al hecho, que en realidad no sé muy bien cómo funciona el término --sí claro, Dungeons and Dragons edición uno, etc, Advacance Dungeons and Dragons ... y la historia sigue ad infinitum, por lo que no me voy a comer la cabeza. 

NOTA: Al parecer la versión que tengo de Strombringer es la 4ª, de 1990, el cual no usa el sistema de d20 y no es un OSR al hecho, sino un BRP, que es especial, segun dice la wikipedia, para fantasia heroica. Esta respuesta en un foro lo describe mejor; añadiendo a la mesa el sistema GURPS.

    Bueno, pues eso, que no estoy haciendo un DnD retroclone sino más bien un BRP, un RuneQuest retro-clone. Estas cosas son taxonomía de geek, la ciencia del friki. Una serie de clasificiaciones que si bien quedan interesantes en un subtítulo, o para citar las fuentes de donde viene el sistema que voy a usar, en el sentido práctico no me la podría refanfinflar menos, vaya.

sábado, 20 de abril de 2024

Kar'Dum TTRPG 2d6 Rouge-like Dungeon Crawler

  Pues yo creo que el título de esta entrada es bastante sencillo. Gracias de antemano a Sleepdrifter por la completa inspiración de este neuvo proyecto. Ya dije en otra entra que pretendia hacer un videojuego (RPG Maker XP, o Twine) pero no soy desarrollador, y ciertamente se me hace cuesta arriba, por lo que otra opción es el clásico Tabletop Role Playing Game de toda la vida.

  Mi idea es hacer algo sencillo primero, para luego, según vaya desarrollando más contexto e historia para mi mundo, hacer todo el libro nuclear que componga un juego de rol de mesa en condiciones, extenso y desarollado.

 Cogeré cosas de aquí y por allá, por ejemplo pretendo usar los atributos y habilidades del The Elder Scrolls II: Daggerfall, usar un sistema de 2d6 y hacerlo bajo las premisas del Old School Renaissence todo lo posible. Otra de las bases de juego que pretendo usar es White Box, en concreto para este dungeon crawler (y ya saltar a Swords & Wizardry una vez vaya a hacer la versión mayor).

La verdad es que mi mente es bastante impulsiva con estas cosas, no lo sé cómo lo iré haciendo, pero se irá publicando con el tiempo .... 

viernes, 19 de abril de 2024

Sobre pueblos y hombres. Drakmore.

  En las tierras de Kar'Dum existe cierto terruño, conocido como la península Hippocampea, donde conviven en incertidumbre gran parte de las razas, llamaremos, humanoides —siendo estas: humanos, elfos (en concreto elfos pálidos y elfos del bosque), medio-elfos, enanos y orcos— así como las razas bestia de los bosques de la Arboleda de Ynelia y de las Sombras de Árenya y los anfibios y reptiloides de las costas y lodazales del sur.

  Toda la península Hippocampea forma parte del reino de Drakmore, cuyas raíces se adentran en la historia siglos ha. En el año que consta, de la Era de las Espinas, su poder se extiende principalmente por el norte, la cabeza de la península, sin llegar hasta la Costa Amarga, fuertemente gobernada por colonias de orcos venidos allende del Havunmeer, el mar del sur, cuyas tierras son desconocidas para los drakmorianos.

   El pueblo drakmoriano es bastante bélico, habiendo tenido largas y numerosas trifulcas con sus ascendientes elfos dorados del norte, en las tierras de Diyunra’Avot, más allá del Mar de Bruma. Sus costumbres bélicas nacieron despues de la indepencia respecto de la Troika Dorada de los Altos Elfos en la capital de Thalgroth. Casi todas las razas humanoides descienden de estos elfos de piel dorada milenarios que, con el paso del tiempo antes si quiera de las Eras que hoy se conocen, derivaron posteriormente en ellas.



   El rey actual, en la tercera era, Thorne de Aquilón, dista de estas costumbres belicistas, y tras su baja guardia en el trono de Aquilón, el grupo de mercenarios conocido como el Anillo del Furor destronó al rey, actualmente en paradero desconocido, y usurpó la corona. Sumiendo así todo el territorio en el caos. Sin embargo se oyen habladurías y rumores de que un elfo pálido vaga por las tierras de Drakmore en servicio del rey para restaurar el orden, se dice, bajo decreto real, junto con dos compañeros más.


   Entre toda la barbarie que azota al reino drakmoriano, se alzan grupos de bandidos diversos, poco organizados y desastrosos que arrasan aldeas y caminos, y en contraposicion, grupos paramilitares de guardias y aldeanos intentan fortalecerse contra las menazas externas al no contar con el apoyo de una corona inexistente por el momento.

   Los únicos sitios donde parece que la paz sigue reinando en tiempos actuales es en el Bosuqe de Las Sombras de Árenya, donde los humanos y elfos de las ciudades no se atreven a deambular; habitados por tabaxi y demás tipos de razas bestiales de todo tipo, asi como humanos y elfos devotos de los dos dioeses dragones e Ynelia.

  Al norte, por encima de la capital de Aquilón se extienden las verdes llanuras de Sifflants, donde se situa la ciudad-biblioteca de Jelafaat, la primera y única ciudad humana no descendiente de los elfos dorados, provenientes de los desiertos, terra ignota, austral de lo conocido por los drakmorianos, los cuales se niegan a pasar la Cordillera de Moungrise, que se extiende desde la espina del hippocampo hasta los pantanos del sur que dividen la península, aislándolos de las demás tierras. Una de las razones de esta negativa viene porque el Paso Transmontanus de la cordillera está controlado por un anciano liche llamado Zendelmor.

Al sur de la capital se encuentra el la Arboleda de Ynelia, diosa de los elementos, así como el Lago del Ojo, espeso bosque espolvoreado de asentamientos, asi como de  ruinas de eras pasadas. En el centro del bosque se encuentra una capilla dedicada a Teneas, la cual es lugar de peregrinación para muchos drakmorianos.

Bajando por la Costa Amarga llegamos hasta el límite de la boca del hippocampo, donde se situa la colonia de Zulgakh, hogar de los orco más allá del mar del sur.


Bienvenido.

¡Bienvenido a los Archivos del la tierras de Kar'Dum, navegante!     Si sigue mis andanzas de plulma y tinta, se habrá dado cuenta de qu...