Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Subtema: Juegos Flash (5ªParte) Programación: Advertencia

Iniciado por mi-go, 03 de Noviembre de 2009, 05:53:32 PM

« anterior - próximo »

mi-go

Llevo mucho tiempo queriendo actualizar el documento que hice para adevertir de ciertas cosas, ya lo he hecho añadiendo un apartado al princpio.


   Advertencia: Cómo hacer y cómo no hacer juegos en flash

Este aparatado ha sido añadido en la 2ª edición de este documento para advertir sobre cómo hacer y cómo no hacer un juego flash, ya que este documento comete los mismos fallos de programación que muchos tutoriales que hay en Internet sobre desarrollo de juegos en flash.

He decidido no eliminar este documento a pesar de que en él se explique una forma no correcta de hacer un juego en flash, porque sí que puede resultar una forma más fácil para los que estén aprendiendo programación en general, como primer paso fácil y motivador a seguir aprendiendo. Pero aquellos programadotes experimentados deberían seguir con atención las siguientes razones de porque no es correcto este manual y cómo se debería hacer realmente un juego.

Existe un peligro grande de aprender a programar videojuegos empezando por Flash/Actionscript por varias razones:
-   Es una API claramente para software "orientado a eventos" del usuario, como una página web o software de gestión.
-   El 99% de los libros y manuales que hay sobre ActionScript usa la librería de igual forma, pensando en software orientado a eventos del usuario.

La forma de programar orientado a eventos se centra mucho en esperar las acciones del usuario y a partir de ahí lanzar cierta lógica de ejecución, sin importar demasiado que exista una única "línea lógica de ejecución" ya que muchas de las acciones son totalmente independientes y no influyen entre ellas.

Por esta razón en muchas webs, programas o juegos hechos en flash se observará un uso excesivo de "event listeners" que ejecutan código generando varias líneas lógicas de ejecución haciendo imposible cierto tipo de control sobre el juego.

Para hacer bien un videojuego en flash hay que tener siempre en mente el modo clásico de un motor de un videojuego con un "main game loop". Muchos libros y artículos en Internet tratan este tema, por ejemplo: http://en.wikipedia.org/wiki/Game_programming#The_game_loop
Y evitar, en la medida de lo posible, el uso de los event listeneters.

Además, recomiendo la lectura de estos dos artículos para entender mejor la forma en la que funciona flash:
El sistema de renderizado de Flash Player
http://llops.com/blog/2008/05/24/el-sistema-de-renderizado-de-flash-player/
EnterFrame vs Timer (I)
http://llops.com/blog/2008/07/27/enterframe-vs-timer-i/


Trabajando de esta manera tendremos:
-   Control completo de la lógica del juego en todo momento.
-   Facilidad para cambiar la velocidad del juego en cualquier momento o hacer pausa.
-   Control para asegurarnos de que el juego se ejecutará siempre a la misma velocidad en todos los pcs.

Teniendo en cuenta el modelo clásico de cómo hacer un videojuego, Flash sigue siendo una herramienta muy potente porque posee una API muy completa, fácil y útil para videojuegos y podemos exportar para gran cantidad de plataformas.
Web personal: www.javiermairena.net
The Game Kitchen: www.thegamekitchen.com
AccessAble Games: www.accessablegames.com
Blog Videojuegos Accesibles: www.videojuegosaccesibles.es

StraT

Hola,

Me siento un poco resucitador de temas muertos, pero es que tengo una duda y viene a cuento de este post (y no de otro).

Dices que deberíamos programar juegos en Flash con el game loop habitual, a lo cual yo pregunto, ¿conoces alguna guía tutorial sobre cómo programarlos de esa manera? He buscado y sólo he visto los event listeners habituales...

Un saludo y gracias.
quot;Solo hay dos cosas infinitas, el universo y la estupidez humana, aunque de lo primero no estoy muy seguro\\\" Einstein

josepzin

No había visto este tema, la verdad es que la lógica de Flash tiene su "cosa"... seguro que genera muchos vicios...

mi-go


No te hace falta un manual en concreto para aprender a programar juegos con un game loop y mantener la lógica correcta. Mira cualquier manual sobre programación de juegos que lo haga así (que deberían ser todos  xD ) y simplemente programa así en flash, ovlidándote de que existen los listener.

Sólo deberías usar los listerners para saber cuando se pulsa una tecla o botón del ratón, pero no hacer que directamente lancen código de lógica, simplemente que anoten un estado de "tecla A pulsada" para que en el siguiente ciclo del game loop se procese.

El tema es no lanzar lógica en listeners que puedan activarse en cualquier momento, porque perdimos el hilo del game loop, pudiendo tener graves problemas con la lógica del juego.
Web personal: www.javiermairena.net
The Game Kitchen: www.thegamekitchen.com
AccessAble Games: www.accessablegames.com
Blog Videojuegos Accesibles: www.videojuegosaccesibles.es

josepzin

¿Y que piensas de los onEnterFrame? Son tan cómodos... :D

mi-go


Bueno, el onEnterFrame es otro de los listener que también hay que usar, por lo menos yo también uso, pero sólo para poner al inicio del juego una llamada para que ejecute el game loop onEnterFrame, y no quitarlo ni cambiarlo durante todo el juego.

this.addEventListener(Event.ENTER_FRAME,this.gameLoop);

Web personal: www.javiermairena.net
The Game Kitchen: www.thegamekitchen.com
AccessAble Games: www.accessablegames.com
Blog Videojuegos Accesibles: www.videojuegosaccesibles.es

TiRSO

Cita de: mi-go en 08 de Julio de 2010, 10:49:48 AM

Bueno, el onEnterFrame es otro de los listener que también hay que usar, por lo menos yo también uso, pero sólo para poner al inicio del juego una llamada para que ejecute el game loop onEnterFrame, y no quitarlo ni cambiarlo durante todo el juego.

this.addEventListener(Event.ENTER_FRAME,this.gameLoop);



¿No sería más correcto usar un Timer en lugar del evento ENTER_FRAME? Algo así:
Código (actionscript) [Seleccionar]

var ticker = new Timer(33); // 30 fps (1000 ms/30 frames)
ticker.addEventListener(TimerEvent.TIMER, gameLoop);
ticker.start();


De esta forma se evitan problemas si el ordenador no tira bien por el juego.


Además, yo no sería tan radical en cuanto a evitar el uso de eventos. En un juego ocurren muchos eventos, y se puede aprovechar la facilidad que proporciona Flash para manejarlos. Una buena opción es crear tipos personalizados de eventos para "avisar" al resto de objetos cuando ocurre algo. Por ejemplo, se puede usar para lanzar eventos con unas coordenadas asociadas (para cuando muere un personaje, por ejemplo): http://sourcecookbook.com/es/recipes/4/clase-positioned-event-para-lanzar-eventos-con-posicion.

mi-go

Bueno, sobre usar el enter frame o un timer hay mil discusiones en internet  xD
Yo estuve leyendo mucho (por ejemplo: http://llops.com/blog/2008/07/27/enterframe-vs-timer-i/) y al final llegué a la conclusión de que era mejor on enter frame

De todas formas cuando la máquina esté saturada tu timer también puede que no se ejecute las veces que debe.
Lo importante, sobre todo, es saber el tiempo que pasa entre un ciclo y otro del gameloop y actualizar posiciones y animaciones en consecuencia.

Crear eventos propios puede estar bien, pero yo lo usaría sólo para activar ciertas variables banderas o cosas así de sencillas, nunca para lanzar lógica de juego. En la lógica de un juego siempre tienes que seguir un mismo orden para que cada game loop termine bien y no pasen cosas raras.

Por ejemplo, si en tu ciclo del gameloop mueves los objetos en este orden: personaje, enemigos, nubes...   nunca podría, por ejemplo, un evento de la nube (un rayo) hacer mover al personaje para atrás. Mejor lanzar el rayo sin listener, al final de ciclo comprobar colisiones y en el siguiente ciclo ya se moverá el personaje (cuando le toque) porque ya está chocando con el rayo. Así mantienes una lógica de juego que no se puede romper, lanzando lógica de juego en listeners puede que la lies mucho.
Web personal: www.javiermairena.net
The Game Kitchen: www.thegamekitchen.com
AccessAble Games: www.accessablegames.com
Blog Videojuegos Accesibles: www.videojuegosaccesibles.es

mi-go


Además, otra cosa, no tiene sentido hacer más iteraciones del gameloop de las que puedas pintar en pantalla  xD

Todo esto es algo un poco raro que no sucede en otras tecnologías de videojuegos y es porque en flash no se puede controlar cuando se pintas las cosas. Normalmente en otras tecnologías se pasa la logica del gameloop y después se pinta, se pinta una vez por cada vez que se hace un ciclo de gameloop; en flash no puedes controlar cuando se hace y cuando no.

En flash, si tu máquina está saturada y baja a 18 imágenes por segundo, aunque tu timer se ejecute 30 veces por segundo (cosa que es posible que tampoco pase ya que está saturada) ¿de que te sirve si no lo puedes pintar?  xD   de hecho si se estuviera ejecutando el timer 30 veces y pintando 18 estarías intentando hacer más de lo que puede la máquina con lo que podrías estar haciendo se se saturara más y no subiera nunca de las 18 imágenes por segundo.

Web personal: www.javiermairena.net
The Game Kitchen: www.thegamekitchen.com
AccessAble Games: www.accessablegames.com
Blog Videojuegos Accesibles: www.videojuegosaccesibles.es

TiRSO

¿Y si el juego depende del tiempo? Si tienes 30 segundos para hacer algo, no interesa que todo vaya a la mitad de velocidad. Es mejor que vaya todo al ritmo que tiene que ir, aunque vaya a trompicones. Dicho esto, es verdad que en flash no debe haber forma de hacer que se salte frames y, si el juego va lento, estás jodido.

mi-go

Si hay algo en el juego que dependa del tiempo, por ejemplo una plataforma que desaparece a los 30 segundos, deberías controlarlo con un timer, pero con un timer propio mirando el tiempo real que ha pasado desde que se inició. No vayas a usar un timer de flash poniéndolo que se ejecute 1 vez por segundo y a la 30 lanzas código de logica... mejor cuando en tu gameloop te toque mover los elementos "plataforma" comprueba si ya han pasado 30 segundos desde que apareció, comparando tiempos (horas).

Sobre que en flash "no puedes saltarte frames" aclarar que yo me refiero a que no puedes controlar cuando se pinta, por lo que sí, los frames de la película principal no los puedes controlar, pero los movimientos de los personajes sí los puedes adaptar al tiempo real que pasa entre cada ciclo del game loop y los frames de las animaciones de esos personajes también, saltándote frames de su animación si hace falta.
Web personal: www.javiermairena.net
The Game Kitchen: www.thegamekitchen.com
AccessAble Games: www.accessablegames.com
Blog Videojuegos Accesibles: www.videojuegosaccesibles.es

StraT

A ver, aclarar que sé lo que es un game loop, estoy habituado a usarlo en otras tecnologías. La cuestión es que Flash es realmente diferente en el aspecto del pintado. Compré el otro día el libro "Real-World Flash Game Development (How to Follow Best Practices AND Keep Your Sanity) y él aboga por hacer algo así:

addEventListener(Event.ON_ENTER_FRAME, gameLoop);

function gameLoop(Event e)
{
   moverObjetos();
   moverFondo();
   ...
}


¿Qué opináis de esta manera de hacerlo?

Saludos
quot;Solo hay dos cosas infinitas, el universo y la estupidez humana, aunque de lo primero no estoy muy seguro\\\" Einstein

mi-go

pues así es como lo hago yo, jeje. Y por lo que he dicho antes creo que es la mejor manera.
Web personal: www.javiermairena.net
The Game Kitchen: www.thegamekitchen.com
AccessAble Games: www.accessablegames.com
Blog Videojuegos Accesibles: www.videojuegosaccesibles.es






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.