Aprende jugando: crea tu “Flappy Bird” en Power Apps

¿Te animás a crear un pequeño juego dentro de Power Apps? En este artículo vamos a ver:
Qué vamos a hacer:
- Una versión de Flappy Bird con tres tuberías, un pajarito que salta y un sistema de colisiones sencillo.
Por qué hacerlo:
- Para practicar la gestión de variables y timers en Power Apps de una forma divertida.
- Para mostrar que Power Apps no solo sirve para formularios y flujos de trabajo, sino que también permite crear minijuegos.
Cómo lo vamos a afrontar:
- Creando variables para definir posiciones y estados del juego (p. ej. puntuación, nivel, posición vertical).
- Añadiendo dos timers: uno para la “gravedad” y colisiones, y otro para el movimiento de tuberías y la lógica de puntaje.
- Implementando la mecánica de salto, colisiones y un botón de reinicio para resetear la partida.
Si te interesa un enfoque práctico, seguí leyendo para descubrir los pasos y el código esencial. ¡Manos a la obra! 🐦✨
1. Configuración inicial: OnStart ⚙️
En la propiedad OnStart de tu aplicación (o pantalla principal), definimos:
OnStart =
Set(varJuegoTerminado, false);
Set(numPuntaje, 0);
Set(numNivel, 1);
Set(numVelocidad, 10);
Set(numPosVertical, 200);
Set(tamGap, 400);
// Altura de las 3 tuberías inferiores
Set(
objTuberias,
{
alturaTubo1: 400,
alturaTubo2: 550,
alturaTubo3: 300
}
);
// Posiciones horizontales de los 3 pares de tuberías
Set(
objPosTuberias,
{
posTubo1: App.Width,
posTubo2: App.Width + tamGap,
posTubo3: App.Width + tamGap * 2
}
);
// Base o suelo (ejemplo)
Set(numBase, 145);
// Flag para “trampa” (evita colisiones si está en true)
Set(varTrampa, false);
¿Para qué cada variable?
- varJuegoTerminado: indica si estamos en Game Over.
- numPuntaje: guarda la puntuación acumulada.
- numPosVertical: posición vertical del pajarito (ej. 200 px desde arriba).
- tamGap: espacio entre tubería superior e inferior; mientras más chico, más difícil.
- objTuberias: alturas para cada tubería inferior.
- objPosTuberias: posición horizontal de cada par (va desde App.Width hacia la izquierda).
- numBase: margen para definir “el suelo” donde deja de caer el pajarito.
- varTrampa: si está en true, no se ejecutan las colisiones (modo “cheat” o depuración).
2. Timer de gravedad y colisiones ⬇️
Agregá un Timer (por ejemplo, timerGravedad). En OnTimerStart:
If(
Not(varJuegoTerminado),
If(
// ¿Todavía no llegamos al fondo?
numPosVertical < App.Height - numBase - imgPajaro.Height,
// Aumentar posición vertical para simular gravedad
Set(numPosVertical, numPosVertical + 10);
// Colisión con tubería 1
If(
(
(imgPajaro.X + imgPajaro.Width > tubo1Inf.X &&
imgPajaro.Y + imgPajaro.Height > tubo1Inf.Y &&
imgPajaro.X < tubo1Inf.X + tubo1Inf.Width &&
!varTrampa)
)
||
(
(imgPajaro.X + imgPajaro.Width > tubo1Sup.X &&
imgPajaro.Y < tubo1Sup.Y + tubo1Sup.Height &&
imgPajaro.X < tubo1Sup.X + tubo1Sup.Width)
),
Set(varJuegoTerminado, true)
);
// Colisión con tubería 2
If(
(
(imgPajaro.X + imgPajaro.Width > tubo2Inf.X &&
imgPajaro.Y + imgPajaro.Height > tubo2Inf.Y &&
imgPajaro.X < tubo2Inf.X + tubo2Inf.Width &&
!varTrampa)
)
||
(
(imgPajaro.X + imgPajaro.Width > tubo2Sup.X &&
imgPajaro.Y < tubo2Sup.Y + tubo2Sup.Height &&
imgPajaro.X < tubo2Sup.X + tubo2Sup.Width)
),
Set(varJuegoTerminado, true)
);
// Colisión con tubería 3
If(
(
(imgPajaro.X + imgPajaro.Width > tubo3Inf.X &&
imgPajaro.Y + imgPajaro.Height > tubo3Inf.Y &&
imgPajaro.X < tubo3Inf.X + tubo3Inf.Width &&
!varTrampa)
)
||
(
(imgPajaro.X + imgPajaro.Width > tubo3Sup.X &&
imgPajaro.Y < tubo3Sup.Y + tubo3Sup.Height &&
imgPajaro.X < tubo3Sup.X + tubo3Sup.Width)
),
Set(varJuegoTerminado, true)
);
)
);
- imgPajaro: el control de imagen del pajarito.
- tuboXInf, tuboXSup: tuberías inferior y superior (1, 2 y 3).
- Cada vez que el timer corre, Pepito cae y se chequean las colisiones.
3. Timer de movimiento: tuberías y puntuación 🏃
Agregá otro Timer (por ejemplo, timerMovimiento). En OnTimerStart:
If(
Not(varJuegoTerminado),
// Desplazar las tuberías a la izquierda
Set(
objPosTuberias,
{
posTubo1: objPosTuberias.posTubo1 - 10,
posTubo2: objPosTuberias.posTubo2 - 10,
posTubo3: objPosTuberias.posTubo3 - 10
}
);
// Incrementar puntaje
Set(numPuntaje, numPuntaje + 1);
// Tubería 1 reaparece cuando sale de la pantalla
If(
objPosTuberias.posTubo1 < -10,
Set(
objPosTuberias,
{
posTubo1: objPosTuberias.posTubo3 + tamGap,
posTubo2: objPosTuberias.posTubo2,
posTubo3: objPosTuberias.posTubo3
}
);
Set(
objTuberias,
{
alturaTubo1: RandBetween(130, App.Height - 100 - (tamGap + 10)),
alturaTubo2: objTuberias.alturaTubo2,
alturaTubo3: objTuberias.alturaTubo3
}
)
);
// Tubería 2
If(
objPosTuberias.posTubo2 < -10,
Set(
objPosTuberias,
{
posTubo1: objPosTuberias.posTubo1,
posTubo2: objPosTuberias.posTubo1 + tamGap,
posTubo3: objPosTuberias.posTubo3
}
);
Set(
objTuberias,
{
alturaTubo1: objTuberias.alturaTubo1,
alturaTubo2: RandBetween(130, App.Height - 100 - (tamGap + 10)),
alturaTubo3: objTuberias.alturaTubo3
}
)
);
// Tubería 3
If(
objPosTuberias.posTubo3 < -10,
Set(
objPosTuberias,
{
posTubo1: objPosTuberias.posTubo1,
posTubo2: objPosTuberias.posTubo2,
posTubo3: objPosTuberias.posTubo2 + tamGap
}
);
Set(
objTuberias,
{
alturaTubo1: objTuberias.alturaTubo1,
alturaTubo2: objTuberias.alturaTubo2,
alturaTubo3: RandBetween(130, App.Height - 100 - (tamGap + 10))
}
)
);
// Aumentar dificultad cada 200 puntos
If(
Mod(numPuntaje, 200) = 0,
Set(numNivel, numNivel + 1);
// Bajar velocidad, por ejemplo
If(
Mod(numPuntaje, 2) = 0 && numVelocidad > 0,
Set(numVelocidad, numVelocidad - 1)
);
// Reducir tamGap para que sea más difícil
If(
tamGap > 280,
Set(tamGap, tamGap - 10)
)
)
);
- Cada tick de este Timer mueve las tuberías y aumenta el puntaje.
- Cuando una tubería queda más allá de -10, se reposiciona a la derecha con una altura aleatoria.
- Cada 200 puntos subimos el nivel y ajustamos la dificultad.
4. El salto del pajarito 🦜
Para que Pepito suba, podés tener un botón, ícono o un rectángulo con:
OnSelect =
If(
numPosVertical > 100,
Set(numPosVertical, numPosVertical - 100)
);
5. Botón para reiniciar ♻️
Cuando hay Game Over, tocalo para volver a empezar:
OnSelect =
Set(varJuegoTerminado, false);
Set(numPuntaje, 0);
Set(numNivel, 1);
Set(numVelocidad, 10);
Set(numPosVertical, 200);
Set(tamGap, 400);
Set(
objTuberias,
{
alturaTubo1: 400,
alturaTubo2: 550,
alturaTubo3: 300
}
);
Set(
objPosTuberias,
{
posTubo1: App.Width,
posTubo2: App.Width + tamGap,
posTubo3: App.Width + tamGap * 2
}
);
¡Y listo! Todo vuelve a su estado inicial.
6. Conclusión: aprender de forma divertida
Crear un minijuego de Flappy Bird en Power Apps con tan solo tres tuberías sirve como un excelente ejercicio práctico para aprender y reforzar conceptos de la plataforma, como:
- Timers: controlar acciones en intervalos regulares (movimientos, colisiones, puntajes).
- Variables y registros: organizar la información de manera clara (posiciones X, altura, puntaje).
- Propiedades de los controles: manipular Height, Width, X y Y para animar o establecer la lógica de colisiones.
- Condiciones lógicas: If, Mod (para puntajes), RandBetween (para aleatoriedad), y otras funciones que hacen tu app más dinámica.
Además, este proyecto demuestra la versatilidad de Power Apps, que no se limita a formularios empresariales o flujos de datos, sino que también puede usarse para propuestas lúdicas o didácticas. De esta forma, combinás el aprendizaje de la plataforma con una experiencia entretenida para tus usuarios (o para vos mismo).
¿Qué sigue?
- Más tuberías: Si querés complicarlo, pasá a 4 o 5 tuberías.
- Rankings: Registrá los puntajes en SharePoint o Dataverse para ver quién es el campeón.
- Mejorar gráficos: Personalizá el fondo, agregá sonidos o animaciones.
- Explorar otras mecánicas: Hacer power-ups, niveles extras, o incluso un menú de bienvenida.
¿Te sirvió el tutorial? ¡Compartilo con colegas y amigos para que ellos también descubran cómo Power Apps puede ir mucho más allá de lo esperado! A seguir aprendiendo, jugando… ¡y volando! 🐦✨