PMYDM
PMYDM
PMYDM
PMYDM
PROGRAMACIÓN MULTIMEDIA Y DISPOSITIVOS
MÓVILES
• SmartPhones o "teléfonos inteligentes" es un tipo de ahorrar energía. En algunos casos, por ejemplo, podrían no
teléfono móvil construido sobre una plataforma disponer de la capacidad de cálculos en punto flotante.
informática móvil, con mayor capacidad de almacenar • Poca memoria principal (RAM).
datos y realizar actividades, semejante a la de una • Almacenamiento de datos persistente reducido (pequeña
minicomputadora, y con una mayor conectividad que un memoria flash interna, tarjetas SD, etc.).
teléfono móvil convencional. El término inteligente, que se • Conexión a algún tipo de red intermitente y con ancho de
utiliza con fines comerciales, hace referencia a la banda limitado.
capacidad de usarse como un computador de bolsillo, y • Pantallas de reducidas dimensiones.
llega incluso a reemplazar a una computadora personal
• Teclados con funcionalidad muy básica y muy pequeños.
en algunos casos.
• PDA (Personal Digital Assistant - asistentes digitales Este tipo de restricciones, y algunas otras que dependerán de cada
personales) o PocketPC (PC de bolsillo). dispositivo en concreto, habrán de ser tenidas muy en cuenta a la
• Handheld, o PCs de mano. hora del análisis y diseño de una aplicación "móvil", pues no podemos
pretender, que esa aplicación pueda contener la misma
• Internet tables, que se encontrarían entre las PDA y
funcionalidad, que la que podemos encontrar habitualmente en un
los PC Ultramóviles (pequeños tablet PC).
programa que es ejecutado en un ordenador de sobremesa o un
Según las fuentes que consultes puedes encontrar diversas portátil.
clasificaciones donde se incluyan unos u otros tipos de dispositivos,
Por otro lado, no todo va a ser restricciones. También habrá que
como por ejemplo:
tener en consideración que esta tecnología va a aportar una serie
• Pagers (o buscapersonas), hoy día ya en desuso. de ventajas muy importantes: movilidad, poco peso, pequeño
al hablar de dispositivos móviles serán los smartPhones y DESARROLLAR SOBRE ESE HARDWARE Y ESE SISTEMA OPERATIVO? ¿CON QUÉ
las tablets. Por otro lado, según la tecnología vaya avanzando te LENGUAJES PUEDO PROGRAMAR? ¿QUÉ HERRAMIENTAS (COMPILADORES,
podrás ir encontrando con nuevos tipos de productos y servicios que BIBLIOTECAS, ENTORNOS, ETC.) HAY DISPONIBLES?
para otras plataformas, como pueden ser las aplicaciones • Función multimedia (cámara digitales integradas y
de escritorio para los PCs o las aplicaciones web (Java, C#, reproductor de videos/mp3), Capacidades fotográficas.
C, etc.). Grabación de audio y vídeo.
• Receptor GPS.
En definitiva puedes observar que en este nuevo mundo del
• Receptor de radio FM.
desarrollo para dispositivos móviles te encuentras con una
problemática similar a la que te puedes enfrentar con los
• Emisor de radio FM.
ordenadores convencionales: distintos tipos de hardware, distintas • Posibilidad de instalar y ejecutar aplicaciones sofisticadas:
opciones de sistemas operativos dependiendo del hardware que los
o Aplicaciones de asistente personal (gestión de
soporte, diferentes lenguajes de programación, plataformas, API y
contactos, calendarios, citas, agendas, alarmas,
bibliotecas, entornos de desarrollo, etc.
etc.).
normal. Hoy día una buena parte de los teléfonos móviles que se
o Diccionarios.
• Los teléfonos HTC de las series A (con sistema Hoy día se han convertido en pequeños ordenadores "de mano"
operativo Android), S (con sistema operativo Windows ("palmtop") o "de bosillo" ("pocket") capaces de realizar muchas de las
Phone), T (Windows Phone con Touch), funciones que realizaría un ordenador personal convencional tales
o P (teléfonos PDA). como crear documentos con un procesador de textos, manejar hojas
• Las series Galaxy y Nexus de Samsung (con Android). de calculo, jugar, navegar por Internet, enviar y recibir correo
• En general cualquier fabricante de terminales de telefonía electrónico, transferir archivos por una red local, ver películas,
móvil actual desarrolla smartPhones. reproducir archivos de audio o vídeo, etc. Es decir, que mientras que
un ordenador convencional de escritorio ("desktop") se coloca sobre
El interior de un smartphone. la mesa ("desk"), el portátil ("laptop") es un ordenador que puedes
Si se te ocurriera abrir un teléfono móvil actual te encontraríamos poner sobre el regazo ("lap"), y un ordenador de mano ("palmtop") lo
una placa de circuito impreso con una serie de dispositivos puedes situar en la palma de la mano ("palm").
electrónicos integrados o insertos en ella. En cierto modo podría
recordar un poco a la placa base de un PC. Entre los dispositivos que Una de sus principales características externas es su pantalla
podrías observar se encontrarían el procesador principal, táctil y el lápiz-marcador (o estilete digital) para interactuar con
procesadores digitales de señal (DSP), procesadores de imagen y de ella. Debido a esto suelen tener pocos botones pues la mayoría de
audio, módem, memorias caché, etc. A este conjunto de dispositivos las tareas se pueden realizar mediante el estilete sobre la pantalla
integrados en la placa se le suele llamar chipset (lo cual te debería táctil. Normalmente tienen un mayor tamaño que la mayoría de los
recordar al mundo del hardware de los PCs y a los conceptos teléfonos móviles, sobre todo la pantalla.
La principal arquitectura de microprocesadores utilizada para receptores de GPS o incluso la funcionalidad de telefonía móvil,
telefonía móvil es la diseñada por la empresa ARM ("Advanced RISC llegándose a confundir en muchas ocasiones la ambigua frontera
Machines", hoy día ARM Holdings), teniendo actualmente más del entre smartPhone y PDA. Es decir, que hay PDA que llegan a
90% de la cuota de mercado no ya sólo para teléfonos móviles, sino convertirse en auténticos teléfonos móviles inteligentes, y teléfonos
en general para todo tipo de pequeños dispositivos electrónicos que móviles que llegan a transformarse en PDA con posibilidad de
necesitan un microprocesador. Algunas de las familias de realizar llamadas telefónicas. Un ejemplo típico de dispositivos de
micros ARM más conocidas son las en su versión de bajo consumo "difícil" clasificación entre smartPhone y PDA podrían ser las
y rendimiento A57, y alto consumo y rendimiento como la A78. Hoy conocidas BlackBerries.
Los sistemas operativos más habituales que te puedes encontrar de Google Phone o GPhone) en 2008.
• Maemo OS. Desarrollado por Nokia para smartPhones, Electronics, Sprint Nextel, Intel, LG, Marvell Technology Group,
PDA e Internet tables. Motorola, y T-Mobile; se estrenó con el fin de desarrollar estándares
abiertos para dispositivos móviles. Junto con la formación de la
• Bada. Desarrollado por Samsung.
Open Handset Alliance, la OHA estrenó su primer producto, Android,
Hay que tener en cuenta que a medida que los teléfonos móviles una plataforma para dispositivos móviles construida sobre la
crecen en popularidad, los sistemas operativos con los que trabajan versión 2.6 de Linux.
también adquieren mayor importancia. Según un artículo en la
El 9 de diciembre de 2008, se anunció que 15 nuevos miembros se
publicación "Kantar.com", la cuota de mercado de sistemas
unirían al proyecto Android, incluyendo PacketVideo, ARM
operativos móviles en 2015 era la siguiente:
Holdings, Atheros Communications, Asustek,
1. Android: 81% Garmin, Softbank, Sony Ericsson, Huawei, Toshiba, Vodafone y ZTE.
2. iOS: 11%
El 24 de febrero de 2014 Nokia presentó sus teléfonos
3. Windows Phone: 8%
inteligentes corriendo Android 4.1 "Jelly Bean" (aunque corriendo una
Como puedes observar, Android tiene la mayor cuota con diferencia. versión propia, tomando la base de AOSP). Se trata de los Nokia X,
X+ y XL
Hace unos años el sistema operativo más usado era Symbian OS,
ahora en desuso. Fue a lo largo del año 2011 cuando Android se colocó En Google, el equipo liderado por Rubin desarrolló una plataforma
por delante de Symbian OS en la cuota de mercado. Como siempre para dispositivos móviles basada en el núcleo Linux que fue
sucede en el mundo de la tecnología, habrá que estar muy pendiente promocionado a fabricantes de dispositivos y operadores con la
de las últimas noticias para tener una buena perspectiva de lo que promesa de proveer un sistema flexible y actualizable. Se informó
nos vamos a encontrar en el mercado durante los próximos año. que Google había alineado ya una serie de fabricantes de hardware
y software y señaló a los operadores que estaba abierto a diversos
Vamos a hacer un rápido repaso de algunos de los sistemas
grados de cooperación por su parte.
operativos más conocidos Android, iOS y Windows Phone, así
como Symbian OS por su relevancia histórica. Hoy en día podemos encontrar multitud de fabricantes que
incorporan Android en sus terminales: Samsung (series Galaxy y
Android. Note), Huawei (Series P y Mate sin los servicios de
ANDROID FUE INICIALMENTE DESARROLLADO POR ANDROID INC., HOY DÍA PARTE Google), Xiaomi, Oppo, etc.
DE LA COMPAÑÍA GOOGLE. ESTÁ BASADO EN UNA VERSIÓN MODIFICADA DEL
Android ha visto numerosas actualizaciones desde su liberación
KERNEL DE LINUX.
inicial. Estas actualizaciones al sistema operativo base típicamente
El primer fabricante que incorporó Android en sus dispositivos arreglan bugs (errores o fallo en el software) y agregan nuevas
fue HTC con su terminal HTC Dream (comercializado también funciones (debuggers). Podemos observar que los nombres de las
versiones del sistema operativo Android corresponden con postres
y que, además, según avanzan la versión avanza alfabéticamente la sean reemplazados por el usuario. Los desarrolladores
letra del postre por orden alfabético (Android 1.0 Apple Pie, Android tienen acceso completo a los mismos APIs del framework
1.1. Banana Bread, Android 1.5 Cupcake, Android 1.6 Donut, etc.). usados por las aplicaciones base.
Actualmente, a febrero de 2021, la última de versión de Android es • Bibliotecas: Android incluye un conjunto de bibliotecas
la 11.0. de C/C++ usadas por varios componentes del sistema.
Estas características se exponen a los desarrolladores a
Bugs (bicho) es un error o fallo en un programa de computador o
través del marco de trabajo de aplicaciones de Android;
sistema de software que desencadena un resultado indeseado. Los
algunas son: System C library (implementación biblioteca
programas que ayudan a la detección y eliminación de errores de
C estándar), bibliotecas de medios, bibliotecas de gráficos,
programación de software son denominados depuradores
3D y SQLite, entre otras.
(debuggers).
• Runtime de Android: Android incluye un set de bibliotecas
La reiterada aparición de nuevas versiones que, en muchos casos, base que proporcionan la mayor parte de las funciones
no llegan a funcionar correctamente en el hardware diseñado para disponibles en las bibliotecas base del lenguaje Java. Cada
versiones previas, hacen que Android sea considerado uno de los aplicación Android corre su propio proceso, con su propia
elementos promotores de la obsolescencia programada o instancia de la máquina virtual Dalvik. Desde la versión
planificada que se refiere a es la determinación o programación del 5.0 utiliza el ART, que compila totalmente al momento de
fin de la vida útil de un producto, de modo que, tras un período de instalación de la aplicación.
tiempo calculado de antemano por el fabricante o por la empresa
durante la fase de diseño de dicho producto, este se torne obsoleto, ANDROID RUNTIME (ART) ES UN ENTORNO DE EJECUCIÓN DE APLICACIONES
no funcional, inútil o inservible. UTILIZADO POR EL SISTEMA OPERATIVO MÓVIL ANDROID. ART REEMPLAZA A
DALVIK, QUE ES LA MÁQUINA VIRTUAL UTILIZADA ORIGINALMENTE POR ANDROID,
Android ha sido criticado muchas veces por la fragmentación que Y LLEVA A CABO LA TRANSFORMACIÓN DE LA APLICACIÓN EN INSTRUCCIONES DE
sufren sus terminales al no ser soportado con actualizaciones MÁQUINA, QUE LUEGO SON EJECUTADAS POR EL ENTORNO DE
constantes por los distintos fabricantes. Se creyó que esta situación EJECUCIÓN NATIVO DEL DISPOSITIVO.
cambiaría tras un anuncio de Google en el que comunicó que los
fabricantes se comprometerán a aplicar actualizaciones al menos Características y especificaciones actuales de Android.
18 meses desde su salida al mercado, pero esto al final nunca se Almacenamiento SQLite, una base de datos liviana, que es usada
concretó y el proyecto se canceló. Google actualmente intenta para propósitos de almacenamiento de datos.
enmendar el problema con su plataforma actualizable Servicios de Entorno de desarro- Incluye un emulador de dispositivos, herramientas
Google Play (que funciona en Android 2.2 y posteriores), separando llo para depuración de memoria y análisis del rendi-
todas las aplicaciones posibles del sistema (como Maps, el teclado, miento del software. Inicialmente el entorno de
Youtube, Drive, e incluso la propia Play Store) para poder desarrollo integrado (IDE) utilizado era Eclipse con
actualizarlas de manera independiente, e incluyendo la menor el plugin de Herramientas de Desarrollo de An-
cantidad posible de novedades en las nuevas versiones de Android. droid (ADT). Ahora se considera como entorno ofi-
cial Android Studio, descargable desde la página
PARA DESARROLLAR APLICACIONES SOBRE ANDROID SE NECESITA EL KIT DE oficial de desarrolladores de Android.
DESARROLLO DE SOFTWARE PARA ANDROID (ANDROID Diseño de disposi- La plataforma es adaptable a pantallas de mayor
STUDIO, ANTERIORMENTE SDK), PROPORCIONADO GRATUITAMENTE tivo resolución, VGA, biblioteca de gráficos 2D, biblioteca
POR ANDROID. ESTE PAQUETE INCLUYE TODO LO NECESARIO PARA CONSTRUIR de gráficos 3D basada en las especificaciones de la
OpenGL ES 2.0 y diseño de teléfonos tradicionales.
APLICACIONES SOBRE EL ENTORNO ANDROID (DEPURADOR, BIBLIOTECAS,
Conectividad Android soporta las siguientes tecnologías de co-
EMULADOR, DOCUMENTACIÓN, ETC.). EL LENGUAJE DE PROGRAMACIÓN QUE SE
nectividad: GSM/EDGE, IDEN, CDMA, EV-DO, UMTS,
UTILIZA ES JAVA (Y POR TANTO ES NECESARIO EL JDK DE ORACLE PARA
Bluetooth, Wi-Fi, LTE, HSDPA, HSPA+, NFC y
PODER COMPILAR PROGRAMAS JAVA). ANDROID STUDIO TAMBIÉN INCORPORA
WiMAX, GPRS, UMTS y HSDPA+.
EL IDE OFICIAL, SUSTITUYENDO A ECLIPSE.
Mensajería SMS y MMS son formas de mensajería, inclu-
yendo mensajería de texto y ahora la Android
Arquitectura de Android
Cloud to Device Messaging Framework (C2DM) es
El sistema operativo de Android tiene los siguientes componentes: parte del servicio de Push Messaging de Android.
Navegador web El navegador web incluido en Android está basado
• Núcleo Linux: Android depende de Linux para los servicios
en el motor de renderizado de código abierto
base del sistema como seguridad, gestión de memoria,
WebKit, emparejado con el motor JavaScript V8
gestión de procesos, pila de red y modelo de controladores.
de Google Chrome. El navegador por defecto de Ice
• Aplicaciones: las aplicaciones están escritas en lenguaje de Cream Sandwich obtiene una puntuación de
programación Java. 100/100 en el test Acid3.
• Marco de trabajo de aplicaciones: la arquitectura está Soporte de Java Aunque la mayoría de las aplicaciones están escri-
diseñada para simplificar la reutilización de componentes; tas en Java, no hay una máquina virtual Java en
cualquier aplicación puede publicar sus capacidades y la plataforma. El bytecode Java no es ejecutado,
cualquier otra aplicación puede luego hacer uso de esas sino que primero se compila en un ejecutable Dal-
capacidades (sujeto a reglas de seguridad del framework). vik y se ejecuta en la Máquina Virtual Dalvik, Dal-
vik es una máquina virtual especializada, diseñada
Este mismo mecanismo permite que los componentes
específicamente para Android y optimizada para Versiones de Android.
dipositivos móviles que funcionan con batería y Las versiones de Android reciben, en inglés, el nombre de
que tienen memoria y procesador limitados. A
diferentes postres o dulces. En cada versión el postre o dulce elegido
partir de la versión 5.0, se utiliza el Android Run-
empieza por una letra distinta, conforme a un orden alfabético.
time (ART). El soporte para J2ME puede ser agre-
gado mediante aplicaciones de terceros como el Nombre código Número de Fecha de lanzamiento Ni-
J2ME MIDP Runner. versión vel
Soporte multimedia Android soporta los siguientes formatos multime- de
dia: WebM, H.263, H.264 (en 3GP o MP4), MPEG-4 API
SP, AMR, AMR-WB (en un contenedor 3GP), AAC, A Apple Pie 1.0 23 de septiembre de 1
HE-AAC (en contenedores MP4 o 3GP), MP3, MIDI, 2008
Ogg Vorbis, WAV, JPEG, PNG, GIF y BMP. B Banana Bread 1.1 9 de febrero de 2009 2
Soporte para strea- Streaming RTP/RTSP (3GPP PSS, ISMA), descarga C Cupcake 1.5 27 de abril de 2009 3
ming progresiva de HTML (HTML5 <video> tag). Adobe D Donut 1.6 15 de septiembre de 4
Flash Streaming (RTMP) es soportado mediante el 2009
Adobe Flash Player. Se planea el soporte de Micro-
E Eclair 2.0–2.1 26 de octubre de 2009 5–7
soft Smooth Streaming con el port de Silverlight
F Froyo 2.2–2.2.3 20 de mayo de 2010 8
a Android. Adobe Flash HTTP Dynamic Streaming
G Gingerbread 2.3–2.3.7 6 de diciembre de 2010 9–10
estará disponible mediante una actualización de
H Honeycomb 3.0–3.2.6 22 de febrero de 2011 11–13
Adobe Flash Player.
I Ice Cream Sand- 4.0–4.0.4 18 de octubre de 2011 14–
Soporte para hard- Android soporta cámaras de fotos, de vídeo, pan-
wich 15
ware adicional tallas táctiles, GPS, acelerómetros, giroscopios,
J Jelly Bean 4.1–4.3.1 9 de julio de 2012 16–
magnetómetros, sensores de proximidad y de pre-
18
sión, sensores de luz, gamepad, termómetro, ace-
K KitKat 4.4–4.4.4, 31 de octubre de 2013 19–
leración por GPU 2D y 3D.
4.4W–4.4W.2 20
Google Play Google Play es un catálogo de aplicaciones gratui-
L Lollipop 5.0–5.1.1 12 de noviembre de 21–
tas o de pago en el que pueden ser descargadas e
2014 22
instaladas en dispositivos Android sin la necesidad
M Marshmallow 6.0–6.0.1 5 de octubre de 2015 23
de un PC.
N Nougat 7.0 15 de junio de 2016 24
Multi-táctil Android tiene soporte nativo para pantallas capa-
O Oreo 8.0 – 8.1 21 de agosto de 2017 26-
citivas con soporte multi-táctil que inicialmente
27
hicieron su aparición en dispositivos como el HTC
P Pie 9 6 de agosto de 2018 28
Hero. La funcionalidad fue originalmente desacti-
vada a nivel de kernel (posiblemente para evitar Q Android 10 10 3 de septiembre de 29
infringir patentes de otras compañías). Más tarde, 2019
Google publicó una actualización para el Nexus One - Android 11 11 8 de septiembre de 30
y el Motorola Droid que activa el soporte multi- 2020
táctil de forma nativa. - Android 12 12 En desarrollo 31
Bluetooth El soporte para A2DF y AVRCP fue agregado en la
versión 1.5; el envío de archivos (OPP) y la explora-
Debes conocer
ción del directorio telefónico fueron agregados en
la versión 2.0; y el marcado por voz junto con el
¿Sabes lo que es API?
envío de contactos entre teléfonos lo fueron en la
versión 2.2. Los cambios incluyeron: API es la interfaz de programación de aplicaciones, abreviada
Videollamada Android soporta videollamada a través de Han- como API (del inglés: Application Programming Interface), es
gouts (ex-Google Talk) desde su versión Honey- el conjunto de subrutinas, funciones y procedimientos (o métodos,
Comb. en la programación orientada a objetos) que ofrece
Multitarea Multitarea real de aplicaciones está disponible, es cierta biblioteca para ser utilizado por otro software como una capa
decir, las aplicaciones que no estén ejecutándose de abstracción. Son usadas generalmente en las bibliotecas de
en primer plano reciben ciclos de reloj.
programación.
Características ba- La búsqueda en Google a través de voz está dis-
sadas en voz ponible como "Entrada de Búsqueda" desde la ver- Una API representa la capacidad de comunicación entre
sión inicial del sistema. componentes de software. Uno de los principales propósitos de una
Tethering Android soporta tethering, que permite al teléfono API consiste en proporcionar un conjunto de funciones de uso
ser usado como un punto de acceso alámbrico o general, por ejemplo, para dibujar ventanas o iconos en la pantalla.
inalámbrico (todos los teléfonos desde la versión De esta forma, los programadores se benefician de las ventajas de
2.2, no oficial en teléfonos con versión 1.6 o inferio-
la API haciendo uso de su funcionalidad, evitándose el trabajo de
res mediante aplicaciones disponibles en Google
programar todo desde el principio. Las API asimismo son abstractas:
Play (por ejemplo PdaNet). Para permitir a un PC
el software que proporciona una cierta API generalmente es
usar la conexión de datos del móvil Android se po-
llamado la implementación de esa API.
dría requerir la instalación de software adiciona
Por ejemplo, se puede ver la tarea de escribir "Hola Mundo" sobre la - MONITOR DE 1280X800.
pantalla en diferentes niveles de abstracción: - JAVA DEVELOPMENT KIT 7.
el sistema operativo. Cuando hagas clic en Run o Debug, la función Instant Run de
Android Studio aplicará los cambios en el código y los recursos
2. Haz que el sistema operativo borre la pantalla.
en tu aplicación en ejecución. Esta interpreta de manera inteli-
3. Haz que el sistema operativo dibuje el texto
gente los cambios y a menudo los entrega sin reiniciar tu app ni
"Hola Mundo" usando la fuente cargada.
volver a compilar tu APK, para que puedas ver los efectos de
3. Usando una aplicación (que a su vez usa el sistema
inmediato.
operativo) para realizar la mayor parte del trabajo:
Editor de código inteligente
1. Escribe un documento HTML con las palabras
Al ofrecer compleción avanzada de código, refactorización y aná-
"Hola Mundo" para que un navegador web lisis de código, el editor de código inteligente te permite escribir
como Firefox, Chrome, Opera, Safari, Midori, un código más eficaz, trabajar más rápido y ser más productivo.
Iceweasel, Web o Internet Explorer pueda A medida que escribes, Android Studio proporciona sugerencias
representarlo en el monitor. en una lista desplegable. Simplemente presiona Tab para inser-
tar el código.
Android Studio: Desarrollo en Android Emulador rápido y cargado de funciones
Android Studio es el IDE oficial de Android. Está diseñado para que Android Emulator se instala e inicia tus apps más rápido que un
Android pueda acelerar el desarrollo y te permita crear las apps de dispositivo real. También te permite crear prototipos de tu app y
mejor calidad para todos los dispositivos de Android y, por tanto, probarlos en todas las configuraciones de dispositivos Android:
proporciona las herramientas más rápidas para la creación de teléfonos, tablets y dispositivos Android Wear y Android TV.
aplicaciones en todos los tipos de dispositivos Android. También puedes simular varias funciones de hardware, como la
localización de GPS, la latencia de red y las funciones multitácti-
Es un entorno de desarrollo integrado para la plataforma Android. les.
Fue anunciado el 16 de mayo de 2013 en la conferencia Google I/O, y Configuración ilimitada de compilaciones
reemplazó a Eclipse como el IDE oficial para el desarrollo de La estructura de proyectos y las compilaciones basadas
aplicaciones para Android. La primera versión estable fue publicada en Gradle de Android Studio te brindan la flexibilidad que
en diciembre de 2014. necesitas para generar APK para toda clase de dispositi-
vos.
Está basado en el software IntelliJ IDEA de JetBrains, y es publicado Sistema de compilación sólido y flexible
de forma gratuita a través de la Licencia Apache 2.0. Está disponible Android Studio ofrece automatización de compilaciones, adminis-
para las plataformas Microsoft Windows, Mac OS X y GNU/Linux. tración de dependencias y configuraciones de compilación perso-
nalizables. Puedes configurar tu proyecto de modo que se incor-
Android Studio está disponible para Windows 2003, Vista, 7, 8, 10 y
poren bibliotecas locales y alojadas, y definir variantes que inclu-
GNU/Linux, tanto plataformas de 32 como de 64 bits, Linux con yan código y recursos diferentes, además de aplicar configura-
GNOME o KDE y 2 GB de memoria RAM mínimo y Mac OS X, desde ciones de reducción de código y firma de apps.
10.8.5 en adelante. Diseño para equipos
Android Studio se integra con herramientas de control de ver-
ANDROID STUDIO ESTÁ DISPONIBLE PARA WINDOWS 2003, VISTA, 7, 8, 10 Y sión, como GitHub y Subversion, para que puedas mantener a tu
GNU/LINUX, TANTO PLATAFORMAS DE 32 COMO DE 64 BITS, LINUX CON equipo actualizado respecto de los cambios en proyectos y com-
GNOME O KDE Y 2 GB DE MEMORIA RAM MÍNIMO Y MAC OS X, DESDE 10.8.5 pilaciones. El sistema de compilación de código abierto de Gradle
EN ADELANTE. te permite adaptar la compilación a tu entorno y ejecutarla en
un servidor de integración continua, como Jenkins.
LOS REQUISITOS DEL SISTEMA PARA LAS TRES PLATAFORMAS SON:
Crea código con confianza
- 2 GB DE RAM (4 GB RECOMENDADOS). A cada paso, Android Studio te permite asegurarte de
crear el mejor código posible.
- 400 MB DE ESPACIO EN DISCO.
Plantillas de código y apps de ejemplo
- 1 GB PARA ANDROID SDK.
En Android Studio se incluyen plantillas de proyectos y código de dispositivos Nokia (ha sido principalmente desarrollada por ellos),
que facilitan la adición de patrones bien establecidos, como un como los de las series N o E y algunos modelos del XpressMusic.
panel lateral de navegación y un paginador de vistas. También También otros fabricantes como Samsung (por ejemplo en el L870)
puedes importar apps totalmente funcionales desde GitHub di- han incorporado la interfaz de usuario S60 en algunos de sus
recto desde la pantalla Create Project. Puedes experimentar con dispositivos.
estas apps, creadas por Google y otros, y también reutilizarlas.
Lintelligence Otras plataformas/interfaces de usuario de Symbian han sido la
Android Studio ofrece un framework de análisis sólido y estático, serie S80 (para los Nokia 92xx, 93xx y 95xx), la S90, UIQ (en
e incluye más de 280 verificaciones de Lint diferentes en toda tu los Sony Ericsson series P800 y P900 o los Motorola RIZR serie Z)
app. A su vez, proporciona varias correcciones rápidas que te per- y MOAP.
miten solucionar con un clic problemas en diferentes aspectos,
como el rendimiento, la seguridad y la corrección. Para el desarrollo de aplicaciones sobre Symbian se utilizó
Herramientas y frameworks de prueba inicialmente una versión específica de C++, aunque hoy día se emplea
Android Studio proporciona una gran cantidad de herramientas C++ estándar con el framework Qt. Los entornos de desarrollo más
y frameworks para ayudarte a probar tus apps de Android. Crea habituales para programar sobre Symbian son Carbide.C++ (basado
y ejecuta código de prueba para tus apps, incluidas pruebas de en Eclipse), o bien QtCreator.
JUnit 4 y de IU funcional. Puedes ejecutar tus pruebas en un
dispositivo, un emulador, un entorno de integración continua o También se pueden desarrollar aplicaciones
Firebase Test Lab. sobre Symbian utilizando Python (Python para S60), Adobe
Crea apps completas y conectadas Flash o Java ME.
Android Studio reconoce que no todo el código se escribe
La última versión de Symbian es OS 10. Nokia Belle, Feature Pack
en Java y tampoco se ejecuta en el dispositivo del usuario.
2., con el lanciamiento el 11 de octubre de 2012 en forma de
Compatibilidad con C++ y NDK
Android Studio te permite usar C++ y el Android NDK junto con actualización.
para cada densidad. Con Vector Asset Studio puedes seleccionar Embeded), y de hecho la familia de sistemas operativos
íconos de diseño de material design proporcionados por Google o de Microsoft para sistemas empotrados en general
cargar tu propio archivo SVG. Vector Asset Studio luego genera (smartPhones, PDA y otros pequeños dispositivos) sigue
archivos de mapa de bits para cada densidad de pantalla a fin llamándose Windows CE, así como el núcleo del sistema operativo.
de admitir versiones anteriores de Android no compatibles con
Algunos de los primeros Windows CE podían encontrarse en
el formato dibujable en vector.
Editor de traducciones dispositivos como las PDA iPAQ de Compaq (hoy día parte de HP),
Translations Editor te proporciona una vista única de todos tus las cuales surgieron como competencia directa de
recursos traducidos, lo cual facilita la modificación o adición de las PDA de Palm (las Palm Pilot) durante la segunda mitad de la
traducciones, y la localización de traducciones faltantes sin abrir década de los noventa. Las iPAQ con Windows CE ofrecían un
cada versión del archivo strings.xml. Proporciona, incluso, un entorno más parecido al Windows de los ordenadores de escritorio
vínculo para pedir servicios de traducción. frente al aspecto más sobrio de la interfaz de usuario de Palm OS.
sutituirá a Windows Phone. DESARROLLO QUE PERMITA GENERAR CÓDIGO EJECUTABLE SOBRE ESOS
Respecto a la plataforma, habría que elegir entre aquellas que estén el hardware (instrucciones máquina), realizar las llamadas al
relacionadas con Java (Java ME, Android). Finalmente se ha sistema operativo necesarias, velar por la seguridad e integridad del
decidido Java ME, que es la que lleva algo más de tiempo código ejecutado, etc.
BIEN DEPENDIENDO CUÁLES SEAN LAS NECESIDADES DE TU CLIENTE. ÉSA ES UNA Por otro lado, una única plataforma de Java podría no encajar
BUENA RAZÓN PARA INTENTAR ESTAR SIEMPRE AL DÍA. adecuadamente con todos los modelos de dispositivos posibles. Es
por ello por lo que Java ME introdujo los conceptos de configuración
El entorno de ejecución y de perfil.
Entorno de desarrollo en Android. Instalación de Las dos máquinas virtuales disponibles en Java ME son la KVM (K
Android Sudio y características. Virtual Machine, se le ha dado ese nombre porque sólo ocuparía
Android Studio es el entorno de desarrollo integrado (IDE) oficial unos pocos Kilobytes de memoria) y la CVM (Compact Virtual
para el desarrollo de aplicaciones para Android y se basa en IntelliJ Machine), algo más pesada.
IDEA .
Configuración del IDE de Android Studio.
Además del potente editor de códigos y las herramientas para Android Studio facilita varias plantillas que ayudan a cumplir con
desarrolladores de IntelliJ. Android Studio ofrece aún más funciones las especificaciones de tu sistema, como el Java Development Kit
que aumentan tu productividad durante la compilación de apps para (JDK) y la memoria RAM disponible, y configuran los ajustes y
Android, como las siguientes: requisitos predeterminados, como una emulación optimizada
predeterminada del Android Virtual Device (AVD) e imágenes del
• Sistema de compilación flexible basado en Gradle. sistema actualizadas.
• Un emulador rápido con varias funciones.
• Un entorno unificado en el que puedes realizar desarrollos Creación de un proyecto en Android
para todos los dispositivos Android. Cada proyecto en Android Studio contiene uno o más módulos con
• Instant Run, para aplicar cambios mientras tu app se archivos de código fuente y archivos de recursos.
ejecuta sin la necesidad de compilar un nuevo APK.
Entre los tipos de módulos se incluyen los siguientes:
• Integración de plantillas de código y GitHub, para ayudarte
a compilar funciones comunes de las apps e importar • Módulos de apps para Android.
ejemplos de código. • Módulos de bibliotecas.
• Módulos de Google App Engine. Interfaz de usuario de Android Studio.
La ventana principal de Android Studio consta de varias áreas
De forma predeterminada, en Android Studio se muestran los
lógicas que se identifican en la siguiente imagen:
archivos de tu proyecto en la vista de proyectos de Android.
También puedes personalizar la vista de los archivos del proyecto 1. La barra de herramientas te permite realizar una gran
para concentrarte en aspectos específicos del desarrollo de tu app. variedad de acciones, como la ejecución de tu app y el inicio
Por ejemplo, al seleccionar la vista Problems de tu proyecto, de herramientas de Android.
aparecerán enlaces a los archivos de origen que contengan errores 2. La barra de navegación te ayuda a explorar tu proyecto y
conocidos de codificación y sintaxis, como una etiqueta de cierre abrir archivos para editar. Proporciona una vista más
faltante para un elemento XML en un archivo de diseño. compacta de la estructura visible en la ventana Project.
3. La ventana del editor es el área en la que puedes crear y
modificar código. Según el tipo de archivo actual, el editor
puede cambiar. Al visualizar un archivo de diseño, por
ejemplo, el editor muestra el Editor de diseño.
4. Las ventanas de herramientas te permiten acceder a
tareas específicas, como la administración de proyectos, la
búsqueda y los controles de versión, entre otras. Puedes
expandirlas y contraerlas.
5. En la barra de estado se muestra el estado de tu proyecto
y el IDE, además de advertencias o mensajes.
Un emulador de Android en un ordenador puede tener miles de Android Studio crea automáticamente directorios de módulos, como
usos, desde un desarrollador que quiere probar sus aplicaciones fuente de recursos y directorios, y un archivo build.gradle defecto
hasta usuarios que quieran jugar con teclado y ratón a los cientos más adecuados para el tipo de dispositivo. Además, Android Studio
de títulos disponibles en esta plataforma. También es una forma de crea módulos de dispositivos con configuraciones de construcción
acceder a aplicaciones que no tenemos disponibles en un ordenador recomendadas, como el uso de la biblioteca de módulos Leanback
y que usamos constantemente cuando estamos con el móvil o Android TV.
tableta.
Modelo de estados de una aplicación
Instalación y ejecución en un dispositivo real.
Las actividades son uno de los componentes fundamentales de las
Como ya se ha comentado antes, algo que debes tener en cuenta apps en la plataforma de Android. Sirven como punto de entrada
cuando se desarrollan aplicaciones con la tecnología Java ME (y en para la interacción del usuario con una app y también son
general para casi cualquier plataforma) es que el aspecto que fundamentales para el usuario que navega en una app (como con
presente el midlet puede que sea diferente en un dispositivo real el botón Atrás) o entre apps (como con el botón Recientes).
con respecto al que se podía observar en un emulador. Es muy
Cuando un usuario navega por tu app, sale de ella y vuelve a entrar,
las instancias de Activity de tu app pasan por diferentes estados de
su ciclo de vida. La clase Activity proporciona una serie de
devoluciones de llamada que permiten a la actividad saber que
cambió un estado, es decir, que el sistema está creando, deteniendo
o reanudando una actividad, o finalizando el proceso en el que se
encuentra.
Para navegar por las transiciones entre las etapas del ciclo de vida
de una actividad, la clase Activity proporciona un conjunto básico de
seis devoluciones de llamadas: onCreate(), onStart(), onResume(),
onPause(), onStop() y onDestroy(). El sistema invoca cada una de
estas devoluciones de llamada cuando una operación entra en un
nuevo estado.
Tema 2. Programación de aplicaciones para dispositivos móviles (I)
Herramientas y fases de construcción el entorno de desarrollo elegido: S. Lo harás del mismo modo que se
suele hacer con todos los lenguajes: mediante el desarrollo de la
En la unidad anterior ya se ha avanzado algo sobre las
clásica aplicación "Hola Mundo".
herramientas que podrían utilizarse para desarrollar una aplicación
de tipo midlet. Como ya has debido ver anteriormente en el módulo Lo primero que hay que hacer para desarrollar una
de Programación, una aplicación Android podrá ser desarrollada aplicación Android con Android Studio es lo mismo que se hace con
utilizando herramientas a través de la línea de órdenes o bien cualquier tipo de aplicación Java: crear un proyecto NetBeans. En
mediante la utilización de un entorno integrado (IDE). Sea cual sea este caso será un proyecto de tipo aplicación móvil. Una vez creado
el método que se utilice para el desarrollo del código, podrás el proyecto, habrá que ir incluyendo y programando clases Java en
distinguir las siguientes fases de construcción para una aplicación él. La primera clase Java que tendrás que escribir será el programa
basada en Java ME: principal de la aplicación. El programa principal de un activity se
encuentra dentro de una clase que será subclase
• Desarrollo del código.
de AppCompatActivity y que tendrá una serie de métodos que
• Compilación.
heredará de ella. A partir de ahí, irás incluyendo el código necesario
• Preverificación. en tu clase midlet para dotar a tu aplicación de la funcionalidad que
• Empaquetamiento. ésta requiera. Además de esta clase principal, podrás ir añadiendo
• Ejecución. poco a poco todas las clases que vayas necesitando.
• Depuración.
Vamos a ver con detalle cada uno de esos pasos.
En nuestro caso, la herramienta que vas a utilizar será Android
Creación de un proyecto Java ME.
Studio. Por otro lado, en la unidad anterior ya vimos cómo instalar
esta herramienta con la funcionalidad necesaria para poder En la unidad anterior ya creaste un ejemplo de proyecto Java ME.
desarrollar aplicaciones Java ME y cómo compilar una aplicación Como pudiste ver, el proceso es similar a la creación de cualquier
básica para poder ejecutarla en el emulador y en un dispositivo real. otro proyecto Java con NetBeans (aplicaciones Java de
escritorio, applets, servlets, etc.).
Desarrollo del código
UN PROYECTO REPRESENTA UNA MIDLET SUITE, ES DECIR, UN CONJUNTO
DE MIDLETS (APLICACIONES) Y NO NECESARIAMENTE SÓLO UNA.
asistente, aunque nosotros por el momento vamos a aprender a archivos de clases Java procesadas (clases preprocesadas,
escribir una aplicación "desde cero" para poder comprender cómo clases compiladas, clases preverificadas, etc.).
ELLA Y QUE IMPLEMENTE TODOS SUS MÉTODOS ABSTRACTOS. ESA NUEVA CLASE
SÍ SERÁ INSTANCIABLE.
pauseApp () destruye el midlet. aplicación correctamente guardados antes de perder el control del
dispositivo (liberar algún recurso, almacenar el estado actual, etc.).
Estos tres métodos ya los viste en la anterior unidad cuando Debes tener en cuenta que, aunque el midlet pierda el acceso a la
estudiaste el modelo de estados de una aplicación, pues sirven para pantalla, los threads continuarán en segundo plano y los
tratar los cambios de estado que se producen en el midlet por temporizadores de la aplicación permanecerán activos.
abstractos que debes implementar) o bien indicar en el proyecto por primera vez (por ejemplo para activar la pantalla de comienzo
de NetBeans que quieres crear un nuevo midlet (en lugar de y realizar inicializaciones) o se está volviendo de una pausa (para
simplemente una nueva clase). En tal caso NetBeans escribirá esas restaurar valores pero no inicializarlos).
líneas de código por ti y lo tendrá en cuenta en el proyecto:
Cuando el usuario o el gestor de aplicaciones cierran el midlet se
produce primero una llamada al método destroyApp. Dentro de ese
método podrás liberar recursos y almacenar la información que
haya de ser persistente y no deba perderse. Podrías notificar que
no quieres pasar al estado destruido lanzando la
excepción midletStateChangeException. Si el
parámetro unconditional de destroyApp es false, se evitará la
destrucción del midlet, pero si es true no habrá nada que hacer y se
finalizará la ejecución. Si se produce alguna excepción durante la
ejecución de este método, será ignorada y se pasará en cualquier
caso a estado destruido.
Ejemplo de un midlet básico Esta fase implica la creación de los siguientes archivos:
Para ello es necesario llevar a cabo los siguientes pasos: (clases; recursos como imágenes y sonidos; archivo
de manifiesto; etc.).
• Crear un nuevo proyecto Java ME de tipo "Mobile • El archvo de manifiesto, que consiste en una descripción
Application". del contenido del archivo JAR. Es un archivo opcional.
• Añadir un nuevo midlet, obteniéndose el esqueleto con los • Archivo JAD.
métodos que deben implementarse obligatoriamente.
De todo esto también se encargará automáticamente
• Importar las bibliotecas de la interfaz gráfica
el IDE de NetBeans cuando pulses el botón para compilar el midlet:
(javax.microedition.lcdui).
se generarán los archivos JAR (incluido el manifiesto) y JAD. En
• Añadir un método constructor donde se creen e inicialicen
cualquier caso también se podría realizar "a mano" con la orden en
los elementos de la aplicación (componentes gráficos,
línea de comandos jar.
variables, etc.).
• Establecer la pantalla inicial en el método startApp. El archivo de manifiesto.
• Implementar el método commandAction. Como has visto, el archivo JAR es el encargado de encapsular todas
• Compilar la aplicación. las clases y recursos que conforman uno o varios midlets. Pero
• Ejecutar la aplicación sobre el emulador. también incluye un archivo de manifiesto (manifest.mf). Este
archivo describe el contenido del JAR y consiste un archivo de texto
Compilación y preverificación. con una estructura de una línea por atributo, donde los valores de
EL PROCESO DE COMPILACIÓN, ES DECIR, DE GENERACIÓN DE UN ARCHIVO los atributos son especificados de la forma "atributo: valor".
BINARIO DE TIPO BYTECODE (CLASS) A PARTIR DE OTRO EN CÓDIGO JAVA YA LO
Un ejemplo de archivo de manifiesto podría ser:
HAS ESTUDIADO EN OTROS MÓDULOS Y NO CAMBIA EN ABSOLUTO.
Se trata de un archivo de texto que puedes consultar y modificar En algunos casos el fabricante del dispositivo (por ejemplo Nokia)
con cualquier editor de texto, aunque NetBeans te permite acceder proporciona un software específico que facilita la gestión y
a él consultando las propiedades del proyecto. mantenimiento de las aplicaciones instaladas (por ejemplo el
Nokia PC Suite). Pero en el fondo lo que hacen es automatizar el
proceso anterior (transferir el archivo JAR a la memoria del
dispositivo e instalarlo en él).
Ejecución
La ejecución de un midlet puede realizarse bien en un
emulador (basta con ejecutar el midlet en NetBeans para que éste
sea ejecutado en el emulador que tengamos configurado en el
proyecto) bien en un dispositivo real. Es casi seguro que el aspecto
final será distinto en ambos casos, aunque el funcionamiento
debería ser prácticamente idéntico (a veces podría haber algunas
diferencias debido a la máquina virtual que haya instalada en el
dispositivo). También es muy probable que haya cambios de aspecto
entre distintos dispositivos (dependiendo de la máquina virtual que
tengan instalada).
Depuración
• Interfaz de usuario de alto nivel. En este caso es el Sólo existe una instancia (un objeto) de la clase Display por midlet.
dispositivo (en realidad la máquina virtual del dispositivo) Se puede obtener una referencia a él mediante el método
quien se encarga de la colocación adecuada de los estático getDisplay (no creamos nosotros un Display, sino que el
elementos (componentes gráficos, barras de propio midlet ya lo trae implícitamente incorporado al ser creado)
desplazamiento, textos, etc.), de la forma de navegación de la propia clase Display. El método getDisplay se suele ejecutar
(por menús y ventanas) y de características visuales una sola vez (habitualmente en el constructor del midlet) y
como el color o los tipos de letra. También se tiene normalmente se almacena la referencia al Display obtenido en una
asociado un sistema específico de entrada de alto nivel. La variable, en lugar de ejecutar continuamente el método getDisplay.
ventaja de utilizar estas APIs de alto nivel es el alto grado Posteriormente, se utilizará ese Display para crear la interfaz de
de portabilidad de la aplicación para diferentes usuario del midlet.
dispositivos. El posible inconveniente es la pérdida de
control sobre el aspecto final de la aplicación, pues la En el siguiente ejemplo de código, obtenemos el Display de
estética de estos componentes va a depender mucho del un midlet en el constructor y lo almacenamos en una variable de la
dispositivo en el que se ejecute el programa. aplicación:
aplicaciones tienen un control total sobre los debe implementar (implements) su correspondiente interfaz.
Tanto los eventos a alto nivel como a bajo nivel tienen una cosa en
común: la gestión de eventos debe de realizarse siempre en el
mismo thread en el que se produce el evento.
La interfaz de usuario de alto nivel utiliza tres tipos de eventos: • Prioridad (Priority). Número entero que especifica la
importancia o prioridad del Command. Cuanto menor sea
• Activación de un comando (Command) asociado un el número, mayor prioridad tendrá.
displayable (Alert, List, Form, TextBox, Canvas).
Cuando un Command (normalmente asociado a un botón del
• Cambio de estado de un elemento (Item) de un formulario
dispositivo) recibe un evento (normalmente que el botón asociado
(Form).
ha sido pulsado), se realiza una llamada al
• Activación de un comando (Command) asociado a un
método commandAction de la interfaz CommandListener.
elemento (Item) de un formulario (Form).
Con este tipo de elementos podremos elegir distintas opciones
Estos tres tipos de eventos disponen a su vez de su correspondiente
dentro de una determinada pantalla (Displayable) como, por
interfaz de listener asociado:
ejemplo, volver a la pantalla anterior, salir de la aplicación, elegir una
opción entre varias, etc. Son los eventos que te permitirán dar
• CommandListener.
movilidad a tu aplicación para poder seleccionar opciones y saltar de CUANDO SE TIENEN VARIOS COMMANDS EN UN MIDLET (LO CUAL ES BASTANTE
una pantalla a otra. HABITUAL PUES AL MENOS APARECERÁ UN COMANDO PARA VOLVER HACIA
Command (String etiqueta, int tipoCmd, int prio- Constructor. DESPLEGABLE ASOCIADO A OTRO SOFT-BUTTON.
ridad)
Command (String etiqueta, String etiquetaLarga, Constructor Oyentes. La interfaz CommandListener y el método
int tipoCmd, int prioridad) commandAction.
int getCommandType () Obtiene el tipo Como has visto en los ejemplos anteriores de gestión de eventos,
de Command.
para realizar una determinada acción no es suficiente sólo con crear
String getLabel () Obtiene la etiqueta
un objeto Command, sino que también hay que implementar la
del Command.
interfaz CommandListener en el midlet para que una vez
int getPriority () Obtiene la prioridad
capturada la activación de ese Command se lleve a cabo una
del Command.
respuesta.
La clase Screen es la superclase abstracta común a todas las clases el Displayable activo y el midlet está en primer plano), la pantalla
del interfaz de usuario de alto nivel. La información mostrada en será actualizada automáticamente. De este modo, la aplicación
una pantalla y su comportamiento están definidos por cada una de actualiza la pantalla sin necesitar ninguna otra acción por parte de
sus subclases. la aplicación. Por ejemplo, supongamos que un objeto de tipo List se
está mostrando en ese momento en pantalla y por tanto todos los
Como ya vimos, hay cuatro tipos de pantallas o displayables en esta elementos de esa lista son visibles. Si la aplicación inserta un nuevo
interfaz. Es decir, cuatro clases que heredan directamente de la elemento al comienzo de esa lista, éste será mostrado
clase Screen: inmediatamente a la vez que el resto de elementos se reorganizará
adecuadamente. No es necesario que la aplicación llame a ningún
• TextBox.
otro método para refrescar o actualizar la pantalla (con la API de
• List. bajo nivel es posible que sí haya que hacerlo).
Recuerda que para crear una pantalla de la interfaz de usuario de En la siguiente tabla puedes observar los principales métodos de la
alto nivel (Screen) en tu midlet no puedes crear un objeto de la clase TextBox:
clase Screen (y mucho menos de la clase Displayable), pues se trata
Método Descripción
de una clase abstracta. Tendrías que crear un objeto de alguna de
TextBox (String titulo, Constructor.
las subclases de Screen: TextBox, List, Alert o Form.
String texto, int tamMax,
int restricciones)
Cuadros de texto. La clase TextBox (I).
void delete (int desplaza- Borra cierta cantidad de caracte-
Un TextBox es una pantalla (hereda de la clase Screen) que permite
miento, int longitud) res a partir de un determinado
introducir texto en múltiples líneas. También ofrece la posibilidad de desplazamiento.
restringir el tipo de texto que puede ser introducido. void insert (String texto, int Inserta un texto en el TextBox a
posicion) partir de determinada posición.
String getString () Devuelve el contenido del Text-
Box en un String.
void setString (String Establece el contenido del Text-
texto) Box a partir de un String.
int getConstraints() Obtiene las restricciones actuales
en el TextBox.
void setConstraints (int Establece las restricciones en
restricciones) el TextBox.
int getMaxSize () Obtiene el número máximo de
caracteres establecido.
void setMaxSize (int Establece el número máximo de
maxSize) caracteres.
int size () Obtiene el número de caracteres
introducidos.
Método Descripción
Alert(String titulo) Constructor.
Como se ha dicho antes, se pueden establecer restricciones Alert(String titulo, String Constructor.
(constraints) al texto que se permite introducir en un TextBox. Esas texto, Image alertImage,
restricciones se encuentran en la clase TextField, que se estudiará AlertType alertType)
más adelante (al ver los componentes de un formulario). En la Image getImage() Obtiene la imagen asociada con la
alerta.
siguiente tabla puedes observar las restricciones de entrada de
void setImage(Image img) Establece la imagen asociada con la
caracteres que proporciona la clase TextField:
alerta.
Restricciones de la clase TextField String getString() Obtiene el texto asociado con la alerta.
void setString(String str) Establece el texto asociado con la
Tipo Descripción alerta.
ANY Permite cualquier carácter de entrada. int getDefaultTimeout() Obtiene el tiempo por defecto que se
DECIMAL Sólo permite valores numéricos, opcionalmente muestra la alerta.
con decimales (números reales). int getTimeout() Obtiene el tiempo real que se mues-
EMAILADDR Sólo permite caracteres válidos en una direc- tra la alerta.
ción de e-mail. void setTimeout(int time) Establece el tiempo real que se mues-
NUMERIC Sólo permite caracteres numéricos. tra la alerta.
PASSWORD Oculta los caracteres introducidos mediante AlertType getType() Obtiene el tiempo AlertType asociado
una máscara para proporcionar privacidad. a la alerta.
PHONENUMBER Sólo permite caracteres válidos para números void setType(AlertType type) Establece el AlertType asociado a la
de teléfono. alerta.
URL Sólo permite caracteres válidos en una URL. LAS ALERTAS PUEDEN RESULTAR MUY ÚTILES PARA AVISAR AL USUARIO DE UNA
SITUACIÓN ESPECIAL COMO UN ERROR, PREGUNTAR SI SE ESTÁ SEGURO DE UNA
Cuando se crea un TextBox hay que indicar su capacidad, es decir, el El título de la alerta es el texto que aparecerá en la parte superior
número de caracteres máximo que podrá contener. Si esa capacidad de la pantalla, mientras que el texto de la alerta será el cuerpo del
En la siguiente tabla puedes observar los principales métodos de la displayable que se hubiera establecido para después de la
• ERROR. Indica que se ha producido un error. boolean isSelected(int numElem) Indica si el elemento está
seleccionado
• INFO. Indica información general.
int size() Obtiene el número de ele-
• WARNING. Indica una situación o problema potencial. mentos de la lista.
Reflexiona
¿Te habías planteado que podrías utilizar las pantallas Alert para Además de este constructor, también puedes utilizar un segundo
ayudarte a depurar tus midlets? De esa manera podrías seguir el constructor que permite proporcionar una lista con un conjunto
rastro de ejecución de tu aplicación. inicial de opciones y de imágenes asociadas.
Listas múltiples.
En las listas múltiples se pueden seleccionar varios elementos (o
ninguno). Los elementos de esta lista tendrán la apariencia
de Check Boxes (casillas de verificación).
La cantidad de objetos que se pueden incluir en un formulario Elementos en un formulario. La clase Item
dependerá del programador, aunque no es muy recomendable
saturar los formularios con muchos elementos, dado el pequeño
tamaño que suelen tener las pantallas de los dispositivos. para el
último (el método
Form (String titulo) Constructor. Todos los objetos de tipo Item tienen una propiedad label (etiqueta
de texto) que es mostrada junto con el objeto en pantalla cuando
Form (String titulo, Item[] éste se hace visible. Esa etiqueta normalmente se coloca en línea
Constructor.
items) con el ítem o sobre él. Al mostrarse la etiqueta en la pantalla del
dispositivo la implementación de la máquina virtual procurará
Añade una imagen al for- distinguir la etiqueta propiamente dicha del propio contenido del
int append (Image imagen)
mulario. elemento. Si se produce un desplazamiento en la pantalla, la
implementación procurará también mantener visibles a la vez
Añade un Item al formula-
int append (Item item) etiqueta y contenido del ítem.
rio.
En la siguiente tabla puedes observar algunos de los principales
Añade un String al formu- métodos de la clase Item:
int append (String cadena)
lario.
Método Descripción
Elimina un Item del formu- String getLabel Obtiene la etiqueta del Item.
void delete (int numItem) ()
lario.
int getLayout () Obtiene las directivas de layout (disposición)
para la colocación del Item en el formulario.
Elimina todos los ítems del
void deleteAll () void setLabel Establece la etiqueta del Item.
formulario.
(String etiqueta)
int setLayout Establece las directivas de layout (disposi-
void insert (Item numItem, Item Inserta un Item en la posi-
(int layout) ción) para la colocación del Item en el formu-
item) ción numItem.
lario.
• Grupos de selección. Clase ChoiceGroup. void setFont () Establece la fuente del texto
del StringItem.
• Barras de progreso. Clase Gauge.
void setText() Establece el texto del Strin-
Todos esos elementos tendrán sus propias características gItem.
específicas, además de las que hereden de la clase Item.
La disposición de un Item en su contenedor (formulario) puede ser Las posibles apariencias del texto de un objeto StringItem son:
configurada mediante las directivas de layout o disposición. Según
• Item.PLAIN. Aspecto normal. Utilizado normalmente para
la directiva que se elija, se intentará colocar el elemento en una
mostrar información textual no interactiva.
disposición u otra (alineación vertical, alineación horizontal,
colocación un avance de línea, etc.) dentro del formulario.
• Item.HYPERLINK. Aspecto de tipo hiperenlace.
• Item.BUTTON. Aspecto de tipo "botón". Utilizado para
Etiquetas de texto. La clase StringItem simular botones en el formulario (lo veremos más
adelante).
En la siguiente tabla puedes observar los principales métodos de la realidad se está reservando un bloque de memoria para
DISPOSITIVO.
El parámetro textoAlt del constructor consiste en el texto
Para trabajar con archivos de imágenes puedes crear un directorio alternativo a la imagen que se mostrará en caso de que ésta no
dentro la carpeta de archivos fuentes del midlet (y llamarlo por pueda ser dibujada en la pantalla (normalmente porque no quepa).
ejemplo "resources", recursos en inglés). Para acceder a los archivos El parámetro layout indica la posición de la imagen (layout o
de esa carpeta desde el código del midlet con el disposición) en la pantalla
método createImage bastaría con escribir la trayectoria (LAYOUT_LEFT, LAYOUT_CENTER, LAYOUT_RIGHT, LAYOUT_NEWLI
"/resources/nombre_archivo". Ese archivo habrá sido incluido en el NE_AFTER, LAYOUT_NEWLINE_BEFORE.). El
archivo .jar al compilar el midlet. Por ejemplo, si el archivo se llama parámetro apariencia tiene los mismos posibles valores que en el
"europa_occidental.png": caso de StringItem (PLAIN, HYPERLINK, BUTTON). Para obtener más
información sobre el layout y la apariencia puedes consultar en la
documentación de la clase ImageItem.
interfaz Choice, de manera que muchos de los métodos de ambas método itemStateChanged (interfaz ItemStateListener),
clases son iguales. que será llamado cada vez que se seleccione (o
deseleccione) una opción.
En la siguiente tabla puedes observar los principales métodos de la
clase ChoiceGroup: En el siguiente ejemplo tienes el código java de un midlet basado en
un formulario que contiene un ChoiceGroup con algunos elementos
Método Descripción en su interior:
ChoiceGroup (String label, int choceType) Constructor.
ChoiceGroup (String label, int choceType, Constructor.
String [] elementos, Image[] imagenes)
Int append (String strElem, Image imgE- Añade un elemento al fi-
lem) nal de la lista.
void delete (int numElem) Elimina el elemento espe-
cificado de la lista.
void deleteAll () Elimina todos los elemen-
tos de la lista.
void insert (int numElem, String strElem, Inserta un elemento en el
Image imgElem) índice especificado.
void set (int numElem, String strElem, Sustituye el elemento en Barras de progreso. La clase Gauge.
Image imgElem) el índice especificado. La clase Gauge sirve para implementar barras de progreso. Este
String getString (int numElem) Recupera el elemento en tipo de componentes pueden resultar muy útiles para representar
el índice especificado. de manera gráfica una determinada cantidad que puede ir variando
Image getImage (int numElem) Recupera la imagen del (volumen de audio, tiempo, cantidad de memoria transferida, etc.).
elemento en el índice es- Representa un valor entero que va desde cero hasta un valor
pecificado. máximo prefijado.
int getSelectedIndex (int numElem, boo- Recupera el índice del ele-
lean seleccionado) mento seleccionado.
boolean isSelected (int numElem) Indica si el elemento es-
pecificado está seleccio-
nado.
int size () Devuelve el número de
elementos de la lista.
Una barra de progreso se considera interactiva cuando puede ser • El atributo de disposición (layout) de un ítem puede
cambiada por el usuario al realizar éste alguna acción, por ejemplo, permitirte situarlo en una determinada zona de la
al pulsar un botón. Se considera no interactiva cuando su valor pantalla dentro de la fila en la que se esté colocando el
cambia por la lógica interna de la aplicación, por ejemplo, la barra de componente (Item.LAYOUT_LEFT, Item.LAYOUT_RIGHT,
progreso de un contador de tiempo, o de una descarga, o de la etc.), pero además puedes decidir si quieres que ese
instalación de un programa. elemento comience en una nueva fila obligatoriamente
(Item.LAYOUT_NEWLINE_BEFORE) o que no haya más
ítems en esa fila después de él
(Item.LAYOUT_NEWLINE_AFTER). También existen otras
En la siguiente tabla puedes observar los principales métodos de la opciones posibles como utilizar todo el espacio disponible
clase Gauge: (Item.LAYOUT_EXPAND) o lo contrario
(Item.LAYOUT_SHRINK).
Método Descripción • El ítem Spacer (también subclase de Item) permite
definir ítems "invisibles" pero de un determinado tamaño,
Gauge (String etiqueta, boolean de manera que puedes colocar separadores (espacios en
interactivo, int valMax, int valI- Constructor. blanco) entre elementos que estén en una misma fila.
nicial)
Gestión de eventos en un formulario
Obtiene el valor actual La gestión de eventos de un formulario se realiza de manera similar
int getValue ()
del Gauge. a la de los Commands de un midlet, es decir, mediante un gestor de
eventos que debemos implementar. En este caso se trata de la
Establece el valor actual
void setValue (int valor) interfaz ItemStateListener y de su método
del Gauge.
abstracto itemStateChanged. De este modo, cuando se realice algún
tipo de acción sobre algún componente (Item) de un formulario, se
Obtiene el valor máximo
int getMaxValue () ejecutará el método itemStateChanged y se podrán llevar a cabo las
del Gauge.
acciones (código desarrollado por el programador) que se consideren
oportunas.
Establece el valor máximo
void setMaxValue (int valor)
del Gauge. Otra forma de gestionar eventos sobre los elementos de un
formulario es mediante la interfaz ItemCommandListener, que
Indica si el Gauge es o no in- dispone también de un único método y que nuevamente se
bolean isInteractive ()
teractivo. llama commandAction (aunque en este caso con otros parámetros
En el siguiente ejemplo tienes el código java de un midlet basado en diferentes al caso de la interfaz CommandListener). Para ello,
un formulario que contiene varios objetos de tipo Gauge: tendremos que asociar un Command a un Item de manera que
cuando se accione ese Command se ejecutará el
método commandAction.
Organizando los elementos en un formulario Este método será llamado cuando algún valor interno de un Item de
En algunos casos puede que te interese una disposición determinada un formulario sea modificado por la acción del usuario (por ejemplo
de los componentes (ítems) en un formulario. Aunque la al rellenar un campo de texto o modificar una opción en un grupo
visualización y organización del formulario va a depender en gran de selección). Con el parámetro item se informa de qué Item es el
medida de la implementación en el dispositivo final, hay algunas que ha sufrido el cambio. Esto puede suceder en casos como los
cosas que se pueden hacer y con las que se pueden obtener buenos siguientes:
resultados estéticos:
• Cuando se cambian los elementos seleccionados en un
• El orden de inserción de los elementos en el formulario es grupo de selección (ChoiceGroup).
importante (método append), pues se irán mostrando en • Cuando se modifica el valor de una barra de
ese orden. También puedes decidir insertar un elemento desplazamiento (Gauge) interactiva.
en una posición determinada (entre dos elementos) con el • Cuando se introduce un valor (o se modifica lo que hay)
método insert. en un campo de texto (TextField).
• Cuando se introduce o modifica el valor de un campo de • Asignar
fecha y hora (DateField). el Command al Item (método addCommand o setDefault
Command).
El criterio para decidir si se ha producido o no un cambio en el estado
• Asignar un oyente para el Item (método
de un Item dependerá de la implementación de la máquina virtual
setItemCommandListener).
en el dispositivo. Por ejemplo, cuando se esté manipulando el valor
de un TextField, en algunas implementaciones bastará con mover el
• Escribir el código apropiado para gestionar el evento
(implementar el método CommandAction de la
cursor en el campo de texto para producir un evento y en otras
interfaz ItemCommandListener)
implementaciones puede que no se produzca un evento de cambio
de estado hasta que el foco no pase a otro componente del
formulario.
El nombre de ese método debería sonarte (de la Aunque la API no proporciona explícitamente una clase Button o
interfaz CommandListener) aunque ahora en lugar de recibir un algo similar para implementar botones, sin embargo sí puedes
parámetro de tipo Displayable, recibe un parámetro de tipo Item ya intentar simularla mediante el uso de objetos StringItem (si
que el Command ha sido invocado desde un Item (elemento de un quieres un botón con un texto) o ImageItem (si quieres un botón
formulario) y no desde un displayable (pantalla que tenía asociados con una imagen) a los cuales les podrías asociar un Command.
una serie de Commands).
Para simular un botón basta con que sigamos los pasos vistos en
Para llevar a cabo esta gestión será necesario lo siguiente: el apartado anterior:
• Crear el Item al que se le desea asociar un comando. • Crear un Item (StringItem o ImageItem) al que se le
• Crear el Command que se le desea asociar. asocia un Command. En este caso es mejor utilizar el
método setDefaultCommand.
• Establecer el oyente de ese Item.
• Implementar el método commandAction con las acciones En el siguiente ejemplo tienes el código java de un midlet en el que
que se deban tomar cuando se active el Command sobre se crean botones utilizando el método que acabas de ver:
ese Item.
Recuerda que para establecer una nueva pantalla como la activa También es recomendable que tus aplicaciones incluyan siempre
debes utilizar el método setCurrent de la clase Display, de manera algunas pautas que ayuden al usuario a manejar el programa con
que cuando se active un Command, se pulse un botón o se dé facilidad:
cualquier otra circunstancia bajo la cual deba mostrarse una nueva
pantalla tendrás que hacer uso de ese método: • Una pantalla inicial de presentación de la aplicación.
• Una pantalla de ayuda con algunas instrucciones
mínimas sobre la aplicación.
• Comandos con etiquetas claras y concisas.
Puede ser interesante dibujar inicialmente cuáles son las pantallas • Formularios sin recargar excesivamente.
(displayables) que vas a necesitar en la aplicación y, a continuación,
Se trata en general de hacer la aplicación lo más amigable y fácil
indicar cómo se podrá ir pasando de unas a otras y bajo qué
de usar al usuario.
circunstancias. Estos esquemas de flujo entre pantallas harán que
el diseño de la aplicación te resulte más fácil y puedas tener una
visión global de la aplicación antes de comenzar a escribir una sola
línea de código.
Creación de interfaces gráficos de usuario podrás arrastrar los elementos hasta la pantalla. Con
esta vista podrías crear formularios sin tener que
utilizando asistentes y herramientas del declarar los ítems que formen parte de él, ni instanciarlos,
entorno integrado ni insertarlos. Todas esas líneas de código las generaría
APLICACIONES MÓVILES DE NETBEANS: VISUAL MOBILE DESIGNER • Vista Source. Ésta la vista que has estado utilizando hasta
ahora. Es la vista del código fuente de las clases de la
El IDE de NetBeans proporciona un asistente para crear midlets aplicación.
(proyectos MIDP) rápidamente y con mucha facilidad, sin tener que • Vista Analyzer. Esta vista es útil para comprobar la
preocuparte demasiado por la parte del código responsable de crear compatibilidad de la aplicación con versiones anteriores de
las pantallas, los Items o los Commands, sino tan solo de utilizarlos la configuración CLDC. También sirve para comprobar los
adecuadamente dentro de tu aplicación. recursos que han sido definidos en la aplicación y cuáles
no son utilizados.
Si tienes mucha experiencia en el desarrollo de midlets es posible
que prefieras no utilizar los asistentes y escribir todo el código tú Con estas cuatro vistas podrás desarrollar aplicaciones de manera
mismo. Así, serás consciente en todo momento de la totalidad de visual, encargándose el asistente de generar la mayor parte del
los elementos que forman parte de tu aplicación y podrás código "rutinario" de creación de objetos, inserción de elementos,
controlarlo todo con mayor facilidad pues lo has escrito tú. Ahora asignación de comandos, etc.
bien, en el caso de un programador que esté aprendiendo a trabajar
con este nuevo entorno o que simplemente quiera hacer alguna
aplicación rápida sin complicarse la vida, siempre puede hacerse uso
de las capacidades que nos brinda un entorno de desarrollo visual
para diseñar e implementar midlets.
Resumiendo, se puede decir que ahora tendrás que crear tu propia Como has visto anteriormente, la clase Canvas proporciona
clase displayable, que será una subclase de Canvas (en lugar de métodos para manejar los eventos de bajo nivel. La implementación
heredar de Screen), y por tanto tendrás que escribir su código, de estos métodos en la propia clase Canvas está vacía. Será cuando
dispone de alguna otra tecla que tenga una correspondencia con un se va pulsando en cada momento podríamos escribir el siguiente
carácter Unicode, su código de tecla debería coincidir con el Unicode. código en el método keyPressed:
Los métodos proporcionados por Canvas para el manejo de códigos Acciones de juego
de teclas son: No todos los dispositivos tienen las opciones de dirección
(arriba, abajo, izquierda, derecha) y las relacionadas con los juegos
Método Descripción
(fuego, seleccionar, etc.) en las mismas teclas (mismos códigos de
boolean hasRepeatEvents Indica si el dispositivo puede gene-
() rar eventos repetidos cuando se tecla). Esto podría dar un problema de portabilidad si se utilizaran
mantiene una tecla pulsada. Per- los códigos de teclas de un dispositivo (o una familia de dispositivos)
mitiría detectar la repetición de te- determinado.
clas.
Por esa razón se recomienda, para garantizar la portabilidad, que
string getKeyName (int Devuelve el nombre de una tecla
las aplicaciones que requieran el empleo eventos de teclado de
codigo) dado su código asociado.
dirección (cursores) y eventos relacionados con juegos hagan uso de
void keyPressed (int co- Se llama a este método cuando se
digo) pulsa una tecla. las acciones de juego en lugar de los códigos de tecla (key codes) o
void keyReleased (int co- Se llama a este método cuando se los nombres de tecla.
digo) suelta una tecla.
Las acciones de juego no son más que códigos estándar para las
void keyRepeated (int co- Se llama a este método cuando se
funciones típicas de juegos (direcciones, disparo, etc.). El
digo) mantiene pulsada una tecla.
perfil MIDP define las siguientes acciones de
El perfil MIDP también permite detectar eventos producidos por un
juego: UP, DOWN, LEFT, RIGHT, FIRE, GAME A, GAME B, GAME
ratón o un puntero en una pantalla táctil (pulsar, soltar y arrastrar)
C y GAME D. Esas acciones de juego se corresponderán con uno (o
si el dispositivo lo soporta. Los métodos relacionados con los eventos
varios) códigos de tecla que a su vez se corresponderán con teclas
de puntero son:
de dirección (cursores) y demás botones especializados del
Método Descripción dispositivo. Dependiendo del aparato, cada una de estas acciones de
boolean hasPointerEvents () Indica si el dispositivo soporta juego puede estar asociada con una tecla diferente (y por tanto con
puntero. un código de tecla diferente).
bolean hasPointerMotionEvents () Indica si el dispositivo soporta ac-
Dado que las acciones de juego están asociadas también a la
ciones de puntero (pulsar, soltar,
arrastrar). pulsación de teclas estamos en realidad también hablando
void pointerDragged () Llamado cuando se arrastra el de eventos de teclado y por tanto se utilizan los mismos métodos
puntero. (keyPressed, keyReleased y keyRepeated) para la gestión de los
void pointerPressed () Llamado cuando se presiona el eventos.
puntero (o clic de ratón).
Para poder realizar las conversiones entre los códigos de teclas y
void pointerReleased () Llamado cuando se suelta el pun-
las acciones de juego la clase Canvas proporciona los siguientes
tero.
métodos
de juego. Sin embargo, una acción de juego puede estar asociada con la pantalla, llama al método showNotify y cuando lo elimina de la
más de un código de tecla (imagina por ejemplo el caso de los pantalla hace una llamada a hideNotify. Estos métodos están vacíos
cursores que tienen sus propios botones pero que también están en la clase Canvas. Su implementación puede resultar muy útil para:
en el teclado numérico).
• Almacenar el estado de la aplicación (disposición de la
Si por ejemplo quisieras controlar el movimiento de los cursores y pantalla, variables, etc.) cuando el AMS por alguna razón
de la tecla "disparo" podrías utilizar la función getGameAction para (por ejemplo por una llamada telefónica entrante o por la
recuperar la acción de juego (en lugar de utilizar directamente llegada de un mensaje corto) quita un objeto Canvas de la
un código de tecla, que sería dependiente del dispositivo). La pantalla del dispositivo (antes llamará a hideNotify).
implementación del método keyPressed podría quedar entonces así: • Restaurar posteriormente la aplicación (al llamar
a showNotify) con la información que previamente había
sido almacenada.
Dibujar elementos en la pantalla. El método paint. que se dibuje se podrán establecer unas u otras propiedades (color,
tamaño, posición, relleno, etc.).
La clase Canvas puede imaginarse como el lienzo que representa la
pantalla. Sobre ese lienzo es donde la aplicación escribirá todo lo que Hay dos formas de obtener un objeto de la clase Graphics:
considere oportuno durante su ejecución. Para ello Canvas dispone
del método abstracto paint que se encarga de dibujar el contenido • Como parámetro del método paint: protected void
de la pantalla. paint (Graphics g). Ese objeto es el que podrás utilizar
para dibujar elementos en la pantalla.
Dado que el método paint es abstracto, para cada subclase
• A través de una imagen mutable (una imagen que se creó
de Canvas que definas deberás implementar ese método. Un
reservando un bloque de memoria y sobre la que luego se
ejemplo trivial de implementación de paint podría ser:
puede obtener un objeto Graphics para poder escribir
sobre ella).
Una posición en la pantalla del dispositivo está definida por dos puede obtener el alto y el ancho de la pantalla.
El origen de coordenadas puede ser modificado mediante el Algunos de los métodos proporcionados por la clase Graphics para
método translate de la clase Graphics, provocando un el manejo de los colores son:
desplazamiento de todos los objetos en la pantalla.
int getColor () Devuelve el color actual.
Reflexiona int getGreenComponent () Devuelve el componente R (rojo), G
int getRedComponent () verde) o B (azul) del color actual.
Piensa en lo útil que puede resultar el método translate para int get BlueComponent ()
producir scrolls o desplazamientos por la pantalla. int setColor (int RGB) Establece el color actual.
int setColor (int red, int green,
Manejo de los colores. int blue)
La clase Graphics proporciona un modelo de coloreado de 24 bits de void setGrayScale (int valor) Establece un valor en la escala de
tipo RGB con 8 bits para cada componente de color (rojo, verde, azul). grises.
Sin embargo no todos los dispositivos soportan colores de 24 bits.
La clase Display proporciona métodos con los que se podrá saber si
Aquí tienes algunos ejemplos de uso de setColor:
el aparato cuenta con una pantalla a color (isColor) o para obtener
el número de colores soportados (numColors).
Método Descripción
int getColor (int Devuelve el color actual de alguno de los elemen-
Una vez seleccionado un color determinado para el "pincel", cualquier
especificadorCo- tos indicados en el especificador de color indi-
cosa que se dibuje en la pantalla será con ese color hasta que se
lor) cado (color del fondo, de la tinta, del borde, etc.).
establezca otro color.
boolean isColor () Indica si el dispositivo tiene pantalla a color.
int numColors () Devuelve el número de colores (si isColor() de- Por ejemplo:
vuelve true) o de niveles de gris (si isColor() de-
vuelve false) que pueden ser representados en
el dispositivo.
Escritura de texto. Dibujo de figuras geométricas
Para dibujar texto en la pantalla la clase Graphics proporciona una Las principales figuras geométricas que la clase Graphics permite
serie de herramientas (entre ellas el método drawString). dibujar son:
El aspecto que tendrá el texto al mostrarse en la pantalla podrá ser • Líneas. Mediante el método drawLine.
configurado a través de la clase Font, permitiendo jugar con la • Rectángulos. Mediante los
combinación de tres tipos de atributos: aspecto, estilo y tamaño. métodos drawRect, drawRoundRect, fillRect, fillRoundRec
t.
Algunos de los métodos proporcionados por la clase Graphics para
el manejo de texto son: • Arcos. Mediante los métodos drawArc, fillArc.
• Triángulos. Mediante el método fillTriangle.
Método Descripción
void drawChar (char caracter, int x, int Dibuja un carácter en la Según el tipo de figura se podrán tener unas u otras características
y, int anchor) pantalla (con el color y específicas (líneas continuas o discontinuas, rellenos, esquinas
fuentes actuales). redondeadas, etc.).
void drawChars (char[] caracter, int Dibuja un conjunto de ca-
desplazamiento, int longitud, int x, int y, racteres en la pantalla (con Algunos de los métodos proporcionados por la clase Graphics para
int anchor) el color y fuentes actuales). el dibujo de figuras geométricas son:
void drawString (String cadena, int x, Dibuja una cadena de ca-
Método Descripción
int y, int anchor) racteres en la pantalla (con
void drawArc (int x, int y, int ancho, Dibuja un arco circular o elíp-
el color y fuentes actuales).
int alto, int startAngle, int arcAngle) tico.
void drawSubstring (String cadena, int Dibuja una cadena de ca-
void drawLine (int x1, int y1, int x2, int Dibuja una línea.
desplazamiento, int longitud, int x, int y, racteres en la pantalla (con
y2)
int anchor) el color y fuentes actuales).
void drawRect (int xi, int y, int ancho, Dibuja un rectángulo.
Font getFont () Obtiene la fuente actual.
int alto)
void setFont (Font fuente) Establece la fuente actual.
void drawRoundRect (int x, int y, int Dibuja un rectángulo con las
ancho, int alto, int arcAncho, int ar- esquinas redondeadas.
Para obtener una fuente podemos utilizar el método cAlto)
estático getFont de la clase Font que devuelve un objeto de tipo Font. void fillArc (int x, int y, int ancho, int Rellena un arco circular o elíp-
alto, int startAngle, int arcAngle) tico (con el color actual).
Para ello se debe indicar una especificación del tipo de fuente que se
void fillRect (int xi, int y, int ancho, int Rellena un rectángulo (con el
desea (atributos face, style y size; o aspecto, estilo y tamaño), por
alto) color actual).
ejemplo:
void fillRoundRect (int x, int y, int an- Rellena un rectángulo con las
cho, int alto, int arcAncho, int arcAlto) esquinas redondeadas (con el
color actual).
void fillTriangle (int x1, int y1, int x2, Rellena un triángulo (con el co-
Una vez que se disponga de un objeto de la clase Font, habrá que
int y2, int x3, int y3) lor actual).
asociarlo al objeto Graphics que será quien ejecutará alguno de sus
métodos (por ejemplo drawString) para dibujar el texto. Esa
asociación se puede llevar a cabo mediante el método setFont de la Dibujo de imágenes. Uso del contexto gráfico.
clase Graphics. Por ejemplo: Al igual que en algunos componentes del API gráfico de alto nivel
(formularios, listas, etc.), también pueden insertarse imágenes en
un Canvas. En este caso pueden incrustarse imágenes mutables e
inmutables.
Para indicar la posición en la que se desea que se dibuje el texto los
métodos de escritura de la clase Graphics disponen del Lo primero que hay que hacer es crear un objeto de la
parámetro anchor (anchor point o punto de anclaje). clase Image para alojar la imagen, a continuación se podrá
manipular esa imagen si se considera oportuno (y si es mutable) y
La definición de un punto de anclaje consiste en la combinación de por último ya se podría mostrar en pantalla mediante el uso del
una constante horizontal (LEFT, HCENTER, RIGHT) con una constante método drawImage de la clase Graphics.
vertical (TOP, BASELINE, BOTTOM) mediante el operador lógico OR.
En el ejemplo anterior la Para imágenes inmutables:
expresión BASELINE | HCENTER significaría que el texto se desea
• Se crea la imagen (por ejemplo a partir de un archivo
anclar de manera centrada tanto horizontal (HCENTER) como
gráfico)
verticalmente (BASELINE). Para obtener más información sobre
los puntos de anclaje puedes consultar la documentación
de MIDP sobre la clase Graphics.
• Se muestra la imagen en un Canvas (usando el método Desplazamiento del origen de coordenadas.
drawImage de la clase Graphics dentro del método paint Como ya has visto al estudiar el sistema de coordenadas, el
del Canvas): origen puede ser movido mediante el método translate de la
clase Graphics, provocando un desplazamiento de todos los
objetos en la pantalla.
Clase Descripción
Hasta la versión 5.0, Android utiliza Dalvik como máquina
GameCanvas Subclase de Canvas que proporciona la funciona-
virtual con la compilación just-in-time (JIT) para ejecutar Dalvik
lidad básica para la pantalla de un juego.
"dex-code" (Dalvik ejecutable), que es una traducción de Java
Layer Clase que representa un elemento visual en el
bytecode. Android 4.4 introdujo el ART (Android Runtime) como
juego. Estos elementos pueden ser de las cla-
un nuevo entorno de ejecución, que compila el Java bytecode
ses Sprite o TiledLayer. Proporciona herramien-
durante la instalación de una aplicación. Se convirtió en la única
tas para detectar colisiones entre capas.
opción en tiempo de ejecución en la versión 5.0.
LayerManager Clase que permite gestionar las distintas capas
visibles (objetos Layer) en cada momento en el
Creación de un proyecto en Android Studio.
juego.
Pasos para crear el primer proyecto Android Studio:
Sprite Layer animado que puede estar compuesto de
una o varias imágenes.
Una vez que iniciamos el entorno del Android Studio aparece el
TiledLayer Clase que representa una malla de celdas (o bal-
diálogo principal:
dosas: tiles) que puede servir para representar
escenarios o mapas de juego.
Android
En la primera unidad de este módulo ya hemos
visto Android (arquitectura, versiones, características e
instalación, entre otros aspectos) y vimos que Android es un
sistema operativo basado en el núcleo Linux. Fue diseñado
principalmente para dispositivos móviles con pantalla táctil,
como teléfonos inteligentes, tablets o tabléfonos; y también
para relojes inteligentes, televisores y automóviles.
La ventana de Distribución de la plataforma Android se presentación y el título de la actividad. A continuación, hacer clic
gen- Son archivos que genera Java y por ninguna razón los
debemos tocar. Si lo hacemos, ya no van a servir y puede que
ni el proyecto sirva para más adelante. Cada vez que
compilamos, Java se encarga de actualizarlo y de generarlo de
nuevo. Dentro de gen encontramos 2 archivos: el BuildConfig y
R. El archivo R es el archivo que tiene los identificadores de todo
lo que tiene la aplicación, por ejemplo imágenes, campos de
texto, botones, etc. Java le asigna un identificador y nosotros
no tenemos que preocuparnos por él, ya que le colocamos un
nombre común que podamos recordar y Java sabe cómo se
llama para nosotros.
bin- Aquí tenemos archivos generados por el mismo Java, que La interfaz visual de nuestro programa para Android se
en realidad no los utilizamos y tampoco debemos manipular, almacena en un archivo XML en la carpeta res, subcarpeta
son archivos binarios como bien dice su nombre. layout y el archivo se llama activity_main.xml.
libs- Se encuentran librerías externas que necesita el proyecto. Al seleccionar este archivo el Android Studio nos permite
visualizar el contenido en "Design" o "Text" (es decir en vista de
res- El directorio "res" contiene todos los recursos de la
diseño o en vista de código):
aplicación.
Vista de diseño:
Para ejecutar la aplicación presionamos el triángulo verde o
seleccionamos del menú de opciones "Run -> Run app" y en este
diálogo procedemos a dejar seleccionado el emulador por
defecto que aparece (Nexus 5X) y presionamos el botón "OK"
Si vemos el código será el siguiente:
(si no tienes ningún emulador puedes crear uno), tal y como se
muestra en la siguiente imagen:
Una Vista o View es un componente que permite controlar la Densidad de píxeles independientes, una unidad abstracta
interacción del usuario con la aplicación. Éstos son muy que se basa en la densidad física de la pantalla. Esta
similares a los controles SWING de Java, unidad es perfecta para buscar la compatibilidad con
como Labels, Buttons, TextFields, Checkboxes, etc. TODAS las pantallas de móvil o tables, ya que es una
medida proporcional.
LOS VIEWS SON ORGANIZADOS DENTRO DE LOS LAYOUTS PARA QUE EL
Otras Unidades que podemos usar (aunque yo aconsejo dp)
USUARIO COMPRENDA LOS OBJETIVOS DE LA ACTIVIDAD.
px. Píxeles, corresponde a píxeles reales en la pantalla.
Los Grupos de Vistas (Layouts) más utilizados son los en. Cm - basado en el tamaño físico de la pantalla.
siguientes: mm. Milímetros - en función del tamaño físico de la pantalla.
pt. Puntos - 1/72 de una pulgada en función del tamaño físico
• LinearLayout de la pantalla.
o Agrupa los elementos en una sola línea, que sp. Escala de píxeles independientes - esto es como la unidad
puede ser vertical u horizontal. de DP, pero también es escalado por la preferencia del usuario
• RelativeLayout tamaño de la fuente. Se recomienda utilizar esta unidad al
o Los elementos se disponen en relación entre especificar tamaños de fuente, por lo que se ajusta tanto para
ellos y los márgenes. Es la más flexible, y la más la densidad de pantalla y preferencias del usuario.
utilizada.
• ScrollView
• La constante FILL_PARENT que indica que la vista
intentará ser tan grande como su padre (menos el
o Se utiliza para vistas que no caben en pantalla.
padding), es decir se ajusta a tope!
Sólo puede contener una vista o grupo de vistas,
y añade automáticamente las barras de • La constante WRAP_CONTENT que indica que la vista
desplazamiento. intentará ser lo suficientemente grande para mostrar su
contenido (más el padding).
• TableLayout
o Agrupa los elementos en filas y columnas. android:layout_weight: Esta propiedad nos va a permitir dar a
Contiene elementos TableRow, que a su vez los elementos contenidos en el layout unas dimensiones
contienen los elementos de cada celda. proporcionales entre ellas. Si incluimos en un LinearLayout
• FrameLayout vertical dos cuadros de texto (EditText) y a uno de ellos le
o Está pensada para contener una sola vista. Si establecemos un layout_weight=”1” y al otro un
se añaden más, todas se alinean en la esquina layout_weight=”2” conseguiremos como efecto que toda la
superior izquierda, solapándose. superficie del layout quede ocupada por los dos cuadros de texto
• AbsoluteLayout y que además el segundo sea el doble (relación entre sus
o Está desaprobado desde la versión 1.5 de propiedades weight) de alto que el primero, si ponemos 1 para
Android. En este contenedor, los elementos se los dos, el tamaño será exactamente igual. Esto se usa mucho,
referencian con coordenadas absolutas ya que así nos aseguramos una proporcionalidad para todos
partiendo de la esquina superior izquierda. Se ha los tamaños de pantalla.
desaprobado porque no se adapta a pantallas
android:id:
de diferentes tamaños, que se popularizaron a
Se trata de un número entero que sirve para identificar cada
partir de Android 1.5.
objeto view de forma única dentro de nuestro programa,
Los Layouts tienen propiedades comunes a todos. Veamos los cuando lo declaramos a través de un xml de resource podemos
propósitos de los atributos usados con mayor frecuencia al hacer referencia a la clase de recursos R usando una @, esto es
diseñar un layout: imprescindible, ya que si no no podremos identificar nuestros
elementos en nuestro programa para después usarlos y/o
atributos height, width (Altura y Ancho): Representa la
modificarlos, veamos algunos ejemplos:
dimensión de longitud vertical de un View. Puedes asignarle
valores absolutos en dps, si dependiendo de las métricas de • android:id=”@id/boton”. Hace referencia a un id ya existente
diseño que tengas ó usar los asociado a la etiqueta “boton”, esto se usa para cuando
valores match_parent y wrap_content. El primero ajusta la usamos los Layout Relativos, ya que para ubicar los
dimensión a las medidas del contenedor padre y el segundo lo elementos, lo hacemos indicando por ejemplo que un
ajusta al contenido del View, por tanto esta propiedad es botón lo insertamos a la derecha de otro, pues bien ese
importante para determinar el Alto y el Ancho de los controles otro se pone así.
y Layouts, ya que para que Android sepa dibujar un objeto View • android:id=”@+id/boton2”. Esto crea una nueva etiqueta en
debemos proveerle estos datos, y podemos hacerlo de 3 la clase R llamada “boton2”.
formas:
android:layout_gravity="center": Esta propiedad es la que se
• android:layout_width="40dp". Representa el ancho de un usa para centrar, es la 'gravedad' una vez mas cuando estén
view. Indicando un número exacto que definamos, entre las comillas, pulsa Control+Espacio para ver todas las
opciones que te da este control, además las puedes combinar, Frecuentemente usaremos el Relative Layout para nuestros
es decir, Center_Horizontal|Top. <-- Esto te lo centra horizontal proyectos debido a la referencia relativa que podemos asignar
y lo ajusta en vertical arriba. a los componentes hijos. Cuando digo relativa me refiero a que
no expresaremos la ubicación de los componentes de esta
Para el resto de Atributos, cada elemento tendrá los propios,
forma:
basta con poner el cursor dentro de la etiqueta del Layout que
estemos colocando y pulsar las teclas Ctrl+Espacio para que “El botón OK estará ubicado en el punto (200,120) del layout y
Eclipse te recomiende las propiedades del elemento que sus dimensiones son 200×30 dp“
estamos insertando.
A esa definición de atributos se le llama definición absoluta, y
Layouts. describe las medidas numéricas para el View.
Si queremos combinar varios elementos de tipo vista usaremos expresiones como la siguiente:
tendremos que utilizar un objeto de tipo Layout. Un Layout es
“El botón OK estará ubicado a la izquierda del extremo derecho
un contenedor de una o más vistas y controla su
del TextView 2 y sus dimensiones serán ajustadas al padre“
comportamiento y posición. Hay que destacar que
un Layout puede contener a otro Layout y que es un ¿Qué significa eso?, quiere decir que no importa de qué tamaño
descendiente de la clase View. sea la pantalla o que densidad manejes, el botón se ajustará
relativamente a las condiciones que se le han impuesto, lo cual
Existen varios y su uso depende de la necesidad de cada
permite una mejor experiencia para distintos usuarios sin
persona. Veamos la definición de los más populares y fáciles
importar las características de su dispositivo.
de usar:
Debes conocer
• LinearLayout: El Linear Layout es el más sencillo. Dentro
de él los elementos son ubicados en forma linear a través Para editar los layouts o ficheros de diseño en XML.
de columnas o filas. Posee un atributo que permite
En el explorador del proyecto abre el
modificar su orientación, ya sea para presentar los
fichero res/layout/activity_main.xml. Verás que en la parte
elementos horizontal o Verticalmente. Dispone los
inferior de la ventana central aparecen dos
elementos en una fila o en una columna.
lengüetas: Design y Text. Podrás usar dos tipos de diseño:
• WebView: Este View fue creado para mostrar el contenido
editar directamente el código XML (segunda lengüeta) o
con formato web.
realizar este diseño de forma visual (primera lengüeta).
• RelativeLayout: Este es el layout más recomendado a
Veamos cómo se realizaría el diseño visual. La herramienta de
usar, ya que los componentes dentro de él se pueden
edición de layouts se muestra a continuación:
organizar de forma relativa entre sí. Dispone los
elementos en relación a otro o al padre.
usará en la app de forma estática. llamado RelativeLayout, el cual contiene un texto con ciertas
alineaciones establecidas.
Pero si los elementos cambian por algún motivo cuando la app
está en funcionamiento, entonces se requiere código Java para Cada recurso del tipo layout debe ser un archivo XML, donde el
modificar dinámicamente los elementos de la UI. elemento raíz solo puede ser un ViewGroup o un View. Dentro
de este elemento puedes incluir hijos que definan la estructura
Ambos métodos no son excluyentes. del diseño.
Crear Layouts en Android Studio Tal y como hemos visto en el apartado anterior, algunos de los
view groups más populares
Dentro de la estructura de un proyecto en Android
son: LinearLayout, FrameLayout, RelativeLayout, TableLayout
Studio existe el directorio res para el almacenamiento de
y GridLayout.
recursos de la aplicación que se está desarrollando.
Cargar layout XML En Android— Al tener definido tu recurso, ya es TableLayout distribuye los elementos de forma tabular. Se
posible inflar su contenido en la actividad. Para ello usa el utiliza la etiqueta <TableRow> cada vez que queremos insertar
método setContentView() dentro del controlador onCreate(). una nueva línea. Aquí tienes un ejemplo:
Jerarquía de EditText.
MultiAutoCompleteTextView.
En más de una ocasión necesitarás que tu aplicación realice varias • Activity.startActivityForResult (Intent intent, int
tareas al mismo tiempo. También puede darse el caso de que alguna requestCode).
de las actividades que el programa ha de realizar sea bastante
dependiendo de si espere que la actividad le devuelva alguna
costosa en tiempo o necesite esperar a que suceda algo y mientras
información o no.
tanto se puedan realizar otros trabajos para no dejar al resto de la
aplicación detenida. Esto puede conseguirse mediante el uso de Por ejemplo, para iniciar otra actividad:
distintos hilos (o threads o hebras) de ejecución en el programa.
UNA DE LAS CARACTERÍSTICAS MÁS IMPORTANTES DEL INTERFAZ ES EL PASO DE Tipos de "intents'.
INFORMACIÓN ENTRE ACTIVIDADES. UNA VEZ TENEMOS CLARO EL ESQUEMA DE Hay dos tipos de intents diferentes:
LA APLICACIÓN Y LA TRANSICIÓN ENTRE PANTALLAS, ES EL MOMENTO DE IR MÁS
ALLÁ Y ATRIBUIRLE UNA SERIE DE PARTICULARIDADES ESPECÍFICAS . • Explícitos: donde se especifica el componente
explícitamente por su nombre (el campo nombre del
ANDROID NOS PROPORCIONA UNA API Y UNAS LIBRERÍAS DE CLASES QUE DAN componente del Intent tiene un valor introducido).
AL PROGRAMADOR LA OPORTUNIDAD DE CREAR APLICACIONES COMPLETAS . Generalmente, no podemos saber el nombre específico de
APARTE DE LA PROGRAMACIÓN DE LA INTERFAZ GRÁFICA DE LA APLICACIÓN (CON los componentes de otras aplicaciones, por eso los intents
TODAS SUS COMPLEJIDADES), EXISTEN OTROS ELEMENTOS QUE PUEDEN explícitos generalmente se utilizan para llamar
ENRIQUECER SU APLICACIÓN COMO LA PERSISTENCIA DE DATOS. componentes de nuestra propia aplicación.
Como los intents implícitos no especifican cuál es el componente al Para llamar a dicha actividad:
DE INTENT.
Filtros de "intents'.
Por ejemplo, puede crear una actividad que sirva para ver páginas
web. Puede anunciar al sistema que su actividad está abierta a
recibir intents para visitar sitios web. La próxima vez que se haga
un intent para visitar una web desde el dispositivo, su actividad será
una de las candidatas para abrir la web (en el caso de que haya
varios componentes para atender intent, el sistema pedirá al
usuario qué quiere usar). Paso de información entre actividades.
Los extras son pares clave-valor que aportan información adicional
Los filtros permiten que los componentes puedan recibir intents
que se ha enviar al componente que trate el intent. Así, diferentes
implícitos. Si un componente no tiene intent filters, únicamente
URI tienen asociados algunos extras en particular. Por ejemplo, la
puede recibir intents explícitos (con su nombre). Un componente que
acción ACTION_HEADSET_PLUG, que corresponde a un cambio en el
define filtros de intents puede recibir intents implícitos y explícitos.
estado de la conexión de los auriculares del dispositivo, tiene un
Un componente tendrá un filtro diferente para cada trabajo que campo extra indicando si los auriculares se han enchufado o no.
puede hacer. Por ejemplo, una aplicación multimedia puede tener
Ejemplo:
diferentes tipos de filtros para anunciar que puede abrir diferentes
tipos de archivos (fotos, audio, vídeo, etc.).
ListViews
<RelativeLayout xmlns:android="http://schemas.android.com/apk/re
s/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip" >
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_marginRight="6dip"
android:contentDescription="TODO"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/lblTitulo"
android:layout_width="fill_parent"
android:layout_height="26dip"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_toRightOf="@id/icon"
android:ellipsize="marquee" El adaptador “infla” el diseño para cada fila en su getView() método
android:singleLine="true" y asigna los datos de los puntos de vista individuales en la fila.
android:text="Description"
El adaptador se asigna a la ListView
android:textSize="12sp" /> a través del método setAdapter en el objeto ListView.
<TextView
Desde la actividad principal se crean los datos para el listview y se
android:id="@+id/lblSubtitulo"
le asigna el adapter al listview:
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@id/secondLine"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_alignWithParentIfMissing="true"
android:layout_toRightOf="@id/icon"
android:gravity="center_vertical"
android:text="Example application"
android:textSize="16sp" />
</RelativeLayout>
Necesitaremos una clase para almacenar los datos de cada fila, por
ejemplo Titular.java:
El resultado final será similar a la siguiente imagen:
Recientemente el componente ListView ha sido sustituido por el las celdas. Os dejo un enlace con un ejemplo.
RecyclerView, por tanto ListView aunque sigue siendo posible
Si quisiéramos modificar el ejemplo anterior, el adaptador quedaría
utilizarlo se ha marcado como obsoleto.
así:
Como puede observarse lo que en el ListView se realizaba en el • Los fragmentos encapsulan vistas y lógica para que sea
getView pasa a realizarse en el ViewHolder, recoge referencias a los más fácil de reutilizar dentro de las Permiten adaptar la
controles de la línea, y en el onBindViewHolder donde se introducen interfaz a todo tipo de pantallas.
los datos en los controles. • Los fragmentos son componentes independientes que
pueden contener vistas, eventos y lógica.
En el MainActivity lo mantendríamos igual, teniendo en cuenta que
en vez de un array hay que pasarle una lista al adaptador y que
debemos indicar el tipo de layout que se va a utilizar en el
RecyclerView, el más habitual en el lineal,
En nuestro caso:
Fragments.
UN FRAGMENTO ES UNA CLASE REUTILIZABLE QUE IMPLEMENTA UNA PARTE DE Creación de un Fragmento (clase que hereda de fragment). Puede
UNA ACTIVIDAD. UN FRAGMENTO NORMALMENTE DEFINE UNA PARTE DE UNA crearse con un asistente New->Fragment->Fragment(Blank):
INTERFAZ DE USUARIO. LOS FRAGMENTOS DEBEN ESTAR INTEGRADOS EN LAS
ACTIVIDADES; NO PUEDEN FUNCIONAR INDEPENDIENTEMENTE DE LAS
ACTIVIDADES.
Debes conocer
Si deseamos cargar el Fragmento de forma dinámica, para por Comunicando fragmentos a través de un listener:
ejemplo adaptarlo a distintos tamaños de pantalla, debemos usar
la clase FragmentManager. En el layour de nuestra actividad Si un fragmento necesita comunicar eventos a la actividad, el
estableceremos una marca donde se insertará el fragmento en fragmento debe definir una interfaz como un tipo interno y es
En la actividad principal:
Ahora debes añadir una ToolBar al layout de tu actividad o
fragmento, puedes colocarlo en cualquier sitio del layout. Vamos a
colocarlo en la parte superior de un LinearLayout como haríamos
con el ActionBar:
ToolBar.
La ToolBar en la sucesora de la AppBar (también conocida como
ActionBar) y se introdujo en el API 21, es uno de los elementos de
diseño más importantes en las actividades, ya que proporciona una
estructura visual y elementos interactivos que son familiares para
los usuarios.
HACERLO.
Las imágenes ic_compose e ic_profile son recursos que se han Para facilitar la programación con el Android Studio modificaremos
introducido utilizando New->ImageAsset sobre la carpeta drawable. las preferencias para automatizar las importaciones a medida que
El resultado : vamos escribiendo o que pegamos código, así obtendremos una
mayor agilidad a la hora de escribir código.
Podemos hacerlo de forma similar a un botón utilizando la Con estas modificaciones el Android Studio hará todos los
propiedad Android:onClick en el Xml: imports automáticamente, es por eso que siempre tendremos que
comprobar que el import sea el correcto para evitar
comportamientos no deseados.
Persistencia.
Es probable que desee que su aplicación pueda guardar algunos
datos entre las diferentes ejecuciones de la aplicación. Por ejemplo,
puede querer guardar las preferencias de la aplicación para que la
próxima vez que lo ejecute tenga la misma apariencia que la última
vez que se ejecutó. Existen diferentes formas de obtener
persistencia en los datos de la aplicación en diferentes ejecuciones:
CUANDO HAYA CREADO EL ESQUEMA DE UNA SENCILLA APLICACIÓN, ES EL mantendrán entre sesiones, aunque su aplicación se haya cerrado.
Por ejemplo: Decimos que una aplicación tiene un acceso transparente a los datos
cuando podemos acceder a la información a través de métodos sin
tener que conocer su implementación. Esta manera de trabajar nos
permite modificar la estructura interna de la información sin que
las aplicaciones que la usan deban modificar su código para
funcionar correctamente.
El lugar más adecuado para cargar y guardar las preferencias de la Creará una base de datos llamada BDClients que contendrá una
aplicación serían los métodos onCreate () y onStop () (el momento única tabla, contactos. Esta tabla tendrá únicamente tres campos:
en que la aplicación se pone en marcha y el momento en que se _id, nombre y email, tal como se puede ver en la tabla:
cierra).
eliminarla (hacer un drop de la tabla) y volverla a crear. • String whereClause: la cláusula WHERE que se aplicará
para borrar de la base de datos. Si se le pasa null, borrará
De vuelta a la clase DBInterface, el siguiente paso es definir los todas las filas de la tabla.
diferentes métodos para abrir y cerrar la base de datos.
• String [] whereArgs: argumentos de la cláusula WHERE.
Este método devuelve la cantidad de filas afectadas por la
cláusula WHERE.
• String
La actividad principal tiene un layout con cinco botones, uno para
límite: especifica el límite de filas devueltas
cada opción de la aplicación:
por query, con el formato de la cláusula de SQL: LIMIT. Si
se le pasa un null, no existe límite. • Añadir.
• Obtener.
Este método devuelve un objeto de la clase Cursor, que proporciona
acceso de lectura y escritura en el resultado devuelto por una • Obtener Todos.
Para obtener todos los contactos, utiliza otra versión de query que
no incluya el primer booleano.
Como puede ver, por cada recurso que añadimos al proyecto se crea
un identificador (en realidad, un entero) que nos permite identificar
los recursos y trabajar fácilmente. En este caso es R.drawable.pollo
Con las cadenas de texto y los controles del layout pasa lo mismo.
Puede mirar (pero no cambiar) los archivos R.java que se encuentran
en la carpeta /app/build/source/r/, accesible desde la vista project del
explorador del proyecto.
En este ejemplo modificarás la aplicación anterior para que la FOTOGRAMAS (FRAMES).VERÁ EJEMPLOS DE AMBOS TIPOS.
Abra el código del programa (archivo MainActivity. Java) para añadir De manera intuitiva, podemos definir interpolación como la acción
el código de respuesta al clic en la imagen. En primer lugar, añadir de encontrar los valores que tiene una función entre dos puntos
la modificación tal como sigue a la declaración de la clase para que conocidos. Nosotros hacemos interpolaciones cuando, por ejemplo,
pueda detectar clics: unimos dos puntos con una línea, o tres puntos con una curva.
Para visualizar un vídeo en sus aplicaciones, es necesario que (restaurantes, gasolineras ...), registrar su recorrido mientras
agregue el siguiente elemento en nuestra aplicación: dentro de la marcha por la montaña, etc. El método más conocido de
pestaña, al editor gráfico de layouts Images & Media, agregue un geolocalización, es decir, de obtención de la posición geográfica, es el
VideoView, que será la pantalla con la que se verá el vídeo. sistema GPS.
Para añadir un vídeo como recurso, debe crear una carpeta llamada Hay otros métodos de geolocalización, como detectar las redes Wi-
raw/ dentro de la carpeta res/ y arrastrar un vídeo con el formato Fi presentes y deducir a partir de las redes identificadas cuál es la
adecuado y con un nombre compatible con Java, como es habitual. posición geográfica. Este método no es tan preciso como el GPS, pero
A su ejemplo, este vídeo se llamará castell.3gp. por otra parte puede funcionar bajo tierra o dentro de edificios,
donde la señal GPS generalmente no llega.
A continuación hay que ir al código de la actividad y añadir lo
siguiente: En este apartado verá cómo obtener las coordenadas GPS y luego
las utilizará para visualizar su posición en un mapa.
Comunicaciones.
CADA VEZ ES MÁS HABITUAL QUE LAS APLICACIONES HAGAN USO DE LA
COMUNICACIÓN PARA INTERNET, INTEGRÁNDOSE EN LAS REDES SOCIALES O
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:interpolator="@android:anim/accelerate_interpolator"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:fromYDelta="0%p"
android:toYDelta="80%p"
android:duration="1000"/>
</set>
imagen.startAnimation(animacionPelota);
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="0"
android:toAlpha="1"
android:duration="2000"/>
</set>
La estructura es muy similar a la del archivo de animación anterior,
pero en este caso nos encontramos algunos elementos nuevos:
Para que su aplicación utilice esta nueva animación, hay que editar el
método onClick() y hacer que el
orden loadAnimation cargue R.anim.apararecer que es la nueva
animación. Intente ejecutar la aplicación para notar el efecto. Como
veis, en este caso la animación no se repite si no vuelva a hacer clic en
la imagen.
Hacer rodar el balón
<translate
android:interpolator="@android:anim/linear_interpolator"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:fromXDelta="-50%p"
android:toXDelta="50%p"
android:duration="4000"/>
</set>
Por cierto, recordad que editar el onClick() para que cargue esta
animación y no otra.
Hacer venir de lejos el balón
<scale
android:interpolator="@android:anim/linear_interpolator"
android:repeatCount="0"
android:duration="4000"
android:pivotX="50%"
android:pivotY="50%"
android:fromXScale="0"
android:toXScale="1"
android:fromYScale="0"
android:toYScale="1"/>
</set>
animacio.start();
En este apartado verá cómo obtener las coordenadas GPS y luego las
utilizará para visualizar su posición en un mapa.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
25
mensaje que aparece, haga clic en "Implemento methods" para que
los añada.Concretamente, los métodos que debemos implementar son:
(LocationManager)getSystemService(Context.LOCATION_SERVICE);
gestorLoc.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000,1,this);
Como siempre, habrá que añadir los importes que les diga el Android
Studio. Con estas instrucciones se accede al servicio GPS y se pide que
las actualizaciones de posición se envíen a esta actividad. Los
argumentos numéricos son, respectivamente, el tiempo aproximado
(en milisegundos) entre actualizaciones y la distancia mínima (en
metros) que debe cambiar la posición para recibir una actualización. En
una aplicación real habrá que poner valores adecuados.
26
@Override
Toast.makeText(getApplicationContext(), text,
Toast.LENGTH_LONG).show();
Las toast (tostadas) son pequeños mensajes temporales que podemos utilizar para
mostrar información al usuario.
@Override
public void onProviderEnabled(String provider) {
Toast.makeText(getApplicationContext(),
"GPS activado por el usuario”,
Toast.LENGTH_LONG).show();
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
27
missatge = "GPS status: Out of service";
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
missatge = "GPS status: Temporarily unavailable";
break;
case LocationProvider.AVAILABLE:
missatge = "GPS status: Available";
break;
}
Toast.makeText(getApplicationContext(),
missatge,
Toast.LENGTH_LONG).show();
}
28
La otra opción, sólo disponible si utiliza el entorno Android Studio, es
ir a Tools/Android/Android Device Monitor, concretamente en la
pestaña Emulator Control, que contiene diferentes herramientas para
controlar el emulador: para simular una llamada telefónica, la
recepción de un SMS ... Si sigue bajando dentro de esta ventana
encontrará una herramienta llamada Location Controles que permite
enviar la posición en el emulador (pestaña GPS), y que se muestra en
la figura.
Los archivos GPX (GPS eXchange formato) son archivos XML que
contienen recorridos expresados como secuencias de coordenadas
GPS, con un tiempo de llegada asociado a cada punto.
29
Figura Carga de una ruta GPX
30
En primer lugar configuraremos un emulador para trabajar con las
google APIs. Tendremos que ir al Android SDK Manager y descargar la
última versión de:
31
Ahora que ya lo tenemos todo listo para poder crear el proyecto, introduzca
la siguiente configuración:
Application name: MultimediaMaps
Compañero domain: cat.xtec.IOC
Minium SDK: API 10: Android 2.3.3 (Gingerbread)
En la selección de actividades elija Google Maps Activity y deje la
configuración predeterminada.
To get one, follow this link, follow the directions and press "Create" at the
end:
https://console.developers.google.com/flows/enableapi?apiid=maps_android_back
end&keyType=CLIENT_SIDE_ANDROID&r=FF:47:8C:B5:B3:8A:XX:13:79:XX:E5:DB:4F:XX:8
F:6A:A5:BD:FF:F5%3Bioc.xtec.cat.multimediamaps
You can also add your credentials to an existing key, using this line:
FF:47:8C:B5:B3:8A:XX:13:79:XX:E5:DB:4F:XX:8F:6A:A5:BD:FF:F5;ioc.xtec.cat.mult
imediamaps
32
Once you have your key (it starts with "AIza"), replace the "google_maps_key"
string in this file.
-->
<string name="google_maps_key" translatable="false"
templateMergeStrategy="preserve">
YOUR_KEY_HERE
</string>
</resources>
33
Con estos pasos ya podremos ejecutar el emulador para comprobar el
funcionamiento del mapa, pero antes observamos cuáles son las
modificaciones que ha hecho el Android Studio para que todo
funcione. Si abre el archivo AndroidManifest.xml podrá observar el
siguiente contenido:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ioc.xtec.cat.multimediamaps" >
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="@string/google_maps_key" />
<activity
android:name=".MapsActivity"
android:label="@string/title_activity_maps" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</manifest>
34
android.permission.ACCESS_NETWORK_STATE: para detectar
cambios en la red.
android.permission.WRITE_EXTERNAL_STORAGE: permite
escribir el almacenamiento del teléfono, en este caso es
necesario para descargar archivos para generar la caché de los
mapas.
com.google.android.providers.gsf.permission.READ_GSERVICES
: permite al API acceder a los servicios de Google.
android.permission.ACCESS_COARSE_LOCATION: acceso a la
posición aproximada mediante la red: wifi y torres de telefonía.
android.permission.ACCESS_FINE_LOCATION: acceso a la
posición más precisa, utilizando además el GPS para obtenerla.
Y además, añade dos etiquetas meta-data con la información sobre la
versión de los Google Play Services y la clave que hemos añadido al
archivo google_maps_api.xml.
35
Figura Google Maps en el emulador
36
argumento el tipo de Pruebe los diferentes valores y observe los
cambios que se producen en la representación.
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
@Override
public void onProviderEnabled(String provider) {
@Override
public void onProviderDisabled(String provider) {
}
...
}
37
Desplazar la cámara en el punto propuesto.
LatLng almacena un par de coordenadas, la latitud y la longitud.
@Override
location.getLongitude ());
mmap.moveCamera (camara);
(Context.LOCATION_SERVICE);
gestorLoc.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000, 1, this);
38
5.4. Añadiendo marcas en el mapa
location.getLongitude ());
39
mmap.moveCamera (camara);
opciones.title"Título");
opciones.position(posicipn);
opciones.icon (BitmapDescriptorFactory.defaultMarker
(BitmapDescriptorFactory.HUE_ORANGE));
marca.showInfoWindow();
40
1. Programación de comunicaciones
1 <uses-permission android:name =
"android.permission.INTERNET"/>
2 <uses-permission android:name=
"android.permission.ACCESS_NETWORK_STATE "/>
4
1 // Obtenemos un gestor de las conexiones de red
2 ConnectivityManager connMgr = (ConnectivityManager)
getSystemService (Contexto.CONNECTIVITY_SERVICE);
3
4 // Obtenemos el estado de la red
5 NetworkInfo networkInfo = connMgr.getActiveNetworkInfo ();
6
7 // Si está conectado
8 if (networkInfo! = null && networkInfo.isConnected ()) {
9 // Red OK
10 Toast.makeText (this, "Red ok", Toast.LENGTH_LONG) .show ();
11 } else {
12 // Red no disponible
13 Toast.makeText (this, "Red no disponible",
Toast.LENGTH_LONG).show ();
14 }
5
posibilidades reales de caída de la conexión. Por lo tanto, debe hacer
estas comprobaciones cuando enciende la aplicación o cuando vuelva
después de haber salido. El lugar ideal para hacerlo sería el método
onStart () de su aplicación.
1.2. BroadcastReceiver
6
Si esta clase se utilizará dentro de su actividad no debe crear la clase
como un archivo .java independiente en su proyecto, puede ser
definida dentro de la clase de su aplicación. Dentro del método
onReceive () actualizar el estado de la red a su aplicación.
7
Por este motivo, lo más adecuado sería registrar el receptor
de broadcast cuando se crea la aplicación onCreate () y darlo de baja
al método onDestroy ().
void permisosCargaImagen(){
//Comprobamos que la versión sea mayor que Marshmallow y
todavía no tenemos asignado el permiso de Internet
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& getActivity().checkSelfPermission(Manifest.permission.INTERNET)
!= PackageManager.PERMISSION_GRANTED) {
//Solicitamos el permiso, al finalizar llamará
a la función onRequestPermissionsResult
requestPermissions(new String[]{Manifest.permission.INTERNET},
MY_PERMISSIONS_REQUEST_INTERNET);
}
else {
//El permiso está concedido y procedemos a cargar la imagen
en segundo plano
CargaImagen cargaImagen = new CargaImagen();
cargaImagen.execute("http://4.bp.blogspot.com/-
SiQNg1gmn5o/UyDYG1mMjjI/AAAAAAAAATs/wqi8OvtYvME/s1600/periodico.png");
}
}
8
@Override
public void onRequestPermissionsResult(int requestCode,String permissions[],
int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_INTERNET: {
// Si el permiso se ha concedido volvemos a llamar
a la función para cargar la imagen
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getActivity(),
"Permiso concedido", Toast.LENGTH_LONG).show();
permisosCargaImagen();
} else {
Toast.makeText(getActivity(),
"Permiso denegado", Toast.LENGTH_LONG).show();
}
return;
}
}
}
9
Guarde y vaya al layout.xml para añadir el componente WebView,
además de un EditText para introducir la dirección web y un botón para
ir:
1<?xml version="1.0" encoding="utf 8"?>
2<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="fill_parent"
4 android:layout_height="fill_parent"
5 android:orientation="vertical">
6
7 <LinearLayout
8 android:id="@+id/linearLayout1"
9 android:layout_width="match_parent"
10 android:layout_height="wrap_content"
11 android:orientation="horizontal">
12
13 <EditText
14 android:id="@+id/editText1"
15 android:layout_width="264dp"
16 android:layout_height="wrap_content"
17 android:hint="Introduce la dirección web">
18
19 <requestFocus/>
20 </EditText>
21
22 <Button
23 android:id="@+id/button1"
24 android:layout_width="wrap_content"
25 android:layout_height="wrap_content"
26 android:onClick="onClickIr"
27 android:text="Ir"/>
28
29 </LinearLayout>
30
31 <WebView
32 android:id="@+id/webView1"
33 android:layout_width="match_parent"
34 android:layout_height="match_parent"/>
35
36 </LinearLayout>
10
7}
Con ello podemos ejecutar la aplicación, indicar una web y ir, tal como
se puede ver en la figura:
11
2. Proveedores de contenidos
12
http://developer.android.com/reference/android/provider/package-
summary.html .
• Uri uri: URI que representa la tabla de donde se obtendrán los datos.
13
• String [] projection: lista de las columnas que se devolverán por cada
fila de la tabla.
• String selection: filtro que indica qué filas devolver con el mismo
formato que la cláusula WHERE de SQL (sin la palabra "WHERE"). Si se
pasa un null devolverá todas las filas de la URI.
• String [] selectionArgs: en el argumento anterior (selection), en
lugar incluir el valor de las columnas, directamente puede indicar "=?"
en la selección. Los "?" Serán sustituidos por los valores
del array selectionArgs en el orden en que aparecen en selection.
• String sortOrder: establece como ordenan las filas, con el mismo
formato que la cláusula de SQL ORDER BY (excluyendo las palabras
"ORDER BY "). Si se pasa null se utilizará el orden predeterminado. Se
pueden consultar los argumentos y su equivalente en un SELECT de
SQL en la tabla.
14
escoger la mesa a la que accederá (tiene un path para cada tabla). La
estructura de un URI es ésta:
1 <prefijo>://<authority>/<path>/<id>
donde:
15
Para obtener datos de un proveedor, su aplicación necesita de un
permiso de lectura por parte del proveedor. No se puede pedir este
permiso durante la ejecución, así que para obtenerlo será necesario
que utilice el elemento <uses-permission> en el su archivo
de manifiesto especificando el permiso que desea obtener del
proveedor.
1<uses-permission android:name="android.permission.READ_CONTACTS">
2</uses-permission>
16
20 whereArgs, // Criterio de selección
21 sortOrder // Orden
22 );
1 // Si ha habido un error
2 if (c == null) {
3 // Código para tratar el error, escribir logs, etc.
4
5 }
6 // Si el cursor está vacío, el proveedor no encontró resultados.
7 elseif (c.getCount () <1) {
8 // El cursor está vacío, el contento provider no tiene elementos.
9 Toast.makeText (this, "No hay datos",
Toast.LENGTH_SHORT).show ();
10} else {
11 // Datos obtenidos
12 Toast.makeText (this, "OK", Toast.LENGTH_SHORT) .show ();
13}
17
14}
15
16 c.close ();
Para obtener una columna a partir del cursor debe utilizar el método
Cursor.getString(int ColumnIndex), al que se le pasa el índice de la
columna que desea obtener. Para obtener el número de columna a
partir del identificador del campo que desea, utilice
Cursor.getColumnIndex(String columnName). Todo esto lo puede
hacer a la vez:
18
Los caracteres "?" Serán sustituidos con los valores
del array de strings whereArgs.
SQL Injection
El objetivo de whereArgs y de la sustitución de los "?" es impedir la inclusión de
código SQL malicioso dentro de la sentencia (ver enlace en
la Wikiquipedia ). Imagínese que cree un código para acceder a todos los contactos
que tengan un nombre igual a una variable que introduce el usuario ("WHERE name
= valor_variable"). Y este usuario, en lugar de introducir el nombre de una persona,
introduce: "nothing; DROP TABLE * ". La sentencia SQL resultante, en seres
ejecutada: "WHERE name = nothing. DROP TABLE * "lograría borrar todas las tablas
de la base de datos (si tuviera permiso para hacerlo).
19
4 if (hasPhone.compareTo("1") == 0) {
5 // Obtenemos los teléfonos
6 Cursor telefonos = getContentResolver().query (
7 ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
8 null,
9 ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "="
+ contactId,
10 null,
11 null);
12
13 // Recorremos los teléfonos
14 while (telefonos.moveToNext ()) {
15 telefono = phones.getString(phones.getColumnIndex
(ContactsContract.CommonDataKinds.Phone.NUMBER));
16 }
17
18 // Cerramos el cursor
19 telefonos.close ();
20}
21
22 // Obtener cursor correos
23 Cursor emails = getContentResolver().query
(ContactsContract.CommonDataKinds. Email.CONTENT_URI,
null, ContactsContract.CommonDataKinds.Email.CONTACT_ID+
"=" + ContactId, null, null);
24
25// Recorremos los correos
26 while (emails.moveToNext ()) {
27 email = emails.getString emails.getColumnIndex
(ContactsContract.CommonDataKinds.Email.DATA));
28}
29 // Cerramos el cursor
30 emails.close ();
31
32 // Mostrar
33 Toast.makeText (this, "id:" + contactId + "\ n" + "Nombre:" +
nomContacto + "\ n
Teléfono: "+ telefono +"\n email: "+ email,
Toast.LENGTH_SHORT).show ();
20
deben dar permisos de escritura el diccionario de datos del dispositivo
insertando la siguiente sentencia en el documento de manifiesto:
1 <uses-permission android:name =
"android.permission.WRITE_USER_DICTIONARY">
2</uses-permission>
1 Uri UriNueva;
2
3 ContentValues Valores = new ContentValues();
4
5 // Creamos el valor de la nueva entrada
6 Valors.put (UserDictionary.Words.APP_ID, "com.android.ioc");
7 Valors.put (UserDictionary.Words.LOCALE, "es_ES ");
8 Valors.put (UserDictionary.Words.WORD, "Hospitalet");
9 Valors.put (UserDictionary.Words.FREQUENCY, "100");
10
11 // Insertamos
12 UriNueva = getContentResolver (). Insert (
13 UserDictionary.Words.CONTENT_URI,
14 Valores
15);
21
3. Modelo de los hilos
Hilos de ejecución
Un hilo de ejecución es la unidad de procesamiento más pequeña que se puede
programar en un sistema operativo. Pueden existir múltiples hilos dentro de un
proceso y compartir recursos (como memoria, código y contexto), lo que no sucede
entre diferentes procesos.
Cuando se utiliza un widget como WebView no es necesario un AsyncTask , Porque
el WebView ya genera un hilo propio internamiento.
22
3.1. AsyncTask
Lo que hace el AsyncTask es crear otro hilo que puede utilizar para
cualquier operación que prevéis que pueda tener una duración notable
y que, por tanto, pueda bloquear la interfaz de
usuario. Concretamente, cualquier operación de acceso a Internet
debería hacerse en un hilo separado obligatoriamente, y la manera más
sencilla es usar una AsyncTask.
Una tarea asíncrona se define como una tarea que se ejecuta en el hilo
de background (hilo BG, por background, es decir, que se ejecuta por
detrás) y los resultados de la que se muestran en el hilo de la interfaz
de usuario (lo llamaremos hilo UI, de User Interface).
Para crear una AsyncTask debe crear una nueva clase que derive de
AsyncTask, e implementar los métodos descritos a continuación. Lo
más importante es saber que algunos métodos se ejecutan al hilo UI y
otros al hilo que hace la operación en el background. Esto es
fundamental porque sólo se pueden modificar las vistas de la aplicación
(escribir valores, mostrar mensajes, hacer avanzar barras de progreso
o mostrar otro tipo de contenidos) desde el hilo UI.
23
un progreso de la tarea realizada mientras ésta se ejecuta en
el background. Por ejemplo, podría animar una barra para
mostrar el progreso de la carga de un fichero.
Result: el tipo del resultado de la computación en
la background.
24
onProgressUpdate (Progress ...) (UI): es llamado en el hilo
UI después de haber llamado publishProgress (Progress ...). Le
permite actualizar algún elemento de la interfaz para mostrar el
progreso de la operación mientras la operación en
el background todavía está en ejecución, tales como actualizar
una animación o hacer avanzar una barra de progreso.
onPostExecute (Result) (UI): este método es llamado cuando
la ejecución en el background finaliza. Recibe el resultado de la
operación que ha
ejecutado el AsyncTask
y como se ejecuta en el
hilo UI permite
visualizar los resultados
obtenidos (como una
imagen, una página web
o una lista de tweets).
25
Por ejemplo, la siguiente clase descarga una imagen de la red,
mediante el método propio Bitmap DescargaImagenDeLaRed (String
url), y usa el Bitmap para mostrarlo en un widget:
3.2. Thread
26
}
});
}
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(MainHilos.this, "Tarea finalizada!",
Toast.LENGTH_SHORT).show();
}
});
}
}).start();
3.3. Handler
27
4. Conexiones HTTP
28
Una conexión HttpURLConnection permite enviar y recibir datos por
la web. Los datos pueden ser de cualquier tipo y tamaño, incluso puede
enviar y recibir datos de las que no conoce el tamaño
previamente. Para usar esta clase debe seguir los siguientes pasos:
29
5 trabajarConElFlujoDeDatos (in);
6 finally {
7 urlConnection.disconnect ();
8 }
9}
5. Fuentes
Developers Android
Licencia: Creative Commons Reconocimiento.
CodePath
Licencia: cc-wiki with attribution required
30
Tema 4. Utilización de bibliotecas multimedia integradas
Aplicaciones multimedia Bibliotecas multimedia
Puede decirse que una aplicación multimedia es aquella que es capaz Para poder desarrollar aplicaciones multimedia, con cierta facilidad,
de procesar, reproducir, transmitir, almacenar, etc. contenidos resulta muy útil disponer de herramientas que nos ayuden en esa
multimedia. Como ya has visto en el caso de los mensajes labor ofreciendo una interfaz de programación de aplicaciones
multimedia para dispositivos móviles, un contenido intuitiva y sencilla de utilizar, así como una arquitectura modular
multimedia está compuesto por diversos medios entre los cuales que permita añadir soporte para nuevos códecs, formatos
destacan: contenedores y protocolos de transmisión.
• Texto, que puede estar sin formato o con formato (por Existen diversos frameworks o bibliotecas que proporcionan APIs
ejemplo mediante un lenguaje de marcas). El texto orientadas al trabajo con multimedia. Algunos ejemplos de
Esos paquetes constituyen lo que se suele denominar las "Java en Java (aplicaciones de escritorio, applets, etc.) que presenten,
Media APIs", constituidas esencialmente por: capturen, manipulen y almacenen flujos de información basados en
el tiempo. Además de eso, la API también proporcionará a los
• Java 2D. Para el trabajo con imágenes en dos programadores avanzados y a los fabricantes de tecnología la
dimensiones, combinado con textos, imágenes y demás posibilidad de realizar procesamientos más específicos así como
elementos relacionados con la composición. incorporar nuevas funcionalidades, soportar nuevos tipos de
• Java 3D. Para el trabajo en tres dimensiones, contenidos y formatos, optimizar la gestión de los ya existentes, etc.
incorporando la posibilidad de trabajar con escenarios,
renderización, construcción de modelos, etc.
El modelo de JMF.
• Java Advanced Imaging. Para la manipulación de
imágenes.
• Java Binding for OpenGL. Proporciona una API que
implementa la especificación OpenGL, integrada con las
bibliotecas de interfaz gráfica de Java.
• Java Image I/O. Para trabajar con imágenes almacenadas
tanto en archivos locales como remotos a los cuales se
pueda acceder por red. Incorpora extensiones adicionales
para nuevos tipos de formatos y flujos de datos.
• Java Media Framework. Permite a las JMF imita el modelo de comportamiento de los dispositivos físicos
aplicaciones Java reproducir, procesar, manipular, utilizados en el mundo de la multimedia: dispositivos como
transmitir y almacenar audio, vídeo y otros tipos de datos reproductores de CD, DVD o BD con los que se graban, procesan y
basados en el tiempo. presentan datos basados en el tiempo (normalmente flujos de audio
o vídeo o ambos a la vez). La información que estos aparatos
En esta unidad nos centraremos en hacer un repaso general de las
muestran al usuario fue previamente capturada, registrada,
posibilidades que puede ofrecerte la API Java Media Framework.
procesada y almacenada en un estudio de grabación utilizando otros
Fuentes de datos.
Como ya has visto, una fuente de datos encapsula un flujo de
información de un tipo de contenido a semejanza de como lo hace
por ejemplo un CD de audio. En JMF, un objeto de tipo DataSource,
representa un medio de audio, vídeo o ambos a la vez.
Un DataSource puede ser un archivo o bien un flujo de entrada que
provenga de una conexión de red. Una vez que se determina su
ubicación (en el caso de un archivo) o su protocolo (en el caso de un
flujo transmitido por la red), el objeto encapsula tanto
la ubicación como el protocolo y el software necesario para recibir Formatos.
la información. Una vez creado, el objeto DataSource, éste puede Para representar formato de un contenido multimedia se utiliza la
alimentar a un reproductor o un procesador para que lo gestione clase Format, la cual no contiene información sobre parámetros de
independientemente de cuál haya sido el origen o fuente de esa codificación o de temporización. Simplemente proporciona el nombre
información (de eso se encarga el DataSource). del formato o codificación utilizado y el tipo de dato que requiere ese
formato.
Los datos se pueden obtener de diversas fuentes (archivos locales
o remotos, streaming a través de la red, etc.). Una fuente de La clase Format tiene a su vez dos subclases utilizadas para definir
datos se puede clasificar en función de cómo se inicie la formatos de audio y vídeo: AudioFormat y VideoFormat. En el caso
transferencia de información: del audio, se describen los atributos específicos para un formato de
audio: la tasa de transferencia (bit rate), el número de bits por
• Pull data Source, si la inicia el cliente. En este caso él es
muestra, o el número de canales. En el caso del vídeo, se proporciona
quien controla el flujo de datos que son obtenidos de la
la información necesaria para poder trabajar con los datos de vídeo.
fuente de datos "pull". Algunos ejemplos de protocolos para
Dada la amplia gama de posibles formatos de vídeo, existe un nuevo
este tipo de fuente de datos podrían
conjunto de subclases que heredan de VideoFormat:
ser HTTP y FILE. JMF proporciona dos tipos de fuentes de
datos pull: PullDataSource y PullBufferDataSource, que • IndexedColorFormat.
utilizan un objeto de tipo Buffer como unidad de • RGBFormat.
transferencia.
• YUVFormat.
• Push data Source, si la inicia el servidor. En este caso es
• JPEGFormat.
el servidor quien controla el flujo de datos. Entre las
• H261Format.
fuentes de tipo "push" puedes encontrar:
el broadcast multimedia, el multicast multimedia y
• H263Format.
Aquí tienes un esquema del modelo de procesamiento de datos Los flujos multimedia se pueden clasificar en función de cómo la
basados en el tiempo con algunos de los ejemplos de los que hemos información es entregada de una manera similar a como hemos
estado hablando: clasificado las fuentes de datos y la captura:
En JMF, los responsables de presentar al usuario un flujo de datos Aquí tienes un ejemplo de creación de un Player utilizando el
multimedia basado en el tiempo (como por ejemplo audio o vídeo) a método createRealizedPlayer:
través del hardware disponible en el equipo son los reproductores.
Ya has visto que para llevar a cabo esta tarea es necesario un objeto
que implemente la interfaz Player. La reproducción de la
información podrá ser controlada directamente desde tu aplicación
o bien podrás ofrecer un componente visual que muestre un panel
de control con el que el usuario podrá interactuar. Si vas a trabajar
con varios flujos de datos, tendrás que crear un reproductor para
cada uno de ellos.
Como verás más adelante, un procesador (Processsor) es un tipo el reproductor inmediatamente después de ser creado.
especial de reproductor (Player) que permite aplicar determinadas Aún no tiene información acerca de la fuente de
Método Descripción
void start () Inicia el reproductor en cuanto sea posible
(en cuanto se encuentre en el estado Pre-
fetched).
Component getVisualCom- Obtiene el componente visual (objeto de
ponent () tipo javax.awt.Component) para mostrar
el reproductor.
Un Player dispone generalmente de dos tipos de componentes para
Component getControlPa- Obtiene el componente (objeto ja-
construir su interfaz de usuario:
nelComponent () vax.awt.Component) que proporciona el in-
terfaz de usuario por defecto para contro-
1. Componente visual. Permite reproducir el contenido
lar el reproductor.
multimedia del flujo que alimenta al Player (por ejemplo,
GainControl getGainControl Obtiene el objeto que permite controlar
si se trata de un vídeo, sería el marco en el cual se
() la regulación de sonido del reproductor.
representaría visualmente el vídeo). En algunos casos
podría no existir, por ejemplo: en el caso de un flujo de
Además de esos métodos, también dispones audio.
de addController y removeController, junto a todos los métodos 2. Componente de control. Panel de control que permite al
heredados de las usuario interactuar con el contenido multimedia: botones
interfaces Controller, Clock, MediaHandler y Duration. de reproducir, pausar, detener, etc.
Debes tener en cuenta que no puedes llamar a cualquier método Puedes obtener esos componentes mediante los métodos del
de Player desde cualquier estado. objeto Player que ya viste en el apartado anterior:
método controllerUpdate del objeto panel, pues ha sido registrado que se detallan todos los eventos posibles.
Una vez conocida la estructura general de funcionamiento de un clase paneldevideo.java, que será encargada de manejar
objeto Player, vamos a intentar desarrollar un pequeño ejemplo de la API así como de interactuar con la interfaz. Por el
aplicación con un reproductor completo. momento esta clase solo se encargará de crear un
objeto MediaPlayer especificando la URL de un archivo de
video, y su reproducción será automática. Los controles de
reproducción se dejaran para más tarde.
La clase que vas a desarrollar recibirá un archivo (un objeto File) que prueba, desde el siguiente enlace.
debe almacenar un contenido multimedia y a continuación creará
• Inclusión de una barra de progreso. En este quinto y
una pequeña interfaz gráfica de usuario con unos componentes
último videotutorial se va a incluir una barra de
mínimos que te permitan trabajar con ese contenido. Esos
progreso de la reproducción añadiendo un par de nuevos
componentes los obtendrás a partir de un objeto Player. Al tratarse
métodos a la
de una aplicación gráfica, necesitarás incluir algunas clases de
clase paneldevideo: startAnimation y stopAnimation.
la API de la interfaces gráficas de
usuario Swing y AWT (JFrame, JPanel, GridbagLayout, etc.). Reproductor MP3
Reproductor de vídeo avanzado (I) de operaciones de procesamiento sobre esos datos (manipulaciones,
filtrados, conversiones, etc.) y proporciona una salida de ese
En la siguiente colección de videotutoriales puedes observar cómo
contenido multimedia procesado. Esa salida podría ser finalmente
desarrollar un reproductor de vídeo, algo más sofisticado, que
enviada a un reproductor o bien a otro procesador que realizará un
incluye más controles:
nuevo conjunto de operaciones sobre la información. En cualquier
• Explicación de cómo realizar el reproductor. En este primer caso, la salida de un procesador volverá a ser una nueva fuente de
tutorial (sin vídeo) se da una idea general de los datos.
componentes que va a ser necesario que construyas. Se
incluye el código fuente en java.
método setOutputContentDescriptor del procesador para controles mediante el método getControls del objeto TrackControl.
especificar el formato de los datos que serán Ese método devuelve todos los controles (objetos Control) asociados
multiplexados a la salida. a una pista determinada, incluyendo controles de códec, como por
ejemplo H263Control, QualityControl y MPEGAudioControl.
• Usando el método setCodecChain de los
objetos TrackControl que representan a las pistas para
Para más información puedes revisar la lista de todos los controles 2. Crear un DataSink para escribir en un archivo mediante
de códec definidos en JMF en el subapartado "Controles" del el método estático createDataSink de la clase Manager.
apartado sobre arquitectura JMF. Habrá que pasarle el DataSource de salida y
un MediaLocator que indique la ubicación del archivo sobre
Conversión de formatos el que se va a escribir.
Puedes seleccionar el formato de una pista concreta mediante la 3. Usar el método open del DataSink para abrir el archivo.
manipulación del objeto TrackControl que representa a esa pista: 4. Iniciar la escritura de datos en el DataSink mediante el
método start.
1. Llamando al
método getTrackControls del procesador para obtener Aquí tienes un ejemplo de cómo podrías usar un DataSink para
el TrackControl de cada pista. Recuerda que volcar los datos de salida de un procesador:
el procesador debe estar aún en estado Configured.
2. Utilizando el método setFormat del procesador para
indicar el formato al cual quieres convertir esa pista.
• Mediante la selección de un Renderer específico para una Cuando un flujo de información es transmitido en tiempo real a un
pista a través del objeto TrackControl que representa a cliente, éste puede comenzar la reproducción de esa información sin
esa pista. necesidad de esperar a que la transferencia de información finalice.
• Mediante la utilización de la salida de un procesador como De hecho, es posible que la transferencia de información no tenga
entrada para un determinado DataSink. una duración o una longitud predeterminada, haciendo que la espera
• Mediante la redirección de la salida del procesador a la a que el flujo de datos finalice no tenga sentido. El término
entrada de un reproductor o de otro procesador. "streaming media", "streaming multimedia" o a veces simplemente
"streaming" (en español flujo de datos multimedia) suele utilizarse
Para seleccionar un Renderer determinado debes seguir los
tanto para las técnicas empleadas para el envío de información por
siguientes pasos:
la red en tiempo real como para los propios contenidos que son
• La implementación de interfaces de plug-in que te una actividad, debido a un cambio en su estado si el sistema es la
permitan llevar a cabo procesamientos personalizados o creación de ella, deteniéndola, reanudarla, o destruirlo, y cada uno de
a medida sobre una pista. devolución de llamada que ofrece la oportunidad de realizar un
trabajo específico que es apropiado que el cambio de estado.
• La implementación completa de nuevos tipos
de DataSources y MediaHandlers. Por ejemplo, cuando se detuvo, su actividad debe liberar todos los
objetos grandes, tales como bases de datos de red o conexiones.
Una vez que implementes un nuevo plug-in, tendrás que instalarlo
Cuando se reanuda la actividad, se puede volver a adquirir los
y registrarlo con el PluginManager o gestor de plug-ins para que
recursos necesarios y reanudar las acciones que fueron
esté disponible para los procesadores.
interrumpidos. Estas transiciones de estado son parte del ciclo de
Una API multimedia para dispositivos móviles vida de la actividad que veremos a continuación.
Android. Actividades en Android. Una aplicación estará formada por un conjunto de actividades
independientes, es decir se trata de clases independientes que no
comparten variables, aunque todas trabajan para un objetivo
común. Otro aspecto importante es que toda actividad ha de ser
una subclase de Activity.
diferentes acciones.
LA PARTE LÓGICA ES UNA ARCHIVO .JAVA QUE ES LA CLASE QUE SE CREA PARA
Cada vez que se inicia una nueva actividad, se detiene la actividad PODER MANIPULAR, INTERACTUAR Y COLOCAR EL CÓDIGO DE ESA ACTIVIDAD.
onStart()
onResume()
onStop() El atributo package indica el nombre del paquete Java que soporta
a nuestra aplicación. El nombre del paquete debe ser único y un
En este estado se encuentra completamente invisible u oculto para
diferenciador a largo plazo.
el usuario, podemos decir que se encuentra en el “fondo”, en este
estado podemos decir que todo se congela, por ejemplo las variables La etiqueta <application> representa como estará construida
e información se mantiene pero no podemos ejecutar el código. nuestra aplicación. Dentro de ella definiremos nodos referentes a
las actividades que contiene, las librerías incluidas,
onRestart()
los Intents, Providers, y demás componentes.
Este método se llama después del "onStop()" cuando la actividad
Algunos atributos de la etiqueta <application> son:
actual se está volviendo a mostrar al usuario, es decir, cuando se
regresa a la actividad. Después de este continua el "onStart()" y luego • allowBackup: Este atributo puede tomar los valores de
en "onResume()" y finalmente ya está de nuevo mostrándose la true o false. Indica si la aplicación será persistente al
actividad al usuario. cerrar nuestro Android Virtual Device (AVD).
onDestroy()
• icon: Indica donde está ubicado el icono que se usará en la
aplicación. Debemos indicar la ruta y el nombre del archivo
Cuando el sistema destruye su actividad se manda a llamar al que representa el icono. En este caso apuntamos a las
método "onDestroy()" para la actividad. Este método es la última carpetas drawable donde se encuentra ic_launcher.png.
oportunidad que tenemos de limpiar los recursos y que si no los Icono por defecto que nos proporciona Android Studio.
eliminamos podrían no tener un buen rendimiento para el usuario • label: Es el nombre de la aplicación que verá el usuario en
en caso de olvidarlo. Es buena práctica asegurarse de que los hilos su teléfono. Normalmente apunta a la cadena “app_name”
que creamos son destruidos y las acciones de larga duración que se encuentra en el recurso strings.xml (Más adelante
también estén ya detenidas. lo veremos).
• theme: Este atributo apunta al archivo de recursos
styles.xml, donde se define la personalización del estilo
visual de nuestra aplicación.
Dentro de <application> encontraremos expresada la actividad
principal que definimos al crear el proyecto Test. Usaremos
<activity> para representar un nodo tipo actividad.
Practica.
Nota: En caso no hayas creado un nuevo archivo XML en la dirección Si deseamos agregar un icono para alguna opción de nuestro menú
res/menú para el menú, y hayas utilizado en main.xml que se es necesario colocar la siguiente línea en nuestro <tiem> del xml:
encontraba ya existente no es necesario modificar nuestro método
onCreateOptionsMenu y éste debe quedar como lo siguiente:
acceso de forma sencilla. superficie donde podemos dibujar y contiene muchos métodos para
dibujar formas: representar líneas, círculos, texto, etc. Se puede crear
rectángulos, cuadrados, círculos, textos, bitmaps o formas libres.
Pero eso no es problema para nosotros, ya que Android Studio La clase Path ermite definir un trazado a partir de segmentos de
autogeneró un archivo de recursos en la dirección main/res/menu. línea y curvas. Una vez definido puede ser dibujado
con canvas.drawPath(Path, Paint). Un Path ambién puede ser
Si abres el archivo main.xml verás el diseño de nuestra Action Bar
utilizado para dibujar un texto sobre el trazado marcado.
que ha sido creada por defecto.
Introducción al diseño de interfaces
gráficas en Android
Índice
1 Vistas............................................................................................................................ 2
1.1 Crear interfaces de usuario con vistas......................................................................2
1.2 Las vistas de Android...............................................................................................3
2 Layouts......................................................................................................................... 4
2.1 Utilizando layouts.................................................................................................... 5
2.2 Optimizar layouts.....................................................................................................6
3 Uso básico de vistas y layouts...................................................................................... 7
3.1 TextView..................................................................................................................7
3.2 EditText....................................................................................................................7
3.3 Button.......................................................................................................................8
3.4 CheckBox.................................................................................................................9
3.5 RadioButton........................................................................................................... 10
3.6 Spinner................................................................................................................... 11
3.7 LinearLayout..........................................................................................................12
3.8 TableLayout........................................................................................................... 14
3.9 RelativeLayout.......................................................................................................16
4 Interfaces independientes de densidad y resolución...................................................17
4.1 Múltiples archivos de recurso................................................................................ 17
4.2 Indicar las configuraciones de pantalla soportadas por nuestra aplicación........... 18
4.3 Prácticas a seguir para conseguir interfaces independientes de la resolución....... 19
1. Vistas
Todos los componentes visuales en Android son una subclase de la clase View. No se les
llama widgets para no confundirlos con las aplicaciones de tipo widget que se pueden
mostrar en la ventana inicial de Android. En sesiones anteriores ya hemos conocido
algunas vistas: el botón (clase Button) y la etiqueta de texto (clase TextView).
Cuando se inicia una actividad, lo hace con una pantalla temporalmente vacía sobre la
que deberemos colocar todos los elementos gráficos de su interfaz. Para asignar el
interfaz de usuario se hace uso del método setContentView, pasando como parámetro
una instancia de la clase View o de alguna de sus subclases. Este método también acepta
como parámetro un identificador de recurso, correspondiente a un archivo XML con una
descripción de interfaz gráfica. Este segundo método suele ser el más habitual.
Usar recursos de tipo layout permite separar la capa de presentación de la capa lógica,
proporcionando la suficiente flexibilidad para cambiar la interfaz gráfica sin necesidad de
modificar ni una línea de código. Definir la interfaz gráfica por medio de recursos en
lugar de mediante código permite también especificar diferentes layouts en función de
diferentes configuraciones de hardware o incluso que se pueda modificar la interfaz en
tiempo de ejecución cuando se produzca algún evento, como por ejemplo cambiar la
2
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
orientación de la pantalla.
En el siguiente código vemos como inicializar la interfaz gráfica a partir de un layout
definido en los recursos de la aplicación. Normalmente el recurso consistirá en un archivo
XML almacenado en la carpeta /res/layout/. En este ejemplo se supone que se está
haciendo uso del archivo milayout.xml, el cual se encuentra precisamente en dicha
carpeta:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.milayout);
TextView miTexto = (TextView)findViewById(R.id.texto);
}
Android proporciona una gran variedad de vistas básicas para poder diseñar interfaces de
usuario de manera sencilla. Usando estas vistas podremos desarrollar aplicaciones
3
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
consistentes visualmente con las del resto del sistema, aunque también es posible
modificarlas o ampliar sus funcionalidades. Algunas de las vistas más utilizadas son:
• TextView: una etiqueta de sólo lectura. Permite texto multilínea, formateado de
cadenas, etc.
• EditText: una caja de texto editable. Permite texto multilínea, texto flotante, etc.
• ListView: un grupo de vistas que crea y administra una lista vertical de vistas,
correspondiéndose cada una de ellas a una fila de la lista.
• Spinner: un cuadro de selección que permite seleccionar un elemento de una lista de
posibles opciones. Se muestra como un botón que al ser pulsado visualiza el listado de
posibles opciones.
• Button: un botón normal.
• CheckBox: un botón con dos posibles estados representado por un recuadro que
puede estar marcado o no.
• RadioButton: un grupo de botones con dos posibles estados. Uno de estos grupos
muestra al usuario un conjunto de opciones de las cuales sólo una puede estar activa
simultáneamente.
• SeekBar: una barra de desplazamiento, que permite escoger visualmente un valor
dentro de un rango entre un valor inicial y final.
2. Layouts
4
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
Los layouts son subclases de ViewGroup utilizadas para posicionar diferentes vistas en
nuestra interfaz gráfica. Los layouts se pueden anidar con el objetivo de conseguir crear
layouts más complejos. Algunos de los layouts disponibles en Android son:
• FrameLayout: es el layout más simple. Lo único que hace es añadir cada vista a la
esquina superior izquierda. Si se añaden varias vistas se van colocando una encima de
la otra, de tal forma que las vistas superiores ocultan a las inferiores.
• LinearLayout: alinea diferentes vistas ya sea en una línea horizontal o una línea
vertical. Un LinearLayout vertical consiste en una columna de vistas, mientras que
un LinearLayout horizontal no es más que una fila de vistas. Este layout permite
establecer un peso mediante la propiedad weight a cada elemento, lo que controlará
el tamaño relativo de cada elemento en la vista.
• RelativeLayout: es el layout nativo más flexible, permitiendo definir la posición de
cada una de sus vistas de manera relativa a la posición de los demás o a los bordes de
la pantalla.
• TableLayout: permite disponer un conjunto de vistas en una rejilla formada por
varias filas y columnas. Es posible permitir que las filas o columnas crezcan o
disminuyan de tamaño.
• Gallery: muestra una lista horizontal de vistas en la que se puede navegar mediante
un scroll.
La documentación de Android describe en detalle las características y propiedades de
cada layout. Esta documentación se puede consultar en
http://developer.android.com/guide/topics/ui/layout-objects.html.
La manera habitual de hacer uso de layouts es mediante un fichero XML definido como
un recurso de la aplicación, en la carpeta /res/layout/. Este fichero debe contener un
elemento raíz, el cual podrá contener de manera anidada tantos layouts y vistas como sea
necesario. A continuación se muestra un ejemplo de layout en el que un TextView es
colocado sobre un EditText usando un LinearLayout vertical:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Introduce un texto"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Escribe el texto aquí"
/>
</LinearLayout>
5
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
Para cada elemento se debe suministrar un valor para los atributos layout_width y
layout_height. Se podría utilizar una altura o anchura exacta en píxeles, pero no es
aconsejable, ya que nuestra aplicación podría ejecutarse en terminales con diferentes
resoluciones o tamaños de pantalla. Los valores más habituales para estos atributos, y que
además permiten que haya independencia del hardware, son los usados en este ejemplo:
fill_parent y wrap_content.
El valor wrap_content limita el tamaño de una vista al mínimo requerido para poder
mostrar sus contenidos. Por su parte, el valor fill_parent expande la vista para que
ocupe todo el tamaño disponible en su vista padre (o en la pantalla, si se trata del
elemento raíz). En el ejemplo anterior, el layout situado como elemento raíz ocupará toda
la pantalla. Las dos vistas dentro del layout ocuparán toda la anchura disponible, mientras
que su altura será tan sólo la necesaria para mostrar sus respectivos textos.
En el caso en el que sea estrictamente necesario por algún motivo (ya que es algo que se
desaconseja en general) es posible implementar un layout en el propio código fuente.
Cuando asignamos vistas a layouts por medio de código, es importante hacer uso de
LayoutParameters por medio del método setLayoutParams, o pasándolos como
parámetro en la llamada a addView, tal como se muestra en el siguiente ejemplo:
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
TextView texto = new TextView(this);
EditText edicion = new EditText(this);
text.setText("Introduce un texto");
edicion.setText("Escribe el texto aquí");
int lHeight = LinearLayout.LayoutParams.FILL_PARENT;
int lWidth = LienarLayout.LayoutParams.WRAP_CONTENT;
ll.addView(texto, new LinearLayout.LayoutParams(lHeight, lWidth));
ll.addView(edicion, new LinearLayout.layoutParams(lHeight, lWidth));
setContentView(ll);
6
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
En esta sección veremos algunos detalles sobre cómo utilizar algunas de las vistas y
layouts proporcionados por Android. Se debe tener en cuenta que esto no es más que una
introducción, y que es posible encontrar una descripción más detallada de todos estos
elementos en la documentación de Android.
3.1. TextView
Se corresponde con una etiqueta de texto simple, que sirve evidentemente para mostrar un
texto al usuario. Su atributo más importante es android:text, cuyo valor indica el texto
a mostrar por pantalla. También pueden ser de interés los atributos android:textColor
y android:textSize. Una curiosidad es que es posible hacer el TextView editable por
medio del atributo booleano android:editable; sin embargo, esta vista no está
preparada para este tipo de acción. Sólo se podrá editar texto a través de su subclase
EditText.
Dentro del código los métodos más utilizados son setText y appendText, que permiten
modificar el texto del TextView o añadir texto adicional durante la ejecución del
programa. En ambos casos el parámetro recibido será una cadena. Para acceder a su texto
usaremos el método getText.
3.2. EditText
EditText no es más que una subclase de TextView que está preparada para la edición de
texto. Al pulsar sobre la vista la interfaz de Android mostrará un teclado para poder
introducir nuestros datos. En el código se maneja igual que un TextView (por medio de
7
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
3.3. Button
Esta vista representa un botón normal y corriente, con un texto asociado. Para cambiar el
texto del botón usaremos su atributo android:text.
La forma más habitual de interactuar con un botón es pulsarlo para desencadenar un
evento. Para que nuestra aplicación realice una determinada acción cuando el botón sea
pulsado, deberemos implementar un manejador para el evento OnClick. Veamos un
ejemplo. Supongamos una actividad cuyo layout viene definido por el siguiente fichero
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/texto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Texto"
/>
<Button
android:id="@+id/boton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Púlsame"
/>
</LinearLayout>
También es posible definir el manejador para el click del ratón en el propio fichero XML,
a través del atributo android:onClick. El valor de este atributo será el nombre del
método que se encargará de manejar el evento. Según la especificación del botón definido
en el siguiente ejemplo:
<Button
8
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/textoBoton"
android:onClick="manejador" />
cada vez que se pulse el botón se lanzará el método manejador, cuya cabecera deberá ser
la siguiente:
public void manejador(View vista) {
// Hacer algo
}
3.4. CheckBox
Obsérvese como se hace uso del atributo android:text del CheckBox para establecer el
texto que acompañará al botón. También se ha hecho uso del atributo android:checked
para establecer el estado inicial del botón. Para hacer que nuestra actividad reaccione a la
pulsación del CheckBox implementamos el manejador del evento OnClick para el mismo:
public class MiActividad extends Activity {
TextView texto;
CheckBox miCheckbox;
9
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
3.5. RadioButton
Para que se realice una determinada acción al pulsar uno de los botones de radio
deberemos implementar el manejador del evento OnClick:
public class MiActividad extends Activity {
boolean valor = true;
RadioButton botonSi, botonNo;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
botonSi = (RadioButton)findViewById(R.id.radio_si);
botonNo = (RadioButton)findViewById(R.id.radio_no);
10
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
botonSi.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
valor = true;
}
});
botonNo.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
valor = false;
}
});
}
}
3.6. Spinner
Un Spinner es una vista que permite escoger uno de entre una lista de elementos. Es el
equivalente a un cuadro de selección de un formulario normal. Construir un Spinner en
Android requiere varios pasos, que vamos a ver a continuación.
• En primer lugar añadimos el Spinner a nuestro layout. El atributo android:prompt
indica la cadena de texto a mostrar en el título de la ventana del selector. Obsérvese
como en este caso su valor se ha definido a partir de una cadena del archivo
strings.xml de los recursos de la aplicación. Esto es así porque no es posible asignarle
una cadena como valor a este atributo.
<Spinner
android:id="@+id/spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:prompt="@string/eligeopcion"
/>
• Añadimos la cadena para el prompt en /res/values/strings.xml:
<string name="eligeopcion">Elige!</string>
• A continuación debemos indicar cuáles serán las opciones disponibles en el Spinner.
Esto se hará también mediante los recursos de la aplicación. En concreto, crearemos
un fichero en /res/values/ al que llamaremos arrays.xml y que contendrá lo siguiente:
<resources>
<string-array name="opciones">
<item>Mensual</item>
<item>Trimestral</item>
<item>Semestral</item>
<item>Anual</item>
</string-array>
</resources>
• Finalmente añadiremos el código necesario en el método onCreate de la actividad
para que se asocien las opciones al Spinner. Para ello se utiliza un objeto de la clase
ArrayAdapter, que asocia cada cadena de nuestro string-array a una vista que será
mostrada en el Spinner. Al método createFromResource le pasamos el contexto de
la aplicación, el identificador del string-array y un identificador para indicar el tipo
11
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Spinner s = (Spinner) findViewById(R.id.spinner);
ArrayAdapter adaptador = ArrayAdapter.createFromResource(
this, R.array.opciones, android.R.layout.simple_spinner_item);
adaptador.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
s.setAdapter(adaptador);
}
3.7. LinearLayout
12
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="red"
android:gravity="center_horizontal"
android:background="#aa0000"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="1"/>
<TextView
android:text="green"
android:gravity="center_horizontal"
android:background="#00aa00"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="2"/>
<TextView
android:text="blue"
android:gravity="center_horizontal"
android:background="#0000aa"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="3"/>
<TextView
android:text="yellow"
android:gravity="center_horizontal"
android:background="#aaaa00"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_weight="4"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="Primera fila"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<TextView
android:text="Segunda fila"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<TextView
android:text="Tercera fila"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
13
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
Ejemplo de LinearLayout
En este ejemplo podemos ver el uso de un par de atributos interesantes. En primer lugar
tenemos android:layout-weight, que va a permitir que las diferentes vistas dentro del
LinearLayout ocupen una porción del espacio disponible proporcional a su peso. Por
otra parte tenemos android:gravity, que permite alinear el texto de una vista. En este
caso se ha centro el texto horizontalmente.
3.8. TableLayout
Se trata de un layout que organiza sus elementos como una rejilla dividida en filas y
columnas. Se compone de un conjunto de elementos de tipo TableRow que representan a
las diferentes filas de la tabla. Cada fila a su vez se compone de un conjunto de vistas.
Existe la posibilidad de tener filas con diferente número de vistas; en este caso la tabla
tendrá tantas columnas como celdas tenga la fila que contenga más vistas.
La anchura de una columna vendrá definida por la fila que contenta la vista de máxima
anchura en dicha columna. Esto quiere decir que no tenemos libertad para asignar valor al
atributo android:layout_width, que debería valer match_parent. Sí que podemos
definir la altura, aunque lo más habitual será utilizar el valor wrap_content para el
atributo android:layout_height. Si no se indica lo contrario esos serán los valores por
defecto.
Aunque no podamos controlar la anchura de una columna, si que podemos tener
columnas de anchura dinámica, usando los métodos setColumnShrinkable() y
setColumnStretchable(). El primero permitirá disminuir la anchura de una columna
con tal de que su correspondiente tabla pueda caber correctamente en su elemento padre.
Por su parte, el segundo permitirá aumentar la anchura de una columna para hacer que la
tabla pueda ocupar todo el espacio que tenga disponible. Hay que tener en cuenta que se
14
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
pueden utilizar ambos métodos para una misma columna; en este caso la anchura de la
columna siempre se incrementará hasta que se utilice todo el espacio disponible, pero
nunca más. Otra opción disponible es ocultar una columna por medio del método
setColumnCollapsed.
15
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
Ejemplo de TableLayout
3.9. RelativeLayout
16
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
android:layout_alignTop="@id/ok"
android:text="Cancelar" />
</RelativeLayout>
Ejemplo de RelativeLayout
Durante el primer año de vida del sistema Android tan solo existía un único terminal que
hiciera uso de este sistema, por lo que a la hora de diseñar una interfaz gráfica no era
necesario tener en mente diferentes configuraciones de hardware. A principios del 2010
se produjo una avalancha en el mercado de nuevos dispositivos basados en Android. Una
consecuencia de esta variedad fue un aumento también en las posibles configuraciones de
resolución o densidad.
A la hora de diseñar una interfaz gráfica para nuestra aplicación Android es importante
tener en cuenta que ésta podría llegar a ejecutarse en una gran variedad de
configuraciones hardware distintas, con diferentes resoluciones (HVGA, QVGA o
WVGA) y densidades de pantalla (3.2 pulgadas, 3.7, 4, etc.). Los tablets cada vez están
más de moda, y es posible que otro tipo de dispositivos también incluyan un sistema
Android en el futuro.
En esta sección trataremos algunas cuestiones relativas a cómo diseñar nuestras interfaces
gráficas teniendo todo esto en cuenta.
17
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
aplicación. Vimos que para determinados tipos de recurso era posible crear una estructura
paralela de directorios que permitiera almacenar recursos a utilizar con diferentes
configuraciones de hardware. En este apartado vemos diferentes sufijos que podemos
añadir al nombre de la carpeta layout o drawable dentro de los recursos de la aplicación
para definir diferentes interfaces según la configuración de nuestra pantalla.
• Tamaño de la pantalla: tamaño de la pantalla relativa a un terminal de tamaño
"estándar":
• small: una pantalla con un tamaño menor de 3.2 pulgadas.
• medium: para dispositivos con un tamaño de pantalla típico.
• large: para pantallas de un tamaño significativamente mayor que la de un
terminal típico, como la pantalla de una tablet o un netbook.
• Densidad: se refiere a la densidad en píxeles de la pantalla. Normalmente se mide en
puntos por pulgada (dots per inch o dpi). Se calcula en función de la resolución y el
tamaño físico de la pantalla:
• ldpi: usado para almacenar recursos para baja densidad pensados para pantallas
con densidades entre 100 y 140dpi.
• mdpi: usado para pantallas de densidad media entre 140 y 180dpi.
• hdpi: usado para pantalla de alta densidad, entre 190 y 250dpi.
• nodpi: usado para recursos que no deberían ser escalados, sea cual sea la densidad
de la pantalla donde van a ser mostrados.
• Relación de aspecto (aspect ratio): se trata de la relación de la altura con respecto a la
anchura de la pantalla:
• long: usado para pantallas que son mucho más anchas que las de los dispositivos
estándar.
• notlong: usado para terminales con una relación de aspecto estándar.
Cada uno de estos sufijos puede ser utilizado de manera independiente o en combinación
con otros. A continuación tenemos un par de ejemplos de carpetas de recursos para
layouts que hacen uso de alguno de los listados anteriormente:
/res/layout-small-long/
/res/layout-large/
/res/drawable-hdpi/
En el caso de alguna aplicación puede que no sea posible optimizar la interfaz para todas
y cada una de las configuraciones de pantalla existentes. En estos casos puede ser útil
utilizar el elemento supports-screens en el Manifest de la aplicación para especificar
en qué pantallas puede ésta ser ejecutada. En el siguiente código se muestra un ejemplo:
<supports-screens
android:smallScreens="false"
android:normalScreens="true"
android:largeScreens="true"
18
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
android:anyDensity="true"
/>
Un valor de false en alguno de estos atributos forzará a Android a mostrar la interfaz por
medio de un modo de compatibilidad que consistirá básicamente en realizar un escalado.
Esto no suele funcionar siempre de manera correcta, haciendo aparecer elementos
extraños o artefactos en la interfaz.
19
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
20
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
Introducción al diseño de interfaces gráficas en Android
21
Copyright © 2012-13 Dept. Ciencia de la Computación e IA All rights reserved.
APLICACIONES MULTIMEDIA INTERACTIVAS:
CLASIFICACIÓN
Consuelo Belloch Ortí
Unidad de Tecnología Educativa. Universidad de Valencia
INTRODUCCIÓN
¿Existen aplicaciones que por sus características pueden resultar interesantes para los
pedagogos, logopedas y educadores? Con el desarrollo y evolución de las tecnologías se
han desarrollado ampliamente un conjunto de aplicaciones denominadas APLICACIONES
MULTIMEDIA INTERACTIVAS, que nos permiten interactuar con el ordenador utilizando
diferentes códigos en la presentación de la información (texto, imagen, sonido,... ). Estas
aplicaciones son las más utilizadas en la educación y en los procesos de intervención en
logopedia.
Para tener una visión general de los diferentes tipos de programas, podemos
clasificarlos en función de diferentes criterios:
• Sistema de navegación
• Finalidad y base teórica
• Nivel de control que tiene el profesional.
Según Fred Hoffstetter: Multimedia es el uso del ordenador para presentar y combinar:
texto, gráficos, audio y vídeo con enlaces que permitan al usuario navegar, interactuar,
crear y comunicarse.
Texto. Para Daniel Insa y Rosario Morata "El texto refuerza el contenido de la
información y se usa básicamente para afianzar la recepción del mensaje
icónico, para asegurar una mejor comprensión aportando más datos y para
inducir a la reflexión" (1998: 5). La inclusión de texto en las aplicaciones
multimedia permite desarrollar la comprensión lectora, discriminación visual,
fluidez verbal, vocabulario, etc. El texto tiene como función principal favorecer
la reflexión y profundización en los temas, potenciando el pensamiento de
más alto nivel. En las aplicaciones multimedia, además permite aclarar la
información gráfica o icónica. Atendiendo al objetivo y usuarios a los que va
destinada la aplicación multimedia podemos reforzar el componente visual
del texto mediante modificaciones en su formato, resaltando la información
más relevante y añadiendo claridad al mensaje escrito.
Sonidos. Los sonidos se incorporan en las aplicaciones multimedia
principalmente para facilitar la comprensión de la información clarificándola.
Los sonidos que se incorporar pueden ser locuciones orientadas a
completar el significado de las imágenes, música y efectos sonoros para
conseguir un efecto motivador captando la atención del usuario. Son
especialmente relevantes para algunas temáticas (aprendizaje de idiomas,
música, ...) y sin lugar a duda, para las aplicaciones multimedia cuya finalidad
es la intervención en problemas de comunicación y/o lenguaje. Asimismo, la
inclusión de locuciones y sonidos favorece el refuerzo de la discriminación y
memoria auditiva.
Hipertextual
Interactividad basada en los sistemas de hipertexto, que permiten decidir y
seleccionar la tarea que deseamos realizar, rompiendo la estructura lineal de la
información .
El término hipertexto fue utilizado en 1967 por Theodor Nelson, haciendo referencia su
estructura interactiva que permite la lectura no secuencial atendiendo a las decisiones del
usuario. El hipertexto es una red de información formada a partir de un conjunto de unidades
de texto que se conectan por múltiples enlaces. En las aplicaciones multimedia interactivas se
pueden establecer diferentes tipos de interrelación entre el usuario y el programa, dando
mayor o menor libertad al usuario para poder establecer su propio recorrido dentro de la
aplicación. El sistema de navegación que utiliza el usuario por el programa está determinada
por la estructura de la aplicación que debe atender a la finalidad y características de la
aplicación multimedia interactiva.
Orihuela y Santos (1999) distinguen además otros cuatro tipos de estructuras en las
aplicaciones multimedia interactivas: Paralela, Ramificada, Concéntrica y Mixta.
• Multimedias informativos:
• Multimedias formativos:
Adell. J. Internet en el aula: a la caza del tesoro. Edutec, Revista Electrónica de Tecnología
Educativa, núm. 16. http://edutec.rediris.es/Revelec2/revelec16/adell.htm
Bartolomé, A. (1994) "Multimedia interactivo y sus posibilidades en educación superior",
Pixel-Bit. Revista de medios y educación, 1, 5-14. .
http://www.us.es/pixelbit/articulos/n1/art11.htm
Bartolomé, A. (1999) Hipertextos, hipermedia y multimedia: configuración técnica, principios
para su diseño y aplicaciones didácticas. En Cabero, J. (coord.). Medios
audiovisuales y nuevas tecnologías para la formación del siglo XXI. Murcia: DM.
Orihuela, J.L. y Santos M.L. (1999) Introducción al diseño digital. Madrid: Anaya Multimedia.
Marquès, P. (1999) Diseño, selección, uso y evaluación del multimedia didáctico.
Informática. Videojuegos. http://dewey.uab.es/pmarques/disdesa.htm
Marquès, P. (1999) Los espacios web multimedia: tipología, funciones, criterios de calidad.
http://dewey.uab.es/pmarques/tipoweb.htm
Prendes, Mª P. y Solano, I. Mª (2001) Taller de Multimedia. Presentado en el Congreso de
Oviedo del 2001. http://tecnologiaedu.us.es/bibliovir/pdf/paz11.pdf
Orígenes de los videojuegos. Por lo general, los saltos tecnológicos aparecen primero en los
Es difícil poner una fecha exacta al origen de los videojuegos, pero ordenadores ya que están en permanente evolución y sus
podemos comenzar en 1947. Fue en ese año cuando se registró una posibilidades de expansión permiten la inclusión de nuevos tipos de
patente en Estados Unidos acerca de un dispositivo de dispositivos. Eso sucedió es su momento con la introducción de las
entretenimiento que consistía en disparar a aviones en una pantalla tarjetas de sonido, los gráficos 3D o las tarjetas de aceleración de
de tubo de rayos catódicos (CRT). Thomas T. Goldsmith, Jr. y Estle cálculos físicos. Las novedades más demandadas pasan poco
Ray Mann aparecen como sus autores. Bien pudieron ser los padres después al mundo de las consolas. A su vez, los dispositivos móviles
del concepto de videojuego. son cada vez más potentes y van adquiriendo poco a poco las
características técnicas de los otros dispositivos antes mencionados.
El Nimrod, construido en 1951, se considera primer ordenador
diseñado exclusivamente para jugar al Nim, un juego donde jugador Programar para una de estas plataformas implica una serie de
y máquina se alternaban para retirar palitos de unos montones. ventajas y de inconvenientes respecto a las demás. Veamos algunos
aspectos interesantes:
Poco después, en 1952, Alexander S. Douglas programó una versión
de las tres en raya (Noughts and Crosses) que se ejecutaba en el
• Consolas: Son dispositivos diseñados exclusivamente para
ordenador EDSAC de la Universidad de Cambridge en 1952. No tuvo
ejecutar videojuegos. Su hardware evoluciona con cada
mucha repercusión dado que solamente podía ejecutarse en el
iteración (que en ellas se llama "generación"), lo que suele
ordenador de dicha universidad.
suceder cada varios años. Generalmente, las capacidades
William Higinbotham podría considerarse como el creador del de una consola en el momento del lanzamiento son
videojuego multijugador. Su "tenis para dos" permitía a dos punteras aunque permanecen constantes durante la vida
jugadores competir en el mismo juego. Se exhibió públicamente del producto. Eso implica que con el paso del tiempo se
durante unas jornadas de puertas abiertas celebradas en su quedarán obsoletas, dando paso a una nueva generación.
empresa. Aunque fue disfrutado por cientos de personas, no llegó al La gran ventaja desde el punto de vista de la
público adecuado y por tanto no condicionó la aparición de otros programación de videojuegos es que el hardware no varía
Característica Evolución de la tecnolo- Diversidad del hardware para el Potencia de cálculo Memoria y capacidad de
gía mismo software almacenamiento
No existe una clasificación unificada de los géneros de videojuegos, Fighter, Mortal Kombat y Virtua Fighter.
ni siquiera los expertos se ponen de acuerdo. De hecho, lo normal es • Videojuegos de disparo en primera persona (FPS):
que un juego moderno sea una mezcla de más de uno. Muchos de Los FPS son juegos donde la pantalla representa lo que
estos géneros han surgido como respuesta a un juego innovador vería el personaje a través de sus ojos. En ellos, el
que en su momento sentó escuela y cuya idea fue repetida y/o personaje suele ir fuertemente armado y dispara a los
mejorada en desarrollos posteriores. A continuación, vamos a enemigos mientras recoge ítems desperdigados por el
describir algunos de los más importantes, resaltando algunos de los nivel. Los más conocidos fueron: Wolfenstein
juegos que dieron paso al género o bien supusieron su 3D, Doom, Duke Nukem 3D y Quake.
popularización: • Plataformas: Este tipo de juegos suele consistir en un
personaje, controlado por el jugador, que avanza por un
• Acción: Los videojuegos de acción son aquellos donde se nivel mediante movimientos rápidos y saltos. Los niveles
realizan movimientos y/o combates rápidos. Aquí suelen recorrerse en horizontal o vertical. Se podría
podemos incluir algunas de los géneros que veremos más considerar Super Mario Bros. como el iniciador del género
adelante como los juegos de lucha, simulaciones de al que siguieron otros éxitos como Bubble
combate, juegos de disparo en primera persona, etc. Como Bobble o Rainbow Island y sin olvidar a Sonic.
representantes de los primeros juegos de acción
• Estrategia: Son juegos donde la planificación de las
podríamos nombrar Pong, Asteroids y Space Invaders.
acciones suele tener bastante peso a la hora de obtener
• Aventura: Son aquellos que sumergen al jugador en una un victoria. Podemos clasificar los juegos en dos
historia que se va desarrollando conforme avanza en el subgéneros: estrategia en tiempo real y estrategia
juego. Suelen incluir puzzles y otros desafíos que se basada en turnos. La diferencia principal entre ambas es
superan con astucia e intuición. Las más antiguas no el tiempo de reacción ante los sucesos, ya que el juego no
tenían gráficos y funcionaban mediante descripciones del se detiene en el primer caso, obligando a realizar acciones
entorno en forma de texto. Entre ellas destacan Zork (en de forma rápida. Uno de los juegos que sentó las bases de
modo texto) y las series: King's Quest y Monkey Island. la estrategia en tiempo real fue The Anciert Art of War,
• Lucha: En ellos, el jugador pelea contra otros jugadores o aunque el género fue popularizado por Dune
bien contra personajes controlados por el videojuego. Eso 2, Warcraft y Command & Conquer. En el caso de la
incluye los juegos de lucha uno contra uno o los juegos estrategia por turnos Civilization fue el gran iniciador, al
cooperativos donde el jugador o jugadores se enfrentan a que siguieron otros títulos célebres como Master of
hordas de enemigos mientras avanzan por un nivel. Como Orion o X-Com.
• Puzzle: Estos juegos permiten al jugador aplicar Clasificación de los videojuegos (III)
estrategias y deducciones lógicas con el fin de conseguir • Minijuegos: Son muchos juegos en uno, generalmente de
ciertos objetivos. Suelen trabajar mucho con formas muy corta duración y con unas reglas simples. Pueden ser
geométricas y combinaciones de elementos y colores que parte de otro tipo de juego, ofreciéndose los minijuegos
pueden ser movidos, intercambiados o rotados. También como una recompensa o como un requisito para seguir
pueden incluir un tiempo limitado o bien introducir una avanzando. En otros casos, el juego en sí consiste en la
competición con otro jugador para darle más emoción. El superación de un conjunto de minijuegos (por
caso más claro de este tipo de juegos es Tetris. ejemplo, Mario Party).
• Simuladores: Como su nombre indica, intentan recrear un • Tradicionales: Los equivalentes electrónicos de los juegos
sistema del mundo real. Desde el funcionamiento de una de toda la vida. El juego Noughts and Crosses (OXO) puede
ciudad (SimCity), de un avión (Microsoft Flight Simulator), considerarse uno de los primeros juegos de este género,
de un negocio de transportes (Transport Tycoon) o de una pero aquí también se incluyen los juegos de cartas, de
nave espacial (X-Wing). mesa (ajedrez, damas), etc.
Clasificación de los videojuegos (II) • Educativos: Su misión es que el jugador aprenda mientras
se divierte. El aprendizaje puede producirse mediante la
• Juegos de rol (RPG): Es la versión electrónica de los juegos
necesidad de memorización de ciertos datos para
de rol tradicionales que se juegan con papel y dados. Los
conseguir cierto objetivo o bien mediante la observación y
jugadores tienen unas estadísticas (fuerza, sabiduría,
repetición de ciertas tareas o comportamientos. Algunas
dinero, etc.) que se van incrementando conforme aumenta
de las series más conocidas son la de Carmen Sandiego y
su experiencia. Además, pueden adquirir y usar objetos y
la saga The Incredible Machine.
armas que van recopilando durante el juego. Al contrario
• Serios: Los juegos serios son un género muy reciente.
que sus equivalentes en papel, aquí no es necesario echar
Están diseñados no solo para entretener sino para que al
a volar la imaginación para situarse en el juego; además,
jugar repetidamente se adquieran ideas que entran
las reglas están implícitas, lo que evitar tener que
dentro del ámbito de la ética, la realidad social o el trabajo
memorizarlas. Las series Ultima, Baldur's Gate o Final
en equipo.
Fantasy son algunos ejemplos de este tipo de videojuegos.
• Juegos de rol multijugador masivos (MMORPG): Son La industria del videojuego.
juegos de rol cuyo principal interés es que el desarrollo de El hecho de que un usuario final disfrute de un videojuego es el
la partida se produce en un escenario donde coinciden resultado del esfuerzo de muchos elementos que han de trabajar
cientos o miles de otros jugadores. En sus orígenes eran coordinados. Lo primero que podemos preguntarnos es ¿de dónde
juegos de texto y se llamaban MUD (Mazmorras sale la inversión inicial para pagar el desarrollo? Normalmente
multiusuario). Suelen ser juegos en los que se paga una procede de un editor o productor que adelanta parte del dinero que
suscripción mensual para acceder. Algunos ejemplos espera a recibir por las ventas del videojuego. Dado que es la entidad
representativos son: Ultima Online y World of Warcraft. que paga, el editor suele tener gran poder de decisión en el
• Carreras: El objetivo de estos juegos es llegar el primero desarrollo.
a la meta. En muchos de ellos se intenta recrear lo mejor
posible las sensaciones de conducir un vehículo en una El desarrollador (puede ser una empresa o un particular) es el
competición. El primero en convertirse en éxito de ventas encargado de diseñar e implementar el videojuego. Suele estar
fue Pole Position. especializado en unos determinados géneros y/o plataformas (por
ejemplo, juegos de rol multijugador en ordenadores personales).
• Deportivos: Estos videojuegos tratan de transmitir la
Respecto al desarrollador podemos distinguir tres casos según los
emoción de practicar un deporte real. Esto incluye desde
proyectos que desarrollen:
deportes individuales, a dobles o en equipo. El
juego Summer Games o las series PC Fútbol, Pro
• Un desarrollador interno es el que trabaja siempre para
Evolution Soccer y FIFA.
el mismo editor o fabricante de hardware.
• Musicales: El jugador tiene que seguir o acompañar el
• Un desarrollador de terceros firma contratos con los
ritmo dado por el juego ya sea mediante la pulsación de
editores para llevar a cabo un proyecto concreto en
botones, movimientos o entonación al cantar. El juego
particular. De hecho, la misma empresa desarrolladora
clásico es el Dance Dance Revolution, donde el jugador
puede tener a la vez proyectos con distintos editores.
tiene que saltar sobre unas flechas que hay en el suelo
• Un desarrollador independiente es un equipo pequeño,
siguiendo las indicaciones de la pantalla. Otros juegos que
puede que incluso unipersonal. Suele autopublicar sus
popularizaron el género son las series Singstar, Guitar
propios juegos y, al no estar atado a un editor, tienen
Hero y Rock Band.
plena libertad creativa. Eso permite que surjan ideas
innovadoras que nunca recibirían dinero de un editor que
las percibiría como una inversión arriesgada. La falta de
recursos económicos suelen suplirla con soluciones y
productos ingeniosos. A la hora de escribir estas líneas
hay un repunte de este tipo de equipos debido a que los
costes de distribución que existen en los dispositivos experimentado. Si el tamaño del equipo es grande, puede aparecer
móviles son muy bajos. el rol de director técnico ("Technical Director"), que tiene un papel
menos directo en la programación porque dedica tiempo a gestionar
La etapa de distribución es la encargada de hacer llegar el videojuego
el equipo; si existe, es él quien se comunica directamente con el
a las estanterías de las tiendas o a las tiendas de descargas
director de proyecto.
digitales. Es aquí donde se genera el beneficio para el desarrollador
y/o el editor. Hay que tener en cuenta que el distribuidor se lleva Motores de juegos
parte de esas ganancias.
Hoy en día en la gran mayoría de los videojuegos presentan tres
grandes componentes a grandes rasgos: el código específico del
juego, el motor de juegos y los recursos.
El equipo de desarrollo
Si bien en los años 70 y 80 los videojuegos eran diseñados e EL MOTOR DE JUEGOS CONTIENE LA FUNCIONALIDAD SOBRE LA QUE SE APOYA
implementados por una persona o un grupo reducido, hoy en día lo EL CÓDIGO ESPECÍFICO PARA REALIZAR ESAS ACTIVIDADES. COMO VEREMOS
normal es que un proyecto se lleve a cabo por decenas de personas. MÁS ADELANTE, UN BUEN MOTOR DE JUEGOS ES INDEPENDIENTE DEL TIPO DE
Como se puede deducir, en ellos no solamente hay programadores JUEGO QUE SE ESTÁ IMPLEMENTANDO Y SÓLO INCLUYE CONCEPTOS GENÉRICOS
y artistas sino que también intervienen editores, productores, COMO LA CAPTURA DE EVENTOS DEL TECLADO/RATÓN, LA GESTIÓN DE
distribuidores, escritores, probadores, publicistas, gestores RECURSOS, LA VISUALIZACIÓN DE LOS OBJETOS , LAS COMUNICACIONES POR RED,
económicos, soporte técnico, etc. Tan solo tienes que fijarte en los LA REPRODUCCIÓN DE SONIDOS, ETC.
En el caso de la producción. podemos dividir al personal en otros El tercer componente, los recursos (o assets, en inglés), es el
grupos según la función que desempeñan: diseño general, compendio de los contenidos del juego. Entre esos contenidos
programación, diseño artístico, audio y gestión. En este módulo podemos encontrar música, efectos de sonido, modelos 3D, fondos
profesional nos centraremos en la parte de producción, y dentro de de pantalla, tipos de letra, niveles, etc. El motor de juegos cargará
ella en los equipos de diseño y programación, especialmente en esta los recursos según le indique el código específico. De la creación de
última. los contenidos suelen encargarse los diseñadores artísticos,
ingenieros de sonido, escritores, diseñadores de niveles, etc. aunque
La parte del equipo dedicada al diseño son las personas encargadas
su desarrollo puede estar supervisado por programadores.
de determinar la idea, la mecánica del juego, los diseñadores de
niveles o de misiones y los escritores de la historia y los diálogos. Entonces, si ya tengo la idea y quiero programar un juego, ¿por
Suelen incluir un diseñador principal (en inglés, "Lead Designer"), que dónde empiezo? ¿Qué componente es el primero sobre el que debo
es quien coordina a los demás. trabajar? Pues dado que la elección del motor de juegos determinará
cómo será el código específico y el formato de los recursos lo lógico
Por otro lado, y dado que el producto final es software, debe haber
es comenzar seleccionando un motor de juegos. Es una decisión que
programadores que se encarguen de la creación del código específico,
no debe tomarse a la ligera ya que cambiar el motor de juego a
del motor de juegos y de todas las demás herramientas
mitad de un proyecto puede tomar mucho tiempo.
relacionadas (editores de niveles, instaladores, etc.). Los equipos de
programadores suelen construirse alrededor del programador
principal (en inglés: "Lead Programmer"), que suele ser el más
En los siguientes apartados haremos una revisión de los distintos basarse en este tipo de motores de juego. A la hora de
componentes que tiene un motor de juego típico y veremos cuáles escribir estas líneas, los más reconocidos son id Tech 5, C4
son sus características más importantes. Engine, Gamestudio, Source
Engine, RAGE, SCUMM (específico para aventuras
Clasificación de motores de juegos. gráficas), Unreal Engine, IW y Torque Game Engine.
Un motor de juegos expone una interfaz de programación de
aplicaciones (API) que permite al código específico utilizar su Programación de un motor. APIs básicas
funcionalidad. Sin embargo, no todos los motores ofrecen las Cada motor soporta solamente determinados lenguajes de
mismas características. programación para el código específico del juego, así que debemos
elegirlo con cuidado. Es importante destacar que algunos motores
Según el nivel de abstracción cubierto por el motor de juegos,
usan un lenguaje propio para especificar el comportamiento del
podemos distinguir 3 tipos de complejidad creciente:
juego. El cómo se integra el código específico del juego con el motor
puede variar considerablemente de un motor a otro, ya que no todos
• Motores diseñados únicamente para facilitar la
los motores comparten la misma estructura interna ni filosofía de
representación en pantalla y el acceso al hardware en
programación. La mejor forma de empezar es estudiar los
general (audio, dispositivos de entrada, red, etc). De hecho,
tutoriales que suelen incluirse con el motor.
muchos de ellos son considerados como librerías más que
como motores de juegos. Algunos Un motor de juegos está especializado solamente en determinados
ejemplos: SDL, LWJGL o Allegro. aspectos, no todos incluyen las mismas características. De hecho, es
• Motores que, además de lo anterior, añaden un soporte posible combinar distintos motores de manera que cada uno aporte
total o parcial a la lógica del juego. Podemos parte de la funcionalidad necesaria para completar los requisitos del
destacar: JGame y Ogre3D. juego. En esos casos, el código específico se comunicará con ambos
• Motores que, además de todo lo anterior, incluyen motores para integrarlos.
plataformas para la creación, modificación o integración
Muchos motores de juegos se apoyan en librerías ya existentes que
de contenidos. Algunos de ellos: Blender Game
les proporcionan parte de su funcionalidad básica. Por
Engine, jMonkeyEngine 3 o XNA Game Studio, Unreal
ejemplo, OpenGL o DirectGraphics suelen utilizarse para mostrar
Engine, CryEngine o Unity.
objetos en 2 y 3 dimensiones, siendo estas librerías las que acceden
Otro aspecto a considerar es el del coste económico y de la licencia directamente a los controladores de la tarjeta gráfica. Esto permite
de uso. Para proyectos personales o no comerciales es posible al motor no estar atado a un determinado hardware. Más aún,
encontrar motores que no nos supongan ninguna inversión, lo que algunas de esas librerías están disponibles para múltiples
puede ser determinante. La licencia de uso de otros motores pueden plataformas (por ejemplo OpenGL) lo que facilita la portabilidad del
impedirnos vender el resultado final o limitar el número de unidades motor a múltiples sistemas.
vendidas antes de tener que pagar.
Las librerías no tienen por qué ser exclusivamente para acceder al
Teniendo todo esto en cuenta, podemos clasificar los motores en dos apartado gráfico: existen muchas otras librerías para otros usos.
grandes grupos según el tipo de licencia de uso: Por ejemplo, OpenAL o FMOD hace lo mismo con el audio
y OpenCL con las operaciones de computación intensiva.
• De código abierto: No es necesario pagar por su uso e
incluyen el código fuente del motor. Hay que prestar Ventajas de la utilización de motores.
atención al tipo de licencia concreto, pues algunas ¿Qué pasaría si no usáramos un motor de juegos? De hecho, los
restringen el uso del motor a la creación de videojuegos primeros videojuegos no los utilizaban. Cuando esto ocurre, el código
que también sea software libre (por ejemplo, la específico es el encargado de todas las tareas: comunicarse
licencia GPL). La documentación y el soporte suele ser directamente con el sistema operativo y el hardware, dibujar en la
llevado a cabo por la comunidad de usuarios. Algunos de pantalla, interceptar los dispositivos de entrada, conectarse con
los más conocidos son Ogre3D, Irrlicht, id Tech otras instancias a través de la red en el caso multijugador,
4 (publicado como código abierto en noviembre de implementar la "inteligencia" de los enemigos, simular la gravedad,
2011), jMonkeyEngine 3 y Crystal Space 3D. detectar cuando dos objetos colisionan, etc.
• Propietario: Son desarrollados por empresas que cobran
A priori, puede parecer una idea buena porque sólo se implementa
por la comercialización de juegos basados en sus motores.
aquello que se va a necesitar, con lo que el resultado será más
En algunos casos pueden ofrecerse de forma gratuita si
óptimo. Además, el código estará más integrado.
se cumplen determinadas condiciones. El coste final puede
depender de muchos factores: número de empleados, de Imaginemos que realizamos el proyecto así. ¿Qué problemas
copias vendidas o del dinero entregado por los editores podríamos encontrarnos? Analicemos algunos escenarios posibles:
para su realización. Suelen estar excelentemente
documentados y, por lo general, incorporan herramientas
adicionales que facilitan la gestión de los contenidos. Las
empresas ofrecen normalmente asistencia técnica de sus
productos. Por todo ello, las grandes producciones suelen
Escenarios Sin un motor de juegos Con un motor de juegos
El juego tiene tanto éxito que Tendremos que revisar todo el código del proyecto anterior y El código del proyecto ya está separado en código
nos encargan una continua- diferenciando lo que nos sigue sirviendo de lo que no. El motivo específico del juego y el motor (código genérico).
ción. es que no hay una separación clara entre lo genérico y lo es-
pecífico del juego.
Hay que migrar el juego a No nos queda más remedio que revisar todo el código del pro- En el momento que el motor de juegos soporte
una nueva plataforma. yecto anterior y analizar qué parte es dependiente de la pla- la nueva plataforma bastará con recompilar el
taforma antigua para sustituirlo por código nuevo. Por su- proyecto.
puesto, tendríamos que tener cuidado de no estropear nada.
Es posible que los recursos ya no sean válidos para la nueva
plataforma y haya que adaptarlos.
Además, si detectamos un error en el juego o mejoramos al-
guna herramienta habrá que cambiar el código por separado
en ambos proyectos.
Llega un nuevo programador Habrá que explicarle la estructura del código, que será distinta Bastará con enseñarle a usar el motor de juego,
a la empresa y queremos para cada proyecto en el que vaya a trabajar y plataforma que será el mismo en muchos proyectos. Luego
formarlo para trabajar en soportada. se le señalarán las particularidades de cada pro-
nuestros proyectos. yecto concreto en el que vaya a trabajar.
Queremos incorporar a Será necesario investigar cómo funciona la característica X, Seguramente haya un motor de juego que im-
nuestro juego el efecto grá- implementarla en todas las plataformas del proyecto y hacer plemente la característica X de serie en todas las
fico X de un juego de la com- las pruebas correspondientes antes de usarla. plataformas, con lo únicamente tendremos que
petencia. usarla.
Componentes de un motor de juegos geométricas (líneas, rectángulos, círculos, etc.) con lo que se evita
Como hemos visto antes, no todos los motores de juegos tienen las tener que implementar los algoritmos en el código específico.
Con Cocos2d se pueden programar los mecanismos típicos de los Sobre los polígonos se pueden aplicar texturas para darle un
juegos 2d con muchísima facilidad, por ejemplo: aspecto más realista. Simplificando mucho, podemos considerarlas
como unas pegatinas que se pegan a su superficie. Las veremos con
• Reproducir efectos de sonidos.
más detalle en la unidad de trabajo de motores 3D.
• Incorporar fuentes de texto y realizar efectos.
• Tratamiento y animación de Sprites o pequeñas imágenes Un motor gráfico 3D simplificará el trabajo con los objetos
con fondo transparente para incluir un videojuego. tridimensionales permitiendo al código específico realizar
• Incorporar miles de efectos: rotar, reflejar, paralaje, operaciones con ellos independientemente del hardware sobre el
escalamiento, tintado, deslizamiento, saltar. que se esté ejecutando el juego. Entre estas operaciones está la de
crear objetos, moverlos, escalarlos, rotarlos, deformarlos, animarlos,
Pero sin duda, la gran ventaja de Cocos2d es que es open source y cambiarles las texturas, etc. Además, deberá soportar la creación de
el soporte de la comunidad es muy alto. En los enlaces siguientes te luces que iluminen dichos objetos y cámaras que permitan observar
mostramos distintos tutoriales y guías de programación, además el mundo renderizado desde la perspectiva que necesitemos en cada
de la descarga de Cocos2d. momento.
El conjunto de todos los objetos de este mundo virtual junto con las
cámaras, las luces y demás elementos forman la escena.
Internamente, la escena se suele almacenar mediante el Algunos detectores de colisiones clasifican los objetos en tipos de
denominado grafo de escena que se estudiará más adelante. manera que sólo comprueban ciertas combinaciones. Por ejemplo:
las colisiones de los objetos tipo "bala" con los tipo "enemigo" sí se
Motor para videojuegos en 3D en Android. Unity. comprueban, pero las colisiones de los objetos tipo "enemigo" con
Aunque existen numerosos motores para videojuegos en 3D en otros tipo "enemigo" no. Esto permite ahorrar mucho tiempo de
Android, el motor de videojuegos que más éxito tiene en el mercado cálculo.
es Unity que es un motor cross-platform (multiplataforma) para la
creación no solo de videojuegos en 3d sino de cualquier tipo de Si el caso de los objetos 2D no es sencillo de solucionar, con los
aplicación que contenga gráficos avanzados, incluidos gráficos en 2d. objetos 3D será más difícil aún porque los objetos tienen volumen
Unity, al contrario de Cocos2d, es propietario, no es Open Source. y no todo está en el mismo plano.
Unity puede usarse junto con 3ds Max, Maya, Softimage, Blender,
Modo, ZBrush, Cinema 4D, Cheetah3D, Adobe Photoshop, Adobe
Fireworks y Allegorithmic Substance.
Los jugadores esperan que los enemigos que aparezcan en el conexiones con el motor de físicas para cambiar las características
videojuego le supongan un desafío. De lo contrario, rápidamente se del sonido según a situación. Por ejemplo, podría producir
perdería el interés por jugar. Es ahí donde entra el motor de un efecto doppler (el que hace que sepamos si una ambulancia está
inteligencia artificial (IA) cuya misión es la de proveer a algunos de acercándose o alejándose simplemente por el sonido que emite).
los elementos del juego de un comportamiento que parezca ser También, otros pueden distorsionar el sonido para simular la
inteligente. Dada la complejidad de algunos de los problemas que acústica de una sala o de un corredor, dotando de más realismo al
Por ejemplo, para encontrar de forma eficiente el trayecto que en aquellos sistemas que soporten audio multicanal (por ejemplo,
tendría que seguir un guardia de seguridad para llegar a un punto 5.1) o bien simularlo en la salida de auriculares. Si el motor de
en un mapa se usan algoritmos de búsqueda de caminos. El más sonidos está integrado con el motor gráfico 3D, una forma de
se le denomina NPC (personaje no jugador) y suele ser controlados a una red social.
Cualquier técnica en el campo de la inteligencia artificial podría Muchos de los gestores de conexiones en red facilitan la creación de
aplicarse aquí: lógica difusa, redes neuronales, redes bayesianas, juegos multijugador permitiendo que el estado y las propiedades de
algoritmos genéticos, etc. Eso sí, hay que considerar que no deben los objetos (por ejemplo, su posición, su nivel de salud, etc.) se
ser muy costosas computacionalmente hablando para que el juego sincronice con todos las demás instancias del juego a través de un
no se ralentice. servidor. En estos casos es posible que el código específico no
necesite apenas cambios para adaptarse al entorno multijugador.
Motor de sonidos
Es el encargado de controlar la reproducción de música y efectos de La forma de implementar el multijugador varía de un motor a otro.
sonido de manera sincronizada con el resto del juego. El código Algunos usan la arquitectura cliente/servidor, de manera que todos
específico puede disponer de esta funcionalidad de forma las instancias de juego se conectan a un mismo servidor, que recibe
independiente al hardware de la plataforma. Esto quiere decir que los datos de cada cliente y los reenvía a los demás. Otros usan
si, por ejemplo, el hardware no soportara la reproducción de más de una arquitectura distribuida o P2P donde todos se comunican
un sonido a la vez, el motor podría realizar la mezcla él mismo para directamente con todos, aunque sólo suele usarse en redes de área
producir el mismo efecto sin tener que cambiar el código específico. local donde eso no supone una penalización de rendimiento.
Tanto la música como los efectos de sonido son parte de los La separación entre los roles de cliente y servidor es la más
recursos del juego. Ambos pueden incluirse como partitura (usando utilizada. De hecho, algunos juegos como Quake 2 o Quake 3, siguen
archivos MIDI) o bien de forma digitalizada, ya sea grabada este modelo incluso para el modo de un jugador, simplemente la
directamente del mundo real o modificada con algún editor de audio máquina se conecta consigo misma. El servidor guarda en memoria
como el de la figura. En los juegos modernos también pueden el estado de la partida (objetos activos, vida restante de cada
incluirse voces que se reproducirán de forma sincronizada con el jugador, ítems, munición restante, etc.) y los clientes sirven
motor de gráficos con el fin de dar la sensación de que el modelo solamente para enviar los movimientos o acciones (saltar, disparar,
está moviendo los labios. etc) y para mostrar por pantalla la proyección de lo indicado por el
servidor. El haberlo diseñado así permite extender soportar sin avanzados que pueden ser acelerados por el hardware si
apenas cambios los modos multijugador. éste lo soporta. La versión inicial fue programada por Loki
Software para facilitarse el trabajo de adaptar juegos
Librerías que dan soporte a los motores. de Windows a Linux.
Internamente los motores también se apoyan en otros
componentes. Por ejemplo: el sistema operativo, librerías de Otras librerías interesantes:
que puede aprovechar la cantidad de núcleos presentes en o Carreras: El juego consiste en una competición
Slick.
El motor de juegos 2D que utilizaremos para aprender los conceptos
es Slick. Se apoya fundamentalmente en la librería LWJGL, la cual
De momento, la carpeta que nos interesa de Slick es la carpeta lib.
incluye código nativo que se ejecuta fuera de la máquina virtual
En ella están muchos de los ficheros que hay que adjuntar al
de Java. El uso de este componente dota al motor de gran rapidez.
proyecto para usar el motor.
Los proyectos que desarrollemos con Slick podrán ser ejecutados en
aquellas plataformas para las que exista el soporte de código nativo
"Add Library...". Para terminar, elige Slick en la lista y haz clic en "Add
Library". Acepta los cambios con "OK".
Todo ello se verá de una forma muy práctica, así que deberías seguir
todas las explicaciones en un ordenador que tenga instalado
el IDE NetBeans y el motor Slick tal y como se explicó en el apartado
anterior.
Sistema de coordenadas.
Elementos de un proyecto 2D
A lo largo de este apartado echaremos un vistazo a los elementos
típicos de un juego 2D y cómo se pueden utilizar con Slick.
Partiremos de un proyecto vacío al que iremos incorporando código
y recursos.
él. Para darle más realismo, haremos que dicho personaje realice motor 2D de manera que se "trocean" internamente para poder
una animación mientras se desplaza. Por último, conseguiremos que dibujar los tiles independientemente. Parte del dibujo de
un tile puede ser transparente, lo cual será útil cuando vayamos a
superponerlo encima de otro tile para hacer efectos visuales.
Pues bien, una única línea es lo que necesita Slick para dibujar el
mapa en la esquina superior izquierda del contenedor del juego.
Ejecuta el proyecto y observa el resultado:
Dibujando tilemaps en Slick.
Si no lo tienes listo aún, crea un nuevo proyecto en NetBeans y
prepáralo para usar Slick tal y como vimos algunas secciones antes.
El método g.translate(X,Y)tiene dos parámetros que se Desplazando el tilemap (II). Respondiendo al teclado.
corresponden con el desplazamiento horizontal (X) y vertical (Y) que
Ya tenemos un mecanismo para desplazar el mapa, pero para que
queramos aplicar. Dado que la ausencia de desplazamiento se
sea útil tendremos que crear un par de variables que almacenen el
corresponde (0,0):
valor actual de dicho desplazamiento. Dichos valores variarán según
las teclas que se pulsen.
• Cualquier valor negativo en el desplazamiento X hará que
los dibujos se dibujen más a la izquierda.
• Cualquier valor positivo en el desplazamiento X hará que
los dibujos se dibujen más a la derecha.
• Cualquier valor negativo en el desplazamiento Y hará que
los dibujos se dibujen más hacia arriba.
• Cualquier valor positivo en el desplazamiento Y hará que
los dibujos se dibujen más hacia abajo.
Sprites.
esas imágenes independientes el trozo se denomina cuadro puede mirar nuestro personaje. Estos son los cambios que vamos a
o frame de la animación. El conjunto de la imagen global que hacer a nuestro código fuente:
Constructor Descripción
Animation(Image[] cua- Crea una animación con todas las imáge-
dros, int duracion) nes pasadas en el array cuadros. Cada una
de ellas se mostrará durante dura-
cion milisegundos.
Animation(Image[] cua- Crea una animación con todas las imáge-
dros, int[] duraciones) nes pasadas en el array cuadros. El
array duraciones indica durante cuantos
milisegundos se mostrará
cada frame respectivamente.
Hemos creado una variable cuadros de tipo SpriteSheet para
Animation(Image[] cua- Igual que el anterior, pero nos permite ac-
almacenar la imagen (spritesheet) que contendrá todos
dros, int[] duraciones, bool tivar o desactivar desde el constructor la
los frames de tamaño 24x32 píxeles y cinco variables de
autoActualizar) temporización automática.
Animation(SpriteSheet Crea una animación partiendo de todos los clase Animation. La variable llamada jugador contendrá ahora una
hoja, int duracion) cuadros del spritesheet hoja pasado como referencia a la animación actual mientras que las demás
parámetro. En el ejemplo veremos cómo almacenarán los datos de la animación correspondiente a la
se carga un spritesheet en Slick. dirección que indica su nombre. Por defecto, nuestro sprite estará
mirando hacia abajo.
Observa que para cargar la animación hemos usado el constructor
más complejo: el que selecciona un rectángulo de frames. Por
ejemplo, en el caso de la animación cuando el jugador mira hacia la
derecha tendríamos que seleccionar la segunda fila entera. Fíjate en
la imagen de arriba: cada frame tiene una coordenada (X,Y) en
el spritesheet, con lo que la fila que buscamos serán los frames (0,1)
(1,1) y (2,1). Si tuviéramos que expresarlo como un rectángulo, sería
uno que comienza en (0,1) y termina en (2,1).
Una posible solución es alterar la porción que vemos del mundo • .getWidth(), que nos devuelve el número de columnas
representado por el mapa. ¿Te suena? ¡Claro! En una de las fases del tilemap completo.
iniciales del proyecto conseguimos movernos libremente por • .getHeight(), que nos devuelve el número de filas
el tilemap. Aprovecharemos los conocimientos adquiridos. del tilemap completo.
• .getTileWidth(), que nos devuelve la anchura de un tile en
píxeles.
• .getTileHeight(), que nos devuelve la altura de un tile en
píxeles.
Fíjate en que si
multiplicamos mapa.getWidth() por mapa.getTileWidth() obtendre
mos la anchura total del mapa en píxeles. Lo mismo ocurrirá con la
altura total si hacemos lo propio sustituyendo Width por Height.
Añade esta línea con las demás variables:
Para no complicarlo mucho, vamos a intentar que el jugador
siempre esté en el centro de la pantalla. Con el fin de realizar los
cálculos necesitaremos usar dos métodos nuevos de la
variable gc de la clase GameContainer que se pasa como parámetro
Éstas al final del método init():
a update():
Colisiones.
Por fin nuestro héroe puede moverse por todo lo ancho y alto del
mapa sin salirse de sus límites y sin que lo perdamos de vista.
Para ello, la única información fiables que tenemos es el tilemap ya Estas propiedades pueden consultarse mediante Slick, aunque los
que la colocación de obstáculos es tarea del diseñador de mapas. En desarrolladores nos advierten de que son funciones muy lentas y
los próximos apartados aprenderemos a extraer información del él no deben usarse en los métodos update() o render(). Por tanto, si
y ha reaccionar de forma correcta ante los obstáculos. vamos a utilizarlas deberemos hacerlo en el método init() y
almacenar los datos extraídos en alguna variable (por ejemplo el
La colisión entre sprites no está soportada por Slick aún. Eso
array que comentamos antes). Los métodos para leer las
significa que, si la necesitamos, tendremos que programarla
propiedades se aplican a objetos de la clase TiledMap:
nosotros. En la unidad anterior se explicaron algunas
aproximaciones a la detección de colisiones usando formas
Método Descripción
geométricas que serían muy sencillas de aplicar.
Las dos primeras nos servirán para guardar las dimensiones del
mapa en tiles. Así evitamos tener que llamar a los métodos
continuamente. El array almacenará un booleano por cada tile del
mapa indicando con true si es un obstáculo o con false si no lo es.
Por último, incorpora las siguientes líneas al final del método init(): Aquí no tendría sentido comprobar sólo la base porque podría
ocurrir que se solaparan, como pasa con el tanque de abajo, y no se
vería natural.
Por lo pronto tenemos que determinar qué variables son distintas Y esto al final de render():
para cada NPC. En este caso será la posición actual, la posición
destino y la animación activa). No podemos reutilizar directamente
las animaciones del protagonista porque interferirían entre sí al no
ser animaciones automáticas, sino manuales.
Los NPCs también pueden participar en esto: dibújalos antes de Los ficheros XM y MOD son conocidos como formatos de
renderizar la última capa y también respetarán los tiles que están música soundtracker. Contienen grabaciones de instrumentos o
a otra altura. Eso sí, ten en cuenta que no se paran ante los sonidos y una partitura que los va reproduciendo en el momento y
obstáculos, con lo que es posible que veas cosas raras cuando pasen tono adecuado para crear la canción. Suelen ocupar poco espacio
por la base de un dibujo de varias alturas. comparados con los MP3 pero aún así pueden llegar a tener gran
calidad. En Internet podrás encontrar páginas con inmensas
Esto funcionará mientras la altura de los sprites no sea mayor que
colecciones de este tipo de música (cuidado con los derechos de autor
la de un tile, que es el caso habitual.
si usas alguna en un proyecto).
pero solo una. Es decir, si hay una canción sonando y solicitamos al void setPosition(float Mueve la reproducción al instante temporal
posicion) de posicion segundos.
motor que reproduzca otra, la primera parará con el fin de dar paso
a la segunda.
Las diferencias entre ambos son puntuales. Por ejemplo, los sonidos
carecen de métodos para pausar y reanudar la reproducción o para
En el método init() procederemos a cargar la canción y, si queremos,
realizar una transición de volumen. Tampoco podemos solicitar
a ordenar la reproducción:
notificaciones. Pero no todo iban a ser inconvenientes: se permite la
reproducción de varias instancias de
objetos Sound simultáneamente. La cantidad de sonidos depende
del sistema operativo y del hardware, pero normalmente son varias
Descarga la siguiente canción y cópiala con el nombre bi-menu.xm a decenas. Además, permite posicionar en el espacio 3D la
la carpeta data de tu proyecto. reproducción del sonido, con lo que si el jugador dispone de un
sistema de audio envolvente podemos colocar el sonido detrás de él,
¡Así de simple! En este caso estaremos reproduciendo la canción bi-
o incluso virtualmente por encima o por debajo.
menu.xm que se encuentra en la carpeta data. Tres observaciones:
la primera es que la orden de reproducción se puede dar en cualquier Éstos son los métodos más destacables de la clase Sound:
momento, no estamos forzados a hacerlo en el método init(); la
segunda es que la canción se reproducirá solamente una vez y Método Descripción
cuando termine, parará. Si necesitamos que se reproduzca void play() Reproduce el sonido una única vez.
indefinidamente tendremos que usar el método musica.loop(). La void play(float Reproduce el sonido una única vez a la velocidad
última observación es que si se trata de un fichero OGG de gran pitch, float volu- indicada por el pitch (si es mayor 1, más rápido, si
men) es menor que 1, más lento) y con el volumen espe-
tamaño, es conveniente pasar true como segundo parámetro al
cificado en volumen (1 es el volumen normal).
constructor. Con eso se solicita que no cargue el fichero completo en
void playAt(float Reproduce el sonido desde la localización 3D espe-
memoria sino que vaya leyendo lo que necesite en cada momento
x, float y, float z) cificada.
(streaming).
void play(float Igual que el equivalente play, pero posicionando la
Aquí mostramos algunos de los métodos más interesantes de la pitch, float volu- reproducción del sonido.
clase Music: men, float x, float
y, float z)
Método Descripción void loop() Reproduce el sonido en un bucle indefinido.
void play() Reproduce la canción una única vez. void loop(float Igual que el equivalente play, pero reproduce inde-
void play(float pitch, Reproduce la canción una única vez a la ve- pitch, float volu- finidamente.
float volumen) locidad indicada por el pitch (si es mayor 1, men)
más rápido, si es menor que 1, más lento) y void stop() Finaliza la reproducción abruptamente.
con el volumen especificado en volumen (1 es bool playing() Devolverá true si la canción está en reproducción.
el volumen normal).
void loop() Reproduce la canción sin parar.
void loop(float pitch, Igual que el equivalente play, pero reproduce Agreguemos entonces sonido a nuestro proyecto. Empezaremos
float volumen) indefinidamente. añadiendo una variable para almacenar la referencia:
void stop() Finaliza la reproducción abruptamente.
void pause() Realiza una pausa en la reproducción.
void resume() Continúa la reproducción que había sido pau-
sada.
En el método init() procederemos a cargar la canción y, si queremos,
void fade(int duracion, Realiza una transición suave al volumen es-
a ordenar la reproducción:
float volumenFinal, pecificado durante duracion milisegundos.
bool pararDespues) Si pararDespues vale true, al finalizar la
transición detiene la reproducción.
bool playing() Devolverá true si la canción está en repro-
ducción.
Y ahora, desde update() podemos reproducirlo cuando queramos, por
float getVolume() Devuelve el volumen de reproducción actual.
ejemplo, al pulsar la barra espaciadora. Si llamamos a play() sin
void setVolume(float Establece el volumen al indicado por el pará-
asegurarnos de que el sonido no está en reproduciéndose, volvería a
volumen) metro volumen (1.0f es el volumen normal).
empezar desde el principio:
Otras alternativas de distribución pasan por la creación de
un applet Java o un paquete JNLP Web Start, pero no las
comentaremos aquí.
Despliegue de un proyecto
sonido que se van a a generar en cada momento y se utiliza el • drawOval: dibuja un óvalo encuadrado en un rectángulo.
framework de android para reproducir estos efectos. • drawPath: dibuja un camino con la pintura específicada.
• drawPicture: dibuja una imagen cualquiera.
El Canvas en Android
• drawPoint/s: dibuja uno o varios puntos.
• drawRect: dibuja un rectángulo.
• drawRoundRect: dibuja un rectángulo con los bordes
redondeados.
• drawText: permite dibujar un texto.
• drawTextOnPath: permite escribir un texto siguiendo una
ruta a través de la pantalla.
Canvas funciona como una capa que captura todas las llamadas a Para referenciar a estos elementos desde el código hay que
“draw” y pinta sobre un Bitmap que es la pantalla. Según las escribir R.drawable.nombrefichero. Tan solo tiene una restricción,
necesidades de rendimiento se puede elegir entre pintar creando que el nombre tiene que estar en minúscula y que como caracteres
una View modificada o en un nuevo hilo de ejecución y un especiales solo acepta el guión bajo.
SurfaceView.
En XML se referencia mediante la expresión
El canvas se repinta regularmente para dar forma a la animación. @drawable/nombrefichero.
Además, para pintar un canvas, se necesitan:
Para dibujar en un canvas un bitmap se utiliza la clase
• Las coordenadas x, y donde se van a pintar el objeto. BitmapFactory y el método drawBipmap:
• Una primitiva del dibujo, es decir, qué dibujar. Por ejemplo,
Rect (Rectángulo), Text (Texto), Bitmap (gráfico).
• Un objeto Paint para describir los colores y estilo para el
dibujo.
derecho de la pantalla, mientras que la corrdenada (x_max, y_max) transparente para poder ser integrada de manera natural en una
corresponde al borde inferior izquierdo. escena. Tan sólo se dibujan encima de la escena los píxeles que no
son transparentes. Para poder hacer un sprite necesitas un
Para calcular x_max e y_max, se utiliza el objeto Display que calcula programa open source con multitud de herramientas para retocar
el tamaño de la pantalla en pixels. y editar imágenes. Con gimp puedes dibujar, recortar, convertir a
diferentes formatos y, por supuesto, crear transparencias, elemento
esencial para crear sprites. Para crear una transparencia en una
imagen, se debe añadir un "Canal Alfa" para que actúe como
transparencia en la imagen.
3. Dibujar. Por último con todo los datos
actualizados al último instante se dibuja la
nueva situación en pantalla y volvemos a
empezar.
3. Cerrar el sistema.
Otra estrategia es tomar una única imagen con todas las posturas
y cargarlas de una vez. Después, se puede ir tomando pedazos de la
imagen en secuencia para formar la animación mediante la
instrucción:
Para crear animanciones se utiliza la clase Animation, que • Al principio del programa, toda la inicialización, que no se
representa una animación que se puede aplicar a Vistas, Superficies repite.
u otros objetos. Además se puede utilizar la clase AnimationSet, que • Mientras la partida esté en marcha, una de las cosas que
representa un conjunto de animaciones que serán visualizadas al haremos es comprobar si hay que atender a alguna orden
mismo tiempo o unas detrás de otras. del usuario, que haya pulsado alguna tecla o utilizado su
ratón o su joystick/gamepad para indicar alguna acción
Android proporciona varios sistemas para crear animaciones:
del juego.
• Property Animations. • Otra de las cosas que hay que hacer siempre es
Para esta unidad hemos decidido que el motor que nos acompañará
es jMonkeyEngine 3. Los motivos son varios:
• Es software libre.
• Está escrito en Java.
• Tiene una comunidad muy activa que le da soporte.
• Es fácil de manejar y permite realizar aplicaciones con un
gran rendimiento, ya que realiza las operaciones más
Estructura de un proyecto jME3.
críticas usando librerías nativas.
Cuando se crea un proyecto con jMonkeyPlatform, se prepara por
Por si no fuera suficiente, jMonkeyEngine 3 (en adelante jME3) nosotros una estructura de carpetas destinada a facilitar la
incluye un entorno de desarrollo propio derivado directamente organización de los assets que incluyamos. Además, se añaden
de NetBeans, que incluye algunos cambios para hacernos la vida automáticamente las librerías que son necesarias para poder
más fácil a la hora de trabajar con el motor sin perder las ventajas compilar el código fuente.
de poder usar lo que ya conocemos.
jME3 es un motor de juegos 3D de código abierto programado colocaremos los assets externos que queramos incluir en el
en Java cuyos orígenes se remontan al año 2003. En el año 2008, proyecto para ser usado por el código específico:
Ejecuta el proyecto tal cual, sin cambios, y tras la compilación Comenzaremos hablando de lo que entendemos como mundo en un
deberías poder observar la siguiente pantalla: motor 3D. Tras ello, explicaremos cómo podemos referenciar puntos
en el espacio o cómo especificar direcciones para continuar con los
conceptos de vértice, polígono y malla.
Sistemas de coordenadas
Las coordenadas permiten localizar un punto. Los sistemas de
coordenadas, por tanto, nos dicen cómo situarnos en el espacio. En
En la ilustración, a representa el vector de coordenadas (ax, ay, az)
el caso de jME3, se usa el sistema de tres dimensiones de la figura.
que está dibujado en color negro. Ahí también se pueden apreciar 3
Todas las coordenadas son relativas al origen: el punto (0, 0, 0). Como
vectores de color azul, rojo y verde: se corresponden con los vectores
ves, se necesitan 3 valores para concretar una posición: uno para el
(1,0,0) , (0,1,0) y (0,0,1) e indican la dirección de los ejes X, Y y Z
eje X (valores positivos hacia la derecha), otro para el eje Y (valores
respectivamente.
positivos hacia arriba) y otro para el eje Z (valores positivos saliendo
de la pantalla hacia ti). Recuerda: a pesar de su aspecto similar, unas coordenadas se
refieren a un punto en el espacio concreto mientras que un vector
El punto origen es donde coinciden todos los ejes y, como hemos
se refiere siempre a una dirección.
dicho antes, se corresponde con el conjunto de coordenadas (0, 0, 0).
Por ejemplo, si el origen fuera la parte central de la superficie de tu Aprovecharemos para presentarte uno de los objetos más utilizados
pantalla, el conjunto (-2, 2, 2) haría referencia a un punto situado en en jME3: com.jme3.math.Vector3f. Esta clase es capaz de trabajar
el cuadrante superior izquierda de la pantalla y que sobresaldría de con grupos de 3 coordenadas y puede usarse para almacenar una
la superficie. posición o un vector y realizar operaciones con ellos.
Es importante destacar que un conjunto de coordenadas es Vector3f v1 = new Vector3f( -20, -30, 40 );
simplemente una posición en el espacio, no debes confundirlo con el
concepto de vector que veremos más adelante. Sus métodos son bastante numerosos: calcular distancia respecto
a otro punto, multiplicaciones vectoriales o escalares, proyecciones,
sumas, etc. Todas ellas son muy interesantes si quieres meterte a
fondo con las matemáticas que hay detrás del mundo de las 3D,
pero nosotros utilizaremos unas pocas solamente.
Hay algunos objetos estáticos de este clase que son muy útiles. Por
ejemplo Vector3f.ZERO equivale al origen o, lo que es lo mismo, las
coordenadas (0, 0, 0).
Ya vimos hace un par de unidades que los objetos que puedes ver
Reflexiona en un juego 3D están generalmente formados por
una malla (mesh) de polígonos. Estos polígonos están conectados
Cuando decimos que un punto está en la posición (1, 0, 0), ¿cuánto
entre sí como una red y pueden definir formas muy complejas.
de lejos estamos del origen? ¿1 centímetro? ¿1 metro? ¿1 kilómetro?
Fíjate en que incluso las superficies curvas como una esfera se divide Por ejemplo, fíjate en la moto y las dos personas que están a su
en polígonos para poder dibujarse: izquierda; los tres son geometrías. Cada uno de ellos dependen de
un nodo de color azul. Supón que sus posiciones reales en el mundo
están establecidas de tal manera que parezca que están sentadas
sobre la moto. Si muevo el nodo del que dependen, el de color rojo, el
cambio afectará de igual forma a los nodos azules y estos, a su vez,
a las geometrías que cuelgan de ellos. ¿El resultado? La moto y sus
ocupantes se moverán a la vez a la nueva posición. Esto ahorra
tiempo y código al programador.
Los polígonos están, a su vez, definidos por los vértices (puntos en Cada spatial es, por tanto, relativo a su spatial padre, del cual
3D) que los componen. Como mínimo, para definir un polígono se depende directamente. Ejemplo: puedo construir una esfera cuyo
necesitan tres vértices. El tipo más común de polígono en el mundo centro esté en la posición (0,0,0). Esa coordenada recibe el adjetivo
3D son los triángulos, los cuáles poseen tres vértices. de "local" porque solo tiene significado dentro de la geometría. Sin
embargo su posición real en el mundo dependerá de la que tengan
Cuando se utiliza un programa de modelado en 3D es necesario los spatials de los que cuelga.
tener esto en cuenta para poder definir la forma del objeto que
deseamos implementar. Añadiendo spatials al grafo (I). Geometrías.
Abre el proyecto HolaMundo que creamos antes y abre el código
Grafo de escena. fuente desde la vista en árbol de la parte izquierda:
Ya hemos explicado que un motor 3D basa su funcionamiento en la
construcción de un mundo al cual vamos añadiendo elementos. Con
el fin de gestionarlos de forma rápida y eficiente, internamente se
almacenan en forma de árbol. Esto nos facilita la clasificación de los
elementos en categorías y permite establecer las relaciones que
existen entre ellos.
En la figura puedes observar que los spatials pueden ser de dos Analicemos el código y veamos cómo casa con el grafo de escena:
tipos: nodos y geometrías.
rootNode.attachChild(geom);
Reflexiona
La última línea indica al motor que queremos añadir la geometría
al nodo raíz, rootNode. Dado que todo lo que cuelga ¿Qué ocurriría si añadimos justo antes de asignar el material
de rootNode forma parte del mundo, lo que acabamos de hacer es a geom2 la siguiente línea?
incorporarlo a este último: por eso podemos verlo.
mat.setColor("Color", ColorRGBA.Pink);
Añadiendo spatials al grafo (II). Nodos.
QUE TANTO EL CUBO COMO LA ESFERA SE VUELVEN DE COLOR ROSA. QUIZÁS
Añade los siguientes imports imports al proyecto:
TE PREGUNTES POR QUÉ EL CUBO NO SE VE AZUL SI LE ASIGNAMOS EL MATERIAL
Actualizando el mundo.
Si volvemos la vista atrás a los motores 2D, seguramente recuerdes
que el bucle de juego (game loop) en Slick alternaba entre llamadas
a dos métodos: update() y render(). En el primero, actualizábamos
la posición de los sprites, leíamos el teclado, etc., en resumen:
implementábamos la lógica del juego (game logic). En el segundo
dibujábamos todos los elementos.
Lo que hemos hecho es crear otra forma, esta vez una esfera de
radio 1 wu (los otros parámetros del constructor se verán más
adelante) y asignarlo a una nueva geometría a la que le aplicaremos
Concretamente estamos indicando al nodo n que queremos rotarlo
el mismo material del cubo.
en el eje Y (el vertical). Como las dos geometrías usan como
Y fíjate: en lugar de incorporar las geometrías directamente referencia al nodo n, cuando lo rotemos, ellas lo acompañarán.
a rootNode lo hemos hecho en un nuevo nodo que hemos llamado
Ejecútalo, y comprobarás apenas se aprecia la rotación en el cubo y
“Pivote”. Finalmente, hemos añadido el nodo recién creado
nada en la esfera. ¿Qué hemos hecho mal? Nada, en realidad están
rotando correctamente pero no lo vemos claramente ya que el tecla espacio, pulsando el botón izquierdo del ratón, girando
material que hemos asignado a las geometrías es siempre un color el joystick a la derecha, pulsando el botón A del gamepad, etc.).
fijo. Cambia los parámetros de .rotate a (0, 2*tpf, 2*tpf) y lánzalo.
Veámoslo con un ejemplo: añade el siguiente import al código del
Al girar ahora también en el eje Z se apreciará la rotación sin
apartado anterior:
problemas.
En la mayoría de motores de juegos 3D, jME3 incluido, se suele usar Puedes añadir varios disparadores de la misma clase, y no estamos
el concepto de action (acción) y de binding (atadura). Básicamente limitados a los del ejemplo:
se trata de definir las posibles acciones que puede realizar el
usuario: saltar, moverse hacia adelante, disparar, cambiar de arma,
etc. y luego asociar cómo las puede lanzar el jugador (pulsando la
Clase de disparador Descripción
KeyTrigger(int tecla) Pulsación de una tecla del teclado KeyIn-
put.KEY_W, .KEY_P, .KEY_2, .KEY_NUM-
PAD2 (el 2 del teclado numérico), etc. Pulsa
Ctrl+Espacio detrás de KeyInput.en el IDE para
verlos todos.
MouseButtonTrigger(int bo- Pulsación de un botón del ratón. El parámetro
ton) boton puede ser el botón izquierdo (MouseIn-
put.BUTTON_LEFT), derecho (.BUTTON_RIGHT)
o central (.BUTTON_CENTER).
Materiales.
MouseAxisTrigger(int eje, Movimiento creciente en uno de los ejes del
Los objetos que coloquemos en nuestro mundo virtual tienen que
boolean invertido) ratón. La variable eje dice qué se controlará:
tener una forma (que se deriva de su malla) y un material que
el eje vertical (hacia arriba, MouseIn-
define su aspecto. Todos los materiales en jME3 son instancias de
put.AXIS_Y), el horizontal (hacia la dere-
la clase Material y existen algunos predefinidos que pueden usarse
cha, .AXIS_X) o la rueda de desplazamiento
(.AXIS_WHEEL). Si invertido vale true, el dis- de base para construir los nuestros.
parador se lanzará cuando disminuya la posi-
Empezaremos cambiando los materiales de nuestro HolaMundo.
ción en dicho eje, es decir, en el caso del eje
Éstas son las líneas que definen el material:
vertical será cuando vaya hacia abajo o en el
caso del eje horizontal cuando se mueva a la
izquierda.
JoyButtonTrigger(int joy, int Similar a MouseButtonTrigger pero
boton) para joysticks y gamepads. Hay que especifi-
car primero en joy el identificador del disposi-
tivo. boton será el identificador del botón que
Si para ver mejor la rotación cambiaste el material a
queremos controlar.
JoyAxisTrigger(int joy, int eje, Similar a JoyButtonTrigger pero para joysti- "Common/MatDefs/Misc/ShowNormals.j3md" y comentaste la línea
boolean invertido) cks y gamepads. Hay que especificar primero donde se establecía el color, vuelve a dejarlo todo como aparece ahí
en joyel identificador del dispositivo Los ejes arriba.
aquí serán JoyIn-
Lo primero que tendríamos que preguntarnos es qué es la
put.AXIS_POV_X y .AXIS_POV_Y.
variable assetManager, pues no aparece en ningún otro sitio del
código fuente. Este objeto nos permite acceder a los recursos de
Respecto a la generación de eventos nuestro juego, realizando la búsqueda del asset que le solicitemos
con inputManager.addListener() hay que destacar que existen dos en todos los sitios que hayamos configurado previamente. Por
tipos de objetos receptores de defecto buscará en la carpeta assets de nuestro proyecto y en otras
notificaciones: AnalogListener y ActionListener. rutas internas del motor que contienen datos predefinidos. El
material concreto que hemos pedido es uno de esos datos que
Existen varias diferencias entre ambos: La primera y fundamental
vienen preinstalados con el motor y tiene la particularidad de que
es que AnalogListener se llamará mientras el disparador
no necesita iluminación de ningún tipo para ser visible. Si queremos
permanezca activo; ActionListener, por otro lado, sólo se llamará
que al material le afecten las fuentes de luz
una única vez cuando se detecte el disparo y otra vez cuando cese.
usaremos Common/MatDefs/Light/Lighting.j3md. En la tarea
La segunda es que AnalogListener recibirá un valor de intensidad
veremos ese material con más detalle.
de disparo, mientras que ActionListener sólo indicará si existe
disparo o no. Cada material tiene unas propiedades propias y debemos
conocerlas porque si intentamos cambiar un valor en una de ellas
También varían el nombre de los métodos llamados y sus
y el material no la soporta provocaremos un error de ejecución que
parámetros:
detendrá el juego en seco.
• AnalogListener.onAnalog(String accion, float valor, float Del material predefinido Unshaded.j3md vamos a destacar dos
tpf): el parámetro valor indicará el grado de intensidad del propiedades que son muy interesantes: "ColorMap" y "Color". Esta
disparo y puede tomar muchos valores (un joystick puede última indica el color que tendrán todos los polígonos que forman
estar hacia arriba del todo o sólo hasta la mitad). la malla del objeto. Si no queremos restringirnos a usar los colores
• ActionListener.onAction(String accion, boolean pulsado, estándar que vienen en el motor, podemos crear el nuestro propio.
float tpf): el parámetro pulsado indicará si es una llamada Aprovechamos la ocasión para explicar cómo podemos definir
para indicar que el control se ha pulsado o bien para colores enjME3: se hace con la clase ColorRGBA y el color se consigue
indicar que ha dejado de pulsarse. mezclando los tres colores luz primarios: el rojo, el verde y el azul.
En ambos casos se incluye el parámetro accion para indicarnos el mat.setColor("Color", new ColorRGBA(rojo, verde, azul, alfa));
nombre de la acción que ha provocado el disparo y tpf para
indicarnos el tiempo que dura el frame actual y cuyo valor tenemos Cuenta bien los parámetros. Hay uno, alfa, que no conocemos aún.
que considerar de cara a las actualizaciones. En el campo de la infografía, el concepto de alfa es equivalente a
transparencia. Un color que tenga un alfa menor que 1 es traslúcido, Cuidado: si el modelo que queremos importar no tiene material será
es decir, dejará entrever lo que hay detrás de él. Lamentablemente obligatorio asignarle uno antes de incluirlo en el grafo de escena.
el material Unshaded ignora el valor del parámetro alfa. Puedes usar el material
base "Common/MatDefs/Misc/ShowNormals.j3md"Common/MatDe
Volviendo a los colores, un valor de 0 en uno de los tres colores
fs/Misc/ShowNormals.j3md" con este tipo de objetos para
primarios implica que no aporta nada al color final, mientras que
visualizarlo si no quieres complicarte mucho.
un valor de 1 indica que está totalmente presente en la mezcla. Por
ejemplo, un color(1,0,0) será un rojo puro, un color(1,1,1) será blanco al Vamos a importar el modelo de una silla de madera. Crea un nuevo
sumar todos los primarios, un color (0,0,0) será negro por la proyecto e incluye este código en el
ausencia de colores y un color (0.5f, 0.5f, 05f) será un gris método simpleInitApp()simpleInitApp():
intermedio ya que todos los colores aportan la mitad de su valor
máximo.
Modelos.
Ya hemos visto que a los spatials de tipo geometría se les puede
asignar una forma. Esa forma está compuesta de polígonos que El fichero contiene el modelo de la silla en formato Blender y en
forman una malla (mesh) y sobre ellos es donde se aplica el formato Ogre3D, acompañados por sus texturas y luces.
material. Lo normal no suele ser crear las mallas desde el código Aunque jME3 puede leer este último tipo de formato, el método de
específico sino obtenerlas de un recurso. A ese recurso le llamamos trabajo recomendado es convertirlo al formato nativo de jME3, de
modelo. extensión .j3o. ¡Cuidado! Cuando se despliegue el proyecto no se
copiarán los modelos y escenarios que no estén en formato .j3o. La
Los modelos puede constar solamente de la malla, aunque también
conversión se realiza haciendo clic con el botón derecho
puede acompañarle el material que lo recubre o, como veremos más
sobre chair.scene en el árbol del proyecto y seleccionando la opción
adelante, animaciones que cambian la forma dinámicamente
“Convert to j3o Binary”.
cuando se lo indicamos.
Importando un modelo.
Incorporar modelos a nuestro proyecto es algo muy sencillo. Lo
primero es copiar el modelo que queremos usar dentro de la
carpeta assets/Models de nuestro proyecto. Dado que normalmente
un modelo puede incluir no sólo la malla sino también sus texturas
e incluso animaciones, suele componerse de varios ficheros. Es por
ello que de cara al mantenimiento del proyecto se recomienda que
cada modelo tenga su propia subcarpeta dentro de Models; la única
excepción obvia es tener varios modelos que compartan materiales,
pues almacenarlos en la misma carpeta ahorra espacio. La carga de Las líneas que están detrás de rootNode.attachChild(silla) sirven
escenas se realiza exactamente igual que con los modelos, pero por para crear una luz de ambiente que nos permita ver el modelo con
motivos de organización se recomienda almacenarlas claridad. Pronto hablaremos de la iluminación.
en assets/Scenes.
Reflexiona que pueden aplicarse a cualquier Spatial, lo que incluye las
clases Node y Geometry.
Habrás comprobado que la silla tiene un tamaño considerable.
¿Recuerdas qué tipos de transformaciones se podían aplicar a Iluminación.
un spatialspatial? ¿Qué transformación podrías realizar para que Tal y como sucede en el mundo real, algunos materiales no se
sea más pequeña la silla? pueden apreciar si no son iluminados por una fuente de luz. Además,
también existen muchos tipos distintos de luces: luz ambiente, luces
PRINCIPIO DEL FORMULARIO
direccionales (como los focos), etc. Cada una de ellas ilumina de una
LAS TRANSFORMACIONES ERAN TRASLACIÓN, ROTACIÓN Y ESCALA. EN ESTE forma distinta los objetos de una escena.
CASO, SERÍA LA ÚLTIMA DE ELLAS. PODRÍAMOS AÑADIR SILLA.SCALE(0.4F); QUE
Recuerda también que hay varios tipos de materiales base que no
REDUCE EL TAMAÑO DEL MODELO A UN 40% DEL ORIGINAL.
necesitan iluminación, como por ejemplo Unshaded y ShowNormals.
Haz pruebas con las tres transformaciones usando los Estos son las clases que implementan los tipos de luces soportados
métodos silla.move(), silla.rotate() y silla.scale(). Con el
por jME3:
autocompletar del IDE comprobarás que algunas de ellas admiten
varias alternativas de parámetros a la hora de llamarlas. Recuerda
Tipos de luz Descripicón y ejemplos de uso
PointLight Tiene 3 propiedades: localización, radio y color. Brilla en todas las direcciones alrededor de su posición hasta llegar al radio. La
intensidad decrece conforme nos alejamos del centro. Es útil para simular bombillas, antorchas, velas, etc. Puede lanzar sombras.
Coloca una luz de color verde en el origen que ilumina hasta 3 metros alrededor.
DirectionalLight Tiene 2 propiedades: color y dirección.Ilumina toda la escena desde la dirección indicada. Todos los rayos de luz vienen paralelos,
como si vinieran de una fuente que está a distancia infinita. Permite simular el efecto de un sol, por ejemplo. Puede lanzar
sombras.
Coloca una luz blanca que viene de la dirección (-1, -1, -1).
SpotLight Tiene 5 propiedades: localización, dirección, color, ángulo interior y ángulo exterior. Es una luz similar a la de un foco: el ángulo
interior marca el máximo de luz y el exterior donde deja de iluminar. Permite simular el efecto de una linterna, un foco o una
farola.
Coloca un foco que ilumina de color blanco lo que tiene delante la cámara hasta 100 metros y está entre 5 y 45 grados alrededor
del centro de luz.
AmbientLight Tiene un único parámetro: el color. La luz ilumina toda la escena globalmente, brilla igual por todos lados, por eso no suele usarse
sola ya que los resultados no son naturales. No crea sombras. Si el color no es blanco puede alterar el color de los demás
materiales de forma general.
Como habrás podido comprobar, para añadir una luz al mundo Reflexiona
utilizamos el método rootNode.addLight() .
Con rootNode.removeLight() podemos retirarla del grafo. Hay otros controles que son muy útiles. Busca en la
documentación Javadoc para ver los detalles.
Moviendo luces y proyectando sombras.
• ChaseCamera(Camera cam) permite a la
Si quieres que una luz se mueva por el mundo se puede hacer de
cámara cam seguir al spatial desde una corta distancia y
dos maneras: posicionándola manualmente en dentro del
permite rotar la vista con el ratón. Puedes usarlo para
método simpleUpdate() o bien indicándole que siga
juegos en tercera persona.
automáticamente al spatial que le indiquemos.
• RigidBodyControl, CharacterControl, VehicleControl, Ghost
El segundo procedimiento se realiza mediante un Control y RagDollControl hacen que el spatial al que lo
objeto LightControl, que es de tipo Control. Este tipo de objetos asignemos responda de forma realista a las fuerzas que
permiten asociarse a un spatial de manera que controlan le apliquemos, las colisiones con otros objetos y le afecte
transformaciones de forma autónoma. En el caso concreto la gravedad. Los veremos en detalle más adelante.
de LightControl, cuando se asocia a un spatial éste actualizará la • MotionTrack() permite que un spatial siga un camino
posición de la luz sin nuestra intervención: determinado de forma automática.
Animaciones.
Existe un tipo de modelo especial: los modelos animados. En lugar
de contener una forma estática, los modelos animados tienen una
geometría variable que les permite cambiar su forma suavemente
según las instrucciones del código específico. Veamos un ejemplo.
Crea un nuevo proyecto, añade la librería jme3-test-data y usa el
código fuente que aparece al final del apartado.
Esas línea obtiene una referencia al objeto que controla la animación Recuerda que el método se llamará en dos ocasiones: una cuando
del spatial donde hemos cargado modelo. pulsemos la barra espaciadora (keyPressed valdrá true) y otra vez
cuando la soltemos (keyPressed será false). En el primer caso
Reflexiona
querremos activar la animación “Walk” (andar) y en el segundo la
Nosotros no lo necesitamos para el ejemplo, pero opcionalmente animación “stand” (de pie).
podríamos haber usado el método control.addListener() para añadir
Sea cuál sea la acción, primero comprobaremos que no se esté ya
un objeto de tipo AnimEventListener al controlador. De haberlo
ejecutando la animación que deseamos. Si es así, le decimos al canal
hecho, el controlador habría llamado a los métodos de dicho objeto
que comience con la nueva animación, pero que realice una
en distintos momentos de la animación (por ejemplo, cuando
transición de la posición actual del modelo hasta la nueva que dure
terminara o cuando cambiara de una animación a otra).
medio segundo. Así el cambio será suave. Con la última línea
Dado que podemos tener más de una animación funcionando sobre indicamos cuántas veces queremos repetir la animación. Si
un mismo modelo (por ejemplo, el brazo de la izquierda está ponemos LoopMode.Loop, la animación se repetirá
blandiendo una espada mientras que la mano derecha está automáticamente hasta que la cambiemos o paremos.
moviendo un escudo), las animaciones se ejecutan en canales. Cada Con LoopMode.DontLoop se ejecutará una vez y parará.
nodo puede tener más de un canal de animación simultáneo, pero
cada canal sólo admite una animación. Fíjate: Físicas y colisiones
jME3 incluye un motor de físicas llamado JBullet que se integra
perfectamente en nuestro mundo virtual. Por defecto viene
desactivado e incluso una vez activado será necesario indicarle qué
geometrías queremos controlar. El motivo es que la capacidad de
cálculo que sería necesaria para simular todas las propiedades
físicas incluso de una pequeña escena sería demasiado hasta para
un ordenador potente.
Detectando colisiones
Como es lógico, en la mayoría de los juegos necesitaremos detectar
las colisiones que se produzcan entre los objetos. jME3 nos lo pone
La primera línea crea un simulador y la segunda lo acopla al bucle fácil, ya que el motor de físicas tiene que tenerlas en cuenta para
interno del motor de juegos. responder de forma natural al movimiento de los objetos.
Para incorporar una geometría al motor de físicas tendremos que Con este comando indicaremos al motor que queremos estar al
crear un objeto de control que conecte la geometría con un modelo corriente de las colisiones que se produzcan:
físico. Uno de los objetos de control más utilizados
es RigidBodyControl que considera la geometría como un cuerpo bulletAppState.getPhysicsSpace().addCollisionListener(collisionListe
sólido con una masa determinada. ner);
La segunda línea asocia el controlador de físicas a la geometría. Con Ten en cuenta que el suelo y las paredes cuentan como nodos que
esta asociación, el controlador podrá modificar la posición y la pueden colisionar y cualquier objeto que esté apoyado en ellos estará
rotación del objeto respondiendo al entorno. Por último, mediante la emitiendo eventos de colisión continuamente hasta que esté en
última línea avisamos al motor de físicas que queremos que tenga reposo. Para evitarlo, comprueba los elementos devueltos
en cuenta un nuevo objeto en sus cálculos. Cuidado: en el momento por .getNodeA() y .getNodeB() para ignorar los eventos relacionados
que incorpores un objeto al simulador de físicas le afectará la con los objetos estáticos.
gravedad, como en el mundo real.
Juegos de disparo en primera persona.
¡Eso es todo! Por supuesto, existen otros tipos de controladores,
Uno de los géneros más extendidos que hacen uso de motores 3D
algunos de los cuáles veremos más adelante.
son los juegos de disparo en primera persona. jME3 tiene un soporte
Reflexiona especial para este tipo de juegos mediante el uso de algunas clases
que nos simplifican algunas tareas, como por ejemplo la
Quizás tengas curiosidad por ver cómo ve el motor de físicas los clase CharacterControl, que implementa un objeto especializado en
objetos que añadimos a la simulación: añade esta línea para acrtivar el control del jugador.
el modo de depuración:
Nuestra versión está traducida al español y un poco cambiada.
bulletAppState.getPhysicsSpace().enableDebug(assetManager); Puedes descargarla el archivo comprimido que incluye el main.java y
la escena town.zip.
JBullet distingue entre dos tipos de objetos: estáticos y dinámicos.
El que acabamos con el ejemplo es dinámico. Los objetos estáticos
tienen masa 0 y no se pueden mover. Un objeto dinámico, por otro
lado, reaccionará adecuadamente al chocar contra un objeto estático.
Por eso el suelo y las paredes suelen programarse como objetos
estáticos, lo que ahorra tiempo de cálculo.
Ejecuta el proyecto y luego vuelve para que podamos analizar parte profundidad en la que se encuentran de forma que sólo se dibujan
del código fuente. los más próximos a la proyección. Es entonces cuando la imagen ya
estará lista para mostrarse en pantalla.
Fíjate en que el código usa una nueva forma de cargar assets. Se
pueden incluir en un archivo .zip y copiarlo en el raíz del proyecto. En el ejemplo de la figura se puede ver el efecto de aplicar un
Con assetManager.registerLocator() añadimos dicho archivo en la programa de cel shading a una escena. Esta técnica convierte una
ruta de búsqueda. proyección 3D en una simulación de dibujo plano 2D. Internamente,
se usan varios programas de shaders con el fin de obtener dicho
Otra novedad es cómo generamos la forma de colisión de la escena. efecto.
La siguiente llamada hará el cálculo por nosotros a partir de la
referencia: En jME3 se pueden implementar vertex shaders y fragment
shaders usando GLSL, que es el estándar de OpenGL para describir
formaEscena = CollisionShapeFactory.createMeshShape((Node) este tipo de programas. De hecho, jME3 usa
escena); internamente shaders para implementar los materiales y otros
efectos especiales como el agua. Lógicamente, las posibilidades son
Por último podrás comprobar que el jugador viene representado en
enormes, pero se salen fuera del ámbito del módulo profesional.
el motor de físicas por una forma de colisión de cápsula. Esta forma
es ideal para representar a jugadores que tienen que pasar por
Efectos de sonido.
sitios estrechos y subir peldaños, al menos desde el punto de vista
Usar sonidos en jME3 no presenta ninguna complicación. Es
de la colisión. La forma estará siempre en vertical, como es de
suficiente con cargar un asset que contenga el sonido y
esperar para el jugador. El primer parámetro del constructor
obtendremos un nodo que podemos situar en el grafo de escena.
de CapsuleCollisionShape es el radio, el segundo la altura y el tercero
el eje sobre el que la cápsula estará siempre apoyada (0=eje X, 1=eje Crea un proyecto nuevo e incorpora la librería jme-test-data.jar ya
Y y 2=eje Z). que contiene algunos sonidos de ejemplo. Para cargar un sonido
basta con ejecutar:
El control CharacterControl incluye un segundo parámetro que
indica el tamaño del escalón: todo desnivel inferior a esa altura
podremos subirlo sin necesidad de saltar. Las tres siguientes
llamadas .set establecen la velocidad del salto, la velocidad de caída
y la gravedad respectivamente.
El parámetro false indica que queremos cargar el sonido completo
en memoria. En caso de que el recurso sea una canción o algo
Shaders
excesivamente largo, hay que colocar true para que vaya leyendo el
Al comienzo, las tarjetas gráficas con aceleración 3D no tenían la
sonido poco a poco conforme se reproduzca.
posibilidad de modificar el comportamiento de los procesos de
renderizado (rendering pipelinerendering pipeline) lo cual limitaba Reflexiona
las opciones a la hora de implementar algunos efectos especiales.
Desde el año 2000, dicha limitación desapareció con la introducción ¿Por qué es lógico que un motor de juego 3D nos devuelva una
de los shaders. Los shaders son programas que se ejecutan en referencia de tipo Node cuando cargamos un sonido?
la GPU de la tarjeta gráfica y que controlan algunos de esos
DADO QUE LA ACCIÓN TOMA LUGAR EN UN ESCENARIO 3D, LO LÓGICO ES QUE
procesos.
EL SONIDO TAMBIÉN SE PUEDA LOCALIZAR ESPACIALMENTE. SI ASOCIAMOS LA
Cuando se quiere dibujar una escena, el motor 3D envía a la tarjeta REPRODUCCIÓN DE UN SONIDO A UN NODO LO PODREMOS COLOCAR EN LA
gráfica una secuencia de vértices. Dichos vértices son procesados POSICIÓN DEL GRAFO QUE NOS INTERESE (POR EJEMPLO, JUNTO A LA
uno a uno por un vertex shader donde pueden sufrir cambios. Para GEOMETRÍA DE UN TANQUE) Y SE MOVERÍA CON EL RESTO DE LOS ELEMENTOS
la ejecución de dicho shader sólo se dispone de la información ASOCIADOS. DE ESTA FORMA EL SONIDO PARECERÁ VENIR DE DONDE DESEAMOS.
Por otro lado, para que el motor pueda hacer sonar el audio
posicional de manera convincente, necesitamos especificar la Creación de un applet Java: si lo que queremos es ejecutar el
localización y dirección desde donde deseamos escuchar. Existe un proyecto en un navegador web, ésta es tu opción. Ten en cuenta que
objeto global llamado listener que almacena dichos datos. Si aquí también puedes encontrar problemas con los recursos
queremos que siga a la cámara, tendríamos que colocar las dos externos que no estén dentro de la carpeta assets. Además,
líneas siguientes en el método simpleUpdate(): un applet Java no puede capturar el ratón más allá de sus límites,
con lo que el comportamiento del movimiento del ratón puede a
veces ser sustituido por otros procedimientos (por ejemplo, pinchar
y arrastrar para mover la cámara). La generación del applet se
realiza de forma similar a los anteriores. La
Despliegue de una aplicación carpeta dist/applet contendrá los ficheros que has de subir a la
jMonkeyPlatform nos ofrece múltiples posibilidades a la hora de página web.
desplegar la aplicación: crear un archivo .jar multiplataforma, crear
ejecutables para una plataforma concreta o crear
un applet Java para los navegadores web. Lo primero es indicar los
datos del proyecto desde sus propiedades, dado que esa información
En la propia aplicación podemos acceder a una tienda como si de la
App Store se tratase, donde encontraremos multitud de recursos
gratuitos y de pago. Incluso podremos extender la herramienta
mediante plugins que obtendremos en dicha tienda.
5. Fuentes ................................................................................................................................ 24
1. Introducción
En este caso tendremos una cámara con vista en perspectiva y una luz
direccional:
2. Creación del entorno
2.1. Añadiendo un terreno
Width: El ancho en
metros de nuestro
terreno.
Lenght: La longitud en
metros del terreno.
Heightmap Resolution:
La resolución del
heightmap. Debe tenerse
en cuenta que debe ser
potencia de 2 + 1.
(Ejemplo: 129,513)
Width: 500m
Lenght: 500m
Height: 500m
Paint Terrain
Paint Detail: Nos permite dibujar los detalles del terreno como hierva.
Consejo:
Vayamos a “Windows->Rendering->Lithgning”
para mostrar las propiedades de renderizado que
se mostraran en una ventana emergente.
Por último debemos añadir una luz a nuestra escena, llamada luz solar.
Para añadir una luz vamos a “GameObject -> Create Other ->
Directional Light”.
Flechas: Movimiento
Espacio: Saltar
Mientras que editar las propiedades básicas debería cumplir con los
requisitos de tu juego la realidad es que no es así. En bastantes
ocasiones, particularmente con elementos como los controladores de
personajes, necesitamos hacer más cambios.
El resultado:
5. Fuentes