Codename One Animation Trouble (también en Solitaire demo)?

¿Qué pasó con las animaciones de Codename One? Utilizo muchos de ellos y, a partir de diciembre, mi aplicación ya no funciona. Cuando dejé cosas en junio todo estaba bien (y fue así por más de un año).

Mi aplicación es un juego de dibujos (damas) y está disponible en las tiendas de aplicaciones desde 2013. Después de ver la demo de CN1 Poker, reescribí completamente mi GUI, ya que quería añadir ese tipo de animaciones a mi aplicación. Lo que pasa ahora es que de repente obtengo un índice de excepciones vinculadas. Entendí esto a la siguiente situación:

cont.addComponent(comp); ... ... cont.getComponent(0); <-- index out of bound exception: 0 out of 0 

Ya he utilizado newVM = true en junio, que ahora es el valor predeterminado, creo. Traté de arreglar las cosas agregando un

 cont.animateLayoutAndWait(100); 

Después de la llamada addComponent. Esto fijó el índice fuera de las excepciones vinculadas, pero ahora la aplicación sólo se bloquea en momentos aleatorios después de trabajar bien durante un corto período de tiempo. Lo intenté pero no he podido encontrar la fuente del problema. Algo ha cambiado en CN1 para que mi código ya no funcione. (Véase también el foro de edad, la búsqueda de "borradores", donde he publicado una lista completa de mi diseño básico.)

He estudiado la nueva demostración de Solitario, que tiene la mayoría de la funcionalidad de animación que necesito. Y las versiones de la tienda de aplicaciones de Solitario funcionan bien en todos mis dispositivos iOS / Android. Un error menor es que es posible arrastrar un grupo de tarjetas, algunas de las cuales están hacia abajo, las cuales están orientadas hacia arriba durante la operación de arrastrar. También es bastante difícil de recoger exactamente la cantidad correcta de tarjetas. Arrastrar un grupo de tarjetas también deja un rastro blanco en la pantalla, que no se ve muy bien. Esto también ocurre en el Simulador.

Como experimento, rediseñé mi diseño de GUI para que se parezca exactamente al código del Solitario: dos capas de botones, la única diferencia es que utilizo GridLayout (10,10) donde Solitaire usa SolitaireLayout (). Esto funciona, excepto por una cosa: si un inspector se mueve hacia abajo el tablero se mueve correctamente sobre otros damas, pero si un inspector se mueve hacia arriba el tablero se mueve debajo de las otras damas.

Mi código se ve así:

 Button pc = (Button)piecesCnt.getComponentAt(a1); Button to = (Button)piecesCnt.getComponentAt(a2); piecesCnt.removeComponent(pc); piecesCnt.addComponent(a1, createPieceButton(Piece.EMPTY_PIECE, true)); piecesCnt.removeComponent(to); piecesCnt.addComponent(a2, pc); piecesCnt.animateLayoutAndWait(1000); 

Así que parece que los botones siempre están dibujados en su orden GridLayout, mientras esperaba que el botón animado (que se mueve) se dibujaría último / en la parte superior, al igual que las cartas en movimiento en Solitario.

¿Es esto una diferencia entre manejar la animación en SolitaireLayout vs. GridLayout? Si es así, ¿se puede cambiar esto en la lógica de animación? De lo contrario tengo que añadir una capa de animación extra y un montón de gastos generales.

Y en Android, la animación (movimiento) no funciona correctamente. Así que decidí también auto-construir y probar la demo de Solitario en mis dispositivos con la versión actual de CN1 (plugin 3.2.6, libs 2016-01-11). He cambiado las animaciones para ser 10 veces más lento, para ver mejor lo que está sucediendo. En el simulador, el diseño y las animaciones funcionan bien, pero en mis dispositivos iOS y Android hay muchos problemas.

Simulador (Windows 7, NetBeans 8.0.2): – He reemplazado los iconos de fuente por texto ya que faltan. – ¿Pero cómo acceder al menú de hamburguesas? No veo los 3 puntos y ni siquiera hay espacio para ello. – A veces es posible arrastrar un grupo de cartas con algunas tarjetas downfacing tomadas; Mientras son arrastrados son temporalmente volteados hacia arriba. – La reproducción automática no siempre parece funcionar. (No todos los movimientos se juegan.)

En iOS 9.2 (iPad 4), iOS 8.4 (iPhone 4): – [?] Se muestra en las casillas de verificación de menú de hamburguesas. – Después de la puesta en marcha, la tarjeta de fondo del cuadro retrocede a la parte inferior del contenedor / pantalla. – A veces, en la animación deal-from-deck, las cartas en el cuadro más a la derecha están mirando hacia arriba temporalmente, y las cartas que ya están mirando hacia arriba están volteadas hacia abajo. Sin embargo, el estado final de transacción es correcto. – Deshacer / Rehacer: a veces resulta en una tarjeta de cara arriba en la cubierta 0 y una cara hacia abajo en la cubierta 1. – Rehacer a veces "salta" a la nueva disposición en lugar de animar. Sólo en el iPhone: – Una secuencia de movimientos de autoplay dejó un estado inconsistente de la fundación: las cartas de la parte superior del corazón-J, club-10, club-K, diamante-Q; Es decir, 2 tarjetas de club en pilas de cimientos diferentes.

En Android 5.1.1 (Nexus 7) hay más problemas. – La animación del reparto de la cubierta no es una vista bonita. Las tarjetas se insertan (se deslizan hacia) en la parte inferior de las pilas de cuadros, por lo que se deslizan bajo las otras tarjetas. Las cartas en movimiento deben estar hacia abajo, pero normalmente están mirando hacia arriba, siempre mostrando la primera carta repartida en el cuadro 1. Las cartas en el cuadro derecho están temporalmente hacia arriba. Finalmente, las cartas que ya están mirando hacia arriba están volteadas hacia abajo y hacia atrás. Sin embargo, el estado final de transacción es correcto. – La reproducción automática también no es correcta cuando hay varios movimientos en una fila. Durante las animaciones, varias cartas de fundación hacia arriba cambian temporalmente el valor de la tarjeta (frontal). También las tarjetas móviles se deslizan debajo de la tarjeta de la fundación (ya veces encima, pero ésta es la excepción). – Después de terminar el juego, la pantalla bien hecha está dañada ya que el texto parece estar desplegado pero no sobrepuesto pero debajo de las tarjetas (en un gran espacio en blanco), que sólo son parcialmente visibles en una pequeña porción en la parte superior de la pantalla. – El inicio de un nuevo juego a menudo falla porque el reparto desde la cubierta no se inicia; La pantalla muestra una baraja y cuatro reyes sobre los cimientos con el cuadro vacío. Al golpear ligeramente la cubierta, una tarjeta se reparte y la secuencia bien hecha se demuestra. A veces, al repetir esto, se logra iniciar con éxito un nuevo juego.

Todo esto ha tomado mucho tiempo y todavía no tengo mi aplicación de trabajo de nuevo, que es muy frustrante. Teniendo tantos problemas con este tema, incluso con una aplicación demo descargada, la construcción de este tipo de aplicación con Codename Uno se siente como la construcción de arena movediza. ¡Por favor ayuda!

Usted probablemente debería haber preguntado una vez que se encontró con problemas en lugar de trabajar tan duro en el post. Sí, hicimos un gran cambio de compatibilidad algo como parte de una corrección de errores para los problemas de animación de larga data (donde las animaciones en paralelo podrían chocar).

Esto introdujo algunas colisiones pero redujo las inconsistencias entre los dispositivos / simulador que siempre es una buena cosa.

Lo anunciamos aquí: https://www.codenameone.com/blog/new-animation-manager.html

En realidad, es MUCH más sencillo crear una animación portátil ahora, ya que todo se sincronizará para evitar colisiones de animación, por ejemplo, si se hace Component.removeComponent() mientras una animación está en progreso, se agregará implícitamente a la cola de animación y se realizará una vez completada la animación En lugar de inmediatamente.

Para posponer su próxima acción hasta después de las animaciones que tenemos:

 form.getAnimationManager().flushAnimation(() -> doThisAfterAnimation()); 

Mucho más simple y ningún caso especial cerraduras globales.

Su un poco difícil de "puerto" de código directamente a la nueva aproximación, pero parece que su lógica de animación se basa en la animación de tomar 1000ms y que terminó completamente cuando el método devuelve que no siempre sea el caso (como agregar o quitar llamadas o Otra lógica podría interponerse en el camino).

En el pasado la única manera de garantizar una animación era completa era distanciarlos aparte, pero ahora sólo puede utilizar flushAnimation para asegurarse de que todas las animaciones se han completado. Tenga en cuenta que algunas cosas que no son explícitamente una animación ahora pueden convertirse en una animación por accidente, por ejemplo, un componente add / remove se convertirá en una animación si hay una animación en progreso cuando las llames …

Siento haber perdido la entrada del blog en el nuevo director de animación del 16 de diciembre. La demostración del Solitario data del 8 de octubre y he comprobado la Guía para desarrolladores del 31 de diciembre, así que pensé que estaba al día. Sin embargo, no está claro para mí cómo usar el nuevo gestor de animación. La nueva Guía para desarrolladores de Januari 11 no dice nada sobre el tema y su respuesta / blog no son muy elaborados.

También ayudaría mucho si la demostración de Solitario se actualizara para trabajar con el nuevo gestor de animación.

Ahora mis preguntas son:

1) ¿Cómo puedo volver a escribir el siguiente código para usar el nuevo gestor de animación? Este es un escenario realista porque tengo animaciones con múltiples pasos que deben realizarse consecutivamente.

 // simplified code (background layer omitted) public void start() { if(current != null){ current.show(); return; } Form form = new Form("Draughts 2"); Container piecesCnt = new Container(new GridLayout(10, 10)); for (int i=0; i<100; i++) { piecesCnt.addComponent(createPieceButton(piece(i), true)); } form.addComponent(piecesCnt); form.show(); new UITimer(() -> { testAnimation(piecesCnt, 0,9 , 9,0); // moves UNDER other pieces testAnimation(piecesCnt, 9,0 , 0,9); // " OVER " " testAnimation(piecesCnt, 1,0 , 9,8); // " OVER " " testAnimation(piecesCnt, 9,8 , 1,0); // " UNDER " " }).schedule(1500, false, form); } private void testAnimation(Container piecesCnt, int x1,int y1, int x2,int y2) { int a1 = 10 * y1 + x1; int a2 = 10 * y2 + x2; Button pc = (Button)piecesCnt.getComponentAt(a1); Button to = (Button)piecesCnt.getComponentAt(a2); piecesCnt.removeComponent(pc); piecesCnt.addComponent(a1, createPieceButton(Piece.EMPTY_PIECE, true)); piecesCnt.removeComponent(to); piecesCnt.addComponent(a2, pc); piecesCnt.animateLayoutAndWait(1000); } 

2) ¿Reescritura esto también resolver el problema de una pieza (verificador) que se mueven en lugar de sobre otras piezas?

3) ¿Cómo hago una pausa entre dos llamadas de testAnimation? (No por dormir, obviamente.)


Actualización 2016-01-14 (vea también la sección de comentarios):

He intentado dos cosas con flushAnimations:

1) Utilice una función como esta:

 private void flushAnimations(Form f) { f.getAnimationManager().flushAnimation(() -> {}); } 

Y lo llaman entre sucesivas animaciones. Esto no funciona.

2) FlushAnimations anidados:

 testAnimation(piecesCnt, 0,9 , 9,0); f.getAnimationManager().flushAnimation(() -> { testAnimation(piecesCnt, 9,0 , 0,9); f.getAnimationManager().flushAnimation(() -> { testAnimation(piecesCnt, 1,0 , 9,8); f.getAnimationManager().flushAnimation(() -> { testAnimation(piecesCnt, 9,8 , 1,0); }); }); }); 

Esto parece funcionar en iOS pero no en mi dispositivo Android: generalmente después de la segunda animación, la pantalla parpadea y salta al siguiente estado en lugar de animar. Aparte de eso, no es una buena solución.

Entonces intenté la solución de UITimer:

 blockUI(piecesCnt); new UITimer(() -> { testAnimation(piecesCnt, 0,9 , 9,0); }).schedule(2000, false, f); new UITimer(() -> { testAnimation(piecesCnt, 9,0 , 0,9); }).schedule(3500, false, f); new UITimer(() -> { testAnimation(piecesCnt, 1,0 , 9,8); }).schedule(5000, false, f); new UITimer(() -> { testAnimation(piecesCnt, 9,8 , 1,0); }).schedule(6500, false, f); new UITimer(() -> { unblockUI(piecesCnt); }).schedule(8000, false, f); private boolean blocked = false; private void blockUI(Container piecesCnt) { blocked = true; int n = piecesCnt.getComponentCount(); for (int i=0; i<n; i++) { piecesCnt.getComponentAt(i).setDraggable(false); } } private void unblockUI(Container piecesCnt) { ... } 

Esto funciona, pero tampoco es una solución muy deseable. Tengo una función 'autoplay' que reproduce un juego completo consistente en> 100 movimientos, cada movimiento consistente en 1 o más pasos de animación. El usuario puede interrumpir este proceso pulsando un botón de parada.

Me gustaría ver cómo las demostraciones de Poker y Solitario (Autoplay!) Deberían codificarse con la nueva manipulación de animación.

Por favor, tómese un minuto para seguir este enlace para ver qué tipo de funcionalidad estoy hablando: http://toernooibase.kndb.nl/opvraag/applet.php?taal=1&kl=46&Id=4579&r=10&jr=16&wed=845502 . Simplemente presione el botón de reproducción automática ('>') debajo de la tarjeta. (Mi aplicación también puede jugar el juego, y puedes configurarlo para que diga 1 minuto por movimiento, durante el cual la GUI está bloqueada).

Vi que la Guía para Desarrolladores fue actualizada el 13 de enero y ahora tiene un capítulo / apéndice sobre Programación de Juegos Casual. Esto es bueno, aunque la versión de CN1Poker que aún no funciona correctamente en un dispositivo Android: la animación de tarjetas de negociación muestra las cartas en su mayoría saltando ya veces deslizándose a sus posiciones. (Funciona bien en el Simulador y en dispositivos iOS.)

¿Cómo se puede decir que es 'mucho más sencillo crear una animación portátil ahora'? Creo que en mi caso en realidad sólo se hizo mucho más difícil. Necesito una alternativa para el viejo enfoque que también se usa en las demostraciones de póquer y solitario: use animateLayoutAndWait y no tenga ninguna acción add / remove durante una animación (también asegurada por la lógica del programa).

Como suscriptor básico (desde hace 3 años) tengo que usar la última versión de CN1, pero con la versión actual de CN1 ya no sé cómo codificar esto. Creo que este es un tema bastante fundamental ya que todos los juegos usan esta funcionalidad.

  • Reemplazar espacio a guión
  • Android KeyStore System - Guardar un KeyPair?
  • API de datos de Youtube: Obtenga acceso al flujo multimedia ya la reproducción (JAVA)
  • Convertir objeto a JSON en Android
  • Reacondicionamiento .jar-s en Android .aar library
  • ¿Cómo puedo comprobar si una aplicación se ejecuta en Android?
  • Permiso de Android.INTERACT_ACROSS_USERS denegación
  • Cambiar el tamaño de un mapa de bits
  • JAVA_HOME se establece en un directorio no válido mientras se ejecuta ./gradlew en OSX
  • Android no puede obtener matriz de bytes de la intención
  • El audio no está claro durante la transmisión entre una clase de Java y la actividad de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.