lunes, 16 de mayo de 2016

Curso de Juegos (5)

Curso “Programación de Juegos”

Curso Gratuito con codigo fuente.
Entrega 5.


Detectando colisiones en los programas y comiendo objetos

Nota: Al final de este artículo está el link de descarga para este nuevo programa (02.Bas) y los links a todas las notas del curso

En el programa anterior (01.BAS) aprendimos a delimitar un escenario y a controlar el movimiento de un objeto en la pantalla.

A ese mismo programa, ahora le agregaremos un par de funcionalidades especiales:

  • La detección de una colisión de nuestro carácter-sprite con algún objeto en pantalla
  • La suma de puntos por cada colisión del carácter-sprite.

La detección de colisiones es importante en un videojuego porque puede servir para crear comportamientos diversos:
  • Evitar que un jugador atraviese un muro o algún objeto sólido de pantalla que debe comportarse como un obstáculo
  • Saber si un jugador ha podido “tocar” algún objeto para asignarle o quitarle puntos. Piense en juegos como el  pac-man en donde algún come-cocos alcanza al jugador y le debe restar vidas o puntos, o en juegos de guerra en donde el jugador atraviesa alambrados y le disminuyen vida en la partida, por ejemplo.
  • Juegos en donde algún disparo o meteorito alcanza al jugador.
  • Juegos en donde el jugador alcanza un objeto que debe sumar algo.
En nuestro juego, ahora vamos a hacer justamente esto último: cuando nuestro carácter-sprite alcance un objeto de la pantalla, se lo “comerá” para hacerlo desaparecer de la vista y sumar un punto para el jugador que controla al caracer-sprite.

Las colisiones pueden ser tan complejas como lo necesite el juego. En las pantallas gráficas las técnicas de colisiones pueden ser un poco más complejas, pero en definitiva se trabajan con rutinas semejantes.

Le recuerdo que estamos trabajando con pantallas de tipo texto para justamente, aprender lo básico de las técnicas, pero mi idea es hacer escalar este curso al entorno gráfico, así podrá ver que no es tan difícil aprender a programar videojuegos si lo hace paso a paso.

Que necesitamos para detectar colisiones

Para lograr esto, vamos a crear un par de variables auxiliares y una función que nos ayudarán con la gestión de mensajes en el sistema (Digo sistema porque esto ya comienza de a poco, a ser un programa complejo)

Variables auxiliares [CONST Si = 1]  y [CONST No = 0] estas son variables constantes que por defecto también son globales y la única función que tienen es permitir crear una respuesta lógica boooleana del tipo SI / NO para distintas respuestas en funciones y delimitar comportamientos definidos sin confusiones provocados por valores numéricos.
 
Variable auxiliar [DIM Puntos AS INTEGER] esta variable sirve para controlar los puntos adquiridos en cada colision. Puede sumar o quitar puntos dependiendo de cómo quiera usted realizar el comportamiento del juego.

Variable tipo Flag (o bandera) [DIM FlagColision AS INTEGER] esta es una variable tipo flag que puede tener dos valores: SI o NO.  Nos alerta en el programa sobre una colision detectada en un momento determinado. En este caso en particular, es usada en tiempo real para evitar que el sistema sume puntos indiscriminadamente y sin límite.

Ya vimos en la nota anterior que durante la ejecución de cada bucle DO/LOOP, el sistema controla si el usuario ha efectuado un movimiento y realiza el ajuste de la posición o coordenada de pantalla a través de las variables c (columna) y f (fila).

En el momento exacto en que se realiza un ajuste de alguna de esas variables (c / f), el sistema pone a FlagColision en NO cuando el usuario ha realizado un movimiento.

Al terminar de evaluar la condición de movimiento del usuario (en el bloque If /Else dentro de Do/Loop), el sistema procederá a verificar si con la nueva posición del carácter-cursor del usuario existe una situación de colisión a través de la función GetColision% (vea más adelante).

Al detectarse esa colisión la función retornará el estado SI, por lo cual el sistema inmediatamente sumará un punto por colisión y además pone el flag en estado NO para evitar que se vuelva a sumar puntos. De este modo se evita sumar más de un punto por colisión.

Esto se hace en cualquiera de los 4 movimientos previstos (arriba, abajo, derecha, izquierda). Vea en el codigo fuente la asignación [FlagColision = No] en cada condición de movimiento:

ELSEIF KeyPress = CHR$(0) + CHR$(77) AND c < MxCol THEN
         'derecha
         LOCATE f, c
         PRINT " "
         c = c + 1
         FlagColision = No 


Si quita esa condición (
FlagColision = No), verá que cuando se realice una colisión, el sistema sumará puntos indiscriminadamente hasta que usted proceda a quitar de la posición de colisión al carácter-sprite que estamos usando en el programa. Este flag limita de ese modo a la suma (o quita de puntos, según como planifique usted su programa) a sólo una vez durante la colisión detectada.

Cómo trabaja la función GetColision%

La Función [FUNCTION GetColision% (fila%, columna%)] es la encargada de detectar cuándo se produce una colisión del carácter-sprite con algún objeto dibujado en pantalla.

En el bucle Do/Loop, después de evaluar los movimientos del usuario con el bloque de instrucciones If/Then, el programa evalúa la nueva posición del carácter-sprite para ver si se produjo alguna colisión en la pantalla. Esto se hace invocando a la función enviando las coordenadas nuevas del carácter-sprite a través de los nuevos valores de las variables (c y f), mediante la invocación  [IF GetColision%(f, c) = Si THEN]

Si la función detecta que se produjo una colisión, devuelve SI, si no hay colisión, devuelve NO.

Para detectar la colisión, la función hace una evaluación de variables.

Las variables [Screen$(4 TO 20)] son las que tienen en su interior el dibujo completo de la pantalla del usuario. Fueron definidas en el bloque “Dibujar Pantalla Inicial” (vea la estructura de este programa en la nota anterior), justo antes del bucle Do/Loop.
 
Como puede ver en el código fuente, se han definido dentro de las variables a los obstáculos que hay en la pantalla como [X].

Las variables Screen$() están ajustadas exactamente para que el sistema, al calcular la fila actual del carácter-cursor, coincida con el valor de la variable Screen$(fila) que contiene los objetos dibujados en esa pantalla. 

Cuando el sistema hace la la evaluación IF de este modo: 

IF MID$(Screen$(fila%), columna%, 1) <> " " THEN
 
Lo que hace en realidad es mirar dentro de la variable Screen$(Fila) en el carácter de columna% para ver si NO está vacío (“ “) a través de la condición [<>]

En el caso que haya algun objeto dibujado en esa posición que es la posición fila-columna del carácter-sprite, devuelve un SI, indicando que se ha realizado una colisión en la pantalla.

En caso que la rutina determine que el espacio “apuntado” por fila-columna está vacío, retorna un NO indicando que la posición está libre y no se ha realizado una colisión en el juego.

Un desafío para usted: el pequeño BUG a depurar

Este programa aún no está completo. Tiene un pequeño “Bug” que no fue depurado para ver si usted es capaz de eliminar ese pequeño error por sus propios medios. No se enoje, si desea programar juegos, constantemente deberá depurar errores de diferente magnitud.
Depurar y corregir es un buen método para aprender a programar y mejorar como desarrollador.

¿En qué consiste el BUG de este programa? Bueno, como verá usted, en cada colisión, el carácter-sprite se “come” al obstáculo representado en este caso por la [X], y al hacerlo, se aumenta en uno la puntuación del usuario, pero resulta ser que por el método de dibujado de pantalla que hemos empleado en este programa, en realidad, las [X] se borran de la pantalla, pero “persisten” dentro de las variables Screen$(filas). 

Esto trae como consecuencia la presencia del BUG que deberemos “depurar”: cuando el carácter-sprite vuelve a pasar por la posición en donde había una X, la rutina de detección de colisiones vuelve a detectar una colisión aunque no hay nada en la pantalla. Reacciona ante el FANTASMA del obstáculo que persiste dentro de la variable.

La solución sería borrar la [X] también de las variables Screen$(filas) cuando se produce una colisión.

Bueno ahora ya sabe cuál es el bug del programa y lo que debe hacer para solucionarlo. ¿Se siente capaz de hacerlo? Espero que sí… y que sea capaz de eliminar el error.

La próxima entrega

En la próxima entrega, le daré una solución al bug planteado por si no lo logró.


Y más tarde ( cuando publiquemos la nota 7), haremos una pequeña modificación a este programa, transformándolo a un programa en donde un pequeño “minero” vaya excavando la montaña para llegar a depósitos de oro y piedras preciosas dentro de la mina, incrementando su fortuna.

Usaremos todas las técnicas planteadas hasta ahora y verá que con tan “poquitos” conocimientos, se pueden lograr programas de juegos rápidamente…. Y con sus propios medios, sin depender de librerías de terceros.


  ----------------------------------------------------------------------
  Curso Gratuito de Programación de VideoJuegos

http://profesorponce.blogspot.com.ar/p/libros-publicados.html


 

No hay comentarios:

Publicar un comentario