Nuevos avatares

This commit is contained in:
2026-05-09 21:18:25 +02:00
parent 92361080f8
commit c77c6bb128
137 changed files with 459 additions and 0 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 105 KiB

View File

@@ -0,0 +1,411 @@
# Diseño UX — Recompensas animadas y revancha con mismos participantes
## Objetivo
Mejorar el final de partida para que no sea solo una pantalla informativa, sino un momento de recompensa visual, progreso y retención. La referencia emocional es el final de partida de juegos competitivos: primero se entiende el resultado, después se ve el progreso, luego se celebran desbloqueos y finalmente se ofrece una acción clara para jugar otra vez.
Este documento sirve como guía para Codex/IA al implementar UI, animaciones y flujo de revancha.
---
## Parte 1 — Pantalla de recompensas animadas
### Principios
- El jugador debe sentir que “ha ganado algo” incluso si perdió la partida.
- La progresión debe mostrarse de forma secuencial, no instantánea.
- Las recompensas nuevas deben tener más peso visual que las ya obtenidas.
- Cada icono debe poder explicarse con texto: nombre, descripción y motivo.
- La pantalla debe mantener la identidad de Farolero: noche, farol, fuego, misterio social, humor.
### Secuencia recomendada
La pantalla final debe dividirse en fases animadas:
1. **Resultado**
- Aparece “Victoria” o “Derrota” / “Ganan jugadores” o “Ganan impostores”.
- Entrada con fade + scale.
- Fondo con glow cálido.
2. **Resumen de partida**
- Palabra secreta.
- Impostor/es.
- Pequeños datos: partidas jugadas +1, victoria/derrota, rol si se conoce.
3. **Fuego/asiduidad**
- Barra circular o lineal empieza en el fuego anterior.
- Avanza progresivamente hasta el fuego nuevo.
- Contador animado: `+6 fuego`.
- Si el fuego sube de tramo, mostrar microcelebración.
4. **Medallas obtenidas**
- Las medallas nuevas entran una a una.
- Cada una aparece con:
- zoom in,
- brillo radial,
- partículas,
- pequeña vibración/sonido si están activados.
- Debajo: nombre y descripción corta.
5. **Medallas actuales**
- Mostrar una fila/grid de medallas principales.
- Al tocar cualquier medalla, abrir detalle.
6. **Acciones finales**
- Botón principal: `Volver a jugar`.
- Botón secundario: `Menú principal`.
- Botón opcional: `Ver historial`.
---
## Componentes sugeridos
### `PantallaRecompensaPartida`
Pantalla o widget reutilizable para local y multidispositivo.
Entradas sugeridas:
```dart
class DatosRecompensaPartida {
final bool victoriaPerfilLocal;
final bool ganoBandoJugadores;
final String palabraSecreta;
final List<String> impostores;
final ProgresoGamificacionUsuario progreso;
final VoidCallback onVolverAJugar;
final VoidCallback onMenuPrincipal;
}
```
Debe evitar duplicar la UI actual en `PantallaFinPartida`, `PantallaFinPartidaOnline` y `PantallaGestorHost`. Idealmente esas pantallas delegan en un mismo componente visual.
### `BarraFuegoAnimada`
Muestra el progreso de fuego desde `antes.fuego` hasta `despues.fuego`.
Características:
- Duración: 900-1400 ms.
- Curva: `Curves.easeOutCubic`.
- Debe mostrar número final y diferencia.
- Si baja, usar color menos agresivo y texto honesto: `-5 fuego por inactividad`.
- Si sube, usar glow naranja/dorado.
### `MedallaDesbloqueadaCard`
Muestra una nueva medalla con imagen grande.
Contenido:
- Imagen 96-128px.
- Nombre.
- Descripción.
- Texto de recompensa: `Nueva medalla desbloqueada`.
Animación:
- scale 0.7 -> 1.08 -> 1.0
- fade in
- glow radial detrás
- confetti puntual si es nueva.
### `DetalleMedallaSheet`
Bottom sheet/modal al pulsar una medalla.
Contenido:
- Imagen grande.
- Nombre.
- Descripción.
- Estado: `Desbloqueada` o `Pendiente` si en futuro se muestra catálogo completo.
- Condición: ejemplo `Juega 10 partidas`.
Esto soluciona el problema de que el usuario no entienda qué significa cada icono.
---
## Librerías recomendadas
### `flutter_animate`
Uso principal para animaciones declarativas:
- entrada de tarjetas,
- fade,
- scale,
- shimmer,
- blur,
- slide,
- efectos secuenciales.
Recomendación: usarla para casi toda la pantalla.
### `confetti`
Uso puntual:
- nueva medalla,
- subida de tramo de fuego,
- victoria importante.
Debe ser controlado, no constante. Si todo explota todo el tiempo, se vuelve barato.
### `lottie`
Uso recomendado si se añaden assets animados:
- fuego de fondo,
- destello de recompensa,
- partículas premium,
- medalla desbloqueada.
### `rive`
Solo si queremos algo más ambicioso:
- fuego interactivo con niveles,
- barra circular con estado `low / medium / high / max`,
- medallas animadas con state machine.
Para primera implementación: `flutter_animate + confetti` es suficiente. `lottie` se puede añadir después si tenemos buenos assets.
---
## Assets visuales recomendados
Crear en:
```text
assets/rewards/
```
Archivos sugeridos:
```text
reward_header_glow.png
fire_progress_burst.png
medal_unlock_burst.png
confetti_spark.png
victory_glow.png
defeat_shadow_glow.png
```
Ver prompts en `docs/assets_medallas_premium.md`.
---
## Sonido y vibración
La app ya tiene configuración de volumen de efectos y vibración. Esta pantalla es el primer lugar ideal para que esa configuración tenga sentido real.
Eventos sugeridos:
- Subida de fuego: sonido suave de chispa.
- Nueva medalla: sonido corto de recompensa.
- Confetti: vibración ligera.
- Victoria: vibración media opcional.
Importante: respetar siempre la configuración del usuario.
---
## Parte 2 — Acción “Volver a jugar”
### Objetivo
Permitir iniciar una nueva partida con los mismos participantes, pero pasando por un momento de gestión antes de arrancar para poder añadir, eliminar o cambiar usuarios.
Esto es importante porque una revancha directa puede ser cómoda, pero también puede arrastrar errores: alguien se va, entra otro jugador, se quiere cambiar nombre, etc.
### Flujo local recomendado
1. Termina la partida.
2. Se guarda automáticamente en historial.
3. Se registran estadísticas y logros.
4. Se muestra pantalla de recompensas.
5. Usuario pulsa `Volver a jugar`.
6. La app abre una pantalla de gestión de jugadores prellenada con los participantes anteriores.
7. El usuario puede:
- mantener todos,
- añadir jugadores,
- eliminar jugadores,
- cambiar configuración de partida si procede.
8. Al confirmar, se crea una nueva partida limpia con esos jugadores.
No debe reutilizar el objeto de partida anterior directamente. Debe crear una partida nueva usando una “plantilla” de jugadores/configuración.
### Flujo multidispositivo recomendado
1. Termina la partida online.
2. Host guarda historial.
3. Cada dispositivo registra sus estadísticas locales.
4. Se muestra recompensa en cada dispositivo.
5. Host pulsa `Volver a jugar`.
6. La sala vuelve a fase `lobby` o a una fase nueva `postPartida`/`preparandoRevancha`.
7. Se mantiene el pool de usuarios anterior.
8. Se limpian estados de partida:
- votos,
- palabras vistas,
- notas si se decide limpiar por partida,
- eliminados,
- roles,
- palabra secreta.
9. En lobby se puede:
- añadir usuarios,
- eliminar usuarios,
- seleccionar/liberar usuarios,
- esperar clientes reconectados si alguno cayó.
10. Host inicia nueva partida cuando haya al menos 3 usuarios seleccionados.
### Decisión importante
Las notas deberían ser por partida, no globales. Para revancha, lo recomendable es empezar con notas limpias. Si se quiere, añadir en futuro opción `conservar notas de la partida anterior`, pero NO por defecto.
---
## Cambios técnicos esperados
### Modelo/estado
Crear una forma de representar “plantilla de revancha”:
```dart
class PlantillaRevancha {
final List<String> nombresJugadores;
final ConfiguracionPartida configuracion;
}
```
O reutilizar modelos existentes si ya hay estructura equivalente.
### Local
Modificar el flujo actual de revancha para que no salte directamente a ver palabras si antes hay que gestionar jugadores.
Actualmente puede existir un `estado.revancha()` que reinicia demasiado rápido. Si es así, debe cambiar hacia:
```text
fin partida -> recompensas -> gestionar jugadores prellenados -> iniciar partida
```
### Online
Añadir transición controlada:
```text
finPartida -> lobby/postPartida -> iniciarPartida
```
El host debe ser autoridad. Los clientes no deberían poder iniciar revancha por su cuenta, pero sí pueden ver estado de “esperando al host”.
### Historial
La partida que termina debe guardarse ANTES de iniciar revancha. Esto ya es una regla crítica.
Al pulsar `Volver a jugar`:
- no debe duplicar guardado histórico,
- no debe duplicar estadísticas,
- no debe duplicar logros.
Usar banderas tipo `_guardada` o mover la lógica a un servicio idempotente.
---
## UX detallada del botón “Volver a jugar”
### Local
Texto botón:
```text
Volver a jugar
```
Subtexto opcional:
```text
Revisá jugadores antes de empezar otra ronda
```
### Online host
Texto botón:
```text
Preparar revancha
```
Subtexto:
```text
Volverás al lobby con los mismos usuarios
```
### Online cliente
Si no es host:
```text
Esperando al host para preparar revancha
```
Si el host activa revancha, el cliente vuelve automáticamente al lobby.
---
## Criterios de aceptación
### Recompensas
- El fuego no cambia de golpe: se anima progresivamente.
- Las nuevas medallas se destacan claramente.
- Cada medalla tiene explicación visible al tocarla.
- La pantalla no depende solo de iconos.
- Existe fallback si no hay nuevas medallas.
- La UI se mantiene útil aunque el usuario pierda.
### Revancha local
- La partida terminada queda guardada en historial antes de jugar otra.
- Los logros/estadísticas se registran una sola vez.
- Se pueden editar participantes antes de reiniciar.
- La nueva partida no arrastra eliminados, votos ni roles anteriores.
### Revancha online
- El host controla la revancha.
- Los clientes vuelven a lobby o esperan al host.
- El pool de usuarios se conserva.
- Se pueden añadir/eliminar/seleccionar usuarios antes de empezar.
- No se duplican historial ni estadísticas.
- Si un cliente se desconecta, el lobby muestra su estado correctamente.
---
## Implementación recomendada por fases
### Fase 1
- Extraer widget visual reutilizable de recompensas.
- Añadir modal de detalle de medalla.
- Animar fuego con `AnimationController` o `TweenAnimationBuilder`.
- Añadir `confetti` al desbloquear medalla.
### Fase 2
- Añadir `flutter_animate` para secuencias más ricas.
- Añadir assets en `assets/rewards/`.
- Reemplazar tarjetas estáticas de fin de partida por flujo secuencial.
### Fase 3
- Revancha local con gestión de jugadores prellenada.
- Revancha online host -> lobby.
### Fase 4
- Lottie/Rive si hay assets premium.
- Sonidos y vibración conectados a configuración.

View File

@@ -74,6 +74,54 @@ class ServicioPerfilUsuario extends ChangeNotifier {
'assets/avatars/capybara_10.png',
'assets/avatars/capybara_11.png',
'assets/avatars/capybara_12.png',
'assets/avatars/avatar_31.png',
'assets/avatars/avatar_32.png',
'assets/avatars/avatar_33.png',
'assets/avatars/avatar_34.png',
'assets/avatars/avatar_35.png',
'assets/avatars/avatar_36.png',
'assets/avatars/avatar_37.png',
'assets/avatars/avatar_38.png',
'assets/avatars/avatar_39.png',
'assets/avatars/avatar_40.png',
'assets/avatars/avatar_41.png',
'assets/avatars/avatar_42.png',
'assets/avatars/avatar_43.png',
'assets/avatars/avatar_44.png',
'assets/avatars/avatar_45.png',
'assets/avatars/avatar_46.png',
'assets/avatars/avatar_47.png',
'assets/avatars/avatar_48.png',
'assets/avatars/avatar_49.png',
'assets/avatars/avatar_50.png',
'assets/avatars/avatar_51.png',
'assets/avatars/avatar_52.png',
'assets/avatars/avatar_53.png',
'assets/avatars/avatar_54.png',
'assets/avatars/avatar_55.png',
'assets/avatars/avatar_56.png',
'assets/avatars/avatar_57.png',
'assets/avatars/avatar_58.png',
'assets/avatars/avatar_59.png',
'assets/avatars/avatar_60.png',
'assets/avatars/avatar_61.png',
'assets/avatars/avatar_62.png',
'assets/avatars/avatar_63.png',
'assets/avatars/avatar_64.png',
'assets/avatars/avatar_65.png',
'assets/avatars/avatar_66.png',
'assets/avatars/avatar_67.png',
'assets/avatars/avatar_68.png',
'assets/avatars/avatar_69.png',
'assets/avatars/avatar_70.png',
'assets/avatars/avatar_71.png',
'assets/avatars/avatar_72.png',
'assets/avatars/avatar_73.png',
'assets/avatars/avatar_74.png',
'assets/avatars/avatar_75.png',
'assets/avatars/avatar_76.png',
'assets/avatars/avatar_77.png',
'assets/avatars/avatar_78.png',
];
PerfilUsuario _perfil = const PerfilUsuario(

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Some files were not shown because too many files have changed in this diff Show More