Desde hace un tiempo, que sigo enfatizando el uso de las estructuras que son necesarias para diversos lenguajes de programación En este caso IF-THEN-ELSE (como vimos en CLASE 4). En ésta ocasión haremos un básico Runner.
Varios alumnos de sexto grado me contaron que quieren seguir aprendiendo Computación y Programación en la secundaria, de hecho le pidieron a sus padres que los anoten en Escuelas Técnicas para tal fin, y la mayoría son nenas, lo cual me parece genial, para revertir la tenencia masculina del sector que se dió en los 80´s (Por culpa de Nintendo y Sega), Varios de ellos llevan sus Pendrives (Memorias USB) propios donde tienen SUS archivos, lo cual es genial, porque habla del compromiso que tienen con lo que apenden. Como si fuera poco, los padres de los chicos apoyan mucho a sus hijos, uno de ellos me preguntó que lenguaje le convendría seguir, y le recomendé C# para crear juegos con Unity3D, y le regalé un libro al chico porque lo ví muy interesado en el tema así que ésta clase haremos un juego simple (aunque nos tome varias semanas completarlo en el aula).
Creando Elementos Gráficos
Para empezar, he creado un monigote amarillo (que NO ES Homero desnudo), un enemigo y dos imágenes de fondo, pueden descargarlos ya que tienen los nombres que usaremos en el proyecto.
Dibujando el Fondo
CieloSOL es la imagen de fondo que estará detrás inmóvil, mientas que fondo es la imagen de los helados con fondo transparente.
En la imagen de abajo se ve que empezamos borrando las pantallas de texto y gráficos copn CLS y CLG respectivamente. Luego se indica el FastGraphics y GRAPHSIZE 500,500 que sirve para que nuestra ventana de gráficos tenga un tamaño de 500x500 píxels.
En la imagen se ven las 2 formas de expresarlo, tanto en líneas separadas como unidas con dos puntos (:) para ahorrar espacio en líneas que usamos siempre. En otros lenguajes de programación se utiliza el ; al final de cada sentencia o bien para agruparlas en una sola línea.
Luego dentro de un loop usamos IMGLOAD para poner la imagen en tamaño 10... supongo que podría dibujar el fondo más grande y hacerlo mucho más detallado, pero me gusta el aspecto de pixel art para éste ejercicio :D
REFRESH es para que se dibujen las imágenes rápidamente usando usamos FastGraphics como dijimos en clases anteriores, un pause 0.1, y CLG para que borre antes de repetir el loop.
Todo lo que está antes de la línea 6 es donde declaramos las variables, siempre les digo a los chicos que es donde le decimos al juego con cuantas vidas empezamos (vidas=1 , por ejemplo), o en que lugar del nivel estamos, una vez dentro del ciclo WHILE ... ENDWHILE ésto puede variar.
Fondo en Movimiento
En éste ejemplo he creado x e y para usar con el personaje, también a=0 para mover el fondo hacia atrás a una velocidad constante.
En la línea 9, establecemos una resta a=a-10 y luego lo usaremos para poner 2 imágenes. En cada ciclo el valor se decrementará en 10 (0, -10, -20, -30, ...-n-10) y luego los usé en 2 imgload para que dibuje las imágenes una al lado de la otra. Si corremos el código, veremos que éste fondo desaparece sobre el margen izquierdo, y es porque con 2 IMGLOAD sólo dibujamos el fondo visible y otro 500 píxeles a la derecha (afuera de la pantalla). El valor restado es la velocidad a la que se moverá el fondo, le digo a los chicos que prueben distintos valores... obvio, aman la velocidad asi que pronto les desaparece de la pantalla.
Este momento es importante para repasar el IF-THEN-ELSE. O sea, si el valor de a es -500, quiere decir que la primer imagen desapareció a la izquierda, y estamos viendo la segunda imagen. Preguntamos si es menos o igual a 500 , que cambie el valor a CERO (0) o sea que siempre veremos estas 2 imágenes pero el cambio es tan rápido que no lo notaremos y parecerá continuo.
para eso usaremos ésto dentro del loop que nos dará el resultado de la imagen:
IF a<= 500 then
a = 0
endif
Personaje Corriendo
Para éste ejemplo he agregado bicho=0 (línea 4) que me permitirá llamar al archivo por el nombre, que para simplificar el ejemplo, están numerados.
En la línea 14 de la imagen siguiente dibujo el personaje a la izquierda (100) y a 350 pixels desde la parte superior lo que lo pone en la parte inferior. Luego el Valor del Tamaño es 5 y finalmente usé LOWER(bicho) que es una forma de convertir el número en un carácter alfanumérico.
Por ejemplo si bicho vale 1, lower(1) convierte el valor a "1" que es el nombre del archivo, luego con bicho=bicho+1 (linea 5) indicamos que cargue en el próximo ciclo la próxima imagen.
Como solo dibujé 5 imágenes, debemos controlar que la variable BICHO jamas contenga el valor 6. O sea que preguntamos, si BICHO = 6 entonces que bicho vuelva a 0, entonces en cada ciclo el valor cambiará de la siguiente manera 0,1,2,3,4,5,0,1,2,3,4,5... jamás saliendo del rango de 0 a 5 (lineas 17, 18 y 19)
Enemigos
Para crear el enemigo, antes de la línea 6 agregué: malo=500 (línea 4), que es la posición inicial horizontal del malo, en el margen derecho de la pantalla.
Dentro del ciclo While...EndWhile agregué las líneas 19 a la 24 para poner el enemigo. La línea 24 es la que dibuja el enemigo en la posición 500+malo, pero en la línea 20 vemos que malo se decrementa en 20 como lo hace a en la línea 9. Por lo tanto empieza en 500+0 y termona en -500.
En el IF de la línea 21, preguntamos si malo llegó a -500, si lo hizo, malo obtiene 1800, por lo tanto en el próximo ciclo la posición del enemigo será 2300 (500+1800) lo cual nos dará algo de tiempo para que vuelva a aparecer por la derecha.
¿ESTOY MUERTO?
Antes de crear los movimientos, definiremos como matar al personaje con el enemigo. Para ésto definí en la línea 4 una variable vivo=true , lo que la hace booleana, sólo puede tener TRUE o FALSE. Así que al iniciar el juego el personaje está en estado VIVO, en la línea 7, cambié el While TRUE que definía un ciclo infinito por la condición (vivo=true) que puede ser verdadera o falsa: WHILE (VIVO=TRUE)
Esto quiere decir que el ciclo se repetirá cuando vivo sea TRUE, así que si lo matamos le debemos asignar el valor FALSE y el ciclo terminará y para éste caso agregué las líneas 31 a la 35 donde se dibuja al enemigo en tamaño 10 (que ocupa la pantalla) y escribe el texto "MUERTO!!!" en sangrientas letras rojas.
Para controlar, debemos agregar un IF con 2 condiciones, en las líneas 24, 25, y 26. Con éste IF preguntamos si 500+malo es igual a 100, o sea si la posición donde está el enemigo y el personaje son la misma, AND quiere decir que tambien debe evaluar si SALTO=false (este punto lo explicaremos después).
Si ambas son ciertas, quiere decir que el enemigo nos tocó y no hicimos nada para evitarlo, entonces se ejecuta la línea 25, donde vivo pasa a ser FALSE y el próximo ciclo no se ejecutará, simplemente saltará a la línea 32 donde ya estamos muertos y el programa termina.
Creando un salto (en otro Archivo)
Si probaron el código de arriba, verán que el personaje corre hasta que el enemigo lo mata, no tiene forma de defenderse. Para ésto usaremos la barra espaciadora, y que nuestro personaje pueda saltar. Pero para lograr un salto correcto, debemos agregar variables de VELOCIDAD y ACELERACION. Muchos de los chicos todavía no conocen las fórmulas de Newton, por ello usaré OTRO ejemplo más simple para explicarlo. Para éste nuevo ejemplo sólo hacemos un círculo, tenemos unestado inicial antes del while true y dentro de éste definimos que queremos hacer con VELOCIDAD y ACELERACION.
Como se ve en la imagen de arriba, tenemos algo muy parecido al juego que hicimos esta clase, sin dibujar fondo, personaje o enemigos. En las líneas 9 y 10 se calcula la posición vertical de la pelotita azul (y), y luego tenemos 2 estructuras if-endif, la primera (linea 12) pregunta si y>289 o sea si en la vntana de gráficos nuestra pelota tocó el piso, si es cierto, velocidad se vuelve CERO y salto se le asigna FALSE. En el segundo if-endif (línea 15) preguntamos si se presiono la tecla 32 que es la barra espaciadora, y ademas, preguntamos si salto es FALSE (para que no haga un salto doble, sól opodrá saltar cuando está en el piso... aunque algunos juegos usan el salto doble, como ChunLi contra el borde de la pantalla, Donkey Kong, Sonic). Si ambas cosas son ciertas, se le asigna una velocidad -2.0 para que la pelota suba (recordemos que el CERO es la parte superior de la pantalla y el 300 es la parte inferior), y se le asigna a salto el valor TRUE para que si presionamos otra vez la barra espaciadora mientras esta en el aire, se ignore. O sea que sol ocuando la pelota este en el piso podrá saltar.
#Código para este mini ejercicio
fastgraphics : clg : cls x = 150 : y = 280 : r = 10 velocidad = -2.0 aceleracion = .03 salto = false WHILE TRUE velocidad = velocidad + aceleracion y = y + velocidad if y > 289 then y = 289 velocidad = 0 salto = false endif
t = key if (t =32) and (salto=false) then velocidad = -2.0 #velocidad vuelve a ser la de subida salto = true endif color blue : circle x, y, r : refresh : clg ENDWHILE
Saltar al Enemigo
Ya vimos en el mini-ejemplo anterior como crear un salto con la barra espaciadora, ahora el codigo lo inserto en el ejercicio que usamos ésta clase. Me tomé la libertad de marcar en amarillo en la imagen de abajo los cambios que le agregué del min-ejemplo.
O sea declaramos las variables en las líneas 5,6, y 7 (tecla, velocidad, aceleracion , s). En la línea 14 cambié el valor vertical del personaje por la variable s , que dibujará al personaje en una posición diferente. En la línea 24, le pedimos que detecte una tecla y guarde el código en la variable tecla, en la línea 25, preguntamos si la tecla es la 32 (barra espaciadora) y si el personaje está en el piso (salto=false), si es cierto, asignamos un valor a velocidad y asignamos salto : TRUE. En la línea 29 preguntamos si el personaje está saltando, si es cierto calculamos la posición con la velocidad y la aceleración. Luego preguntamos si la posición del personaje está más abajo del piso (línea 33) si es cierto, ponemos la velocidad en cero, asignamos a salto el valorFALSE y volvemos a s a la posición 350 (para que no vaya más abajo del piso). Para que el enemigo no nos mate al saltar, en la línea 22, agregamos una tercer condición, si s=350. Parafraseando el contenido de ese IF: Si la posición del enemigo y el personaje es la misma y no esta saltando, entonces vivo es FALSO, el while no se vuelve a repetir y el código salta a la línea 42 donde dibujamos al enemigo y el cartel con letras rojas. Se pueden hacer algunos cambios cosméticos, y mejorar mucho, pero prefiero que quede de ésta forma ya que hace claro el funcionamiento de la estructura: IF-THEN-ELSE.
#Código Completo del Juego
cls : clg : fastgraphics : graphsize 500,500 x = 250 : y = 400 : a = 0 : bicho = 0 malo = 500 : vivo = true : salto = false tecla = 0 # numero de tecla presionada velocidad = -8 # velocidad del salto aceleracion= 0.2 # la fuerza del salto s=350 # Posición vertical del personaje WHILE vivo = true a = a - 20 imgload 250, 250 , 10 , "cieloSol" #fondo quieto de atras con sol imgload x + a, 250 , 10 , "fondo" : imgload x + a + 500 , 250 , 10 , "fondo" #fondoMueve if a <= -500 then : a = 0 : endif imgload 100, s , 5, lower(bicho) #dibuja al corredor, el valor vertical es: s bicho = bicho + 1 if bicho = 6 then : bicho = 0 : endif malo = malo - 20 #enemigo if malo < -500 then : malo = 1800 : endif imgload 500 + malo, 350 , 2 , "enemigo" #dibuja al enemigo if (500+malo) = 100 AND (salto = false) AND (s=350 ) then : vivo = false : endif #muerto? tecla = key #detecta que tecla esta presionada if (tecla=32) AND (salto=false) then#si esta presionado espacio, SALTA salto = true velocidad = -2 endif if (salto = true) then #si el personaje esta en el aire velocidad=velocidad + aceleracion s = s + velocidad*20 endif if s > 350 then #si el personaje esta en el piso, velocidad es cero s = 350 velocidad = 0 salto = false endif refresh : pause 0.03 : clg ENDWHILE #GAME OVER imgload 250, 230 , 10 , "enemigo" color red font "impact" , 80, 80 text 50,380 , "MUERTO!!!" refresh