Anda di halaman 1dari 95

Curso de Videojuegos en 2D

Peralta Rodrigo
8 de julio de 2014

ndice
1. Qu es y cmo se hace un videojuego?

1.1.

Qu es un videojuego? . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.2.

Qu diferencia a un juego de otro? . . . . . . . . . . . . . . . . . . . . . .

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.6.

1.7.

1.5.1.

Interfaz

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

1.5.2.

Recursos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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?

. . . . . . . . . . . . . . . . . . .

2.2.

Qu es Haxe? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

18

2.3.

Instalacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

18

2.4.

Eligiendo un IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

18

3. Hello World en Haxe


3.1.

17

19

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

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

20

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

. . . . . . . . . . . . . . . . . . .

30

3.18.3. Funciones en variables Dinmicas

4. Arquitectura de un videojuego
4.1.

Game Loop

31

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.1.1.

Frames Por Segundo (FPS)

. . . . . . . . . . . . . . . . . . . . . .

4.1.2.

Manejando FPS en Haxeixel

31
32

. . . . . . . . . . . . . . . . . . . . .

34

4.2.

Manejando Render() en Haxeixel . . . . . . . . . . . . . . . . . . . . . . .

35

4.3.

Eventos

35

4.4.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.3.1.

Event Dispatcher

4.3.2.

Event Handler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

36

4.3.3.

Manejando Input en Haxeixel

. . . . . . . . . . . . . . . . . . . .

36

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

37

Estados de Juego

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

5. Sprites: La clase FlxSprite

36

39

5.1.

Mtodos importantes de FlxSprite . . . . . . . . . . . . . . . . . . . . . . .

39

5.2.

Algunos atributos de FlxSprite

39

. . . . . . . . . . . . . . . . . . . . . . . .

6. Proyectos en Haxeixel

41

7. BreakOut
7.1.
7.2.

7.3.

Main.hx . . .
La clase Playstate.hx
La clase

42
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

42

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

43

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

43

7.2.1.

Atributos

7.2.2.

Mtodo Create

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

43

7.2.3.

Mtodo Update . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

45

7.2.4.

Funciones Callback . . . . . . . . . . . . . . . . . . . . . . . . . . .

46

Tarea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

47

8. Imgenes y Animaciones

48

8.1.

Sprites a partir de imgenes

. . . . . . . . . . . . . . . . . . . . . . . . . .

48

8.2.

Animaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

48

8.2.1.

50

Comportamientos . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9. Tiempo de carga, Loaders


9.1.

Loading
9.1.1.

9.2.

51

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

La clase: FlxAsyncLoop

. . . . . . . . . . . . . . . . . . . . . . . .

51
52

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.Sonidos y Msica

63

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
11.1. La clase: FlxSave

68
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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
13.1. Pixel Perfect Collision

75
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.2. Efectos sobre nuestros Sprites


13.2.1. FlxTween

75

. . . . . . . . . . . . . . . . . . . . . . . . .

75

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

75

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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


14.1.1. Mtodos de FlxTileMap
14.1.2. FlxTimeMapExt
14.1.3. FlxCaveGenerator

. . . . . . . . . . . . . . . . . . . . . . . .

84

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

86

. . . . . . . . . . . . . . . . . . . . . . . . . . .

86

15.Comunidad
15.1. Comercializacin

84

88
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

89

15.1.1. Publicidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

89

15.1.2. Sponsors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

89

15.1.3. Tiendas Online

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

90

15.1.4. Venta Directa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

90

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

90

15.2. Redes Sociales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.1.5. Tiendas Indie

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

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:

illbelemaxi@gmail.com por

cualquier duda o correccin del mismo.


Illbele Maximiliano.

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 grca, 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


solo en su casa

que es recomendable intentar abandonar la idea del oo programando

e intentando hacer todo, dando el paso inicial con el desarrollo de juegos, hacia el difcil
camino del

trabajo en equipo1 .

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 .


Ninguno es mejor que otro, simplemente son juegos muy distintos, que apuntan a

pblicos

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 interactivos. Digo fuertemente porque un libro puede ser interactivo o una obra de teatro
puede involucrar al pblico, pero un videojuego depende completamente de la interaccin con el jugador para entretenerlo.
diferentes. Pero la clave es la siguiente:

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

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 , 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 .

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.

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 .

Figura 1: Screen Shot del Multitask

5 http://www.kongregate.com/games/icylime/multitask

Recursos: imgenes y sonidos.


Los recursos son los objetos sobre los cuales podemos realizar cambios para interactuar 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

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 interfaces 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 , 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 interfaz 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 .

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.

una plataforma es una tecnologa que permite la creacin de


juegos y como toda tecnologa, tiene sus lmites. De todos modos la cantidad de
En conclusin:

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 falta, 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 .
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 simplicar 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.loadF romF ile(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 arquitectura 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 . 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

2.

10 .

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 complicadas, 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 presentamos 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 recomiendo 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-

11 . Si se les complica mucho instalarlo

ux, no deberan hacerse los inteligentes y usar Linux

12 .

y usan Mac, deberan sentirse mal por usar Mac

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

static

function main ( )

trace (" hello

world " ) ;

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<0>:

null.

3.1.2. Operadores Binarios y Unarios


Asignacin: =, +=, *=, -=... (La asignacin devuelve el valor, permite hacer cadenas).
Comparacin: ==, <=, <, >, >=.
Operadores Aritmticos: +, -, *, /, %.

&&, ||.
Bitwise: |, &, >>, <<, >>>.
Unarios: !, , ++, .

Operadores Booleanos:
Operadores
Operadores

3.1.3. Bloques
Los bloques son importantes en Haxe, herramienta til para simplicar algunas expresiones. 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

static

function main ( )

Void

Void

2 {
3

var

s =

String ;

i f ( true ) {

" Vrai " ;

" Faux " ;

else

trace ( s ) ;

10 }

En otros lenguajes sera:


1 public

static

function main ( )

2 {
3

var

i f ( true ) {

String ;

s = " Vrai " ;

else

s = " Faux " ;

trace ( 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 varN ame[: varT ype][= 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 varN ame [: varT ype][= 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

var

5
6

static

function main ( )

myNumber

Int = 1 5 ;

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

static

function main ( )

var

myNumber = 2 ;

myNumber

Int = 1 5 ;

t r a c e ( myNumber ) ;

var

9
10

myNumber

// T r a c e s

Int = 1;

t r a c e ( myNumber ) ;

11

// T r a c e s

12

t r a c e ( myNumber ) ;

13

// T r a c e s

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

sayHelloT o

de un objeto llamado

user.sayHelloT o(00 M r00 ,00 Benjamin00 );

21

user.

3.4. Construyendo una instancia de una clase


Se usa la palabra clave
1

var

user =

new

new:

U s e r ( "Mr" , " B e n j a m i n " ) ;

Un ejemplo de la clase User podra ser:


1 class

User

2 {

p u b l i c function new ( t i t l e

3
4

//Do

String ,

name

String ) {

things

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

3 }

else

t r a c e ( "You

5 }

else

are

young " ) ;

i f ( a g e >= 16 && a g e < 1 8 ) {


are

almost

are

an

an

adult " ) ;

t r a c e ( "You

adult ") ;

7 }

Tambin podemos usar lo que aprendimos de bloques:


1

var

age = 1 8 ;

2 trace (

i f ( a g e <18) {

3
4

"You

are

not

are

an

an

adult . " ;

} else {

5
6

"You

adult " ;

8 );

3.6. Switch
1 switch ( t i t l e ) {

case

2
3

"Mr" :
t r a c e ( "You

case

4
5

"Ms" ,

are

man" ) ;

" Melle " :

t r a c e ( "You

are

a woman" ) ;

default :

6
7

trace ("I

don ' t

know

if

you

are

a man

or

a woman" ) ;

8 }

Si hay ms de un valor con el cual comparar debera ser separado por comas. Notar
que

no hay break ya que slo un caso es llamado.


22

3.7. While
Hay dos syntax posibles. El while loop normal:
1 while ( c o n d i t i o n ) {
2

exprToBeExecuted ;

3 }

Y el do while:
1 do {
2

exprToBeExecuted ;

3 } while ( c o n d i t i o n ) ;

Ejemplos:
1 while ( i < 1 8 ) {
2

trace ( i ) ;

i ++;

// W i l l

trace

numbers

from

to

17

included

// W i l l

trace

numbers

from

to

17

included

4 }

1 do {
2

trace ( i ) ;

i ++;

4 }

while ( i < 1 8 ) ;

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
2

in

0...10){

trace ( i ) ;

//

Will

trace

numbers

from

to

3 }

Nota:

0 . . . 10

es una construccin especial. El operador

...

recibe dos int y devuelve

13 que devolver todos los int desde el primero (incluido) hasta el ltimo
un interador
(excluido).
Esta construccin es particularmente til para iterar sobre listas y arreglos.
Por ejemplo:
1 class

Te sth aXe

2 {
3

public

static

function main ( ) :

var

l . add ( " H e l l o " ) ;

= new

Void

L i s t <S t r i n g >() ;

13 Error Chistoso!

23

l . add ( " World " ) ;

for ( s

in

l ){

neko . Lib . p r i n t l n ( s ) ;

10

11

12 }

3.9. Break y Continue


break es usada para salir de un ciclo prematuramente.
La palabra continue es usada para ir directamente a la siguente iteracin de nuestro
La palabra

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 annimas. Son valores que pueden ser asignados a cualquier variable, por ejemplo:
1 public

class

User

2 {
3

var

p u b l i c function new ( )

sayHello

: String

Void ;

s a y H e l l o = function ( t o

t r a c e ( " Hello " + to ) ;

};

String )

s a y H e l l o ( " World " ) ;

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
1 #i f

cpp

//C++ c o d e

#if

3 #elseif neko
4

// Neko

code

5 #elseif php
6

//PHP

code

7 #e l s e
8

// Code

for

other

targets

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 : T ypeOf M yV ariable;

3.14.2. Tipado esttico


En Haxe, una vez que una variable ha sido declarada y se sabe su tipo, no es posible 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 {

public

static

function main ( )

var

e = " String " ;

var

e = 12;

e
e

:
:

String ;
Int ;

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

static

function main ( )

var

e = " Test " ;

String ;

e = 12;

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

static

function main ( ) {

var

human = new HumanBeing ( " B e n j a m i n " ) ;

HumanBeing ;

c o n g r a t u l a t e ( human ) ;

public

9
10

human

static

function

t r a c e ( " Congrats

congratulate ( l t

" +

LivingThing )

l t . name ) ;

14 I.M: Por eso los programadores de Videojuegos lo hacen en las Game Jam en 24Hs.
26

11 }
12
13 c l a s s

LivingThing

14 {

var

15

public

16

p u b l i c function new ( )

17

name

String ;
{

name = " " ;

18

19 }
20
21 c l a s s

HumanBeing extends

LivingThing

22 {
23

p u b l i c function new ( name

24

25

super () ;

26

t h i s . name = name ;

27

String )

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

outputString ( st

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 oid
Otro ejemplo, la funcin:

public function sumAndCeil(a : Float, b : Int) : Int;


Tiene tipo:

F loat 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.f ilter.
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 f ilter(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 takesStringReturnsF unction(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:

takesStringReturnsF unction(Hello)(W orld);

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 desconocido, su tipo ser inferido como el tipo de el valor asignado, as que por ejemplo,
si escribs:
1

var

s;

2 s = " Hello

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
2

var
var

s;
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 {

static

3
4

function

print ( s

String )

trace ( s ) ;

public

var

8
9

static

function main ( )

t;

print ( 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 {

public

static

function main ( )

var

dynamicVar = " H e l l o " ;

dynamicVar = 1 2 3 ;

dynamicVar = {name : " John " ,

dynamicVar = new Array<S t r i n g >() ;

dynamicVar

Dynamic ;

lastName

" Doe " } ;

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 {

public

static

function main ( )

var
var

dynamicVar = " H e l l o " ;

dynamicVar
year

Dynamic ;

Int ;

y e a r = dynamicVar ;

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 {

public

static

function main ( )

var

dynamicVar = function

dynamicVar

Dynamic ;
( name

String )

t r a c e ( " H e l l o " + name ) ;

};

dynamicVar ( ) ;

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 . i s O p e n ( ) )
2

ProcessInput () ;

Update ( ) ;

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 constante.

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 . i s O p e n ( ) )
2 {
3

t i m e S i n c e L a s t U p d a t e += c l o c k . r e s t a r t ( ) ;

while ( t i m e S i n c e L a s t U p d a t e > TimePerFrame )

timeSinceLastUpdate

ProcessInput () ;

Update ( TimePerFrame ) ;

TimePerFrame ;

10

Render ( ) ;

11 }

La condicin

(timeSinceLastU pdate > T imeP erF rame)

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 u p d a t e ( )

2 {

t h i s . x += 1 ;

3
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 u p d a t e ( TimePerFrame :

Float )

2 {

t h i s . x += 6 0 * TimePerFrame ;

3
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 f rameRate : 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:

F lxG.elapsed
34

Gracias a esto nuestro game loop volvera a:


1 while ( mWindow . i s O p e n ( ) )
2

processInput () ;

update ( ) ;

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(newF lxT ext(0, 0, 100, Hello W orld!));


Por lo tanto nuestro game loop queda:
1 while ( mWindow . i s O p e n ( ) )
2

processInput () ;

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
2

Lib.current.stage.addEventListener(M ouseEvent.M OU SE _DOW N, mouseP ressed);


Lib.current.stage.addEventListener(M ouseEvent.M OU SE _U P, mouseReleased);

3
4 private
5

function m o u s e P r e s s e d

firing

( e v e n t : MouseEvent )

Void {

= true ;

6 }
7
8 private
9

function m o u s e R e l e a s e d

firing

( e v e n t : MouseEvent )

Void {

= false ;

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 if
2

( FlxG . k e y s . p r e s s e d .DOWN)
// h a g a

algo

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 . i s O p e n ( ) )
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 representado 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:

F lxG.switchState(newP layState());

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 incrementa 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, siempre y cuando nos acordemos de llamar al mtodo

40

super.update().

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:

f lixel tpl n N ombre


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 opciones 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/.

https://github.com/HaxeFlixel/flixel-demos/tree/dev/Arcade%20Classics/
Breakout.

Cdigo:

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 = 3 2 0 ;

//

Ancho

del

juego

en

pixels

Alto

del

juego

en

pixels

2 var

g a m e H e i g h t : Int = 2 4 0 ;

3 var

i n i t i a l S t a t e : Class<FlxState> = P l a y S t a t e ;

4 var zoom : Float =

1;

//

se

//

acomode

5 var

f r a m e r a t e : Int = 6 0 ;

6 var

s k i p S p l a s h : Bool = f a l s e ;

// no

las

Estado

dimensiones

muestre

42

//

el

loguito

de

de

inicial .
pantalla

flixel .

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

extends FlxState

PlayState

2 {
3

private

static

inline

var BAT_SPEED : I n t = 3 5 0 ;

4
5

p r i v a t e var _bat : FlxSprite ;

p r i v a t e var

_ b a l l : FlxSprite ;

7
8

p r i v a t e var _ w a l l s : FlxGroup ;

p r i v a t e var

_ l e f t W a l l : FlxSprite ;

10

p r i v a t e var _ r i g h t W a l l : FlxSprite ;

11

p r i v a t e var _topWall : FlxSprite ;

12

p r i v a t e var _bottomWall : FlxSprite ;

13
14

p r i v a t e var

_ b r i c k s : FlxGroup ;

7.2.2. Mtodo Create


1

Funcin

de

inicializacin

agregamos
_walls

al

Esto

el

de

tema

estado ,

los

_bricks

de

todos

las

es

una

paredes

tambin

ladrillos

las

los

tcnica

los

recursos
las

incluimos

incluimos

utilizada

en

haxe

en

posteriori
en

el

el

grupo

grupo

para

simplificar

tema

de

colisiones

*/

override p u b l i c function

//

FlxG . mouse . v i s i b l e

Escondemos

el

c r e a t e ( ) : Void
Mouse

= false ;

7
8

// Cramos

_bat = new

el

bate

FlxSprite (180 ,

10

_bat . makeGraphic ( 4 0 ,

11

_bat . immovable = true ;

6,

220) ;

F l x C o l o r . HOT_PINK) ;

12
13

// Creamos

14

_ b a l l = new

15

_ b a l l . makeGraphic ( 6 ,

16

_ball . e l a s t i c i t y

17

_ball . maxVelocity . s e t (200 ,

18

_ball . v e l o c i t y . y = 200;

la

bola

FlxSprite (180 ,
6,

160) ;

F l x C o l o r . HOT_PINK) ;

= 1;
200) ;

19
20

// U t i l i z a r e m o s

el

grupo

walls

para

colisiones

21

_ w a l l s = new FlxGroup ( ) ;

43

simplificar

el

los

las

22
23
24

// P a r e d

25

_ l e f t W a l l = new

26

_ l e f t W a l l . makeGraphic ( 1 0 ,

Izquierda

FlxSprite (0 ,

0) ;

240 ,

27

_ l e f t W a l l . immovable = true ;

28

_ w a l l s . add ( _ l e f t W a l l ) ;

F l x C o l o r .GRAY) ;

29
30

// P a r e d

31

_ r i g h t W a l l = new

32

_ r i g h t W a l l . makeGraphic ( 1 0 ,

33

_ r i g h t W a l l . immovable = true ;

34

_ w a l l s . add ( _ r i g h t W a l l ) ;

Derecha

FlxSprite (310 ,

0) ;

240 ,

F l x C o l o r .GRAY) ;

35
36

// P a r e d

37

_topWall = new

38

_topWall . makeGraphic ( 3 2 0 ,

39

_topWall . immovable = true ;

40

_ w a l l s . add ( _topWall ) ;

de

Arriba

= Techo

FlxSprite (0 ,

0) ;

10 ,

F l x C o l o r .GRAY) ;

41
42

// P a r e d

43

_bottomWall = new

44

_bottomWall . makeGraphic ( 3 2 0 ,

45

_bottomWall . immovable = true ;

46

_ w a l l s . add ( _bottomWall ) ;

de

Abajo =

Piso

FlxSprite (0 ,

239) ;

10 ,

F l x C o l o r .TRANSPARENT) ;

47
48

//

49

_ b r i c k s = new FlxGroup ( ) ;

Some

bricks

creamos

los

ladrillos

bricks

rromper

50
51

var bx : Int = 1 0 ;

52

var by : Int = 3 0 ;

53
54

var

b r i c k C o l o u r s : Array<Int> = [ 0 x f f d 0 3 a d 1 ,
xfffd8014 ,

0 xffff9024 ,

0 xff05b320 ,

0 xfff75352 ,

0 xff6d65f6 ] ;

55
56

for

( y in

for

57

0...6){

( x in

0...20){

58

var t e m p B r i c k : FlxSprite = new F l x S p r i t e ( bx ,

59

t e m p B r i c k . makeGraphic ( 1 5 ,

60

t e m p B r i c k . immovable = true ;

61

_ b r i c k s . add ( t e m p B r i c k ) ;

62

bx += 1 5 ;

63

64

bx = 1 0 ;

65
66

15 ,

by ) ;

brickColours [ y ] ) ;

by += 1 5 ;
}

67
68

//

Agregamos

al

estado

todos

69
70

add ( _ w a l l s ) ;

71

add ( _bat ) ;

44

los

sprites

que

creamos

72

add ( _ b a l l ) ;

73

add ( _ b r i c k s ) ;

74

7.2.3. Mtodo Update


1

override p u b l i c function update ( ) : Void

super . update ( ) ;

En

cada

llamado

del

bate

clickeamos

esto

una

*/

_bat . v e l o c i t y . x = 0 ;

Unas

lneas

compilacin

trasladarse

*/

10

#if

para

update ,

que

deje

seteamos
de

dispositivos

condicional ) ,

movimiento

cdigo

de

para

la

moverse

velocidad

si

no

direccin

5
7

funcin

la
es

la

directamente
descendente

idea

de

donde

con

el

tctiles

( utilizando

movimiento

toc y

deto

si

del

hace

reseteamos

bate

es

un
el

estado .

!FLX_NO_TOUCH
for

11

( touch

if

12

in

FlxG . t o u c h e s . l i s t )

( touch . p r e s s e d ) {

if

13

( t o u c h . x > 1 0 && t o u c h . x < 2 7 0 )

14

_bat . x = t o u c h . x ;

15

16

17

for

18

( swipe

if

19

in

FlxG . s w i p e s ) {

( swipe . d i s t a n c e > 100)

if

20

( ( s w i p e . a n g l e < 10 && s w i p e . a n g l e >


s w i p e . a n g l e > 170

21

||

swipe . angle <

10) | |
170) ) {

( der , b ) ,

si

FlxG . r e s e t S t a t e ( ) ;

22

23

24

25

#end

26
27

28 / *
29

La

idea

posteriori

ocurri un
30
31

direccin

*/
if

32
33

evento

con

el

es

valor

la

las

} else

if

teclas

velocidad ,

( izq , a)
del

36

//

Si

"A" ] ) && _bat . x > 1 0 )

( FlxG . k e y s . a n y P r e s s e d ( [ "RIGHT" ,

apret

la

letra

en

esa

BAT_SPEED ;
"D" ] ) && _bat . x < 2 7 0 ) {

_bat . v e l o c i t y . x = BAT_SPEED ;

35

bate

bat_speed

( FlxG . k e y s . a n y P r e s s e d ( [ "LEFT" ,
_bat . v e l o c i t y . x =

34

escuchar

alteramos

reseteamos

45

el

Juego .

37

if

38

FlxG . r e s e t S t a t e ( ) ;

39

40

if

41
}

43

if

44

( _bat . x > 2 7 0 ) {
_bat . x = 2 7 0 ;

46
47

( _bat . x < 1 0 ) {
_bat . x = 1 0 ;

42

45

( FlxG . k e y s . j u s t R e l e a s e d . R) {

Finalmente

detectamos

las

colisiones

48
49

R ec or da mo s

que

sprites ,

est
50

En

el

funcin
51

En

52

*/

el

decir

definido
caso

de

funcin

la

es

por

las

de

callback

sus

el

las

utiliza

la

funcionamiento

colisin fsica
luego

del

entre

choque

entre

( ball ,

bricks

entre

( ball ,

bat )

se

define

colisiones

se

define

53
54

FlxG . c o l l i d e ( _ b a l l ,

55

FlxG . c o l l i d e ( _bat ,

56

FlxG . c o l l i d e ( _ b a l l ,

57

_walls ) ;
_ball ,

ping ) ;

_bricks ,

hit ) ;

7.2.4. Funciones Callback


p r i v a t e function

3
4

h i t ( B a l l : FlxObject ,

Brick : FlxObject ) : Void

= false ;

Brick . e x i s t s
}

5
6

p r i v a t e function

p i n g ( Bat : FlxObject ,

B a l l : FlxObject ) : Void

var

b a t m i d : I n t = S t d . i n t ( Bat . x ) + 2 0 ;

var

b a l l m i d : I n t = Std . i n t ( B a l l . x ) + 3 ;

10

var

d i f f : Int ;

11
12

if

( b a l l m i d < batmid )

13

//

14

diff

15
16

Ball

else

if

17

//

18

diff

19
20

is

on

= batmid

the

{
left

else

the

bat

10 *

diff ) ;

( b a l l m i d > batmid ) {

Ball

on

the

= ballmid

right

of

the

bat

batmid ;

Ball . v e l o c i t y . x = (10
}

of

ballmid ;

Ball . velocity . x = (
}

diff ) ;

21

//

22

// A

Ball

la

hit .

ping .

los
ya

atributos .

colisiones

callback

caso

collide ,

que

is

little

perfectly
random X

in

the

to

stop

46

middle
it

bouncing

up !

la

funcin

23

B a l l . v e l o c i t y . x = 2 + FlxRandom . i n t R a n g e d ( 0 ,

24

8) ;

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 MakeGraphic(). Explicaremos ahora cmo generar sprites animados a partir de un
Tambin veremos cmo se usa la tcnica

sprite sheet.

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
2 Width

Int ,

? Height

Dynamic ,

:
:

Int ,

? Animated

? Unique

Bool ,

Bool ,
? Key

? Reverse

String )

:
:

Bool ,

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

2 _ s h i p = new

FlxSprite ;
FlxSprite (x , y) ;

3 _ s h i p . l o a d G r a p h i c ( " a s s e t s / s h i p . png " ) ;


4 add ( _ s h i p ) ;

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

propio FrameRate.

las animaciones corren a su

Ahora, veamos como usar la funcin loadGraphic() para cargar una animacin.
1 loadGraphic ( Graphic
2 Height

Int ,

? Unique

Dynamic ,
:

Bool ,

? Animated

? Key

String )

Bool ,
:

? Width

Int ,

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

_thief

2 _ t h i e f = new

FlxSprite ;
FlxSprite (x , y) ;

3 _ t h i e f . l o a d G r a p h i c ( " a s s e t s / t h i e f . png " ,

true , 9 0 , 9 0 ) ;

4 add ( _ t h i e 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 a n i m a t i o n . add ( Name
Looped

String ,

Frames

Array<Int >, ? FrameRate

: Int ,

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 comportamiento 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

_thief

2 _ t h i e f = new

FlxSprite ;
FlxSprite (x , y) ;

3 _ t h i e f . l o a d G r a p h i c ( " a s s e t s / t h i e f . png " ,

true , 9 0 , 9 0 ) ;

4 _ t h i e f . a n i m a t i o n . add ( " d e f a u l t " ,

2] ,

[0 ,

1,

16 ,

true ) ;

5 _thief . animation . play ( " d e f a u l t " ) ;


6 add ( _ t h i e 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 F lxAsyncLoop(Iterations : Int, Callback : Void Void, IterationsP erU pdate : 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

Sprite {

2 var gameWidth : Int = 6 4 0 ;


3 var

g a m e H e i g h t : Int = 4 8 0 ;

4 var

i n i t i a l S t a t e : Class<FlxState> = MenuState ;

5 var

f r a m e r a t e : Int = 6 0 ;

...

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 . FlxSprite ;

5 import

f l i x e l . FlxState ;

6 import

f l i x e l . g r o u p . FlxGroup ;

7 import

f l i x e l . t e x 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 . FlxColorUtil ;

10 import

f l i x e l . u t i l . FlxRandom ;

11 import

f l i x e l . util . FlxSpriteUtil ;

Atributos:
1

2 /*

Creamos
y

otra

var

nuestros
que

drops

tenga

lo

grupos ,

que

estemos

uno

para

por

mostrar

cargar :

barra

de

grpFinished

progreso

*/ p r i v a t e

_ g r p P r o g r e s s : FlxGroup ;

3 private

var _ g r p F i n i s h e d : FlxGroup ;

4 private

var _loopOne : FlxAsyncLoop ;

5 private

var _maxItems : Int = 5 0 0 0 ;

6
7 //

Creamos

8 private

una

fancy

progress

bar

var _bar : FlxBar ;

9
10 //

Agregamos

11 p r i v a t e

una

Barra

de

Texto

la

Barra

de

Progreso

var _barText : FlxText ;

Mtodo Create:
1 override public function

c r e a t e ( ) : Void {

2 _ g r p P r o g r e s s = new FlxGroup ( ) ;
3 _ g r p F i n i s h e d = new FlxGroup ( _maxItems ) ;
4
5 //

Creamos

nuestro

Ciclo

de

Carga

6 _loopOne = new F l x A s y n c L o o p ( _maxItems ,

addItem ,

100) ;

7
8 _bar = new F l x B a r ( 0 ,
50 ,

null ,

"" ,

0,

0,

100 ,

F l x B a r . FILL_LEFT_TO_RIGHT,

FlxG . w i d t h

true ) ;

9 _bar . c u r r e n t V a l u e = 0 ;
10 F l x S p r i t e U t i l . s c r e e n C e n t e r ( _bar ) ;
11 _ g r p P r o g r e s s . add ( _bar ) ;
12
13 v a r

aux = " L o a d i n g . . .

";

14 _barText = new F l x T e x t ( 0 ,

0,

15 _barText . s e t F o r m a t ( null ,
BORDER_OUTLINE,

28 ,

FlxG . w i d t h ,
0xffffff ,

aux + _maxItems ) ;

" center " ,

FlxText .

0 x000000 ) ;

16 F l x S p r i t e U t i l . s c r e e n C e n t e r ( _barText ) ;
17 _ g r p P r o g r e s s . add ( _barText ) ;
18
19 // No d e b e m o s
cargar

actualizar

el

grupo

de

fin

hasta

que

terminemos

de

todo

20 _ g r p F i n i s h e d . v i s i b l e

= false ;

21 _ g r p F i n i s h e d . a c t i v e = f a l s e ;
22
23 add ( _ g r p P r o g r e s s ) ;
24 add ( _ g r p F i n i s h e d ) ;
25
26 //

Agregamos

la

instancia

de

FlxAsyncLoop

53

Para

realizar

la

Carga

50 ,

27 add ( _loopOne ) ;
28
29 // I m p o r t a n t e :

No

olvidar

30 s u p e r . c r e a t e ( ) ;
31 }

Funcin Auxiliar, para nuestro loader, addItem()


1 public

function a d d I t e m ( ) : Void

2 {

3 / * En

cada

4 10 x 1 0

en

iteracin

una

de

nuestro

posicin y

con

ciclo ,

un

color

creamos
al

azar

un

Sprite

cuadrado

*/

5
6 var random_x = FlxRandom . i n t R a n g e d ( 0 ,

FlxG . w i d t h ) ;

7 var random_y = FlxRandom . i n t R a n g e d ( 0 ,

FlxG . h e i g h t ) ;

8 var

sprite

= new

F l x S p r i t e ( random_x , random_y ) ;

9
10 // C o l o r
11 var

al

azar

r a n d o m _ c o l o r = F l x C o l o r U t i l . getRan domColo r ( 0 ,

255 ,

255) ;

12
13 s p r i t e . makeGraphic ( 1 0 ,

1 0 , random_color

);

14 _ g r p F i n i s h e d . add ( s p r i t e ) ;
15
16 //

Actualizamos

el

valor

de

la

progreso

el

17 _bar . c u r r e n t V a l u e = ( _ g r p F i n i s h e d . members . l e n g t h

_maxItems )

" + _maxItems ;

18 _barText . t e x t = " L o a d i n g . . .

barra

de

texto

100;

"

19 _barText . t e x t += _ g r p F i n i s h e d . members . l e n g t h + "


20 F l x S p r i t e U t i l . s c r e e n C e n t e r ( _barText ) ;
21 }

Mtodo Update:
1 override public function

u p d a t e ( ) : Void {

2 //

si

3 if

( ! _loopOne . s t a r t e d ) {

el

ciclo

no

empez => p l a y

_loopOne . s t a r t ( ) ;

5 } else {
6

//

Una

vez

sprites !

if

que

termina

notar

que

el
al

ciclo ,
utilizar

( _loopOne . f i n i s h e d ) {

_grpFinished . v i s i b l e

= true ;

_grpProgress . v i s i b l e

= false ;

10

_ g r p F i n i s h e d . a c t i v e = true ;

11

_grpProgress . a c t i v e = f a l s e ;

12
13

// D e s t r u y o

14

_loopOne . k i l l ( ) ;

15

_loopOne . d e s t r o y ( ) ;

16

el

ciclo

17 }
18 s u p e r . u p d a t e ( ) ;
19 }

54

oculto

el

grupos ,

loader
se

muestro

simplifica

los

todo !

Figura 12: Al ejecutarlo, veremos en orden estas pantallas, la primera reeja el estado
Cargando indicando el avance, y la segunda el estado nal con 5000 cuadraditos ubicados
al azar de distintos colores.

9.3. Evitando problemas con: Recycling


A veces usamos una misma imagen repetidas veces y tenemos que estar creando y
destruyendo el sprite que contiene la imagen. Destruir y crear objetos es algo que puede
relentizar el funcionamiento de nuestro juego, entonces hay que tratar de limitar los recursos que se crean mientras el juego corre.
Por ejemplo las balas de una nave espacial, todas las balas son iguales. Y cada vez que
disparamos tenemos que crear un sprite para esa bala, y cada vez que una bala se va fuera
de rango o choca contra un enemigo hay que destruir ese sprite (sino, nos quedamos sin
memoria).
Pero si nos damos cuenta de que solo existen, por ejemplo, un mximo de 10 balas en
cualquier instante del juego, lo que podemos hacer es crear un FlxGroup que contiene 10
sprites de balas y simplemente ir usndolos de manera circular.
Entonces, lo nico que tendramos que hacer, es crear las 10 balas con el loader y
despus simplemente usar repetidas veces las mismas 10 balas.
1 // c r e a m o s
2

var

3 bullets
4

var

del

grupo

que

contiene

10

balas

n u m B u l l e t s : Int = 1 0 ;
= new FlxTypedGroup<FlxSprite>( n u m B u l l e t s ) ;

s p r i t e : FlxSprite ;

5 for

(i

sprite

in 0 ... n u m B u l l e t s ) {

s p r i t e . makeGraphic ( 8 ,

sprite . exists

b u l l e t s . add ( s p r i t e ) ;

= new

FlxSprite (

100 , 100) ;

2) ;

= false ;

10 }
11 add ( b u l l e t s ) ;

55

Ahora, si queremos reutilizar una de estas balas:


1 if

( FlxG . k e y s . j u s t P r e s s e d . SPACE) {

var

bullet . reset (x , y) ;

bullet . velocity .y =

b u l l e t : FlxSprite = PlayState . b u l l e t s . r e c y c l e () ;

200;

5 }

9.4. Prctico: FlxInvaders


A manera de motivacin comenzamos mostrando el juego que analizaremos:

Figura 13: Screen Shot del Juego FlxInvaders

Prctico: analizando el cdigo de FlxInvaders


Demo:

http://haxeflixel.com/demos/FlxInvaders/

56

9.4.1. Diagrama de clases

9.4.2. La clase Main


Clase creada automticamente donde seteamos el estado que queremos que corra cuando comience o se resetee el juego, mediante la lnea:
1 var

i n i t i a l S t a t e : Class<FlxState> = P l a y S t a t e ;

9.4.3. La clase PlayState


Clase principal donde se dene el juego:
Se crean los recursos:

Create.

Dene la lgica del juego:

Update.

El mtodo Create:
1 override

p u b l i c function

2 FlxG . mouse . v i s i b l e

c r e a t e ( ) : Void {

= false ;

// O c u l t a m o s

el

mouse

3
4 //
5 var

Lo

primero

que

hacemos

es

crear

Balas .

n u m P l a y e r B u l l e t s : Int = 8 ;

6 // No

olvidarse

de

inicializar

un

arreglo !

7 p l a y e r B u l l e t s = new FlxGroup ( n u m P l a y e r B u l l e t s ) ;
8 var

s p r i t e : FlxSprite ;

57

9
10 //

Creamos

una

cantidad

finita

11 f o r

(i

in 0 ...

12

//

Creamos

13

sprite

14

//

white

box

15

s p r i t e . makeGraphic ( 2 ,

8) ;

16

sprite . exists

17

//

18

p l a y e r B u l l e t s . add ( s p r i t e ) ;

de

balas

que

reciclaremos

numPlayerBullets ) {
un

= new

Create

sprite

2 x8

Agregamos

fuera

de

pantalla

( offscreen )

100 , 100) ;

FlxSprite (

= false ;
la

bala

al

grupo

de

balas

19 }
20
21 add ( p l a y e r B u l l e t s ) ;
22
23 //

Creamos

la

nave ,

que

es

el

jugador

lo

agregamos

al

estado

24 _ p l a y e r = new P l a y e r S h i p ( ) ;
25 add ( _ p l a y e r ) ;
26
27 // De
28 var

la

misma

manera :

inicializamos

los

aliens ,

incluyendo

sus

balas

n u m A l i e n B u l l e t s : Int = 3 2 ;
= new FlxGroup ( n u m A l i e n B u l l e t s ) ;

29 a l i e n B u l l e t s
30
31 f o r

(i

32

sprite

in 0 ...

33

s p r i t e . makeGraphic ( 2 ,

34

sprite . exists

35

a l i e n B u l l e t s . add ( s p r i t e ) ;

numAlienBullets ) {

= new

FlxSprite (

100 , 100) ;

8) ;

= false ;

36 }
37 add ( a l i e n B u l l e t s ) ;
38
39 //

Creamos

filas

c /u

con

10

aliens

de

un

color

los

agregamos

al

estado

40 var

n u m A l i e n s : Int = 5 0 ;

41 _ a l i e n s = new FlxGroup ( n u m A l i e n s ) ;
42 var a : Alien ;
43 var

c o l o r s : Array<Int >;

44
45 c o l o r s

GREEN,

[ F l x C o l o r . BLUE,

( F l x C o l o r . BLUE

( F l x C o l o r .GREEN |

F l x C o l o r .RED) ,

F l x C o l o r .GREEN) ,

FlxColor .

F l x C o l o r .RED ] ;

46
47 f o r

(i

48

a = new

in 0 ... n u m A l i e n s ) {
Alien (8 + ( i

c o l o r s [ Std . i n t ( i
49

% 10)
/

10) ] ,

32 ,

24 + S t d . i n t ( i

10)

32 ,

alienBullets ) ;

_ a l i e n s . add ( a ) ;

50 }
51
52 add ( _ a l i e n s ) ;
53
54 //

Finalmente

creamos

se

como

rrompen

escudos ,

todo

al

que

recibir

consisten
un

55 _ s h i e l d s = new FlxGroup ( ) ;

58

de

disparo .

cajitas

blancas

que

56
57 f o r

(i

58

sprite

in 0 ...

64) {

= new

F l x S p r i t e ( 3 2 + 80

FlxG . h e i g h t

Std . i n t ( i

32 + ( S t d . i n t ( ( i

% 16)

/
4)

16) + ( i

% 4)

4,

4) ) ;

sprite . active = false ;

59
60

s p r i t e . makeGraphic ( 4 ,

61

_ s h i e l d s . add ( s p r i t e ) ;

4) ;

62 }
63
64 add ( _ s h i e l d s ) ;
65
66 //

Este

grupo

almacena

las

cosas

las

que

el

las

que

los

mensaje

con

el

jugador

puede

disparar !

aliens

puede

disparar !

67 _ v s P l a y e r B u l l e t s = new FlxGroup ( ) ;
68 _ v s P l a y e r B u l l e t s . add ( _ s h i e l d s ) ;
69 _ v s P l a y e r B u l l e t s . add ( _ a l i e n s ) ;
70
71 //

Este

grupo

almacena

las

cosas

72 _ v s A l i e n B u l l e t s = new FlxGroup ( ) ;
73 _ v s A l i e n B u l l e t s . add ( _ s h i e l d s ) ;
74 _ v s A l i e n B u l l e t s . add ( _ p l a y e r ) ;
75
76 //

Finalmente

77 var

agregamos

un

t : FlxText = new F l x T e x t ( 4 ,

4,

estado

FlxG . w i d t h

8,

del

juego !

statusMessage ) ;

78 t . a l i g n m e n t = " c e n t e r " ;
79 add ( t ) ;
80 }

Mtodo Update:
1 override public function
2 //

Observar

que

necesitamos
de

u p d a t e ( ) : Void {

utilizamos
el

superposicin

efecto
de

overlaps

fsico

de

la

no

colisiones

colisin

slo

sino

ya

que

capturar

4 FlxG . o v e r l a p ( a l i e n B u l l e t s ,

_vsPlayerBullets ,
_vsAlienBullets ,

stuffHitStuff ) ;

stuffHitStuff ) ;

5
olvidarse

de

llamar

al

super . update !

7 super . update ( ) ;
8
9 //
10 i f

Ahora

verificamos

las

condiciones

de

victoria

de

derrota

prdida

( ! _player . e x i s t s ) {

11

//

12

s t a t u s M e s s a g e = "YOU LOST" ;

13

FlxG . r e s e t S t a t e ( ) ;

14 } e l s e

Moriste

if

=>

seteamos

el

estado

( _ a l i e n s . g e t F i r s t E x i s t i n g ( ) == null ) {

15

//

16

s t a t u s M e s s a g e = "YOU WON" ;

17

FlxG . r e s e t S t a t e ( ) ;

Mataste

Todos

el

elementos .

3 FlxG . o v e r l a p ( p l a y e r B u l l e t s ,

6 // Jams

no

los

aliens

=> G a n a s t e

18 }
19 }

Funcin callback para denir qu sucede si se superponen dos objetos:

59

evento

1 // S i m p l e m e n t e
2 private function

eliminamos

ambos

objetos

s t u f f H i t S t u f f ( O b j e c t 1 : FlxObject ,

O b j e c t 2 : FlxObject ) : Void

3 {
4

Object1 . k i l l ( ) ;

Object2 . k i l l ( ) ;

6 }

9.4.4. La clase Alien


1 package ;
2
3 import

f l i x e l . FlxG ;

4 import

f l i x e l . FlxSprite ;

5 import

f l i x e l . g r o u p . FlxGroup ;

6 import

f l i x e l . u t i l . FlxRandom ;

7
8 class
9 //

extends FlxSprite {

Alien

Atributo

para

almacenar

el

tiempo

pasado

entre

disparos ,

para

limitarlos .

10 p r i v a t e
11 //

var _ s h o t C l o c k : Float ;

Almacenamos

12 p r i v a t e

var

la

posicin

original

para

lgica

la

del

movimiento .

_ o r i g i n a l X : Int ;

13
14
15 p u b l i c
16 //

function new (X : Int , Y : Int ,

Llamamos

17 s u p e r (X,
18 //

C o l o r : Int ,

B u l l e t s : FlxGroup ) {

super !

Y) ;

Cargamos

la

imgen

del

alien ,

19 l o a d G r a p h i c ( " a s s e t s / a l i e n . png " ,

ponemos

que

es

animado !

true ) ;

20 c o l o r = C o l o r ;
21 _ o r i g i n a l X = X ;
22 r e s e t S h o t C l o c k ( ) ;
23

24 / *

Ahora

creamos

queremos
en

para

independiente

25

una

simple

reproducir
dar

la

en

animacin " a l i e n . p n g "

orden

sensacin

alteramos

el

1 ,2 ,3 ,1
de

que

frame

se

rate

pero

de

con

poco

r a n d = Math . f l o o r ( 6 + FlxRandom . f l o a t ( )

27 t h i s . a n i m a t i o n . add ( " D e f a u l t " ,

[0 ,

1,

28
29 //

dale

play !

30 t h i s . a n i m a t i o n . p l a y ( " D e f a u l t " ) ;
31
32 v e l o c i t y . x = 1 0 ;
33 }
34
35 override public function

u p d a t e ( ) : Void {

60

0,

los

mueven

*/

26 var

contiene

claro

2] ,

un

4) ;

rand ) ;

frames

nidices

manera
de

azar

arrancan

36 //

Si

los

aliens

ca mbi amos

37 i f

se

la

movieron

velocidad

( x < _originalX

38

x = _originalX

39

velocity .x =

40

v e l o c i t y . y++;

demasiado

para

el

de

otro

su

posicin

inicial

le

lado

8) {
8;

v e l o c i t y

.x;

41 }
42
43 //

Lo

44 i f

( x > _originalX + 8) {

mismo

en

el

otro

lado ,

45

x = _originalX + 8;

46

velocity .x =

v e l o c i t y

es

decir

simulamos

paredes

.x;

47 }
48
49 //

Comenzamos

contar

el

tiempo

cuando

pasamos

cierta

lnea

imaginaria

horizontal

50 i f
51

( y > FlxG . h e i g h t
_shotClock

0.35) {

FlxG . e l a p s e d ;

52 }
53
54
55 i f
56

( _ s h o t C l o c k <= 0 ) {
//

Si

puedo

disparar ,

velocidad . y

disparo

es

decir

reciclo

una

bala

con

positiva

57

resetShotClock () ;

58

var

59

b u l l e t . r e s e t ( x + width

60

bullet . velocity . y = 65;

b u l l e t : FlxSprite = c a s t ( c a s t ( FlxG . s t a t e ,
alienBullets . recycle () ,
/

PlayState ) .

FlxSprite ) ;

b u l l e t . width

2,

y) ;

61 }
62
63 s u p e r . u p d a t e ( ) ;
64 }
65

66 / *
67

funcin

Esta

nuevo ,

68

el

resetea
rango

va

el

tiempo

entre

en

que

11

este

alien ,

segundos

*/

69 p r i v a t e

function

r e s e t S h o t C l o c k ( ) : Void {

_ s h o t C l o c k = 1 + FlxRandom . f l o a t ( )

70
71 }

72 // F i n

de

la

clase

73 }

9.4.5. La clase PlayerShip


1 package ;
2
3 import

f l i x e l . FlxG ;

4 import

f l i x e l . FlxSprite ;

61

10;

pueden

disparar

de

5
6 class

extends FlxSprite {

PlayerShip

7
8 public
9 //

function

Centramos

new ( ) {

la

nave ,

hard

codeado

xq

sabemos

el

ancho

de

la

imagen

xD

10 s u p e r ( FlxG . w i d t h

6,

FlxG . h e i g h t

12 ,

" a s s e t s / s h i p . png " ) ;

11 }
12
13 override

p u b l i c function u p d a t e ( ) : Void {

14
15 // En

cada

update

frenamos

la

nave

16 v e l o c i t y . x = 0 ;
17
18 // Hacemos
19 i f
20

que

se

mueva

si

teclea

las

( FlxG . k e y s . a n y P r e s s e d ( [ "LEFT" ,
velocity .x

flechas !

"A" ] ) ) {

100;

21 }
22 i f
23

( FlxG . k e y s . a n y P r e s s e d ( [ "RIGHT" ,

"D" ] ) ) {

v e l o c i t y . x += 1 0 0 ;

24 }
25
26 //

Llamar

al

super . update !

27 s u p e r . u p d a t e ( ) ;
28
29
30 //

Simulamos

31 i f

( x > FlxG . w i d t h

32

una

pared

x = FlxG . w i d t h

la

derecha

width
width

4) {
4;

33 }
34
35 //

Simulamos

36 i f

( x < 4) {

37

una

pared

la

izquierda

x = 4;

38 }
39
40 // lgica
41 i f

del

disparo ,

sale

del

centro

de

la

nave

se

reciclan

( FlxG . k e y s . j u s t P r e s s e d . SPACE) {

42

var

b u l l e t : FlxSprite = c a s t ( c a s t ( FlxG . s t a t e ,

43

b u l l e t . r e s e t ( x + w i d t h /2

44

bullet . velocity .y =

playerBullets . recycle () ,

FlxSprite ) ;
b u l l e t . width /2 ,

140;

45 }
46
47 s u p e r . u p d a t e ( ) ;
48 }
49 // F i n

de

la

PlayState ) .

clase

50 }

62

y) ;

9.5. Tarea: FlxInvaders


1. Limitar la cantidad de balas por segundo que podemos disparar. Para hacer esto hay
que copia la idea de la clase Alien. Sino, podemos disparar tan rpido logrando que
nuestras balas ms viejas desaparezcan.
2. Perder si los invasores llegan hasta cierta altura. Es decir, la siguiente situacin es
inadmisible en un buen juego:

Figura 14: Inslito

3. Que las balas estn en la capa ms alta. Es decir, redenir el mtodo update, agregando grupos que referencien capas, entonces slo en un lugar lo hago visible segn
que capa debe ir arriba de otra.

Figura 15: Es muy confusa la situacin actual. Hay balas arriba de aliens y debajo, no
deberamos agregar confusin al jugador.

4. Agregarle un loading screen que genere los aliens usando FlxAsyncLoop.


5. Una vez que perdemos nos queda la frase,

63

YOU LOST, evitar esto.

Figura 16: Hint, se puede agregar otro estado de derrota!

10. Sonidos y Msica


Si Pac-Man nos hubiera afectado de jvenes, estaramos todos corriendo en crculos
en cuartos oscuros, tragando pastillas y escuchando msica electrnica repetitiva.
Marcus Brigstocke.

Los sonidos y la msica de un videojuego son tan importantes como las imgenes o el

15 .

diseo. A veces una cancin puede hacer que un videojuego valga la pena jugarlo

Los videojuegos estn generando tantos ingresos que muchos msicos profesionales como Danny Baranowsky, compositor de Necrodancer, Desktop Dungeons, Drifter, Super
Meat Boy y otros, han decido dedicarse a componer msica exclusivamente para videojuegos.
Esto tambin es verdadero para otras profesiones como actores de voz o creadores de
efectos de sonidos.
A continuacin veremos cmo incluir sonidos y msica en nuestros juegos.

10.1. La Clase: FlxSound


Cargar sonidos y msica es an ms fcil que cargar imgenes y animaciones.
Esta clase se puede usar tanto para representar sonidos cortos, como canciones largas.
Lo primero que tenemos que crear es un objeto FlxSound.
1

var

sound

FlxSound = new F l x S o u n d ( ) ;

Una vez que tenemos nuestro objeto, debemos cargarle un sonido incrustado:
1 s o u n d . loadEmbedded ( " a s s e t s /MainMenu . mp3" , true ) ;

El tipo de la funcin es:


: Dynamic , ? Looped
Void Void ) : FlxSound

1 loadEmbedded ( EmbeddedSound
2 :

Bool ,

? OnComplete

Bool ,

? AutoDestroy

15 R.P: la cancin de tetris se va quedar grabada en mi cerebro por el resto de mi vida.

64

EmbeddedSound:
Looped:

path al archivo de sonido.

indica si el sonido debe repetirse indenidamente.

AutoDestroy :

si el objeto debera destruirse al terminar su reproduccin.

OnComplete: recibe una funcin callback que es llamada al terminar su reproduccin.


Finalmente! hace falta

darle play al sonido para poder escucharlo dentro del juego.

1 sound . p l a y ( ) ;

10.2. Tiempo de Carga de Sonidos y Recycling


Al igual que las imgenes, deberamos cargar todos los sonidos que vamos a utilizar en
nuestro juego dentro del loading screen. Y slo darle play al sonido que nos haga falta.
Si queremos utilizar un mismo sonido mltiples veces al mismo tiempo, vamos a tener
que crear mltiples instancias del mismo sonido para poder darle play a todas las instancias. Por suerte, de la misma manera que podemos reciclar imgenes,

sonidos.

podemos reciclar

Por lo tanto el siguiente cdigo es vlido:


1

var

s o u n d s = new FlxTypedGroup<FlxSound >(2) ;

2 add ( s o u n d s ) ;
3
4

var

s o u n d = new F l x S o u n d ( ) ;

5 s o u n d . loadEmbedded ( " a s s e t s /MainMenu . mp3" ) ;


6 s o u n d s . add ( s o u n d ) ;
7
8

var

s o u n d = new F l x S o u n d ( ) ;

9 s o u n d . loadEmbedded ( " a s s e t s /MainMenu . mp3" ) ;


10 s o u n d s . add ( s o u n d ) ;
11
12

var

sound

FlxSound = s o u n d s . r e c y c l e ( ) ;

13 s o u n d . p l a y ( ) ;

10.3. Agregando un Sonido a un Estado


Si tratan de usar sonidos de la manera que vimos hasta ahora, vern que los sonidos
se reproducen independientemente del estado se encuentren. Eso es porque no los hemos
agregados al estado.
1 add ( s o u n d ) ;

Veremos que al agregar un sonido al estado, ste se destruye cuando se destruye el


estado, el sonido tambin se reinicia cuando se reinicia el estado. Si no agregamos un
sonido al estado, el objeto va seguir existiendo pero no va haber manera de accederlo o
modicarlo de ninguna manera.

65

Si queremos que un sonido que dure ms all de un estado, podemos utilizar la clase
Reg.hx para crear una variable de sonido esttica que pueda ser modicada en cualquier
estado.
1 public

static

var

s o u n d : FlxSound = new F l x S o u n d ( ) ;

2 Reg . s o u n d . loadEmbedded ( " a s s e t s /MainMenu . mp3" ) ;


3 Reg . s o u n d . p l a y ( ) ;

10.4. Sonidos de acuerdo a plataformas


Distintas plataformas manejan distintos formatos de sonidos. Es por eso que cuando
estemos agregando msica a nuestros juegos tenemos que usar compilacin condicional
para evitar problemas en distintas plataformas.
1
2
3
4
5
6

var s o u n d
#if flash

FlxSound = new F l x S o u n d ( ) ;

s o u n d . loadEmbedded ( " a s s e t s /MainMenu . mp3" ) ;

#else
s o u n d . loadEmbedded ( " a s s e t s /MainMenu . o g g " ) ;

#end

7 add ( s o u n d ) ;
8 sound . p l a y ( ) ;

10.5. Atributos de un Objeto FlxSound


autoDestroy : Bool, si queremos destruir el objeto o no cuando termina la reproduccin.

onComplete : V oid V oid,

contiene una funcin de callback que ser llamada

cuando el sonido termina su reproduccin.

pan : F loat,

establecemos el pan del sonido, -1 indica que todo el sonido sonar a la

izquierda, 1 establece todo el sonido a la derecha. El panning basado en proximidad


pisa este valor.

playing : Bool,
volume : F loat,

indica si el sonido actualmente est siendo reproducido o no.


volumen actual del sonido. Toma valores entre 0 y 1.

x : F loat, indica la posicin en x del sonido, til solamente cuando usamos proximity().
y : F loat, indica la posicin en y del sonido, til solamente cuando usamos proximity().

66

10.6. Mtodos de un Objeto FlxSound


play(?F orceRestart : Bool) : Void, mtodo que reproduce un sonido, se puede usar
sobre sonidos que actualmente se encuentran en pausa. Si ForceRestart un sonido
que est en pausa se reproduce desde el principio, por defecto est en false.

pause() : Void,

mtodo que pone en pausa un sonido.

resume() : Void,

mtodo que contina la reproduccin de un sonido, slo se puede

utilizar sobre objetos que se encuentran en pausa.

stop() : Void,

mtodo que termina la reproduccin de un sonido.

f adeIn(Duration : Float, ?F rom : Float, ?T o : Float) : Void, mtodo que permite


hacer que el sonido crezca desde From a To durante Duration segundos al iniciar la
reproduccin. Por defecto:(1,0,1).

f adeOut(Duration : Float, ?T o : Float) : Void, igual que el anterior slo que toma
lugar al nalizar la reproduccin y slo puede bajar el volumen. Por defecto:(1,0,1).

getActualV olume() : Float,

mtodo que devuelve el valor del volumen actual.

proximity(X : Float, Y : Float, T argetObject : flixel.FlxObject, Radius : Float, ?P an :


Bool) : FlxSound, mtodo que permite cambiar cmo se reproduce un sonido dependiendo de la posicin de otro objeto.

X e Y establecen la posicin del sonido.

TargetObject: el objeto que se desea seguir.

Radius: el radio alrededor del cual se escucha el sonido.

Pan: si el sonido aparte de modicar su volumen tambin va modicar la direccin de la cual viene.

67

11. Guardando Datos


 . . .
Gordon
Freeman

Hasta ahora hemos creado juegos que no son persistentes, eso est bien para juegos
cortos o repetitivos como sera un arcade o un puzzle. Pero si queremos crear un juego
que dure ms de una hora debemos poder guardar el estado del juego para reanudarlo en
otro momento.
Veremos cmo poder hacer resolver este problema:

11.1. La clase: FlxSave


Haxeixel provee una clase para poder hacer esto de manera muy simple. Primero
debemos crear un objeto FlxSave:
1

var

save

FlxSave = new F l x S a v e ( ) ;

Ahora para poder utilizar un save debemos enlazarlo a nombre especco:


1 save . bind ( ` ` s l o t 1 ' ' ) ;

Una vez hecho el enlace, podemos empezar a cargar o guardar datos usando el siguiente
campo:
1 save . data

data

es un campo de tipo

Dynamic.

Si recuerdan, un campo dynamic puede tener

cualquier cantidad de campos dentro de l. Por ejemplo, ahora sera vlido:


1 save . data . l e v e l

= 42;

2 s a v e . d a t a . name =

` ` Pantufla ' ' ;

3 save . data . s c o r e s = [ 3 0 0 , 1 0 0 , 6 6 6 ] ;

Y esa es la forma en la cual se escriben datos en el save. Si estamos en ash no hace


falta ms nada para que los datos se guarden. Pero si estamos en otra plataforma falta
hacer un ush:
1 save . f l u s h ;

Y listo! Los datos se han guardado. Ahora cmo los recuperamos al correr el juego
de nuevo? Simple, primero hacemos el enlace al mismo nombre y recuperamos los datos:
1

var

save

FlxSave = new F l x S a v e ( ) ;

2 save . bind ( ` ` s l o t 1 ' ' ) ;


3
4
5

var
var
var

level
name
score

Int = s a v e . d a t a . l e v e l ;
String = s a v e . d a t a . name ;

:
:

Int = s a v e . d a t a . s c o r e s [ 0 ] ;

68

Ahora, recuerden que al trabajar con un objeto dinmico, no siempre puede tener
valores guardados, y esto puede llevar a tremendos errores al momento de la ejecucin.
Es por eso que siempre deberamos vericar que no sean
1

var

save

null:

FlxSave = new F l x S a v e ( ) ;

2 save . bind ( ` ` s l o t 1 ' ' ) ;


3

var

4 if

level

Int ;

( save . data . l e v e l

!= null )

level

= save . data . l e v e l ;

level

= 1;

6 else
7

Es muy importante entender que los datos guardados no tienen que ver con el objeto
que se utiliza para guardarlos, es por eso que el siguiente cdigo es vlido:
1

var

save

FlxSave = new F l x S a v e ( ) ;

2 save . bind ( " s l o t 1 " ) ;


3 save . data . l e v e l

= 5;

4
5

var

save2

FlxSave = new F l x S a v e ( ) ;

6 save2 . bind ( " s l o t 1 " ) ;


7

var

level

Int = s a v e 2 . d a t a . l e v e l ;

Se podra decir que el objeto save es una interface para acceder los datos guardados
pero no es dnde se guardan los datos, un ejemplo de algo que
1

var

save1

no funcionara:

FlxSave = new F l x S a v e ( ) ;

2 save . bind ( " s l o t 1 " ) ;


3 save . data . l e v e l

= 5;

4
5 save . bind ( " s l o t 2 " ) ;
6

var

level

Int = s a v e . d a t a . l e v e l ;

La razn porque esto no funciona es: en el slot2 no se ha guardado nada de informacin


todava, y entonces su valor de level es

null.

En realidad, esto compila y corre. Pero si tratamos de leer el valor de level veremos que

NaN. En otros casos donde trabajamos con objetos que tienen mtodos (algo
ms complicado que un Int) veremos que efectivamente puede crashear el programa.
es igual a

Lo que se recomienda es tener una sola variable save dentro de la clase Reg.hx Dentro
de un estado se puede realizar el enlace y todos los otros estados pueden acceder a los
datos.

11.1.1. Atributos de FlxSave


data : Dynamic, indica el campo que contiene todos los valores que tenemos guardados o queremos guardar. Slo se puede acceder una vez que hemos hecho un enlace.

name : String ,

establecemos el nombre al cual el objeto se encuentra enlazado.

Slo se utiliza para saber el nombre, si queremos cambiar el nombre al cual estamos
enlazados debemos usar la funcin bind().

69

11.1.2. Mtodos de FlxSave


bind(N ame : String) : Bool, automticamente crea o reconecta con datos guardados
localmente. Devuelve

true si se pudo conectar exitosamente.

f lush(?M inF ileSize : Int, ?OnComplete : Bool Void) : Bool,


que estn en el objeto al disco de manera inmediata. Devuelve

escribe los datos

true

si es exitoso.

Toma como argumentos opcionales un tamao mnimo de archivo y una funcin


callback que es llamada en caso de ser exitosa la escritura a disco.

false si no
existe un enlace con ese nombre. No requiere un ush, as que usar con precaucin.
erase() : Bool,

borra todos los datos asociados a ese nombre, devuelve

destroy() : V oid,

destruye el objeto y libera la memoria, no toca los datos.

close(?M inF ileSize : Int, ?OnComplete : Bool Void) : Bool,


ush y despus a destroy.

70

primero llama a

12. Cmaras y ScaleModes


Los videojuegos son malos para vos? Eso es lo que dijeron del rock & roll.
Shigeru Miyamoto.

Hasta ahora nuestros juegos han sido jos, es decir, la cmara del juego no se ha
movido. Eso es muy til para juegos de tipo puzzle u otros gneros donde no hace falta.
Pero en la gran mayora de juegos, vamos a tener que movernos a travs de nuestro mundo
virtual, y es ah donde entra en juego la cmara.

12.1. Qu es la cmara?
La cmara es una ventana para ver los objetos que hemos creado en nuestro juego.
Podemos agrandar o achicar esa ventana. Por defecto, tiene el mismo tamao que la
resolucin del juego. Tambin podemos cambiar la posicin de esa ventana. Y podemos
modicar qu parte de nuestro mundo la ventana est mirando.

Como pueden ver, todo lo que est fuera de la cmara, no se muestra. Por ms que
nuestro fondo verde fuese innito no se a va ver porque est fuera de la cmara. El color

71

de fondo de lo que no cubre la cmara es el color de fondo de la ventana y eso se puede


cambiarse en Project.xml.
Notar que cuando cambiamos el focus, no estamos moviendo la cmara y es por eso
que se ve ms supercie verde.

12.2. La clase: FlxCamera


Esta es nuestra clase que maneja la cmara. Haxeixel por defecto te crea una instancia
de esta clase cuando corres tu juego. Es una cmara que tiene el ancho y alto de la
resolucin del juego y se encuentra en la posicin (0,0) con zoom = 1.
Esta cmara se puede acceder de la siguiente manera:

F lxG.camera
Si queremos modicar los valores o llamar mtodos de esta cmara se hace de la
siguiente manera:

F lxG.camera.width = 640/2;
F lxG.camera.x = 200;
F lxG.camera.y = 200;
F lxG.f ocus(new F lxP oint(0, 400));
Tambin podemos crear ms cmaras si nos hiciera falta (til para juegos donde hay
splitscreen

16 , y otros casos ms.) En ese caso, hay que agregarla a la lista de cmaras.

Ejemplo para crear un splitscreen:


1 FlxG . c a m e r a . w i d t h = S t d . i n t ( 6 4 0 / 2 ) ;
2 FlxG . c a m e r a . f o l l o w ( _char1 ) ;
3

var

c a m e r a = new FlxCamera ( S t d . i n t ( 6 4 0 / 2 ) , 0 , S t d . i n t ( 6 4 0 / 2 ) , 4 8 0 , 1 ) ;

4 c a m e r a . f o l l o w ( _char2 ) ;
5 FlxG . c a m e r a s . add ( c a m e r a ) ;

Otro ejemplo donde se utiliza ms de una cmara es para tener un

minimapa:

1 FlxG . c a m e r a s . add ( new FlxCamera ( 5 4 0 , 3 8 0 , 6 4 0 , 4 8 0 , 0 . 2 ) )

12.2.1. Atributos de FlxCamera


alpha : F loat,

el valor alpha de la cmara, su opacidad. Toma valores entre 0 y 1.

angle : F loat,

el ngulo de la cmara en grados.

bgColor : Int,

color de fondo de la cmara.

16 Divisin de pantalla

72

bounds : f lixel.util.F lxRect,

establece los lmites del rango de la cmara, es decir,

dnde deja de seguir un objeto, setear con el mtodo setBounds.

deadzone : f lixel.util.F lxRect,

La zona muerta alrededor del objeto que se est

siguiendo en la cual la cmara no se mueve, slo se empieza a mover para mantener


el objeto dentro de la zona muerta.

height : Int,
width : Int,
style : Int,

altura de la cmara.
ancho de la cmara.

establece a la cmara uno de los estilos predenidos.

x : F loat,

la posicin

de la cmara. El zoom no afecta este valor.

y : F loat,

la posicin

de la cmara. El zoom no afecta este valor.

zoom : F loat,

el zoom de la cmara. 1 = normal, 2 = zoomx2, 0.5 = zoomx0.5, etc

12.2.2. Mtodos de FlxCamera


new(?X : Int, ?Y : Int, ?W idth : Int, ?Height : Int, ?Zoom : Float),

instancia una

nueva cmara en esa ubicacin especca con ese tamao especco.

copyF rom(Camera : FlxCamera) : FlxCamera,

copia los bounds, objeto de foco,

y deadzone de una cmara a otra.

f ade(?Color : Int, ?Duration : Float, ?F adeIn : Bool, ?OnComplete : Void


Void, ?F orce : Bool) : Void, la pantalla gradualmente se cubre con el color especicado.

Color:

el color al cual cambia.

Duration:
F adeIn:

la duracin en segundos del fade.

si hace un fade desde el color o hacia el color.

OnComplete:
F orce:

una funcin que se llama cuando termina el fading.

si obliga el reseteo del efecto o no.

f ocusOn(point : flixel.util.FlxPoint) : Void, hace que el foco de la cmara est en


este punto.

f ollow(T arget : FlxObject, ?Style : Int, ?Of f set : flixel.util.FlxPoint, ?Lerp :


Float) : Void, le indica a la cmara que su foco siga a un objeto.
T arget :
Style :

el objeto al cual seguir.

un estilo predenido.

73

Of f set : el oset del deadzone del estilo elegido. Slo disponible para PLATAFORMER,
LOCKON.

Lerp :

el delay de la cmara al moverse, para suavizar el movimiento.

setBounds(?X : Float, ?Y : Float, ?W idth : Float, ?Height : Float, ?U pdateW orld :


Bool) : Void, especica los bordes de donde la cmara se puede mover.
shake(?Intensity : Float, ?Duration : Float, ?OnComplete : Void Void, ?F orce :
Bool, ?Direction : Int) : Void, causa un efecto de temblor de la cmara.
Intensity :

un porcentaje del tamao de la pantalla representando la distancia

mxima que se puede mover mientras tiembla.

Duration :

la duracin del temblor.

OnComplete:
F orce:

una funcin que se ejecuta cuando el temblor termina.

si el efecto resetea cualquier otro efecto de temblor.

Direction:

cmo debera temblar, usar las constante predenidas:

SHAKE_BOTH_AXES, SHAKE_VERTICAL_ONLY o SHAKE_HORIZONTAL_ONLY.

stopF X() : V oid,

mtodo para detener todos los efectos de cmara que estn cor-

riendo.

12.2.3. Estilos Predenidos de FlxCamera


ST Y LE _LOCKON (inline, null) : Int,

cmara sin deadzone.

ST Y LE _N O_DEAD_ZON E(inline, null) : Int, cmara sin deadzone y centrada


en el objeto.

ST Y LE _P LAT F ORM ER(inline, null) : Int;

el deadzone no es muy ancho pero

s es alto.

ST Y LE _SCREEN _BY _SCREEN (inline, null) : Int, la cmara se va mover de


pantalla en pantalla a saltos.

ST Y LE _T OP DOW N (inline, null) : Int,

el deadzone es un cuadrado de tamao

mediano alrededor del objeto.

ST Y LE _T OP DOW N _T IGHT (inline, null) : Int, idem supra pero con un cuadrado ms chico.

74

13. Funcionalidad Avanzada


La peor cosa que un nio puede decir de su tarea es que es muy difcil.
La peor cosa que un nio puede decir de un juego es que es muy fcil.
Henry Jenkins.

13.1. Pixel Perfect Collision


Basta de hitboxes cuadrados! Ahora, gracias al siguiente mtodo podemos lograr que
nuestros sprites veriquen colisiones exactas pixel a pixel.
La siguiente funcin toma dos sprites de argumento y devuelve

true si sus pixeles se

estn tocando. Puede tener tolerancia a la opacidad de los pxeles, es decir qu tan visibles
tienen que ser los pxeles para determinar si es una colisin o no.
1 FlxG . p i x e l P e r f e c t O v e r l a p ( S p r i t e 1
2 ? AlphaTolerance

Int ,

? Camera

FlxSprite , S p r i t e 2
FlxCamera ) : Bool
:

Sprite1:

el primer sprite de la colisin.

Sprite2:

el segundo sprite de la colisin.

AlphaT olerance:

tolerancia a la opacidad. 255

completamente visibles. 1

FlxSprite ,

detecta slo colisiones entre cosas

detecta colisiones de cualquier cosa que no sea comple-

tamente invisible.

Camera:

si la colisin est sucediendo en otra cmara que no sea FlxG.camera, se

tiene que pasar como argumento.


A tener en cuenta: este tipo de deteccin de colisiones no tiene funcin callback. Eso
quiere decir que no se puede usar con Grupos. Slo se puede usar entre dos sprites especcos.

13.2. Efectos sobre nuestros Sprites


Hay varios efectos que haxeixel permite que nosotros apliquemos sobre nuestros
sprites. Ahora vamos a ver algunos de ellos.

13.2.1. FlxTween
Tween viene de la palabra Inbetween. Es una manera de crear los frames para una
animacin de un sprite de manera automtica. Podemos Tweenear distintos valores de
un sprite a lo largo de una duracin, y los frames sern generados automticamente.
Por ejemplo, podemos cambiar el ngulo de un sprite por 90 grados a lo largo de un
periodo de 3 segundos.

75

O podemos usarlo para cambiar el color de un sprite a otro color a lo largo de medio
segundo. Hay varios tweens que podemos aplicar sobre un objeto:

angle(Sprite : flixel.FlxSprite, F romAngle : Float, T oAngle : Float, Duration :


Float, ?Options : TweenOptions) : flixel.tweens.misc.AngleTween, tweenea el
ngulo de un sprite.

Sprite:

el sprite que queremos tweenear.

F romAngle: de qu ngulo empezar. Si el sprite no est en este ngulo, el tween


lo coloca en ese ngulo.

T oAngle:

el ngulo en el que el sprite tiene que terminar.

Duration:
Options:

la duracin en segundos del sprite.

lo explicaremos ms adelante.

circularM otion(Object : flixel.FlxObject, CenterX : Float, CenterY : Float, Radius :


Float, Angle : Float, Clockwise : Bool, DurationOrSpeed : Float, ?U seDuration :
Bool, ?Options : TweenOptions) : flixel.tweens.motion.CircularMotion, tweenea al objeto en un movimiento circular.

Object:

el objeto al cual tweenear.

CenterX :

la posicin

CenterY :

la posicin

Radius:
Angle:

del crculo en el cual se va a mover.


del crculo en el cual se va a mover.

el radio del crculo en el cual se va a mover.

la posicin sobre la cual empieza en el circulo.

Clockwise:

horario o antihorario.

DurationOrSpeed:

la duracin del tween.

color(Sprite : flixel.FlxSprite, Duration : Float, F romColor : Int, T oColor :


Int, ?F romAlpha : Float, ?T oAlpha : Float, ?Options : TweenOptions) :
flixel.tweens.misc.ColorTween, tweenea el color y la opacidad de un sprite de un
sprite.

Sprite:

el sprite al cual tweenear.

Duration:

duracin del tween en segundos.

F romColor:
T oColor:

el color nal.

F romAlpha:
T oAlpha:

el color inicial.

la opacidad inicial.

la opacidad nal.

76

f ader(V olume : Float, Duration : Float, ?Options : TweenOptions) :


flixel.tweens.sound.Fader, tweenea el volumen de un sonido.
V olume:

el volumen al cual tweenear.

Duration:

la duracin del tween.

linearM otion(Object : flixel.FlxObject, F romX : Float, F romY : Float, T oX :


Float, T oY : Float, DurationOrSpeed : Float, ?U seDuration : Bool, ?Options :
TweenOptions) : flixel.tweens.motion.LinearMotion, tweenea el movimiento
lineal de un objeto.

Object:

el objeto a tweenear.

F romX :

la posicin X inicial.

F romY :

la posicin Y inicial.

T oX :

la posicin X nal.

T oY :

la posicin Y nal.

DurationOrSpeed:

la duracin del tween.

linearP ath(Object : flixel.FlxObject, P oints : Array < flixel.util.FlxPoint >


, DurationOrSpeed : Float, ?U seDuration : Bool, ?Options : TweenOptions) :
flixel.tweens.motion.LinearPath, tweenea un camino lineal, es como hacer mltiples linearMotions.

Object:

el objeto a tweenear.

P oints:

los puntos por los cuales pasa el objeto de manera lineal.

DurationOrSpeed:

la duracin en segundos del tween.

num(F romV alue : Float, T oV alue : Float, Duration : Float, ?Options : TweenOptions) :
flixel.tweens.misc.NumTween, tweenea un valor numrico.
F romV alue:
T oV alue:
Duration:

el valor inicial.

el valor nal.
la duracin del tween en segundos.

quadM otion(Object : flixel.FlxObject, F romX : Float, F romY : Float, ControlX :


Float, ControlY : Float, T oX : Float, T oY : Float, DurationOrSpeed : Float, ?U seDuration :
Bool, ?Options : TweenOptions) : flixel.tweens.motion.QuadMotion, tweenea
un movimiento cuadrtico de un objeto.

Object:

el objeto que queremos tweenear.

F romX :

la posicin X original.

77

F romY :

la posicin Y original.

ControlX :

usado para determinar la curva en X.

ControlY :

usado para determinar la curva en Y.

T oX :

la posicin X nal.

T oY :

la posicin Y nal.

DurationOrSpeed:

la duracin del tween en segundos.

quadP ath(Object : flixel.FlxObject, P oints : Array < flixel.util.FlxPoint >


, DurationOrSpeed : Float, ?U seDuration : Bool, ?Options : TweenOptions) :
flixel.tweens.motion.QuadPath, Idem que LinearPath pero cuadrtico.
tween(Object : Dynamic, V alues : Dynamic, Duration : Float, ?Options : TweenOptions) :
FlxTween, una manera de hacer tween a cualquier cantidad de variables numricas
de un Objeto.

Object:

el objeto a tweenear, puede ser cualquier cosa.

V alues:
tweenear

un objeto que contiene los valores a tweenear, Ej: x:200,y:300 va a

Duration:

a esas posiciones desde donde se encuentren ahora.

la duracin del tween.

13.2.2. TweenOptions
Es un objeto con los siguientes campos:

var complete : N ull < CompleteCallback >:

una funcin callback que se llama

cuando el tween termina.

var ease : N ull < EaseF unction >:

un efecto que se le agrega al tween al iniciar,

terminar o ambos, ms adelante veremos los distintos efectos.

var loopDelay : N ull < F loat >:

la demora en loopear el tween, si es el tipo de

tween que loopea.

var startDelay : N ull < F loat >:


var type : N ull < Int >:

la demora en iniciar el tween.

el tipo de tween, ms adelante veremos qu tipos existen.

TweenOptions se utiliza de la siguiente manera, se crea un objeto TweenOptions y se


lo utiliza dentro de un mtodo tween:
1

var

o p t i o n s : TweenOptions = {
bounceOut ,

var

type :

FlxTween . ONESHOT,

e a s e : FlxEase .

c o m p l e t e : onTweenEnd }

t w e e n = FlxTween . t w e e n ( _char ,

y:400 ,

Tipos de Tweens

78

x :300

},

0.8 ,

options ) ;

ON ESHOT (inline, null) : Int, un tween que corre una sola vez y se destruye cuando
termina.

P ERSIST (inline, null) : Int,

un tween que corre una sola vez pero no se destruye

al terminar.

LOOP IN G(inline, null) : Int,

un tween que se repite indenidamente. Podemos

acceder a tween.executions para saber cuntos loops viene haciendo.

BACKW ARD(inline, null) : Int,

un tween que corre en reversa.

P IN GP ON G(inline, null) : Int,

un tween que va y vuelve, es como un loop de

ONESHOT y BACKWARD.
Tipos de Ease:
Hay muchos:

http://api.haxeflixel.com/types/flixel/tweens/FlxEase.html

elasticInOut(t : F loat) : F loat,

al iniciar y al terminar el tween hace un efecto

elstico.

elasticIn(t : F loat) : F loat,

slo al iniciar tiene el efecto elstico

elasticOut(t : F loat) : F loat,

slo al terminar.

13.2.3. FlxGlitchSprite
new(T arget : F lxSprite, Strength : Int = 4, Size : Int = 1, Delay : F loat =
0,05, ?Direction : GlitchDirection) : F lxGlitchSprite
Crea una copia de un sprite con un efecto de distorsin. No se debe agregar el sprite
original al display, solo el GlitchSprite.

T arget:

el sprite a copiar.

Strength:
Size:

qu tan fuerte debe ser el efecto.

el ancho de cada pedazo del glitch.

Delay :

cuntos segundos pasan entre los updates de cada glitch.

Direction: qu direccin debera tener el glitch. Acepta: GlitchDirection.HORIZONTAL


o GlitchDirection.VERTIAL.

79

13.2.4. FlxWaveSprite
N ew(T arget : FlxSprite, ?M ode : WaveMode, Strength : Int = 20, Center : Int =
1, Speed : Float = 3) : FlxWaveSprite: crea una copia de un sprite pero con un efecto
de ondas. Al igual que antes, slo se debe agregar al displaylist la copia.

T arget:
M ode:

el sprite a copiar.

qu modo usar para el efecto. WaveMode.ALL aplica la distorsin en toda la

imagen.

W aveM ode.BOT T OM :

hace el efecto ms fuerte hacia abajo. WaveMode.TOP la

inversa de BOTTOM.

Strength:
Center:
Speed:

qu tan fuerte debera ser el efecto.

el centro del efecto cuando se usa los modos BOTTOM o TOP.

qu tan rpido se mueve el efecto. Mientras ms alto ms rpido.

13.2.5. FlxSpriteFilters
Podemos agregar ltros a nuestros sprites de la siguiente manera. Creamos un ltro de
alguno de los siguientes:

GlowF ilter

: crea un brillo alrededor o dentro del objeto.

BlurF ilter

: hace que el sprite se vea borroso.

DropShadow

: le hace una sombra a nuestro sprite.

newGlowF ilter(color : Int, alpha :


Float = 1, blurX : Float = 6, blurY : Float = 6, strength : Float = 2, quality : Int =
1, inner : Bool = false, knockout : Bool = false) : GlowFilter
Se crean haciendo instancias de dichos ltros:

color:

el color del brillo.

Alpha:

la opacidad.

BlurX :

la cantidad de brillo en X.

BlurY :

la cantidad de brillo en Y.

Strength:
Quality :
Inner:

qu tan fuerte es el brillo.

la cantidad de veces que se aplica el ltro.

si el brillo es por dentro o por fuera.

80

Knockout:

true = el objeto se hace transparente.

N ewBlurF ilter(blurX : Float = 4, blurY : Float = 4, quality : Int = 1) : BlurFilter


BlurX :

qu tan borroso se ve en X.

BlurY :

qu tan borroso se ve en Y.

Quality :

la cantidad de veces que se aplica el ltro.

N ewDropShadowF ilter(distance : Float = 4, angle : float = 45, color : Int =


0, alpha : Float = 1, blurX : Float = 4, blurY : Float = 4, strength : Float =
1, quality : Int = 1, inner : Bool = false, knockout : Bool = false, hideObject : Bool =
false) : DropShadowFilter
distance:
angle:
color:

el oset de la sombra en pxeles.

el ngulo de la sombra en grados.


el color de la sombra.

Alpha:

la opacidad de la sombra.

BlurX :

qu tan borroso se ve en X.

BlurY :

qu tan borroso se ve en Y.

Strength:
Quality :

qu tan fuerte es la sombra.

la cantidad de veces que se aplica el ltro.

HideObject:

aparentemente lo mismo que knockout

17 R.P: No le encontr la diferencia.

81

17 .

Una vez creado un ltro, hay que crear un FlxSpriteFilter sobre un sprite y agregarle
ese ltro:
1 new

FlxSpriteFilter

( S p r i t e : FlxSprite ,

H e i g h t I n c r e a s e : Int =0)

Sprite:

W i d t h I n c r e a s e : Int =0 ,

FlxSpriteFilter

el sprite al cual queremos agregar el ltro.

W idthIncrease:

cunto incrementar el ancho del sprite, til para ltros como blur

que necesitan espacio fuera del grco original.

HeightIncrease:

idem pero con altura

Ejemplo:
1
2

var
var

filter

= new D r o p S h a d o w F i l t e r ( ) ;

c h a r F i l t e r = new

F l x S p r i t e F i l t e r ( _char , 1 0 , 1 0 ) ;

3 charFilter . addFilter ( f i l t e r ) ;

82

14. Tiles
En conclusin, los juegos son profesores. La pregunta es: qu estn enseando?
Raph Coster - A Theory of Game Design

Qu es un tile? Un tile es una imagen pequea, usualmente rectangular, que se utiliza


para construir imgenes ma grandes. Por ejemplo, un rbol, una casa, una montaa. Los
tiles son usados para generar mapas que son agrupamientos de tiles. Con apenas unos
cuantos tiles podemos generar una cantidad innita de mapas sin tener que redibujar una
y otra vez cada mapa. Imagnense cuntas islas pueden dibujar con solo 3 tiles: agua,
arena y pasto.

Figura 17: Ejemplo de un Tile Sheet

Algunos tiles son continuos, es decir que esperan que haya otro tile que lo siga en
alguno de sus lados. Un tile puede ser continuo en cualquiera de sus cuatro lados. Esto
quiere decir que hay 16 combinaciones distintas de continuidad de un tile, yendo de cero
continuidad a continuidad en sus 4 lados.

Figura 18: (1) Un bosque continuo a derecha y izquierda. (2) Un bosque continuo hacia
arriba izquierda y abajo.

83

Hay varias formas de implementar tiles en HaxeFlixel, veamos algunas de ellas:

14.1. La clase: FlxTileMap


El ms simple de todos. Toma un archivo de texto y lo convierte en tiles colisionables.
Primero tenemos que crear el objeto Tilemap:
1 _map = new F l x T i l e M a p ( ) ;

Despus tenemos que cargar el texto y las imgenes:


1 _map . loadMap ( " 0 , 1 , 1 , 0 , 1 , 1 , 1 , 0 \ n

0 , 1 , 1 , 0 , 1 , 1 , 1 " , " a s s e t s / t i l e . png " ) ;

Ac los ceros quieren decir: No colocar tile y los unos quieren decir : Colocar tile. Y
por ltimo agregar el mapa a nuestro display list:
1 add (_map) ;

Y listo tenemos un mapa hecho con tiles! Si queremos que nuestro personaje colisione
con los tiles, solo hace falta agregarlo en el update:
1 FlxG . c o l l i d e ( _char ,

_map) ;

Este es un caso simple, donde use un tile que tena un espacio en blanco y una imagen
para cuando el tile esta en uso. Tambin se puede colocar ms de una imagen y usar los
nmeros que se pasan como argumento. Ej:
1 _map . loadMap ( " 0 , 1 , 2 , 2 , 1 , 0 , 0 , 3 " , " a s s e t s / t i l e 2 . png " ) ;

En este caso, cada nmero corresponde a un tile distinto dentro de la imagen que
le pase. Tambin se le puede decir que use el modo de

continuidad automtica. Esto

quiere decir que nosotros slo colocamos 0 y 1, y si en el mapa encuentra dos 1's conectados
usa los tiles correspondientes para continuarlos. En este caso nosotros debemos pasarle
los 16 tiles de continuidad.
1 _map . loadMap ( " 0 , 0 , 0 , 0 \ n

0 ,1 ,1 ,0\n

0 , 1 , 0 , 0 , 0 \ n0 , 0 , 0 , 0 " , " a s s e t s / t i l e 3 .

png " , 5 0 , 5 0 , F l x T i l e m a p .AUTO) ;

Tambin hay otro modo que es ALT. La diferencia entre ALT y AUTO es que AUTO
se usa para paredes nas mientras que ALT se usa para paredes gruesas que requieren
dibujos con esquinas en su interior.
Ac es muy importante colocar todos los ceros alrededor de los unos, porque sino el
AUTO o ALT va a asumir que tiene que colocar un tile continuo. Y presten atencin
que

las imgenes tienen que ir en ese orden predenido, sino el AUTO o ALT va

completarlo con cualquier cosa.

14.1.1. Mtodos de FlxTileMap


function new() : Void,

la funcin constructora.

84

function loadM ap(M apData : Dynamic, T ileGraphic : Dynamic, ?T ileW idth :


Int = 0, ?T ileHeight : Int = 0, ?AutoT ile : Int = 0, ?StartingIndex : Int =
0, ?DrawIndex : Int = 1, ?CollideIndex : Int = 1) : FlxTilemap, carga el mapa
con string data y los grcos de los tiles.

MapData: un String de valores separados por coma y line-return indicando dnde


deberan ir los tiles.

TileGraphic: la imagen dnde estn todos los tiles.

TileWidth: el ancho de cada tile.

TileHeight: el alto de cada tile.

AutoTile: toma valores AUTO o ALT.

StartingIndex: usado para colocar tiles vacos. Se recomienda dejar en cero. Ignorado si AutoTile es usado.

DrawIndex: a partir de este nmero los tiles sern visibles. Se recomienda dejar
en 1. Ignorado si AutoTile es usado.

CollideIndex: todos los tiles despus de este valor se consideran colisionables


desde cualquier direccin. Ignorado si AutoTile es usado.

function setT ileP roperties(T ile : Int, ?AllowCollisions : Int = 4369, ?Callback :
FlxObject FlxObject Void = null, ?CallbackF ilter : Class < Dynamic >=
null, ?Range : Int = 1) : Void, setea las colisiones y funciones callbacks para cada
tile.

Tile: el tipo de los tiles que estamos seteando.

AllowCollisions: establecemos desde dnde debe detectar colisiones, usar constantes de FlxObject: NONE, ANY, LEFT, RIGHT, etc.

Callback: la funcin a llamar, ej:

CallbackFilter: si slo quers que la funcin callback se llame para ciertas clases.

Range: se indica el rango de tiles para el cual el callback funciona.

lavaCallback(T ile : FlxTile, Object : FlxObject).

function f ollow(?Camera : FlxCamera = null, ?Border : Int = 0, ?U pdateW orld :


Bool = true) : Void, esta funcin limita los bordes de la cmara al mapa.

Camera: la cmara que queremos limitar.

Border: modica el lmite de la cmara por la cantidad de tiles que indiquemos.

UpdateWorld: actualiza las colisiones de los tiles.

function f indP ath(Start : FlxPoint, End : FlxPoint, ?Simplif y : Bool = true,


?RaySimplif y : Bool = false, ?W ideDiagonal : Bool = true) : Array < FlxPoint >,
devuelve un arreglo de puntos que puede ser utilizado para generar un objeto FlxPath.

85

Start: el punto en el cual empieza.

End: el punto en el cual termina.

Simplify: si corre un algoritmo de simplicacin o no, que remueve puntos que


estn sobre la misma lnea. Default:

True.

False.

RaySimplify:

WideDiagonal: si requiere un tile adicional para las esquinas.

Default:

returns: un arreglo de puntos.

True.

14.1.2. FlxTimeMapExt
Extiende la clase anterior agregando las siguientes funcionalidades:

function setClouds(?Clouds : Array < Int >= null) : Void,

setea el arreglo de

tiles como nubes, tiles que slo colisionan desde arriba.

function setSlopes(?Lef tF loorSlopes : Array < Int >= null, ?RightF loorSlopes :
Array < Int >= null, ?Lef tCeilSlopes : Array < Int >= null, ?RightCeilSlopes :
Array < Int >= null) : Void, setea los arreglos de tiles como Pendientes, tiles
diagonales para corregir la colisin.

LeftFloorSlopes: los tiles que son pendientes hacia la izquierda en el piso.

RightFloorSlopes: los tiles que son pendientes hacia la derecha en el piso.

LeftCielSlopes: los tiles que son pendientes hacia la izquierda en el techo.

RightCeilSlopes: los tiles que son pendientes hacia la derecha en el techo.

Ejemplo, extrado de los demos de Haxeixel:


1 var tempFL : Array<Int> = [ 5 ,

13 ,

21];

2 var tempFR : Array<Int> = [ 6 ,

14 ,

22];

3 var tempCL : Array<Int> = [ 7 ,

15 ,

23];

4 var tempCR : Array<Int> = [ 8 ,

16 ,

24];

5 var tempC

12 ,

20];

: Array<Int> = [ 4 ,

6
7 l e v e l . s e t S l o p e s ( tempFL ,

tempFR ,

tempCL ,

tempCR ) ;

8 l e v e l . s e t C l o u d s ( tempC ) ;

14.1.3. FlxCaveGenerator
Un generador de cuevas al azar. Simplemente genera el data String para un tilemap, y
nosotros le pasamos las imgenes de los tiles.

86

static function generateCaveString(Columns : Int, Rows : Int, ?SmoothingIterations :


Int = 6, ?W allRatio : Float = 0,5f ) : String, genera el String data que se le pasa
a un tilemap.

Columns: cantidad de columnas de la matriz.

Rows: cantidad de las de la matriz.

SmoothingIterations: mientras ms alto ms suave es la cueva.

WallRatio: la posibilidad de que un tile sea pared o no.

87

15. Comunidad
Les dije que aprendan ingls.
Rodrigo Peralta
La comunidad indie es extremadamente til y ahora veremos qu nos puede ofrecer:
Recursos:
Antes que nada, voy a compartir el link que contiene todos los recursos que van a necesitar en su vida:

http://www.pixelprospector.com/indie-resources/.

En esa pgina

hay un montn de listas ya hechas de todos los posibles recursos que necesitemos. Todos
los links que voy a dar abajo estn en esa pagina.
Msica y Sonido
Hay excesivo material artstico dando vueltas en internet. Mucha gente que vive de
vender su arte a desarrolladores de videojuegos. Algunos tienen su propia pgina,
como por ejemplo:

http://oryxdesignlab.com:

su 16-bit fantasy Sprite Set fue utilizado para el

muy exitoso juego de ash Return to Tolagal,

portal/view/631339.

http://www.newgrounds.com/

Hay muchos artistas online pero cmo hacemos para encontrarlos?


Podemos hacerlo entrando a una de las siguientes pginas:

http://www.pixelprospector.com/places-to-find-graphics-artists/
http://www.pixelprospector.com/the-big-list-of-musicians/
http://www.pixelprospector.com/places-to-find-musicians/
Como pueden ver, hay artistas que trabajan freelance, otros venden sus obras ya
creadas y otros ambas.Tambin hay material gratuito, aunque por razones obvias
hay menos y de menor calidad, dentro del sitiio

http://www.pixelprospector.com

podemos entrar a :

/the-big-list-of-royalty-free-graphics/
/the-big-list-of-royalty-free-music-and-sounds-free-edition/
Notar: la comunidad indie es tambin un excelente lugar para

conseguir trabajo.

Material de estudio:
Si recuerdan en las primeras unidades se habl de roles, la idea simple es que una
persona tiene que estar capacitada para cubrir bien su rol. Y todos los roles son
importantes y requieren capacitacin. Por esto se aconseja, como en cualquier mbito de la vida, no estancarse, acceder al bastsimo material de estudio para seguir
mejorando.

88

Marketing:
Muy importante, gente estudia careras para saber esto. No subestimes la importancia
que tiene el marketing en tu juego.

http://www.pixelprospector.com/the-big-list-of-indie-game-marketing/
http://www.pixelprospector.com/how-to-contact-press/
http://www.pixelprospector.com/contents-and-examples-of-press-kits/

Game Design:
Si penss que no existe una teora sobre cmo disear un juego ests subestimando
el arte de hacer juegos. Cualquiera puede hacer un juego pero no cualquiera puede
hacer uno bueno.

http://www.pixelprospector.com/the-big-list-of-game-design/

Msica:
Si quers aprender a hacer msica!

/the-big-list-of-sound-and-music-creation-software/

Grcos:
Si quers aprender a hacer arte grco!

/the-big-list-of-graphics-programs-windows-edition/
/the-big-list-of-drawing-and--animation/
/the-big-list-of-pixel-art-tutorials/

15.1. Comercializacin
Hay varias maneras de comercializar nuestros juegos que listaremos a continuacin.

15.1.1. Publicidades
Publicidades dentro de nuestros juegos.

http://www.pixelprospector.com/advertising-places-to-buy-targeted-ad-space/

15.1.2. Sponsors
Gente compra tu juego para ponerlo en su sitio.

https://www.fgl.com/

89

15.1.3. Tiendas Online


Tiendas online de juegos donde podemos publicar nuestros juegos para venderlos.

http://www.pixelprospector.com/the-big-list-of-online-game-stores/

15.1.4. Venta Directa


El creador del juego vende su juego directamente a un tercero.

http://www.pixelprospector.com/the-big-list-of-payment-processors/

15.1.5. Tiendas Indie


Estas son tiendas donde es muy fcil subir nuestros primeros juegos. Tambin se crean
muchos game jams en estos sitios:

http://itch.io/
http://gamejolt.com/

15.2. Redes Sociales


Las redes sociales son muy buenas para mantenerse informado de lo que est pasando
en la comunidad. Y para conocer gente con la cual podemos trabajar, como por ejemplo
artistas que no se encuentran en las listas anteriores.
Twitter: til si segus la gente correcta, un hashtag til:
Reddit:

http://www.reddit.com/r/IndieGaming/
http://www.reddit.com/r/gamedev

90

#gamedev.

16. Game Jams


The right man in the wrong place can make all the dierence in the world
Half Life 2

Los game jams tienen 2 propsitos:


Prctica
Reconocimiento
Mientras ms gamejams hacemos, mejores somos haciendo juegos y ms gente nos
conoce. Una pgina que muestra todos los gamejams:

http://compohub.net/

16.1. Nuestro 3hr Game Jam


La idea inicial era participar de un 3hr Game Jam mundial, que todas las semanas
suben una palabra o frase, a partir de ella hay que desarrollar un juego. Por alguna razn
el da previsto los desarrolladores no actualizaron la palabra semanal.

16.2. La palabra elegida


Radiacin fue la palabra elegida por Peralta Rodrigo, es decir a partir de esa palabra
hay que desarrollar nuestro juego. Incluyendo la frase, reejando una idea relacionada y
cualquier otra idea que se te ocurra en 10 minutos.

16.3. Nuestros Juegos


16.3.1. Chernobyl Walker

91

Autores:
Bella Nicols.
Ilich Franco.
Passarino Ignacio.
Unanue Diego.

16.3.2. Green Goo Jump

Autor:
Rodrigo Peralta.

16.3.3. Radiation Scape


Autores:
Garzn Gonzalo.
Illbele Maximiliano.
Tresca Agustn.

92

16.3.4. Rodri Activo

Autores:
Arguello ngel.
Carrillo Florencia.
Moyano Miguel .
Verblud Javier David.

16.4. Y el Ganador es!


Luego de una larga evaluacin a cargo de Peralta Rodrigo se decidi que el mejor juego

la experiencia de participar. Todos subimos uno o dos lvls participando de la

misma
.
era

...

93

Referencias
[1] Haxe 2 Beginner's Guide - Benjamin Dasnois
[2] SMFL Game Development - Artur Moreira, Jan Haller, Henrik Vogelius Hansson
[3]

haxeflixel.com

94

Anda mungkin juga menyukai