Registrarse

[RPGXP] Cómo leer y analizar errores, así como debuggear código

Manurocker95

Doctorando en Ingeniería Biomédica & Game Dev
Miembro insignia
¡Hola! Según he visto este tiempo, muchísima gente tiene problemas con el código. Es algo normal si nunca habéis programado, pero mandar el error a otros esperando que lo solucione, no ayuda a nadie. Es por esto que espero que la gente tome este tutorial y le eche ganas y tiempo. Este tutorial está dedicado a Pokémon Essentials, pero adaptándolo, sirve para cualquier programa y cualquier lenguaje.

1) Introducción: Ruby

Lo primero que tenemos que saber es que RPG Maker XP usa RGSS que está basado en Ruby. Ruby es lo que se llama un "lenguaje de programación orientado a objetos" ó POO. Para hacerlo simple, miremos esto como si fuera un juego de rol. Un equipo está formado por un grupo de 1 a N (pudiendo ser N cualquier número) personajes, y cada personaje tiene cualidades propias. Da igual de donde vengan, cada uno tiene sus cosas. Bien, en POO ese "personaje" se conoce como "objeto". Cada objeto es de un tipo ó, como se le denomina en programación, "clase" y cada clase tiene atributos/propiedades (características) y métodos (comportamientos).

Así, si queremos definir cómo es alguien lo haremos con:

class MiClase
# propiedades y métodos
end

Pero esto no implica que ese objeto exista. Que yo piense el concepto de "persona asiática de origen japonés que come arroz", no hace que aparezca a mi lado, ¿verdad? Tendría que crear un objeto, asignarle la clase "persona", sus propiedades serían "asiática" y "origen japonés" y su comportamiento "comer arroz".

¿Y cómo sé que en ruby algo es una propiedad (característica) o un método (comportamiento)?

Por un lado, dentro de la definición de ese concepto de clase, los métodos tienen "def" justo antes del nombre. Esto es porque estamos "definiendo el método". Las propiedades, por el contrario, no lo tienen. Un método puede tener o no, un valor de retorno y le podemos pasar de 0 a N (siendo N cualquier número) argumentos (información añadida en variables) para que este los use.

¿Por qué?

Porque se utilizan en lo que se denominan "variables", que son contenedores de datos. Una variable SOLO existe en su mundo y SOLO se pueden utilizar una vez se les ha asignado un valor. Al asignarles un valor, se les asigna un tipo del tipo de dicho valor. Si no, su valor sería nulo (null o nil dependiendo del lenguaje). A esto se le denomina "declaración de una variable".

Respecto a su acceso, las variables pueden ser globales (cuando vemos que tiene "$" justo antes. Ejemplo: $Trainer, es una variable global (que se puede acceder desde cualquier parte y modificar sin necesidad de ninguna referencia a ella); variable de clase, como (solo existe dentro de esa clase); públicas pero propias de una clase (cuando vemos que tienen un @ en su uso en la clase) o de un método si no lo tienen y se declaran en el método.

Para acceder a las variables de un objeto, éste tendrá que tener un método que nos permita acceder a dicha variable. Si la variable es global, se declara fuera de toda clase y se le asigna el valor en una. Si una variable tiene un accedo que permite solo la lectura ("attr_reader"), no podrá ser modificada desde otro objeto que no sea él mismo, es decir, que si yo tengo un atributo "ser guapo" de solo lectura, solo yo podré establecer si lo soy o no. Si es de acceso total ("attr_accessor"), cualquiera podrá acceder y modificar su valor.

Los objetos se almacenan en variables al igual que sus propiedades, pero al igual que estas, deben tener un valor. Para asignar un valor a una variable de un objeto (de una clase), lo haremos con "nombre de la variable = Nombre de la clase.new". Por ejemplo, si vamos al main, en el método "pbCallTitle", vemos que está devolviendo un " Scene_DebugIntro.new". Es decir, ese valor, podríamos guardarlo en una variable y así tener acceso a sus variables y métodos.

La creación del valor de un objeto se denomina "instanciación" o "creación de una instancia de un objeto" ya que estamos creando una instancia y guardandola en una variable. Es importante destacar que cuando un objeto se instancia se llama a un método (comportamiento) de inicialización, llamado "constructor". En Ruby, como han sido muy originales, al constructor lo han llamado "initialize".

2) Leer errores

Supongamos el siguiente error que nos ha saltado:

1587397285135.png


Vamos a analizarlo:

Paso 1) Ver el tipo de excepción:

Lo primero, nos sale "Exception: Argument Error". Esto nos indica que es un error en los argumentos de algún método.

Paso 2) Ver el mensaje: "Message: wrong number of arguments (0 for 1)". Es muy importante leer esto, porque nos indica exactamente qué error es. En este caso, esto es porque parece ser que algún método está recibiendo 0 argumentos, cuando esperaba 1. Si no sabéis inglés, podéis traducirlo en google translator.

Paso 3) Ver la línea en la que sucede: Justo después de el mensaje nos pone la línea donde ha fallado la compilación. Salvo que haya errores en los que falte algún "end" de cierre de clase, método o condición, nos pondrá la línea exacta donde está el error. Abrimos los scripts y vamos a ese Script y línea. En caso del ejemplo:

Script: Game_map y línea 40

1587397641790.png


Como podemos ver, estamos guardando el valor de retorno del método "load_map" en la variable "@map", pero parece ser que este método debería ser así:

1587397709032.png


ya que el método recibe una cadena de caracteres. ¿Cómo lo sabemos? Porque si buscamos con Control + Shift + F, podemos buscar cualquier cosa entre todos los scripts. Tendremos que buscar la que se nos ajuste.

1587397794160.png


Debe coincidir el número y valor de parámetros/argumentos que mandamos a los métodos.


Ejemplo 2: No existe un método/variable en una clase:

1587397912604.png


En este ejemplo, estoy llamando a "pokedex" cuando no hay nada así. Recordemos que la programación SÍ distingue entre mayúsculas y minúsculas.

Esto mismo puede pasar si el valor de esa variable es nulo. Así, que debemos comprobar que antes de usar esa variable, la misma tenga valor.

3) Quick tip: Debuggear con Debug log

Esta tip es algo propio de Pokémon Essentials. Hay una función que permite mostrar textos por consola de comandos mientras jugamos para así poder debuggear código (comprobar que todo funciona bien). Para utilizarla, mientras jugamos debemos pulsar F7 y se abrirá, pero veremos que no saca nada.

Antes, debemos modificar el método PBDebug.log(msg) y dejarlo así:

def PBDebug.log(msg)
echo("#{msg}\r\n")
if $DEBUG && $INTERNAL
@@log.push("#{msg}\r\n")
if @@log.length>1024
PBDebug.flush
end
end
end

De esta manera, podremos debuggear cada parte que queramos del código:

1587398253324.png


Si queremos comprobar si el código pasa por una parte u otra (para así encontrar el bug), podemos hacerlo mediante la consola de debug.

¡Y eso es todo!
 

Adjuntos

Arriba