Está en la página 1de 46

Índice de contenido

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

LICENCIA: CC by-sa, creditos gerkrt

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.

Introduccion basica a la programacion


La programacion es un proceso lexico, donde se escriben las ordenes que uno quiere que el
programa ejecute.

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.

Como testear rapidamente


Si quieres testear codigo rgss de forma facil y rapida, una opcion es crear una clase de testeo
que al instanciarla ejecute el codigo de testeo:

class Testear

def initialize

# ordenes de testeo aqui

p 'prueva, todo va bien!'

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.

Switches/Interruptores e introduccion basica a ruby


Esta es la parte mas basica del rpgmaker y que todo el mundo sabe hacer. Un switch se evalua
como verdadero o falso, como encendido o apagado y se usa para marca o para guardar
informacion de algo.

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.

# Creamos una variable boolean que es false:

interruptor = false

# Ahora la activamos:

interruptor = true

Vamos a explicar las partes mas basicas de este codigo:

-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.).

Operaciones y valores basicos


En la programacion para dar un valor a una variable se usa el simbolo =. Si ya se que te sonara a
igualdad y no asignacion pero asi es. Se asigna al identificador de la izquierda el valor de la
derecha:

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

Esto es el equivalente a la expresion anterior. Con el += el programa suma automaticamente el


valor actual de la variable a la actual, por lo que te ahorras codigo.

variable_numerica2 = variable_numerica * 15

variable_numerica3 = (variable_numerica/2) + (variable_numerica2/2)

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.

Declaracion de variables e identificadores

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]

p ' esta lleno'

else

p ' esta vacio'

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'

#hacer lo que sea

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.

Condicion y efectos II, eventos comunes y pseucodigo


Este comando es el equivalente en programacion al if. Vamos a poner el primer ejemplo
practico para que lo vayais captando.

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:

Explica aquesta comanda metodo = evento comun

eleccion = $comando. preguntas_y_respuestas ( 'Dios ha muerto', 'Alabado sea el señor')

if eleccion == 'Dios ha muerto'

cura_relacion -=5

if eleccion == 'Alabado sea el señor'

cura_relacion -=5

end

end

9
if cura_relacion > 100

cura_relacion = 100

end

if cura_relacion < 0

cura_relacion = 0

end

Comentarios y claridez del codigo


Normalmente algo infrautilizado en los rpgmaker, aqui es importantisimo ya que normalmente
se dice que se mantiene y modifica mas codigo que se crea de 0, y con el XP tenemos el mas
claro ejemplo: montones de scripts que se han creado estudiando los default.

Obviamente los scripts de enterbrain estan ampliamante comentados, estructurados y


documentados, a la vez que bien separados e implementados en la Orientacion a Objetos para
que resulte muy facil para qualquiera escribir o modificar nuevo codigo basado en ello.

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:

# Define el valor base a usar como daño

daño = 15

# Calcula y aplica el daño. Se corrige usando la formula del enemigo

daño_creado = enemigo.calcular_daño daño

enemigo.aplicar_daño daño_creado

=begin

todas las lineas escritas aqui

son comentarios

y son excluidas por el programa

=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.

Eventos comunes: Funciones I


Seguro que habreis usado y encontrado muy utiles los eventos comunes en el rpgmaker. Sus
ventajas son que os permiten tener un set de eventos a llamar organizados y modularizados. De
esta forma se facilita un monton la creacion de engines.

En la programacion el equivalente a esto es la funcion. I se usa de la misma forma.

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.

Eventos comunes: Funciones II y numeros aleatorios


Ahora vamos a provar con algo mas complicado, asi como añadir el concepto de parametros
para las funciones o los valores de retorno.

Imaginemos que queremos crear un sistema de robo en combate con el sigiente diseño:

1- Todos los personajes van a poder robar

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.

El equivalente en pseudocdigo seria esto:

def robar(personaje, enemigo)

if rand 100 > personaje.atributo_robar

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 '.' .

Funciones y globales: La mayor diferencia respecto al maker es que en este estamos


acostumbrado siempre a tener a nuestra disposicion un set de variables y switches fijos y
permanentes. De esta forma se puede guardar el estado o modificaciones sin usar return, y
tampoco seria necesario pasar un parametro porque se podria acceder a una variable global en
todo momento.

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

# No hace falta el return pero devuelve automaticamente esa x.

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.

En ruby para evaluar tres variables seria asi de facil:

if variable1 == 99 and variable2 > 5 and variable3 <= 8

I si queremos negar toda la condicion anterior, seria:

unless variable1 == 99 and variable2 > 5 and variable3 <= 8

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

if a == 99 and not b > 5

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:

file = fopen('ruta fichero', 'w')

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:

p palabra + ':' + decimal_float.to_s

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.

Los strings tienen muchos metodos muy variados, por ejemplo:

arr_str = 'w e p'.split(' ') # divide el string en un array de strings separando lo por el caracter
pasado como separador.

'min'.upcase # pone todo el texto en mayusuclas

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:

¿De que rama animal procede? Es un mamifero

16
¿Que hace un perro? Ladra, come, mueve la cola

¿Que es tiene un perro? Su raza, color de pelo, edad, nombre...

Ahora vamos a trasladar todo esto a la programacion:

class Perro < Mamifero

def initialize (raza, color_pelo, edad)

@raza = raza

@color_pelo = color_pelo

@edad = edad

end

def ladrar

`p 'bub!'

end

def mover_cola

p 'el perro mueve la 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.

El metodo initialize es el constructor y es llamado cuando se crea un nuevo perro. El constructor


crea la clase y le añade una serie de valores que necesitara, en este caso: raza, color de pelo,
edad. Nota que el constructor puede recibir parametros como si de una funcion fuera, asi que al
crear el perro podriamos pasarle los argumentos necesarios.

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.

class Perro < Mamifero

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.

Acceder a las variables

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.

Analizemoslo segun este principio:

-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:

class Perro < Mamifero

attr_accessor :edad

attr_reader :raza

attr_reader :color_pelo

def initialize (raza, color_pelo, edad)

@raza = raza

@color_pelo = color_pelo

@edad = edad

end

def ladrar

`p 'bub!'

end

def mover_cola

p 'el perro mueve la 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

Tendriamos una instancia de String basada en el numero y su metodo to_s

Siendo practicos

En realidad tu no vas a necesitar crear aun objetos, pero es bien facil:

perro = Perro.new ('Doberman', 6, 'Negro')

Ahora perro es una instancia de Perro. Para comparar:

string = String.new ('Frase')

Es lo mismo pero con otro objeto distinto.

De la misma forma, podemos llamar a los metodos de perro:

perro.ladrar

perro.comer

O incluso a los de mamifero:

perro.caminar

Tambien podriamos examinar sus variables:

p perro.raza

Y modificarlas si podemos:

20
perro.edad += 1

Nota que el . Se usa para todo. Para metodos y variables.

Pero yo no uso el .new para... ¿que pasa aqui?

Eso es porqueruby lo hace automaticamente por ti para facilitar la programacion. Obviamente


tener que llamar a los constructors (.new) de todo seria un rollazo, asi que para los objetos y
tipos basicos no es necesario:

string = String.new ('Frase')

string = 'Frase'

Son equivalentes.

Libreria estandard de ruby


Ruby trae consigo una enorme biblioteca de objetos con docenas de clases diferentes y con
muchos metodos implementados para hacer la mayoria del trabajo pesado.

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

def test( arg)

21
end

test # Error por no pasar todos los parametros.

'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 los eventos habreis usado tres tipos de bucles:

-Los eventos de tipo automatico

-Los eventos de tipo proceso paralelo

-El uso de los bucles en los comandos de eventos.

En todos los casos se muestra como trabaja un bucle y su funcion en RGSS es equivalente. Por
ejemplo:

for comando in evento

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':

for comando in evento

# Comprueba que si es un comando de salir, rompera el bucle

22
if comando.tipo == 'Salir de proceso paralelo'

# La sentencia break rompe la ejecucion de los bucles.

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.

for manzana in lista_manzanas

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:

for nombre_variable_extraida in lista_datos_a_iterar y termina con un end.

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

while marca == true

if obtener_mazana

vender_manzana

else if cerrar tienda

marca = false

end

end

En este caso el bucle que incorpora la condicion en su declaracion se ejecutara mientras la


variable marca sea verdadera y cada vez ejecutra el codigo central. En este caso es un codigo
imaginario hipotetico en el cual el bucle se queda escuchando si se puede vender una manzana
o no y cuando se pasa una señal de cerrar la tienda, tiene que romper el bucle, por lo que pone
la condiciona false.

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 personajes de tu juego, enemigos, armas, objetos, mapas...

-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 = [] # Crea un array vacio por ahora

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,

6,7,8,9,10 # la condicion es que el espacio venga despues de una coma ,

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.

Ruby permite una serie de comandos bastante extensos en este sentido:

lista.last # ultimo valor del array

val = lista[-1] # lo mismo, solo que guardandolo en una variable nueva

lista.last # ultimo valor del array

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

lista[1] += 3 # suma 3 al elemento en la posicion 1.

Metodos basicos para los arrays

.push : Pone un valor al final del array

.first : Primer valor

.include?(valor) : Se usa en los condicionales. Ruby buscara si valor existe en el arary y devolvera
true si es cierto.

.size : Da el numero total de elementos del array

Ejemplo de array

array = 1,5,99

p “Array: #{array} Tamaño: @{array.size}”

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.

Obviamente es mucho mas facil recordar esto:

27
hash_personajes['alex']

Que usar un numero abstracto cada vez:

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= (

'alemania' => 'berlin',

'españa' => 'madrid'

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.

Comentario final sobre estructuras de datos

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).

Iterando en listas y hashes


Una de las ventajas de la programacion es usar los bucles para tratar enormes grupos de
informacion. Imaginemos que tenemos una base de datos con 1500 personas. Cada una de ellas
tiene un valor de popularidad que queremos modificar, sumadole 10 puntos. ¿Como lo
hariamos?

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

persona.popularidad += 15 # cada vez se extrae y usa la siguiente persona

end # los bucles se mantienen hasta haber acabo de mostrar toda la lista, repitiendo la
operacion en su interior.

La sintaixs es:

for nombre_variable in array

Nota que nombre_variable es un nombre que puedes elegir libremente.

Iterando entre dos numeros y rangos

Tambien es muy comun este tipo de iteracion, a la par que es equivalente:

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

¿Facil, eh? Pues en ruby aun se puede acortar mas.

lista_personas.each {|i|i.popularidad += 10}

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.

Sobre los hashes

Los hashes tambien pueden ser iterados en caso de necesidad, y el metodo es exactamente
igual:

hash_personas.each {|i|i.popularidad += 10}

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.

personaje.lista_habilidades = 1,8, 12, 28 # Lista imaginaria de las variables del personaje.


Contiene sus ids

# usadas en la base de datos.

30
hab_10pm = [] # crea array vacio para poner luego

for id_hab in personaje.lista_habilidades # itera en la lista

# Usa la id extraida del array para indexr el array de la base de datos en busca

# del valor de pm del hechizo

if base_de_datos.habilidades[id_hab].pm < 10

# Va llenando el array de respaldo

hab_10pm. push id_hab

end

end

# Lo imprime

hab_10pm.eacb {|i|p I}

Del pseudo codigo a la realidad


He usado pseudocodigo porque creo que es lo mejor en una corta y primera introduccion como
esta, sin embargo y aunque sean equvialentes, lo que has ido leyendo no tiene porque ser
codigo ruby valido. Ahora que ya sabes mas aqui vienen las traducciones que podras estudiar
tranquilamente:

if base_de_datos.habilidades[id_hab].pm < 10: if $data_skills[id_hab].ph < 10 . Obviamente el


pm se traducee a ph y tal. En este caso se accede a los valores configurados de la base de datos
usando los obejtos globales(accesibles desde qualquier lugar) llamados $data.

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.

personaje.lista_habilidades = 1,8, 12, 28: En la realidad seria $game_actors[id_personaje].skills.

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

Usando este formato de lista.

Reusabilidad del codigo y librerias


Esto con los eventos es algo raro, pero si existe. Imaginate que te pasan una demo o juego-
tutorial con algunos engines hechos. Esto contienen ya muchas funciones que tu vas a usar o
modificar para adaptarlas a tus propositos.

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.

¿Que puedo hacer y que no?

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.

Proyecto final de tutorial (mi primer script Fisher Price)


Para acabar este tutorial vamos a crear nuestro primer script potable, a la par que
introduciremos algunos pasos mas. Crearemos un sistema capaz de drenar vida I magia al
enemigo al atacar con la arma adecuada.

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

# modificado para drenado de pv y ph

#------------------------------------------------------------------------------

# This class deals with battlers. It's used as a superclass for the Game_Actor

# and Game_Enemy classes.

#==============================================================================

class Game_Battler

#--------------------------------------------------------------------------

# * Applying Normal Attack Effects

# attacker : battler

# modificado para drenar pv I ph al asignar el daño

#--------------------------------------------------------------------------

def attack_effect(attacker)

# Clear critical flag

self.critical = false

# First hit detection

hit_result = (rand(100) < attacker.hit)

# If hit occurs

if hit_result == true

34
# Calculate basic damage

atk = [attacker.atk - self.pdef / 2, 0].max

self.damage = atk * (20 + attacker.str) / 20

# Element correction

self.damage *= elements_correct(attacker.element_set)

self.damage /= 100

# If damage value is strictly positive

if self.damage > 0

# Critical correction

if rand(100) < 4 * attacker.dex / self.agi

self.damage *= 2

self.critical = true

end

# Guard correction

if self.guarding?

self.damage /= 2

end

end

# Dispersion

if self.damage.abs > 0

amp = [self.damage.abs * 15 / 100, 1].max

self.damage += rand(amp+1) + rand(amp+1) - amp

end

# Second hit detection

eva = 8 * self.agi / attacker.dex + self.eva

hit = self.damage < 0 ? 100 : 100 - eva

hit = self.cant_evade? ? 100 : hit

35
hit_result = (rand(100) < hit)

end

# If hit occurs

if hit_result == true

# State Removed by Shock

remove_states_shock

# Substract damage from HP

self.hp -= self.damage

# State change

@state_changed = false

states_plus(attacker.plus_state_set)

states_minus(attacker.minus_state_set)

# When missing

else

# Set damage to "Miss"

self.damage = "Miss"

# Clear critical flag

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.

Lo segundo es que programando es importante añadir comentarios para documentar. Aqui

36
quizas esten de mas por lo poco grande dell proyecto pero en todo caso son validos igualmente.

3. Creando las variables de configuracion

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:

armas_drenadoras = [[1, 40, 'pv'], [3, 60, 'ph']]

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 = [] # Declaramos el array antes de poner nada mas.

armas_drenadoras[1] = [ 40, 'pv'] # Asi se hace para añadir nuevos elementos al array.

armas_drenadoras[3] = 60, 'ph' # El azucar sintatico mola, xd. Es equivalente a lo anterior, ya


que lo que define al array es la , I no el [].

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.

4. Protegiendo y haciendo visible el array

¿Donde declaramos el array? ¿Con que tipo de objeto, o alcance?

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 = [] # Declaramos el array antes de poner nada mas.

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

Lo de llamar minombre al modulo tiene el motivo de diferenciarlo de los demas y de sus


variables, ya que un modulo se puede extender igual que una clase y te lo podrian sobre
escribir.

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.

Finalemente, para acceder a una variable en un modulo se escribe:


nombremodulo::nombrevariable.

Osea aqui: Minick::Armas_drenadoras

5. Implementandolo en el metodo attack effect

# Substract damage from HP

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

# Comprueva que haya una entrada en el array para la arma equipada

if Minick::Armas_drenadoras[attacker.weapon_id] != nil

# Drena segun el tipo de la misma

if Minick::Armas_drenadoras[attacker.weapon_id][1] == 'pv'

attacker.hp += self.damage * Minick::Armas_drenadoras[attacker.weapon_id]


[0]/100

else

attacker.sp += self.damage * Minick::Armas_drenadoras[attacker.weapon_id]


[0]/100

end

end

Vamos a comentar paso por paso este sistema.

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.

El segundo condicional es muy facil. Comprovamos el tipo contenido en el subarray. Los


subarrays se acceden usando [][] contiguos.

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.

attacker.sp += self.damage * Minick::Armas_drenadoras[attacker.weapon_id][0]/100

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.

6. ¿Ya hemos terminado?

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:

1.is_a? Numeric → true

1.is_a? String → false

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).

El codigo final seria pues:

# 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] != nil and attacker.is_a? Game_Actor

# Drena segun el tipo de la misma

if Minick::Armas_drenadoras[attacker.weapon_id][1] == 'pv'

attacker.hp += self.damage * Minick::Armas_drenadoras[attacker.weapon_id]


[0]/100

else

attacker.sp += self.damage * Minick::Armas_drenadoras[attacker.weapon_id]


[0]/100

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.

8.Script completo y presentable al mundo

#=============================================================================
=

# Mi primer script Fisher Price

# 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:

Amas_drenadoras[5] = 60, 'ph'

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

Armas_drenadoras = [] # No toques esto

Armas_drenadoras[1] = [ 40, 'pv']

Armas_drenadoras[3] = 60, 'ph'

end

#==============================================================================

# ** Game_Battler

# modificado para drenado de pv y ph

#------------------------------------------------------------------------------

# This class deals with battlers. It's used as a superclass for the Game_Actor

# and Game_Enemy classes.

#==============================================================================

class Game_Battler

#--------------------------------------------------------------------------

# * Applying Normal Attack Effects

# attacker : battler

# modificado para drenar pv I ph al asignar el daño

#--------------------------------------------------------------------------

def attack_effect(attacker)

# Clear critical flag

self.critical = false

# First hit detection

42
hit_result = (rand(100) < attacker.hit)

# If hit occurs

if hit_result == true

# Calculate basic damage

atk = [attacker.atk - self.pdef / 2, 0].max

self.damage = atk * (20 + attacker.str) / 20

# Element correction

self.damage *= elements_correct(attacker.element_set)

self.damage /= 100

# If damage value is strictly positive

if self.damage > 0

# Critical correction

if rand(100) < 4 * attacker.dex / self.agi

self.damage *= 2

self.critical = true

end

# Guard correction

if self.guarding?

self.damage /= 2

end

end

# Dispersion

if self.damage.abs > 0

amp = [self.damage.abs * 15 / 100, 1].max

self.damage += rand(amp+1) + rand(amp+1) - amp

end

# Second hit detection

43
eva = 8 * self.agi / attacker.dex + self.eva

hit = self.damage < 0 ? 100 : 100 - eva

hit = self.cant_evade? ? 100 : hit

hit_result = (rand(100) < hit)

end

# If hit occurs

if hit_result == true

# State Removed by Shock

remove_states_shock

# Substract damage from HP

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] != nil and attacker.is_a? Game_Actor

# Drena segun el tipo de la misma

if Minick::Armas_drenadoras[attacker.weapon_id][1] == 'pv'

attacker.hp += self.damage * Minick::Armas_drenadoras[attacker.weapon_id]


[0]/100

else

attacker.sp += self.damage * Minick::Armas_drenadoras[attacker.weapon_id]


[0]/100

end

end

# State change

@state_changed = false

states_plus(attacker.plus_state_set)

states_minus(attacker.minus_state_set)

# When missing

44
else

# Set damage to "Miss"

self.damage = "Miss"

# Clear critical flag

self.critical = false

end

# End Method

return true

end

end

Final del tutorial y recomendaciones


Terminado el tutorial recomiendo expandir tus conocimientos leiendo tutoriales o libros de ruby
y tambien de RGSS. Busca el libro de anemus sobre RGSS u otros, por ejemplo, y ya tendras una
base mucho mas adecuada para entenderlo.

Tambien recomiendo buscar informacion sobre la orientacion a objetos y sobretodo el concepto


de herencia pues se da muy poco en este tutorial y es vital.

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.

Algunas ideas a buscar:

-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

-Gran repaso a las clases y modulos

-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

También podría gustarte