Trucos sobre manejo de softwarelibre y gnu linux. También a los programas que hago en gambas3, python, java, etc.... Consejos y trucos sobre otros programas: excel, word, internet, instalación de programas, Arduino y demás....
Dedicado a mis proyectos en Gambas ,un lenguaje de programación parecido al Visual Basic + Java pero ampliamente mejorado y...¡¡para gnu/linux!!.La potencia del gnu/linux sumada a la facilidad del Basic
Consultas, Desarrollo de programas y petición de presupuestos:
Normalmente en los juegos de ruleta online, nos muestran un marcador sobre los números que salen, y los van colocando en 3 columnas: los números Rojos, el Cero, y los números Negros. Pues he hecho un programa para que también veamos la distribución de los números que salen por: Columnas(o filas), Docena, Par-Impar, 1-18 y 19-36 y por supuesto Rojo y Negro.
Os dejo un video para que lo veais en funcionamiento:
Desarrollo de Juegos de Tablero (6): Control de Partida: Eventos Y Observadores
En este artículo describiré la forma de como programar cuando una ficha/personaje llegue a una casilla y que el programa haga algo (mostrar un mensaje, dar una penalización o premio, etc.). Para ello vamos a usar la programación orientada a eventos, mediante el mecanismo de definir eventos y observadores. Creo que esta es la forma más genérica de programarlo y que luego admitirá añadirle más cosas o interacciones en el juego, aunque también se podría haber programado usando el Patrón Chain Of Responsibility: Cadena de Responsabilidad
Vamos a la explicación:
1. Tenemos una clase llamada "Control de partida", que estará observando lo que ocurre en la partida, en este ejemplo va a observar a los jugadores que haya.
Esta clase tiene definido un observador:
Private
ObservadorControl
As Observer
También tiene un método llamado "addobservador", al que le pasamos un array de jugadores que debe de observar.
PublicSubaddObservador(pAsObject[])
'En
nuestro caso las piezas a vigilar son las piezas de los jugadores DimobjetoTmpAsObject ForEachobjetoTmpInp
Ahora queremos que cuando se produzca un evento "_Llegue" de un jugador, aparezca un mensaje en el programa, con el nombre del jugador y la casilla a la que ha llegado. Se programaría asi:
PublicSubObservador_LLegue(jugAsObject,NumeroCasillaAsInteger) DimmensajeAsString 'muestro
datos del objeto
mensaje=("El
jugador")&"
"& jug.nombre&",
"&("ha
llegado a la casilla nº:")&"
"&NumeroCasilla Message.Info(mensaje) End
2. Vamos a añadir el código necesario para la clase Jugador.
La clase jugador debe de producir el evento _Llegue, cuando sepa que ha llegado a la casilla.
Para ello tenemos que hacer 3 cosas:
2.1. Definir el evento _llegue
EventLLegue(piezaAsObject,NumeroCasillaAsInteger)
2.2. Hacer saltar el evento, cuando llegue a la casilla:
RaiseLlegue(Me,NumeroCasilla)'informo
de que jugador a llegado a la casilla NumeroCasilla
2.3. ¿Cuando sabe el jugador que ha llegado a la casilla? Bien, eso lo sabe a traves su objeto miPiezaAnimada (de la clase PiezaAnimada). Esta clase en su método actualizaPosicion(), sabe cuando ha llegado a la casilla destino y cambia la animación a "miEstado.Parado". Lo que vamos a hacer, es en la parte del jugador:
2.3.1 Observar ese objeto "miPiezaAnimada", añadiendole un observador en el jugador
2.3.3 Y que cuando reciba un evento de miPiezaAnimada (que lo vamos a llamar _LlegadaCasilla), dispare el evento que _Llegue(), para que sea escuchado por el control de juego:
'informo
de que jugador a llegado a la casilla NumeroCasilla
End
2.3.4. Ahora en la clase PiezaAnimada, hay que añadirle:
2.3.4.1 Un evento "_llegadaCasilla"
EventLLegadaCasilla(NumeroCasillaAsInteger)
2.3.4.2. Que se dispare cuando llegue a una casilla destino. Eso lo hacemos añadiendo al método actualizaPosicion(), el lanzamiento del evento _LlegadaCasilla:
PublicSubactualizaPosicion() IfcasillaFinal=casillaInicialThenReturn'a
llegado a la casilla de destino contadorA+=1
'lanzar
evento de llegada a la casilla destino por parte de la pieza. '--------------------------------------------------------------------------
RaiseLLegadaCasilla(Me.CasillaActual()+1) Endif End
Resumiendo:
El mecanismo programado funciona así:
Cuando la clase piezaAnimada llegue a la casilla destino, produce un evento _LlegadaCasilla.
Este es escuchado por el jugador, y produce otro evento _Llegue.
Este evento _Llegue es escuchado por el Control de Juego, que nos muestra un mensaje por pantalla dando el nombre del jugador y de la casilla a la que ha llegado.
En los próximos artículos veremos como implementar las reglas del juego, por ejemplo:
- Cuando llegue a una casilla roja, retroceda 2 casillas
- Cuando llegue a una casilla azul, se haga una pregunta, y si acierta gane 2 puntos.
- el objetivo del juego, será llegar a la casilla 43 ( el tesoro) y mostrar cuantos puntos ha tenido el jugador.
Desarrollo de Juegos de Tablero (4 y 5): Autómata para Animación del personaje y/o fichas (4º parte)
En esta entrada, vamos a desarrollar varias animaciones para el personaje. Nuestro personaje va a tener 3 estados:
- Parado
- Andando hacia la izquierda
- Andando hacia la derecha
Cada estado tiene su propia animación, con lo cual nuestro personajes o fichas, las tienes que ir almacenando. El estado inicial del personaje es "Parado", y si se mueve a una casilla cambia de estado. Si por ejemplo, va hacia la derecha de la pantalla, su estado cambia a "Andando hacia la derecha", y se animará con esos sprites. Cuando llegue a la casilla de destino cambiará de estado y volverá a estar en el estado "Parado".
¿Como implementar todo esto?
1º Creamos una nueva clase que contiene la lista de estados posibles, la clase "EstadosPosibles":
'
Gambas class file PublicParadoAsInteger=1PublicAndarDerechaAsInteger=2PublicAndarIzquierdaAsInteger=3
Esto nos facilitará en el futuro ampliar los estados posibles, y además ayuda a escribir el código en el IDE de gambas
2º Creamos otra clase "EstadoAnimacion" que se encargará de llevar la lista de animaciones para usarla por el personaje:
'
Gambas class filePropertyestadoAsStringPrivatehestadoAsString PublicGaleriaAnimacinesAsNewCollection PrivateFunctionestado_Read()AsStringReturnhestadoEnd PrivateSubestado_Write(ValueAsString)hestado=ValueEnd PublicSubCambioEstado(cadenaAsString)hestado=cadenaEnd PublicSubanimacionActual()AsAnimacionReturnGaleriaAnimacines[hestado]End
Como veis en los objetos de esta clase, almacenamos tanto el estado en que este el personaje como la lista de animaciones. Para ellos internamente usamos una colección "GaleriaAnimacines", siendo su key (o llave) el estado (hestado). (enlace al curso de gambas: uso de colecciones en gambas3)
A la clase "PiezaAnimada", vamos a hacer varios cambios:
- A su constructor _new() le cambiamos los parámetros de entrada, porque anteriormente lo habíamos codificado para que admitiera los datos de una animación. Ahora como vamos a manejar varios, crearemos un objeto público de la clase "EstadoAnimacion" para añadirselos:
PublicSub_new(ficheroRutaEnTableroAsString,ptableroAsDrawingArea)…end '------------------
estados de animacion -----------------PublicmiEstadoAnimacionAsNewEstadoAnimacionPublicmiEstadoAsNewEstadosPosibles'---------------------------------------------------------
- Tendremos un nuevo método para asignar la animación que deberá usar para cuando se dibuje:
PublicSubActualizaAnimacion(estadoAsString) AnimacionTmp=miEstadoAnimacion.GaleriaAnimacines[estado] End
- El método "Mueve": lo modificamos para que cuando la casilla este hacia la izquierda, cambie la animación a la izquierda, y viceversa.
Además aparece un nuevo contador "ContadorA", que llevará la cuenta de los incrementos que lleva la animación (esta la usaremos en el método actualizaposición() )
- Tambien cambiamos el método de actualizaPosicion(), para que cuando llegue a la casilla destino, cambie la animación al estado "parado":
PublicSubactualizaPosicion() IfcasillaFinal=casillaInicialThenReturn'a
llegado a la casilla de destino contadorA+=1pto.x=casillaInicialX+difx*contadorApto.y=casillaInicialY+dify*contadorA IfcasillafinalX=pto.xAndcasillafinaly=pto.yThencasillaInicial=casillaFinalmiEstadoAnimacion.CambioEstado(miEstado.Parado)AnimacionTmp=miEstadoAnimacion.animacionActual()Endif End
- La Clase Jugador:
Para facilitar y "abstraer" el uso de estas nuevas clases y métodos, vamos a crear una nueva clase "interface" que usaremos como clase Padre, llamada Jugador, para manejar los método de los objetos de PiezaAnimada:
'
Gambas class file Public
MiPiezaAnimada
As PiezaAnimada Public
miEstado
As New EstadosPosibles Public
Sub _New() End Public
Sub dibuja() MiPiezaAnimada.dibuja() End Public
Sub actualizaPosicion() MiPiezaAnimada.actualizaPosicion() End Public
Sub Mueve(casilla
As Integer) MiPiezaAnimada.Mueve(casilla) End
Esta clase es muy útil, ya que tiene el método constructor (_new()) sin definir. Crearemos tantas clases que hereden de este "Jugador" como tipo de personajes tengamos (enemigos, soldados, tanques, cañones, etc), así tendremos un constructor a la medida, osea con sus propias animaciones y en futuro añadirle sus propiedades y métodos específicos.
Por ejemplo la clase "JugadorAzul", la definimos asi:
'
Gambas class file InheritsJugador PublicSub_New(ficheroRutaEnTableroAsString,ptableroAsDrawingArea) DimanimacionTmpAsAnimacion Me.MiPiezaAnimada=NewPiezaAnimada(ficheroRutaEnTablero,ptablero)'agrego
distintas animaciones 'Andando
a la derechaanimacionTmp=NewAnimacion("jacinto.png",4,7,"0,1,2,3,2,1,0,4,5,6,5,4,1")Me.MiPiezaAnimada.miEstadoAnimacion.GaleriaAnimacines.Add(animacionTmp,Str$(Me.miEstado.AndarDerecha)) 'Parado...animacionTmp=NewAnimacion("jacinto.png",4,7,"26,26,26,26,26,26,26,0,0,0,0,0,0,26,26,26,26,26,26,26,7,7,7,7,7,7")Me.MiPiezaAnimada.miEstadoAnimacion.GaleriaAnimacines.Add(animacionTmp,Str$(Me.miEstado.Parado)) 'Andando
a la derechaanimacionTmp=NewAnimacion("jacinto.png",4,7,"7,8,9,10,9,8,7,11,12,13,12,11")Me.MiPiezaAnimada.miEstadoAnimacion.GaleriaAnimacines.Add(animacionTmp,Str$(Me.miEstado.AndarIzquierda)) 'digo
cual es el estado inicial.Me.MiPiezaAnimada.miEstadoAnimacion.estado=Me.miEstado.Parado'actualizo
animacionMe.MiPiezaAnimada.ActualizaAnimacion(Me.miEstado.parado) Me.Mueve(0)
'Me pongo en la casilla 0 End
De esta manera definimos sus animaciones correspondiente y usaremos los métodos de la clase interface "Jugador", para realizar las distintas tareas que tenga que hacer la ficha o personaje.
Os dejo un video que muestra lo explicado, ya en funcionamiento:
Ya hemos acabado con el tema de animación de personajes/fichas, en el próximo artículo entraremos en la dinámica del juego de tablero y como programarlo, osea que cuando llegue el personaje a una casilla del tablero, pasará algo en el juego:
- caemos en una casilla de "pregunta": si acertamos, dará puntos al personaje , sino, perderemos puntos.
- caemos en una casilla de otro jugador: nos hacen pagar un tributo o se produce un combate, por ejemplo.
- caemos en una casilla y esta nos envía a otra casilla del tablero (la cárcel , o avanzamos o retrocedemos en el tablero)
- etc.