Documentos de Académico
Documentos de Profesional
Documentos de Cultura
De Los Eventos A La Programacion RGSS
De Los Eventos A La Programacion RGSS
Requerimientos..............................................................................................1
Objetivos.........................................................................................................2
Pseudocodigo.................................................................................................2
Introduccion basica a la programacion .........................................................2
Ruby y RGSS.................................................................................................3
Como testear rapidamente.............................................................................3
Switches/Interruptores e introduccion basica a ruby.....................................4
Variables.........................................................................................................5
Operaciones y valores basicos......................................................................5
Condicion y efectos I......................................................................................7
Condicion y efectos II, eventos comunes y pseucodigo................................8
Comentarios y claridez del codigo...............................................................10
Eventos comunes: Funciones I....................................................................11
Eventos comunes: Funciones II y numeros aleatorios................................12
Condicionales avanzados............................................................................14
Variables II y strings.....................................................................................15
Objetos.........................................................................................................16
Herencia.......................................................................................................18
Todo es un objeto en ruby............................................................................20
Libreria estandard de ruby ..........................................................................21
Errores..........................................................................................................21
Bucles...........................................................................................................22
Arrays...........................................................................................................25
Iterando en listas y hashes...........................................................................28
Del pseudo codigo a la realidad...................................................................31
Testear II......................................................................................................32
Reusabilidad del codigo y librerias...............................................................32
Entender el codigo RGSS y los datos del rpgmaker....................................33
Proyecto final de tutorial (mi primer script Fisher Price)..............................33
Final del tutorial y recomendaciones............................................................45
Requerimientos
-Un conocimiento por lo menos medio de eventos de rpgmaker, en qualquiera de sus versiones.
Se recomienda haber usado bucles, etiquetas, condiciones y efectos y variables. Si has hecho
engines personalizados completos aun lo tendras mas facil.
1
Objetivos
Aprender la mecanica e ideas basicas de la programacion para que luego podais ojear scripts o
libros sobre ello sin problema.
La ventaja de este tutorial sobre otros es que esta pensado en la correlacion entre eventos y
scripts.
Pseudocodigo
Este tutorial usa un lenguaje ruby un pelin modificado. Se hace para poder poner por ejemplo
los comandos del rpgmaker con codigo escrito de forma facil y que sea mas facil de leer. Sin
embargo todo lo demas si sera valido, pero si pruebas el script, te va a dar error.
He creado un objeto inventado llamado $comando. Este tiene todo los comandos del maker
como metodos, aceptando sus argumentos necesarios. Si es necesario, el comando devuelve un
valor de retorno util para evaluarlo.
Quizas ahora no estes entendiendo esto pero da igual. Mas adelante se explicara.
La gente acostumbrada a los eventos tiene en mente una forma mas grafica de funcionar, pero
la verdad esque cada evento del rpg maker es convertido internamente en codigo escrito e
informacion por el programa. Asi cuandopor ejemplo escribimos el comando cambiar variables
sumando 3000 a la variable numero 15, eso se traduce en el siguiente texto hipotetico (o real,
en el caso del rpgmaker xp)
$game_variables[15] += 3000
Asi, los comandos del maker y sus eventos son interpretados por el programa conviertiendolos
en informacion valida para el mismo. Los scripts y los eventos funcionan de forma muy similar.
Nosotros aprenderemos a hacer ese proceso por nosotros mismos, y este tutorial te enseñara
las demas cosas que son equivalentes entre la programacion con los eventos a la programacion
real, que son bastantes.
2
Ruby y RGSS
Ruby es un lenguaje interpretado de alto nivel. Es un lenguaje muy moderno y muy simplificado,
accesible, rapido de escribir, legible... su unico handicap es su lentitud.
RGSS es una libreria grafica creada por Enterbrain para sus rpgmaker. Permite manejar
ventanas, sprites, texto, etc, asi como la carga de recursos, sonidos, y musicas.
Asi pues el RGSS es solo la libreria grafica, y Ruby es el lenguaje. Ademas de eso el XP tiene un
elenco de scripts default que manejan toda la logica del juego, basados en ruby y RGSS.
class Testear
def initialize
end
end
Entonces tu llamas en un evento de mapa con el llamar script, o en otro lado, esta linea:
Testear.new
Esto crea una nueva instancia de Testear y ejecutara el codigo en initialize. En este caso p
mostrara un mensaje de windows con el texto prueva, pero podrian ser mas cosas, y de esta
forma las tienes agrupadas en un solo sitio.
No hace falta que entiendas como funciona esto aun. Solo entra en tu editor de scripts y insertas
uno nuevo antes del script llamado Main(nada puede ir detras de este). Ponle de nombre
tutorial scripts y le pegas el codigo este.
3
Luego vas a un mapa, creas un personaje y cuando le das aceptar que llame a la linea de script:
Testear.new
Si te sale un cuadro de mensaje con ese texto, todo ha ido bien. Apartir de ahora te recomiendo
hacer tus pruebas de rgss en ese metodo de la clase test, porque se ejecutaran cada vez asi de
facil y las tendras ordenadas. Ponlo en un proceso paralelo para ahorrar tiempo por eso,xD.
En programacion existe un tipo equivalente llamado boolean. Este acepta los estados verdadero
y falso y se usa de la misma manera que en el rpgmaker. Sin embargo, en ruby su valor se define
por true si es verdadera y por false si falsa.
interruptor = false
# Ahora la activamos:
interruptor = true
-Normalmente es necesario hacer un salto de linea tras cada expresion completa, como estas
dos.
-El codigo de un programa rgss es leido e ejecutado de forma secuencial de arriba a abajo, de la
misma forma que los eventos. Asi pues, primero se desactiva el interruptor y luego se activa.
-El codigo terminara cuando no tenga nada mas que ejecutar y llege al final de sus ordenes. En
este caso la activacion es la ultima linea y por tanto el fin de la ejecucion
-Ruby no usa ningun marcador de fin linea, aunque es comun que tengas que escribir ; al final de
estas.
-Las lineas con un # al principi son comentarios (tambien presentes en los rpgmaker como
anotaciones). Sirven para organizar el codigo y son ignorados por el programa.
4
Variables
Aunque gracias a los eventos creas que una variable es solo una cantidad numerica, esto no es
asi y solo es valido para los eventos del maker.
En la programacion los switches tambien lo son, y un monton de cosas mas. Se llama variables a
todo aquello que guarda algun tipo de valor e informacion. Asi:
variable_texto = 'Texto'
variable_switch = false
variable_decimal = 1.2
etc, etc
Todo ello es conocido como variables, y luego cada variable tiene su tipo (decimal, boolean,
texto, etc.).
identificador = valor
Nota que el identificador se usa para poder extraer luego el valor de esa variable y poder usarla,
de forma similar a como con el maker usariamos una variable de evento n15 con los mensajes
de texto por ejemplo \v[15] o asignandolo con otro comando.
p identificador
Esta linea imprimiria el valor del identificador. p es un alias de print y es la principal forma de
comunicarse que tendras con ruby.
cantidad_manzanas = 4
p cantidad_manzanas
5
Otros operadores
De igual manera que en el maker, puedes hacer unas cuantas cosas aparte de asignar una
variable:
+ Suma
- Resta
* Multiplica
/ Divide
% Resto
^ e Elevar
Ejemplo:
variable_numerica = 15
variable_numerica = variable_numerica + 15
Mucha atencion a esta nueva linea. Lo que quiere decir es que variable numerica sera ahora
igual a la suma del valor actual de variable numerica + 15. Esta seria la forma usada en todos los
casos, aunque exista una version acortada que te gustaria usar:
variable_numerica += 15
variable_numerica2 = variable_numerica * 15
En programacion se usan muchas cosas de las matematicas, y el uso de los () es una de ellas. En
este caso primero se hacen las divisiones y luego la suma y todo se asigna de forma correcta a la
variable 3.
Por ultimo, es importante entender un concepto que con el rpgmaker no existe ya que no
6
puedes encontrarte en una situacion donde vayas a usar una variable no definida, por ejemplo.
Esto en la programacion si pasa y normalmente daria error, aunque ruby es un lenguaje muy
flexible y permite declarar variables en cualquier lado.
-Los identificadores de una variable son unicos. Asi que siempre que uses ese nombre,
accederas o modificaras esa variable. Si la vuelves a asignar obviamente perdera su contenido.
-Los identificadores en ruby han de estar en minusculas I no admiten algunos simbolos como =,
*, etc, I otras cosas raras. Tampoco admiten espacios pero se usa el _.
Condicion y efectos I
Probablemente el elemento mas potente del rpgmaker, y tambien de la programacion. Como
dice el nombre del comando, Se comprueba una condicion → Se lanza un efecto si esta es cierta
→ U otro si es falsa o nada en absoluto.
Imaginemos que queremos comprovar si el switch 2 de un cofre esta activado, para que si lo
esta, este diga que esta vacio o lleno. Esto en ruby seria:
if $game_switches[2]
else
end
Vemos que la estructura es bastante parecida. if marca la condicion principal, que va seguida de
espacios y luego la expresion a evaluar, else es lo que pasa cuando esta expresion no se cumple.
end es usado para marcar el fin de un bloque. Los bloques pueden ser cualquier cosa, un bucle,
una clase, un metodo... pero siempre se termina con un end final correspondiente en nivel a la
expresion que lo inicio.
If true
p'soy el primer if
if true
7
p 'el segundo if'
end
end
Siempre se empieza y termina antes el bloque mas interior, que esta contenido por los demas, y
el programa es llamado y usado de arriba a abajo, ejecutado en ese orden. llamar_funcion llama
Notad que en programacion se tabula el codigo, esto es para que este mas ordenado. Ademas
en el editor este sale coloreado. Cada vez que se hace un nuevo bloque o nivel, se avanza un
tabulador. Se puede tabular el texto seleccionado hacia adelante o hacia atras, por lo que es
muy facil de usar.
Ahora vamos a construir un pequeño engine que guarda en una variable la relacion de un NPC
con el protagonista. Esta variable ira del 0 al 100 (por lo que se debera comprovar el tope y el
minimo) y empeorara si le insultas y mejorara si le alabas, reduciendose o mejorando 5 cada
vez.
8
El equivalente programado de esto seria:
cura_relacion -=5
cura_relacion -=5
end
end
9
if cura_relacion > 100
cura_relacion = 100
end
if cura_relacion < 0
cura_relacion = 0
end
Es decir, hay una serie de cosas que en general, son malas practicas, como usar identificacores
muy cortos o ilegibles... o que no transmiten lo que son, o apilar demasiado las lineas, no
separarlas, no modularizar los problemas complejos, etc...
Los comentarios son una muy buena practica. Explican al programador e incluso a ti mismo que
hace el codigo. Nota que es bastante corriente que un programador escriba codigoque luego no
vaya a entender al cabo de unos meses, por lo que es recomendable usarlo asi. Mal ejemplo:
d= 15
dc=e.crdn d
e.apdn dc
10
Esto se podra leer muy extremo y seguro que a mas de uno le parecera arte abstracto, pero
sirve como ejemplo valido. No hay un solo comentario que nos explique hace cada funcion y los
nombres son inteligibles. Ademas el = esta pegado a cada valor. Una solucion seria:
daño = 15
enemigo.aplicar_daño daño_creado
=begin
son comentarios
=end
Este otro tipo de comentario hace que el bloque entre begin y end se comente por completo. Es
util para comentarios muy largos. Nota que se deben escribir al principio de linea.
Imaginemos que creamos un evento comun para hacer que el personaje Alex pierda 200 de vida
en batalla. Nuestro equivalente seria:
def perder_vida
$comando.cambiar_pv('Alexis', 200)
11
end
Como hemos dicho, esto es una funcion que va de la misma forma que un evento comun. En
ruby se llamaria escribiendo la linea:
perder_vida
Esto pararia el evento actual y ejectuaria la funcion hasta terminarla devolviendo al final el
control al evento actual.
Sintaxis: La sintaxis en el caso de funciones en ruby es que se declara el bloque con def y se
termina de la forma tipica. Una funcion sigue las reglas tipicas de nombramiento.
Imaginemos que queremos crear un sistema de robo en combate con el sigiente diseño:
2- Cada personaje va a tener un atributo de robo base unico que ira del 1 al 100..
3- Queremos que la funcion ademas modifique la experiencia de robo y active una variable para
saber el objeto. Si la variable es valor 0 querra decir que no ha robado.
4- Cada enemigo tendra un objeto a robar. Si la ID es 0, querra decir que no puede robarle nada.
return enemigo.item_a_robar
else
return false
end
12
end
Atributos: Notad que hemos implementado el atributo de robo en la clase personaje y con el
enemigo igual. Esto ahora te va a sonar a chino pero bueno, xD. La idea es que a cada personaje
se le puede acceder a su informacion usando el .atributo, y con los enemigos igual. Esto seria
valido para enemigo.pv o enemigo.str, por ejemplo, ya que son estructuras de datos accesibles
usando el '.' .
Variable global: Una variable global es aquella que es accesible desde qualquier parte del
programa. En los eventos esto es el pan de cada dia. Los switches, variables y demas son
accesibles desde qualquier sistema u evento. Y toda la informacion de el comando operar
variables (mapa, pasos, dinero, vida del personaje,etc...) tambien lo es.
Sin embargo esta practica es nada recomendada en la programacion real. Las variables globales
se usan lo menos posible porque hacen el codigo menos protegido y mas tendiente a errores.
Ademas es una falla de rendimiento tener en memoria todos los datos cada vez.
Asi se tiene que tener en memoria cada vez lo que se va a necesitar y nada mas. De esta forma
nacen las variables locales, que en este caso, son las que se pasan como parametros. Una
variable local solo es valida en el bloque en el que se llamo, es decir, en la funcion en la que se
llamo.
return: Esta clausula termina la funcion en ejecucion actual y devuelve un valor a la funcion que
la llamo. La idea es
Tradicionalmente ha sido usada la convencion de que una funcion o programa deberia devolver
por lo menos true si ha ido bien y false sino. Aunque esto no es obliatorio, de hecho la mayoria
de funciones no lo necesitan.
Por ultimo en ruby se pasa siempre como retorno de forma automatica el ultimo dato tratado
13
para qualquier cosa. Osea:
def sumar
x = 1+5
end
Parametros:
Mas sobre los parametros: Se pueden pasar todos los parametros que quieras, o ninguno. Nota
que normalmente sera obligatorio que la funcion reciba siempre los parametros que le has
definido.
Ruby ademas permite dos opciones bastante utiles: la de dar un valor por defecto al parametro
para que si no lo pasas lo adquiera, y la de aceptar una cantidad variable de parametros usando
la construccion *args.
Ademas existe el paso por referencia o sin ella. Con el paso por referencia se puede modificar
directamente una variable (como si fuera globall) mientras que con el otro siempre deberas
asignarla en una nueva.
Mas sobre las funciones: Algunos conceptos interesantes son las funciones recursivas.
Condicionales avanzados
Una de las desventajas de los eventos es no poder usar condicionales complejos de forma facil.
14
El unless es un condicional alternativo que actua de forma inversa al if.
La expresion and es usada para hacer calculos booleanos, osea, para indicar que varias
condiciones se han de cumplir so o si:
a == 99
b=3
if a == 99 and b > 5
En este caso el condicional no se cumpliria, porque solo la primera es valida, y el and requiere
las dos.
Ademas del and se usa el or, que hace que se pueda cumplir una u otra condicion:
a == 99
b=3
if a == 99 or b > 5
En este caso si funcionaria ya que con el or basta que una sea valida.
Finalmente existe otra expresion usada llamada not, que funciona como el unless, inviertiendo
el signficado de lo que modifica:
a == 99
b=3
En este caso si funcionaria ya que ahora la comparacion de b esta negada, invertida, por lo que
si esta es falsa, es cuando es verdadera para el and general.
Variables II y strings
En ruby existen muchos tipos de variables, mientras que en RGSS solo 2: el boolean true/false, y
el numerico. Algunos ejemplos:
15
decimal_float = 0.0
palabra = 'string'
Aqui vemos como existen muchos tipos de variables, que son objetos(explicado mas adelante).
Desde ficheros, a decimales, o palabras.
Las palabras son las mas interesantes para vosotros. Contiene una lista de caracteres de texto y
se usan para manejar texto en general. El texto viene delimitado por 'texto' o “texto”.
En ruby se puede converitr cualquier tipo a casi qualquier otro tipo, por ejemplo:
En este caso estamos imprimiendo un mensaje que muestra 'string:0.0', concatenando las dos
variables y la nueva que creamos al aire(no hace falta declararla), llamada ':'.
El metodo .to_s convierte el decimal en una palabra, o string, y de esta forma se puede
concatenar con las dos otras variables, que eran strings(no se puede concatenar de distintos
tipos).
Nota que en ruby los operadores clasicos se usan para mas cosas. Por ejemplo el + se usa para
concatenar un string tras otro, pero tambien para unir dos listas, etc.
arr_str = 'w e p'.split(' ') # divide el string en un array de strings separando lo por el caracter
pasado como separador.
Objetos
Ruby es un lenguaje 100% orientado a objetos y aunque no vaya a ser algo que te suene mucho
viniendo del rpgmaker, si necesita algun tipo de introduccion y explicacion para que puedas
entender por lo menos este tutorial.
Un objeto es una abstraccion de un objeto real pasado a codigo programado. Por ejemplo,
vamos a imaginar que queremos definir un perro:
16
¿Que hace un perro? Ladra, come, mueve la cola
@raza = raza
@color_pelo = color_pelo
@edad = edad
end
def ladrar
`p 'bub!'
end
def mover_cola
end
def comer
p 'ñam ñam
end
end
Aqui vemos la implementacion del perro en lo que es el elemento vital de los objetos: la clase.
Una clase define precisamente eso: una clase de algo. En este caso, un perro.
17
Por ultimo, el @se usa para definir el valor de la variable de instancia. Una instancia es el nuevo
perro que creamos con el constructor, es decir, el perro que instanciamos. Cada instancia es
totalmente independiente asi que las variables de instancia se refieren a que tienen un valor
unico para cada nuevo perro creado. Con el @@ se crean variables con un valor que compartan
todos los perros, pero esa es otra historia.
Herencia
La herencia es una de las claves de la OO. Como su nombre indica, liga a una clase padre con
una clase hijo. Una forma facil de entenderla es que el hijo es una especializacion del padre. En
este caso, el padre seria el mamifero y el perro el hijo. Luego el mamifero podria tener como
padre al animal, I el perro otros hijos, etc.
Esto es lo que quiere decir el < entre Perro I Mamifero en la declaracion de la clase. Que perro
hereda de el.
Las clases que heredan de otras obtienen sus metodos y variables, es decir, que si el mamifero
tuviera una variable llamada nombre y el metodo caminar, la clase perro tendria en realidad eso
metodos y variables tambien.
Por regla general, se debe encapsular al maximo una clase, haciendo el minimo de cosas
accesibles externamente. La razon es que una de las ventajas de usar objetos es que los objetos
solo se comunican entre si atraves de interfaces publicas, dejando el resto de cosas internas y
privdas. Alomejor no captaras ahora porque esto es bueno pero ayuda a programar mejor.
-La edad del perro tendria que variar, asi que la haremos variable.
-La raza o color no, asi que no tiene porque variar, aunque si es necesario poder saberlos
externamente.
Por tanto haremos que la edad del perro pueda ser modificada y leida, y el resto solo leida.
attr_accessor :edad
18
attr_reader :raza
attr_reader :color_pelo
Nota la diferencia entre reader/accesor. Por defecto una variable es totalmente privada e
inaccesible en la clase.
Estas definciones se suelen añadir antes del constructor, por lo que la defincion final seria:
attr_accessor :edad
attr_reader :raza
attr_reader :color_pelo
@raza = raza
@color_pelo = color_pelo
@edad = edad
end
def ladrar
`p 'bub!'
end
def mover_cola
end
def comer
p 'ñam ñam
end
end
19
Todo es un objeto en ruby
En ruby todo, absolutamente todo es un objeto de algun tipo. Por ejemplo, un 1 es un objeto
Number, y un 'frase' un objeto string.
Un archivo abierto es un File y una lista un Array. Cuando por ejemplo, convertimos al 1 en un
string:
1.to_s
Lo que hacemos es llamar a uno de los metodos validos de ese objeto. Y si ahora hicieramos:
numero_a_string = 1.to_s
Siendo practicos
perro.ladrar
perro.comer
perro.caminar
p perro.raza
Y modificarlas si podemos:
20
perro.edad += 1
string = 'Frase'
Son equivalentes.
En general es siempre recomendable que antes de hacer algo, heches una ojeada a la libreria
por si ya existe algo que te pueda facilitar la tarea.
http://www.ruby-doc.org/stdlib/
Visita esta pagina en busca de lo que puedas necesitar. Nota que el Rpg Maker XP usa una
version algo antigua de ruby asi que quizas algunas de las clases o metodos no esten.
Errores
Los bugs en el rpgmaker son lo mismo que en la programacion: fallos que hacen malfuncionar el
programa. Si por ejemplo quisieramos sumar una variable sin declarar aun, ruby nos saltaria un
error diciendo que la variable no esta definida y no sabe que es:
variable += 5 # Error
21
end
'frase'.abs # Error porque frase es un string I no tiene el metodo para poner el valor absoluto.
Etc,etc.
Nota que tu puedes crearte tus propios errores, lanzarlos, controlarlos... pero eso queda aparte
de ese tutorial. A eso se le llama excepciones.
Bucles
Bucles en los eventos
En todos los casos se muestra como trabaja un bucle y su funcion en RGSS es equivalente. Por
ejemplo:
comandos.ejecutar_comando(comando)
end
Este bucle imaginario iterarira en un evento, que tiene una lista de comandos definidos por el
usuario, y cada vez avanzaria en esta lista, extraiendo la variable comando con la entrada de la
lista. Luego ejecuta cada vez el comando adecuado de forma automatica, sin tener que
escribirlo tu manualemente cada vez.
Los procesos paralelos y automaticos funcionan de esta forma, ejecutando la secuencia de los
eventos una y otra vez hasta que por lo que sea, se rompen para poder continuar con el
programa. Imaginemos un comando de evento llamado 'Salir de proceso paralelo':
22
if comando.tipo == 'Salir de proceso paralelo'
break
else
comandos.ejecutar_comando(comando)
end
end
Por tanto los bucles son secuencias de codigo que se ejecutaran una y otra vez hasta que las
paremos de una u otra forma. En general ningun bucle suele durar para siempre y hay muchas
formas de parar su ejecucion para poder continuar con el programa.
En la programacion
Cuando programamos, tenemos muchas mas opciones y variedad a la hora de usar los preciados
bucles, que son una de las principales gracias de la programacion, ya que permiten automatizar
la gestion de los datos por el ordenador. Aunque esto se explica mejor en el siguiente capitulo.
En ruby se usan 3 tipos de bucles principales, el bucle for, el bucle while y el 'bucle' each.
Aunque en el fondo todos sean equivalentes y se pueden usar para todo, aunque a cada uno se
le de mejor una u otra cosa.
El bucle for
El bucle for se usa mejor para iterar en listas de datos, secuencias de numeros y cosas por el
estilo. Tiene una sintaxis que te permite iterar en todos estos datos de forma automatica y muy
muy facil. Nota que este bucle queda mejor explicado en el siguiente capitulo.
p manzana
end
El bucle for se declara especificando el nombre a usar para los datos que se extraen de la lista y
luego la lista en la que se va a iterar y extraer el dato:
23
El bucle avanzara en toda la lista de manzanas y cuando esta se acabe, parara. El codigo en el
centro se ejecuta cada vez, en este caso veriamos cada vez la manzana imprimida en pantalla.
Bucle while
El bucle while se usa cuando queremos basarnos mas bien en una condicion mas visible y facil.
marca=true
if obtener_mazana
vender_manzana
marca = false
end
end
En el bucle while la condicion puede ser qualquier condicion corriente usada por un if.
Notas
-En la programacion se evaluan de forma automatica las variables que no son nulas o falsas o
vacias como verdaderas. Esto quiere decir que no se usa nunca el ==true porque el programa lo
mira de forma automatica. Osea que while marca == true es equivalente a while marca.
-Nota que los bucles como hemos dicho son intercambiables. Sin embargo para hacer con un
bucle for el trabajo del while deberias regenerar cada vez el puntero de iteracion o hacer que
este fuera un numero eterno, etc. Y al inreves el bucle while deberia usar una variable contador
para poder llevar el indice del array a extraer los datos....
24
-De la misma forma, estos no son todos los usos de los mismos. Se usan los bucles para muchas
mas cosas que iras descubriendo con el tiempo. Ademas ruby incorpora mas bucles y muchos
metodos de iteracion distintos en la listas y objetos, asi que ve investigando y provando.
Arrays
¿No las conoces?
Solo los que hayas usado el 2k3 conocereis ligaramente que son los arrays. Por aquel entonces
no existian de forma verdadera o facil, pero si existia una opcion en operaciones de variable que
te permitia setear el valor de la variable basado en una posicion relativa de esta en la lista de
variables del rpgmaker.
Usando este metodo con una variable definida, podias por ejemplo, ir de las variables 0 a la 100
sumandoles 5 a todas. Lo unico que debias hacer era sumar 1 cada vez a la variable que
guardaba el indice a usar por el operaciones de variables.
Listas
Un array es una lista de datos ordenados secuencialmente, por ejemplo, 1, 2, 3. Es algo tan vital
en programacion que no sabria decirte un lenguaje que no los tenga.
Antes he mencionado la forma en que en los makers podias usar listas de valores, pero ahora
vamos a imaginar algunas aplicaciones practicas de estas en un videojuego:
-La lista de experiencia necesaria para cada nivel para los personajes.
-Una lista con las armas que drenan PV para un script(ver ejemplo al final).
Etc,etc.
Nota que los arrays de ruby son dinamicos (pueden cambiar de tamaño) y pueden contener
cualquier tipo de valor, incluso otros arrays.
Creandolos
lista = Array.new(1,2,3)
25
Aunque hay otras formas:
lista = [1,2,3] # Los [] son prescindibles, en ruby lo que diferencia realmente al array es la ,:
lista = 1,2,3 # El [] se usa a para placer propio o para situaciones donde el contexto no sea
claro.
Lista = 1,
2,
# Si, ruby admite este tipo de declaraciones linea por linea. Aunque imaginatelo mas util:
Lista = 1,2,3,4,5,
Extraiendo informacion
En programacion las listas funcionan de una forma atipica, desde 0. Es decir, la posicion 0 del
array es la posicion 1 natural.
p lista[0] # imprimiria 1
Se usan los [] para marcar la posicion que queremos modificar o ver. El [] se escribe tras el
nombre de la variable y cuando lo usemos el programa pensara en la variable contenida en [] y
no en el aray.
Modificando un valor
26
Se usa lo mismo que al extraer:
lista.last = 15 # Ahora el ultimo valor de la lista es 15. Equivalente a indexar usando size-1:
lista[lista.size-1] = 15
.include?(valor) : Se usa en los condicionales. Ruby buscara si valor existe en el arary y devolvera
true si es cierto.
Ejemplo de array
array = 1,5,99
array.push 120
array[2] = 0
if array.include? 99
p 'tiene 99'
end
Hashes
Un hash es una lista desordenada donde se extrae el valor de algo usando una clave de texto.
Nota que los hashes quedan muy lejanos y se trataran levemente, solo.
27
hash_personajes['alex']
array_personajes[13]
El problema de los hashes es que son mas ineficientes en algunos aspectos. En general deberas
usar el array siempre y cuando el numero te baste. Osea, si no vas a extraer algo usando una id
clara como clave, te la puedes ahorrar:
hash_absurdo= (
Si tu quieres acceder usando la clave conocida, es mejor el hash, porque no vale la pena la
comparacion con el poco rendimiento ganado.
Pero si tu solo quieres la lista de capitales para iterar en ellas y mostrar sus nombres sin mostrar
el pais... ¿que sentido tiene usar el hash entonces? Ninguno.
Ruby tiene dos estructuras mas similares al array: el openstruct y el struct. Puedes hechar una
ojeada a los dos. Tambien se usan las matrices, arrays multidimensionales con multiples valores
y posiciones. En Rpg Maker se usan para los mapeados, con una dimension x(ancho de los tiles),
una dimension y(alto) y z(en ella se guardan los valores de configuracion como las capas,
eventos, terrenos, vehiculos, etc).
Aunque existe la posibilidad de tener a un grupo de monos esclavizados modificando los 1500
manualmente, la mejor respuesta es usar un bucle for.
28
for persona in lista_personas # iteramos en un array de objetos personas
end # los bucles se mantienen hasta haber acabo de mostrar toda la lista, repitiendo la
operacion en su interior.
La sintaixs es:
for x in 0...lista_personas.size
lista_personas[x].popularidad += 15
end
Aqui la sintaxis ha cambiado un poco. La x sigue siendo lo mismo, solo que esta vez su valor va
iterando de 0 hasta el tamaño del array, que era 1500, asi que haria 1500 iteraciones extraiendo
de forma equivalente el indice.
Este tipo de sintaxis es conocida como rangos, y es muy poderosa en ruby, asi que deberias
explorarlo un poco. Los rangos son objetos que definen un conjunto de numeros ordenados
entre una clave de empiezo y una de fin:
0...lista_personas.size
clave_empiezo...clave_final
Nota que se usan … en este caso, pero tambien existe la opcion de usar .. . Los …, con tres
puntos, es equivalente a escribir lista_personas.size-1, osea, que se deja el ultimo valor para
iterar.
¿Que utilidad tiene esto? Pues en este caso por ejemplo, el for ir iria hasta el final del array I
finalmente trataria de acceder al elemento 1500, fallando y cerrando el programa. Esto es
porque el array efectivamente tiene 1500 posiciones pero internamente empieza por 0, asi que
su numero maximos seria 1499.
29
Each
Esta suele ser la mejor forma de hacer iteraciones simples en ruby, o no tan simples, y de hecho
es hasta un 200% mas rapida que un bucle for.
En el each se crea el bucle entre los {} y el | separa la variable que se extrae del codigo que se
ejecuta cada vez, llamado bloque.
lista_a_iterar.each{|variable_extraida| variable_extraida.to_s }
Nota que existen diversas formas de iterar listas en este sentido(definiendo paso por paso, por
cada llave en los hashes, etc), aunque para eso recomiendo mirar la referencia de ruby.
Los hashes tambien pueden ser iterados en caso de necesidad, y el metodo es exactamente
igual:
Nota que no se garantiza ningun orden. Eso si, cada persona sera iterada una vez y se acabaran
iterando todas.
Ejemplo de iteracion
# Este pequeño script pondria en un array de respaldo todas las habilidades que consuman
menos de 10 pm.
30
hab_10pm = [] # crea array vacio para poner luego
# Usa la id extraida del array para indexr el array de la base de datos en busca
if base_de_datos.habilidades[id_hab].pm < 10
end
end
# Lo imprime
hab_10pm.eacb {|i|p I}
Estos contienen solo la configuracion incicial y existe uno para coda cosa: $data_items,
$data_actors, etc. No se guardan los cambios en los personajes aqui por ejemplo, sino en el
objeto global $game_actors.
31
Nota que tampoco se haria una asignacion directa asi, sino que se traslada desde lo configurado
en la base de datos o usando un metodo del personaje que comprueba si ya lo tiene, si es una
habilidad valida aprendible por el personaje, etc...
Testear II
Para testear codigo, se usa la funcion p, sobretodo. Esta imprime un mensaje de texto y para la
ejecucion del programa hasta que este este bien: p 'mensaje'
Tambien puedes añadir variables, o objetos, que saldran inspeccionados completos: p 'mensaje',
var1, objeto1
Tambien lo seria cuando usas el rpgmaker en si. Se podria decir que todos los comandos de
evento del rpgmaker son como una gigantesca libreria que te da Enterbrain y que puedes
ejecutar y usar a qualquier momento. Los parches con nuevas funciones serian librerias extra
que añadirian nuevas opciones.
Este concepto es vital tambien en la programacion y una de las cosas mas distintas respecto a
los eventos. Con estos todo el que quisiera un sbp, smp.. tenia de hacerlo de 0. Hasta para
añadir la menor chorrada. Eso con la programacion es absurdo. Tienes un monton de scripts
default hechos y un monton mas extras tambien. Puedes crear tuyos pero lo normal sera que
por lo menos se apoyen en los default.
La cuestion es que aqui no vas a tener que reescribir todo el sbp, smp o crear de todo. En
principio solo deberias modificarlos o agregar lo que necesitas. Nada mas. Reinventar la rueda
es inutil, amenos que sea como reto o para aprender.
La libreria estandard de ruby es gigantesca. Busca por ese nombre o en ingles: ruby standard
library y veras que tiene centenares de atributos y metodos creados para facilitarte la vida.
32
Entender el codigo RGSS y los datos del rpgmaker
Una de las claves de scriptear bien es ir conociendo como funcionana los scripts del rpgmaker,
para saber donde se hace tal y cual cosa, y poder modificarlos de forma rapida. Notad que este
conocimiento viene de la experiencai aunque tambien podeis preguntar o buscar informacion.
Los datos de la base de datos estan guardados en una serie de objetos globales accesibles desde
cualquier lugar, como por ejemplo, $data_items, que contiene todos los datos de los objetos de
tu juego, por ejemplo, $data_items[3].price te dara su precio.
Tambien existen otros objetos, llamados $game_actors, por ejemplo, que contiene los
personajes. La diferencia entre este y $data_actors, es que el primero es modificable y el
segundo no, claro, los personajes cambian de valor, nviel, vida, etc, en el juego, y se deben
guardar con cada partida.
Es muy recomendable estudiar el manual para ver tods los objetos que hay a tu disposicion, por
ejemplo, para ventanas, graficos, etc, asi como usar el codigo default como base para qualqueir
cosa para aprender usandolo como base.
0. Planficacion I diseño: Esta etapa es vital pero el problema es que inutil para algo tan simple.
Igualmente es recomendable planficiar las cosas y tratarlas de resolver antes en papel.
1. Buscar donde aplicarlo en los scripts que tenemos: Descubrir donde se muestra en el script
de combate la asignacion de daño para poder redirigir parte de este al atacante.
En este paso deberias buscar por ti mismo , preguntar o mirar en otros scripts parecidos como
puede ser. En todo caso yo ya se la respuesta y es en el metodo attack_effect de la clase Game
Battler 3.
33
2. Creando el codigo: Ahora podriamos escribir directamente el codigo alli pero no lo
recomiendo lo mas minimo. Es mucho mejor hacer los scripts separados del default. Es mas
comodo, organizable, rapido y portable.
Asi que en nuestro editor de scripts vamos antes del main I ponemos insertar. Ponemos de
nombre Drenar PV/PH.
Ahora nos dirigimos al game battler y copiamos la clase y el metodo que vamos a editar en
nuestro nuevo script, cerrando tambien la declaracion de la clase:
#==============================================================================
# ** Game_Battler
#------------------------------------------------------------------------------
# This class deals with battlers. It's used as a superclass for the Game_Actor
#==============================================================================
class Game_Battler
#--------------------------------------------------------------------------
# attacker : battler
#--------------------------------------------------------------------------
def attack_effect(attacker)
self.critical = false
# If hit occurs
if hit_result == true
34
# Calculate basic damage
# Element correction
self.damage *= elements_correct(attacker.element_set)
self.damage /= 100
if self.damage > 0
# Critical correction
self.damage *= 2
self.critical = true
end
# Guard correction
if self.guarding?
self.damage /= 2
end
end
# Dispersion
if self.damage.abs > 0
end
35
hit_result = (rand(100) < hit)
end
# If hit occurs
if hit_result == true
remove_states_shock
self.hp -= self.damage
# State change
@state_changed = false
states_plus(attacker.plus_state_set)
states_minus(attacker.minus_state_set)
# When missing
else
self.damage = "Miss"
self.critical = false
end
# End Method
return true
end
end
Nota dos cosas en este codigo. La primera es que ruby permite la redifinicion de una clase en
qualquier momento. Esto quiere decir que puedes volver a escribir un metodo o una clase mas
adelante y sera esta ultima definicion la usada. En este caso vamos a sobrescribir el metodo de
attaque.
36
quizas esten de mas por lo poco grande dell proyecto pero en todo caso son validos igualmente.
Si vamos a crear armas que drenan cosas, deberemos indicar en algun sitio que cosas, cuanto
drenan y que armas son, ¿no?.
Lo mas obvio y rapido seria usar una variable global con un array o hash. Nota que el hash para
estas cosas es mayormente siempre mejor:
Este array seria un array de arrays. Cada subarray tiene la informacion de una arma. La posicion
0 es la id de la arma, la 1 el % que drena I el ultimo una marca para el tipo.
Sin embargo podemos mejorar ese codigo. ¿Porque no usar el indice del array como
identificador de la arma? Casi no se pierde nada y se gana bastante, y no habria que usar un
bucle para buscarlo:
armas_drenadoras[1] = [ 40, 'pv'] # Asi se hace para añadir nuevos elementos al array.
Ruby retorna en los valores no inicializados o vacios de un array el valor nil (nulo) asi que gracias
a esto podremos si una tiene o no.
El $ indica variable global, accesible desde todo el programa, pero es una mala practica. La
mejor alternativa en rgss es el uso de un modulo.
module Minick
Amas_drenadoras[1] = [ 40, 'pv'] # Asi se hace para añadir nuevos elementos al array.
Amas_drenadoras[3] = 60, 'ph' # El azucar sintatico mola, xd. Es equivalente a lo anterior, ya que lo que
37
define al array es la , I no el [].
end
Los modulos son un tipo de clase totalmente estatica en ruby (no se puede instanciar y solo se
puede llamar sus metodos usando la clase en si). Se usan para varias cosas pero en rgss se usan
para encapsular datos fijos, puesto que solo admiten usar constantes. Sin embargo para el 99%
de las cosas son validos y pueden tener metodos y toda la pesca, aunque no heredar de otra
clase.
Amas_drenadoras
Nota este cambio de nombre. La primera letra mayuscula es la forma de declarar que una
variable es constante en ruby. Una constante no debe modificada y lanzara un error si lo
intentas. Las constantes son utiles para configuraciones fijas. Ayudan a descubrir errores ya que
si sabes que una variable va a ser fija no poder cambiarla no es problema y si el programa te
avisa de que se intenta cambiar descubriras rapidamente donde y porque.
self.hp -= self.damage
Vamos a escribir el codigo despues de esta linea. La razon es que es la posicion en que se han
hecho todos los calculos necesarios, y ademas asi nos guiamos por como esta montado ya el
script default.
self. Es una referencia de un objeto hacia a si mismo. Veras que el metodo attack effect recibe
de parametro attacker, que es el battler atacante (sea amigo o enemigo) asi que el objeto del
self. Es el defensor al que se le quita la vida.
38
Por tanto, nosotros deberemos subir la vida a ese battler atacante definido en la variable
attacker.
# Absorbe pv/ph
if Minick::Armas_drenadoras[attacker.weapon_id] != nil
if Minick::Armas_drenadoras[attacker.weapon_id][1] == 'pv'
else
end
end
Primero el primer condicional. Este es usado para asegurarse de que la posicion del array es
valida. Sino te podria dar errores. Ademas usamos attacker.weapon_id. La clase Game actor
tiene este atributo accesible y nos dara la id de la arma equipada actualmente.
Luego los battlers tienen un valor llamado damage que almacena el daño acumulado de una
accion contra ellos. Osea que si queremos drenar en % tendremos que aplicarlo sobre este valor
de daño.
Esta linea es la clave. Al sp/hp del atacante se le suma el daño del defensor * el %configurado
del arma partido entre 100. El uso del /100 es para que quede en parametros tipicos de uso de
%, es decir, 1.55, 0.50, etc.
Quizas te estes preguntando porque ese attacker es el mismo que en game actors, game party, y
en scene battle, etc. Y la respuesta es que si. Y que si lo modificamos aqui, modifcamos el objeto
real que esta contenido en game actors.
39
Esto es porque en ruby los objetos pueden tener diversas referencias. Es decir, diversos
nombres identificativos que apunten a un mismo valor u objeto. De hecho es lo normal y se han
de usar metodos especiales la copiar y tal para que no pase.
Ahora quedaria testear el asunto usando el p. Pero esto nos lo vamos a saltar. Imaginate que
pruebas el asunto. En cierto momento, tal como esta, te va a dar un error, y es que el
weapon_id no esta definido para los enemigos pero nosotros lo usamos siempre. Nota que este
atributo es usado por personajes/enemigos ya que las dos clases heredan de game_battler.
Debemos hacer algo para que solo lo usen los personajes. Hay varias opciones pero la mas
simples es usar el metodo .is_a?. Este metodo analiza el tipo de un objeto. Es decir:
I por tanto lo podemos usar para crear condiciones segun sea un Game_Actor o Game_Enemy
(las dos clases para personajes y enemigos en el rgss).
# Absorbe pv/ph
# Comprueva que haya una entrada en el array para la arma equipada I que sea game actor
if Minick::Armas_drenadoras[attacker.weapon_id][1] == 'pv'
else
end
end
40
7. Comentarios finales
Esto es solo un ejemplo. Es muy desaconsejable usar arrays porque son muy dificiles de ver
desde fuera ya que usan numeros. En vez de eso se usan hash o estructuras que usan entradas
de texto o simboloso para cada parametro. Nota que son mas lentas pero es bastante
indiferente a esta escala y usando un lenguaje pensado para el programador como ruby. Otra
alternativa valida es usar metodos con cases en ellos.
Ademas se podria haber variado o mejorado el diseño. ¿Era lo mejor poner el atributo tipo o se
deberia haber creado dos listas? Etc,etc... piensa que tal como esta por ejemplo, una arma solo
puede tener uno de estos efectos.
#=============================================================================
=
# By minick
# Version: 1.3
# License: MIT
# Date: 1/12/1900
#=============================================================================
=
=begin
---------INTRODUCCION-------
Este script permite definir armas que drenan PV y PH, asi como su % de drenado.
----------INSTRUCCIONES-------
Solo debes añadir una arma nueva cada vez copiando esta expresion:
Esto hara que la arma de id 5 drene un 60% de ph. Nota que si en vez de 'ph'
41
es 'pv' drenara pv.
=end
module Minick
end
#==============================================================================
# ** Game_Battler
#------------------------------------------------------------------------------
# This class deals with battlers. It's used as a superclass for the Game_Actor
#==============================================================================
class Game_Battler
#--------------------------------------------------------------------------
# attacker : battler
#--------------------------------------------------------------------------
def attack_effect(attacker)
self.critical = false
42
hit_result = (rand(100) < attacker.hit)
# If hit occurs
if hit_result == true
# Element correction
self.damage *= elements_correct(attacker.element_set)
self.damage /= 100
if self.damage > 0
# Critical correction
self.damage *= 2
self.critical = true
end
# Guard correction
if self.guarding?
self.damage /= 2
end
end
# Dispersion
if self.damage.abs > 0
end
43
eva = 8 * self.agi / attacker.dex + self.eva
end
# If hit occurs
if hit_result == true
remove_states_shock
self.hp -= self.damage
# Absorbe pv/ph
# Comprueva que haya una entrada en el array para la arma equipada I que sea game actor
if Minick::Armas_drenadoras[attacker.weapon_id][1] == 'pv'
else
end
end
# State change
@state_changed = false
states_plus(attacker.plus_state_set)
states_minus(attacker.minus_state_set)
# When missing
44
else
self.damage = "Miss"
self.critical = false
end
# End Method
return true
end
end
Por ultimo, examina algunos scripts que sean medianamente buenos, aunque no tires para algo
complejo. Huye de los que estan mal documentados o usan variables globales sin encapsular
porque te va a ser mas dificil aprender con ellos. Fijate por ejemplo en como los scripts tratan de
mejroar la compatibilidad usando el alias.
-Acceso a ficheros. En este tutorial no se explica nada. Leer y escribir ficheros de texto o para
guardar y cargar datos usando el metodo Marshall.
-Biblioteca estandard de ruby o manual del XP: Echate una ojeada por estos dos por que salen
miles de metodos y clases y te daras cuenta de la inmensidad de opciones que ofrecen.
-Algun tutorial que trate la base grafica y tal del RGSS. En ingles hay mas pero en español puedes
buscar el de Anemus.
-Errores y excepciones.
45
-Uso de referencias en ruby
-Expresiones regulares
-Simbolos
-El case when de ruby (una alternativa a los ifs) y las variantes de los bucles y condicionales
normales: until, unless, etc
-Tomarte tu tiempo estudiando todos los scripts por defecto que incopora el programa. Esta es
la tarea mas complicada en mi opinion y tengo una recopilacion de todo lo que ido aprendiendo
en formato de tutorial en camino, aunque siempre puedes buscar ayuda en foros.
46