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:
Buscar una imagen dentro de otra y obtener su posición (coordenadas x,y)
Muchas veces necesitamos desarrollar un programa que reconozca donde esta en una imagen un icono o una subimagen (una porción de la imagen principal). Vamos a usar los png2pat y visgrep, para realizar esta tarea.
Tenemos la siguiente imagen de fondo:
Y queremos buscar la subimagen donde está el icono de la nube:
Los archivos de imagen (tanto el fondo como la imagen que buscamos) deben de tener la extensión ".png", si es otra hay que convertirla con algún programa (gimp, convert, etc).
Estos serian los pasos:
1) Convertimos la imagen "nube.png" al el formato "pat" usando el comando png2pat y ">" $png2pat nube.png > /tmp/nube.pat
2) Y ahora la buscamos en el fondo: $visgrep fondo.png /tmp/nube.pat
3) Nos mostrará las coordenadas de donde esta la imagen "nube.pat"
$visgrep fondo.png /tmp/nube.pat 365,98 -1
La x=365, y la Y=98, así tendremos localizado el punto donde esta la subimagen (su esquina superior izquierda) dentro del fondo
Os dejo en enlace de la ayuda de los comandos que están en el paquete xautomation png2pat visgrep
Tenéis que tener instalado xautomation para tener los dos comandos disponibles:
En un próximo artículos haré un programa donde se usen estos comandos.
Desarrollo de simple juego didáctico: Preguntas sobre un mapa
En este artículo desarrollaré un simple juego didáctico, que tratará sobre preguntas sobre un mapa (se puede usar también cualquier tema, por ejemplo sobre un dibujo de anatomía, etc). El objetivo del programa es ir colocando un botón en distintos sitios del mapa, y se hacer una pregunta referida a donde esta el botón situado.
Bien empezamos:
Vamos a hacerlo sobre un mapa de Andalucía, y preguntar el nombre de las provincias.
1) Partimos de este mapa:
2) Vamos a tomar los datos que necesitamos:
2.1) Nos preparamos la siguiente tabla, con los datos donde vamos a colocar el botón (las coordenadas) , preguntas y respuesta.
Posicion del botón
indice
x
y
Pregunta
Respuesta
0
156
323
¿cual es el nombre de la provincia?
Cádiz
1
40
180
¿cual es el nombre de la provincia?
Huelva
2
166
193
¿cual es el nombre de la provincia?
Sevilla
3
289
291
¿cual es el nombre de la provincia?
Málaga
4
556
260
¿cual es el nombre de la provincia?
Almería
5
420
253
¿cual es el nombre de la provincia?
Granada
6
437
127
¿cual es el nombre de la provincia?
Jaén
7
262
119
¿cual es el nombre de la provincia?
Córdoba
Nota:
Las coordenadas x e y de la tabla, las puedo obtener viendo el cursor en gimp cuando me desplazo por el mapa.
2.2) Al mapa que tengo, le voy a borrar los nombres, eso lo puedo hacer con Gimp:
He usado la "herramienta de clonado" de gimp, y queda muy bien :)
3) En el siguiente esquema podemos ver lo que tiene que hacer el programa:
4) ¿como introduzco los datos de posiciones y preguntas y respuestas en el programa?
4.1) Vamos a usar arrays de point (http://gambaswiki.org/wiki/comp/gb.qt4/point?l=es), para guardar las coordenadas x, e y. Esta la usaremos para saber donde tengo que colocar el botón de pregunta.
Public ArrayCoordenadas As New Point[] 'array de coordenadas del botón pregunta
4.2) Vamos a crear una estructura de datos para almacenar la pregunta y respuesta:
Public Struct PreguntaRespuestas preguna As String respuesta As String End Struct
Y crearemos un array de la estructura "PreguntaRespuestas", para manejar los datos:
Public ArrayPyR As New PreguntaRespuestas[] 'array de datos de preguntas y respuestas
4.3) Crearemos un subrutina para introducir los datos de la tabla, en nuestras estructuras de datos:
PublicSubcargodatos() DimdatopointAsNewPoint
DimdatotmpAsNewPreguntaRespuestas
datotmp.preguna=("¿cual
es el nombre de la provincia?")
datotmp.respuesta="Cádiz"ArrayPyR.Add(datotmp)'el
1º dato es cadiz
datopoint.x=156
datopoint.y=323
ArrayCoordenadas.Add(datopoint)'coordenada
de cadiz
'---------------------------------
datopoint=NewPoint'hago
una nueva instancia
datotmp=NewPreguntaRespuestas'hago
una nueva instancia datotmp.preguna=("¿cual
es el nombre de la provincia?")
datotmp.respuesta="Huelva"
ArrayPyR.Add(datotmp) datopoint.x=40
datopoint.y=180
ArrayCoordenadas.Add(datopoint)
......
5) Cuando el usuario haga click en el botón Preguntar, el programa eligirá un numero aleatorio, y mostrará el botón de pregunta en la posicion que indique el array de coordenadas usando el numero aleatorio elegido como indice.
PublicSubButtonEmpezar_Click() numero=Int(Rnd(0,ArrayCoordenadas.count))'redondeo
para obtener un numero entero ButtonPregunta.x=ArrayCoordenadas[numero].XButtonPregunta.y=ArrayCoordenadas[numero].YButtonPregunta.Visible=True'muestro
el boton de pregunta End
6) El usuario pulsa en el botón de pregunta.
Usamos el numero elegido aleatoriamente en el paso anterior, para mostrar la pregunta y respuesta (usando como indice el numero aleatorio en el array ArrayPyR[]
Mostramos un formulario para mostrar la pregunta y que el usuario pueda escribir la respuesta.
Si la respuesta es acertada, se lo decimos, sino, mostramos la respuesta correcta:
IfUpper$(respuestaUsuario)=Upper$(ArrayPyR[numero].respuesta)ThenMessage.Info(("Muy
bien !!! Acertaste"))ElseMessage.Error(("Te
equivocaste, la respuesta correcta era:")&"\n"&ArrayPyR[numero].respuesta) Endif
7) Finalmente ocultamos el botón pregunta, y el programa esperará a que se pulse de nuevo el botón empezar para repetir el proceso.
En este video podeis ver el programa en funcionamiento:
Y en este video explico los pasos que he seguido para hacer el programa:
Diagrama de secuencia
Modificación del mapa con gimp (toma de coordenadas, borrado de zonas, redimensionamiento del mapa)
Codificación
Nota:
Hay una mejora que se me ocurrio cuando hice los videos.
En ver de usar un Arrray Point y otro array de estructura PreguntaRespuesta, más simple hubiese sido definir una estructura que tuviera todas las propiedades, algo asi como:
Public struct PreguntasRespuestas
x as integer
y as integer
pregunta as string
respuesta as string
End struct
Desarrollo de Juegos de Tablero (8): Aplicación Reglas y como programarlas
En este artículo explicaré como aplicar reglas y programarlas en el juego de tablero que estamos desarrollando. Para explicar la forma de programarlo, el juego va a tener unas reglas sencillas, así facilitará entender la forma de programarlo y en el futuro se podrá ampliar con toda la complejidad que queramos. Las reglas a programar serian las siguiente:
- Cada vez que un jugador caiga en una casilla, elige una carta de "suerte", y ejecuta lo que diga la carta. Hay 5 cartas de suerte:
Tres de las cartas son de movimiento, osea avanzamos o retrocedemos un numero de casillas que indique. Y dos cartas son para los puntos de Vida, nos da puntos o nos lo quita.
-Si por una carta de suerte, nos trasladamos a otra casilla, no cogeremos ninguna carta, pasando el turno al siguiente jugador.
Empezamos:
1) Tenemos un archivo texto donde con varias secciones donde vamos a guardar:
Sección: [reglas casillas][/reglas casillas]
Contiene la información de lo que hay en la casilla. En este caso solo tenemos "coger una carta de suerte", y lo indicamos como "cartasuerte".
[reglas casillas]
1|cartasuerte
2|cartasuerte
....
[/reglas casillas]
Nota: Si tuvieramos varias "barajas" de cartas o distintas opciones, lo indicaríamos.
Sección: [cartasuerte][/cartasuerte]
En esta sección definimos cada "carta": su texto, acción a realizar, y valor numérico para indicar número de casillas o puntos a sumar o restar:
[cartasuerte]
Viento a favor !!! avanzas 5 casillas |avanza|5
Viento en contra :( retrocede 2 casillas |retrocede|2
Llueve y hace mal tiempo :( retrocede 1 casilla|retrocede|1
Consigues Pescar, ganas 10 puntos de vida|puntosVida|10
Pierdes mucha agua potable, pierdes 5 puntos de vida|puntosVida|-5
[/cartasuerte]
2) Programas una nueva clase "Regla", que será la encargada de leer las reglas,
PrivatelineasReglasAsString[]PrivateListaCartaSuerteAsString[] PublicrutaCartasAsString="Reglas/CartasDeSuerte.txt" PublicSub_new() cargaCartasSuerte()cargaReglas() End PublicSubcargaCartasSuerte() DimcontenidoAsStringDimdatosficheroAsString contenido=File.Load(rutaCartas)'las
cartas vienen definida por:"texto|accion|puntuacion"datosfichero=Between(contenido,"[cartasuerte]","[/cartasuerte]")ListaCartaSuerte=Split(datosfichero,"\n","",True) End PublicSubcargaReglas() DimcontenidoAsStringDimdatosficheroAsString contenido=File.Load(rutaCartas)datosfichero=Between(contenido,"[reglas
casillas]]","[/reglas
casillas]")lineasReglas=Split(datosfichero,"\n","",True) End
y ejecutarlas cuando un jugador llegue a la casilla.
Public
Sub llega(jug
As Jugador,
casilla
As Integer) Dim
accion
As String accion
= Split(lineasReglas[casilla
- 1],
"|")[1]
'leo
la parte de accion del jugador jug.CumpliendoRegla
= TrueejecutaRegla(jug,
accion) End Public
Sub ejecutaRegla(j
As Jugador,
accion
As String) Select
Case accionCase
"cartasuerte"AccionCartaSuerte(j)Case
"pregunta"AccionCartaPregunta(j)Default'no
hacer nada...End
Select End Private
Sub AccionCartaSuerte(j
As Jugador) Dim
elegida
As Integer Dim
carta
As String[] 'el
valor 0 continee el texto, y el valor 1 contiene la puntuacion elegida
= Int(Rnd(0,
ListaCartaSuerte.count))Print
elegida,
ListaCartaSuerte[elegida]carta
= Split(ListaCartaSuerte[elegida],
"|") Message.Info(carta[0]) Select
Case carta[1] Case
"avanza"If
(j.CasillaDondeEstoy
+ Val(carta[2])
- 1)
> lineasReglas.count
Thenj.Mueve(lineasReglas.count)Elsej.Mueve(j.CasillaDondeEstoy
+ Val(carta[2])
- 1)EndifCase
"retrocede"If
j.CasillaDondeEstoy
- Val(carta[2])
- 1
> 0
Thenj.Mueve(j.CasillaDondeEstoy
- Val(carta[2])
- 1)Elsej.Mueve(0)EndifCase
"puntosVida"j.puntosVida
+= Val(carta[2]) End
Select End
3) Modificamos la clase Control de Partida, para llamar una instancia de la clase regla, para llegue el jugador a una casilla:
Public
Sub Observador_LLegue(jug
As Object, NumeroCasilla
As Integer)
Dim
mensaje
As String
'Llega
a una casilla
If
jug.cumpliendoRegla
= False
Then
'no
esta cumpliendo ninguna regla, tiene que leerla
reglasTablero.llega(jug,
NumeroCasilla)
Else
'ha
llegado a una casilla, pero porque ha cumplido una regla, no hay que
ejecutar otra regla
jug.cumpliendoRegla
= False
Endif
End
Nota:
La nueva propiedad "cumpliendoRegla" de la clase jugador, nos facilita saber si el jugador a llegado a la casilla por una desplazamiento ordenado por los dados o por si ha llegado cumpliendo alguna regla.
Aqui os dejo un video para ver tanto el código como la ejecución del programa:
Ya prácticamente esta el 90% del juego de tablero....
En el próximo articulo veremos como añadir un "enemigo" al juego. También nos falta añadir detalles gráficos como una barra de puntos de cada jugador, mejora del formulario de mensajes, implementar el juego "por turnos" y un dado aleatorio.