« Julio 2004 | Inicio | Septiembre 2004 »

Agosto 29, 2004

El patrÛn State aplicado al desarrollo de juegos ( IV y final )

Por fin ( todo llega ) un ejemplo de cÛmo puede desarrollar un juego a partir de una m·quina de estados.

La descripciÛn del juego es la siguiente. Van apareciendo gotas de agua en pantalla, en posiciones aleatorias. Durante el tiempo del que disponemos, tenemos que evitar que el n˙mero de gotas en pantalla sobrepase un umbral determinado. Para eliminar una gota de pantalla, basta con hacer click sobre ella. Una vez terminado el tiempo, se nos ofrece la opciÛn de volver a jugar, o de terminar el juego. Si volvemos a jugar, el n˙mero m·ximo de gotas que puede haber en pantalla disminuye. Se va repitiendo este patrÛn hasta que el jugador decida abandonar el juego, o hasta que se sobrepase el umbral m·ximo de gotas en pantalla, momento en que el juego termina, con derrota.

AquÌ puede verse el diagrama de estados correspondiente.

En nuestro ejemplo, hemos construido el juego en tres capas distintas. No es exactamente un MVC, aunque es algo parecido. Tendremos una clase DropsController que har· las funciones de controllador ( instanciar el modelo del juego, y hacer de conexiÛn entre la capa de presentaciÛn y dicho modelo ), DropsWorld, que es el modelo propiamente dicho, y la clase que tiene agregada la m·quina de estados del juego. Finalmente, tendremos una vista ( que en este caso es muy ligera, ya que consiste solamente en un ìbocadilloî de informaciÛn y un contador de tiempo ). Por lo tanto, el mundo no tiene conocimiento de la existencia de la vista, ni la vista de la existencia del mundo. No es una implementaciÛn estricta de ninguno de los patrones conocidos, pero es con la que m·s cÛmodo trabajo. Por lo tanto, es la utilizada.

El proceso de inicializaciÛn del juego es el siguiente: Al cargar el swf, se instancia el controlador, que a su vez instancia el mundo, registra los listeners al mismo, y manda arrancar su m·quina de estados. Para que el mundo pueda emitir eventos hacemos que extienda de la clase EventSource ( en el package net.designnation.events ). Dicha clase no es m·s que una parte de nuestra implmentaciÛn del patrÛn observer para poder emitir y registrarnos a eventos. De esta forma, los eventos emitidos por el mundo son escuchados por el controlador. El controlador tambiÈn crea un clip vacÌo, cuyo onEnterFrame servir· de generador de pulsos para las m·quinas de estados del juego

Una vez instanciado el mundo, se arranca su m·quina de estados:

public function initWorld( param: Object ) { this.stageMC = param.baseline; this.initBehaviour( ); var theClass: DropsWorld = this; this.base_MC.onEnterFrame = function( ) { theClass.doProcess( ); } this.mySMachine.startMachine( ); } private function doProcess( ) { this.BEngineVal.doProcess( ); }

Hemos delegado la ejecuciÛn del ciclo de la m·quina de estados en el el onEnterFrame del clip base_MC.

La m·quina de estados la definimos en el mÈtodo initBehaviour( )

private function initBehaviour( ) { var initGame: State= new State( "initGame", new CallbackDecl( this, "initGameAction" ) ); var startGame : State= new State( "startGame", new CallbackDecl( this, "startGameAction" ) ); var createDrop : State= new State( "createDrop", new CallbackDecl( this, "createDropAction" ) ); var overDrops : State = new State( "overDrops", new CallbackDecl( this, "overDropsAction" ) ); var endOfTime : State= new State( "endOfTime", new CallbackDecl( this, "endOfTimeAction" ) ); var defeat : State= new State( "defeat", new CallbackDecl( this, "defeatAction" ) ); var victory : State= new State( "victory", new CallbackDecl( this, "victoryAction" ) ); var endOfGame : State= new State( "endOfGame", new CallbackDecl( this, "endOfGameAction" ) ); new Transition( "initGameToStartGame", initGame, startGame, new CallbackDecl( this, "initGameToStartGameEval" ) ); //---------------------------------------------------------- new Transition( "startGameToCreateDrop", startGame, createDrop, new CallbackDecl( this, "startGameToCreateDropEval" ) ); //---------------------------------------------------------- new Transition( "createDropToEndOfTime", createDrop, endOfTime, new CallbackDecl( this, "createDropToEndOfTimeEval" ) ); new Transition( "createDropToOverDrops", createDrop, overDrops, new CallbackDecl( this, "createBubbleToOverDropsEval" ) ); new Transition( "createDropToSelf", createDrop, createDrop, new CallbackDecl( this, "createDropToSelfEval" ) ); //---------------------------------------------------------- new Transition( "overDropsToDefeat", overDrops, defeat, new CallbackDecl( this, "overDropsToDefeatEval" ) ); //----------------------------------------------------------- new Transition( "endOfTimeToVictory", endOfTime, victory, new CallbackDecl( this, "endOfTimeToVictoryEval" ) ); new Transition( "endOfTimeToStartGame", endOfTime, startGame, new CallbackDecl( this, "endOfTimeToStartGameEval" ) ); //------------------------------------------------------------- new Transition( "defeatToEndOfGame", defeat, endOfGame, new CallbackDecl( this, "defeatToEndOfGameEval" ) ); //------------------------------------------------------------- new Transition( "victoryToEndOfGame", victory, endOfGame, new CallbackDecl( this, "victoryToEndOfGameEval" ) ); this.mySMachine.resetToInit( initGame ); }

Y una vez instanciados tanto los estados como las transiciones, debemos implementar los callbacks que llevan asociados.

La clase que se utiliza para presentar las gotas es un controlador bastante ligero. TambiÈn extiende a EventSource, por lo que ser· capaz de emitir un evento cuando se haga click sobre el clip que lleva agregado. Seguro que este punto puede dar lugar a discusiÛn, pero una gota es una gota, no un MovieClip, por lo tanto he optado por que la clase Drop, dada su funcionalidad, tenga un clip con el gr·fico de la gota agregado, y no sea en sÌ misma una subclase de MovieClip.

El cÛdigo en general se explica por sÌ solo, por lo que una lectura atenta del mismo puede ser suficiente para comprender el funcionamiento del mismo.

TambiÈn quisiera resaltar que Èsta no deberÌa considerarse como una implementaciÛn definitiva. Gran parte del cÛdigo de DropsWorld es com˙n a todos los juegos que se desarrollen de esta forma, por lo que deberÌa subclasificarse para crear un mundo base que implementara las operaciones b·sicas de la m·quina de estados ( arranque, parada, inicializaciÛn, etc ). Por lo tanto, el cÛdigo presentado puede ( y deberÌa ) mejorarse considerablemente. Igualmente, el juego en sÌ requiere de un poco m·s de trabajo ( no hay feedback sobre cu·l es el n˙mero m·ximo de gotas que puede haber en pantalla, sobre si estamos lejos o cerca de ese umbral, etc. ). Adem·s., dada la forma en la que se registran los listeners, antes de destruir las gotas deberÌan de-registrase los listeners que tengan asociados, para evitar referencias circulares.

A˙n asÌ, tambiÈn quisiera resaltar que el tiempo del desarrollo del juego ( dejando aparte el framework base, por su puesto ), no ha llegado a dos horas. Y el resultado final es Èste:

Quisiera tambiÈn dejar constancia de mi agradecimiento a Celia Carracedo por los gr·ficos del juego.

El cÛdigo fuente del juego puede descargase aquÌ. No olvides definir el classpath apropiado para compilarlo. Los packages son:

net.designnation.behaviours
net.designnation.data
net.designnation.events
net.designnation.physics
net.designnation.PoppingDrops ( game classpath )

Agosto 21, 2004

macromedia.com para dispositivos mÛviles

Es probable que sea el ˙ltimo en enterarme, pero me acabo de dar cuenta de que toda la web de macromedia es navegable desde el pocketpc.

Yo ya me he creado un canal de avantgo para poder leer offline el Developer Center. ;)

Un trabajo impresionante. Enhorabuena!

Agosto 20, 2004

Interesante aplicaciÛn para pocketpc

Mobilympics es una aplicaciÛn para pocket pc realizada por el equipo de la web portuguesa pc de bolso.

Con esta aplicaciÛn se pueden seguir el calendario y resultados ( ya que se puede sincronizar directamente con los datos de la organizaciÛn de los juegos ) de siete deportes de equipo.

El programa es "Ad-ware", es decir que al salir del mismo nos enseÒan un anuncio de los sponsores del proyecto. Nadie es perfecto.

Agosto 17, 2004

Lo que hago en el trabajo ( habitualmente )

Bueno, ø quÈ hace un programador habitualmente en el trabajo? pues... programar. Ahora bien, øquÈ programo habitualmente?

Bueno, pues desde que estoy en esta empresa, he programado varias webs ( PHP, MySQL, CSS, ActionScript ), varias aplicaciones con Flash Communication Server, varias aplicaciones con AS para webs de terceros ( o en subcontratas ), pero habitualmente, lo que hacemos en esta empresa son cdroms multimedia ( juegos ) educativos, para diferentes gobiernos autonÛmicos que se cargan en ordenadores que van en aulas mÛviles.

Trabajamos habitualmente con una empresa de autobuses que tiene una secciÛn dedicada a "aulas mÛviles", esto es, cogen un autob˙s, lo vacÌan por dentro, y crean un aula, con paneles expositores, sillas, mesas, biblioteca, ordenadores, etc... Suelen ser autobuses grandes, que cuando aparcan sacan de los costados dos enormes cajas, convirtiÈndose en autobuses m·s grandes todavÌa.
Entonces, estos autobuses ( que est·n pintados y decorados muy chulamente y en funciÛn de cual sea el multimedia en cuestiÛn ) recorren las comunidades, y cada dÌa o cada semana est·n en una ciudad, o pueblo. Y ese dÌa, los niÒos en lugar de tener clase de .... van al autob˙s a jugar el juego educativo.

Estos juegos tienen mucha, mucha pelÌcula ( animaciÛn ). De hecho, la mayorÌa de los que trabajan aquÌ son animadores, que han participado en diferentes series de dibujos para televisiÛn ( incluida aquella de fabulosos dibujos de Batman de la warner, por aquÌ hay alg˙n storyboard ).

Entonces, claro, como la animaciÛn y la programaciÛn son dos mundos muy diferentes, mi trabajo consiste en coordinar, quÈ pelÌculas se hacen ( si esta parte se hace en una sola o en dos o en tres ), cÛmo se hacen, quÈ audios van embebidos en la pelÌcula y cuales se cargan de mp3 externos, quÈ cosas tienen que ser movieclips ( para meterles la programaciÛn ) etc.., cÛmo me tienen que pasar las cosas ( tener en cuenta que por ejemplo, si se hace para el gobierno vasco, o la xunta de galicia , los juegos son biling¸es ), adem·s si el juego tiene Èxito, luego suele ser comprado por otros gobiernos o diputaciones, incluso del extranjero, entonces, hay que hacerlo de modo que traducirlo sea lo m·s f·cil posible ( y barato ). Un minuto de animaciÛn cuesta mucho tiempo y dinero, por tanto, hay que en la medida de lo posible cargar todos los textos de todas las pelÌculas de archivos xml externos, todos los audios de conversaciones de archivos externos etc...
En ocasiones no es posible y en caso de traducirlo hay que rehacer la animaciÛn entera, eso depende de cÛmo est· planteado el juego. En el que estamos haciendo ahora, por ejemplo, los personajes hablan en primer plano, por lo que hay que sincronizar los movimientos de la boca con los audios, y si el personaje dice una "o" tiene que poner cara de estar diciendo una "o". AsÌ pues, en este caso, cuando se traduzca al gallego, pues ....rehacer la animaciÛn del personaje entera. En el cd que estamos haciendo ahora, hay m·s de 30minutos de animaciones, y el juego consiste en una aventura gr·fica en la que manejas tres personajes diferentes y tienes varios escenarios, entonces en funciÛn del personaje que tengas elegido y del escenario donde estÈs, y en funciÛn de si es la primera vez que el personaje en cuestiÛn entra en ese escenario, o si ya han pasado todos por allÌ etc.. pues en funciÛn de todos esos par·metros ( y unos cuantos m·s ) muestras unas pelÌculas u otras. Por supuesto, todas las pelÌculas son ( m·s o menos ) interactivas y requieren de la actuaciÛn del usuario.
El juego est· programado completamente usando ProgramaciÛn orientada a objetos, lo que me est· permitiendo hacerle muy r·pido y con posibilidad de realizar f·cilmente los cambios que "sugiere" el cliente cuando ve las pruebas.
Es un trabajo intersante, antes de llegar aquÌ habÌa trabajado con diseÒadores, pero no con animadores. Es a veces complicado, pero al final el resultado es muy elegante.

Agosto 14, 2004

design-nation. mobile

Dada la gran cantidad de dispositivos mÛbiles que pueden utilizarse actualmente para navegar la web ( telÈfonos, pdas, por ejemplo ) hemos pensado que ha llegado el momento de hacer este blog accesible a dichos dispositivos.

Por eso hemos implementado, como versiÛn 0.1, un script para poder acceder a los contenidos del blog desde dispositivos mÛviles. El script devuelve los diez ˙ltimos posts, y puede utilizarse para crear un canal avantgo, por ejemplo, de manera que se puede descargar el blog para luego leerlo offline.

Por ahora, el problema est· en los posts con cÛdigo. Al utilizar un plugin para dar formato al cÛdigo en la presentaciÛn, que a˙n no hemos integrado en la versiÛn mÛvil, el cÛdigo se ve de forma, digamos, poco legible. Pero todo se andar·.

Para ver la versiÛn mobile: click aquÌ

Agosto 13, 2004

Servidor de Sockets para AS con PHP5

Gracias a mi hermano CÈsar he descubierto este servidor de sockets,en freshmeat. Su nombre Cyber Socket Server, y seg˙n pone funciona en hosts con PHP5. Hay que bajarlo y estudiarlo un poco a ver que tal.
Direcciones:
Proyecto en freshmeat
CSS ( Cyber Socket Server )
freshmeat

Seg˙n la descripciÛn del proyecto, es similar a Flash Communication Server, yo como soy incrÈdulo dudo que transmita video ( el protocolo rtmp es de macromedia y hasta donde yo se, ni siquiera Unity que es el servidor de sockets m·s conocido tiene para emisiÛn de video ) pero aunque "sÛlo" sean datos compartidos en tiempo real, le voy a echar un vistazo con calma.
Un saludo.

Agosto 12, 2004

Sound.onSoundComplete: øBug o feature?

No lo tengo muy claro. ø Es un bug del flash player o realmente es el comportamiento esperable?

Veamos. El problema tiene cierta relaciÛn con la serie de post anteriores ( e inconclusa, lo sÈ, pero llegar· a su final en breve ) sobre las m·quinas de estados.

El caso es que tengo un juego en el que debe realizarse una transiciÛn a un nuevo estado cuando un sonido termine de "ejecutarse", es decir, cuando se lance el evento onSoundComplete del correspondiente objeto Sound. El caso es que siempre ha funcionado correctamente, pero hoy, al hacer una pasada de prueba por el juego, me he encontrado con que ya no funcionaba.

øCÛmo? Pero si esto siempre ha funcionado!!. DespuÈs de un par de horas de debugeo, se me ha encendido la bombilla. Resulta que he formateado mi m·quina de desarrollo anteayer, y al instalar el nuevo sistema, no me ha reconocido ni la tarjeta de sonido, ni la tarjeta gr·fica. Vamos, que ahora mismo, si miro el panel de control de la m·quina, no hay ning˙n dispositivo de audio.

Bueno, pues al parecer, eso hace que no se lance nunca el evento onSoundComplete.

En todo caso, sea un bug o una feature, es algo a tener en cuenta ( al menos para mÌ ).

Agosto 10, 2004

Hasta el gorro de spam, oiga!!

Pues eso, que despuÈs de borrar casi unos 350 comentarios un pelÌn escabrosos durante la ˙ltima semana, ha llegado el momento de tomar decisiones dr·sticas.

Desde la salida de Movable Type 3.0, hemos estado d·ndole vueltas a la idea de pasarnos a WordPress o a b2Evolution, pero cuando comenzamos el blog cometimos el error ( entonces no parecÌa tal ) de dejar las urls de los posts por defecto ( es decir, numÈricas en vez de basadas en el tÌtulo del post ). Bien, ahora eso es un problema importante, porque no tenemos acceso al .htaccess del servidor, por lo que el cambio a un sistema de urls diferentes supondrÌa que los motores de b˙squeda deberÌan volver a indexar el sitio, quien tuviera alg˙n bookmark lo perderÌa, etc.

Por lo tanto, sin mucho convencimiento, nos hemos actualizado a MT3.01. En principio parece que el cambio no ha resultado demasiado doloroso, al menos para nosotros. Pero puede que sÌ lo sea un poco m·s para vosotros, ya que a partir de ahora los comentarios van a ser moderados, es decir, que no se publicar·n inmediatamente, sino que requerir·n de nuestra aprobaciÛn.

Y eso es algo que a nosotros mismos no nos gusta nada ( suena demasiado parecido a "censura" ). De todas formas, vamos a implementar los comentarios para los que tengan typeKey, y a˙n tenemos que ver cÛmo funciona el tema del registro de "comentadores".

En fin, que esperamos que sepais entender el motivo de este cambio.

Agosto 08, 2004

Y se acabaron las vacaciones...

Dos semanas no duran nada, se mire como se mire. Pero bueno, aquÌ est· un pequeÒo repaso a estas dos semanas con algunas fotografÌas.

Vitoria - Gasteiz, en la plaza de la Virgen Blanca: Uno es CÈsar y el otro es Javier. Por cierto, Vitoria es una ciudad preciosa.

vitoria.jpg


M·s Vitoria. ExhibiciÛn de unos aizkolaris

aizkolaris.jpg

Luanco ( Asturias ). Un hotelito precioso.

luanco1.jpg

Cabo de PeÒas ( Asturias ). El Mar Cant·brico.

luanco2.jpg


Vuelta a Madrid. Todo Chichos!!!!

madrid1.jpg

Y fiestas de San Cayetano. Que sÌ!!

madrid2.jpg

QuÈ dura puede llegar a ser la vuelta...