Curso “Programación de Juegos”
Curso Gratuito con codigo fuente.
Entrega 7. Juego completo "El minero"
Curso Gratuito con codigo fuente.
Entrega 7. Juego completo "El minero"
Juego “El
Minero”
Ahora vamos a empezar a aplicar lo que aprendimos en las notas anteriores para armar un pequeño y simple programa, en el que vamos a controlar a un “minerito” que excava en la montaña buscando oro y diamantes.
Ahora vamos a empezar a aplicar lo que aprendimos en las notas anteriores para armar un pequeño y simple programa, en el que vamos a controlar a un “minerito” que excava en la montaña buscando oro y diamantes.
Pero la tarea de nuestro minero no es fácil ni está exenta de peligros:
debe excavar en la montaña creando túneles para poder llegar a los tesoros y en
su camino puede toparse con paredes de roca sólida. Al mismo tiempo la montaña
esconde depósitos de dinamita explosiva, que si son movidas por el minero
explotan y le restan vida.
A medida que el minero recoge oro y diamantes, se incrementa un
contador de puntos. Si llega a los depósitos de dinamita, hay una explosión
(con un efecto mínimo) y se restan puntos de su vida.
En esta ocasión no están grabados los records ni los nombres de los
concursantes. Sería algo simple de hacer, pero como quiero enfocarme en el
desarrollo de las rutinas del juego, no las incluí (por ahora).
El juego tiene la misma
estructura que los anteriores:
1) Inicialización de variables, declaraciones de subrutinas y funciones
2) Dibujo de pantalla
3) Bucle de ejecución con llamadas para capturar los eventos del
programa
Empecemos:
La estructuras GetColision%() y Dibuja.Pantalla () ya fueron tratadas en las notas anteriores y siguen vigentes cumpliendo las mismas funciones.
La estructuras GetColision%() y Dibuja.Pantalla () ya fueron tratadas en las notas anteriores y siguen vigentes cumpliendo las mismas funciones.
La única diferencia ahora es que la función GetColision%() nos informa
sobre el tipo de colisión que tiene el minero.
En los programas anteriores simplemente nos interesaba saber que el
cursos chocaba con algo, ahora nos interesa saber contra qué choca el minero:
- si choca contra la roca = no puede atravesarla
- si es arena = puede excavarla
- si es dinamita = se debe generar una explosión (y además pierde puntos)
- si es oro = suma una cierta cantidad de puntos
- si es diamante = suma otra cantidad de puntos
Esto lo resolvemos haciendo que la función GetColision%() detecte la
colisión y nos devuelva un número especial para cada colisión generada.
¿Se pone interesante, verdad?
Para cuando hay que sumar puntos, nos ayuda una subrutina nueva: Asigna.Puntos
(TipoColision%). Esta subrutina trabaja en la asignación (suma o resta) de
puntos, de acuerdo a la colisión. Además cumple una función secundaria pero no
menos importante: si la colisión es con dinamita, genera el efecto de la
explosión (muy simple, por supuesto)
Todo está trabajado en gamas de grises. No he implementado color para
concentrar su atención en el desarrollo.
Están las variables usuales que implementamos enteriormente:
INTEGER c, f para controlar las dimensiones generales de la pantalla y
usadas por el sistema de control de movimientos generales que evita que nos
salgamos de pantalla.
STRING KeyPress para detectar nuestrto teclado (aún no hemos
implementado mouse)
INTEGER FlagColision que es un flag que alerta sobre una colisión
detectada
STRING Screen$(4 TO 20) para dibujar la pantalla con sus detalles
INTEGER Colision% para detectar una
colision
Han aparecido nuevas variables:
INTEGER Puntos para sumar o restar puntos a la labor de nuestro minero
INTEGER Tiempo para darle emoción al trabajo. Asigna un tiempo límite
al trabajo de nuestro minero (para ver como se comporta bajo “presión”)
INTEGER Objetos lleva la cuenta de los objetos encontrados por el
minero (en este juego hay 17 objetos disponibles entre pepitas de oro y
diamantes)
Hasta el bucle DO/LOOP todo es claro para el programador de juegos en
que se ha convertido (¿verdad?) o por lo menos… así debería ser… La única
diferencia es que la pantalla ahora tiene un tipo de dibujo más creativo y hemos
asignado un dibujo (carácter ASCII) diferente a cada objeto que hay en
pantalla. Cuando se produzca el evento de colisión, la rutina detectora de la
colisión, nos informará contra qué chocó nuestro minero y eso hara que el
programa se comporte de diferentes modos:
- si choca contra roca le impedirá perforarla (probablemente se le rompa el martillo o el pico que use), pero lo cierto es que se impedirá el movimiento del minero
- si choca contra arena…. Simplemente el programa le permitirá pasar dejando un hueco porque nuestro minero va creando un tunel de extracción de minerales preciosos…
- si choca contra una pepita de oro o un diamante, incrementará su fortuna
- si encuentra un cartucho de dinamita mientras va picando con su herramienta… volará el peluquín de nuestro amigo (no le matará para no ser trágicos)… pero perderá parte de la fortuna encontrada
¿Cómo se logra ese comportamiento? Pues a través de ciertas rutinas
implementadas en cada detección de tecla. Veamos un ejemplo (usted puede
descifrar los otros)
Dentro del DO/LOOP está la rutina que detecta la tecla presionada:
KeyPress = UCASE$(INKEY$)
La variable KeyPress es analizada por los IF siguientes (Estructura If –
elseif –elseif, etc)
Analicemos el evento de oprimir la tecla
CURSOR UP:
IF KeyPress = CHR$(0) +
CHR$(72) AND f > MnFila THEN
' si el jugador presionó cursor arriba y no se
ha salido del límite respectivo de pantalla
' recuerde
que la comparación [ AND f > MnFila ] analiza si el movimiento es válido y
' no ha superado
el límite de pantalla. En caso de que el movimiento salga de pantalla
'es ignorado por
el programa y el minero no se mueve una décima de centímetro
Colision% = GetColision%(f - 1, c)
' Si el movimiento
es válido, se verifica si hay una colisión.
'Para eso tenemos
estas variables, que son retornadas por GetColision%
' CONST Nada = 0 'no ha colisionado con nada
' CONST Roca = 1 'colision con roca (impasable)
' CONST Arena = 2 'colision con arena (puede atravesarla)
' CONST Oro = 3 'encontro oro (suma puntos)
' CONST Diamante = 4 'encontro un diamante (suma puntos)
' CONST Dinamita = 5 'encntro dinamita escondida (resta puntos)
SELECT CASE Colision% 'dependiendo de
GetColision% el programa toma decisiones:
CASE No, Arena, Oro, Diamante, Dinamita
'en estos
casos se hace el movimiento y hay que cambiar la posición del minero en
'la pantalla,
lo que se hace borrando primero al minero con estas dos instrucciones
LOCATE f, c
PRINT " "
'luego se
mueve su posición una linea hacia arriba en la pantalla
f = f - 1
CASE Roca
' el el caso de que haya colisionado con una
roca…no hay movimiento! Nuestro
'minero no
tiene herramientas para romper la roca…
END SELECT
'dependiendo
también del tipo de colisión esta rutina asignará puntos cuando
'corresponda.
También los restará si chocó con una dinamita… (cuidado)
CALL Asigna.Puntos(Colision%)
'se reinicializa
el flag de colisión para hacer una nueva detección de movimiento
FlagColision = No
Las otras rutinas para las otras tres teclas de cursor, trabajan de la
misma manera.
Al terminar el IF/END nos encontramos con la opción de cortar el juego
en cualquier momento al presionar ESCAPE
ELSEIF KeyPress = CHR$(27)
THEN EXIT DO 'escape
END IF
Al salir del IF/END IF no encontramos con la variable de tiempo para
ver si superamos el tiempo límite que le hemos dado al minero para cumplir con
su tarea:
Tiempo = Tiempo – 1
Las sentencias que siguen son de “refresco de pantalla” o actualización
de datos, sencillas de entender.
Más abajo en el programa, tenemos una sentencia que corta el programa cuando
se agota el tiempo programado
IF Tiempo < 1 THEN EXIT
DO
Analicemos la Rutina Asigna.Puntos
(TipoColision%)
DIM z%, fila%, columna%
IF TipoColision% = Oro THEN
' si el minero
encuentra oro suma puntos….(guardados en la variable “Oro”)
Puntos = Puntos +
Oro
'…y hay un objeto
menos para descubrir
Objetos = Objetos
- 1
ELSEIF TipoColision% =
Diamante THEN
' si el minero
encuentra diamantes suma puntos….(guardados en la variable
' “Diamante”)
Puntos = Puntos +
Diamante
'…y hay un objeto
menos para descubrir
Objetos = Objetos
- 1
ELSEIF TipoColision% =
Dinamita THEN
Puntos = Puntos -
Dinamita
'…si encuentra
dinamita, se le resta puntos (pierde vida)
'y también se
genera el efecto de explosion
FOR z% = 1 TO 100
LOCATE f - 1, c - 1: PRINT "***"
LOCATE f, c - 1: PRINT "***"
LOCATE f + 1, c - 1: PRINT "***"
LOCATE f - 1, c - 1: PRINT " "
LOCATE f, c - 1: PRINT " "
LOCATE f + 1, c - 1: PRINT " "
NEXT z%
'finalmente se reescribe
la pantalla para evitar la presencia “fantasmal” de objetos
'que no están en
la pantalla (a la vista) pero que permanecen en memoria ram
'y generarían efectos
indeseable (vea las notas 5 y 6 – el “BUG” del programa)
LOCATE f - 1, c -
1: PRINT MID$(Screen$(f - 1), c - 1, 3)
LOCATE f, c - 1:
PRINT MID$(Screen$(f), c - 1, 3)
LOCATE f + 1, c -
1: PRINT MID$(Screen$(f + 1), c - 1, 3)
END IF
END SUB
Queda el análisis de la función GetColisión%, que ahora esta programada
para avisar del tipo de colisión que se hace entre un objeto y nuestro amigo
minero:
La estructura SELECT/CASE es la encargada de leer el punto de pantalla
en el que se produce el choque. Lo hace extrayendo de la memoria RAM el
contenido de la pantalla con la función MID$
SELECT CASE MID$(Screen$(fila%), columna%, 1)
Una estructura IF/END IF analiza el carácter ASCII encontrado y
determina si es arena, roca, diamante, oro o dinamita…. o si no hay colisión
alguna.
IF
MID$(Screen$(fila%), columna%, 1) = "°" THEN
GetColision% = Arena
ELSEIF
MID$(Screen$(fila%), columna%, 1) = "" THEN
GetColision% = Dinamita
ELSEIF
MID$(Screen$(fila%), columna%, 1) = "Ü" THEN
GetColision% = Oro
ELSE
GetColision% = Diamante
END
IF
Conclusiones
Si lo analiza un poco, ya hemos abierto la “caja de pandora” y ahora
depende de usted mismo.
Con esta misma base de elementos, técnicas y rutinas, usted puede
implementar:
2) Programas de tipo PacMan pero sin enemigos dinámicos. Recuerde que todavía no implementamos enemigos (lo haremos por primera vez en la nota 9)
3) Programas de tipo aventura (incluso podría ser conversacional), porque a partir de un plano se pueden además generar más de un nivel (que incluya varios planos o pisos) implmementando adicionalmente variables bidimensionales en donde el primer indice indique el piso: Screen$(piso, fila) y con pequeñas modificaciones podemos hacer que nuestro heroe “salte” de piso a piso al llegar a una posición que tenga una escalera que suba o baje de nivel.
4) Programas del tipo “calabozos y dragones” simples sin enemigos.
Esto es todo por ahora.
Como puede ver… muy rápidamente se puede crear un juego simple con poquitos
conocimientos nuevos.
Todavía hay grandes cantidades de técnicas por ver y analizar. Vamos a
encarar (quizá ya en la nota próxima) la creación de enemigos que trabajen con
voluntad propia (bots) para darle un poco más de dinámica a estos juegos, que
no por ser simples dejan de ser interesantes.
Hasta la proxima entrega.
----------------------------------------------------------------------
Curso Gratuito de Programación de VideoJuegos1. Introducción
2. A quienes va dirigido el curso
3.Temario del curso / Herramientas
4.Primer programa (codigo fuente)
5.Detectando colisiones y comiendo objetos
6.Eliminando el bug de nuestro programa
7.Juego completo "El Minero"
8.La I.A. ( Inteligencia artificial ) en los juegos
9.La generación de bots enemigos en el juego
6.Eliminando el bug de nuestro programa
7.Juego completo "El Minero"
8.La I.A. ( Inteligencia artificial ) en los juegos
9.La generación de bots enemigos en el juego
----------------------------------------------------------------------
Por Ricardo Ponce
Links de Interés:
Cursos de Formación Profesional
Toda la oferta de cursos
Libros Gratuitos para Usted
Nuestro Canal YouTube
Toda la oferta de cursos
Libros Gratuitos para Usted
Nuestro Canal YouTube
Servicio Técnico en Sistemas, Redes y CiberSeguridad
Márketing en Internet y Redes Sociales
Su Aula Virtual en Internet
Su Taller en Internet
Su empresa en Internet
No hay comentarios:
Publicar un comentario