jueves, 13 de octubre de 2016

Capítulo 77. Programando mi primer video juego en Small Basic Parte 1


Diario de un programador. Día 179

Programando mi primer videojuego en Small Basic. Parte 1


Por primera vez voy a hacer un juego completo, por lo tanto fue todo un desafío conseguirlo. Este juego, se supone que fue uno de los primeros (si no es que el primero) juegos de la historia. Se trata del juego tic tac toe, también conocido como tres en raya o gato, como suelen llamarlo por aquí donde yo vivo.

Aquí una imagen del juego:

El juego es para 2 jugadores. Al primer jugador le corresponden las X mientras que al segundo jugador le corresponden los 0.
En un principio me pareció sencillo, me dije ¿Qué tan difícil puede ser dibujar un par de rayas, unos círculos y unas equis y almacenarlas en una matriz?, sin embargo la cosa se me complicó desde el principio, ya que tuve que liarme en cómo hacer para que al primer clic saliera una equis, luego al siguiente clic (turno del otro jugador) saliera un circulo, o que no se permitiera hacer clic sobre una casilla que ya se encuentra ocupada,  o cómo hacer para alinear las figuras (equis y círculos) dentro de las casillas sin importar que el usuario haga clic en cualquier parte de ESA casilla, o no permitir que se dibujen figuras fuera de la matriz, o cómo hacer que el programa “entienda” que un jugador ha ganado y cuando lo haga, trazar una línea sobre sus figuras, etc, etc, etc. Como se podrán dar cuenta, son muchas las opciones que hay que tener en cuenta, pero aún así fue muy motivante y emocionante ver cómo este pequeño proyecto iba tomando forma.

EMPEZANDO DESDE CERO

Manos a la obra.
Lo primero que hice fue crear una subrutina a la cual llamé “inicio”, esta me va a permitir iniciar y reiniciar el juego. Al momento, esta es la única forma que conozco para volver a cargar o reiniciar una partida.
Esta subrutina contendrá los elementos iniciales del juego, por lo tanto, dentro de ella se ubicarán las coordenadas de las líneas, los colores, tamaños etc.
Voy a ir paso a paso así que este tutorial se podría extender un poco, pero como es mi costumbre, prefiero hacerlo de esta forma y así no dejar mayores dudas al respecto.
Entonces, de primera el código se vería de esta forma:

Sub inicio
 
  GraphicsWindow.Width = 370
  GraphicsWindow.Height = 300
  GraphicsWindow.PenWidth = 2
  GraphicsWindow.PenColor = "Green"
  GraphicsWindow.CanResize = "no"

EndSub

inicio()
Como se puede ver, es una subrutina con elementos que ya se habían visto antes. Se tiene una ventana con un tamaño de 370 x 300 pixeles. Luego con PenWidth, se ajusta el grosor del lápiz a 2, a este lápiz se le asigna un color verde “Green” (color que utilizaré para las líneas verticales y horizontales) y posteriormente se desactiva el redimensionamiento de la ventana con CanResize = “no”. Se da por finalizada esta subrutina con EndSub y posteriormente es llamada con inicio() para poder ver que se obtiene. Al ejecutar el programa, se debería ver algo así:


Lo siguiente que se debe agregar a esta subrutina son las líneas verticales y horizontales donde irán ubicadas las figuras. Para ello utilicé el siguiente código:

  'lineas horizontales
  GraphicsWindow.DrawLine(80,110,290,110)
  GraphicsWindow.DrawLine(80,170,290,170)

  'lineas verticales
  GraphicsWindow.DrawLine(150,60,150,220)
  GraphicsWindow.DrawLine(220,60,220,220)

Al ejecutar nuevamente el código, se puede apreciar la figura que se creó.

Ya por último, voy a crear una matriz de 3 x 3 dentro de esta subrutina, la cual me servirá para almacenar los valores que se vayan creando al momento de ir jugando.

  For fila = 1 To 3
    For columna = 1 To 3
      matriz[fila][columna] = 0
    EndFor
  EndFor

Esta matriz la llené con ceros. Pudo haber sido cualquier otro valor, yo quise llenarla con ceros simplemente para poder crearla.
A modo de ayuda, también generé un  comentario de la matriz para después saber cual espacio corresponde reemplazar posteriormente.
  'Matriz de 3 x 3 de ceros
  'X = 1
  'O = 9

  '1,1  1,2  1,3
  '2,1  2,2  2,3
  '3,1  3,2  3,3
Mi idea original era la siguiente: Crear una matriz de 3 x 3 y llenarla con ceros. Cuando una X seleccione una casilla,(por ejemplo la 2,2 de la matriz) el cero será cambiado por un 1. En cambio, si un círculo seleccionaba una casilla, el cero será cambiado por un 9. ¿Por qué? Porque, al llenar una fila, columna o diagonal con el número 1, ésta podría sumar 3, en cambio, al llenar una columna, fila o diagonal con 9, ésta podría sumar 27. Entonces, si el resultado de la suma de una fila, columna o diagonal entregaba un 3 o un 27, entonces habría un ganador. En un principio iba a escoger un 2 en vez del 9, pero rápidamente me di cuenta que no solamente sumando 1+1+1 daría un 3, sino que también 2+1 daría 3, finalizando el juego en forma inesperada. Por la misma situación tampoco podría escoger el 3... Así que sin pensarlo demasiado escogí el 9 para no darme mayores complicaciones, pudo haber sido el 4, 5, 6 etc.
Sigamos...
Antes de realizar todos esos cálculos, necesitaba crear las figuras. La idea era que al hacer un clic con el ratón en alguna parte del área del juego, se dibujara una X. Posteriormente, al segundo clic (turno del segundo jugador) se dibujara un O.
Así que vamos por parte. Lo primero es crear la X con un clic.
Aquí se me complicó un poco, porque una X, consta de dos líneas diagonales, que tenían que aparecer en el mismo lugar que apuntaba el ratón.
Bueno, para empezar creé un evento para poder dibujar las figuras.

GraphicsWindow.MouseDown = clicX

Este evento también lo incluí dentro de la subrutina “inicio”
Posteriormente hice la subrtutina que me permitiera dibujar la X. Lo que hice fue lo siguiente: Como una X consta de dos diagonales y una diagonal consta de 4 coordenadas(x1,y1, x2,y2), entonces necesitaba 8 coordenadas para dibujar la X.
Para que la cosa no se me complicara tanto fui paso a paso: Primero voy a simplemente a dibujar una X en la esquina superior izquierda cada vez que haga clic. Con el siguiente código debería ser suficiente:

Sub clicX
  GraphicsWindow.PenColor = "Blue"
  GraphicsWindow.DrawLine(0,0,30,30)
  GraphicsWindow.DrawLine(0,30,30,0)
EndSub

Con esto, al momento de hacer clic, aparece una X en la esquina superior izquierda.... Es un comienzo...

Dibujando la X parte 2

Ahora  que ya se puede dibujar la X, el siguiente paso sería lograr que la X apareciera en el mismo lugar donde se hiciera clic. Para ello tuve que modificar un poco el código y utilizar la propiedad MouseX y MouseY del objeto GraphicsWindow. Esta propiedad permite obtener las coordenadas X e Y del mouse, perfecto para lo que tratamos de hacer.  Ahora, la siguiente pregunta era como utilizar esa propiedad para dibujar la X. En primer lugar pensé: Para realizar una X necesito 8 coordenadas (4 por cada diagonal)y la propiedad MouseX y MouseY me entregan una coordenada cada uno (X e Y) ¿cómo hacerlo?, bueno, en esta parte utilicé papel y lápiz (algo que utilizo muy a menudo para resolver problemas así que lo recomiendo) y me puse a dibujar lo que quiero conseguir. En esta parte voy a representar aquel dibujo que hice en papel, con un dibujo que haré en paint.
Lo primero que pensé fue: "Bueno, con mouseX y mouseY puedo conseguir una coordenada, supongamos que mi mouse se encuentra en la posición x = 100 y en la posición y = 100."

"Entonces, si quisiera que se dibuje una diagonal de 30 pixeles justo en el centro de la flecha"

"A la posición X1 e Y1 debería restarle 15, para poder calcular la posición inicial"
"Y a la posición X2 e Y2 debería sumarle 15, para poder calcular la posición final"
 Entonces, para cada valor (x1,y1, x2,y2) debería crear una variable distinta y así poder guardar la posición del mouse con los valores +15 o -15 según corresponda
Esto lo hice de la siguiente manera:

  posX1 = GraphicsWindow.MouseX - 15
  posY1 = GraphicsWindow.MouseY - 15
  posX2 = GraphicsWindow.MouseX + 15
  posY2 = GraphicsWindow.MouseY + 15

Ahora, solo queda asignar esas variables a la operación DrawLine.

GraphicsWindow.DrawLine(posX1,posY1,posX2,posY2)

 Entonces, ahora la subrutina se ve de esta forma:

Sub clicX
  GraphicsWindow.PenColor = "Blue"
  posX1 = GraphicsWindow.MouseX - 15
  posY1 = GraphicsWindow.MouseY - 15
  posX2 = GraphicsWindow.MouseX + 15
  posY2 = GraphicsWindow.MouseY + 15
  GraphicsWindow.DrawLine(posX1,posY1,posX2,posY2)
 
EndSub

Al ejecutar el programa, se puede apreciar que realmente dibuja una línea diagonal en el mismo lugar donde hacemos clic y además de que queda centrada respecto a la flecha del mouse.


Muy bien, ahora que podemos dibujar una diagonal. Agreguemos el código para poder dibujar la otra diagonal y así formar la X. Esto quedaría de la siguiente forma:

  posA1 = GraphicsWindow.MouseX + 15
  posB1 = GraphicsWindow.MouseY - 15
  posA2 = GraphicsWindow.MouseX - 15
  posB2 = GraphicsWindow.MouseY + 15

Si agregamos esto a la subrutina, entonces quedaría de la siguiente forma:

Sub clicX
  GraphicsWindow.PenColor = "Blue"
  posX1 = GraphicsWindow.MouseX - 15
  posY1 = GraphicsWindow.MouseY - 15
  posX2 = GraphicsWindow.MouseX + 15
  posY2 = GraphicsWindow.MouseY + 15
  posA1 = GraphicsWindow.MouseX + 15
  posB1 = GraphicsWindow.MouseY - 15
  posA2 = GraphicsWindow.MouseX - 15
  posB2 = GraphicsWindow.MouseY + 15
 
  GraphicsWindow.DrawLine(posX1,posY1,posX2,posY2)
  GraphicsWindow.DrawLine(posA1,posB1,posA2,posB2)
EndSub

Al ejecutar el código podemos ver como se dibuja nuestra X, quedando centrada con respecto al mouse.


Debido a lo extenso que resulta explicar este programa, tendré que dividirlo en varias partes, pero pronto subiré la segunda parte para así continuar con la construcción de este juego. Saludos

Gustavo J. Cerda Nilo
Julio 2016, Octubre 2016



6 comentarios:

C++ El apuntador This

El apuntador This En C++, cada objeto tiene acceso a su propia dirección a través de un puntero o apuntador denominado This. Lo...