Saltar la navegación

7. Juegos de realidad

Rétor dice:Ha llegado el momento decisivo en el que ya estás preparado para cumplir el reto que has asumido. Ya conoces qué es el Internet de las Cosas y has visto cuáles son los elementos principales de un sistema robótico y cómo se interconectan entre sí.

Has trabajado los componentes de la placa micro:bit y te has centrado en aprender a programar en un nuevo entorno para poder volcar el programa en el microprocesador de esta placa. De hecho, has programado la placa Micro:bit en varios ejemplos que te pueden ser de mucha utilidad. También has recordado el código Python y, con él, has refrescado algunos ejemplos que te resultarán de utilidad en la programación del reto.

En lo que sigue, debes centrarte en cumplir con tu reto de programar, probar y documentar una aplicación que será una versión del famoso juego de esquivar los objetos que lanza una nave espacial y que no deben alcanzar al jugador. Esto lo vas a conseguir programando poco a poco cada una de las funciones necesarias de los dos principales objetos que intervienen en el juego, para posteriormente programar la parte principal del programa que lo une todo y lo pone en funcionamiento.

Así que ¡ánimo! verás como te gusta.

1. Patrones de respuesta

Para conseguir alcanzar una meta es importante que seas un buen o buena estratega. Es decir, tener métodos, técnicas, “trucos” para llegar antes o de forma más fácil donde tú quieres.

Ahora te voy a enseñar una estrategia, ¡Aprovéchala para alcanzar tu reto!

El nombre de la estrategia es patrones de respuesta. En muchos casos los ejercicios o actividades que tienes que hacer son similares e incluso casi idénticos a otros que ya has hecho antes o que te han puesto como ejemplo previamente. Tienes algo así como un modelo en el que fijarte para encontrar parecidos que te permitan resolverlo. En este reto recuerda que estás creando un videojuego, ¿Has hecho alguno antes? ¿Cómo planificaste su creación?

Podrás encontrar todo lo que necesitas sobre esta estrategia en el siguiente enlace a la guía de la competencia de aprender a aprender.

Tómate el tiempo que necesites y recuerda que siempre puedes preguntarle al docente o a algún compañero o compañera cuando no entiendas algo.

¡Ánimo, seguro que lo haces genial!

2. ¡A jugar!

Imagen del funcionamiento del juego en el que el enemigo va cayendo hacia la fila inferior.A continuación vamos a aclarar las características principales que debe cumplir el juego y sus bases de funcionamiento, para que cuando programes cada parte, sepas cómo debe comportarse. Memoriza bien las características para poder aplicarlas:

  1. Primero se elije el nivel del juego. Este nivel puede ser 1, 2 o 3 y lo elegimos pulsando el botón A de la placa micro:bit.
    1. Nivel 1: Es el de menor dificultad. En este nivel el enemigo va bajando actualizando su posición cada 500 ms. Es el movimiento más lento en lel juego.
    2. Nivel 2: En este caso el enemigo va bajando actualizando su posición cada 250 ms.
    3. Nivel 3: Finalmente, en el nivel más difícil es cuando el enemigo se moverá más rápidamente: actualizando su posición cada 100 ms.
  2. El jugador tiene 3 vidas y el juego se acaba cuando las vidas llegan a cero.
  3. Una vez elegido el nivel en el que se va a jugar, se pulsa el botón B de la placa micro:bit y empieza el juego.
  4. El juego consiste en mover al jugador hacia la derecha o hacia la izquierda por la fila inferior, huyendo de ser atrapado, mientras que el enemigo aparecerá en alguna posición aleatoria de la fila superior e irá cayendo hacia abajo. Si el enemigo llega a la fila inferior cayendo sobre el punto que representa al jugador, el jugador perderá una vida. Si el jugador se va totalemnte a la derecha de la pantalla, aparecerá por la izquierda.
  5. Si el jugador pierde las 3 vidas, el juego finaliza y se muestra en la pantalla el tiempo total de juego conseguido.

¡Vamos ahora a programar cada parte!

3. Enemigo a las puertas

Vamos a comenzar a programar las funciones del enemigo, que serán las más simples puesto que las únicas acciones que realizaremos con él serán crearlo y moverlo. Sigue las indicaciones siguientes:

Imagen de un marcianito enemigo de los videojuegos.

Comienza siempre comentando el código

No olvides documentar siempre el código que escribes informando mediante los comentarios de las acciones que pretendes conseguir o que vas a pasar a tratar:

# -------------------------
# Funciones del enemigo
# -------------------------

Crear al enemigo

Ahora vas a definir la función que crea al enemigo. Para ello sigue los pasos:

  • Comienza definiendo la función y llámala crea_enemigo().
  • Define las dos variables x,y que determinarán su posición. Estas variables serán globales para que se puedan modificar no solo desde la función sino también desde el programa principal. Así, recuerda que debe definirse este tipo de variable:
    global nombre_variable.
  • Asigna a la variable de posición y el valor 0, para crear al enemigo en la fila superior de la matriz de leds (la matriz e puntos de micro:bit considera que la fila 0 es la superior y se incrementa a medido que nos movemos hacia abajo).
  • Asigna a la variable de posición x un valor aleatorio para que el enemigo aparezca en cualquier posición posible de la fila superior.
  • Enciende al enemigo, para que se vea donde ha iniciado su posición al crearse. En micro:bit, el comando Python para apagar/encender un led es: display.set_pixel(x,y,valor) , donde: x,y son las coordenadas del led; valor es un número entre 0 y 9 que da la intensidad de luz. 0 es apagado y 9 es encendido totalmente. Nosotros utilizaremos justo estos dos valores.

Mover al enemigo

El movimiento del enemigo es hacia abajo, pero recuerda que en micro:bit la posición vertical se va incrementando a medida que bajamos por la matriz de leds. Entonces ahora harás:

  1. Apagar el punto que representa al enemigo, ya que si vamos a moverlo, debemos "olvidar" la posición anterior".
  2. Incrementar la variable de posición vertical.
  3. Volver a encender al enemigo para mostrarlo en su nueva posición.

En micro:bit, el comando Python para apagar/encender un led es: display.set_pixel(x,y,valor) , donde: x,y son las coordenadas del led; valor es un número entre 0 y 9 que da la intensidad de luz. 0 es apagado y 9 es encendido totalmente. Nosotros utilizaremos justo estos dos valores.



Lumen dice: ¡No olvides!

Recuerda que, como en todo programa Python, antes de empezar deberás importar las librerías que vas a utilizar:

  • En este reto, al utilizar la micro:bit, como ya viste en el apartado 3.2. Ex machina: nuestra placa, necesitarás importar la libería que nos proporciona las funcines de comunicación de las acciones que deseamos a nuestra placa. ¿Recuerdas cuál es?
  • ¿Nacesitas alguna librería más? Ten en cuenta que nuestro enemigo aparecerá en alguna posición horizontal aleatoria...

4. Activar las defensas

Ahora vas a crear las funciones que utilizará nuestro jugador, representado por el punto que se mueve por la fila inferior. Las funciones tendrán que garantizarle su creación y su desplazamiento para defenderse del ataque. ¡Ayudémosle!

¿Qué acciones puede necesitar hacer nuestro punto-héroe? Pues piensa que puede: ser creado, ser mostado, ser eliminado, comprobar si está siendo comido. ¡Tenemos 4 funciones por implementar!

Comentamos nuestro código

Comenzamos la codificación de estas funciones comentando qué comienza ahora en el listado de comandos del programa. Recuerda antes de cada función especificar de la misma manera lo que vas a codificar a continuación:

# --------------------
# Funciones del punto-héroe
# --------------------

Crear punto

Vamos a comenzar por crear nuestro jugador, el punto-héroe. Para ello necesitarás dos variables globales para sus coordenadas (recuerda darles nombres diferentes a las que has utilizado para las coordenadas del enemigo, por ejemplo coordenada a y coordenada b). Además, debes asegurar que el punto no se crea encima de la posición del enemigo, ya que perdería nada más empezar, ¿se te ocurre cómo verificar esto?

Paso a paso:

  1. Crear las dos variables globales a y b.
  2. Dar valores iniciales a estas variables, controlando que no comiencen posicionadas encima del enemigo. La coordenada a será horizontal y debe ser creada al azar. La coordenada b será vertical y siempre tendrá el valor de la última fila inferior de la pantalla de leds.

Mostrar punto

Mostrar el punto-héroe se reduce tan solo a encender el punto en la pantalla.

Mover punto

Para mover nuestro punto a derecha o izquierda pulsando los botones A y B de la placa, creamos la función mover_punto(). Esta función debe:

  1. Comprobar si se ha pulsado el botón A, y mover entonces la coordenada horizontal del punto una posición hacia la izquierda.
  2. Comprobar si se ha pulsado el botón B, y mover entonces la coordenada horizontal del punto una posición hacia la derecha.
  3. ¡Controla los límites de la pantalla!
  4. Recuerda finalmente, apagar el punto antes de actualizar su posición y volver a encenderlo en la nueva posición.

Para comprobar si se ha pulsado un botón, se llama a la función button_a.was_pressed() que devuelve True si se ha pulsado el botón A de la placa, o button_b.was_pressed() que devuelve True si se ha pulsado el botón B de la placa.

¿Ha sido eliminado?

Si el enemigo se ha "comido" a nuestro punto-héroe, Tendremos que apagar el punto. Esa función, que bien podría llamarse comer_punto() deberá entonces apagarlo con el comando que has visto en el ejercicio anterior sobre las funciones del enemigo.

Comprobar si el enemigo se ha comido al punto

Para esta función, a la que podemos llamar comprobar_enemigo_come_punto(), tendrás que utilizar una estructura que nos devuelva (return) un valor True si las posiciones coinciden, o un valor false si no coinciden, y por tanto no se lo ha comido.

Lumen dice: Algunas pistas

Aquí tienes algunas pistas para implementar estas funciones:

  1. Para verificar que cuando se crea nuestro punto-héroe no lo hace encima del enemigo en ese momento, puedes utilizar una estructura tipo bucle hacer siempre controlado con una variable false/true tal que, cuando se entre en el bucle, si tras crear el punto-héroe se comprueba que no está encima del enemigo, se ponga a false y se termine el bucle de intentos de creación. Para saber si enemigo y punto-héroe coinciden en posición, necesitarás una estructura de tipo condicional que compare las coordenadas de ambos. Si coinciden habrá que intentar dar un nuevo valor a la coordenada vertical.
  2. Recuerda que en programación los índices de las filas y columnas de las matrices siempre empiezan por cero. Luego, la última fila de la matriz de leds de nuestra placa micro:bit tendrá el valor 4.
  3. ¡OJO!: Los nombres de las funciones y de las variables no pueden contener espacios en blanco en ellos.
  4. Para comprobar los límites de movimiento del punto por la fila inferior, recuerda que debes controlar que la variable que guarda la posición horizontal mo pase del valor 4, en cuyo caso, debes actualizar su valos para que aparezca por el lado contrario de la pantalla.

5. Tomando posiciones

Es la hora de comenzar la programación del inicio del juego. Para ello, antes de comenzar la ejecución principal del mismo, necesitarás crear las variables, crear a nuestro punto-héroe (aunque sin mostrarlo aún en pantalla), establecer las vidas, iniciar un valor de nivel de dificultad por defecto y programar dicho nivel de dificultad. ¡Atendamos a cada acción por orden!

Imagen que muestra la casilla de salida de un juego con la palabra Start.

Comentamos la nueva fase

Recuerda indicar en el código que comienzas una nueva fase en la programación con los comentarios adecuados:

# ----------------------------
# Inicializamos las Variables
# ----------------------------

Recuerda también que cada uno de los pasos aquí dados a continuación deben ir precedidos de su correspondiente comentario para saber qué operaciones se atienden en cada momento.

Declaramos variables

Recuerda que tienes 4 variables que declarar para el funcionamiento de los personajes.

Crea el punto-héroe

A continuación deberás llamar a la función que crea a nuestro personaje principal, aunque de momento no lo visualizaremos, eso se realizará durante la ejecución del programa.

Inicia valores por defecto

Ahora tendrás que iniciar el valor de la variable vidas, que cuenta el número de vidas del protagonista.

También tendrás que iniciar la variable nivel_dificultad a 1, al menos, aunque después el jugador elija el nivel que más le convenga.

Finalmente, necesitarás una variable que vaya contando el número de ciclos de enemigo que nuestro punto-héroe está en activo. Esta variable comenzará en 0 y se irá incrementando cada vez que el enemigo caiga totalmente y se inicie arriba u nnuevo enemigo...y siga vivo nuestro punto-héroe, ¡por supuesto!

Configuramos la dificultad al inicio del juego

¡Es el momento de que, al iniciar el juego en la placa, el jugador elija a qué nivel de dificultad desea jugar! Para ello al iniciar entraremos en un bucle por siempre en espera de que se pulse el botón b de la placa para empezar el juego en sí (recuerda las instrucciones del juego en el punto 1 de este apartado). Al entrar en ese bucle:

  1. Primero, mostraremos la letra N en la pantalla, que indicará que se va a mostrar el nivel de dificultad en curso. Para mostrar un valor en pantalla utilizamos el comando: display.scroll("N") o display.scroll(variable)
  2. Después mostramos en pantalla el valor de la variable que indica el nivel seleccionado.
  3. A continuación entramos en una estructura condicional cuya finalidad es detectar si se pulsa el botón A para cambiar el nivel de dificultad. Cada vez que se pulsa el botón A, el nivel se debe incrementar en uno. Cuando supere el máximo valor (3) comenzará de nuevo por 1.
  4. Finalmente, no olvides establecer el tiempo de caída del enemigo según el nivel elegido:
    1. En el nivel 1, el tiempo de caída será de 500 ms (actualziación de posición del enemigo). Necesitarás iniciar la variable tiempo a este valor.
    2. En el nivel 2 el tiempo será de 250 ms.
    3. En el nivel 3, el tiempo será de 100ms.



6. Entramos en bucle...en el principal

¡Es la hora de dar la forma final a nuestro juego y comenzar a funcionar! Vamos a programar el cuerpo principal de funcionamiento. En esta fase tendrás que atender a las condiciones de desarrollo de la partida: correrá mientras existan vidas, habrá que crear un enemigo y mostrar a nuestro punto-héroe en pantalla, hacer bajar al enemigo mientras se comprueba si se pulsan los botones de desplazamiento a izquierda o a derecha para hacer huir a nuestro punto-héroe, cuando el enemigo llegue abajo hay que comprobar si se ha "comido" al punto-héroe y finalmente, comprobar si quedan vidas. En caso de que no queden mostraremos en pantalla el fin del juego y el tiempo que hemos estado en activo, que determina la puntuación alcanzada.

Gif animado en el que podemos ver en la pantalla de la micro:bit cómo caen "asteroides" desde la parte superior hasta la inferior, en la que un led que hace de protagonista es controlado por el jugador, desplazándose de izquierda a derecha para evitar que los asteroides le golpeen.

¡Comenta que entremos en la parte principal!

No olvides, como siempre, comentar la nueva fase en la que entramos en nuestro programa:

# ---------------------
# Bucle Principal
# ---------------------

¡Ni olvides comentar también cualquier acción posterior de estas que trabajamos a continuación! Documentar es fundamental.

Bucle de vidas

Comenzaremos entrando en un bucle que se repetirá mientras nos queden vidas para continuar la partida iniciada.

Mostrar punto

A continuación, dentro del bucle de juego, lo primero que haremos, es mostrar la posición en la que se creó nuestro punto-héroe en un principio. Así el jugador sabe con antelación de qué posición parte.

Creamos al enemigo

Comenzamos ahora creando un nuevo enemigo, que empieza a guerrear en la fila superior.

El enemigo desciende...

Entramos ahora en un bucle de 4 pasos que se encargará de ir descenciendo a nuestro enemigo en vertical. Para ello:

  1. Primero, antes de mover al enemigo, dejaremos pasar el tiempo seleccionado en el nivel para la velocidad de actualización del descenso del enemigo. En micro:bit se hace con el comando sleep(tiempo), donde tiempo es la variable en la que hemos almacenado la rapidez de actualización de posición acorde al nivel que se juega.
  2. Luego, moveremos al enemigo llamando a su función mover_enemigo().
  3. Finalmente, daremos la opción al jugador para que se mueva rápido con el fin de salvarse de la colisión. Llamaremos entonces a la función que mueve a nuestro punto-héroe mover_punto().

¿Nos ha comido?

Una vez que el enemigo ha descendido a la última fila, es el momento de comprobar si nos ha comido. Para ello debes llamar a la función de comprobación de nuestro punto-héroe llamada comprobar_enemigo_come_punto(). Si es así:

  1. El punto-héroe ha sido eliminado y hay que llamar a su función comer_punto() para apagarlo.
  2. Restarremos una vida a nuestra variable contador de vidas.
  3. Crearemos un nuevo punto-héroe llamando a la función crear_punto().

¡Hemos sobrevivido a un nuevo ciclo!

Una vez que el enemigo ha completado un descenso y no hemos perdido vidas, hemos completado un nuevo ciclo de juego. No olvides sumar 1 a tu puntuación de permanencia en la partida.

Game over

Consumidas todas las vidas, el juego ha terminado. Indicaremos en la pantalla tal circunstancia con dos acciones:

  1. Mostrar en pantalla la palabra FIN.
  2. Mostrar en pantalla el contador de ciclos, que nos da la puntuación obtenida.



¿Jugamos?

7. ¿Y si nos movemos con sensores?

¡Para el alumando valiente! Te proponemos a continuación un par de mejoras para tu recién estrenado juego:

  1. La primera mejora: Cuando el enemigo se come a nuestro fantástico punto-héroe hasta ahora la función come_punto() simplemente lo apaga. Pero...¿y si en vez de apagarlo mostramos por pantalla una cara triste? Si quieres afrontar este reto aprende aquí con qué comandos podemos mostrar una cara triste en nuestra pantalla de la micro:bit. En Python, por supuesto: en la ventana que se abre, despliega las opciones de código junto a la palabra bloques y selecciona Python.
  2. La segunda mejora: ¿qué te parecería que nuestro punto se desplace usando los sensores de movimiento de la placa en vez de usar los pulsadores de los botones A y B? Para ello, deberás usar la información que te proporcionan los acelerómetros. Concretamente, el acelerómetro x te informará de si la placa se mueve bajando hacia la izquierda o hacia la derecha, y con esto podrás mover a nuestro punto-héroe hacia un lado u otro. Utiliza para leer la información de los sensores la función accelerometer.get_x(). El siguiente código te hará actualizar la posición x del punto-héroe:
# Si inclinamos hacia la horizontal izquierda y x>0
    if (acel_x < -150) and (a > 0):
        a = a - 1
# Si inclinamos hacia la horizontal derecha y x<4
    if (acel_x > 150) and (a < 4):
        a = a + 1

Deberás modificar entonces la función mover_punto() para utilizar esta nueva técnica de movimiento. ¡Adelante, hará el juego más divertido y emocionante!

Clavis dice Piensa en lo que has hecho

Antes de seguir, para un momento y reflexiona sobre lo que has hecho.

Para ello es muy adecuado que intentes identificar qué procedimientos has tenido que poner en marcha para realizar esta actividad; cuáles eran estrategias necesarias y con qué recursos contabas para resolverla.

Piensa también en cuáles han sido las dificultades que te has encontrado a la hora de dar respuesta.

¡Todo esto te será muy útil cuando tengas que enfrentarte a alguna actividad parecida!

Entonces, estarás preparada o preparado para poder resolverla sin problemas con tu experiencia previa.