Publicat per

PR2 – SKIP BALLS

Publicat per

PR2 – SKIP BALLS

Vídeo de presentación del proyectoEn este vídeo se muestra el funcionamiento de la App. Ideación de la App y selección de la…
Vídeo de presentación del proyectoEn este vídeo se muestra el funcionamiento de la App. Ideación de la App y…

Vídeo de presentación del proyecto
En este vídeo se muestra el funcionamiento de la App.

Ideación de la App y selección de la API externa

Para continuar con la segunda práctica, como se pedía en el enunciado, debía integrar una API externa que aportara valor real a la aplicación desarrollada en la PR1. Desde el inicio tuve claro que no quería añadir la API como un simple “extra técnico”, sino que debía integrarse de forma coherente dentro del concepto del juego.

Mi primera idea, antes incluso de investigar APIs existentes, fue que los skins de los robots pudieran obtenerse externamente. Sin embargo, rápidamente descarté esta opción, ya que el diseño del juego requiere que los personajes tengan ruedas y no animaciones de caminar, lo que hacía muy compleja la integración de assets externos sin romper la coherencia visual y funcional del juego.

La segunda idea fue utilizar la API Astronomy Picture of the Day de la NASA para mostrar un fondo distinto cada día. Llegué incluso a obtener el token y hacer pruebas, pero finalmente descarté esta opción al darme cuenta de que trabajar con imágenes tan pesadas no era adecuado para un juego arcade sencillo, además de suponer una carga innecesaria de procesamiento en cada iteración del draw.

Finalmente opté por integrar JokeAPI, una API que ofrece chistes de forma ligera y rápida. Me pareció una opción especialmente adecuada para un MVP, ya que aporta personalidad y trasfondo a los personajes sin interferir en la jugabilidad. En un juego arcade tan simple, dotar de carácter a los robots suma valor a la experiencia del usuario. Además, esta idea deja abierta una clara evolución futura del proyecto, como la creación de un lore o guion más elaborado, o personajes con estilos de humor propios que se puedan desbloquear progresivamente.

Para reforzar esta idea, el usuario puede seleccionar desde el panel de ajustes la categoría de humor que desea, y será el robot el que le “cuente” el chiste, reforzando la sensación de personaje con identidad propia.

Consultas y pasos seguidos en la documentación de Capacitor

El primer uso de Capacitor en el proyecto fue Capacitor Motion, utilizado para leer la inclinación del dispositivo móvil y permitir el movimiento lateral del jugador. Esta funcionalidad se encapsuló en un módulo externo motion.js, que posteriormente se importaba en sketch.js. En concreto, se utilizó Motion.addListener('orientation',
callback)
, obteniendo el valor gamma para controlar el movimiento izquierda/derecha.

En una iteración posterior del proyecto fue necesario mantener la pantalla encendida mientras el usuario jugaba, ya que en partidas largas la pantalla se apagaba automáticamente. Para solucionar esto se utilizó Capacitor Keep Awake, llamando a KeepAwake.keepAwake() desde setup(). Para asegurar la persistencia de los datos a largo plazo se decidió utilizar Capacitor Preferences. A diferencia del almacenamiento temporal, Preferences garantiza que los datos no se pierdan entre sesiones. Este plugin se utilizó para guardar información como la categoría de chistes seleccionada, opciones de audio, personajes desbloqueados, nombre de usuario y ranking de puntuaciones. La lógica se centralizó en el módulo storage.js, utilizando Preferences.get() y Preferences.set().

Durante el desarrollo surgió un problema con el audio: la música continuaba sonando aunque el usuario cambiara de aplicación o apagara la pantalla. Para gestionar correctamente estos estados se utilizó Capacitor App, empleando App.addListener('appStateChange',
callback)
para pausar música y lógica del juego cuando la app pasaba a segundo plano.

Para mejorar el feedback durante la partida se integró Capacitor Haptics. Se creó un módulo específico haptics.js, desde el que se utilizó Haptics.impact() para acciones suaves como recoger monedas y Haptics.vibrate() con duración para el Game Over. En este punto fue importante adaptar la implementación a las limitaciones del dispositivo utilizado.

Finalmente, la integración de la API externa se realizó mediante fetch, gestionando todas las llamadas de forma asíncrona con async/await.

El flujo de desarrollo fue el habitual con Capacitor:

  • En ordenador: npm run dev
  • En dispositivo real (Xiaomi Redmi Note 12): npm run
    build
    , npx cap sync android, npx cap open
    android

Pruebas con funcionalidades nativas del dispositivo

Para ajustar el control por inclinación fue necesario realizar múltiples pruebas, afinando la velocidad del movimiento del jugador hasta encontrar un equilibrio entre sensibilidad y control. Se limitaron los rangos de inclinación para evitar comportamientos erráticos.

En el caso de Haptics, el dispositivo Xiaomi utilizado no diferenciaba claramente entre los estilos light, medium y heavy. Por este motivo se optó por combinar Haptics.impact() para acciones leves y Haptics.vibrate() con duración para eventos importantes como la muerte del jugador, ofreciendo así un feedback más claro.

Integración de la API: dinamismo y control de errores

Cuando el jugador pierde la partida al colisionar con una bomba, el juego realiza una petición a la API de forma dinámica. Esta llamada depende directamente de la configuración del usuario, ya que la categoría de chistes seleccionada se inyecta como parámetro en la URL de la petición.

Dado que la conexión a internet puede fallar o no estar disponible, se implementó un sistema de fallback. Si la petición a la API falla o tarda demasiado, el juego utiliza una base de datos interna de chistes almacenados localmente, garantizando que la experiencia no se rompa.

Aunque la API permite seleccionar idioma, la cantidad de chistes disponibles en castellano era muy limitada, por lo que se decidió mantener los chistes en inglés, manteniendo el resto de la interfaz del juego en castellano.

Decisiones y aprendizajes

Inicialmente la idea era mostrar los chistes durante la partida cada vez que el jugador recogía una moneda. Sin embargo, tras probarlo, se comprobó que esta decisión rompía el ritmo del juego y perjudicaba la experiencia de usuario. Finalmente se optó por mostrar los chistes únicamente en la pantalla de Game Over, momento en el que el jugador puede leerlos con calma.

Fue necesario implementar un sistema claro de estados del juego: pantalla de inicio, juego activo, Game Over y ajustes. Esto permitió que el proyecto funcionara como un MVP estable y comprensible.

Durante el desarrollo también fue clave aprender a depurar directamente en Android mediante Logcat, ya que muchos errores no eran visibles desde las herramientas de desarrollo del navegador.

Problemas, soluciones y conclusiones

Uno de los problemas más complejos fue gestionar correctamente el audio y la persistencia de datos asíncronos. Al tener el código distribuido en varios módulos y trabajar de forma intermitente en el tiempo, fue necesario apoyarse en flags, pruebas controladas y herramientas de IA como Gemini y Copilot para identificar rápidamente los errores.

Como conclusión, este proyecto ha servido para consolidar el flujo completo de desarrollo de una app híbrida con Capacitor, desde la ideación hasta la distribución, y para entender la importancia de diseñar bien un MVP antes de escalar funcionalidades.

Bocetos, capturas e iteraciones

Primeros bocetos para la implementación de los chistes:

Resultados del estado de inicio de la app, estado de juego, Game Over y settings:

Fuentes y citaciones

Vínculo al .apk

https://github.com/elecinas/skip-balls/releases/download/v1.0/app-debug.apk

Debat0el PR2 – SKIP BALLS

No hi ha comentaris.

Publicat per

App Skip Balls

Publicat per

App Skip Balls

Procés d’ideació de l’aplicació Per a la realització d’aquest repte era necessari concebre una aplicació mòbil que fes ús d’alguna funcionalitat nativa…
Procés d’ideació de l’aplicació Per a la realització d’aquest repte era necessari concebre una aplicació mòbil que fes ús…

Procés d’ideació de l’aplicació

Per a la realització d’aquest repte era necessari concebre una aplicació mòbil que fes ús d’alguna funcionalitat nativa del dispositiu mòbil. Des del principi tenia clar que volia desenvolupar una aplicació de caràcter lúdic, ja que és un tipus de projecte que permet experimentar tant amb la interacció com amb la part visual.

Com a referència inicial, em vaig inspirar en jocs clàssics d’arcade com Galaxian o Arkanoid, especialment pel que fa a la simplicitat mecànica i al’ús de moviment com a element central del joc. A partir d’aquí vaig decidir aprofitar el giroscopi del mòbil per controlar el moviment del personatge, fent que aquest es desplaci lateralment segons la inclinació del dispositiu.

La idea final es concreta en un joc on cauen objectes des de la part superior de la pantalla, i el jugador ha d’esquivar-los movent el mòbil de costat a costat, simulant un efecte de gravetat.

Procés de desenvolupament i adaptació del tutorial base

El punt de partida del projecte va ser el tutorial base proporcionat per l’assignatura, que explicava com crear una aplicació senzilla amb Capacitor, p5.js i accés a les funcionalitats natives del dispositiu.

A partir d’aquesta base, el projecte va evolucionar progressivament mitjançant la integració d’un canvas a pantalla completa, la implementació d’un sistema de joc i l’ús de les funcionalitats natives.

Durant el desenvolupament es van resoldre diversos problemes tècnics, especialment relacionats amb errors d’instal·lació d’Android Studio, configuració de dependències i execució de l’app en dispositius reals.

Tot aquest procés va permetre entendre millor com Capacitor actua com a pont entre el codi JavaScript i les funcionalitats natives del sistema operatiu.

Ús de funcionalitats natives del dispositiu

L’aplicació, mitjançant Capacitor, fa ús dels sensors d’orientació (Motion API) que detencten la inclinació del dispositiu i permeten controlar el moviment lateral del personatge dins del joc.

També es va fer servir la pantalla sempre activa (Keep Awake) utilitzant un plugin de Capacitor per evitar que la pantalla s’apagui durant la partida. I, finalment, l’emmagatzematge local mitjançant l’API Preferences que es fa servir per guardar l’informació de l’usuari, puntuació, ranking i personatges desbloquejats. Amb tot aixó s’aconsegueix complir el requisit d’integrar elements natius dins l’aplicació.

Proves, iteracions i millores

Durant el desenvolupament es van realitzar múltiples proves tant en emulador Android com en dispositius reals, ja que algunes funcionalitats (com els sensors) no es poden fer servir en entorns simulats.

Després de les proves es van aplicar millores com l’ajustament de velocitat i acceleració del personatge, regular freqüéncia i velocitat de caiguda de partícules, afegir sistema de Game Over i reinici de partida i, finalment, implementar un sistema de dificultat progressiva.

Presa de decisions i aprenentatges

Una de les decisions més importants va ser simplificar l’abast del projecte, centrant-me en una mecànica clara i funcional, en lloc d’intentar integrar massa funcionalitats natives que podrien complicar el desenvolupament.

També va ser rellevant decidir separar el codi en mòduls (particles, storage, motion), millorant la llegibilitat i el manteniment del projecte.

A nivell d’aprenentatge, aquest projecte ha permès entendre el flux de treball amb Capacitor, el desplegament d’apps en Android, depurar errors natius mitjançant Logcat i integrar sensors del dispositiu en una aplicació.

Ús d’IA generativa com a suport

Durant el desenvolupament del projecte s’ha utilitzat la IA generativa com a eina de suport, principalment:

  • ChatGPT: Per resoldre bloquejos tècnics, errors de consola, problemes d’instal·lació i dubtes sobre Capacitor. Els prompts incloïen directament errors i captures de pantalla.
  • GitHub Copilot: Integrat a Visual Studio Code per detectar errors de codi.
  • Gemini: utilitzat per a la generació d’estils visuals (CSS), ja que la part estètica no era l’objectiu principal de l’assignatura.

L’ús d’aquestes eines ha permès agilitzar el procés i centrar esforços en el disseny i la lògica del joc.

Fonts i recursos utilitzats

Conclusions

Aquest projecte ha estat una primera aproximació al desenvolupament d’aplicacions mòbils natives utilitzant tecnologies web. A través de Capacitor, ha estat possible reutilitzar coneixements previs de JavaScript i p5.js per crear una aplicació funcional, interactiva i preparada per créixer en futures iteracions (pràctica 2).

El procés ha posat especial èmfasi en la resolució de problemes, l’experimentacio i l’aprenentatge pràctic, aspectes clau en el desenvolupament d’apps reals.

Vincle a GitHub

Repositori: https://github.com/elecinas/skip-balls

Dispositiu mòbil per les proves

Xiaomi Redmi Note 12

Debat0el App Skip Balls

No hi ha comentaris.

Publicat per

Timer Rings

Publicat per

Timer Rings

Introducció i context Aquest projecte forma part de l’activitat R3 on es proposa transformar el rellotge creatiu de la R1 en una…
Introducció i context Aquest projecte forma part de l’activitat R3 on es proposa transformar el rellotge creatiu de la…

Introducció i context

Aquest projecte forma part de l’activitat R3 on es proposa transformar el rellotge creatiu de la R1 en una extensió funcional del navegador Firefox.

L’objectiu era aprofitar l’animació creada i convertir-la en una eina útil relacionada amb el temps mentre es mantenia la coherència visual i aportant funcionalitat real.

Per aquest motiu he desenvolupat un temporitzador de treball i descans (tipus pommodoro) integrat dins la extensió web feta amb Manifest V3.

Concepte de l’extensió

L’extensió és una combinació entre temporitzador Pomodoro i rellotge visual abstracte, on l’usuari pot iniciar períodes de treball i descans. I una vegada iniciat pot pausar, aturar o reiniciar. També es pot veure el temps restant o el temps excedit en el cas que finalitzi la sessió i no s’aturi el temporitzador. L’estat del temps es manté tot i que es tanqui el popup gràcias a localStorage.

Esbossos del procés i wireframes

Aquí veiem la idea inicial abans de començar el codi.

Aquí les proves de color quan els botons estan actius, tant en mode dia com en mode nit.

També era important la mida i la posició del temps excedit una vegada acabat el timer.

I finalment, es va desenvolupar l’opció de que l’usuari pogués editar el temps que volia en cada sessió en el panell lateral del navegador.

La interfície

La interfície del popup está formada pel rellotge abstracte, sis botons SVG (WORK, REST, PLAY, PAUSE, STOP i RELOAD), un text digital que mostra el temps de sessió i un secundari que mostra el temps excedit (si cal). S’ha estilitzat tot fent un CSS extern.

Funcionament tècnic

L’extensió utilitza p5.js per al dibuix del rellotge i les animacions, el càlcul del temps  i l’ús de storeItem() i getItem() per guardar l’estat en el storage. Es fa servir Vanilla JavaScript per gestionar els botons i l’àudio (donat que p5.sound era bloquejat per l’extensió) i es fa servir el localStorage perquè l’usuari pugui editar els temps del timer. I finalment Manifest V3 per gestionar l’extensió.

Documentació del procés i dificultats

Es van trobar problemes amb Content Security Policy, incompatibilitat de p5.sound CDN amb manifest, la substitució de millis() pel temps absolut del sistema, la col·locació dels botons a sobre del canvas i la consistència del temps excedit.

De tot aixó es van extreure aprenentatges com: com funciona realment una extensió de navegador, com persisteix l’estat a localStorage i organitzar un projecte amb canvas p5.js i DOM alhora.

La proposta de millora

Com a proposta de millora en poso dos:

Registre d’activitats

Crear un historial de treball i descans, guardant cada sessió en un array a localStorage, amb la possibilitat de visualitzar estadístiques.

Icona dinàmica

Fer una icona de l’extensió que canvïi segons l’estat del temporitzador.

Enllaç a Github

https://github.com/elecinas/time-rings-clock-extension

 

Debat0el Timer Rings

No hi ha comentaris.

Publicat per

Brush or treat: Procés de desenvolupament

Publicat per

Brush or treat: Procés de desenvolupament

La idea inicial era que la temàtica de Halloween fos una sorpresa, així que l’aplicació web semblava un joc innocent fins que…
La idea inicial era que la temàtica de Halloween fos una sorpresa, així que l’aplicació web semblava un joc…

La idea inicial era que la temàtica de Halloween fos una sorpresa, així que l’aplicació web semblava un joc innocent fins que es feia clic al botó d’iniciar/apagar.
Per aquest motiu es van tractar per separat l’estètica de Healthy Smile Labs i la de Brush or treat.

La primera havia de ser neta, asèptica, gairebé com un consultori mèdic. En canvi, en entrar al programa de raspallat, el vídeo havia de tornar-se fosc i inquietant.

A més, la idea principal era la d’una presència fosca al voltant de l’usuari que l’amenaça perquè es raspalli les dents. Quan l’usuari ho fa, la presència embogeix i encara l’amenaça més. Tot això ambientat dins de l’humor negre, i no massa explícit, ja que està pensat per a un públic més aviat jove.

Esbossos de les captures de pantalla
Esbossos fets per tenir una idea de les captures de pantalla

A nivell visual, l’estil s’inspira en el terror clàssic: colors foscos, contrastos freds i efectes de llum intermitent. Les il·lustracions i gràfics han estat creats per mi, amb un traç brut i expressiu per reforçar la sensació d’incomoditat, i inspirats en la bogeria de Jinx (de la sèrie Arcane —Netflix—).

La tipografia utilitzada prové de dafont.com, triada pel seu aspecte distorsionat que encaixa amb l’atmosfera. Els sons de l’ambientació s’han obtingut de Pixabay amb llicència lliure, i s’ha ajustat el volum perquè s’integrin sense saturar l’experiència.
També s’ha afegit un sistema de partícules per als “dents” que apareixen en el crazyMode, per reforçar el to surrealista.

Captura de pantalla amb el programa apagat
Captura de pantalla en modePhantom
Captura de pantalla en crazyMode

Les llibreries utilitzades són: p5.js per a la visualització, ml5.js per a la detecció facial —centrant la interacció en l’obertura de la boca i en pintar creus a la posició dels ulls—.
També s’ha utilitzat Electron per convertir-la en una aplicació d’escriptori, i el projecte s’ha pujat a un repositori de GitHub
https://github.com/elecinas/BrushOrTreat

Gràcies a Git, s’ha pogut treballar amb més tranquil·litat i mantenir un bon control de canvis.

El flux és simple i directe: en iniciar l’aplicació, es mostra la càmera i un entorn fosc; l’usuari pot activar el programa amb el botó “iniciar”.
Apareix una ambientació inquietant i fosca amb la presència d’un fantasma que xiuxiueja amenaces, però quan l’usuari obre la boca, l’atmosfera canvia dràsticament: sons de rialles, música més intensa, imatges de somriures inquietants i dents que es multipliquen per la pantalla mentre se li tatxen els ulls.
Aquest joc d’ambientacions es pot aturar amb el mateix botó amb què es va iniciar, tornant a l’estat normal.

Conclusió

En començar el desenvolupament de l’app vaig decidir prioritzar-ne el muntatge i l’acabat, deixant per més endavant l’elecció de la llibreria de reconeixement facial i la d’Electron.
Això va ser un error, ja que, d’una banda, vaig haver d’instal·lar Electron amb l’aplicació ja creada a GitHub i ho vaig fer afegint els arxius manualment, en lloc de crear una aplicació d’Electron des del principi —que hauria estat molt més senzill—.
Però el més complicat va ser intentar migrar de llibreria de reconeixement facial: ho vaig provar amb MediaPipe de Google durant no sé quantes hores, sense aconseguir-ho.
Així que, per manca de temps i una planificació poc encertada, em vaig quedar amb ml5.js.


Debat0el Brush or treat: Procés de desenvolupament

No hi ha comentaris.

Publicat per

Time Rings

Publicat per

Time Rings

Per la creació del meu rellotge vaig plantejar-me la idea dels cicles: El temps és cíclic, els cercles representen el temps, els…
Per la creació del meu rellotge vaig plantejar-me la idea dels cicles: El temps és cíclic, els cercles representen…

Per la creació del meu rellotge vaig plantejar-me la idea dels cicles:
El temps és cíclic, els cercles representen el temps, els planetes són esferes que són cercles amb volum i les òrbites dels planetes són cícliques.
Així doncs vaig partir d’una idea de representar els cicles temporals de manera circular, una per a cada part del temps:

Amb la idea plantejada vaig mesurar, fent servir illustrator, la millor manera de distribuir els espais (seccions) i els segments; cada cercle te 6 subcercles que són proporcionals a 24 i 60

L’elecció de la paleta era clara, el dia amb tons de cel de dia i la nit fosca. I el color dels cercles llampants per contrastar.
Així doncs, el programa detecta quin mes estem i, el rellotge és diürn o nocturn. Diürn, pinta un sol i cel blau (encara no detecta si està núvol ^^U) i nocturn pinta la lluna i cel negre.
En conseqüència s’adapta tota la paleta de colors.
La tipografia, obtinguda de Google Fonts, havia de ser digital, ja que evoca els rellotges digitals vintage.j
El podreu trobar aquí:
https://editor.p5js.org/elecinas/full/R8xMMmG7E

NOTA: S’ha fet servir l’eina d’IA ChatGPT per la creació de la funció que detecta si és de dia o de nit segons on som i el mes que som, a més de revisar el codi quan no funcionava per detectar on eren els errors.

Debat0el Time Rings

No hi ha comentaris.