viernes, 14 de octubre de 2016

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

Continuación del capítulo anterior...


Ya que tenemos esto, lo siguiente será crear la figura de los círculos. El proceso para crear el círculo es similar al utilizado para crear la X, entonces para crearlo se me ocurre agregar lo siguiente a la subrutina:

  GraphicsWindow.PenColor = "Red"
  GraphicsWindow.DrawEllipse(posX1,posY1,30,30)

La subrutina quedaría entonces de la siguiente manera:

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)
 
  GraphicsWindow.PenColor = "Red"
  GraphicsWindow.DrawEllipse(posX1,posY1,30,30)
EndSub


Al ejecutar y probar el código veo lo siguiente:


Veo que el círculo aparece en la misma posición que la X. Bueno, esto era de suponer ya que ambas instrucciones están en la misma subrutina. Ahora la idea es que aparezcan en forma alternada, o sea que al hacer un clic aparezca una y luego, al hacer otro clic aparezca la otra y así sucesivamente.
 Pero antes, lo que debo hacer es separar estas instrucciones, para que se ejecuten por separado. Se me ocurre que debería dejarlas en subrutinas independientes, de modo que al hacer clic, se llame a la subrutina que contiene la X y al hacer otro clic, se llame a la que contiene el círculo.
Entonces, esto quedó de la siguiente manera:

Sub FiguraX
  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


Sub FiguraO
  posX1 = GraphicsWindow.MouseX - 15
  posY1 = GraphicsWindow.MouseY - 15 
  GraphicsWindow.PenColor = "Red"
  GraphicsWindow.DrawEllipse(posX1,posY1,30,30)
EndSub

Ahora, para llamar a cada subrutina en forma independiente, lo hago de la siguiente manera:

Sub clicX
  FiguraX() 
EndSub

Al ejecutar el código, veo que solamente se dibuja la X y si cambio FiguraX() por FiguraO()

Sub clicX
  FiguraO() 
EndSub

Entonces se dibujan los círculos.
Ahora, la pregunta es cómo hacer para que aparezcan en forma alternada. Lo que se me ocurre es crear una variable auxiliar, la cual vaya aumentando uno en uno cada vez que se haga clic, entonces, si el número es impar, se dibujará la X y si el número es par se dibujará el circulo... ¿Quién diría que uno de los primeros códigos que aprendí me sería útil? Jajaja
Para implementar lo anteriormente expuesto, primero crearé una variable auxiliar a la cual llamaré "interruptor" y la inicializaré con el valor de 1, para que empiece dibujando las X ( X números impares y O números pares)
interruptor = 1
Esta variable quedará ubicada dentro de la subrutina "inicio" para que se inicialice a penas empiece el programa y que cada vez que el juego se reinicie, su valor vuelva a 1.


Ahora, para saber si el valor de la variable interruptor es par o impar, agregamos el siguiente código (que ya a estas alturas debe de ser ultra archi conocido) dentro de la subrutina ClicX, quedando de la siguiente forma:

Sub clicX
  If Math.Remainder(interruptor,2) <> 0  Then
    figuraX()
  EndIf
  If Math.Remainder(interruptor,2) = 0 Then
     figuraO()
  EndIf 
EndSub

Muy bien, pero aún falta hacer que la variable interruptor vaya aumentando su valor cada vez que se hace clic, para ello voy a agregar lo siguiente al final de la subrutina clicX:

Sub clicX
  If Math.Remainder(interruptor,2) <> 0  Then
    figuraX()
  EndIf
 
  If Math.Remainder(interruptor,2) = 0 Then
     figuraO()
  EndIf 
  interruptor = interruptor + 1
EndSub

Al ejecutar el programa, se puede ver que ahora cambia la figura cada vez que se hace clic


Para saber cómo se va actualizando la variable interruptor o cualquier otra variable, yo siempre ocupo la instrucción TextWindow.WriteLine, de esta forma puedo saber que está ocurriendo dentro del programa. Por ejemplo, si agrego la instrucción TextWindow.WriteLine de esta forma:

Sub clicX
  If Math.Remainder(interruptor,2) <> 0  Then
    figuraX()
  EndIf
 
  If Math.Remainder(interruptor,2) = 0 Then
     figuraO()
  EndIf 
  interruptor = interruptor + 1
  TextWindow.WriteLine(interruptor)
EndSub

Puedo saber  que está sucediendo con esa variable y verificar si realmente está cambiando su valor. Esto es especialmente útil cuando nos damos cuenta que algo no funciona y necesitamos ver si tal variable o elemento está haciendo su trabajo como debiese de hacerlo o como nosotros queremos que lo haga.

Ya que se tiene certeza de que funciona, se puede proceder a borrar dicha línea.

ALINEANDO LAS FIGURAS

Ahora que ya se pueden dibujar ambas figuras en forma alternada, lo que debemos hacer ahora es alinearlas dentro del campo de juego, o sea, dentro de las casillas formadas por las líneas horizontales y verticales, no permitiendo que se dibujen fuera de ellas. Lo que se me ocurrió fue lo siguiente: (volviendo al lápiz y al papel)
Toda la zona enmarcada es la que considero "dentro del juego"
Así que si el jugador hace clic dentro de esta zona, entonces se considerará un clic válido. Supongamos que el jugador hace clic dentro de la siguiente zona:
Si el jugador hace clic en cualquier parte de la zona marcada con color rojo, entonces la X (que es la primera jugada) se debe ubicar y centrar dentro de esa casilla. Como dijimos, si hace clic fuera de la zona del juego, no se debe dibujar nada. Entonces, la zona de color, se encuentra ubicada en ciertos rangos de coordenadas X,Y que tenemos que hallar. Si se hace clic dentro de ese rango, entonces la figura se dibuja. Ese rango de coordenadas, lo podemos saber según las coordenadas que les dimos a las líneas verticales y horizontales ubicadas en los siguientes sectores:
'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)
Con esto obtenemos el primer rango que corresponde a X. El rango de X será entre 80 a 150 pixeles
Ahora por el rango de Y:
'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)
Con esto obtenemos el segundo rango que corresponde a Y. El rango de Y será entre 60 a 110 pixeles
Entonces, cuando el jugador haga clic dentro de este rango, lo que haremos será ubicar la X en el centro de esta casilla, (o lo más cercano a este). Para lograr esto propongo el siguiente código el cual modifica la subrutina figuraX y posteriormente la subrutina figuraO:

Sub FiguraX
  GraphicsWindow.PenColor = "Blue"
  gmX = GraphicsWindow.MouseX
  gmY = GraphicsWindow.MouseY
 
  'ubicacion 1,1
  If gmX >= 85 And gmX <= 145 And gmY >= 65 And gmY <= 105 Then
      GraphicsWindow.DrawLine(100,70,130,100)
      GraphicsWindow.DrawLine(100,100,130,70)
  EndIf
EndSub

Como se puede apreciar, tanto al rango de X como al rango de Y, le hice una pequeña modificación de 5 pixeles simplemente para dejar espacio entre la casilla y las líneas verticales y horizontales.
Entonces, si se hace clic dentro del rango establecido, se debería dibujar la X en el centro de la casilla. Al probar el código vemos que funciona:
Bueno, dejaré este tutorial hasta aquí el día de hoy, para poder continuar con la tercera parte en el próximo post. Saludos

Gustavo J. Cerda Nilo
Julio 2016, Octubre 2016




2 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...