Me parece, que, con las pruebas que he realizado path find crea una única instancia. Es decir, se ejecuta solo un proceso por cada programa.
Lo digo porque cuando más de un proceso utiliza path find de manera simultánea, todos se "teletrasportan" a donde está el otro proceso.
¿Hay alguna forma de solucionar esto? Porque la verdad es que me fastidia todo el invento!
GRacias.
es una unica corrida de path_find a la vez, deberias consumir todos los resultados antes de llamarla desde otro proceso.
Entonces la única posibilidad que me queda es guardar en un array privado de cada proceso todos los puntos que haya encontrado ¿no? Mientras no haga un frame ese proceso monopolizará el pathfind y no habrá problemas ¿Estoy en lo cierto?
Y ya para saberlo ¿Como puedo averiguar cuantos puntos encontró? lo digo para el tamaño del array.
Gracias splinter.
Este código se cuelga, pues a cada segundo :P
[code language="bennu"]
repeat //bucle principal
say("BUcle principal");
px=x+rand(-80,80);
if(y<=105) py=y+rand(0,20); else py=y+rand(-10,20); end //esto es para que si está en la superficie, solo busque por abajo, y si no, busque en las dos direcciones.
if( map_get_pixel(0,0,px,py)!=blanco )
if( path_find(0,0,x,y,px,py,1) ) //buscamos el punto aleatorio
say("encontrado camino");
i=0;
while( PATh_GETXY(puntos
- ,puntos[1]) and i<300); //y lo recorremos
say("guardando camino");
long_camino+=1;
i++;
end
from i=0 to long_camino;
x=puntos- ;
y=puntos[1];
frame;
end
end
end
dig();//esto lo único que hace es un agujero debajo del proceso
frame;
until(exit_status);[/code]
Vale, ya encontré el error, o eso creo...
A parte del desbordamiento de pila, que ya lo he corregido, resulta que el path find no entiende el negro rgb como espacio vacío, por lo que los agujeros que hago con ese color no le parecen puntos válidos, sin embargo al resto del programa sí, y he ahí el conflicto. Entonces ¿Como puedo hacer esos agujeros? porque si pongo drawing_color(0) no me pinta nada. ¿Una ayudita please?
Esto sigue sin funcionar.
Estoy probando con nuevas y excitantes formas de hacerlo y ni para atrás.
Estoy probando a hacer los agujeros con draw_fcircle en lugar de con map put utilizando el 0 como color, y sí, los agujeros los hace, pero a la hora de buscar el camino hacia algún punto que esté en un agujero, se queda trabado otra vez. Me estoy volviendo mico.
EDIT
Ya está muy claro, cualquier punto que caiga dentro de un agujero hecho con draw_fcircle provoca que el programa se quede conjelado buscando el camino, y la verdad es que no llego a entender el motivo.
¡Esto me trae loco!
posiblemente se consuma mucho tiempo analizando.
Suele pasar con puntos cercanos.
Aquí el código completo, por si hay algo que se me escapa
[code language="bennu"]Program ants;
import "mod_key"
import "mod_grproc"
import "mod_video"
import "mod_map"
import "mod_say"
import "mod_wm"
import "mod_rand"
import "mod_text"
import "mod_timers"
import "mod_draw"
import "mod_path"
import "mod_chipmunk"
import "mod_proc"
global
white;
hormiga;
blanco;
marron;
bujero;
alto=600;
ancho=800;
ant_alto=1;//estas medidas deben ser la mitad en números enteros de lo que mida la figura para detectar colisiones
ant_ancho=2;//esto es por comodidad de calcular los bordes de la figura los cuales se miden desde el medio de la misma
begin
set_mode(ancho,alto,16);
marron=rgb(00,00,00);
blanco=rgb(255,255,255);
white=new_map(800,500,16);
bujero=new_map(12,12,16);
hormiga=new_map(4,3,16);
map_clear(0,white,rgb(255,255,255));
map_clear(0,hormiga,rgb(155,95,95));
//map_clear(0,0,rgb(80,80,255)); cielo azul
//map_clear(0,bujero,marron);
drawing_map(0,bujero);
drawing_color(marron);
draw_fcircle(6,6,6);
map_put(0,0,white,(800/2),350);
/********bujeraco*/
drawing_map(0,0);
drawing_color(0);
draw_fcircle(300,100,150);
from x=0 to 1;
ant();
end
Repeat
frame;
until(exit_status);
end
process ant()
private
boca=0;
int i;
estado;
int PX,PY,xx,yy;
puntos[300][2];
long_camino=0;
begin
x=rand(400,600);
graph=hormiga;
y=99;
repeat //bucle principal
say("BUcle principal");
px=x+rand(-80,80);
if(y<=105) py=y+rand(-10,20); else py=y+rand(-10,20); end //esto es para que si está en la superficie, solo busque por abajo, y si no, busque en las dos direcciones.
if( map_get_pixel(0,0,px,py) ==0 )
say("El punto"+px+" "+py+" parece válido "+map_get_pixel(0,0,px,py));
if( path_find(0,0,x,y,px,py,1) ) //buscamos el punto aleatorio
say("encontrado camino");
i=0;long_camino=0;
while( PATh_GETXY(&xx,&yy) )
puntos
- =xx;puntos[1]=yy; //y lo recorremos
//say("guardando punto: "+i);
long_camino++;
i++;
end
from i=0 to long_camino-1;
x=puntos- ;
y=puntos[1];
//say("Caminando a punto: "+i);
frame;
end
end
end
dig();//esto lo único que hace es un agujero debajo del proceso
frame;
until(exit_status);
end
function dig()
private
dead_end=0;
begin
drawing_map(0,0);
drawing_color(0);
if( map_get_pixel(0,0,father.x+ant_ancho+1,father.y)==blanco ) //si hay un hueco blanco
dead_end+=10; //aumentamos la posibilidad de cabar
end
if( map_get_pixel(0,0,father.x-(ant_ancho+1),father.y)==blanco ) //si hay un hueco blanco
dead_end+=10; //aumentamos la posibilidad de cabar
end
if( map_get_pixel(0,0,father.x+ant_ancho+1,father.y)==blanco ) //si hay un hueco blanco
dead_end+=10; //aumentamos la posibilidad de cabar
end
if( map_get_pixel(0,0,father.x,father.y+ant_alto+1)==blanco ) //si hay un hueco blanco
dead_end+=10; //aumentamos la posibilidad de cabar
end
if( map_get_pixel(0,0,father.x,father.y-(ant_alto+1))==blanco ) //si hay un hueco blanco
dead_end+=10; //aumentamos la posibilidad de cabar
end
if( rand(0,200) < dead_end) //ahora en función de la posibilidad de estar en un callejón
draw_fcircle(father.x+rand(-4,4),father.y+rand(-2,2),6);
//map_put( 0,0,bujero,father.x+rand(-4,4),father.y+rand(-2,2) );
end
end
[/code]
Gracias splinter :D
el problema es que no estas usando 0 para dibujar los caminos... debes usar 0... rgb(0,0,0) no es 0.
put_pixel y todas las demas, con drawing_color(0); funciona bien.
edit: perdon, si veo el drawing_map a 0, voy a revisar el codigo
que idiota que soy, el mapa de caminos solo puede ser de 8bits de profundidad...
y no deberias usar el mapa 0,0 para eso, mejor es usar un mapa especial para eso.
Tienes razón splinter!
Llevava un rato pensando justo eso, pero por no se que motivo no me atrevía a probar, creo que el principal era la pereza.
Ahora sí que va como la seda.
Desde luego el mayor valor añadido que tiene bennu eres tú.
Muchas gracias.
Por cierto splinter, me parece que si se aplica move_text a un write_var me parece que el valor de la variable no se actualiza. ¿es eso posible?
move_text solo cambia las coordenadas, no tiene que ver con el lo que muestra... debe ser otra cosa.
Tienes razón, el problema estará en mi programa, no te preocupes, lo revisaré.
Por cierto, volviendo al tema del path find. ¿Tiene alguna limitación especial que yo no sepa?
Es que para un punto dado en una ocasión me funciona sin problemas, pero sin embargo al intentar llegar a ese punto desde otro más lejano me da un error que me provoca un crash.
Creo que había una limitación de distancia, o eso ya se corrigió?
Creo que crashea si intentas hacer un path_find entre dos puntos que no se pueden conectar
Quote from: Abram on April 08, 2011, 10:14:48 AM
Creo que crashea si intentas hacer un path_find entre dos puntos que no se pueden conectar
No creo que sea el caso, ya que cuando crashea en windows 7 se queda la imagen congelada, y siempre me fijo y los dos puntos si que se pueden unir, y además suelen estar muy cerca. Tal vez el problema sea que encuentra 0 puntos y luego el problema me lo da el array en el que los guardo, puesto que no devuelve nada. mm, tu afirmación me ha inspirado. Intentaré investigar eso.
Bueno, lo que dice Abram a mi es lo que me ha pasado siempre
Estoy intentando cercar los errores y parece que el path find no es el que lo está provocando, ya que después de ejecutarlo he puesto un say ("El camino se recorrió con éxito") y sí que aparece en la consola. Si el error lo diera el path_find esa línea no llegaría a aparece, ¿no?
Uff, esto se complica amigos.
Creí que lo tenía cercado pero esto se complica más y más a cada rato. Unas veces casca al poco, otras tarda un montón y para colmo lo hace en distintos puntos de ejecución del programa. Antes parecía que recorría los caminos, ya que siempre saltaba el error después de haberlos recorrido, pero ahora salta también en medio. Sospecho que tal vez el problema sea de algún array, pero me está costando encontrarlo.
usas array de strings dinamicos?
puede que exista algun problema con la que recupera las direcciones, la verdad que a mi nunca me crasheo, ni con caminos cerrados (puntos que no se conectan)
Creo que ya lo tengo. Es el tipico fallo de desbordamiento de toda la vida, al menos despues de solucionar esto ha dejado de caer. Aunque puede que lo que haya hecho haya sido enmascarar el probpema real...
llamabas a una funcion a si mismo muchas veces?
podrias explicar el fallo, asi descartamos sea problema del motor?
Quote from: SplinterGU on April 08, 2011, 02:40:41 PM
puede que exista algun problema con la que recupera las direcciones, la verdad que a mi nunca me crasheo, ni con caminos cerrados (puntos que no se conectan)
No se si esto te sirve para algo o no, pero ya te puedo confirmar que no crashea aunque no encuentre camino. Hoy se me quedó en un bucle con el siguiente mensaje "No se puede encontrar un camino a xx yy", cientos de veces y durante más de una hora.
La verdad es que no se para que me doy ese feedback por consola si luego no tengo ninguna condición para actuar en consecuencia ;D al menos no te frustras por no saber lo que es.
¡DIOS BENDIGA A LOS SAY! (y a los s.a.i. también)
Tranquilo que no es problema del motor, es un array con menos tamaño del que se creía. No pasa ná!
La verdad es que estoy avanzando...
bien, me alegro, gracias.
Eso si, hay algo que te puedo constatar 100% seguro y es que no encuentra caminos de logitud superior a, creo, unos 600, o al menos en mis pruebas no encontraba camino desde, por ejemplo el 523-267 al 0,99, así que hice un bucle
[code language="bennu"]while( ! path_find(0,fondo,father.x,father.y,x,y,1));
x+=10%ancho;
end[/code]
Y para mi sorpresa nunca encontraba un camino desde el 0,99, siempre empezaba en el 110-99, y según me iva alejando, pues desde el 120, el 130, el 140, y nunca me retornaba un camino mayor de 550.
¿Es esa una de sus limitaciones? ¿no se puede configurar para hallar mayores caminos?
tienen limitaciones, es cierto, yo me olvide decir que para path_find se usan mapas en escala, o sea, que 1 pixel del mapa de busquedas representa unos cuantos pixels del mapa original.
Quote from: SplinterGU on April 12, 2011, 03:32:56 PM
tienen limitaciones, es cierto, yo me olvide decir que para path_find se usan mapas en escala, o sea, que 1 pixel del mapa de busquedas representa unos cuantos pixels del mapa original.
Esa suele ser en efecto la forma más comun de utilizarlos, pero no se hasta que punto se perderá precisión en un proyecto como el mio que utiliza entornos deformables. ¿tal vez con una escala de la mitad no se note demasiado?
Pero claro, luego habra que transformar las coordenadas, ¿bastará con multiplicar por 2 los resultados? Pero eso probocará, si no es que me equivoco una vez mas, que los procesos se muevan al doble de velocidad.
Y ahora que me doy cuenta tengo otro problma mas, y es que algunos procesos agregan un pixel mas en determinada zona ¿como proporciono eso si ya trabaja con la unidad minima?
No se pueden eliminar,o al menos aumentar las limitaciones modificando la mod_path?
Bueno, a las malas siempre puedo hacer busquedas consecutivas, aunque realmente de momento no es un problema ya que en realidad no creo que vaya a necesitar caminos tan largos de momento, tan solo los tomo asi de largos por precaución, por lo que reducirlos no es de momento un problema.
Muchas gracias como siempre.
busquedas consecutivas no sirven, tienes que cubrir todo el terreno.
el problema es que esta limitado por temas de procesamiento de calculos, si modificas la pathfind puedes ampliar el rango.
Yo ese pathfind con rango/profundidad variable en la búsqueda todavía sueño con él de vez en cuando y me humedezco...
Quote from: Windgate on April 12, 2011, 08:06:21 PM
Yo ese pathfind con rango/profundidad variable en la búsqueda todavía sueño con él de vez en cuando y me humedezco...
Pues pásate por mi hilo de las hormiguas, ahí alguien (perdon no me acuerdo del nombre) ha explicado que se puede y que además admite bastantes niveles de dureza o dificultad a la hora de pasar.
Splinter, servir si que sirve, pero con performance ruinosa.
Mira lo haría así:
Voy acercando los puntos hasta que me devuelva un camino válido
Guardo las coordenadas de los puntos a recorrer.
Busco otro camino desde un punto más alejado hasta el primer punto del camino anterior
Añado los nuevos puntos al array.
Voila!
no sirve, porque no podes calcular el tramo correcto, en base a que datos y caminos calculas el primer destino parcial? no tiene sentido, es ridiculo, porque para saber el primer destino parcial, necesitas saber el camino mas optimo al destino final, cosa que no podes hacer.
para mi, eso que dices no tiene sentido... o no te estoy entendiendo lo que dices.
Lo pego por aqui, dadle las gracias al gran Osk ^^
path_wall(VALOR)
Esta función, definida en el módulo "mod_path", modifica el valor de "pared" empleado por la función path_find().
Este valor de pared será un número que indica la posición mínima del color dentro de la paleta (perteneciente al
gráfico de 8 bits que representa el camino) a partir del cual un punto del gráfico es intraspasable. Es decir, si por
ejemplo el parámetro vale 5, todos los píxeles del gráfico del camino pintados con los colores que ocupan las
posiciones 0,1,2,3 y 4 de la paleta serán traspasables, y el resto no.
El orden de los colores traspasables influye en la facilidad de "traspase". En el ejemplo anterior, el color 1 es el más
fácil de traspasar porque no ofrece apenas resistencia para los móviles; en cambio, el color 4 será más dificultoso, y en
principio no será la opción escogida para crear un camino, a no ser que no haya otra opción. Es decir, la posición de
los colores en la paleta se interpreta como el "coste" de movimiento de un punto dado, hasta llegar a la posición
marcada por el parámetro, la cual marca la barrera infranqueable. Más concretamente: cada posición en la paleta
requiere el doble de pasos que la anterior, hasta llegar a la posición infranqueable (1ª posición, 1 paso necesario; 2ª
posición, 2 pasos necesarios,etc)
Evidentemente, esta función se ha de invocar siempre antes de path_find(), ya que ésta utiliza el valor previamente
definido por path_wall() para calcular el camino más adecuado. Si no se utiliza esta función, por defecto, el valor de
la "pared" que utilizará path_find() está a 1, lo que significa que sólo los puntos a 0 serán traspasables por el camino
a resolver. Por otro lado, si a la función se le pasara como parámetro un valor menor a 0, éste no será modificado.
Quote from: SplinterGU on April 12, 2011, 09:39:40 PM
no sirve, porque no podes calcular el tramo correcto, en base a que datos y caminos calculas el primer destino parcial? no tiene sentido, es ridiculo, porque para saber el primer destino parcial, necesitas saber el camino mas optimo al destino final, cosa que no podes hacer.
para mi, eso que dices no tiene sentido... o no te estoy entendiendo lo que dices.
A ver, esta técnica es fatal, una mierda como una casa, pero vale.
Si yo se que va a haber camino, pues voy acercando el origen, hasta que me retorne un camino válido, luego entonces pido un camino desde el primer origen hasta el origen que yo mismo "acerqué". Obviamente entre cada llamada tienes que guardar los puntos en algún array.
Ahora, ¿Que me dices de lo que te he preguntado antes sobre los mapas escalados? ¿Que hago con las cosas que trabajan a nivel de pixel? Me quedaría un mapa desproporcionado.
Los mapas de búsqueda de caminos siguen el mismo principio que los mapas de durezas, no os compliqueis la vida: el mapa puede ser la mitad de grande, por lo que cada punto del mapa de caminos representan 2x2 pixels del mapa normal. No avances el personaje en el mapa de caminos: muévelo en el mapa normal y usas el mapa de caminos para consultar las "durezas", dividiendo la posición entre 2, no se si me explico.
PD: casi ningún juego requiere precisión a nivel de pixel, por lo que puedes escalar a la mitad, a un tercio, a la cuarta parte...
Ya drumpi, como tu bien dices, para "consultar" vale. Pero, luego para ir recorriendo el camino.. . ¿basta con poner x=punto[0][0]*2 Y=punto[0][1]*2 y así ir recorriendolos?
En efecto en pocos juegos se requiere precisión a nivel de pixel, pero cuando los entornos son deformables, y tienes procesos que añaden un pixel aquí o un pixel allá, ¿que haces? pones un pixel en el mapa de durezas y dos en el real? mm, ahora que lo digo podría funcionar...
¿tu que opinas?
es como ha explicado drumpi.
Pues debo haberlo hecho mal o no he entendido bien lo que me ha querido decir drumpi, porque he adaptado (como he podido) mi código a las consultas al mapa a dividirlas por 2 y su correspondiente realización en el mapa "a la vista" multiplicarlas por 2 y el resultado obtenido es, sencillamente, horrible, horripilante, no hacen más que traspasar paredes, eso sí, se mueven más rápido, pero la fidelidad a lo que se muestra dista mucho de ser satisfactoria.
¿Lo estaré haciendo mal?
no se, pone el codigo y lo vemos.
aunque ahora no tengo tiempo.
Vale, ya he retocado todo, y ya no atraviesa las paredes, parece funcionar perfectamente, pero todo tiene un aspecto mucho más "tosco"
Las montañas de tierra que antes dibujaba a nivel de pixel, ahora son cuadradotas, debido a que cada pixel es el doble, los agujeros ya no son tan sueves, sino que tienen dientes de sierra y el movimiento que antes era muy fluido queda muy robótico.
Splinter, como puedo modificar la mod_path? o a ver si se nos ocurre alguna otra solución elegante... y eficiente.
EL codigo lo pongo en el hilo de mi proyecto, que no quiero saturar los servidores ;D
estoy viendo y no veo el limite en el codigo, voy a tener que probarlo y ver como es que esta limitando, si es que lo esta haciendo o hay algun otro error.
Quote from: SplinterGU on April 13, 2011, 02:59:31 PM
estoy viendo y no veo el limite en el codigo, voy a tener que probarlo y ver como es que esta limitando, si es que lo esta haciendo o hay algun otro error.
estoy seguro de que lo haras de la mejor de las maneras posibles.
Grande splinter,muy grande
Hombre, si te da posiciones en el path-find, lógicamente en el "mundo real" las tendrás que multiplicar por 2, y no debería darte movimientos demasiado robóticos comparados con un mapa de tamaño 1:1.
Es más, generalmente estos algoritmos se usan con tiles, y estos pueden ser de 8x8, 16x16, 32x32 e incluso más gordos. Puedes suavizar el movimiento moviéndote hacia la posición 3 puntos más adelante, haciendo media de los siguientes 3 puntos, o incluso usar near_angle.
Lo suyo es que busques los puntos que actúen como vértices, donde se cambie de dirección, y te dirijas hacia ellos, olvidándote de los intermedios (aunque puede dar problemas con pasillos estrechos).
Hombre drumpi, eso que dices tiene sentido, pero de momento "creo" que he encontrado una solución.
Esto no va de tiles, ni nada parecido, así que de momento prefiero mantener la precisión al pixel aunque tenga que hacer unos cuantos ajustes, pero tu idea no creas que cae en saco roto, la rescataré para otros proyectos, aunque tu no lo sepas he aprendido bastante de ti.
Splinter, por cierto, aún ando intrigado con el límite real del path find. Creía que lo había encontrado en 600, pero hoy el programa me petó porque encontró un camino de 826, y yo tenía un array contando con que nunca pasarían de 800.
Ah, y una duda que estoy seguro que ya has resuelto más de una vez, pero en fin, Verdad que es imposible que dos procesos intenten acceder a la vez al mismo array? Lo digo porque creo que había alguna implementación de semáforos o jerarquías y cada proceso se ejecutaba por un orden y nunca dos procesos a la vez.
Un saludo!
los procesos bennugd nunca se ejecutan 2 a la vez.
con respecto a usar un mapa 2x2 cada pixel, no significa que luego te tengas que mover de 2 en 2, puedes moverte de 1 en 1, solo tienes que calcular la recta entre cada 1 de esos pasos que son de 2x2, por ejemplo, si tengo un path find que comienza en 0,0 y la siguiente es 2,2 entonces puedo moverme de 0,0 a 1,1 y luego a 2,2.
o hacer primero un mapa de pixels 2x2 y luego calcular el path_find entre cada segmento, por ejemplo, desde 0,0 a 2,2 y aca con un mapa si de pixels, aunque no lo creo necesario.
La verdad es que ya he eliminado la mayoría de los path find, por lo que el código ha ganado en simpleza y velocidad a la hora de ejecutarse. Estaba un poco obcecado con los path find y no me daba cuenta de que para ciertas cosas no los necesitaba, así que tal vez lo del mapa 2x2 sí que sea viable con la nueva forma en la que tengo planteado el programa.
Para lo de calcular los puntos intermedios, ¿haría falta utilizar la ecuación de la recta? o tal vez con dividir por dos valdría.
Primero al punto x/2 e y/2, y luego que lo moviese al punto x,y. ¿o tal vez hay algo que se me está escapando en esa operación? Bueno, sería en realidad x y y luego x*2 y*2
Vale, creo que es algo más simple, algo así
por ejemplo con A(-3,2) y B(5,2)
PM de X
la formula es (X2+X1 )/2
-3+5=2/2=1
PM de Y
la formula es (Y2+Y1)/2
2+2=4/2=2
las coordenadas del PM serian (1,2)
Pero claro, habría de meter un frame entre punto y punto. Mmm, queda un poco feo a nivel de código no?
x=X1
frame;
x=x2;
frame;
Uff
creo que dividiendo por 2 podria ser, si aumentas resolution, porque un incremento de 0.5 en cada paso, por ejemplo, no haria que se mueva.