¿? Creia que tenia todo controlado en este código, pero el jodido fantasmilla me sigue dando errores en tiempo de ejecución por intentar acceder a su puñetero padre; He puesto como primera e indispensable condición en todas partes que la variable father sea true, pero no hay manera. Bien es cierto que no siempre da este error, sino que es en momentos críticos con muchos procesos dentro. Ya estoy algo rallado.
[code language="bennu"]Process fantasmilla_miniradar(int jugador,int lugar);
private
vehiculo_miniradar ident;
vehiculo_miniradar padre;
int explosion_delante;
begin
file=fpg_minijuego;
graph=1;
region=jugador;
//map_clear(0,graph,rgb(255,0,0));
padre=father;
repeat
alpha=miniradar_fantasmilla_alpha; //LÍNEA DE DESARROLLADOR, PONERLA CON VALOR POSITIVO PORSIACA
frame;
switch(lugar)
case 1:if(father)x=father.x+25;y=father.y;end end//case 1
case 2:if(father)x=father.x;y=father.y-70;end end//case2
end
ident=collision(type vehiculo_miniradar);//Aquí collisiona
explosion_delante=collision(type explosiones_miniradar);
/*Esta parte es para actuar dependiendo de si es el fantasmilla derecho o el superior*/
switch(lugar)
case 1: if(father) //esto es para que si no tiene padre no haga nada
if(ident || collision(type valla_miniradar))padre.coche_derecho=1; //esto es para que no se adelanten o no se salgan del arcen
else padre.coche_derecho=0;end//Este solo avisa de que hay un coche a la derecha
end/*superif*/end//case 1
case 2: if(father) //esto es para que si no tiene padre no haga nada
if((ident &&(ident.region==padre.region)&& ident.velocidad_publica<padre.velocidad_publica) || explosion_delante)
if(padre.coche_derecho==0 && padre.adelantando==0)//Este if tiene que ir aparte porque si no el else haría que se frenase el coche por ejemplo si ident=0 (no hay ninguno delante) o cualquiera de las otras condiciones fuera falsa
adelantar_miniradar(padre,jugador);
padre.adelantando=1; //así solo llama al adelantamiento una vez por cada coche, de lo contrario lo llamaba todo el rato que el fantasma estaba en contacto con el coche (adelantaba 3 o 4 veces por frame)
elif(padre.frenando==0 && !padre.adelantando);
frenada_miniradar(padre,ident.velocidad_publica,jugador);
padre.frenando=1;
end //if
end//if
end/*superif*/end//case 2
end//switch
until(y<miniradar_umbral_desaparicion[jugador])
signal(id,s_kill_tree); //esto es necesario para liquidar a los procesos frenada y adelantamiento, que intentando acceder a su abuelo cuando esta ya había muerto generaban muchos errores en tiempo de ejecución.
end[/code]
exists(father)
y solo hace falta compararlo tras cada frame... luego, hasta el proximo frame, si la condicion dio true, entonces father existe...
Splinter, cuando mandas un signal s_kill_tree mata a toda la descendencia ¿no? y si no la tiene no da error en tiempo de ejecución no? Es que el puñetero proceso me sigue dando el mismo error.
Ahora que le he quitado una de las funcionalidades (en la que detectaba colisiones con un proceso que mataba a su padre y yo creo que su padre moría justo después de que el hiciera la comprobación de que existia, o algo así) el error me lo ha dado otro proceso, pero esta vez no era procedimiento 0 no activo, sino otro procedimiento. No se cual será, me imagino que su abuelo, ya que es el único al que accede. Pero ahora que pienso todo esto no tiene sentido! Si yo hago un s_kill_tree con el proceso que destrulle al padre de todos estos, ¿no debería haber problema no?
descendencia si, ascendencia no... y los procesos huerfanos no recien signal, quizas debas hacer un signal por tipo de proceso... y puedas usar las caracteristicas de las funciones signal_action...
Creí que lo de signal action había sido un delirio de drumpi (no se porque me suena algo así). Si me lo explicas un poco intento hacerlo.
Pero cuando digo s_kill_tree me refiero que mato a sus hijos, nietos etc, y sin embargo me sigue dando errores de accesos a procesos no activos, antes eran el 0, ahora tienen identidad, pero es el miso error.
Me pasa solo con 2 procesos. El caso es que el padre antes de morir, mata a su hijo (el fantasma) y a sus nietos (posibles procesos frenada y aceleración) ¿por que sigo teniendo este problema?
De postear el código ya lo hago mañana, que lo tendría que apañar y es largo.
antes de acceder a un proceso, tenes que verificar que existe con exists... del exists hay informacion en el wiki...
con respecto a los signals, lo de drumpi si fue un delirio... pero bueno, mas alla de eso, esto de los sginals ya estaba en planes mucho antes del delirio mencionado :D...
signal_action sirve para decir como se comportara un proceso ante la accion de una señal. las posibles acciones son:
S_DFL - Signal default
S_IGN - Signal ignore
existen 2 formas o ambitos de uso de la funcion signal_action, una es local (afecta al proceso llamador) o remota (afecta a otro proceso), la sintaxis es la siguiente:
signal_action([process,] signal, action);
donde:
process, puede ser un proceso especifico, procesos de un tipo especifico (usando TYPE) o todos los procesos (usando 0 o ALL_PROCESS)
signal, puede ser cualquiera de las señales ya conocidas (incluida las TREE).
action, cualquiera de las 2 mencionadas arriba (S_DFL o S_IGN).
A todo este sistema se agregan 8 nuevas señales, que sirven para forzar las señales independientemente de su action... podrian ser vistas como algo parecido a "signals dios", estas son:
S_KILL_FORCE
S_WAKEUP_FORCE
S_SLEEP_FORCE
S_FREEZE_FORCE
S_KILL_TREE_FORCE
S_WAKEUP_TREE_FORCE
S_SLEEP_TREE_FORCE
S_FREEZE_TREE_FORCE
cuyo valor son las signals conocidas + 50
-------------
quizas esto se aplique a tu necesidad actual o quizas no...
La verdad es que ahora no se me ocurre una aplicación inmediata, pero está bien saber estas cosas, cada día hay más funcines!
El caso es que me sigue dando el mismo problema, voy a poner el código del padre para que veas que, en teoría, es imposible que ninguno de sus hijos pueda acceder a un proceso inactivo.[code language="bennu"]/***********************************************************************************
***-------------------EL PUTO COCHE DE LOS WEBOS---------------------------------------------
*******************************************************************************************/
Process vehiculo_miniradar(int bonus,float velocidad,int jugador);
Private
//float avance;
//int fotos=1; //valor máximo 1
//int carril=0; //por defecto irán por el carril 0
//float slow_mo;
//int detectado=1;
Begin
file=fpg_minijuego;
region=jugador;
avance=miniradar_salida_coches[jugador];
if(velocidad<600)
graph=miniradar_graficos_coches[rand(0,2)];
elif(velocidad<1000 && velocidad>600)
graph=miniradar_graficos_coches[rand(2,6)];
elif(velocidad>1000 && velocidad<2000)
graph=miniradar_graficos_coches[rand(7,9)];
elif(velocidad>2000)
graph=miniradar_graficos_coches[rand(7,9)];
end
if(bonus)
chivato_bonus_miniradar(bonus,jugador);
end
velocidad_publica=velocidad;
fantasma1=fantasmilla_miniradar(jugador,2);
fantasma2=fantasmilla_miniradar(jugador,1);
/*AFECTADOS POR LA LLUVIA*/
if(miniradar_lluvia_activa[jugador])
velocidad_publica-=velocidad_publica*0.2; //le pasamos velocidad como parámetro ya que si le pasaramos velocidad pública, la frenada modifica esta variable y entraría en un bucle infinito.
end
// Elección de carril
from i=0 to miniradar_num_carriles;//aqui comprueba si el carril vale 0 (libre)
if(!miniradar_carril_ocupado[jugador]) //pero si el carril i vale 1(true), el carril está ocupado
carril=i;
break; //Nos vamos al otro carril
else //todos los carriles ocupados
carril=0;
avance+=100;
end
end
miniradar_carril_ocupado[jugador][carril]++;//avisamos de que el carril está ocupado
x=miniradar_carril[jugador][carril]; //y nos vamos al carril
repeat
/*COMPORTAMIENTO EN CASO DE BONUS*/
/*AUTO*/
if(miniradar_bonus[jugador]==1&& fotos>0 && y<miniradar_limite_inferior[jugador]-100 && (velocidad_publica*0.2)>miniradar_vel_permitida) //Esto es para que solo le puedas pillar una vez por pero que no pase nada si le das al flash antes de que este dentro de los límites Antes ocurria que el coche todavía no había aparecido en pantalla y sin embargo ya habías gastado la foto y no te permitía puntuar.
foto_miniradar(jugador);
end
/*SLOW MOTION*/
slow_mo=velocidad_publica/miniradar_slow_mo;//así la cámara lenta actua en tiempo real cuando se cambia la velocidad del coche
if(miniradar_bonus[jugador]==2)avance-=(slow_mo/100);//si el jugador la camara lenta (bonus 2) va lento
else avance-=(velocidad_publica/100); //de lo contrario irá a velocidad normal
end
y=avance;
if(miniradar_flashing[jugador] && fotos>0 && y<miniradar_limite_inferior[jugador]) //Esto es para que solo le puedas pillar una vez por pero que no pase nada si le das al flash antes de que este dentro de los límites Antes ocurria que el coche todavía no había aparecido en pantalla y sin embargo ya habías gastado la foto y no te permitía puntuar.
fotos--;
velocimetro_miniradar(x,y,velocidad_publica*0.2,jugador);
end
if(y<=miniradar_altura_banda[jugador] && detectado>0)//esto es para el marcador de velocidad
miniradar_vel_detect[jugador]=velocidad_publica*0.2;
detectado--; //esto es para que una vez detectados dejen de mandar su valor al radar y lo dejen libre para otros
end
frame;
until(y<miniradar_umbral_desaparicion[jugador]);
miniradar_carril_ocupado[jugador][carril]--;//libera el carril (vacio)
signal(fantasma1,s_kill_tree);
signal(fantasma2,s_kill_tree);
//explosión de las naves o algo
End [/code]
Este es el supuesto padre y abuelo de todos, como ves, al final mata a los fantasmillas y toda su descendencia...
[code language="bennu"]Process fantasmilla_miniradar(int jugador,int lugar);
private
vehiculo_miniradar ident;
vehiculo_miniradar padre;
int explosion_delante;
begin
file=fpg_minijuego;
graph=1;
region=jugador;
//map_clear(0,graph,rgb(255,0,0));
padre=father;
repeat
alpha=miniradar_fantasmilla_alpha; //LÍNEA DE DESARROLLADOR, PONERLA CON VALOR POSITIVO PORSIACA
frame;
switch(lugar)
case 1:if(exists(father))x=father.x+25;y=father.y;end end//case 1
case 2:if(exists(father))x=father.x;y=father.y-70;end end//case2
end
ident=collision(type vehiculo_miniradar);//Aquí collisiona
/*Esta parte es para actuar dependiendo de si es el fantasmilla derecho o el superior*/
switch(lugar)
case 1: if(exists(father)) //esto es para que si no tiene padre no haga nada
if(ident || collision(type valla_miniradar))padre.coche_derecho=1; //esto es para que no se adelanten o no se salgan del arcen
else padre.coche_derecho=0;end//Este solo avisa de que hay un coche a la derecha
end/*superif*/end//case 1
case 2: if(exists(father)) //esto es para que si no tiene padre no haga nada
if((ident &&(ident.region==padre.region)&& ident.velocidad_publica<padre.velocidad_publica))
if(padre.coche_derecho==0 && padre.adelantando==0)//Este if tiene que ir aparte porque si no el else haría que se frenase el coche por ejemplo si ident=0 (no hay ninguno delante) o cualquiera de las otras condiciones fuera falsa
adelantar_miniradar(padre,jugador);
padre.adelantando=1; //así solo llama al adelantamiento una vez por cada coche, de lo contrario lo llamaba todo el rato que el fantasma estaba en contacto con el coche (adelantaba 3 o 4 veces por frame)
elif(padre.frenando==0 && !padre.adelantando);
frenada_miniradar(padre,ident.velocidad_publica,jugador);
padre.frenando=1;
end //if
end//if
end/*superif*/end//case 2
end//switch
until(y<miniradar_umbral_desaparicion[jugador]|| !exists(father))
end[/code]
Este es el código de uno de los procesos que más errores da, junto con los de frenada y adelantamiento.
[code language="bennu"]
process adelantar_miniradar(int coche,int jugador)
private
vehiculo_miniradar coche_a_mover;
float vel_adelantamiento;
begin
coche_a_mover=coche;
vel_adelantamiento=coche_a_mover.velocidad_publica;
from i= miniradar_carril[jugador][coche_a_mover.carril] to miniradar_carril[jugador][coche_a_mover.carril+1];
coche_a_mover.x++;
frame;
if(!exists(father))signal(id,s_kill);end //esto es necesario, si no tiene padre quiere decir que el abuleo (curiosamente en la variable privada padre) va a morir pronto, y si intenta acceder a alguna de sus variables da error en tiempo de ejecución
end // from
coche_a_mover.adelantando=0; //avisa de que ya ha adelantado
end //begin
Process frenada_miniradar(int coche,float velocidad_final,int jugador)
private
float reduccion_justa;
vehiculo_miniradar coche_a_frenar;
begin
coche_a_frenar=coche;
reduccion_justa=coche_a_frenar.velocidad_publica/4;
repeat
if(!exists(father))signal(id,s_kill);end //esto es necesario, si no tiene padre quiere decir que el abuleo (curiosamente en la variable privada padre) va a morir pronto, y si intenta acceder a alguna de sus variables da error en tiempo de ejecución
coche_a_frenar.velocidad_publica--;
mapa_frenadas_miniradar(jugador,coche_a_frenar.x-10,coche_a_frenar.y+20);
mapa_frenadas_miniradar(jugador,coche_a_frenar.x+10,coche_a_frenar.y+20);
frame;
until(coche_a_frenar.velocidad_publica<=velocidad_final);
coche_a_frenar.frenando=0; //avisa de que ya ha frenado.
end[/code]
Te pongo esto por si hay alguna evidencia a primera vista de la que yo no me doy cuenta, pero si ves que hace falta ya te pongo una versión compilable.
1) debes ser coherente con los chequeos, si usas father en el exists luego usa father no uses "padre", aunque arriba lo asignes al anterior...
2) tambien usas "ident" y ahi no chequeas por si existe, solo hace un "if (ident ...", ahi tambien tenes que poner el exists, lo mismo para cada uno de los procesos que accedes externamente...
splinter, uso father en el exists porque sé que se actualiza a cada frame, sin embarlo la varible padre no se actualiza a cada frame,aunque creo que con el exist eso no importa no? te dice en tiempo real si está vivo o no. claro lo hice antes de pensar en el funcionamiento de exist. Mediante father no puedo acceder a las variables públicas (que no locales) y por eso usaba las dos, porque creía que era importante que se actualizase a cada frame, ya veo que es indiferente.
¿donde debería poner el exist dentro del ident? creí que con que el ident tuviera un valor... espera! puede tener un valor y estar el proceso muerto! no reparé en eso.
Así sería correcto o resultaría redundante?
Lo voy a probar, pero a lo mejor estoy poniendo exists de mas XD
[code language="bennu"]/*-------------------------------------------------------------------------------*/
Process frenada_miniradar(int coche,float velocidad_final,int jugador)
private
float reduccion_justa;
vehiculo_miniradar coche_a_frenar;
begin
coche_a_frenar=coche;
reduccion_justa=coche_a_frenar.velocidad_publica/4;
repeat
if(!exists(coche_a_frenar))signal(id,s_kill);end //esto es necesario, si no tiene padre quiere decir que el abuleo (curiosamente en la variable privada padre) va a morir pronto, y si intenta acceder a alguna de sus variables da error en tiempo de ejecución
coche_a_frenar.velocidad_publica--;
mapa_frenadas_miniradar(jugador,coche_a_frenar.x-10,coche_a_frenar.y+20);
mapa_frenadas_miniradar(jugador,coche_a_frenar.x+10,coche_a_frenar.y+20);
frame;
until(coche_a_frenar.velocidad_publica<=velocidad_final || !exists(coche_a_frenar));
if(exists(coche_a_frenar))coche_a_frenar.frenando=0;end//avisa de que ya ha frenado.
end
process adelantar_miniradar(int coche,int jugador)
private
vehiculo_miniradar coche_a_mover;
float vel_adelantamiento;
begin
coche_a_mover=coche;
if(exists(coche_a_mover))
vel_adelantamiento=coche_a_mover.velocidad_publica;
from i= miniradar_carril[jugador][coche_a_mover.carril] to miniradar_carril[jugador][coche_a_mover.carril+1];
coche_a_mover.x++;
frame;
if(!exists(coche_a_mover))signal(id,s_kill);end //esto es necesario, si no tiene padre quiere decir que el abuleo (curiosamente en la variable privada padre) va a morir pronto, y si intenta acceder a alguna de sus variables da error en tiempo de ejecución
end // from
coche_a_mover.adelantando=0; //avisa de que ya ha adelantado
end//if de existencia de padre
end //begin
/*---------------------------------------------------------------------------------*/
Process fantasmilla_miniradar(int jugador,int lugar);
private
vehiculo_miniradar ident;
vehiculo_miniradar padre;
int explosion_delante;
begin
file=fpg_minijuego;
graph=1;
region=jugador;
//map_clear(0,graph,rgb(255,0,0));
padre=father;
repeat
alpha=miniradar_fantasmilla_alpha; //LÍNEA DE DESARROLLADOR, PONERLA CON VALOR POSITIVO PORSIACA
frame;
switch(lugar)
case 1:if(exists(padre))x=padre.x+25;y=padre.y;end end//case 1
case 2:if(exists(padre))x=padre.x;y=padre.y-70;end end//case2
end
ident=collision(type vehiculo_miniradar);//Aquí collisiona
/*Esta parte es para actuar dependiendo de si es el fantasmilla derecho o el superior*/
switch(lugar)
case 1: if(exists(padre)) //esto es para que si no tiene padre no haga nada
if(ident || collision(type valla_miniradar))padre.coche_derecho=1; //esto es para que no se adelanten o no se salgan del arcen
else padre.coche_derecho=0;end//Este solo avisa de que hay un coche a la derecha
end/*superif*/end//case 1
case 2: if(exists(padre) && exists(ident)) //esto es para que si no tiene padre no haga nada
if((ident.region==padre.region)&& ident.velocidad_publica<padre.velocidad_publica))
if(padre.coche_derecho==0 && padre.adelantando==0)//Este if tiene que ir aparte porque si no el else haría que se frenase el coche por ejemplo si ident=0 (no hay ninguno delante) o cualquiera de las otras condiciones fuera falsa
adelantar_miniradar(padre,jugador);
padre.adelantando=1; //así solo llama al adelantamiento una vez por cada coche, de lo contrario lo llamaba todo el rato que el fantasma estaba en contacto con el coche (adelantaba 3 o 4 veces por frame)
elif(padre.frenando==0 && !padre.adelantando);
frenada_miniradar(padre,ident.velocidad_publica,jugador);
padre.frenando=1;
end //if
end//if
end/*superif*/end//case 2
end//switch
until(y<miniradar_umbral_desaparicion[jugador]|| !exists(padre))
end[/code]
PD: SPLINTER, A PARTIR DE AHORA (NO PORQUE ANTES NO LO MERECIERAS) VAS A APARECER EN LOS CRÉDITOS DE TODOS MIS PATÉTICOS INTENTOS DE JUEGOS.
Por cierto, splinter, me asalta una duda acerca de las signals. Cuando un proceso recive una s_kill, ¿aborta en ese mismo momento? O ejecuta sus últimas líneas? por ejemplo, si justo antes del último end, yo le pongo a un proceso un unload map, y luego le mando un s_kill ¿ejecuta esa última instrucción? ¿O se va a la porra?
Por cierto, creo que estoy a punto de encontrar una gran utilidad a tu sistema nuevo de señales.
Los procesos se ejecutan 1 por vez hasta el frame... cuando un proceso recibe una señal y si esta es un kill, afecta en el momento... esto es por ejemplo, si me hago yo mismo un kill, o lo hace un proceso que acabo de llamar y todavia espero su retorno...
si vos queres que un proceso ejecute algo de codigo una vez muerto, deberias usar "on exit goto" u "onexit:", busca en el foro que hay documentacion al respecto.
Vale, es lo que me imaginaba, la funcion onexit ya la conocía de fenix 0.93, gracias, lo que yo ya no entiendo es porque esto me sigue dando errores de proceso tal o cual no activo, y siempre son los mismos dos procesos, adelantamiento y frenada, que por lo visto no saben morir cuando les toca, tengo ya exists(father) como condicion en todo, y aún así sigue dando el mismo error.
Si le puedes hechar un vistazo splinter, sin agobios por supuesto, te lo agradezco.
Venga un saludo.
PD: dios que dolor de cabeza.
pero cuando te da? podes mostrar el log? lo compilaste con -g y ejecutaste con -d? ahi vas a ver exactamente donde te da el errror...
1)
until(coche_a_frenar.velocidad_publica<=velocidad_final || !exists(coche_a_frenar));
por
until(!exists(coche_a_frenar) || coche_a_frenar.velocidad_publica<=velocidad_final);
2) si el id a procesar viene de un collision no seria necesario el exists para ese id (no vi que ident venia de un collision)
Creo que solo es el 1)... asi, a simple vista no vi ninguno mas.
efectivamente ident viene de collision, pero no creo que sea problema del ident (es decir, no accede mucho al ident, y desde luego el proceso frenada no accede a el, sino que le pasan un valor suyo como parametro. El problema yo creo que viene cuando el abuelo muere en medio de una iteración del bucle de process_frenada, que no detecta que ha muerto e intenta acceder a sus valores. ¿Es posible esto? Entonces el mismo problema se presentaría aunque viniera de un collision.
nadie puede morir fuera de un frame... mientras un proceso se ejecuta, ningun otro lo hace, solo cuando se ejecuta un frame se ejecuta otro proceso. pense que ya lo habia dejado en claro...
cambiaste el punto 1)
Perdona splinter, sí que lo cambié, y ahora parece que ya no da ese error, he recredo , bueno , he hecho lo mismo que hacía antes cuando daba el error tres o cuatro veces y lo he llevado un poco al límite y ya no aparece, parece que la sutileza no es mi fuerte, ja jaja. Muchas gracias. Como ya dije, a los créditos que vas.
Hola a todos, me acabo de leer el hilo entero mientras buscaba información sobre el uso de signal.
La cosa es que quiero "capturar" una señal para que mi proceso disparo realice una acción cuando el proceso enemigo le manda una señal...
Había pensado que signal_action devuelve un valor si se recibe la señal y otro valor si no es así, pero no consigo llegar a buen puerto... ¿Alguien sabe decirme en qué se basa el valor que devuelve sig_action? He leído el function_list y he mirado otras fuentes pero no hay manera...
En cualquier caso gracias!
no, signal_action permite decir si una señal sera ignorada o no...
lo que vos queres hacer lo podes hacer seteando una variable local a un proceso con un valor determinado... y chequear en este ese valor...
¿Quieres decir que si el proceso disparo tiene la variable:
LOCAL bool muerto=FALSE;
un proceso enemigo podría ejecutar:
IF (objeto=collision(type disparo)) objeto.muerto=TRUE; END?
Pensaba que el acceso a variables locales a partir del ID del proceso había dejado de ser posible, creo recordar que en Fenix 0.92 no podía hacerse, corrígeme si me equivoco que soy un poco noob...
Y por supuesto, ¿La captura de señales (En plan sistema operativo UNIX) no puede hacerse en procesos de Bennu?
si, se podia y se puede... pero tenes que usar ==, si usas = estas asignando el valor TRUE a objecto.muerto
la captura de señales, de momento no es posible...
pero posiblemente en un futuro se podra hacer algun modulo...
OK, Splinter, esa característica me será no de mucha, sino de MUCHíSIMA ayuda.
En el ejemplo de código sí que quería asignar un TRUE a la muerte del disparo, para que el disparo sepa que debe morir. Lo de detectar colisiones mutuamente entre procesos distintos lo tenía un poco atragantado pero creo que ya tengo la solución.
Thanks!
;)