Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gráficos y multimedia
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Puntos a tratar
•
Videojuegos para dispositivos móviles
•
Texturas en OpenGL
•
Motor Cocos2D
•
Escena 2D
•
Sprites
•
Fondos
•
Acciones
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Historia
1997
Del Snake ...
2010
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Videojuegos para dispositivos móviles
•
No están diseñados específicamente para jugar
•
Están más limitados que otros dispositivos
•
Escasa memoria / memoria de vídeo
•
Tamaño de la aplicación
•
Menor capacidad de procesamiento
•
Pantalla reducida
•
Diferente interfaz de entrada
•
Almacenamiento limitado
•
Poco ancho de banda
Y no tan
limitados
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Características de los juegos
•
Gran audiencia
•
Siempre los llevamos encima
•
Útiles para “hacer tiempo”
•
Intuitivos
•
Pausables
•
Guardar progreso
•
Rejugabilidad
•
Recompensas y logros
•
Juegos sociales
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Entretenimiento rápido
VS
Entretenimiento
rápido
Juego inmersivo
(Myst)
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Optimización de texturas
•
La memoria de video es limitada
•
Debemos reducir los binarios al máximo
•
Acelerar render
•
Formatos de textura
RGB8888
32 bits, canal alpha 8 bits
RGB4444
16 bits, canal alpha 4 bits
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Compresión de texturas
•
Existen formatos de compresión con pérdidas
–
Dependiente del disposiHvo
•
ATITC, PVRTC, DXT
–
Todos los disposiHvos OpenGL ES 2.0 soportan ETC1
• $ANDROID_SDK_HOME/tools/etc1tool
–
PVRTC
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
RBG8888 vs RGB4444
RGB8888
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Dithering
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Motores Open Source para móviles
http://www.andengine.org/
http://code.google.com/p/libgdx/
http://jmonkeyengine.com/
http://www.cocos2d-iphone.org/
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Plantilla de Cocos2D
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Gestión de estados en Cocos2D
•
La clase principal de Cocos2D es CCDirector
•
Tenemos un singleton que gestiona la ejecución del juego
•
Establece el estado actual, y permite transiciones a otros estados
•
Los estado se representan mediante escena (CCScene)
•
Las escenas contienen un grafo de nodos (CCNode)
•
Representan los elementos que intervienen en la escena
•
Sprites, fondos, texto, botones, capas
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Grafo de la escena 2D
CCSprite
CCLabel
CCLayer
CCAction
CCLayer
CCScene
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Capas
•
Las escenas normalmente tienen una capa principal
•
Implementamos una subclase de la capa (CCLayer)
@interface MenuPrincipalLayer : CCLayer +(CCScene *) scene;
@end
+(CCScene *) scene {
CCScene *scene = [CCScene node]; MenuPrincipalLayer *layer =
[MenuPrincipalLayer node]; [scene addChild: layer]; return scene;
}
-‐(id) init {
if( (self=[super init])) {
// Inicializar componentes de la capa
...
Inicializamos todos los
elementos de la capa
(nodos) y los añadimos
como hijos con addChild:
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Transiciones entre escenas
•
Mostrar escena inicial al ejecutar el juego
•
Cambiar a otra escena
•
Cambiar a otra escena con una transición
[[CCDirector sharedDirector] runWithScene: [MenuPrincipalLayer scene]];
[[CCDirector sharedDirector] replaceScene: [PuntuacionesLayer scene]];
[[CCDirector sharedDirector] replaceScene:
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Fuentes
•
Podemos utilizar dos tipos de fuentes
•
Fuentes TrueType del sistema
•
Fuentes bitmap personalizadas
•
Fuentes TrueType
•
Fuentes bitmap (formato.fnt)
CCLabelTTF *label = [CCLabelTTF labelWithString:@"Game Over"
fontName:@"Marker Felt"
fontSize:64]; [self addChild: label];
CCLabelBMFont *label = [CCLabelBMFont labelWithString:@"Game Over"
fntFile:@"fuente.fnt"]; [self addChild: label];
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Creación de fuentes bitmap
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Menús
•
Pueden contener items de texto o imágenes
CCMenuItemImage * item1 = [CCMenuItemImage
itemFromNormalImage:@"nuevo_juego.png"
selectedImage:@"nuevo_juego_selected.png"
target:self
selector:@selector(comenzar:)];
CCMenuItemImage * item2 = [CCMenuItemImage itemFromNormalImage:@"continuar.png"
selectedImage:@"continuar_selected.png"
target:self
selector:@selector(continuar:)];
CCMenuItemImage * item3 = [CCMenuItemImage itemFromNormalImage:@"opciones.png"
selectedImage:@"opciones_selected.png"
target:self
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Sprites
•
Se representan con la clase CCSprite
•
Se posicionan con position y anchorPoint, como todos los
nodos (ccp equivale a CGPointMake)
•
Podemos aplicar diferentes transformaciones
•
rotation, scale, scaleX, scaleY, skewX, skewY
self.sprite.position = ccp(240, 160);
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Fotogramas
•
Necesitamos diferentes fotogramas para cada sprite
•
Crearlos en diferentes imágenes malgastaría memoria de vídeo
•
Es recomendable empaquetarlos en sprite sheets
•
Todos los fotogramas en una misma imagen
•
Aprovecha el tamaño óptimo de texturas de OpenGL
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Carga de sprite sheets
•
Añadir contenido del sprite sheet a la caché de fotogramas
•
Cada fotograma se identifica por un nombre
•
Por defecto, el nombre de fichero de su imagen original
•
Como alternativa, podemos obtener primero el fotograma y a
partir de él el sprite
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile: @"sheet.plist"];
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Animación de sprites
•
Podemos definir una animación a partir de los fotogramas
•
Establecemos la periodicidad
•
La añadimos a la caché a animaciones
CCAnimation *animAndar = [CCAnimation animation];
[animAndar addFrame: [[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName: @"frame01.png"]]; [animAndar addFrame: [[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName: @"frame02.png"]];
animAndar.delay = 0.25;
[[CCAnimationCache sharedAnimationCache] addAnimation: animAndar
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Sprite batch
•
Optimiza la forma de renderizar sprites
•
En OpenGL los sprites son texturas mapeadas sobre geometría
•
Es más eficiente enviar toda la geometría en una única
operación, y después mapear la textura sobre ella
•
Se puede hacer para sprites que usen el mismo sprite sheet
•
Creamos un CCSpriteBatchNode y añadimos sprites como hijos
CCSpriteBatchNode *spriteBatch =
[CCSpriteBatchNode batchNodeWithFile:@"sheet.png"]; [self addChild:spriteBatch];
CCSprite *sprite1 = [CCSprite spriteWithSpriteFrameName:@"frame01.png"]; sprite1.position = ccp(50,20);
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Colisiones entre sprites
•
Detectar interacción entre sprites
•
Enemigo toca a nuestro personaje
•
Nuestra bala impactar en el enemigo
•
La intersección entre forma complejas es costosa
•
Simplificamos mediante un bounding box
•
Rectángulo que abarca el sprite
•
La intersección de rectángulos es muy sencilla
CGRect bbPersonaje = [spritePersonaje boundingBox]; CGRect bbEnemigo = [spriteEnemigo boundingBox];
if (CGRectIntersectsRect(bbPersonaje, bbEnemigo)) { // Game over
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Fondo
•
El fondo habitualmente es muy extenso
•
No podemos crear una imagen con todo el fondo del nivel
•
Creamos el fondo como un mosaico a partir de piezas
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Herramienta Tiled Map Editor
•
Se puede utilizar para crear el mosaico
•
Guarda el resultado en formato TMX
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Carga del mapa
•
Cocos2D soporta el formato TMX
•
Podemos añadirlo como nodo a la escena con addChild:
•
Dimensiones del mapa
•
Dimensiones de cada tile: ancho x alto
•
Celdas del mosaico: columnas x filas
•
Tamaño del mapa (ancho*columnas) x (alto*filas)
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Motor del juego
•
El elemento principal es el hilo del juego
•
CCDirector gestiona este ciclo, en cada iteración:
•
Dibuja los nodos de la escena actual
•
Actualiza los nodos de la escena actual
•
Sólo se dibujará y se actualizará la escena actualmente activa
while(true) {
leeEntrada();
actualizaEscena(); dibujaGraficos(); }
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Actualización de la escena
•
Podemos definir un método en nuestra escena que se ejecute
en cada iteración del ciclo del juego
•
Un buen lugar para definirlo es la subclase de CCLayer
•
Programamos la ejecución del método con
•
Implementamos el método anterior
[self schedule: @selector(update:)];
-‐ (void) update: (ccTime) dt {
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Acciones
•
Actualizan los nodos de la escena automáticamente
•
Hay acciones instantáneas y acciones con una duración
•
Todas derivan de CCAction
•
Por ejemplo, acción para mover un nodo a una posición
•
Ejecutar la acción
CCMoveTo *actionMoveTo = [CCMoveTo actionWithDuration: 3.0
position: ccp(200, 50)];
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Secuencia de acciones y repetición
•
Podemos crear una secuencia de acciones
•
Podemos repetir una acción o secuencia
CCPlace *actionPlace = [CCPlace actionWithPosition:ccp(0, 50)]; CCMoveTo *actionMoveTo = [CCMoveTo actionWithDuration: 3.0
position: ccp(200, 50)];
CCSequence *actionSequence =
[CCSequence actions: actionMoveTo, actionPlace, nil];
[sprite runAction: actionSequence];
CCRepeatForever *actionRepeat =
Especialista Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Animaciones
•
Podemos reproducir una animación por fotogramas de un sprite
mediante una acción CCAnimate
•
Debemos proporcionar el nombre de la animación en la caché de
animaciones
CCAnimate *animate = [CCAnimate actionWithAnimation: [[CCAnimationCache sharedAnimationCache]
animationByName:@"animAndar"]];
[self.spritePersonaje runAction: