samuko
Profesional de WaH
¿Conocéis el juego 2048? Ese en el que hay que unir números para sumarlos e ir aumentándolos. Hay muchas variantes (no solo con números), pero aún no entiendo cómo no existe (o yo no me he enterado) con Pokémon, que literalmente evolucionan.
Así que he decidido crearlo Os presento el Poké2048: ¡combina evoluciones de Eevee para ganar puntos! Me ha llevado un tiempo, pero creo que está entretenido. Además, lo puedes instalar en tu propio fangame de forma muy sencilla.
[IMG width="345px"] width="339px"] width="359px"]
¡Espero que os guste! ^^
Así que he decidido crearlo Os presento el Poké2048: ¡combina evoluciones de Eevee para ganar puntos! Me ha llevado un tiempo, pero creo que está entretenido. Además, lo puedes instalar en tu propio fangame de forma muy sencilla.
[IMG width="345px"] width="339px"] width="359px"]
Descarga el archivo y copia todas las carpetas EXCEPTO 'DATA/' en la carpeta de tu Fangame.
Advertencia: copiar estos archivos supondrá reemplazar los iconos de los Pokémon en la carpeta Icons/ y de la carpeta Windowskins/
Luego copia este código encima del Script 'Main':
Por último, para empezar a jugar puedes usar el script 'pb2048', que devuelve el número de evoluciones conseguidas (si evo son el nº de evoluciones, 2**evo devuelve la puntuación alcanzada).
Advertencia: Para "ganar" el juego se necesita llegar a 11 evoluciones, mientras que Eevee tiene 8. Por eso he añadido tres nuevas (Stoneon, Fliyeon, Rhyeon). Para que funcione, debes añadirlas a tu lista de Pokémon o cambiarlas por otros Pokémon.
Advertencia: copiar estos archivos supondrá reemplazar los iconos de los Pokémon en la carpeta Icons/ y de la carpeta Windowskins/
Luego copia este código encima del Script 'Main':
Ruby:
# =============================================================================
# ** Poke2048 by Samuko
# You can copy this page and paste in your Pokemon Essentials scripts.
# To use it, call method 'pb2048'
# Para usarlo, llama el script 'pb2048'
# =============================================================================
# undos: nº de veces que puedes deshacer una jugada
# animations: muestra las animaciones al evolucionar
# showtext: muestra las instrucciones al iniciar el juego
def pb2048(undos=3,animations=true,showtext=true)
Poke2048_Scene.new.start(undos,animations,showtext)
end
class Poke2048_Scene
POKEMON = [0,:EEVEE,:VAPOREON,:JOLTEON,:FLAREON,:ESPEON,:UMBREON,:LEAFEON,:GLACEON,
:STONEON,:FLIYEON,:RHYEON,:SYLVEON]
COLORS = [[255]*3,[255]*3,[0,0,255],[255,255,0],[255,0,0],[255,0,0],[245,40,170],[0,0,80],[0,255,0],[0,200,250],
[140,50,0],[170,110,255],[0,0,120],[200,200,0]]
X0 = (Graphics.width-64*4)/2
Y0 = (Graphics.height-64*4)/2
def start(undos=0,animations=true,showtext=false)
@animations = true
@table = Table.new(4,4) # => Table 4x4
@tables_history = Array.new(undos)
#@pokes = [] # => Array of [id,i,j] where id=index of POKEMON, (i,j) is position of the pokemon
@viewport = Viewport.new(0,0,Graphics.width,Graphics.height); @viewport.z = 99999
@sprites = {}
@sprites["bg"] = s = SpriteWrapper.new(@viewport)
s.z = 0
s.bitmap = BitmapWrapper.new(Graphics.width,Graphics.height)
s.bitmap.fill_rect(0,0,Graphics.width,Graphics.height,Color.new(255,255,255))#COLORS[0])
for i in 0...4
for j in 0...4
s.bitmap.fill_rect(X0 + 1+64*i,Y0 + 1+64*j,60,60,Color.new(200,200,200)) #color to tone be changed
@sprites["poke#{i}#{j}"] = Poke2048_Pokemon.new(@viewport)
end
end
for i in 0...undos_left
@sprites["celebi#{i}"] = s = Poke2048_Pokemon.new(@viewport,false)
s.poke = PBSpecies::CELEBI
s.y = Graphics.height - 64
s.x = 64*i
end
pbFadeInAndShow(@sprites)
@turn = 0
@maxspecies = 1
##
self.add(1)
self.add(1)
Kernel.pbMessage(_INTL("¡Utiliza las flechas ^ v <- -> para combinar a los Pokémon y evolucionarlos!")) if showtext
Kernel.pbMessage(_INTL("¡Pulsa Z para deshacer un movimiento!")) if showtext && undos > 0
@sprites["window"] = w = Window_AdvancedTextPokemon.newWithSize("",0,0,Graphics.width,64) # if !@sprites["window"]
w.viewport = @viewport
w.z = 500
refresh_window
yield(self) if block_given?
loop do
break if self.turn
@turn += 1
end
pbFadeOutAndHide(@sprites)
pbDisposeSpriteHash(@sprites)
@viewport.dispose
return evos
end
# i,j => 0...4
# force => 0=ignore if already exist, 1=find another pos if already exist, 2=delete if already exist
def add(poke,i=rand(4),j=rand(4),force = 1)
if @table[i,j] != 0 || force == 2
return if force == 0
return if tableFull?
i,j = rand(4),rand(4) until @table[i,j] == 0
return add(poke,i,j,force)
end
@table[i,j] = poke
scene_add(poke,i,j)
end
def turn
wait
if gameOver?
Kernel.pbMessage(_INTL("\\me[Voltorb Flip game over]¡Ohhh! El tablero está lleno...\\wtnp[80]"))
Kernel.pbMessage(_INTL("¡Enhorabuena! ¡Has conseguido {1} evoluciones!",evos)) if evos > 1
return true
end
if Input.trigger?(Input::B)
return true if Kernel.pbConfirmMessageSerious(_INTL("¿Quieres retirarte con {1} evoluci{2}?",
evos,evos == 1 ? _INTL("ón") : _INTL("ones")))
elsif Input.trigger?(Input::A)
if undos_left == 0 || !@tables_history.last; pbPlayBuzzerSE
else
pbPlayCrySpecies(:CELEBI)
@table = @tables_history.pop
#@tables_history.push(nil).delete_at(0) # make the last one nil to forbid repeating
refresh_boxes
refresh_undos
t = 10
wait(t) do |i|
c = 255*(t-i-1)/t
self.iterate { |i,j|
s = @sprites["poke#{i}#{j}"]
s.pokemon.color.set(c,c,c,c) if s && s.visible
}
end
end
end
dir = Input.dir4
if dir && [2,4,6,8] === dir
oldtable = nil
oldtable = @table.clone if undos_left > 0
done = self.movement(dir)
if done
thenew = 1
thenew = 2 if rand(5) == 0
thenew = 3 if rand(50) == 0
self.add(thenew)
if undos_left > 0
@tables_history.push(oldtable).delete_at(0)
end
end
end
return false
end
def evos; @maxspecies-1; end
def undos_left; @tables_history.length; end
def movement(dir)
@move_table = {} # [i, j] => no. of movements
@evolve_table = {} # [i-origin, j-origin] => [i-matching,j-matching]
@direction = dir
self.iterate(dir) { |x,y|
movethis(dir,x,y)
}
return self.scene_animation
end
def movethis(dir,x,y)
this = @table[x,y]
return if this == 0 # no poke here
@move_table[[x,y]] = 0 if !@move_table[[x,y]]
i = x; j = y # temporal i, j
loop do # iterate while not in the border
nexti,nextj,following = tableGetNext(dir,i,j)
break if following && following < 0 # Limit of the table -> stop
break if following != 0 && following != this # Different pokes -> stop here
# Here, next can be the same species (move & evolve) or either nil species (just move)
@move_table[[x,y]] += 1
@table[i,j] = 0#nil # Leave this tile
if following == 0
@table[nexti,nextj] = this # Fill the next gap
elsif following == this
@table[nexti,nextj] += 1 # Fuse with next
@evolve_table[[x,y]] = [nexti,nextj]
break # stop here
else
# shouldn't happen
PBDebug.forceLog("ERROR!! this=(#{i},#{j})=#{this}, following=(#{nexti},#{nextj})=#{following} -> will disappear")
end
i = nexti; j = nextj
end
end
def tableFull?
return @table.all? { |e| e != 0 }
end
def gameOver?
return false if !tableFull?
self.iterate do |i,j|
list = [[i,j+1],[i+1,j],[i,j-1],[i-1,j]].map { |e| @table[*e] }.compact
return false if list === @table[i,j]
end
return true
end
def tableGetNext(dir,i,j) #
iplus,jplus = {2=>[0,1], 4=>[-1,0], 6=>[1,0], 8=>[0,-1]}[dir]
i += iplus
j += jplus
return [i,j,@table[i,j]] if ((0...4)===i && (0...4)===j)
return [i,j,-1]
end
def iterate(dir=4,&block)
case dir
when 4
for i in 0...4
for j in 0...4
yield(i,j)
end
end
when 6
for i in [3,2,1,0]
for j in 0...4
yield(i,j)
end
end
when 8
for j in 0...4
for i in 0...4
yield(i,j)
end
end
when 2
for j in [3,2,1,0]
for i in 0...4
yield(i,j)
end
end
end
end
# SCENE METHODS #
def scene_add(poke,i,j) # add and wait
@sprites["poke#{i}#{j}"] = Poke2048_Pokemon.new(@viewport) if !@sprites["poke#{i}#{j}"]
s = @sprites["poke#{i}#{j}"]
time = 10
s.x = X0 + 64*i + 32
s.y = Y0 + 64*j + 32
s.zoom = 0.0
refresh_box(i,j)
wait(time) { |k|
s.zoom = (k+1)*1.0/time
s.x = X0 + 64*i + 32*(1-s.zoom_x)
s.y = Y0 + 64*j + 32*(1-s.zoom_y)
} if @animations
refresh_box(i,j)
end
# Animate data stored in @move_table (to @direction) & @evolve_table
def scene_animation
# MOVEMENTS
@move_table.delete_if { |point,moves| !moves || moves == 0 }
return false if @move_table.empty?
pbSEPlay("Mining cursor")
animations = []
time = 6
@move_table.each { |point,moves|
#next if !point || !moves || moves == 0
sprite = @sprites["poke#{point[0]}#{point[1]}"]
if !sprite && $DEBUG; p "!!! no existe el sprite #{point}. Tablero:"; print; next; end
xdesp = ydesp = 0
desp = moves*64.0/time
case @direction
when 8; ydesp = -desp
when 6; xdesp = desp
when 4; xdesp = -desp
when 2; ydesp = desp
end
animations.push([sprite,xdesp,ydesp])
}
wait(time) {
animations.each { |e|
e[0].x += e[1]
e[0].y += e[2]
}
}
animations.clear
@evolve_table.compact!#.filter! { |e| @evolve_table[e] }
if !@evolve_table.empty?
# Here, there're two same sprites for each point, so make one invisible.
if @animations
evolvesprites = @evolve_table.values.map { |point| @sprites["poke#{point[0]}#{point[1]}"] }
@evolve_table.keys.each { |point| s = @sprites["poke#{point[0]}#{point[1]}"]; s.visible = false if s }
#oldcolors = evolvesprites.map { |e| e.pokemon.color }
# turn white
#wait(6) { |i|
c = 255#*(i+1)/6
evolvesprites.each { |s|
s.pokemon.color.set(c,c,c,c)
}
#}
# minimize
spritesoldposes = evolvesprites.map { |e| [e,e.x,e.y] }
pbSEPlay("show",60,150)
t = 6
wait(t) { |i|
spritesoldposes.each { |a|
sprite,oldx,oldy = a
sprite.zoom = (t-i)/t.to_f
sprite.x = oldx + 32*(1-sprite.zoom)
sprite.y = oldy + 32*(1-sprite.zoom)
}
}
# update species
@evolve_table.each_value { |point|
sprite = @sprites["poke#{point[0]}#{point[1]}"]
newspecies = POKEMON[@table[*point]]
sprite.poke = newspecies
}
# maximize
wait(t) { |i|
spritesoldposes.each { |a|
sprite,oldx,oldy = a
sprite.zoom = i/t.to_f
sprite.x = oldx + 32*(1-sprite.zoom)
sprite.y = oldy + 32*(1-sprite.zoom)
}
}
# make visible
#wait(6) { |i|
c = 0#*(6-i)/6
evolvesprites.each { |s|
s.pokemon.color.set(c,c,c,c)
}
#}
end
maxspecies = @table.to_a.max
if maxspecies > @maxspecies
@maxspecies = maxspecies
pbPlayCrySpecies(POKEMON[maxspecies]) # play latest cry
if maxspecies == 12 # 2048
wait(20)
Kernel.pbMessage(_INTL("\\me[Voltorb Flip win]¡Enhorabuena! ¡Has obtenido {1} puntos!\\wtnp[80]",2**evos))
end
if maxspecies == POKEMON.length-2 # almost reach the end
POKEMON.push(rand(493)+1) rescue nil
end
end
refresh_window
end
refresh_boxes # Refresh all
return true
#pbPlayCrySpecies(POKEMON[@table[*@evolve_table.keys.sample]]) # play random cry
end
def wait(frames=1)
frames.times do |f|
Graphics.update
Input.update
pbUpdateSpriteHash(@sprites)
yield(f) if block_given?
end
end
def refresh_box(i,j)
@sprites["poke#{i}#{j}"] = Poke2048_Pokemon.new(@viewport) if !@sprites["poke#{i}#{j}"]
s = @sprites["poke#{i}#{j}"]
data = @table[i,j]
s.x = X0 + 64*i
s.y = Y0 + 64*j
s.zoom = 1.0
s.poke = POKEMON[data] # auto visibilize
s.pokemon.color.set(0,0,0,0)
end
def refresh_boxes
(0...4).each { |i| (0...4).each { |j| refresh_box(i,j) } }
end
def refresh_window
win = @sprites["window"]
text = _INTL("Evoluciones: {1}",evos)
if evos > 0
text << " - "
text << _INTL("Puntuación: {1}",(2**evos).floor)
end
win.text = text
end
def refresh_undos
for i in 0..@tables_history.length
s = @sprites["celebi#{i}"]
next if !s
s.visible = i < undos_left
end
end
def print
a = []
for j in 0...4
ret = ""
row = []
for i in 0...4
t = @table[i,j]
row.push(t && t!=0 ? (2**(t-1)).to_s : "*")
end
ret << row.join(" ")
#ret << "\n"
a.push(ret)
end
p *a
end
end
class Poke2048_Pokemon < IconSprite
attr_reader :pokemon
def initialize(viewport=nil,box=true)
super(viewport)
setBitmap("Graphics/Pictures/poke2048") if box
self.z = 100
@pokemon = PokemonSpeciesIconSprite.new(0,viewport)
#self.poke = poke
@pokemon.z = 101
self.visible = @pokemon.visible = false
@animation = nil
@animframe = 0
end
def poke=(species)
if species && species != 0 && (species.is_a?(Integer) || hasConst?(PBSpecies,species))
species = getID(PBSpecies,species)
@pokemon.species = species
self.visible = true
else
self.visible = false
end
end
def visible=(v)
super
@pokemon.visible = !!v
end
def x=(v)
super
@pokemon.x = v
end
def y=(v)
super
@pokemon.y = v
end
def zoom=(v)
self.zoom_x = v
self.zoom_y = v
@pokemon.zoom_x = v
@pokemon.zoom_y = v
end
def zoom
return zoom_x
end
def color=(c)
super
@pokemon.color = c.clone
end
def update
if @animation
frames = @animation[:frames]
sprites.each { |s| s.x += @animation[:x]/frames } if @animation[:x]
sprites.each { |s| s.x += @animation[:y]/frames } if @animation[:y]
@animframe += 1
if @animframe >= frames
@animframe = 0
@animation = nil
end
end
super
@pokemon.update
end
def sprites
return [self,@pokemon]
end
end
class Table
def to_a
ret = []
for i in 0...xsize
if ysize && ysize > 1
for j in 0...ysize
if zsize && zsize > 1
for k in 0...zsize
ret.push(self[i,j,k])
end
else
ret.push(self[i,j])
end
end
else
ret.push(self[i])
end
end
return ret
end
def all?(&block)
to_a.all?(&block)
end
def any?(&block)
to_a.any?(&block)
end
# Returns nil if indexes are not between 0 and x,y,z sizes
def atStrict(x,y=nil,z=nil)
return nil if [x,y,z].compact.any? { |e| e<0 }
return self[x,y,z] if y && z
return self[x,y] if y
return self[x]
end
end
class Array
def any?(&block)
return map(&block).include?(true)
end unless method_defined?(:any?)
def all?(&block)
return !map(&block).include?(false)
end unless method_defined?(:all?)
def filter!(&block)
self.delete_if { |it| next !yield(it) }
self
end unless method_defined?(:filter!)
def filter(&block)
ret = dup
ret.filter!(&block)
return ret
end unless method_defined?(:filter)
alias intersect filter
def compactSet!
return self if length <= 1
indexes = []
for i in 1...length
indexes.push(i) if self[0...i].include?(self[i])
end
counter = 0
for i in 0...indexes.length
self.delete_at(indexes[i]-counter)
counter += 1
end
return self
end
def compactSet
return dup.compactSet!
end
def find(&block)
for i in self
if yield(i)
return i
end
end
return nil
end unless method_defined?(:find)
def subarray?(ary)
return ary.all? { |o| self.include?(o) }
end
# If param is a Array, return wether it's a subarray of self
# else return wether param is in Array
def ===(param)
if param.is_a?(Array)
return self.subarray?(param)
else
return self.include?(param)
end
end
def count(item)
return filter { |it| item == it }.length
end
alias_method "cartesian_prod", "*"
def *(param)
if param.is_a?(Array) # => Array of pairs
ret = []
for i in self
for j in param
ret.push([i,j])
end
end
return ret
else
return cartesian_prod(param)
end
end
def **(int)
return [] if int < 0
return [nil] if int == 0
ret = dup
(int-1).times do |i|
ret*=ret
end
return ret
end
def to_h
ret = nil
if length == 2
ret = {}
for i in 0...self[0].length
key = self[0][i]
value = self[1][i]
ret[key] = value
end
else
ret = {}
for i in self
ret[i[0]] = i[1]
end
end if all? { |a| a.is_a?(Array) }
return ret
end #unless method_defined? :to_h
end
class Hash
def compact!
self.delete_if { |k,value|
value === nil
}
end unless method_defined?(:compact!)
def compact
ret = self.clone
ret.compact!
return ret
end unless method_defined?(:compact)
end
Advertencia: Para "ganar" el juego se necesita llegar a 11 evoluciones, mientras que Eevee tiene 8. Por eso he añadido tres nuevas (Stoneon, Fliyeon, Rhyeon). Para que funcione, debes añadirlas a tu lista de Pokémon o cambiarlas por otros Pokémon.
Última edición: