Mundo Maker
¡Bienvenid@ a Mundo Maker!

¿Quieres aprender todo sobre el RPG Maker?



Regístrate y forma parte de Mundo Maker.
Conectarse

Recuperar mi contraseña

Temas importantes
----------------------------------------
Páginas con recursos RPG Maker
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
Afiliados
Estadísticas
Tenemos 4193 miembros registrados.
El último usuario registrado es Godot.

Nuestros miembros han publicado un total de 85222 mensajes en 12132 argumentos.

[Tutorial] Las "reserved words" más típicas

Ver el tema anterior Ver el tema siguiente Ir abajo

[Tutorial] Las "reserved words" más típicas

Mensaje por Wecoc el 2014-01-29, 23:48

ATENCIÓN: Si no sabes nada de RGSS, RGSS2 o RGSS3 no te esfuerces con ésto y busca antes un tutorial más básico. Entre que no me explico demasiado bien a veces y que parto de la idea de que quien lo lea tiene cierta base, si un inexperto en el tema lee el topic le puede dar un chungo.

Las "reserved words" fueron marcadas en azul.

alias:
alias se utiliza cuando quieres redefinir un nuevo método usado en un script anterior y/o oculto, para que a parte de ponerle las funciones nuevas siga teniendo las antíguas.

Llamada:
alias new_method old_method unless $@

Donde old_method es el nombre real del método y new_method un nuevo nombre para definirlo y que corresponderá al mismo tal y como era antes de hacer el cambio.

No se puede usar en métodos de tipo
self.(nombre)

Código:
## (( Script A ))

class Test
  def refresh
    self.contents.clear
    # ( Montones de cosas más)
  end
end

## (( Script B ))

class Test
  alias default_refresh refresh unless $@
  def refresh
    default_refresh # aplica lo que ya tenía en el Script A
    self.contents.draw_text(0, 0, 184, 32, "Nueva función", 0)
    # ( Montones de cosas más)
  end
end

Recomiendo poner nombres específicos por ejemplo refresh_minimap_wecoc , porque si diera la casualidad de que se usaran dos scripts que ambos usan un
alias para el mismo método y tuvieran el mismo nuevo nombre daría error.

Os digo algunos truquillos.

Si no sabes cual era el arity (creo que se llama así xD significa el número de argumentos a hacer en la llamada por ejemplo
def initialize(a, b, c) sería 3) puedes usar (*args)

Código:
## (( Script B ))

class Test
  alias default_refresh refresh unless $@
  def refresh(*args)
    default_refresh(*args) # aplica lo que ya tenía en el Script A con sus argumentos
    self.contents.draw_text(0, 0, 184, 32, "Nueva función", 0)
    # ( Montones de cosas más)
  end
end

El método antíguo se guardará con nuevo nombre que le has dado así que podrás hacer la llamada con el nombre normal para el método ampliado o el nuevo nombre para el método original.

Código:
# PROBLEMA

class Window_Scrollable < Window_Selectable
  def initialize(x, y, width, height)
    super(x, y, width, height) # Carga lo de Window_Selectable pero en realidad
                              # queremos que cargue lo de Window_Base !!
    # (Hacer algo)
  end
end

# SOLUCIÓN

class Window_Base
  alias window_base_initialize initialize unless $@
end

class Window_Scrollable < Window_Selectable
  def initialize(x, y, width, height)
    window_base_initialize(x, y, width, height)
    # (Hacer algo)
  end
end

super:
super se usa cuando tienes una clase ancestral (A) a otra (B) es decir cuando tienes una situación de éste tipo: class B < A y quieres ampliar un método de la clase A en la B.

Ejemplo:

Código:
class Hello
  def initialize(a, b)
    @a = a
    @b = b
  end
end

class World < Hello
  def initialize(a, b, c)
    super(a, b) # Hace lo que estaba escrito en el initialize de Hello
    @c = c
  end
end

En
alias puse un truquillo que arregla un posible problema que podrías tener con super.

Si no sabes el número de argumentos ( por ejemplo initialize(a, b, c) ) de la llamada original puedes usar (*args), aún así éste caso es mucho más típico en
alias que en super (ver ejemplo allí)

do, break y otras cosas ( BUCLES 1):
Algunos métodos usan un argumento especial que se pone así { } y que normalmente aplica un bucle con alguna restricción. por ejemplo 2.times{ p "Hola" } . do hace lo mismo pero multilínea. Atención no dejarse el end en ese caso.

Código:
2.times do
  p "Hola"
end

Ese argumento especial se llama &block. El método más típico que usa el &block (o
do) es el loop.

do supone un ciclo en el que se hará algo mientras se cumpla una condición si la hay.
break sirve para romper el ciclo, y en loop como no hay condición es obligatorio ponerlo o el script crashearía.

Código:
a = 0
loop do
  a += 1
  p a
  break if a >= 5
end

Para la condición a veces se usan variables, por ejemplo en el each de array en el que la variable es cada una de las entradas de la array, pero puede haber más de una como en each_with_index donde las variables son la entrada de la array y su índice.

Código:
a = ["A", "B", "C", "D", "E"]
a.each_with_index{|x, i| p x, i+1} # "A" 1, "B" 2 ...

Para ponerlo con el do se hace igual.

Código:
a = ["A", "B", "C", "D", "E"]
a.each_with_index do |x, i|
  p x
  p i + 1
end

Usando el
do, estan el times, el upto y el downto

times repite una cosa x veces, en uno de los ejemplos anteriores apareció.

upto y downto son un tipo de ciclo que hacen algo desde un valor hasta otro. El
break también tiene cabida aquí.

upto va sumando de 1 en 1 desde un integer hasta el siguiente, a cada paso suma 1. downto es igual pero a cada paso resta 1.

Código:
1.upto(5) do |number|
  p number # 1, 2, 3, 4, 5
end

5.downto(1) do |number|
  p number # 5, 4, 3, 2, 1
end

Si te interesaron upto y downto te interesará saber que no tienes por qué ir de 1 en 1, existe step que es exactamente igual que ellos pero tú elijes el paso, tanto positivo como negativo.

Código:
4.step(12, 2) do |x|
  p x # 4, 6, 8, 10, 12
end

Y ya que estamos hablando de bucles hay un método interno a ellos llamado
retry que repite el bucle a un mismo paso en vez de avanzar si se cumple una condición puesta con if.

Código:
a = 0
1.upto(3) do |number|
  a += rand(2)
  p number
  retry if a == 1 # Por ejemplo 1, 2, 2, 2, 3 : se repite el paso 2 del bucle
end

El hermanastro gemelo de
retry es redo. Por lo que a mí respecta, hacen lo mismo. Seguro que hay alguna diferencia - creo que redo vuelve a hacer el paso del bucle pero sin tener en cuenta que ya lo hizo y en cambio retry no, o alguna huevada así - pero tampoco es muy importante, es cuestión de testear, si es que alguna vez los llegáis a usar.

Nyyaaa, me lo debaja: el
next. El next se salta uno de los pasos del bucle si se cumple una condición.

Sigamos porque hay más cosas en los bucles. Hay un bucle parecido al loop
do que es el begin, aunque es un poco especial.

begin no utiliza do. La diferencia con loop do es que para romper el ciclo de begin la mayoría de veces se utiliza until ((nota a parte: y a veces a parte usa rescue)), el cual también puede ser usado en los otros bucles pero no es lo más habitual.
Hablaré de
rescue a parte porque no es exclusivo de begin, resumidamente evita que salga un error devolviendo algo en vez del error.

En realidad el que hace de bucle en el
begin es el until, el cual va en el end (sin el until, begin funcionaría una sola vez)

until cicla el begin hasta que se cumpla una condición concreta.

Código:
a = 0
b = 10
begin
  a += 1
  b -= 1
  p b - a # 8, 6, 4, 2, 0
end until a >= b

Finalmente, hay otro llamado
while que hace que mientras suceda una condición se produzca el ciclo; es como loop do pero con condición añadida.

Voy a dar un último ejemplo de uso del
do, uno en el que no hay bucle, solo condición y además ésta es un símbolo. ¡Qué cosa tan rara! Es el caso del catch.
El catch aplica un proceso en el que si se cumple que la variable correspondiente a ese símbolo vale
true, pasa algo, y si no no pasa nada. Es difícil de explicar pero con un ejemplo se verá más claro.

Código:
def generar_integer
  x = rand(1000) # Genera un número random entre 0 y 999
  throw :var if x == 123 # Si el número vale 123 activa :var
end

catch(:var) do
  1000.times { generar_integer } # Genera 1000 números (bucle times)
  p "¡Se generaron 1000 números y ninguno vale 123!" # Solo si :var fue activada dice eso
end

¿Os mareasteis con tanto bucle? xD

for, un ciclo especial ( BUCLES 2):
El famoso for es un ciclo que hace algo en cada valor de un rango o de una array. No usa do o &block.
Si lo hace por rango irá sumando éste de 1 en 1 y sustituirá ese número por una variable, a la que muchas veces se le pone i de integer (número entero). Si lo hace por array hará el ciclo para cada uno de los valores de la array por orden sumando su índice de 1 en 1.

Recordad que los rangos pueden ser de dos puntos si incluyen el último número o de tres si no lo incluyen. Recordad también que se pueden poner
for encadenados.
for no es nada sin el in, se usan conjuntamente de la siguiente manera:

Llamada con un rango:
Código:
for i in 0...10
  p i # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
end

Código:
array = [4, 3, 9, 2]
for i in array
  p i # 4, 3, 9, 2
end

Al ser un bucle también puede usar
break, retry y next y todos esos vistos en el spoiler anterior, de hecho next es mucho más típico en éste tipo de bucles.

Código:
array = [4, 3, 0, 2]
for i in array
  next if i == 0
  p i # 4, 3, 2
end

rescue y ensure:
rescue evita que salga un error de código haciendo algo. Es como decir "en caso de emergencia, haz x cosa". Suele ir seguido de nil, lo que significa que no haga nada, solo sale el error y ya está.
Es útil cuando cargas un archivo con el cache, ya que si lo intentaras cargar y no estuviera en la carpeta daría error de "No se encontró archivo". Si pones
rescue nil detrás de esa línea ignorará el error.

Código:
self.bitmap = RPG::Cache.picture(@picture_name) rescue nil

Si por ejemplo usaste
rescue dentro de begin o de algún loop por el estilo y quieres que pasado el rescue suceda algo más independientemente de si hubo el rescue o no, y además quieres que ese algo siga estando dentro del bucle, es que te lo montas complicado, jeje. Para ello tienes que usar ensure.

Código:
a = 12
b = 0
begin
  eval"#{a} / #{b}" # Evalúa a / b
rescue ZeroDivisionError # Si estas dividiendo entre 0
  p "Dividiste entre 0, pendejo."
ensure
  p "Operación a / b realizada."
end

case y when:
Dada una variable con distintos valores posibles, se aplicará algo según si el valor de ésta variable entra dentro de una condición u otra.

Llamada:
Código:
case var
when a
  # pasa A
when b
  # pasa B
else
  # pasa C
end

La "condición" del
when puede ser un rango, un número, una string, etc.

Ejemplo:

Código:
case @item
when RPG::Item # Item
  $game_party.lose_item(@item.id, @number_window.number)
when RPG::Weapon # Weapon
  $game_party.lose_weapon(@item.id, @number_window.number)
when RPG::Armor # Armor
  $game_party.lose_armor(@item.id, @number_window.number)
end

Si detrás del
when y su condición pones then puedes poner lo que pase en la misma línea siempre y cuando eso solo ocupe una. when se usa conjuntamente con case, mejor no intentar usarlos separadamente.

return y yield:
return devuelve algo y a la vez interrumpe el método aunque haya más líneas debajo, por lo que suele ir o al final del método o con una condición.

Código:
def get_power
  return @power
end

Es, creo yo, de los más fáciles de entender y utilizar. Además es muy usual.
Puedes usarlo sin nada, simplemente
return, si lo único que te interesa es frenar el proceso dada una condición.

Código:
def do_something
  a = rand(2)
  if a == 0
    return
  end
  p a
end

En cambio, otro más complicadillo es el
yield.

Te preguntarás qué hace
yield. Yo también xDDD
Es para decirlo de manera fácil el equivalente de
return para &block.
Como dije en el apartado de los Bucles (1), &block es cuando pones una condición así { } detrás de un método.

Un ejemplo de &block:

Código:
array = [0, 1, "2", nil, "Hey", :hola]
p array.select{|x| x.is_a?(String)} # ==> ["2", "Hey"] (seleccionó las string)

Los ejemplos de uso de
yield que encontraréis buscándolos en los scripts del RPG maker no os dejaran las cosas demasiado claras.

El caso más básico de
yield sería el siguiente.

Código:
def greeting
  yield
end

greeting {p "Hola"} # => "Hola"

Es más normal devolver el
yield con algo, y ese algo será la variable que usaremos cuando llamamos el &block.

Código:
def each_actor
  yield @actor_id
end

class_array = each_actor{|actor| $data_actors[actor].class_id}

Se puede usar más de una variable cuando llamas el &block, se pondrán por comas detrás del
yield.

Aquí se verá más claro el símil entre
yield y return, quizá.

Código:
def each_vowel
  vowel_array = ["a", "e", "i", "o", "u"]
  if block_given?
    vowel_array.each { |vowel| yield vowel }
  else
    return vowel_array
  end
end

each_vowel { |vowel| p vowel.concat("l") } # => al, el, il, ol, ul

undef:
undef elimina un método. Se usa cuando tienes una clase ancestral a otra, y te interesa que la otra tenga la mayoría de métodos de la primera, pero no todos.

Código:
class Hello
  def hola
    p "hola"
  end
end

class World < Hello
  undef hola
end

world = World.new
p world.hola # => eso dará error
avatar
Wecoc
Administrador
Administrador



Créditos 9272

Gracias : 503

Volver arriba Ir abajo

Re: [Tutorial] Las "reserved words" más típicas

Mensaje por orochii el 2014-01-30, 02:43

Jaja, pos bonito tema. Yo personalmente (?), cuando puedo prefiero usar each en vez de for... eh... sólo quería decirlo. xD. Es por culpa de Newold, cuando había dado recomendaciones de ciclos y otras cosas.
El each, eso sí, no es una palabra reservada. Es un método y depende de la clase. Ejemplo con un array:
Código:
ary=[1,2,3]
(0...ary.size).each{|i|
  ary[i]+=1
}
p ary #2,3,4
Eso en un for sería...
Código:
ary=[1,2,3]
for i in 0...ary.size
  ary[i]+=1
end
p ary #2,3,4
Termina siendo lo mismo xD.

El yield no tenía claro lo que hacía, xD. Pensaba era igual que hacer algo como...
Código:
def aguacatus_maximus
  1
  asereje_ja_deje
end
...ahora probé poner "yield 1" ahí y zas error xD!. En fin, igual se puede partir la función en subfunciones, yo lo hago para evitar dejar funciones inmensas, casi que me gusta convertir mi código en pseudocódigo a punta de funciones xDD.
Ahora entiendo es un mini-return, es como un break+return.

=D.
avatar
orochii
Caballero Shiro
Caballero Shiro

0/3

Créditos 6689

Gracias : 337

Volver arriba Ir abajo

Ver el tema anterior Ver el tema siguiente Volver arriba


Permisos de este foro:
No puedes responder a temas en este foro.