Programación de Juegos 2D HaxeFlixel
-
Upload
maximiliano-illbele -
Category
Documents
-
view
215 -
download
26
description
Transcript of Programación de Juegos 2D HaxeFlixel
-
Curso de Videojuegos en 2D
Peralta Rodrigo
8 de julio de 2014
-
ndice
1. Qu es y cmo se hace un videojuego? 6
1.1. Qu es un videojuego? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2. Qu diferencia a un juego de otro? . . . . . . . . . . . . . . . . . . . . . . 8
1.3. Gneros y Clones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3.1. Gneros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3.2. Clones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.4. Juegos basados en otros . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.5. Plataformas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.5.1. Interfaz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.5.2. Recursos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.6. Roles de un equipo de desarrollo . . . . . . . . . . . . . . . . . . . . . . . . 13
1.6.1. Diseador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.6.2. Artista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.6.3. Programador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.6.4. Msico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.6.5. Sonidista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.6.6. Guionista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.7. Herramientas disponibles . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.7.1. Lenguaje de programacin . . . . . . . . . . . . . . . . . . . . . . . 15
1.7.2. Libreras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.7.3. Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.7.4. Creadores de juegos . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.7.5. Motores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2. Aprendiendo Haxeixel 17
2.1. Qu es Haxeixel? Por qu Haxeixel? . . . . . . . . . . . . . . . . . . . 17
2.2. Qu es Haxe? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.3. Instalacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4. Eligiendo un IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3. Hello World en Haxe 19
3.1. Syntax Bsico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.1.1. Constantes y sus tipos . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.1.2. Operadores Binarios y Unarios . . . . . . . . . . . . . . . . . . . . . 19
3.1.3. Bloques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.2. Declaracin de variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.3. Acesso a campos y llamadas a funciones . . . . . . . . . . . . . . . . . . . 21
3.4. Contruyendo una instancia de una clase . . . . . . . . . . . . . . . . . . . . 21
3.5. If . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.6. Switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.7. While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1
-
3.8. For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.9. Break y Continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.10. Return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.11. Objetos annimos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.12. Funciones Locales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.13. Compilacin condicional . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.14. Tipado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.14.1. Variables explcitamente tipadas . . . . . . . . . . . . . . . . . . . . 25
3.14.2. Tipado esttico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.15. Herencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.16. Tipado de Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.16.1. Funciones de Alto Orden . . . . . . . . . . . . . . . . . . . . . . . . 27
3.17. Inferencia de Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.18. El tipo Dinmico, librndonos del sistema tipado . . . . . . . . . . . . . . 29
3.18.1. Asignando a variables dinmicas . . . . . . . . . . . . . . . . . . . . 29
3.18.2. Asignando desde variables dinmicas . . . . . . . . . . . . . . . . . 29
3.18.3. Funciones en variables Dinmicas . . . . . . . . . . . . . . . . . . . 30
4. Arquitectura de un videojuego 31
4.1. Game Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.1.1. Frames Por Segundo (FPS) . . . . . . . . . . . . . . . . . . . . . . 32
4.1.2. Manejando FPS en Haxeixel . . . . . . . . . . . . . . . . . . . . . 34
4.2. Manejando Render() en Haxeixel . . . . . . . . . . . . . . . . . . . . . . . 35
4.3. Eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
4.3.1. Event Dispatcher . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.3.2. Event Handler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.3.3. Manejando Input en Haxeixel . . . . . . . . . . . . . . . . . . . . 36
4.4. Estados de Juego . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5. Sprites: La clase FlxSprite 39
5.1. Mtodos importantes de FlxSprite . . . . . . . . . . . . . . . . . . . . . . . 39
5.2. Algunos atributos de FlxSprite . . . . . . . . . . . . . . . . . . . . . . . . 39
6. Proyectos en Haxeixel 41
7. BreakOut 42
7.1. La clase Main.hx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
7.2. La clase Playstate.hx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.2.1. Atributos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.2.2. Mtodo Create . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.2.3. Mtodo Update . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
7.2.4. Funciones Callback . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
7.3. Tarea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2
-
8. Imgenes y Animaciones 48
8.1. Sprites a partir de imgenes . . . . . . . . . . . . . . . . . . . . . . . . . . 48
8.2. Animaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
8.2.1. Comportamientos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
9. Tiempo de carga, Loaders 51
9.1. Loading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
9.1.1. La clase: FlxAsyncLoop . . . . . . . . . . . . . . . . . . . . . . . . 52
9.2. Analizando la Demo: FlxAsyncLoop . . . . . . . . . . . . . . . . . . . . . . 52
9.2.1. La Clase Main.hx . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
9.2.2. La clase MenuState . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
9.3. Evitando problemas con: Recycling . . . . . . . . . . . . . . . . . . . . . . 55
9.4. Prctico: FlxInvaders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
9.4.1. Diagrama de clases . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
9.4.2. La clase Main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
9.4.3. La clase PlayState . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
9.4.4. La clase Alien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
9.4.5. La clase PlayerShip . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
9.5. Tarea: FlxInvaders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
10.Sonidos y Msica 64
10.1. La Clase: FlxSound . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
10.2. Tiempo de Carga de Sonidos y Recycling . . . . . . . . . . . . . . . . . . . 65
10.3. Agregando un Sonido a un Estado . . . . . . . . . . . . . . . . . . . . . . . 65
10.4. Sonidos de acuerdo a plataformas . . . . . . . . . . . . . . . . . . . . . . . 66
10.5. Atributos de un Objeto FlxSound . . . . . . . . . . . . . . . . . . . . . . . 66
10.6. Mtodos de un Objeto FlxSound . . . . . . . . . . . . . . . . . . . . . . . 67
11.Guardando Datos 68
11.1. La clase: FlxSave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
11.1.1. Atributos de FlxSave . . . . . . . . . . . . . . . . . . . . . . . . . . 69
11.1.2. Mtodos de FlxSave . . . . . . . . . . . . . . . . . . . . . . . . . . 70
12.Cmaras y ScaleModes 71
12.1. Qu es la cmara? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
12.2. La clase: FlxCamera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
12.2.1. Atributos de FlxCamera . . . . . . . . . . . . . . . . . . . . . . . . 72
12.2.2. Mtodos de FlxCamera . . . . . . . . . . . . . . . . . . . . . . . . . 73
12.2.3. Estilos Predenidos de FlxCamera . . . . . . . . . . . . . . . . . . 74
13.Funcionalidad Avanzada 75
13.1. Pixel Perfect Collision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
13.2. Efectos sobre nuestros Sprites . . . . . . . . . . . . . . . . . . . . . . . . . 75
13.2.1. FlxTween . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
3
-
13.2.2. TweenOptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
13.2.3. FlxGlitchSprite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
13.2.4. FlxWaveSprite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
13.2.5. FlxSpriteFilters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
14.Tiles 83
14.1. La clase: FlxTileMap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
14.1.1. Mtodos de FlxTileMap . . . . . . . . . . . . . . . . . . . . . . . . 84
14.1.2. FlxTimeMapExt . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
14.1.3. FlxCaveGenerator . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
15.Comunidad 88
15.1. Comercializacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
15.1.1. Publicidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
15.1.2. Sponsors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
15.1.3. Tiendas Online . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
15.1.4. Venta Directa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
15.1.5. Tiendas Indie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
15.2. Redes Sociales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
16.Game Jams 91
16.1. Nuestro 3hr Game Jam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
16.2. La palabra elegida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
16.3. Nuestros Juegos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
16.3.1. Chernobyl Walker . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
16.3.2. Green Goo Jump . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
16.3.3. Radiation Scape . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
16.3.4. Rodri Activo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
16.4. Y el Ganador es! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
4
-
A los Lectores
Agradezco al analista en computacin Rodrigo Peralta, quien merece los crditos por
este trabajo. Estuvo a mi cargo la redaccin e indizacin del curso Videojuegos en 2D,
dictado por la Fundasoft en Fa.M.A.F, con el n de sistematizar lo expuesto por este gran
maestro.
Para entender la totalidad del apunte, es necesario tener algn conocimiento previo de
Programacin Orientada a Objetos (POO).
Los usuarios seguramente pueden encontrar online una mejor y ms completa gua
para empezar a programar videojuegos con Haxeixel, pero este apunte incluir no slo
desarrollo tcnico de la herramienta/framework sino una gran cantidad de referencias
y conocimientos de gente que ya estuvo desarrollando videojuegos, (de ac en adelante
simplemente juegos).
Lo que realmente aprecio del apunte es que est escrito con la misma losofa del
curso, a su vez voy a dar mi mejor esfuerzo para la elaboracin de tutoriales detallados,
didcticos, con ejemplos y referencias.
Espero que realmente disfruten leyendo este apunte tanto como yo lo hice asistiendo
al curso y no tengan dudas en contactarse conmigo al mail: [email protected] por
cualquier duda o correccin del mismo.
Illbele Maximiliano.
5
-
1. Qu es y cmo se hace un videojuego?
Para m los juegos son el arte supremo, el medio supremo. Es la suma total
de todos los medios expresivos de todos los tiempos, hecho interactivo.
Phil Fish
El desarrollo de videojuegos combina muchos campos diferentes como ser edicin gr-
ca, composicin musical, guionistas y desarrolladores de software. Es un campo con
mucho potencial y desde sus inicios involucra una fuerte interaccin entre personas de
distintos mbitos, es decir, es un trabajo con una fuerte interdisciplina. Es por esto
que es recomendable intentar abandonar la idea del oo programando solo en su casa
e intentando hacer todo, dando el paso inicial con el desarrollo de juegos, hacia el difcil
camino del trabajo en equipo
1
.
Este curso trata de explicar cmo desarrollar videojuegos, as que para empezar vamos
a hablar de qu es un videojuego.
1.1. Qu es un videojuego?
Denir precisamente el concepto videojuego requiere hablar dentro de un marco terico
complejo, el cual no es el prposito de este curso, pero s intentar llegar a resumir una
nocin simple que nos sirva como desarrolladores.
Los videojuegos son arte ya que permiten a sus creadores expresar sus ideas o puntos
de vista mientras entretienen a su pblico.
Slo porque son arte no quiere decir que un videojuego tiene que ser expresivo para ser
exitoso, Angry Birds por ejemplo es un juego muy exitoso que se trata de tirar pjaros
para derrumbar estructuras con chanchos, no hay un mensaje muy claro ah.
Pero, tambin tenemos juegos como Papers Please que trata sobre la depresiva vida
de un empleado de aduana que tiene que juntar suciente plata cada da para que su
familia pueda sobrevivir
2
.
Ninguno es mejor que otro, simplemente son juegos muy distintos, que apuntan a
pblicos diferentes. Pero la clave es la siguiente: un videojuego debe entretener!
Nadie va comprar un juego para colgarlo en la pared o exponerlo en un museo. La gente
juega videjuegos porque est aburrida y quiere pasar el tiempo.
La diferencia entre videojuegos y otras formas de arte es que son fuertemente in-
teractivos. Digo fuertemente porque un libro puede ser interactivo o una obra de teatro
puede involucrar al pblico, pero un videojuego depende completamente de la in-
teraccin con el jugador para entretenerlo.
Es por esto que para implementar esta interaccin en un videojuego necesitamos:
1
I.M: lo malo de trabajar en equipo es que el resto se equivoca.
2
R.P: suena aburrido pero les juro que es divertido, a la media hora de estar jugndolo no
tena ms plata para pagar el alquiler y mi hijo haba muerto
6
-
1. Tener imgenes y sonidos.
Interactuamos con un videojuego, en la misma forma en la que interactuamos con
el mundo, con nuestros sentidos. Los sentidos que usamos para interactuar con los
videojuegos son la vista, el tacto y el odio
3
, pero eso se debe solamente a limitaciones
tecnolgicas. Algn da quizs existan aparatos que nos simulen olores, sabores y
sensaciones en la piel. Imagnense los juegos de terror que se podrn hacer con esa
tecnologa. Slenderman un poroto al lado de eso. Mapas, niveles, menes, msica de
fondo, animaciones, todo se reduce a imgenes y sonidos. El texto puede ser visto
como imagen y la msica puede incluirse dentro de los sonidos
4
.
2. Poder reaccionar ante las acciones del jugador.
Si un juego no reacciona a mis acciones no es un juego, es una pelcula o algo por el
estilo. Cmo puede nuestro juego mostrarle al jugador que sus acciones hacen algo?
simplemente modicando imgenes y reproduciendo sonidos.
Supongamos que estamos jugando un juego de plataforma y el jugador mueve el
joystick a la derecha. Nosotros tenemos que hacer que su personaje se mueva a la
derecha con una animacin como si caminara.
3
Error chistoso!
4
R.P: podramos discutir si es as pero no lo vamos a hacer.
7
-
Para hacer eso usamos de imgenes que vamos intercambiando a cierta frecuencia
creando frames consecutivos y vamos cambiando de posicin el dibujo para simular
que nuestro personaje camina.
A veces hacer nada es interactuar! Si jugaron el juego asteroides van a saber
que si se quedan quietos eventualmente un asteroide va a chocar contra ustedes y
los va matar. No moverse es una decisin que tomaron y el juego reacciona ante esa
decisin. Y esa es la forma que normalmente aprendemos a jugar un juego, viendo
cmo reacciona ante nuestros inputs. Si nunca jugaron PAC-MAN cmo van a saber
que tienen que correr de los fantasmas? Murindose, no les queda otra.
1.2. Qu diferencia a un juego de otro?
Para hacer juegos originales primero tenemos que entender muy bien qu determina
que un juego sea distinto de otro.
Interfaz
La interfaz es la forma en la que nos comunicamos con el juego. Son las acciones que
el juego nos permite realizar. Si un juego usa una interfaz distinta, por ms que el
resto del juego sea igual, es un juego distinto.
Ahora, ustedes me dirn Pero un mario para PC que usa las echas no es el mismo
que un mario para PC que usa W-A-S-D? No, no es lo mismo. Slo da la casualidad
de que las teclas W-A-S-D tienen la misma distribucin que las teclas de las echas,
entonces es prcticamente lo mismo. Si tuviramos que jugar a el mario con las teclas
Q-N-P-Z sera un juego mucho ms difcil, y si se jugara con el mouse? Eso s que
sera un juego distinto. Si quieren ver un juego que usa la interfaz de manera muy
original juegen MultiTask
5
.
Figura 1: Screen Shot del Multitask
5
http://www.kongregate.com/games/icylime/multitask
8
-
Recursos: imgenes y sonidos.
Los recursos son los objetos sobre los cuales podemos realizar cambios para inter-
actuar con el juego, son la esencia del juego. Si un juego usa recursos distintos, por
ms que el resto del juego sea igual, es un juego distinto.
De nuevo, ustedes me dirn: un juego donde mario tiene un traje azul no es el
mismo juego? No, es casi lo mismo, es una diferencia tan chica que prcticamente
no se notara. Pero si cambiamos a mario por un pingino, y cambiamos pastos verdes
por nieve y hielo: hablamos de SuperTux! Que es muy parecido a mario, pero es un
juego distinto.
Figura 2: Sreen Shoot De Supertux
O si agarramos Crush the Castle, y cambiamos la catapulta por una hondera,
piedras por pjaros, y personas por chanchos: hablamos de Angry Birds!
Figura 3: Crush the Castle Versus Angry Birds
9
-
Reglas de interaccin con el jugador.
Las reglas de interaccin denen qu cambios producen las acciones del jugador sobre
el juego. Qu pasa cuando toco a un monstruo? Qu pasa si pongo esta caja ac?
Qu pasa si golpeo a este jarro con mi espada? Todas esas cosas estn denidas por
las reglas de interaccin.
Si un juego usa reglas distintas de interaccin con el jugador, por ms que el resto
del juego sea igual, es un juego distinto. En Mario cuando salts sobre un enemigo,
lo mats, pero si lo tocs de frente te mata. En Sonic pasa lo mismo, pero si ests
rodando hecho bolita tambin los mats. Una diferencia en las reglas de interaccin
que hace que los juegos sean distintos entre s.
Reglas de Interaccin con los Recursos
Recuerdan cuando dije que hacer nada tambin es interactuar en algunos casos.
Eso es porque tambin hay reglas de interaccin entre los recursos del juego. En
asteroids Cmo reaccionan los asteroides cuando se chocan entre ellos? Rebotan o
se atraviesan? Cmo rebotan? Con 100% de elasticidad o van perdiendo velocidad?
Giran al rebotar? Qu pasa cuando llegan al borde de la pantalla? Salen del otro
lado o desaparecen? Si un juego usa reglas distintas de interaccin con los recursos,
por ms que el resto del juego sea igual, es un juego distinto.
En conclusin, un videojuego est compuesto por una interfaz, recursos, y reglas de
interaccin entre ellos. Si cambiamos cualquiera de estos elementos, por ms que sea un
cambio menor, estaramos cambiando el juego.
Parecen pocas cosas, pero las posibilidades de juegos son innitas. El nico
lmite es nuestra imaginacin. Actualmente las maneras de utilizar la interfaz son
muchsimas, y con el tiempo a medida que emerjan nuevas tecnologas existirn an
10
-
muchas ms posibilidades. Por ejemplo, la deteccin de movimiento di lugar a toda una
montaa de juegos nuevos.
Sucede lo mismo con los recursos? El arte no tiene lmite. Distintas historias, msica,
dibujos y animaciones, dan un toque nico a cada juego hacindolos distintos y atrayendo
distintos gustos. Y no nos olvidemos de las reglas de interaccin, las maneras de interactuar
con nuestros recursos son innitas. Hay juegos esperando ser creados!
1.3. Gneros y Clones
1.3.1. Gneros
Igual que la mayora de formas de arte, un videojuego se puede clasicar en gneros.
Dos juegos pertenecen al mismo gnero cuando, independiente de sus inter-
faces o recursos, tienen reglas de interaccin similares. Si cambiamos las reglas
de interaccin drsticamente es probable que los juegos pertenezcan a gneros distintos.
Ejemplos de gneros:
Juegos de plataforma: Mario, Sonic y Castlevania.
Beat them up: Streets of Rage, Golden Axe y Cadillacs and Dinosaurs.
Simuladores: Sim City, Sims y Transport Tycoon.
Recuerdan cuando dijimos antes que los distintos tipos de videojuegos que existen
son innitos. Por esa misma razn la cantidad de gneros que existen tambin son
innitos. A medida que se crean juegos nuevos van apareciendo gneros que los denen.
Un ejemplo de un gnero nuevo que recin surgi este ao es el Procedural Death
Games, sus referentes son: Binding of Isacc, Spelunky y Rogues Legacy.
1.3.2. Clones
Un juego es un clon de otro juego cuando tiene prcticamente las mismas
reglas de interaccin pero usa recursos distintos.
Es muy comn que cuando un juego se hace popular, en pocos das aparecen una
gran cantidad de clones que tratan de llevarse un poco de ese xito y sacarle ganancia
monetaria. Igual, no es siempre el caso, a veces alguien hace un clon para honrar un juego,
como sera el caso de SuperTux que es un clon de Mario totalmente gratuito y open source.
1.4. Juegos basados en otros
A veces un juego usa reglas de interaccin claves de un juego y las cambia un poquito
y crea un juego distinto Esto est genial! Porque el arte no se puede crear sobre el vaco
ya que es el producto realizado por una persona basado en su cultura, sus pensamientos
y sentimientos con una nalidad esttica o comunicativa.
Los gneros se crean de esta manera. Un juego nuevo sale y dene un gnero, y despus
salen un montn de juegos distintos basados sus conceptos claves. Distintos juegos pueden
11
-
ser simplemente nuevas versiones de otro juego o que se basen en sus reglas de interaccin
con una sutil diferencia. Un gran ejemplo de esto es 2048 que est basado en Threes pero
tiene algunos cambios
6
, como desplazar hasta la la o columna mxima posible mientras
que Thress, lo hace en una sola la o columna por vez.
1.5. Plataformas
Una plataforma es el dispositivo electrnico sobre el cual corre el juego. Ejemplos de
plataformas incluyen PC, Xbox, PlayStation, Gameboy, etc.
La plataforma afecta drsticamente a nuestra interfaz y a nuestros recursos.
1.5.1. Interfaz
Cada plataforma tiene uno o ms perifricos de entrada asociados a ella. La PC tiene
teclado y mouse. Las consolas tienen joysticks distintos entre s. Los celulares inteligentes
tienen una pantalla tctil.
Los perifricos de entrada asociados a una plataforma determinan qu in-
terfaz puede tener nuestro juego. No podemos hacer un juego que use un mouse para
la Xbox.
Si recuerdan la interfaz es parte de lo que dene a un juego. Analizando Call of Duty,
observamos cmo cambia la jugabilidad mediante la utilizacin de distintas plataformas
como ser la PC o una consola
7
.
1.5.2. Recursos
Cada plataforma tiene distintas especicaciones de hardware que afectan a los recursos
que podemos utilizar en nuestros juegos.
La memoria no voltil de una plataforma determina la cantidad de recursos totales
puede haber en nuestro juego.
La memoria voltil de una plataforma determina la cantidad de recursos que puede
haber en un instante dado del juego.
La velocidad de procesamiento de una plataforma determina a qu velocidad mxima
podemos realizar cambios sobre nuestros recursos (FPS).
Los juegos viejos tienen poca resolucin, podemos ver los pxeles. Los sonidos y la
msica eran de 8 bits. Mientras que los juegos modernos tienen resoluciones altsimas,
efectos impresionantes y en el caso de algunos juegos la msica fue hecha por una orquesta.
En conclusin: una plataforma es una tecnologa que permite la creacin de
juegos y como toda tecnologa, tiene sus lmites. De todos modos la cantidad de
juegos que se pueden hacer usando cualquiera de estas tecnologas disponibles siguen
siendo prcticamente innitos.
6
R.P: Estos cambios hacen que 2048 sea un juego muchsimo mejor que Threes.
7
R.P: A mi me divierte jugar Call of Duty en PC pero odio jugarlo en consola.
12
-
1.6. Roles de un equipo de desarrollo
Ahora vamos a describir los roles necesarios en un equipo de desarrollo de videojuegos.
Las personas involucradas en un equipo de desarrollo de un juego pueden
ocupar uno o ms roles. Por ejemplo, alguno de ustedes puede ser buen artista y
entonces hace el diseo, la programacion o el arte y para la msica contrats a un tercero.
En este curso, vamos a tomar los roles de programadores, diseadores y si hace fal-
ta, guionistas. Si alguien tiene las capacidades para cubrir otro rol, mejor! Igual, no se
preocupen, ms adelante en el curso vamos a ver las distintas maneras de conseguir los
recursos hechos por otros personas dedicadas, ya sean gratis, o pagas.
1.6.1. Diseador
Es la persona encargada de describir ya sea en palabras o con algn tipo de modelo
el juego que se va a hacer. El diseador dene la interfaz, los recursos, y las reglas de
interaccin. En otras palabras, el diseador dene el juego. El diseo es considerada la
parte ms importante del juego ya que normalmente determina si un juego es entretenido
o no.
1.6.2. Artista
El artista se encarga dibujar todas las imgenes y animaciones que se van a usar en el
juego, es uno de los que se encarga de darle forma a los recursos del juego. Personajes,
fondos, mens, botones y hasta puede tener que crear la tipografa para el juego.
El arte inuye muchsimo en el juego, un juego de terror no puede tener zombies que
parezcan osos de peluche que hacen sonreir a un beb. Ni un juego para nios puede tener
monstruos con colmillos que derraman sangre de su boca.
13
-
1.6.3. Programador
El programador es el que se encarga de implementar las reglas de interaccin para que
acten de la manera en que el juego fue diseado. Es un rol con muchsima importancia,
si el trabajo del programador no est bien hecho el juego puede terminar con bugs que
pueden causar una reaccin muy negativa en el pblico. Imaginen estar jugando un juego
por dos horas y que tir un error se cierre y no haya guardado ningn dato y tengan que
empezar de vuelta
8
.
Lamentablemente, es el rol menos apreciado por el pblico, porque es invisible
a sus ojos y odos. Un jugador puede apreciar el diseo de un juego, un jugador puede
apreciar el arte de un videojuego, puede apreciar la msica, pero una frase que nunca van
a escuchar es: Qu bien programado que est este juego.
1.6.4. Msico
Es la persona que hace la msica, es uno de los que se encarga de darle forma a los
recursos del juego. Un juego sin msica puede volverse bastante aburrido. Al igual que
el arte, la msica es lo que le da la esencia del juego. Insisto un juego de horror tiene
que tener msica tenebrosa que te ponga los pelos de punta. No puede tener una cancin
cmica, salvo que sea un circo abandonado.
1.6.5. Sonidista
Es la persona que hace los sonidos que se utilizan en el juego, es uno de los que se
encarga de darle forma a los recursos del juego. Ruidos de botones, personaje corriendo,
montruos gruiendo, etc. A veces el sonidista y el msico son la misma persona, pero no
siempre. Al igual que el msico y el artista, los sonidos tienen que reejar la esencia del
juego. Sonidos graciosos en juegos graciosos, sonidos tenebrosos en juegos tenebrosos, etc.
1.6.6. Guionista
Es la persona que escribe la historia del juego, es uno de los que se encarga de darle
forma a los recursos del juego. Buenos juegos requieren buenas historias, ah es donde entra
el guionista. Si el diseo del juego es largo y montono, por ejemplo un tower defense,
la historia es la que hace que sea mucho ms entretenido. Al igual que los otros roles, la
historia tiene que integrar la esencia del juego.
1.7. Herramientas disponibles
Hay muchsimas herramientas disponibles para la creacin de videojuegos. Cuando
alguien decide empezar a desarollar videojuegos normalmente la primer pregunta que se
hace es: Qu lenguaje de programacin debera usar? No es una pregunta fcil
8
I.M: estoy seguro que cualquiera de nosotros le dara una segunda oportunidad pero no
jueguen con nuestros lmites.
14
-
de contestar, por eso vamos a ver las distintas herramientas que hay disponibles para la
creacin de juegos.
1.7.1. Lenguaje de programacin
Si alguien no sabe lo que es puede abandonar la lectura ahora mismo o quizs no. Con
los lenguajes de programacin implementamos la lgica de un juego, pero cmo hacs
para mostrar imagenes? Hacer animaciones? Poner msica? Responder a las acciones
del jugador. Algunos lenguajes vienen ms preparados que otros para estas cosas, pero en
la mayora de casos vamos a necesitar usar libreras.
Ejemplos: Python, C++, Java, Haxe.
1.7.2. Libreras
Las libreras nos proveen una interfaz a componentes de ms bajo nivel para simpli-
car el desarrollo del juego. Si quisiramos cargar una imagen en la placa de video de
nuestra computadora en C++, no sera una tarea nada simple. En vez de eso, SFML
(Simple Fast Media Library) nos permite cargar una imagen con una sola instruccin:
texture.loadFromFile(image.png).
Ejemplos: SFML, PyGame, OpenFL.
1.7.3. Frameworks
Un framework es una base sobre la cual uno construye su aplicacin. Tienen una serie
de libreras que proveen funcionamiento que si no usramos el framework tendramos que
implementar nosotros.
An con la librera queda mucho trabajo por hacer. Tenemos que disear una arqui-
tectura para el juego y construir todas sus clases. El game loop, el sistema de estados,
los modos de escena, todas esto deber ser implementado en cada juego que hagamos.
Obviamente lo haramos una sola vez y despus copy-paste, copy-paste
9
. Un framework
nos alivia de esta tarea dndonos una arquitectura ya armada, que en el 99% de los casos
es mejor programada de la que hubiramos hecho nosotros y por lo tanto mucho ms
eciente. Los frameworks tambin cuentan con un montn de libreras para hacer mucho
ms rpido cosas que tardaramos meses en hacer.
Ejemplos: HaxeFlixel, FlashPunk, Phaser.
1.7.4. Creadores de juegos
El ms alto nivel que existe. A esta altura no podemos ver lneas de cdigo. Los
creadores de juego son programas con una interfaz de usuario que facilitan la creacin
de juegos. Algunos son especcos para ciertos gneros mientras que otros permiten la
creacin de mltiples tipos de juegos.
Ejemplos: RPG Maker, Construct2.
9
I.M: Si no existiera el copy-paste no cometeramos el 80% de los errores al programar.
15
-
1.7.5. Motores
Los motores se encuentran entre los frameworks y los creadores de juegos. En este
nivel todava hay programacin, la cantidad de cdigo que vemos depende del motor en
s. Algunos motores se parecen ms a un framework, algunos se parecen ms a un creador
de juegos. Tambin algunos motores suelen restringirte a crear ciertos gneros de juegos.
Ejemplos: Unity, UnrealEngine.
Al nal que herramienta me conviene? La que ms les guste.
En este curso vamos a usar el framework Haxeixel, ms adelante voy a justicar
esta eleccin. Pero recuerden que a su pblico, generalmente, no le interesa cmo fue
hecho su juego. La programacin es invisible al pblico. Por eso no pierdan tiempo
tratando de hacer cosas que ya estn hechas, y de una manera mejor. Cuando tienen que
usar un arreglo, nadie implementa el suyo, usa el de la librera estndar.
No digo que no est bueno meterse a veces ms profundo en el cdigo para ver cmo
funcionan ciertas cosas, eso est genial y a veces lo van a tener que hacer porque no queda
otra. Pero recuerden que nadie se va dar cuenta si su juego es un 1.5% ms eciente en
memoria porque implementaron su propio algoritmo de bsqueda. Porque les puede pasar
que mientras ustedes estn peleando para cargar imgenes a la placa de video en C++
alguien puede estar vendiendo sus juegos hechos con Game Maker.
16
-
2. Aprendiendo Haxeixel
Si slo pudieras aprender un lenguaje de programacin, Haxe
sera ese lenguaje. Es universal. Es poderoso. Es fcil de usar.
haxe.org
2.1. Qu es Haxeixel? Por qu Haxeixel?
Haxeixel es un framework construido sobre:
1. Haxe: lenguaje de programacin multiplataforma.
2. OpenFL: conjunto de libreras multiplataforma.
Por qu Haxeixel?
1. Multiplataforma.
Con Haxeixel podemos hacer juegos para casi cualquier plataforma a veces sin tener
que cambiar una sola lnea de cdigo
10
.
2. Open Source.
Unity y otros motores son multiplataforma, pero hay que pagar para usarlo pagos y
no son para nada open source. Unity Pro sale USD $1500. Game Maker Profesional
sale USD $ 800. Y sus versiones gratuitas son limitadas en algunos aspectos.
3. Equilibrio entre libertad y facilidad.
Al trabajar con un framework, por no ser de tan alto nivel, no nos limita lo que
podemos crear, como lo hara un creador de juego o algunos motores. Ni tampoco
programamos a tan bajo nivel para obligarnos a programar componentes compli-
cadas, utilizando una gran cantidad de horas para decidir por ejemplo en qu lugar
queremos un botn.
4. Hay juegos exitosos hechos con Haxe y OpenFL.
Esto es muy importante, es deprimente encontrar una tecnologa con la cual uno
se encuentra cmodo y descubrir que nadie nunca vendi un solo juego con eso.
Papers Please es considerado el mejor juego independiente del 2013. Y est hecho
en OpenFL. Ahora, Haxeixel es un framework por encima de OpenFL. Pero porque
empiecen con Haxeixel no quiere decir que no puedan terminar trabajando solo con
OpenFL. Es ms, va haber ciertas cosas en las cuales vamos a tener que usar OpenFL
porque Haxeixel no ofrece una librera para eso. Inclusive Haxeixel es un excelente
punto para empezar a hacer juegos ya mismo!
10
R.P: Yo compil un juego para ash y android sin cambiar nada
17
-
2.2. Qu es Haxe?
Haxe (pronunciado como Hex) es un lenguaje de programacin open source. Mientras
que otros lenguajes estn limitados a su propia plataforma (Java al JVM, C# a .Net,
ActionScript al Flash Player), Haxe es un lenguaje multiplataforma, a continuacin pre-
sentamos un listado de algunas plataformas a las que puedo compilar Haxe.
Javascript
Flash
NekoVM
PHP
C++
C#
Java
Android
Haxe es un lenguaje muy parecido a Javascript o ActionScript as que los que hayan
trabajado en esos lenguajes no van a tener muchos problemas adaptndose.
2.3. Instalacin
Hay un instalador automtico de Haxe para todos los sistemas operativos que se puede
descargar desde: http://haxe.org/download As que no hace falta decir mucho ms que:
Next, Next, Next, No leer nada, Agree, Next.
2.4. Eligiendo un IDE
Para Windows, recomiendo http://www.flashdevelop.org/. Es lo que uso para tra-
bajar y es, en mi opinin, excelente, open source y tambin sirve para OpenFL y Haxeixel.
Si estn en Linux o Mac, recomiendo que usen Sublime-Text. Para instalarlo recomien-
do que lean lo siguiente: http://haxeflixel.com/documentation/sublime-text/, la
instalacin est en un repositorio GitHub, si se les complica mucho instalarlo y usan Lin-
ux, no deberan hacerse los inteligentes y usar Linux
11
. Si se les complica mucho instalarlo
y usan Mac, deberan sentirse mal por usar Mac
12
.
11
R.P
12
R.P
18
-
3. Hello World en Haxe
Now you're thinking with portals.
Portal
Abran un archivo nuevo en su editor de texto favorito y llmenlo Main.hx
Escriban lo siguiente:
1 class Main
2 {
3 public stat ic function main ( )
4 {
5 t r a c e ( " h e l l o world" ) ;
6 }
7 }
Ahora compila de la siguente manera:
haxe -main Main -neko helloworld.n
Y lo ejecutan de la siguiente manera:
neko helloworld.n
Yey! Hemos hecho nuestro primer programa en Haxe.
3.1. Syntax Bsico
3.1.1. Constantes y sus tipos
Bool: true, false.
Int: 1234, -456, 0xF, 0xF0.
Float: 0.72, -0.45, .50, 1e2.
String: Hello World, `Goodbye Cruel World', Hello somebody.
EReg: /[a-ZA-Z]+/.
Unknown: null.
3.1.2. Operadores Binarios y Unarios
Asignacin: =, +=, *=, -=... (La asignacin devuelve el valor, permite hacer cadenas).
Comparacin: ==, =.
Operadores Aritmticos: +, -, *, /,%.
Operadores Booleanos: &&, ||.Operadores Bitwise: |, &, >>, >.Operadores Unarios: !, , ++, .
3.1.3. Bloques
Los bloques son importantes en Haxe, herramienta til para simplicar algunas expre-
siones. Los bloques estn delimitados por llaves { }. Lo que los hace especial en Haxe es
19
-
que tienen un valor y un tipo. El valor de un bloque y su tipo es igual al de la ltima
expresin de este bloque. Notar que bloques vacos son de tipo Void.
Mostramos un ejemplo a continuacin mostrando cmo nos simplica el cdigo:
1 public stat ic function main ( ) : Void
2 {
3 var s : String ;4 s = i f ( true ) {
5 "Vrai " ;
6 } else {
7 "Faux" ;
8 }
9 t r a c e ( s ) ;
10 }
En otros lenguajes sera:
1 public stat ic function main ( ) : Void
2 {
3 var s : String ;4 i f ( true ) {
5 s = "Vrai " ;
6 } else {
7 s = "Faux" ;
8 }
9 t r a c e ( s ) ;
10 }
3.2. Declaracin de variables
Una variable se declara con la palabra reservada var. Hay dos maneras de declarar
una variable. Una es a nivel de clase, la otra es declarando variables locales en bloques de
cdigo.
1. A nivel de clase:
[public|private][static]var varName[: varType][= someV alue];
Las variables son por defecto privadas, a menos que la clase implemente la interface
Public. Slo a las variables estticas se les puede dar un valor cuando son declaradas.
2. En un bloque de cdigo:
var varName [: varType][= varV alue];
Una variable est disponible desde la lnea donde se declara hasta donde termina el
bloque en que se declar.
20
-
1 class Main
2 {
3 public stat ic function main ( )
4 {
5 var myNumber : Int = 15 ;6 }
7 }
Una variable puede ser declarada mltiples veces, en el mismo bloque o en bloques
distintos. La declaracin que se toma en cuenta es la ms cercana.
1 class Main
2 {
3 public stat ic function main ( )
4 {
5 var myNumber : Int = 15 ;6 myNumber = 2 ;
7 t r a c e (myNumber) ; //Traces 2
8 {
9 var myNumber : Int = 1 ;10 t r a c e (myNumber) ; //Traces 1
11 }
12 t r a c e (myNumber) ; //Traces 2
13 }
14 }
3.3. Acesso a campos y llamadas a funciones
Para acceder a campos y llamar a mtodos en Haxe se utiliza la notacin de punto.
As que si uno quiere acceder la variable name de un objeto llamado user se hace de la
siguiente manera:
user.name
Para llamar una funcin lo nico que tens que hacer es poner parntesis despus del
nombre de la funcin y escribs tus argumentos dentro del parentsis, separados por comas.
As es como se llama una funcin llamada sayHelloTo de un objeto llamado user.
user.sayHelloTo(Mr, Benjamin);
21
-
3.4. Construyendo una instancia de una clase
Se usa la palabra clave new:
1 var user = new User ( "Mr" , "Benjamin" ) ;
Un ejemplo de la clase User podra ser:
1 class User
2 {
3 public function new( t i t l e : String , name : String) {
4 //Do t h i n g s
5 }
6 }
Se puede llamar al constructor de la superclase usando super() con parmetros si hiciera
falta. Para acceder a la clase actual se usa la palabra clave this.
3.5. If
1 i f ( age < 16) {
2 t r a c e ( "You are young" ) ;
3 } else i f ( age >= 16 && age < 18) {
4 t r a c e ( "You are almost an adul t " ) ;
5 } else {
6 t r a c e ( "You are an adult " ) ;
7 }
Tambin podemos usar lo que aprendimos de bloques:
1 var age = 18 ;2 t r a c e (
3 i f ( age
-
3.7. While
Hay dos syntax posibles. El while loop normal:
1 while ( cond i t i on ) {
2 exprToBeExecuted ;
3 }
Y el do while:
1 do{
2 exprToBeExecuted ;
3 }while ( cond i t i on ) ;
Ejemplos:
1 while ( i< 18) {
2 t r a c e ( i ) ; //Wil l t r a c e numbers from 0 to 17 inc luded
3 i++;
4 }
1 do{
2 t r a c e ( i ) ; //Wil l t r a c e numbers from 0 to 17 inc luded
3 i++;
4 } while ( i < 18) ;
3.8. For
Haxe tiene un loop de for que funciona sobre iteradores. Un iterador es un objeto que
soporta algunos mtodos denidos en el typedef del iterador. Tiene varios valores y los va
devolviendo uno por uno en cada llamada de la siguiente funcin.
Ejemplo:
1 for ( i in 0 . . . 1 0 ) {
2 t r a c e ( i ) ; // Wil l t r a c e numbers from 0 to 9
3 }
Nota: 0 . . . 10 es una construccin especial. El operador . . . recibe dos int y devuelve
un interador
13
que devolver todos los int desde el primero (incluido) hasta el ltimo
(excluido).
Esta construccin es particularmente til para iterar sobre listas y arreglos.
Por ejemplo:
1 class TesthaXe
2 {
3 public stat ic function main ( ) : Void
4 {
5 var l = new List() ;6 l . add ( "He l lo " ) ;
13
Error Chistoso!
23
-
7 l . add ( "World" ) ;
8 for ( s in l ) {
9 neko . Lib . p r i n t l n ( s ) ;
10 }
11 }
12 }
3.9. Break y Continue
La palabra break es usada para salir de un ciclo prematuramente.
La palabra continue es usada para ir directamente a la siguente iteracin de nuestro
ciclo sin ejecutar el cdigo despus de la palabra continue.
3.10. Return
La palabra clave return es usada para salir de una funcin o devolver un valor de una
funcin (y salir).
3.11. Objetos annimos
Los objetos annimos pueden ser creados en cualquier momento utilizando llaves.
var user = {age : 12, name : Benjamin};
Figura 4: Haxe tiene DuckTyping
24
-
3.12. Funciones Locales
Funciones locales son funciones sin un nombre, llamadas comnmente funciones ann-
imas. Son valores que pueden ser asignados a cualquier variable, por ejemplo:
1 public class User
2 {
3 var sayHe l lo :String Void ;4 public function new( ) {
5 sayHe l lo = function( to : String) {
6 t r a c e ( "He l lo " + to ) ;
7 } ;
8 sayHe l lo ( "World" ) ;
9 }
10 }
Las funciones locales pueden acceder a cualquier variable local declarada en el mismo
alcance que las variables estticas pero no pueden acceder la variable this.
3.13. Compilacin condicional
Haxe nos permite hacer compilacin condicional, esto signica que ciertas partes del
cdigo son compiladas mientras que otras se ignoran dependiendo de las banderas que le
damos al compilador y de qu plataforma tenemos como objetivo.
Instrucciones de compilacin condicional siempre empiezan con el comando #if
1#i f cpp
2 //C++ code
3 #elseif neko
4 //Neko code
5 #elseif php
6 //PHP code
7#else
8 //Code f o r o ther t a r g e t s
9 #end
3.14. Tipado
3.14.1. Variables explcitamente tipadas
Variables son explcitamente tipadas si vos escribs su tipo al declararlas. Esto es lo
que hemos visto hasta ahora y se hace de la siguiente manera:
var myV ar : TypeOfMyV ariable;
3.14.2. Tipado esttico
En Haxe, una vez que una variable ha sido declarada y se sabe su tipo, no es posi-
ble asignarle un valor de otro tipo. Aunque debera notarse que el compilador permite
25
-
redeclarar una variable con el mismo nombre y otro tipo. As que el siguiente cdigo
compila:
1 class Main
2 {
3 public stat ic function main ( ) {
4 var e : String ;5 e = " St r ing " ;
6 var e : Int ;7 e = 12 ;
8 }
9 }
Aunque este cdigo compile, uno no debera estar haciendo esto porque puede ser
confuso a otros desarolladores o hasta a vos mismo si tens que leer tu cdigo varios das
despus
14
.
Por lo tanto, para mantener las cosas simples, una vez que una variable es tipada, su
tipo no se puede cambiar y slo se pueden asignar valores de ese tipo. As que lo siguiente
no funcionara:
1 class Main
2 {
3 public stat ic function main ( )
4 {
5 var e : String ;6 e = "Test " ;
7 e = 12 ;
8 }
9 }
3.15. Herencia
En Haxe, una clase puede extender a otra clase. En tal caso, tiene todos los campos
de sus clases padres y tiene todos los tipos que tienen sus clases padres (ms su propio
tipo). Lo que eso signica, por ejemplo, es: cuando una funcin quiere un parmetro de
tipo A, si B extiende A, vos pods pasar una instancia de B a tu funcin. Esto se ve en
el siguiente cdigo:
1 class Main
2 {
3 public stat ic function main ( ) {
4 var human : HumanBeing ;5 human = new HumanBeing ( "Benjamin" ) ;
6 cong ra tu l a t e (human) ;
7 }
8 public stat ic function cong ra tu l a t e ( l t : LivingThing ) {
9 t r a c e ( "Congrats " + l t . name) ;
10 }
14
I.M: Por eso los programadores de Videojuegos lo hacen en las Game Jam en 24Hs.
26
-
11 }
12
13 class LivingThing
14 {
15 public var name : String ;16 public function new( ) {
17 name = "" ;
18 }
19 }
20
21 class HumanBeing extends LivingThing
22 {
23 public function new(name : String)
24 {
25 super ( ) ;
26 this . name = name ;
27 }
28 }
(Haxe no tiene ningn tipo de multi-herencia. )
3.16. Tipado de Funciones
Las funciones tambin son tipadas. Esto es bueno por dos razones: es posible pasar
una funcin como parmetro a otra funcin y guardar funciones tipadas en una variable.
Expresando el tipo de una funcin
Todas las funciones en Haxe son tipadas, as que por ejemplo, cuando uno escribe:
1 public function outputStr ing ( s t : String) : Void ;
Sabemos que la funcin outputString toma un parmetro de tipo String y devuelve
Void, esto signica que no devuelve ningn objeto. El tipo de la funcin se representa de
la siguiente manera:
String V oidOtro ejemplo, la funcin:
public function sumAndCeil(a : Float, b : Int) : Int;
Tiene tipo:
Float Int Int
3.16.1. Funciones de Alto Orden
Como mencionamos antes, una funcin puede tomar como argumento otra funcin.
Esto es til por ejemplo para aplicar ltros en listas o arreglos. Hay tal cosa en la librera
estndar:
List.filter.
27
-
Voy a simplicar las cosas un poco diciendo que este mtodo, que toma una una lista de
String podra ser declarado de la siguiente manera:
public function filter(f : String Bool) : List < String >;
Como deben haber adivinado, esta funcin toma una funcin como parmetro, pasa cada
elemento de la lista a ella, si la funcin devuelve true, entonces suma ese elemento a una
lista que devuelve.
El tipo de esta funcin es el siguiente:
(String Bool) List < String >
Las funciones tambin pueden devolver una funcin; en este caso, simplemente tienes
que poner los parntesis despus de la ltima echa del tipo:
public function takesStringReturnsFunction(s : String) : String Bool;
Esta funcin tiene el tipo:
String (String Bool)Toma un String y devuelve una funcin que toma un String y devuelve un Bool. Llamando
la funcin devuelta sera tan simple como escribir:
takesStringReturnsFunction(Hello)(World);
3.17. Inferencia de Tipos
Cuando omitimos el tipo de una variable en el momento de su declaracin el compilador
inferir el tipo de la variable segn el tipo utilizado en su primera referencia.
Hay varias maneras de que el compilador adivine el tipo de tus variables.
1. Asignando un Valor: cuando asigns un valor a una variable que tiene un tipo de-
sconocido, su tipo ser inferido como el tipo de el valor asignado, as que por ejemplo,
si escribs:
1 var s ;2 s = "He l lo World" ;
El tipo de s ser inferido a String.
2. Asignando el valor de una variable a otra: si asigns a una variable que tiene tipo
desconocido el valor de una variable con un tipo conocido, su tipo tambin ser
inferido:
1 var s ;2 var t : String ;3 s = t ;
28
-
Ac el tipo inferido de s es String.
3. Pasando la variable como parmetro de funcin
Cuando pasas una variable a una funcin, su tipo es inferido como aquel que es
esperado por la funcin. Por ejemplo:
1 class Main
2 {
3 stat ic function pr in t ( s : String) {
4 t r a c e ( s ) ;
5 }
6
7 public stat ic function main ( ) {
8 var t ;9 p r i n t ( t ) ;
10 type ( t ) ;
11 }
12 }
3.18. El tipo Dinmico, librndonos del sistema tipado
Cuando uno dene una variable como tipo Dynamic, esto signica que el compilador
no har ningn chequeo de tipos en esta variable en tiempos de compilacin.
3.18.1. Asignando a variables dinmicas
Cuando declars una variable como Dynamic, vas a poder asignarle cualquier valor en
tiempo de compilacin. As que el siguiente cdigo es compilable:
1 class DynamicTest
2 {
3 public stat ic function main ( ) {
4 var dynamicVar : Dynamic ;5 dynamicVar = "He l lo " ;
6 dynamicVar = 123 ;
7 dynamicVar = {name : "John" , lastName : "Doe" } ;
8 dynamicVar = new Array() ;
9 }
10 }
No le va molestar al compilador aunque ests asignando distintos valores con distintos
tipos a la misma variable.
3.18.2. Asignando desde variables dinmicas
Uno puede asignar el contenido de cualquier variable dinmica a una variable de
cualquier tipo. Es ms, se podra decir que el tipo Dynamic puede ser usado en lugar
de cualquier tipo y que una variable de tipo Dynamic es de cualquier tipo. Con eso en
mente, uno puede ver que ahora se puede escribir y compilar este cdigo:
29
-
1 class DynamicTest
2 {
3 public stat ic function main ( ) {
4 var dynamicVar : Dynamic ;5 var year : Int ;6 dynamicVar = "He l lo " ;
7 year = dynamicVar ;
8 }
9 }
Entonces aunque asignemos un String a una variable tipada como Int, el compilador
no se quejar. Pero deberan tener en mente que esto es en tiempo de compilacin! Si
uno abusa esta posibilidad, uno puede terminar con un comportamiento muy raro.
3.18.3. Funciones en variables Dinmicas
Tambin es posible guardar funciones en las variables Dynamic y llamarlas:
1 class DynamicTest
2 {
3 public stat ic function main ( ) {
4 var dynamicVar : Dynamic ;5 dynamicVar = function (name : String) {
6 t r a c e ( "He l lo " + name) ;
7 } ;
8 dynamicVar ( ) ;
9 }
10 }
Como pueden ver, es posible asignar funciones a una variable Dynamic y despus es
posible llamarla al igual que cualquier funcin. Aunque este cdigo compile, su xito
corriendo depende de la plataforma objetivo.
30
-
4. Arquitectura de un videojuego
Its dangerous to go alone! take this!
Legend of Zelda.
Antes de empezar a programar necesitamos aprender la arquitectura de un videojuego.
Por ms que el framework implemente la arquitectura por nosotros, necesitamos entender
cmo funciona para poder utilizarla. Lo que se va a ver al principio no es la forma de
trabajo de Haxeixel, pero sirve para entender qu es lo que esta haciendo Haxeixel por
nosotros.
4.1. Game Loop
El game loop es el cdigo central del juego, y normalmente tiene esta forma:
1 while (mWindow. isOpen ( ) ) {
2 Process Input ( ) ;
3 Update ( ) ;
4 Render ( ) ;
5 }
ProcessInput()
Se encarga de responder al input del jugador, normalmente se maneja con eventos
que vamos a explicar ms adelante.
Update()
Despus de responder al input del jugador (o no si no hace nada), hay que actualizar
los objetos del juego. Esto puede involucrar mover imgenes de lugar, detectar y
manejar colisiones, es decir, toda la lgica de los objetos se maneja aqu.
Render()
Despus de actualizar los objetos de nuestro juego tenemos que renderizarlos. Si los
actualizamos y no los renderizamos, los objetos no van a cambiar de lugar en el
monitor.
Ejemplo
1. Supongamos que tenemos un personaje que est contra una pared.
2. El jugador aprieta la tecla para moverse en esa direccin.
3. El handle input detecta esa tecla e incrementa la velocidad del personaje, pero no
lo mueve, esa es la funcin del update.
31
-
4. El update actualiza la posicin del objeto movindolo una cierta distancia de acuerdo
a la velocidad del objeto, dejndolo solapado sobre la pared.
5. En el monitor todava no se vi ningn cambio.
6. Ahora, dentro de la misma funcin update, despus de moverse segn la velocidad
del objeto, hay una parte del cdigo que se encarga de las colisiones. Y esa parte
del cdigo, detecta que el personaje y la pared han colisionado, y entonces mueve al
jugador 5 pxeles fuera de la pared.
7. Ahora le toca a la funcin render, que dibuja todos los objetos sobre la pantalla.
8. Como el personaje qued al nal en el mismo lugar, parece que no pas nada. Pero
internamente cada vez que te chocas con una pared la ests atravezando y la lgica
te reposiciona.
4.1.1. Frames Por Segundo (FPS)
Ahora, nuestro game loop de antes tiene 2 problemas:
No limita la cantidad de FPS.
No corrige variaciones de FPS.
Limitar los FPS
Hay varios problemas que surgen de no limitar la cantidad de FPS.
El primero sera que el juego corre a distintas velocidades en distintas computadoras,
en algunos casos tan rpido que el juego se vuelve injugable.
El segundo problema es que, si nuestro game loop corre ms rpido que la frecuencia
del monitor, el monitor no va a tener tiempo de terminar nuestro pedido de render() antes
de que le enviemos otro pedido de render(), vamos a ver lo que se llama screen tearing,
que es cuando vemos una lnea horizontal en la pantalla porque una parte del juego est
ms actualizada que otra.
32
-
Figura 5: Ejemplo: Screen Tearing
Variaciones de FPS
Supongamos que queremos que nuestro personaje se mueva 60 pxeles por segundo.
Entonces nosotros le damos una velocidad de 1 pixel por frame.
A una frecuencia de 60 FPS el personaje se mueve 60 pxeles a la derecha en un segundo.
Ahora supongamos que sufrimos de lag, y nuestro juego corri a 24 FPS. Ahora nuestro
personaje se mueve 24 pxeles en un segundo. Pero nuestro personaje tena que moverse
60 pxeles en un segundo independientemente de los fps. Nuestro personaje no debera
moverse ms rpido o ms lento dependiendo de los FPS, su velocidad debera ser con-
stante.
Figura 6: El problema del lag y los FPS
Solucin:
Vamos a tener que agregar un poco de cdigo a nuestro game loop para poder corregir
ambos problemas:
33
-
1 while (mWindow. isOpen ( ) )
2 {
3 timeSinceLastUpdate += c lock . r e s t a r t ( ) ;
4 while ( t imeSinceLastUpdate > TimePerFrame )
5 {
6 timeSinceLastUpdate = TimePerFrame ;7 Process Input ( ) ;
8 Update (TimePerFrame ) ;
9 }
10 Render ( ) ;
11 }
La condicin (timeSinceLastUpdate > TimePerFrame) corrige el primer error limi-
tando los FPS para que no vayan ms rpido que TimePerFrame.
El while que contiene esa condicin corrige el segundo error encargndose de correr el
update() tantas veces como haga falta para que todo est actualizado.
Noten que render est por fuera del loop, ya que no importa cuntos render hagamos
si los objetos no se cambiaron de posicin no habr screen tearing.
Noten que update ahora tiene un argumento de tiempo, esto es para que la velocidad
de los objetos sea la misma sin importar a cuntos FPS corre.
Consideremos de nuevo el ejemplo anterior que queramos que tuviera velocidad de 60
pxeles por segundo. Su funcin de update del objeto tendra una pinta as:
1 public function update ( )
2 {
3 this . x += 1 ;
4 }
Ahora, esto slo andara a 60 pxeles por segundo, cuando el juego corre a 60 FPS. Para
hacerlo independiente de los FPS tenemos que tomar como argumento el TimePerFrame:
1 public function update (TimePerFrame : Float)
2 {
3 this . x += 60*TimePerFrame ;
4 }
Ahora s, sto se va a mover a 60 pxeles por segundo sin importar el FPS.
4.1.2. Manejando FPS en Haxeixel
Dentro del archivo GameClass.hx encontraremos:
var frameRate : Int = 60;
Para cambiar el framerate en el cual el juego debera correr simplemente cambiamos ese
valor. Ni siquiera tenemos que pasar como argumento el valor TimePerFrame a la funcin
update(). Si nos hiciera falta saber cunto tiempo paso desde el ltimo frame podemos
acceder ese valor usando la siguiente variable:
FlxG.elapsed
34
-
Gracias a esto nuestro game loop volvera a:
1 while (mWindow. isOpen ( ) ) {
2 proce s s Input ( ) ;
3 update ( ) ;
4 render ( ) ;
5 }
4.2. Manejando Render() en Haxeixel
En Haxeixel no tenemos que llamar la funcin render(). Lo nico que tenemos que
hacer es agregar los objetos que queremos que sean renderizados a lo que se llama el
DisplayList. Y todo lo que este en el DisplayList va a ser renderizado automticamente.
Para agregar algo al DisplayList se usa el mtodo add():
add(newFlxText(0, 0, 100, Hello World!));
Por lo tanto nuestro game loop queda:
1 while (mWindow. isOpen ( ) ) {
2 proce s s Input ( ) ;
3 update ( ) ;
4 }
4.3. Eventos
Un evento es una accin u ocurrencia detectada, que puede o no ser manejada por el
programa. Su uso principal es para responder al input del usuario pero vamos a ver que
sirve para otros nes:
Ejemplos de Eventos:
35
-
Event.SOUND_COMPLETE : un sonido termin su reproduccin.
MouseEvent.CLICK: el mouse hizo click.
KeyboardEvent.KEY_DOWN: una tecla fue presionada.
4.3.1. Event Dispatcher
Es un objeto que puede generar eventos. Event.SOUND_COMPLETE es generado por
un objeto de tipo Sound cuando termina su reproduccin. En este caso nosotros podramos
repetir el sonido o cambiarlo. Pero para hacer eso necesitamos otra cosa.
4.3.2. Event Handler
Son objetos que pueden manejar eventos. Uno le pide a un event handler que escuche
por un tipo determinado de objeto y se le asigna una funcin callback que va a ser llamada
cuando el evento sea detectado.
Por ejemplo:
1 Lib.current.stage.addEventListener(MouseEvent.MOUSE_DOWN,mousePressed);2 Lib.current.stage.addEventListener(MouseEvent.MOUSE_UP,mouseReleased);3
4 private function mousePressed ( event :MouseEvent) : Void {
5 f i r i n g = true ;
6 }
7
8 private function mouseReleased ( event :MouseEvent) : Void {
9 f i r i n g = fa l se ;
10 }
4.3.3. Manejando Input en Haxeixel
Los eventos son usados en OpenFL pero no son tan usados en Flixel.
En Flixel lo que hace es captura todos los eventos que ocurrieron entre el ltimo frame
y el frame actual. Tambin podemos ver eventos continuos como por ejemplo, si una tecla
est siendo continuamente apretada.
1 i f (FlxG . keys . p re s s ed .DOWN) {
2 //haga a l go
3 }
Este tipo de cdigo ira dentro de nuestro bloque de update, eliminando en Flixel la
necesidad de procesar los inputs en un bloque separado.
Dejando nuestro game loop de la siguiente manera:
1 while (mWindow. isOpen ( ) ) {
2 update ( ) ;
3 }
36
-
4.4. Estados de Juego
Hasta ahora nuestro Game Loop nos permite hacer juegos muy simples. Pero si quisiramos
un juego que tiene un men con una intro, un men de opciones, un men de seleccin
de niveles, los niveles en s, y por ltimo el Game Over.
Organizar todo ese cdigo dentro de nuestra funcin update sera horrible y tedioso.
Tendramos que estar agregando y sacando objetos con cada cambio de men y sera una
sola funcin de cientos de lneas de cdigo.
Por suerte el sistema de Estados nos facilita esto muchsimo. Cada men sera repre-
sentado como un estado, cada uno con sus propios recursos y su propia funcin update.
De esta manera cada estado tendra recursos distintos y respondera de manera distinta
al jugador.
Por ejemplo, los controles del juego slo deberan estr habilitados en el estado de
juego. Mientras que en el men slo responde cuando se hace click sobre los botones de
START o OPTIONS. Cambiar de estado se vuelve tan simple como llamar la funcin:
FlxG.switchState(newPlayState());
Figura 7: Estados de un Juego
Cada estado que creamos tiene que extender la clase FlxState. Mtodos de la clase
FlxState:
create()
add(object:FlxSprite)
remove(object:FlxSprite)
37
-
update()
destroy()
38
-
5. Sprites: La clase FlxSprite
Thank you Mario! But our princess is in another castle!
Mario
FlxSprite es la clase que vamos a utilizar para mostrar imgenes en nuestros juegos.
Normalmente vamos a extender esta clase para agregar nuestras propias variables,
como por ejemplo puntos de vida, nivel, ataque, defensa.
Hay que tener en cuenta que siempre que sobreescribamos una funcin hay que llamar
a la funcin super() sino vamos a tener errores importantes en el juego.
5.1. Mtodos importantes de FlxSprite
loadGraphic() : recibe un string con el path de una imagen y la carga. Para poder
ver la imagen el Sprite tiene que ser agregado a algn estado con add().
makeGraphic(): se utiliza para crear imgenes a partir de rectngulos y un color, por
ejemplo dibujar un cuadrado rojo.
5.2. Algunos atributos de FlxSprite
x : posicin horizontal del Sprite. Cero es el borde izquierdo de la pantalla e incre-
menta hacia la derecha.
y : posicin vertical del Sprite. Cero es el borde superior de la pantalla e incrementa
hacia abajo.
velocity : velocidad del Sprite, su posicin va cambiar de acuerdo a este valor en cada
update(). Es una dupla (x,y), donde cada atributo guarda la velocidad horizontal y
vertical respectivamente. Se acceden de la siguiente manera: velocity.x.
acceleration : aceleracin del Sprite, su velocidad va cambiar de acuerdo a este valor
en cada update(). Al igual que velocity es un punto con valores x e y, de tipo oat.
scale: controla la escala de la imagen, es lo que modicamos si queremos agrandar o
achicar la imagen. Tambin una dupla (x,y), de tipo oat.
width: determina el ancho del hitbox del sprite que por defecto es el ancho de la
imagen. El hitbox es el rea que se va usar para controlar si hay una colisin.
height: determina la altura del hitbox del sprite que por defecto es la altura de la
imagen.
oset: controla la posicin del hitbox del sprite. Tambin una dupla con valores x e
y. Normalmente debe ser modicado despus de cambiar el ancho o alto del hitbox.
39
-
Para simplicarnos la vida, la clase FlxSprite tiene su propio mtodo update() que
corre automticamente si el sprite fue agregado al estado que est corriendo
actualmente.
Por defecto lo nico que hace el update() de un sprite es actualizar su posicin de
acuerdo a su velocidad y actualizar su velocidad de acuerdo a su aceleracin.
Pero nosotros podemos sobreescribir ese mtodo y agregar nuestra propia lgica, siem-
pre y cuando nos acordemos de llamar al mtodo super.update().
40
-
6. Proyectos en Haxeixel
Game Over
:p
Ahora vamos a ver qu archivos y carpetas conforman un proyecto de Haxeixel y cul
es la funcin de cada uno.
Podemos crear un proyecto a partir de un template:
flixel tpl n Nombre
El comando nos crear un directorio con los siguientes archivos:
Project.xml: contiene los settings de la aplicacin. Ac se denen opciones como
resolucin, nombre de la aplicacin, fps, si es pantalla completa o no, orientacin de
la pantalla si es un dispositivo mvil, etc.
Main.hx: el main de nuestro juego. Este archivo es el nico que tiene cdigo de
OpenFL, nunca vamos a tener que editarlo.
Reg.hx: una clase para guardar valores globales estticos. Se usa para compartir
valores entre distintos estados. Viene con varios ejemplos.
GameClass.hx: esta clase contiene los settings del juego. La diferencia entre las op-
ciones de esta clase y las opciones en Project.xml es que stas son las del juego
mientras que las de Project.xml son las de la aplicacin (o si sirve para entenderlo
mejor, de la ventana). El juego corre dentro de la aplicacin (o ventana), esto quiere
decir que si Project.xml tiene una resolucin de 800x600 y GameClass.hx de 640x480
el juego va correr dentro de una ventana de 800x600 pero slo va a ocupar 640x480.
El resto va a tener el color de Background que hayamos denido en Project.xml.
MenuState.hx y PlayState.hx son estados de juego vacos. Ac es donde vamos a
escribir todo el cdigo de nuestro juego, creando otros estados ms si hiciera falta.
Probablemente tambin tengamos que crear otras clases que extienden a FlxSprite.
41
-
7. BreakOut
If people were inuenced by video games, then the
majority of Facebook users would be farmers by now.
Anonymous
Prctico: analizando el cdigo de BreakOut
Ahora en clase vamos a analizar el cdigo del demo BreakOut:
Juego: http://haxeflixel.com/demos/Breakout/.
Cdigo: https://github.com/HaxeFlixel/flixel-demos/tree/dev/Arcade%20Classics/
Breakout.
Comando para crear el proyecto de BreakOut: ixel create.
Figura 8: Diagrama de Clases del Breakout
7.1. La clase Main.hx
La clase Main.hx, no tiene lgica simplemente crea al iniciar una intancia de PlayState,
en ella lo nico que solemos cambiar son los siguientes atributos:
1 var gameWidth : Int = 320 ; // Ancho de l juego en p i x e l s
2 var gameHeight : Int = 240 ; // Alto d e l juego en p i x e l s
3 var i n i t i a l S t a t e :Class = PlayState ; // Estado i n i c i a l .
4 var zoom :Float = 1; // se acomode a l a s dimensiones de p an t a l l a5 var f ramerate : Int = 60 ;
6 var sk ipSp la sh :Bool = fa l se ; //no muestre e l l o g u i t o de f l i x e l .
42
-
7.2. La clase Playstate.hx
PlayState Hereda de la clase FlxState, y sobreescribe los mtodos create y update:
7.2.1. Atributos
1 class PlayState extends FlxState
2 {
3 private stat ic inl ine var BAT_SPEED: Int = 350 ;
4
5 private var _bat :FlxSprite ;
6 private var _ball :FlxSprite ;
7
8 private var _walls :FlxGroup ;
9 private var _leftWal l :FlxSprite ;
10 private var _rightWall :FlxSprite ;
11 private var _topWall :FlxSprite ;
12 private var _bottomWall :FlxSprite ;
13
14 private var _bricks :FlxGroup ;
7.2.2. Mtodo Create
1 /* Funcin de inicializacin de todos l o s recur sos y a p o s t e r i o r i l o s
agregamos a l estado , l a s paredes l a s inc lu imos en e l grupo
_wal ls y l o s l a d r i l l o s tambin l o s inc lu imos en e l grupo
_bricks Esto es una tcnica u t i l i z a d a en haxe para s im p l i f i c a r
e l tema de l a s c o l i s i o n e s
2 */
3 override public function c r e a t e ( ) :Void
4 {
5 // Escondemos e l Mouse
6 FlxG . mouse . v i s i b l e = fa l se ;
7
8 //Cramos e l ba te
9 _bat = new FlxSpr i t e (180 , 220) ;
10 _bat . makeGraphic (40 , 6 , FlxColor .HOT_PINK) ;
11 _bat . immovable = true ;
12
13 //Creamos l a bo l a
14 _ball = new FlxSpr i t e (180 , 160) ;
15 _ball . makeGraphic (6 , 6 , FlxColor .HOT_PINK) ;
16 _ball . e l a s t i c i t y = 1 ;
17 _ball . maxVelocity . s e t (200 , 200) ;
18 _ball . v e l o c i t y . y = 200 ;
19
20 // Ut i l i z a remos e l grupo wa l l s para s im p l i f i c a r e l tema de l a s
c o l i s i o n e s
21 _walls = new FlxGroup ( ) ;
43
-
22
23
24 //Pared I z qu i e r da
25 _leftWal l = new FlxSpr i t e (0 , 0) ;
26 _leftWal l . makeGraphic (10 , 240 , FlxColor .GRAY) ;
27 _leftWal l . immovable = true ;
28 _walls . add ( _leftWal l ) ;
29
30 //Pared Derecha
31 _rightWall = new FlxSpr i t e (310 , 0) ;
32 _rightWall . makeGraphic (10 , 240 , FlxColor .GRAY) ;
33 _rightWall . immovable = true ;
34 _walls . add ( _rightWall ) ;
35
36 //Pared de Arriba = Techo
37 _topWall = new FlxSpr i t e (0 , 0) ;
38 _topWall . makeGraphic (320 , 10 , FlxColor .GRAY) ;
39 _topWall . immovable = true ;
40 _walls . add (_topWall ) ;
41
42 //Pared de Abajo = Piso
43 _bottomWall = new FlxSpr i t e (0 , 239) ;
44 _bottomWall . makeGraphic (320 , 10 , FlxColor .TRANSPARENT) ;
45 _bottomWall . immovable = true ;
46 _walls . add (_bottomWall ) ;
47
48 // Some b r i c k s , creamos l o s l a d r i l l o s o b r i c k s a rromper
49 _bricks = new FlxGroup ( ) ;
50
51 var bx : Int = 10 ;
52 var by : Int = 30 ;
53
54 var br i ckCo lour s :Array = [0 xffd03ad1 , 0 x f f f 75352 , 0
x f f fd8014 , 0 x f f f f 9 0 2 4 , 0 xf f05b320 , 0 x f f 6d65 f 6 ] ;
55
56 for ( y in 0 . . . 6 ) {
57 for ( x in 0 . . . 2 0 ) {
58 var tempBrick :FlxSprite = new FlxSpr i t e (bx , by ) ;
59 tempBrick . makeGraphic (15 , 15 , br i ckCo lour s [ y ] ) ;
60 tempBrick . immovable = true ;
61 _bricks . add ( tempBrick ) ;
62 bx += 15 ;
63 }
64 bx = 10 ;
65 by += 15 ;
66 }
67
68 // Agregamos a l e s tado todos l o s s p r i t e s que creamos
69
70 add ( _walls ) ;
71 add (_bat ) ;
44
-
72 add ( _ball ) ;
73 add ( _bricks ) ;
74 }
7.2.3. Mtodo Update
1 override public function update ( ) :Void
2 {
3 super . update ( ) ;
4 /* En cada l lamado a l a funcin update , seteamos l a v e l o c i dad
de l ba t e a 0 e s t o es para que de j e de moverse s i no
c l i ckeamos una direccin
5 */
6 _bat . v e l o c i t y . x = 0 ;
7
8 /* Unas lneas de cdigo para d i s p o s i t i v o s tctiles ( u t i l i z a n d o
compilacin cond i c i ona l ) , l a idea de movimiento d e l ba t e es
t r a s l a d a r s e d irec tamente a donde toc y s i hace un
movimiento descendente con e l de to reseteamos e l e s tado .
9 */
10 #if !FLX_NO_TOUCH
11 for ( touch in FlxG . touches . l i s t ) {
12 i f ( touch . pre s s ed ) {
13 i f ( touch . x > 10 && touch . x < 270)
14 _bat . x = touch . x ;
15 }
16 }
17
18 for ( swipe in FlxG . swipes ) {
19 i f ( swipe . d i s t anc e > 100) {
20 i f ( ( swipe . ang le < 10 && swipe . ang le > 10) | | (swipe . ang le > 170 | | swipe . ang le < 170) ) {21 FlxG . r e s e t S t a t e ( ) ;
22 }
23 }
24 }
25 #end
26
27
28 /*
29 La idea a p o s t e r i o r i es escuchar l a s t e c l a s ( i zq , a ) ( der , b ) , s iocurri un evento a l teramos l a ve l oc idad , d e l ba te en esa
direccin con e l v a l o r bat_speed
30 */
31 i f (FlxG . keys . anyPressed ( [ "LEFT" , "A" ] ) && _bat . x > 10) {
32 _bat . v e l o c i t y . x = BAT_SPEED;33 } else i f (FlxG . keys . anyPressed ( [ "RIGHT" , "D" ] ) && _bat . x < 270) {
34 _bat . v e l o c i t y . x = BAT_SPEED;
35 }
36 // Si apret l a l e t r a R reseteamos e l Juego .
45
-
37 i f (FlxG . keys . j u s tRe l ea s ed .R) {
38 FlxG . r e s e t S t a t e ( ) ;
39 }
40 i f (_bat . x < 10) {
41 _bat . x = 10 ;
42 }
43 i f (_bat . x > 270) {
44 _bat . x = 270 ;
45 }
46
47 /* Finalmente detectamos l a s c o l i s i o n e s
48
49 Recordamos que l a funcin c o l l i d e , u t i l i z a l a colisin fsica en t re l o s
s p r i t e s , es d e c i r que e l funcionamiento luego d e l choque ya
est d e f i n i d o por sus a t r i b u t o s .
50 En e l caso de l a s c o l i s i o n e s en t re ( b a l l , b r i c k s ) se d e f i n e l a
funcin c a l l b a c k h i t .
51 En e l caso de l a s c o l i s i o n e s en t re ( b a l l , ba t ) se d e f i n e l a funcin
c a l l b a c k ping .
52 */
53
54 FlxG . c o l l i d e ( _ball , _walls ) ;
55 FlxG . c o l l i d e (_bat , _ball , ping ) ;
56 FlxG . c o l l i d e ( _ball , _bricks , h i t ) ;
57 }
7.2.4. Funciones Callback
1 private function h i t ( Ba l l :FlxObject , Brick :FlxObject) :Void
2 {
3 Brick . e x i s t s = fa l se ;
4 }
5
6 private function ping (Bat :FlxObject , Ba l l :FlxObject) :Void
7 {
8 var batmid : Int = Std . int (Bat . x ) + 20 ;
9 var bal lmid : Int = Std . int ( Ba l l . x ) + 3 ;
10 var d i f f : Int ;
11
12 i f ( ba l lmid < batmid ) {
13 // Ba l l i s on the l e f t o f the ba t
14 d i f f = batmid bal lmid ;15 Ba l l . v e l o c i t y . x = ( 10 * d i f f ) ;16 } else i f ( ba l lmid > batmid ) {
17 // Ba l l on the r i g h t o f the ba t
18 d i f f = bal lmid batmid ;19 Ba l l . v e l o c i t y . x = (10 * d i f f ) ;
20 } else {
21 // Ba l l i s p e r f e c t l y in the middle
22 // A l i t t l e random X to s top i t bouncing up !
46
-
23 Ba l l . v e l o c i t y . x = 2 + FlxRandom . intRanged (0 , 8) ;
24 }
25 }
26 }
7.3. Tarea
Como podrn haber visto todava le faltan ciertos features para decir que es un juego,
por esto se proponen las siguientes actividades.
1. Agregar al juego un sistema de vidas y por lo tanto que se pueda perder.
2. Inventar tu propio sistema de puntaje e implementarlo.
3. Corregir movimiento de bate, es decir si ahora se teclean las 2 teclas juntas (izquierda,
derecha), el juego responde slo a un input en el update.
4. Modicar el random de la funcin Ping cuando cae al medio, a gusto.
5. Agregar un estado GameOver.hx que muestre el puntaje cuando perds todas tus
vidas.
6. Agregar un Nivel.
47
-
8. Imgenes y Animaciones
Now is not the time to use that!
Profesor Oak.
Vimos cmo crear sprites a partir de guras geomtricas usando el mtodo MakeGraph-
ic(). Explicaremos ahora cmo generar sprites animados a partir de un sprite sheet.
Tambin veremos cmo se usa la tcnica Recyling para hacer un juego ms eciente.
8.1. Sprites a partir de imgenes
Para cargar una imagen a un Sprite usamos la siguiente funcin:
1 loadGraphic ( Graphic : Dynamic , ?Animated : Bool , ?Reverse : Bool , ?
2 Width : Int , ?Height : Int , ?Unique : Bool , ?Key : String) : FlxSprite
Para cargar una imagen no animada se usa slo el primer argumento al cual le pasamos
el path de la imagen que queremos cargar, por ejemplo:
1 var _ship : FlxSprite ;2 _ship = new FlxSpr i t e (x , y ) ;
3 _ship . loadGraphic ( " a s s e t s / sh ip . png" ) ;
4 add (_ship ) ;
8.2. Animaciones
Para cargar una animacin a un sprite, tambin usamos la funcin loadGraphic.
La diferencia es que vamos a necesitar lo que se llama un sprite sheet que consiste
de una serie de imgenes o frames separados que formarn distintas animaciones.
Por ejemplo, uno de los sprite sheets de Sonic 2 tendra esta pinta:
Figura 9: Sprite sheet del Sonic 2
48
-
Para ver una animacin en nuestro juego a partir de un sprite sheet, necesitamos
intercambiar la imagen que se ve en pantalla por la imagen que le sigue en el sprite sheet
hasta llegar a la ltima y volver a repetir la animacin si hace falta.
Todo esto a un cierto frame rate, que no va a ser el mismo al cual corre el juego. Si los
sprites de Sonic cambiaran a 60 FPS necesitaramos tener muchos ms sprites para evitar
que la animacin se vea ultra acelerada. Es por eso que las animaciones corren a su
propio FrameRate.
Ahora, veamos como usar la funcin loadGraphic() para cargar una animacin.
1 loadGraphic ( Graphic : Dynamic , ?Animated : Bool , ?Width : Int , ?
2 Height : Int , ?Unique : Bool , ?Key : String) : FlxSprite
Graphic: es de tipo Dynamic, pero por ahora nosotros le vamos a pasar un String
que contenga el path de la imagen que queremos usar.
Animated: indica si la imagen es una sola imagen o si tiene una animacin.
Width: el ancho de cada uno de los frames de la animacin.
Height: la altura de cada uno de los frames de la animacin.
Ejemplo:
1 var _thie f : FlxSprite ;2 _th ie f = new FlxSpr i t e (x , y ) ;
3 _th ie f . loadGraphic ( " a s s e t s / t h i e f . png" , true , 9 0 , 9 0 ) ;
4 add ( _thie f ) ;
Figura 10: Ladrn
49
-
8.2.1. Comportamientos
No alcanza con slo cargar una sprite sheet para hacer una animacin, hace falta
denir comportamientos. Habrn notado que en distintas partes del sprite sheet trataban
distintos comportamientos de Sonic. Es decir, en una parte est empujando, en otra
haciendo el giro, en otra esperando, etc. Esto se llama comportamiento y es una forma
muy prctica que nos permite Haxeixel de organizar nuestro sprite sheet. Para agregar
un comportamiento a un Sprite usamos el siguiente mtodo:
1 animation . add (Name : String , Frames : Array, ?FrameRate : Int , ?
Looped : Bool)
Donde animation es un campo del Sprite que contiene nuestras animaciones.
Name: indica el nombre del nuevo comportamiento para referenciarlo luego.
Frames: un arreglo de nmeros indicando qu frames van a ser usados en este com-
portamiento y en qu orden.
FrameRate: establecemos el framerate al cual va correr este comportamiento. (As
es, distintos comportamientos pueden tener distintos framerates.)
Looped: indica si el comportamiento deber repetirse o slo ejecutarse una vez.
Ejemplo:
1 var _thie f : FlxSprite ;2 _th ie f = new FlxSpr i t e (x , y ) ;
3 _th ie f . loadGraphic ( " a s s e t s / t h i e f . png" , true , 9 0 , 9 0 ) ;
4 _th ie f . animation . add ( " d e f au l t " , [ 0 , 1 , 2 ] , 16 , true ) ;
5 _th ie f . animation . play ( " d e f au l t " ) ;
6 add ( _thie f ) ;
En nuestro ejemplo del ladrn, este comportamiento dice que se van a ver los frames
0,1,2 en ese orden a 16 frames por segundo y se va repetir indenidamente.
El mtodo play() recibe como argumento uno de los nombres de comportamientos que
se haya declarado anteriormente y lo anima.
Si no llamamos al mtodo play no se animar ningn comportamiento.
50
-
9. Tiempo de carga, Loaders
When problem solving is removed from a game, it
ceases to be a game and becomes just an activity.
Jesse Schell - The Art of Game Design
Dado que cargar una imagen lleva un cierto tiempo, tiempo en el cual el procesador
est ocupado, y nuestro juego no se actualiza. Ahora qu pasa si nuestro juego tiene
que cargar una cantidad grande de imgenes? Vamos a empezar a notarlo, a veces lo
pueden ver en juegos cuando recin empieza que, por unos segundos, todo anda ms lento
y despus arranca y anda bien.
Una manera de resolver esto es usando un loader, que detallaremos a continuacin. A
su vez tenemos otro problema al cargar imgenes, qu vamos a hacer con los recursos que
son creados indenidamente? Por ejemplo, balas, enemigos, misiles, etc. No nos alcanza
la memoria para crearlos todos al principio, porque podran ser innitos. La idea de ir
creando los recursos y destruirlos segn la necesidad, pero como ya vimos, eso produce un
tiempo de carga que puede relentizar nuestro juego. La solucin a este segundo problema
es el Recyling, que tambin explicaremos a continuacin.
9.1. Loading
La idea de loading es muy simple, slo empezar el juego despus de que todos los
recursos estn cargados. Estas son las famosas loading screens que vemos en todos los
juegos.
Figura 11: Loading Screens
51
-
Una opcin es mostrar una imagen ja al jugador mientras el juego se carga. Pero una
solucin ms esttica es mostrar al jugador una barra a medida que se cargan los recursos.
Normalmente para realizar esto necesitaramos trabajar con hilos. Un hilo tendra que
estar cargando los recursos mientras otro actualiza la barra de loading.
9.1.1. La clase: FlxAsyncLoop
Por suerte HaxeFlixel nos provee la clase FlxAsyncLoop, que simplica mucho esto.
Se usa de la siguiente manera:
1 new FlxAsyncLoop(Iterations : Int, Callback : Void Void, IterationsPerUpdate : Int);
Es bsicamente un loop que llama a la funcin Callback, una cantidad de veces igual
a Iterations, haciendo IterationsPerUpdate cantidad de iteraciones en cada update.
O sea que la carga de recursos se tiene que hacer dentro de la funcin Callback. Y esta
funcin tiene que comportarse de manera iterativa.
No nos sirve de nada una funcin que trata de cargar todos los recursos en una iteracin,
esto sera lo mismo que no usar esta funcin.
9.2. Analizando la Demo: FlxAsyncLoop
Podemos ver la demo entera en: http://haxeflixel.com/demos/FlxAsyncLoop/
9.2.1. La Clase Main.hx
Lo nico interesante para observar en la clase Main.hx es cmo dene las dimensiones
del juego, su frame rate y el estado Inicial que va a llamarse cuando se ejecute Main:
MenuState.
1 class Main extends Sp r i t e {
2 var gameWidth : Int = 640 ;
3 var gameHeight : Int = 480 ;
4 var i n i t i a l S t a t e :Class = MenuState ;
5 var f ramerate : Int = 60 ;
6 . . .
7 }
9.2.2. La clase MenuState
Imports:
1 package ;
2 import f l i x e l . addons . u t i l . FlxAsyncLoop ;
3 import f l i x e l . FlxG ;
4 import f l i x e l . F lxSpr i t e ;
5 import f l i x e l . F lxState ;
6 import f l i x e l . group . FlxGroup ;
7 import f l i x e l . t ex t . FlxText ;
52
-
8 import f l i x e l . u i . FlxBar ;
9 import f l i x e l . u t i l . F lxCo lo rUt i l ;
10 import f l i x e l . u t i l . FlxRandom ;
11 import f l i x e l . u t i l . F l xSp r i t eU t i l ;
Atributos:
1
2 /* Creamos nues t ros drops grupos , uno para mostrar barra de progreso
y o t ra que tenga l o que estemos por cargar : grpFin i shed */private
var _grpProgress : FlxGroup ;
3 private var _grpFinished :FlxGroup ;
4 private var _loopOne :FlxAsyncLoop ;
5 private var _maxItems : Int = 5000 ;
6
7 // Creamos una fancy progre s s bar
8 private var _bar :FlxBar ;
9
10 // Agregamos una Barra de Texto a l a Barra de Progreso
11 private var _barText :FlxText ;
Mtodo Create:
1 override public function c r e a t e ( ) :Void {
2 _grpProgress = new FlxGroup ( ) ;
3 _grpFinished = new FlxGroup (_maxItems ) ;
4
5 // Creamos nues tro Cic lo de Carga
6 _loopOne = new FlxAsyncLoop (_maxItems , addItem , 100) ;
7
8 _bar = new FlxBar (0 , 0 , FlxBar .FILL_LEFT_TO_RIGHT, FlxG . width 50 ,50 , null , "" , 0 , 100 , true ) ;
9 _bar . currentValue = 0 ;
10 F l xSp r i t eUt i l . s c reenCenter (_bar ) ;
11 _grpProgress . add (_bar ) ;
12
13 var aux = "Loading . . . 0 / " ;
14 _barText = new FlxText (0 , 0 , FlxG . width , aux + _maxItems ) ;
15