Professional Documents
Culture Documents
tomado de http://www.BleachEatingFreaks.com/flash/games/memory/
(traducido por dante becerra lagos, softenglish@gmail.com)
La mejor forma para que nosotros podemos hacer un juego de memoria es establecer el
método aquí. En la vida real ¿Cómo ejecutaríamos un juego de memoria? Pensaremos en
cada carta como una carta de naipe. Queremos modelar nuestras imágenes y hacerlo fácil para
añadir más en otro momento, ¿Correcto? Por lo tanto digamos que las cartas constituyen un
mazo. Esto es lo que recomiendo para empezar el juego.
1) Barajar el mazo.
2) Tomar X cartas del mazo (uno real tendría 52, y resultaría en un juego muy largo. Por
esta razón solo usaremos X cantidad de cartas del total. Esto nos facilitará hacer
niveles en el futuro, aumentando X en forma dinámica)
3) Fotocopiar las cartas extraídas de modo que tengamos un duplicado perfecto) (2 de
cada carta)
4) Baraja los duplicados ( no podemos tenerlos en el mismo orden que nuestro primer
mazo)
5) Por último, reparte las cartas de ambos mazos al mismo tiempo.
¡El Monstruo Lógico! La lógica nos dice que idealmente tu querrías entregarlas al azar porque
de otra forma alguien se puede dar cuenta que si se entregaran de los mazos al mismo tiempo,
no hay forma que N pueda parear N+2K, de esta forma reduciendo las posibilidades a la
MITAD! Pero nos gustaría pensar que nadie se dará cuenta sin saber como fue programado.
No es como si ellos vieran verdaderamente entregar las cartas desde los dos mazos.
En consecuencia ¿Suena como una forma razonable sacar las cartas y entregarlas? ¿Como
podemos hacerlo mas divertido?
Ahora cualquiera puede finalmente descubrir todas las cartas, pero es nuestro trabajo hacer
divertido el juego. En ese caso, registraremos el número de intentos y el tiempo que transcurre
durante el juego. Esto nos permitirá tener un sistema de puntaje, y entonces el juego se hace
mas competidito e interactivo.
Bien, ahora ¿Como podemos hacer todo esto en el computador? Bien usemos un arreglo para
representar el mazo. Tendremos N cantidad de imágenes, y queremos tomar X de ellas y
usarlas como cartas. Esencialmente cada valor en el arreglo será mostrado como su numero
mas 1, de esta forma el índice 0 (cero) del arreglo será la imagen 1, y así sucesivamente.
No te olvides cuando leas el código que “//” y /* algo aquí*/ son comentarios para los lectores,
no el computador. Podemos crear un mazo de cartas con una función createDeck(). Esta
función es muy simple.
/*
* Función createDeck -
* crea un arreglo que sirva como un modelo de cartas de distinto tipo
*/
function createDeck() {
// crea las cartas
startDeck = new Array();
// cada carta = su posicion de arreglo + 1
for (x=0;x<picCount;x++) {
startDeck[x] = x + 1;
}
return startDeck;
}
La función anterior crea el modelo de mazo antes mencionado. Simplemente necesita una
variable global llamada picCount la cual contendrá la cantidad de imágenes que tendremos en
total. Cuando tú añades una imagen, asegúrate de ajustar picCount en forma
correspondiente. Ahora que tenemos un mazo necesitamos una forma de barajarlo.
¿Como lo hacemos? Hemos establecido el mazo como un arreglo. Una opción es elegir dos
elementos en forma aleatoria e intercambiarlos. Pero entonces ¿Cuantas veces tenemos que
hacer esto antes de que estemos seguros de que el mazo esta apropiadamente barajado? Al
menos el doble del tamaño del mazo. ¿Correcto? Tengo una idea.
Tomamos una carta en forma aleatoria y la ponemos en una nueva pila. Aleatoreamente
tomamos una carta en forma seguida hasta que la nueva pila esté llena y la vieja haya
desaparecido. Nuestra nueva pila será un conjunto aleatorio de nuestro mazo original de
cartas.
El monstruo lógico! La lógica nos dice que sacar una carta de un mazo es fácil, la pila se cae
instantáneamente y la ranura faltante se borra, pero si tu tienes un mazo en el computador, de
5 billones de cartas y tu sacas la mitad, entonces 2.5 billones de cartas tienen que moverse
hacia abajo de una vez. En cada ocasión consumiendo mucho tiempo del computador.
El monstruo lógico tiene razón. Las listas son mas difíciles de manejar que en la vida real.
Cuando se saca una carta de un mazo, el mazo completo se queda ahí, y se le debe DECIR a
cada una de las otras cartas que se mueva hacia abajo. Esto esta compuesto por la dificultad
que hemos elegido usar un arreglo, y que ya hemos designado dos mazos completos al
espacio del computador. Se chuparía para mover 3, 4 ,5 o incluso X mazos de espacio solo
para clasificar 1 mazo.
Elegimos una carta del mazo, la copiamos en nuestro nuevo lugar. Si ya esta en el mazo
nuevo, la desechamos, si es nueva la dejamos. Finalmente, seleccionaremos aleatoreamente
todas las cartas y las copiamos en nuestro nuevo mazo. Cuando esto ha sido realizado,
desechamos el mazo antiguo y hemos barajado.
// copia el arreglo
scanData = new Array();
scanData = scanData.concat(deck);
Usamos la estructura de datos de pila la cual es muy común en computación. Flash tiene
funciones incorporadas para una pila, lo cual hace el proceso completo más rápido. En efecto,
cuando usas una función Flash MX en vez de una escrita a medida, la ejecución del programa
es usualmente más rápida. Esto tiene que ver con el nivel en que se ejecuta el código.
Actionscript se ejecuta como un script, en cambio las funciones innatas de Flash residen en
ejecutables y DLL’s.
Por lo tanto ahora podemos crear un mazo y barajarlo. ¿Y ahora como vamos a solucionar el
problema de manipular las cartas?
Bien, hagamos una función que manipule. Le decimos cuantas cartas manipular, y le daremos
un mazo vacío. La función manipuladora barajará el mazo, tomará P cartas de la parte superior,
las copiará y las barajará. Y luego las entregamos. Entregar las cartas será simplemente hacer
una copia de una carta, poner sus posiciones X e Y y ya que todas las cartas no son reales,
tenemos que decirle a la carta que imagen mostrar. Aquí esta nuestra función de manipulación
terminada.
/*
* Función manipulación (deal - toma las cartas y las entrega en la
* pantalla. De un número de imágenes único y uPic*2 cartas son
* entregadas en la pantalla.
*
* Parámetros:
* uPic = cantidad de imágenes únicas a manipular
* mazo de cartas desde donde manipularlas (todas las imágenes)
*/
function deal(uPic, cardDeck) {
moveY = 1;
moveX = 1;
// ir a la próxima hilera después de que rowBreak cartas
// son manipuladas
rowBreak = 8;
rowBreak es una variable que nos dice cuantas cartas por hileras (rows). Podemos modificar
esto para subdividir dinámicamente en filas a cualquier ritmo. La variable deck1 esta llena con
la versión barajada de mazo trasladado. Nosotros luego sacamos una porción de las cartas y
barajamos el resto. Esto se hace con la función slice. Básicamente cortamos la parte superior y
la volvemos a poner en el mazo, las otras caen al suelo.
deck1=deck1.slice(0,uPic);
el mazo2 (deck2) esta luego compuesto por una versión barajada del mazo1 y tenemos
nuestras cartas listas para empezar.
Nosotros creamos la carta, luego establecemos 3 cosas. Le decimos que posición X y posición
Y y que imagen mostrar.
-xpos esta controlada principalmente por el numero envolvente moveX, en la medida que las
cartas se incrementan hasta rowBreak.
-ypos esta controlada por moveY, el cual seguirá avanzando en cada rowBreak se hace mas
grande.
-curPicNum es la variable que controla que imagen la carta debe mostrar. Como puedes ver,
hemos hecho una carta movieClip que querrá saber cuales de sus imágenes picCount mostrar.
Sin establecer la detención de la carta movieClip en una imagen particular, simplemente
continuara moviéndose continuamente en círculos a través de las imágenes.
Ahora podemos hacer que nuestras cartas hagan lo que queramos, es hora de hacer los
movieClips y animaciones necesarias que harán el juego atractivo al ojo.
Primero haz un movieclip que será llamado "cardFront". Este consistirá en todas las imágenes
que serán los frentes de las cartas. También, necesitaremos un mc/graphic llamado "cardBack"
el cual será las partes traseras de las cartas que veremos.
CardFront:
Te sugiero que dimensiones todas las imágenes usando el ancho y alto de la carta. Luego
numerarlas y ponlas en un directorio espacial. Esto haría la importación más simple. Ahora crea
el movieclip apropiado e importa todas las imágenes de ese directorio. Cada imagen debe
importarse a su propio fotograma. La cantidad de fotogramas que tienes debería ser tu variable
picCount. Aquí puedes ver las mías.
La carta de juego: La verdadera carta que usaremos, en realidad pasara varias fases. Lo que
haremos, de modo que podamos nivelar nuestro código para que funcione en un nivel modular,
es que crearemos un movieclip llamado “card”, y haremos toda la animación ahí dentro. Luego
insertaremos el movieclip card dentro del movieclip de la carta de juego, de modo que
tengamos una capa exterior para escribir nuestro código.
El movieclip “carta” (card) debería tener varias animaciones. Deberías animar la parte trasera
de la carta dando se vuelta, y luego el frente abriéndose, como si la carta se hubiese dado
vuelta. También puedes animar la carta volviéndose a voltear, y animar como te gustaría que la
carta se fuese cuando la persona hace el par. Así se ve el mío.
Como puedes ver tengo tres capas. Una para las acciones y títulos de los fotogramas, una para
el frente de la carta y uno para la parte trasera. Aquí hay un análisis mayor de cómo particioné
este mivieclip.
Fotograma1: tiene la acción “stop()” y el nombre de “cardturn”. El stop esta ahí para hacer que
la carta se de vuelta cuando se le pida hacerlo.
Fotograma2-29: animación de las cartas dándose vuelta para mostrar el frente. Como en el
Fotograma2, tengo la acción
Este es para decirle a la raíz que esta carta se esta animando. Tenemos que hacer esto porque
solo debemos permitirle a alguien voltear 2 cartas a la vez. Tenemos que controlar cuantas
cartas están en juego cierto? De otra manera podríamos estar volteando varias cartas a la vez.
Fotograma30: Simplemente nombré el fotograma “holdDown” (mantener abajo) para mantener
la carta en esa posición.
Aquí, _root.card2Match es la carta que buscamos parear. Cuando sean las mismas, tenemos
lo que queremos. La razón por la cual es una condición carrera, como se establece
anteriormente en los comentarios, es porque cuando se voltea una carta, siempre se pareara
consigo misma, de modo que es importante que esta carta haga toda esta búsqueda antes que
la otra carta la alcance. Estamos seguros con la condición de carrera, porque el código se
evalúa sobre la base de fotograma por fotograma. Este paradigma de código no debería salir
de Actionscript , y no es un paso que los programas normales puedan saltarse.
Este código saca la carta del juego, tenemos que hacer esto ya que lo podríamos haber
saltado. Y también chequeamos si el juego terminó. Si es así saltamos al final, de lo contrario
nos quedamos donde estamos con la carta faltante. El mivieclip raíz continuará ejecutándose,
el stop solo afectará el movieclip que contiene, de esta forma solo afectando esta carta.
Este código también que inicialicemos la variable totalCardsNum, con el numero total de
cartas que tendremos.
Uy! Se ve como mucho.¿ Cierto? Pero es todo sentido común y simple. Tienes que enseñarle
al computador a hacer cosas que tu quieres que el haga, ese es el juego de la programación.
Ahora tenemos nuestro manipulador, y tenemos nuestra carta de juego. Todo lo que tenemos
que hacer es finalizar algo de código en la carta, y comenzar a tirarlas! Oh! y por su puesto,
hacer nuestras escenas de comienzo y fin.
Para las cartas, toma una instancia de la carta de juego (playingCard) y ponla en el escenario
principal. Asegúrate que sea lo suficientemente baja para estar fuera de la pantalla. Nombra la
instancia pCard. Pon el siguiente código.
on (release) {
// solo animar dos cartas en algún momento.
if ((_root.cardsInPlay < 2) && (this.theCard._currentframe <= 1))
{
// si esta es la primara carta guardar el numero de la imagen
//*** no usarse en paginas web ***
if (_root.cardsInPlay == 1) {
_root.card2Match = this.theCard.cardFace._currentframe;
}
// comenzar animacion
this.theCard.play();
// contra intento
_root.attemptCount++;
_root.gameAttempts = "ATTEMPTS:"
+ Math.round(_root.attemptCount / 2);
}
}
Este simple código le dice a la carta, de que cuando es soltada cheque 2 cosas:
Ahora, anima la carta con la directiva “ play” e incrementamos el conteo de los intentos.
Recuerda? El conteo de los intentos se va a utilizar para calcular el puntaje. Parece que las
carta están listas para girar. Escribamos nuestro código simple de manipulación.
// crear un mazo
fullDeck = new Array();
fullDeck = createDeck();
// Total de cartas unicas
totalUniqueCards = 16;
// numero total de cartas en juego
totalCardsNum = totalUniqueCards * 2;
// manipula las cartas+ los duplicados del mazo
deal(totalUniqueCards, fullDeck);
// esperar aqui ahora.
stop();
Suficientemente simple? Gracias a las funciones!!!! Ahora podemos jugar con al memoria,
establecer el numero de cartas a manipular, establecer las imágenes fácilmente y manipular las
cartas fácilmente. Este juego puede ser fácilmente amplificado para tener características mas
avanzadas.
Bien, lo que hice fue hacer un cronometro simple en el juego principal. Este consiste en un
mivieclip, con un texto dinámico dentro. Llame al texto “gameTime”
onClipEvent(load) {
staticPrefix = "TIMER: ";
startTime = getTimer();
staticSuffix = " seconds";
}
onClipEvent(enterFrame) {
curTime = getTimer();
elapsed = curTime - startTime;
_root.secondsElapsed = Math.floor(elapsed / 1000);
//trace(secondsElapsed);
this.gameTime = staticPrefix +
_root.secondsElapsed + staticSuffix;
}
Este es un código cronometro básico . En la carga del mivieclip, obtiene cuantos milisegundos
el juego ha estado funcionando con el getTimer(). Luego cada fotograma después de ese
(enterFrame), calcula el tiempo el tiempo transcurrido con curTime-startTime. Esto por su
puesto retorna milisegundos, lo que implica que tenemos que dividir por 1k para tener los
segundo normales. Este código establece _root.secondsElapsed para nosotros. De modo
que ahora podemos usar eso para calcular el puntaje he puesto dos textos dinámicos, uno
llamado summary y el otro finalScore.
También hago un chequeo rápido para asegurarme que alguien no hizo un clic derecho con el
mouse y eligió jugar, para saltarse el juego y obtener un puntaje perfecto. El código en el
fotograma es el siguiente:
// asegurarse que alguien no hizo trampa con el clic derecho del mouse
if (_root.totalCardsNum != 0) {
gotoAndPlay("beginning");
}
FELICITACIONES! Ahora tienes todas las piezas para hacer un juego de memoria. Puedes ver
la versión finalizada de este juego
en:http://www.BleachEatingFreaks.com/flash/games/memory/