Saltar navegación

Activa JavaScript para disfrutar de los vídeos de la Mediateca.

TFG - Contenido educativo

Ajuste de pantalla

El ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:

Subido el 19 de mayo de 2026 por Johnny Andrés S.

9 visualizaciones

Descargar la transcripción

Hola, somos Álvaro Ilzarbe, Jorge Navarro y Andrés Inche, y vamos a presentar nuestro 00:00:00
proyecto intermodular correspondiente al grado superior de Desarrollo de Aplicaciones Multipletaforma 00:00:04
en el IES Francisco de Quevedo. 00:00:08
Nuestro proyecto consiste en una aplicación multipletaforma relacionada con el ámbito 00:00:10
competitivo de Pokémon, desarrollada con Kotlin Multiplatform. 00:00:13
La aplicación permite crear, consultar y analizar equipos Pokémon utilizando datos 00:00:16
reales sobre Pokémon, movimientos, habilidades, objetos y también equipos utilizados en torneos 00:00:20
oficiales. 00:00:25
Para entender el contexto del proyecto, hay que tener en cuenta que en el competitivo 00:00:25
de Pokémon no basta con elegir Pokémon al azar. Los jugadores necesitan construir equipos 00:00:28
equilibrados, revisar estadísticas, comprobar eficacias de tipos, calcular daños aproximados 00:00:32
y analizar qué estrategias funcionan en partidas reales o torneos. Actualmente, una de las 00:00:36
herramientas más conocidas para esto es Pokémon Showdown, que se considera prácticamente 00:00:41
el estándar para crear equipos, probar estrategias y simular combates. Sin embargo, aunque es 00:00:44
una herramienta muy completa, no cuenta con una aplicación móvil específica. En móviles 00:00:49
lo habitual es acceder desde el navegador web, lo que puede resultar menos cómodo para 00:00:53
consultar datos, revisar equipos o trabajar con la interfaz durante mucho tiempo. 00:00:56
A partir de esa necesidad, decidimos crear una aplicación que reuniera varias funciones 00:00:59
útiles en un formato más adaptado a una experiencia multiplatforma. 00:01:03
La idea no era hacer solamente una Pokédex o una base de datos estática, sino una herramienta 00:01:05
que ayudara al usuario a crear equipos, consultar información relevante y apoyarse en ejemplos 00:01:09
reales de entorno competitivo. 00:01:13
La justificación del proyecto está precisamente en ofrecer una alternativa más cómoda y 00:01:15
organizada para este tipo de consultas, especialmente en dispositivos donde el uso de una web no 00:01:18
siempre es más práctico. 00:01:22
Además, el proyecto nos permitía aplicar muchos contenidos del ciclo 00:01:23
Como el desarrollo de interfaces en plataforma, el consumo de APIs externas, la organización cliente-servidor 00:01:27
La gestión de datos, el trabajo con backend y frontend y el uso de control de versiones en equipo 00:01:31
En cuanto a los datos, la aplicación obtiene información relacionada con Pokémon, movimientos, habilidades y objetos 00:01:36
Además, también incorpora la consulta de equipos presentados en torneos competitivos 00:01:40
Lo que permite al usuario tomar referencias reales, comparar estrategias y ver tendencias dentro del metajuego 00:01:44
Los objetivos principales del proyecto son 00:01:49
Desarrollar una aplicación multiplataforma funcional 00:01:50
Permitir la creación y consulta de equipos Pokémon 00:01:52
Implementar herramientas de análisis, como el cálculo de daño y eficacia 00:01:55
Integrar datos externos mediante APIs 00:01:59
Y organizar el proyecto con una estructura realista, separando responsabilidades entre las distintas partes de la aplicación 00:02:02
En resumen, nuestro proyecto combina una temática cercana y motivadora con un desarrollo técnico completo 00:02:07
No queremos hacer únicamente una aplicación de consulta, sino una herramienta que conectara datos, análisis y creación de equipos dentro de una experiencia multiplataforma 00:02:11
A continuación explicaremos con más detalle las tecnologías utilizadas, la estructura del proyecto y las principales funcionalidades desarrolladas. 00:02:18
Para el desarrollo del proyecto, lo primero que hicimos fue crear un repositorio compartido en GitHub, donde centralizamos todo el código, la documentación y el control de versiones. 00:02:24
Esto nos permitió trabajar de forma simultánea, diseñar cambios de manera ordenada y mantener un seguimiento claro de la evolución del proyecto. 00:02:30
Una vez preparado el entorno de trabajo, repartimos las distintas partes del proyecto entre los miembros del equipo. 00:02:35
Para coordinar las tareas utilizamos Taiga como herramienta de organización, lo que nos ayuda a distribuir el trabajo, planificar objetivos y llevar un control del progreso del desarrollo. 00:02:39
Como el objetivo era crear una aplicación móvil multiplataforma, utilizamos Android Studio como entorno principal de desarrollo. 00:02:46
Antes de empezar con el código diseñamos el diseño visual mediante Figma, lo que nos permitió definir la experiencia del usuario y organizar las diferentes pantallas antes de pasar al código. 00:02:51
Durante las prácticas y procesos de planificación se nos recomendó utilizar Kotlin Multiplatform, ya que se ajustaba especialmente bien a la idea del proyecto. 00:02:59
Esta tecnología nos permitía compartir lógica de negocio entre distintas plataformas, manteniendo una arquitectura más eficiente, modular y preparada para un desarrollo multiplataforma realista. 00:03:05
Además, encajaba con uno de los principales objetivos del proyecto, aplicar tecnologías actuales relacionadas con el desarrollo multiplataforma. 00:03:13
En cuanto a la parte del servidor y gestión de datos, optamos por utilizar Kator, 00:03:18
que es el backend, encargándose de la comunicación cliente-servidor. 00:03:21
Para la persistencia de datos, empleamos MySQL como sistema de base de datos, 00:03:24
donde almacenamos información relacionada con los usuarios, equipos y distintos elementos necesarios para el funcionamiento interno del sistema. 00:03:28
Respecto a la seguridad de la aplicación, implementamos autenticación basada en JWT, 00:03:34
JSON Web Token. 00:03:38
Esto nos permitió gestionar el acceso de usuarios de forma segura, controlar las sesiones y validar las peticiones autenticadas entre cliente y servidor. 00:03:39
De esta forma conseguimos una estructura más cercana a un entorno de desarrollo profesional incorporando mecanismos reales de autenticación y protección de datos. 00:03:45
A continuación mi compañero Jorge explicará cuáles fueron los problemas que nos encontramos durante el desarrollo. 00:03:52
En esta parte de la defensa vamos a explicar los principales problemas que tuvimos durante el desarrollo de la aplicación, 00:03:56
de qué forma conseguimos solucionarlos y especialmente qué aprendizaje sacamos de todos y cada uno de ellos. 00:04:01
Uno de nuestros principales problemas fue que, dado que ninguno de los tres integrantes del grupo tenemos experiencia realmente en Kotlin multiplatform, pues carecíamos realmente de la experiencia para entrar de lleno en el desarrollo y, sobre todo, en cómo funcionan los módulos en una aplicación de este tipo, qué responsabilidad tiene cada módulo. 00:04:07
Al final, un poco también por prueba y error, casi acabamos decidiendo que nuestros tres principales módulos, que iban a ser el server, el módulo server, que es el que tiene el backend independiente, hecho con Cator, el de JadeBrainz, y el tendríamos el módulo shared, que tendrían estructuras redutilizables, pero sobre todo tendríamos ComposeApp como módulo en el que se va a compartir casi todo el código común a todas las versiones de la aplicación. 00:04:26
porque, claro, a su vez 00:04:52
una aplicación multiplataforma tenemos que 00:04:54
organizar cómo funcionan los targets 00:04:56
y problemas que nacen de la compatibilidad 00:04:57
entre versiones de librerías, de según 00:05:00
dónde se vaya a ejecutar y este tipo de 00:05:02
proyecto, pues eso es fundamental. La solución 00:05:04
fue ir estabilizando poco a poco 00:05:06
la configuración del Gradle 00:05:07
separando responsabilidades y 00:05:09
aprendiendo la arquitectura 00:05:12
que es necesaria para una aplicación 00:05:14
de estas características. Otro problema 00:05:15
que tuvimos durante el desarrollo 00:05:17
de la aplicación fue poner en práctica 00:05:19
lo que hemos aprendido durante todo el año en la clase 00:05:21
de acceso a datos. Una vez 00:05:23
las tres tablas principales que utilizamos, que son 00:05:25
usuarios, equipos y equipos lots, 00:05:27
estaban disponibles y funcionaban 00:05:29
perfectamente, nuestra primera decisión 00:05:31
en realidad importante 00:05:33
al respecto de cómo íbamos a realizar 00:05:35
a trabajar con la database 00:05:37
fue crear una clase en la que 00:05:39
teníamos lógica centralizada de las operaciones 00:05:41
que realizamos sobre la database para que 00:05:43
cualquiera pudiera, cualquiera miembro del equipo 00:05:45
pudiera mirarlo en cualquier momento, que es 00:05:47
la database operations.kt 00:05:49
y esto nos permitió gestionar 00:05:51
de forma clara las operaciones que íbamos a hacer 00:05:52
y el aprendizaje aquí fue básicamente 00:05:54
separar rutas y lógica 00:05:56
de datos y 00:05:59
realizar al final 00:06:00
operaciones complejas en 00:06:02
una sola clase para que el código sea 00:06:05
mantenible y menos propenso a errores 00:06:07
uno de los problemas más importantes que tuvimos 00:06:08
al final fue decidir cómo íbamos 00:06:11
a enfrentar la seguridad 00:06:13
de la aplicación, evidentemente al principio 00:06:14
lo más básico era 00:06:16
leer usuario y contraseña 00:06:18
y buscar a ver que hiciera un match 00:06:21
evidentemente tuvimos que 00:06:22
decidir pues que seguridad 00:06:25
íbamos a implementar 00:06:27
en nuestra aplicación 00:06:28
lo primero al final lo hicimos 00:06:30
utilizando la librería Bcrypt 00:06:32
para jasear las contraseñas 00:06:34
y que compruebe la contraseña 00:06:36
del usuario durante el login 00:06:38
nosotros en nuestra base de datos 00:06:39
si otra persona se hace un usuario 00:06:43
realmente crea un usuario, nosotros no podemos ver 00:06:45
realmente la contraseña como texto plano, evidentemente, 00:06:47
porque para eso estaba Bacrit, para hashearla. 00:06:51
Otra cosa que implementamos también fue realizar una protección 00:06:54
un poco más robusta de las rutas privadas utilizando Authenticate 00:06:58
y sobre todo lo más importante en cuanto a la seguridad 00:07:01
fue implementar una autenticación mediante JSON Web Token. 00:07:04
Básicamente el servidor genera un token 00:07:08
y cuando el usuario inicia sesión correctamente 00:07:11
y es ese token el que se utiliza para acceder a todas las rutas protegidas. 00:07:13
nuestra implementación al final 00:07:16
nos permite tener una autenticación 00:07:19
stateless, que 00:07:21
significa que al final 00:07:22
no dependemos de que se guarde 00:07:23
una sesión 00:07:27
por así decirlo en el servidor 00:07:28
y al final 00:07:30
una de las mejoras más importantes 00:07:32
fue que decidí que 00:07:35
no íbamos a depender de enviar un 00:07:37
user ID desde el cliente 00:07:38
ya que el backend 00:07:41
obtiene el usuario autenticado directamente 00:07:42
desde el token. Esto al final es clave 00:07:44
porque si no, evidentemente, pues 00:07:46
un cliente podría mandar cualquier 00:07:48
user ID cambiando 00:07:50
un parámetro. El aprendizaje 00:07:52
principal que sacamos de 00:07:55
este problema en específico 00:07:56
fue aprender a hacer un login 00:07:58
en condiciones como 00:08:00
almacenar contraseñas en una base de datos, 00:08:02
implementar un hasheo 00:08:05
y sobre todo 00:08:06
aprender a validar la identidad 00:08:09
desde el backend 00:08:10
y garantizar que cada usuario 00:08:11
y solo puede acceder a sus propios datos. 00:08:14
El problema que tuvimos fue aprender a conectar correctamente 00:08:16
el frontend con el backend de la aplicación. 00:08:20
Dependiendo además de si se va a ejecutar en Android, 00:08:22
en el emulador, en el escritorio, el host puede cambiar. 00:08:24
Para ello, bueno, centralizamos host y ruta dentro de constante 00:08:27
para no tener las URLs repartidas por toda la aplicación 00:08:30
y garantizar, pues al final, una mantenibilidad y una legibilidad. 00:08:33
Separamos llamadas de autenticación en una clase específica. 00:08:36
Era importante manejar correctamente los errores 00:08:40
Para que, bueno, si el servidor no está disponible, que la aplicación mostrara un mensaje elegible. 00:08:43
Y para los equipos hicimos algo parecido también. 00:08:50
Separamos las llamadas relacionadas con equipos en su propia API. 00:08:52
Tomamos la decisión de que enviamos el token en la cabecera authorization como un better token. 00:08:56
También implementamos un fallback en posibles hosts o llamadas. 00:09:02
Tuvimos el problema de actualizar los equipos después de iniciar sesión o después de modificar datos. 00:09:07
y añadimos un estado para mostrar errores relacionados con los equipos 00:09:12
en vez de dejar un poco que el usuario no supiera que había pasado. 00:09:16
Como extra, en la versión en Android tuvimos que declarar permisos como Internet 00:09:19
y permitir ciertas conexiones durante el desarrollo. 00:09:23
Aquí nuestro principal aprendizaje fue conectar frontend y backend 00:09:26
yendo más allá de hacer simplemente peticiones HTTP y contemplar los distintos entornos, 00:09:30
la sesión, los tokens, los errores de red, el feedback visual que le estamos dando al usuario en general. 00:09:37
Uno de los bloques más complejos, a su vez, de todo el proyecto fue el motor del combate. La mejor idea era separar la lógica del combate en varias clases que tengan distintas responsabilidades. 00:09:41
Este problema lo solucionamos a base de tener la clase Battle Engine, que actúa como el coordinador principal del combate y que básicamente resuelve turno, decide qué va a ocurrir y se apoya para cosas específicas en clases específicas. 00:09:53
Como por ejemplo la Damage Calculator, que es un que hace el cálculo de daño, una parte matemática muy específica con muchos modificadores posibles y que lo mantuvimos en su clase individual. 00:10:09
Otra de las clases en las que asignamos una responsabilidad es muy específica, la de Ability Effect Resolver, que básicamente lo que hace es resolver el efecto de una habilidad concreta, dado que las habilidades interactúan con cualquier aspecto de la batalla, tanto con estadísticas, con el porcentaje de daño, efectos variopintos. 00:10:22
Tenemos PokeAPI Battle Data Source. Lo que hacemos en esta clase es asignarle la responsabilidad específica de cargar datos relacionados con Pokémon y los movimientos para que pueda trabajar con la información oficial de la PokeAPI. 00:10:42
Y finalmente, para una lógica de este calibre, decidimos hacer una clase que era Battle Engine Test para hacer test y comprobar que el motor se comporta como esperamos. 00:10:59
El aprendizaje principal que sacamos de aquí fue al final entender que cuando una lógica de dominio es muy compleja, la mejor forma de lidiar con ella es irla dividiendo en piezas muy pequeñas y así el código es más fácil de entender, de explicar, de probar y de ampliar. 00:11:10
En este apartado ahora lo que vamos a hacer va a ser hablar de las diferentes partes que consideramos más importantes dentro de nuestro proyecto. 00:11:31
El objetivo de haber creado una aplicación con una estructura multiplatform consiste en poder llegar a reutilizar la mayor parte de código posible. 00:11:37
Durante las prácticas recibimos la recomendación de utilizar este tipo de arquitectura porque nos permitía poder utilizar el mismo código para poder crear una aplicación web, una aplicación móvil, una aplicación iOS y cosas similares. 00:11:45
En esta ocasión en el proyecto se encuentran divididos en tres módulos principales 00:11:57
Pero vamos a explicar un poquito 00:12:00
El módulo Shared, que consiste en un módulo pequeño transversal 00:12:02
Que tiene unas utilidades básicas 00:12:06
Tenemos aquí cosas como constantes, clases básicamente de demo 00:12:08
Y un poquito de información sobre la plataforma 00:12:12
Una clase un poquito más secundaria 00:12:14
Porque la principal clase que tenemos dentro de la estructura de CodeMultiplatform 00:12:16
Consiste en el módulo ComposeUp 00:12:20
En esta clase podemos ver dentro del despliegue del SRC las diferentes estructuras, que aquí es donde se encuentran las pantallas del Android, del apartado web, del apartado aplicación pura y del apartado iOS. 00:12:23
que todas estas aplicaciones, todos estos módulos 00:12:36
lo que hacen es tirar del propio módulo 00:12:38
del Common Main, que es básicamente donde se 00:12:40
encuentra la interfaz visual 00:12:42
de todas las clases con toda 00:12:44
la estructura que se ha ido utilizando 00:12:46
para poder generar todas las diferentes 00:12:48
funcionalidades 00:12:50
dentro de lo que viene siendo la propia aplicación 00:12:52
y luego por último tenemos el módulo 00:12:54
Server, que básicamente es un backend independiente 00:12:56
que utiliza Cator, que expone 00:12:58
el API REST que estamos utilizando 00:13:00
o en este caso más de un API REST 00:13:02
se encarga de dar persistencia a los datos 00:13:03
autentificar usuarios y servir la información que consumen o que utiliza la aplicación a los 00:13:05
clientes el resultado final consiste en crear una única aplicación que se desarrolla en diferentes 00:13:12
plataformas a la vez como hemos podido ver en plataformas como el propio ordenador web android 00:13:18
ios de acuerdo la lógica es común ya que se escribe solamente una única vez como hemos podido 00:13:23
ver en la parte del común main esto es mucho más práctico mucho más sencillo a la larga porque si 00:13:28
Si se encuentra un bug en la lógica, se corrige una única vez para todas las plataformas 00:13:33
y no hay que ir modificando cada plataforma de forma unitaria. 00:13:38
La base de datos que hemos creado para este proyecto es una base de datos de MySQL 00:13:43
con 10 tablas principales que lo que hacen es modelar el sistema completo de nuestra aplicación. 00:13:46
Por un lado tenemos las datos más principales, los datos maestros, 00:13:52
que son las tablas de los tipos, donde se almacenan los 18 tipos principales que hay de Pokémon, 00:13:55
la tabla de habilidades, donde se almacenan todas las habilidades existentes en los Pokémon, 00:13:59
la tabla de los objetos que te permite almacenar todos los objetos de forma individual 00:14:03
la tabla de movimientos donde te permite almacenar todos los ataques que existen 00:14:06
en la versión de la franquicia de los juegos de Pokémon 00:14:10
por otro lado también tenemos lo que es la tabla de las especies 00:14:12
que consiste básicamente en uno de los puntos más importantes que podemos definir 00:14:14
de la aplicación porque es la que te permite tener localizado un Pokémon 00:14:18
con sus características individuales 00:14:22
ya que cada Pokémon tiene un valor de 6 características diferentes 00:14:24
que son vida, ataque, defensa, ataque especial, defensa especial y velocidad 00:14:27
Por otro lado, la tabla de usuarios, donde tenemos la información de cada usuario que utiliza la aplicación con su contraseña y su correo electrónico identificatorio. 00:14:30
También tenemos lo que vienen siendo los equipos de cada usuario, que están asociados por el ID de cada usuario que se genera, a lo que viene siendo el equipo, de tal forma que equipo 1 tenga el ID de X jugador, equipo 2 puede tener el de X jugador o el de Y jugador. 00:14:39
Por otro lado, tenemos la tabla de lo que son los equipos slots, que son datos persistidos de cada Pokémon en el equipo, ¿vale? 00:14:52
De tal forma que son los movimientos propios, habilidades propias con los que estén usando, el objeto que haya equipado la persona, los puntos individuales y cosas similares. 00:14:59
Datos de información que el usuario le ha metido a su propio equipo. 00:15:07
Y luego tenemos lo que viene siendo, por último, la tabla de Pokémon movimientos, que básicamente lo que te hacen es una correlación entre la tabla de Pokémon y la tabla de ataques, 00:15:10
permitiéndote decir que X Pokémon tiene acceso a estos determinados ataques 00:15:20
porque si no, cada Pokémon podría tener acceso a los 800.000 ataques que existen dentro de la Database 00:15:24
con lo cual, esta tabla es bastante, bastante necesaria, todavía sé 00:15:31
La base de datos indica también a normalizar lo que me he mencionado, los datos al máximo 00:15:35
Voy a poner un ejemplo de a lo que me refiero 00:15:38
No tendría sentido que si tenemos un Pikachu y un Raichu, que son ambos del mismo tipo 00:15:40
se duplicara el dato de que son de tipo eléctrico 00:15:46
Con lo cual, lo que se hace es usar una referencia a ese tipo y solamente se utiliza una vez ese dato y no dos veces. 00:15:50
¿Esto qué es lo que nos permite tener? 00:15:56
Nos permite tener por un lado una integridad referencial, es decir, no hay Pokémon con tipos inválidos, 00:15:58
una mayor eficiencia, ya que permite que si a futuro se produjera el cambio de un Pokémon o de un nombre de un tipo, 00:16:04
se podrá cambiar solamente una referencia y no tendrías que ir mil Pokémon revisando cuál sería la referencia correspondiente. 00:16:11
y una mayor escalabilidad, ya que permite poder estar preparado para poder hacer millones de registros 00:16:19
en vez de solamente uno al momento y da mayor facilidad a la hora de funcionar. 00:16:26
También hay que mencionar que el servidor se conecta utilizando Exposed, 00:16:31
que es básicamente para unas operaciones de tipo de type 6, ¿vale? 00:16:34
Que se ejecutan directamente contra la base de datos, que esto es una funcionalidad propia de Kotlin. 00:16:38
Vamos a hablar ahora de una cuestión de lo que viene siendo el corazón principal del proyecto, 00:16:43
que es el motor interno de peleas, ¿vale? 00:16:46
Es un motor que simula las batallas de los Pokémon 00:16:48
Lo que viene siendo de la misma forma que en el juego 00:16:51
Y se encuentra dividido principalmente en cuatro capas 00:16:53
La primera de ellas es el Battle Engine 00:16:55
Que es el director de orquesta, por así definirlo 00:16:58
Es el que maneja los hilos 00:17:00
Es la clase principal en la cual se dedica a gestionar el combate 00:17:02
Ya que recibe la información de la pelea 00:17:05
De, por un lado, los equipos de ambos jugadores 00:17:07
Y, por otro lado, los datos de la batalla 00:17:11
Es decir, los datos internos que tiene cada Pokémon 00:17:12
Las estadísticas, unidades, etcétera 00:17:15
¿De acuerdo? ¿Cómo funciona? Pues lo que se dedica a hacer esta clase es Tom, que genera un estado inicial, que es lo que se denomina en los juegos como Battle Preview, ¿vale? 00:17:17
Que ves a todos los Pokémon entrando y visualmente quedan ahí registrados, recibe las acciones de los jugadores y determina el orden de actuación, ya que aquí hay que tener en cuenta que los Pokémon van por velocidades, ¿vale? 00:17:27
Luego pasa el tema de los valores de los daños al Damage Calculator 00:17:39
Que ahora hablaremos de ello 00:17:43
Y el tema de aplicar los efectos de las habilidades al Ability Effect Resolver 00:17:44
Luego gestiona, lo que viene siendo los cambios de los Pokémon y las acciones entre turnos 00:17:51
Pero básicamente se dedica a dirigir todo este tipo de acciones 00:17:55
Y pasar a las clases siguientes los datos correspondientes 00:17:58
¿Qué cuáles son las clases siguientes? 00:18:02
Pues mira, vamos a empezar primero con el Damage Calculator 00:18:04
Que es básicamente el cerebro matemático 00:18:06
En Pokémon cada golpe no genera el mismo valor de daño al oponente, genera un baremo de A a B y entre A y B hay 16 valores diferentes que puede llegar a dar ese ataque. 00:18:09
Con lo cual hemos visto bastante necesario crear una calculadora interna, vamos a decirlo así, para poder llevar a cabo ese valor y dar fidelidad a los resultados. 00:18:25
Por eso hemos visto la necesidad de crear esta clase 00:18:34
Ya que a fin de cuentas es la que aplica 00:18:36
Esa fórmula, ¿vale? 00:18:38
Porque a fin de cuentas es una fórmula bastante compleja 00:18:40
Porque tiene en cuenta diferentes baremos 00:18:42
Diferentes multiplicadores 00:18:45
Diferentes multiplicadores en negativo 00:18:46
Es bastante complejo 00:18:49
Y era bastante, bastante necesario esta parte 00:18:51
Pero hay una forma que es bastante necesario 00:18:53
El apartado del Ability Effect Resort 00:18:55
Porque hay muchos Pokémon que sus habilidades 00:18:57
Interactúan directamente con el cálculo de daño 00:18:59
De las peleas 00:19:01
Por ejemplo, hay algunos que tienen habilidades que bajan las estadísticas del rival. Hay otros que se dedican a modificar el clima de la batalla haciendo que haya otros ataques que sean más fuertes o menos fuertes, que permitan cambiar el terreno. 00:19:02
Vale, todo esto tenemos que gestionar de alguna forma y hemos creado una clase que se dedica a gestionarlo para saber qué efecto se genera dependiendo de la situación. 00:19:14
Y por último, sucede lo mismo con los objetos 00:19:21
Hay objetos que se dedican a subir las características o bajar las características de los ataques del propio Pokémon 00:19:24
De tal forma que era bastante necesario crear una clase que se dedicara a gestionar de forma interna 00:19:30
Ese tipo de objetos para saber luego en el cálculo de daño cómo poder llegar a manejarlo 00:19:37
El siguiente punto que vamos a tratar va a ser el tema de las API REST 00:19:42
Para explicar y para partir de un punto inicial vamos a decir que los API REST son un conjunto de URLs 00:19:44
que el cliente, dependiendo 00:19:51
de donde sea, que en este caso 00:19:53
como tenemos holding multiplatform, va a ser de diferentes 00:19:55
sitios, consulta para poder 00:19:57
obtener o guardar los datos de forma 00:19:59
propia. Para poder llevar a cabo 00:20:01
esto, hemos creado una serie de endpoints 00:20:03
organizados en cinco categorías diferentes 00:20:05
que cada uno va hacia 00:20:07
un punto diferente. El primero 00:20:09
de ellos es la autentificación, lo que es el login 00:20:11
que hemos hecho lo que es básicamente 00:20:13
un post, un post 00:20:14
tirando los datos 00:20:17
hacia el login con el JWT 00:20:19
para poder hacer que el usuario 00:20:21
utilizando el token que se genera 00:20:23
pueda loguearse, eso por un lado 00:20:25
luego, una de las principales 00:20:27
puntos que 00:20:29
más información nos proporciona 00:20:31
es utilizar el API REST de la PokeAPI 00:20:33
que es una de las dos APIs principales 00:20:35
que hemos utilizado 00:20:38
¿por qué? porque de la PokeAPI hemos hecho 00:20:39
diferentes GET para poder obtener tanto tipos 00:20:41
como habilidades, como movimientos, como las especies 00:20:43
de los Pokémon, porque si no, íbamos a tener 00:20:45
que haber metido a mano una cantidad de datos que era 00:20:47
inhumana, vamos a ser honestos 00:20:49
luego el siguiente punto del cual vamos a hablar 00:20:51
es la otra API REST, es la API REST de 00:20:53
Limitless, que es una página 00:20:55
donde puedes obtener la información de 00:20:57
los equipos que se han estado jugando 00:20:59
de tal forma que es lo que genera 00:21:01
una database interna dentro de la 00:21:03
aplicación del móvil de los datos 00:21:05
de cada torneo, pudiendo consultar 00:21:07
la información de que jugador 00:21:09
ha jugado, que y que equipo ha quedado 00:21:11
en que posición en un determinado 00:21:13
torneo, luego por otro lado 00:21:16
para poder mostrar la información de lo que viene siendo 00:21:17
el propio usuario, hemos creado un endpoint 00:21:19
que apunta al usuario utilizando el propio 00:21:21
ID del usuario por medio 00:21:23
del uso de un GET, ¿vale? 00:21:24
Y luego, por último, pero no menos importante 00:21:27
un GET para saber 00:21:29
qué equipos tiene qué usuario 00:21:30
como hemos dicho, hemos utilizado 00:21:33
el propio ID del usuario para poder 00:21:34
asignárselo a unos equipos, como he 00:21:37
dicho antes cuando explicaba la parte de la database 00:21:39
de tal forma que haciendo un GET 00:21:41
podemos hacer que ese GET nos dé 00:21:43
el equipo del usuario determinado 00:21:45
que estamos usando ese id como digo apartado queremos hablar del tema de la seguridad vale 00:21:47
que consideramos que es un tema muy importante a la hora de poder crear una aplicación ya no sea 00:21:51
móvil sino multiplatform como es nuestro caso que hemos basado la seguridad principalmente en 00:21:55
dos elementos importantes por un lado es el paseo de las contraseñas vale para poder dar esa 00:22:00
seguridad a los usuarios de que las contraseñas no van a ser liqueadas con una facilidad alta y 00:22:06
Y por otro lado, lo que viene siendo el logueo de los usuarios, que lo hemos hecho mediante un JWT, es decir, un JSON Web Token. 00:22:15
Vamos a explicar un poquito rápidamente el flujo de cómo funciona este sistema, que básicamente sería, 00:22:25
el usuario hace el logueo con lo que viene siendo tanto su nombre de usuario como la contraseña. 00:22:29
Se mandan al servidor. Primero, se hace una comprobación de si este usuario está en la base de datos. 00:22:35
¿Existe? Sí 00:22:40
¿Tiene la contraseña correcta? Sí 00:22:42
Perfecto, se genera el JWT 00:22:44
Para poder utilizar las diferentes acciones 00:22:46
Posteriores, ya sea 00:22:48
Del equipo, del IDE 00:22:50
Etcétera, etcétera 00:22:52
¿Cómo funciona esto a la hora de crear un usuario? 00:22:53
Pues a la hora de crear un usuario 00:22:56
Se hace primero la comprobación de si ese usuario 00:22:57
Está en la base de datos 00:23:00
Si no está en la base de datos, se va a generar un usuario 00:23:01
Pidiendo al usuario que introduzca la contraseña 00:23:04
La cual va a almacenarse 00:23:06
Por medio de un raseo de contraseñas 00:23:07
no se van a guardar en ningún momento en texto plano ni de forma similar 00:23:10
porque eso no es una práctica segura y eso lo hemos podido ver también en clase 00:23:13
de que es mucho más seguro aplicar el hashable 00:23:16
y el funcionamiento ha sido similar al que hemos hecho en clase 00:23:20
con lo cual nos parecía mucho más apropiado poder optar por ese tipo de almacenamiento 00:23:23
para poder dar esa seguridad al usuario 00:23:29
y una vez se ha almacenado la base de datos se genera el usuario y ya el usuario puede lograrse 00:23:31
A continuación os haré una demostración de lo que es capaz de hacer nuestra aplicación 00:23:35
Lo primero que vemos al iniciar es el formulario de inicio de sesión con el botón de crear cuenta. 00:23:38
Al darle, se abrirá el formulario para crear una nueva cuenta. 00:23:43
Al rellenar el formulario y darle al botón de crear cuenta, nuestra cuenta será creada y nos dejará acceder. 00:23:46
Una vez acceda a la aplicación, llegas al menú principal, donde hay 7 opciones disponibles. 00:23:52
La primera opción es el Team Builder, que como su nombre indica, nos permite crear nuestro propio equipo. 00:23:56
Esta de aquí es una función que tiene la aplicación y facilita mucho el trabajo al momento de crear tu equipo, el autocompletado. 00:24:01
No solo lo tiene Pokémon, sino también el objeto que puede llevar 00:24:05
Otra función que tiene la aplicación es mostrarte la cantidad de habilidades que tiene un Pokémon 00:24:09
Si bajamos un poco más abajo podemos ver los movimientos 00:24:13
Que al igual que el nombre y los objetos, también tiene autocompletado 00:24:15
Si bajamos más abajo tenemos los puntos de esfuerzo 00:24:17
Los cuales nos permiten darle ciertas características a nuestros Pokémon 00:24:20
Si seguimos bajando podemos ver los botones 00:24:23
El de guardar equipo y el de cambiar el meta 00:24:25
Si le damos a guardar equipo podemos ver cómo se ha creado el equipo y también se ha guardado 00:24:27
La siguiente opción sería equipos propios 00:24:31
Nos permite ver los equipos que tenemos 00:24:33
Eso sí, el Team Builder nos da una forma de añadir equipos a esta aplicación 00:24:34
Si la damos aquí, podemos importar un Pokémon siguiendo el mismo estilo de importación de Shodown 00:24:37
Y después podemos pegar el texto de Shodown abajo 00:24:41
Al darle a importar, se nos crea justo debajo el equipo que acabamos de importar 00:24:44
Pasando con la tercera opción, tenemos el simulador de batallas 00:24:50
Nos permite seleccionar uno de los equipos que tengamos 00:24:52
El botón de simulador de batallas nos lleva al simulador de batallas 00:24:54
Aunque el nombre diga jugador 1 y jugador 2, realmente es el usuario que controla los dos equipos 00:24:56
Esto le permite crear situaciones que de otro modo no se podrían dar 00:25:00
El simulador de combate funciona como los juegos originales 00:25:02
Tras elegir las acciones contra el primer equipo, puedes darle al botón Cambiar Jugador para tomar las acciones del segundo jugador 00:25:05
Tras seleccionar las acciones de los dos equipos, podrás darle al botón de Jugar Turno, el cual las ejecutará 00:25:10
En el recuadro de encima, se puede ver los movimientos que se han realizado y en el orden en el que se ha hecho 00:25:14
El botón de calculadora te permite ir a la calculadora de daño y guardar el replay te permite guardar la repetición del combate 00:25:18
Nuestra cuarta opción es la tabla de tipos 00:25:23
Una vez aquí podrás seleccionar cualquiera de los 18 tipos y te dirá sus debilidades, sus naturalidades, sus resistencias y sus inmunidades 00:25:25
Como en Pokémon, los Pokémon pueden tener hasta dos tipos 00:25:31
Puedes seleccionar tus equipos y verás la combinación de sus debilidades y resistencias 00:25:33
La quinta opción es la base de datos de los torneos 00:25:36
Aquí puedes filtrar por meta y seleccionar cualquier torneo 00:25:38
Donde verás los jugadores que participaron en este 00:25:40
Puedes guardarte sus equipos y utilizarlos en la aplicación 00:25:42
Nuestra quinta opción es la calculadora de daño 00:25:46
Utilizan todos los datos de los Pokémon para calcular el daño que realizarían en una situación concreta 00:25:48
Nos dirigimos abajo para seleccionar el ataque que queremos hacer 00:25:52
Podemos elegir las condiciones del campo y cuando ya esté todo listo le damos a calcular daño 00:25:54
Al dar a calcular daño nos aparece una ventana emergente 00:25:58
Con el nombre del ataque, el daño mínimo que se podría haber hecho, el daño máximo que se podría haber hecho, la media del daño, la cantidad de DPS que le podrías haber quitado al Pokémon y cuántos golpes habría que darle para derrotarlo. 00:26:00
Por último, tenemos el Replace, donde podemos ver la repetición de los combates que hayamos guardado en el simulador de batallas. 00:26:09
Darle, podemos ir turno por turno y ver lo que fue ocurriendo. 00:26:15
Vayamos con las conclusiones. 00:26:19
En conclusión, el desarrollo de este proyecto nos ha permitido aplicar de forma práctica gran parte de los conocimientos adquiridos durante el ciclo de desarrollo de aplicaciones múltiples de forma, 00:26:21
integrando tantas tecnologías de frontend como de backend dentro de una arquitectura completa y funcional. 00:26:28
Podemos afirmar que se han cumplido los objetivos principales que se han planteado desde el inicio del proyecto. 00:26:33
Hemos conseguido desarrollar una aplicación multiplataforma orientada al competitivo de Pokémon 00:26:36
capaz de gestionar equipos, consultar información relevante 00:26:40
y ofrecer una experiencia más cómoda y adaptada al entorno móvil que las soluciones actualmente disponibles. 00:26:43
Además del resultado funcional obtenido, el proyecto ha supuesto una experiencia muy importante 00:26:48
de aprendizaje técnico y organizativo. 00:26:51
El uso de Kotlin Multiplatform nos permitió comprender mejor los beneficios y desafíos del entorno multiplataforma, especialmente en aspectos relacionados con la reutilización de lógica de negocio, la modularidad del código y la compatibilidad de tecnologías. 00:26:54
Desde el punto de vista técnico, tecnologías como Kator, MySQL y JWT han sido fundamentales para construir una herramienta robusta, segura y organizada. 00:27:06
La implementación de autenticación mediante tokens, la gestión estructurada de la base de datos y la separación cliente y servidor nos han permitido acercarnos a un modelo de desarrollo similar al utilizado en aplicaciones reales del sector. 00:27:13
A lo largo del proceso, también hemos encontrado diferentes dificultades 00:27:23
relacionadas principalmente con la configuración del entorno 00:27:26
de la plataforma, la integración del frontend y backend 00:27:28
y la adaptación de ciertas dependencias y librerías. 00:27:30
Sin embargo, la resolución de estos problemas 00:27:32
ha sido precisamente una de las partes 00:27:34
más enriquecedoras del proyecto, ya que nos ha obligado 00:27:36
a investigar, experimentar y mejorar nuestra capacidad 00:27:38
de análisis de los usos y resolución de problemas. 00:27:40
Finalmente, consideramos que este proyecto no sólo 00:27:42
cumple los requisitos académicos planteados, sino que 00:27:44
también demuestra el potencial que puede tener una aplicación 00:27:46
de este tipo dentro de un nicho concreto, como el competitivo 00:27:48
de Pokémon. Además, dejará abiertas las posibles 00:27:50
líneas de mejora futuras como la ampliación de funcionalidades, la integración de nuevas APIs 00:27:52
o la expansión completa hacia otras plataformas soportadas por Kotlin Bully Platform. 00:27:55
En definitiva, este trabajo supuso una experiencia completa de desarrollo de software, 00:28:00
combinando planificación, diseño, programación, trabajo en equipo y resolución de problemas 00:28:03
dentro de un proyecto técnico realista y cercano al ámbito profesional. 00:28:07
Materias:
Informática
Niveles educativos:
▼ Mostrar / ocultar niveles
  • Formación Profesional
    • Ciclo formativo de grado superior
      • Primer Curso
      • Segundo Curso
Subido por:
Johnny Andrés S.
Moderado por el profesor:
Lucia San Miguel López (lucia.sanmiguel)
Licencia:
Todos los derechos reservados
Visualizaciones:
9
Fecha:
19 de mayo de 2026 - 6:15
Visibilidad:
Público
Centro:
IES FRANCISCO DE QUEVEDO
Duración:
28′ 12″
Relación de aspecto:
1.78:1
Resolución:
1920x1080 píxeles
Tamaño:
1.73

Del mismo autor…

Ver más del mismo autor


EducaMadrid, Plataforma Educativa de la Comunidad de Madrid

Plataforma Educativa EducaMadrid