miércoles, 14 de noviembre de 2012

Android: Crear animación con sprites (Animation)

Buenos días, en este tutorial vamos a aprender como crear una animación con la clase AnimationDrawable y con sprites de una manera sencilla y muy útil.
En este caso los sprites están por separado, más adelante publicaré otro tutorial con todos los sprites en una sola imagen. Ya que es algo más óptimo.

Para empezar muestro los sprites que vamos a utilizar:

Para descargar los sprites: http://adf.ly/UUGQd

Como podéis ver los sprites que van hacia arriba tienen el prefijo 'u' del que se dirigen abajo 'a', derecha 'd' e izquierda 'i'. Tenerlos completamente ordenados es esencial para llevar acabo la animación.  

Seguidamente crearemos nuestro projecto, en mi caso eclipse, y crearemos 4 archivos .xml en la carpeta de res/drawable en el caso de no existir la crearemos. Los archivos .xml deben ser los siguientes:

arriba.xml
<?xml version="1.0" encoding="utf-8"?>  
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"  
    android:oneshot="false">  
    <item android:drawable="@drawable/u_1" android:duration="60" />  
    <item android:drawable="@drawable/u_2" android:duration="60" />  
    <item android:drawable="@drawable/u_3" android:duration="60" />  
    <item android:drawable="@drawable/u_4" android:duration="60" />  
    <item android:drawable="@drawable/u_5" android:duration="60" />  
    <item android:drawable="@drawable/u_6" android:duration="60" />  
    <item android:drawable="@drawable/u_7" android:duration="60" />  
    <item android:drawable="@drawable/u_8" android:duration="60" />  
</animation-list>


En este xml lo que hace es agrupar todas las imagenes (que debemos tener integradas en el res/drawables anteriormente), las agrupamos en el óden en el que tendrá que aparecer la animación y añadiremos tantos sprites como necesitemos en este ejemplo son 8 para cada dirección del personaje. Ahora deberíamos crear los siguientes archivos para la direccion de abajo, derecha e izquierda:

abajo.xml
<?xml version="1.0" encoding="utf-8"?>  
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"  
    android:oneshot="false">  
    <item android:drawable="@drawable/a_1" android:duration="60" />  
    <item android:drawable="@drawable/a_2" android:duration="60" />  
    <item android:drawable="@drawable/a_3" android:duration="60" />  
    <item android:drawable="@drawable/a_4" android:duration="60" />  
    <item android:drawable="@drawable/a_5" android:duration="60" />  
    <item android:drawable="@drawable/a_6" android:duration="60" />  
    <item android:drawable="@drawable/a_7" android:duration="60" />  
    <item android:drawable="@drawable/a_8" android:duration="60" />  
</animation-list>
derecha.xml
<?xml version="1.0" encoding="utf-8"?>  
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"  
    android:oneshot="false">  
    <item android:drawable="@drawable/d_1" android:duration="60" />  
    <item android:drawable="@drawable/d_2" android:duration="60" />  
    <item android:drawable="@drawable/d_3" android:duration="60" />  
    <item android:drawable="@drawable/d_4" android:duration="60" />  
    <item android:drawable="@drawable/d_5" android:duration="60" />  
    <item android:drawable="@drawable/d_6" android:duration="60" />  
    <item android:drawable="@drawable/d_7" android:duration="60" />  
    <item android:drawable="@drawable/d_8" android:duration="60" />  
</animation-list>
izquierda.xml
<?xml version="1.0" encoding="utf-8"?>  
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"  
    android:oneshot="false">  
    <item android:drawable="@drawable/i_1" android:duration="60" />  
    <item android:drawable="@drawable/i_2" android:duration="60" />  
    <item android:drawable="@drawable/i_3" android:duration="60" />  
    <item android:drawable="@drawable/i_4" android:duration="60" />  
    <item android:drawable="@drawable/i_5" android:duration="60" />  
    <item android:drawable="@drawable/i_6" android:duration="60" />  
    <item android:drawable="@drawable/i_7" android:duration="60" />  
    <item android:drawable="@drawable/i_8" android:duration="60" />  
</animation-list>
Una vez ya tengamos todo bien organizado pasamos a crear un ImageView en el main.xml con 4 botones. Este código ya no es necesario ya que hice un tutorial para eso (ver). Ya podemos ir a nuestra activity y empezar con el java.
Una vez tengamos relacionado nuestro 4 botones y el ImageView en nuestra clase  (ver) voy a poner de ejemplo cómo sería el botón de Up para que vosotros de manera algo más autodidacta añadáislas funciones a los otros tres botones. Adjunto el código que irá dentro del boton Up totalmente comentado:
//Añadimos el Listener tal y como ya sabemos
//En este caso un Touch en vez de un click para
//dar efecto de pulsado o no pulsado
bt_up.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
 //Si el usuario esta tocando el botón
 if (event.getAction() == MotionEvent.ACTION_DOWN ) {
  //Cargamos la animacion del xml en el imageview
  //previamente ya creado
  imageView.setBackgroundResource(R.drawable.arriba);   
  //mi_animacion es de la clase AnimationDrawable
  //Obtenemos el fondo del imageview que es donde cargaremos 
  //la animacion, IMPORTANTE:
  //No añadais imagen en el src del main.xml ya que taparía
  //el fondo y no nos dejará ver la animación
  mi_animacion = (AnimationDrawable) imageView.getBackground();   
  //Emezamos la animacion
  mi_animacion.start();
         return true;
         }
 //Si levanta el dedo del botón
 if (event.getAction() == MotionEvent.ACTION_UP){
  //Pararemos la animación
  mi_animacion.stop();
  //Mostamos la imagenn inicial para dar más realismo al stop()
  imageView.setBackgroundResource(R.drawable.u_1);
         return true;
  }
 return false;
 }
 });
Y con esto es todo! os adjunto un vídeo para ver el resultado final, espero que hayáis aprendido mucho y que comentéis vuestros resultados o dudas que surjan. Muchas gracias!

Espero vuestros comentarios y puntuaciónes!!!

33 comentarios:

  1. Muy bien explicado, espero tener un dia los conocimientos suficientes para desarrollar algo así ^^
    Seguro que con todos los tutoriales cogeré el nivel necesario.
    Gracias

    ResponderEliminar
  2. Para que la variable mi_animacion pueda accederse dentro del ontouch, me obliga a declararla como final, pero al hacer esto me dice:

    "The final local variable mi_animacion cannot be assigned, since it is defined in an enclosing type"

    te paso el cofigo a ver si le ves el problema.

    http://pastebin.com/VULfL2Cy

    gracias!

    ResponderEliminar
    Respuestas
    1. Buenos días, veamos, en tu código haces esto:

      final ImageView imageView = (ImageView) findViewById(R.id.iv_mario);
      final AnimationDrawable mi_animacion = new AnimationDrawable();

      es cierto que te obliga a poner final ya que después lo activas o desactivas dentro de un OnTouch. Para que esto no te pase y evitar problemas deja las anteriores dos líneas de esta manera:

      imageView = (ImageView) findViewById(R.id.iv_mario);
      mi_animacion = new AnimationDrawable();

      Y las declaras fuera del OnCreate, de esta manera:

      public class Main extends Activity {

      public ImageView imageView;
      public AnimationDrawable mi_animacion;

      @Override
      protected void onCreate(Bundle savedInstanceState) {

      Comentame los resultados y gracias por preguntar!

      Eliminar
  3. Buenas tardes!
    despues de testear lo que nos has comentado, hemos llegado al siguiente codio.

    http://pastebin.com/H6s1Cgt0

    Todo Correcto!

    veras que en el apartado de declaracion ontouch hemos cruzado los movimientos laterales. Error nuestro jejeje.

    muchas gracias por tus tutos, son geniales!

    ResponderEliminar
  4. Felicidades muy buenos tutoriales, recien conosco la pagina

    ResponderEliminar
  5. ola q tal, estuve intentando correr el programa y no ejecutaba, al final se paraba la aplicacion, y vi q el error era q no se podía convertir la imagen a "drawable", puse las imagenes en la carpeta de res todo, pero no puede convertirlas, q podría hacer?

    ResponderEliminar
    Respuestas
    1. Las imágenes deben estar en res/drawable y si son formatos stardar como jpg o png lo coje sin ningún problema. Has probado el código tal cual esta en el tutorial? Me parece raro que te de ese error. Mira aver si me puedes copiar tu código. Gracias!

      Eliminar
    2. otro factor es que aveces eclipse se pone de reyna de preferencia si las imagenes levan _ cambiales el nombre

      Eliminar
    3. También da problemas con los números

      Eliminar
  6. disculpa una pregunta.. que atributo o q componente se tendría q agregar para que el textview se mueva en la pantalla

    ResponderEliminar
    Respuestas
    1. Crearé próximamente un tutorial de como crear animaciones de los objetos en pantalla, ves echando un ojo a la página, lo publicaré esta semana.
      Muchas gracias a todos! ;)

      Eliminar
    2. pues gracias a ti por encaminarnos en desarrollo movil... estare alerta!

      Eliminar
    3. Ya está disponible el nuevo tutorial sobre animación!
      http://www.tutorialeshtml5.com/2013/06/tutorial-android-crear-animaciones-con.html

      Gracias!

      Eliminar
  7. Hola la verdad que excelente los tutoriales , felicitaciones !!! Gracias por compartir la información.
    solamente quería hacerte una consulta desarrolle la aplicación sin ningún problema , solo que a la hora de ejecutarla en un dispositivo me dice el msj "la aplicación se ha detenido de forma inesperada. vuelve a intentarlo" , que puede ser eso ¿?¿?¿

    saludos y muchas gracias .

    ResponderEliminar
    Respuestas
    1. Ese mensaje de error es el común no te voy a poder ayudar mucho.. tendría que poner que error te da en el LogCat.

      Ese error puedo ser porque te falte la linea que une el boton de mover con el del XML y pete por no aver tenido espacio en memoria. Revisate este tutorial y nos cuentas http://www.tutorialeshtml5.com/2012/02/tutorial-basico-android-agregar-boton.html

      Igualmente pon aqui el LogCat de cuando da error ^^ Gracias!


      +1? ^.^

      Eliminar
  8. una pregunta me puedes enviar el proyecto a mi correo ???

    ResponderEliminar
    Respuestas
    1. Intentaré publicar aquí el proyecto esta semana.
      Agradecería un +1 :D muchas gracias!!

      Eliminar
  9. Hola, excelente tutorial!

    Queria saber si puedes aconsejarme... Estaba trabajando con una esfera en movimiento dentro de la pantalla, pero cada vez se presione la imagen debe cambiar a una imagen que ya me han entregado, estoy trabajando con Bitmap, cada vez que se presione cambia una variable local "estado" que permite cambiar el estado del objeto que tiene un bitmap... he logrado hacer el cambio de la esfera, pero esto pasa cada vez que realizo un evento onTouch en cualquier parte de la pantalla, es posible agregar eventos onTouch para un Bitmap? o debería cambiar el proyecto completamente a ImageView?

    ResponderEliminar
    Respuestas
    1. Disculpa el retraso, yo lo que haría es meter la imagen en el imageView y añadir hay el listener.
      Muchas gracias!

      Recordar el +1 ^^

      Eliminar
  10. Excelente tu pagina, soy nuevo en el tema y he intentado realizar el programa, hago todo el codigo y no me muestra error alguno pero cuando lo ejecuto dice "la aplicación se ha detenido de forma inesperada. vuelve a intentarlo", tengo una duda las imagenes deben ir en el mismo lado que van los archivos XML?

    Saludos.

    ResponderEliminar
    Respuestas
    1. No, las imágenes van en la carpeta res/drawables

      utiliza el debug para ver en eclipse que error te lanza.

      Eliminar
    2. Victor por favor en la carpeta res/drawables tengo las imagenes y me podria indicar en dodne van los archivos XLM, actualmente los tengo en la misma carpeta en la que estan las imagenes.

      Saludos.

      Eliminar
    3. Los archivos XML deben ir en res/layouts

      Eliminar
  11. Hola segui tu tutorial y tuve exito, me corre bien en el emulador no me da problemas... pero cuando lo exporto al cel en .apk, no hace las animaciones, me hara falta agregar algo al manifest.xml ¿? o cual crees que sea mi problema ¿?

    ResponderEliminar
    Respuestas
    1. Alan, por favor me podrias enviar el programa?

      Saludos.

      Eliminar
  12. jorge muchas gracias!! ya pude solucionarlo :D

    ResponderEliminar
    Respuestas
    1. tengo problemas con mi programa, no muestra error alguno pero cuando lo ejecuto se cierra inesperadamente, por favor me podrias pasar tu programa para mirar que me esta quedando mal.

      Eliminar
    2. aaa ok jorge, perdon... no lo habia visto, claro que si a donde te mando mi codigo ¿? o te lo pego todo aqui ¿?

      Eliminar
    3. enviamelo al correo por favor es jlopez1029@hot..., muchas gracias.

      Eliminar
  13. Buenas!! Podrías volver a subir las imagenes del sprite?, el link ya no funciona. Gracias.
    PDTA: muy bueno el tutorial ;)

    ResponderEliminar
  14. Podrías volver a subir las imagenes del sprite o el proyecto? buen tutorial era lo que buscaba gracias!

    ResponderEliminar
  15. hola me gustaria saber como hacer una animacion con una sola imagen asi como lo mencionas al principio?

    ResponderEliminar