Problema con collision();

Started by Raziel, February 21, 2013, 05:00:03 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Raziel

He estado programando algo bastante sencillo cuando se me ocurrió hacer que, cuando un determinado enemigo colisionara con el gráfico del personaje, no fuera capaz de moverse, para así dar la impresión de que no puede "atravesarlo". Pero, cuando quise hacer lo mismo con el personaje, es decir, que al colisionar con el enemigo no fuera capaz de atravesarlo, me encontré con un problema al que no le encuentro solución: una vez ocurrida la colisión, ninguno de los dos podemos desplazarnos hacia ninguna parte. Me gustaría que me ayudaran a resolver este problema. He aquí el código:

Import "mod_text";
Import "mod_video";
Import "mod_key";
Import "mod_screen";
Import "mod_map";
Import "mod_rand";
Import "mod_sound";
Import "mod_grproc";
Import "mod_proc";

Global

int idcon;
int idpers;
int idenem;
int idmus;
int idmus2;

end


main ()

begin

   idcon = load_fpg ("contenedor.fpg");
   set_mode (640, 480, 32);
   put_screen (idcon, 3);
   
   idmus = load_wav ("machete.wav");
   idmus2 = load_wav ("monstruos.wav");
   
   idpers = personaje();
   idenem = enemigo(320, 240, idcon, 2, 100);
   
   
loop

if (key (_esc))

let_me_alone();
exit(0);

end

   frame;
   
end

end



personaje ()

private

int acertado;

end

begin

file = idcon;
graph = 1;
x = 50;
y = 50;

loop

if (!collision (type enemigo))

if (x - 15 > 0 && key (_LEFT) ) x = x - 2; end
if (x + 15 < 640 && key (_RIGHT)) x = x + 2; end
if (y - 15 > 0 && key (_UP)) y = y - 2; end
if (y + 15 < 480 && key (_DOWN)) y = y + 2; end

end

acertado = collision (type siervo);

if (acertado != 0)

signal (acertado, s_kill);

end

   frame;
   
end

end



enemigo (x, y, file, graph, size)

Private

int dx;
int dy;

end

begin

loop

if (!collision (type personaje))

dx = idpers.x - x;
dy = idpers.y - Y;
x = x + sign (dx, 1);
y = y + sign (dy, 1);

end

if (rand (0, 1000) > 995)

siervo ();
siervo ();
siervo ();
siervo ();

play_wav (idmus2, 0);

end

   frame;
   
end

end


siervo ();

Private

int dx;
int dy;

end

begin

file = idcon;
graph = 2;
x = father.x + rand (-30, 30);
y = father.y + rand (-30, 30);
size = 25;

dx = idpers.x - x;
dy = idpers.y - y;

loop

x = x + sign (dx, rand (2, 3));
y = y + sign (dy, rand (2, 3));

if (x < -5 || x > 645 || y < -5 || y > 485)  break; end

frame;

end

end



function sign (int a, int b)

private

int R;

end

begin

if (a < 0) R = -b; end
if (a > 0) R = b; end
if (a == 0) R = 0; end

return(R);

end


El enemigo está programado para seguirme todo el tiempo y dispararme. Les dejaré los recursos adjuntos para que lo puedan probar y ver a lo que me refiero. Si tienen alguna sugerencia, las tomaré con gusto.

Arcontus

Creo que el problema es obvio y tu mismo has llegado a la solucion aun que aplicarla es un poco más dificil.

Para empezar si se encuentra un enemigo con el pj y ambos colisionan, está claro que ambos no pueden avanzar, pero no debería impedir que retrocedieran... Claro que los conceptos "avanzar" y "retroceder" son los que te va a costar más o menos programar, ya que pueden tener muchas casuisticas diferentes.

Yo en tu lugar, comenzaría haciendo la casuistica más sencilla, que es que ambos procesos van uno hacia la izquierda y otro a la derecha encontrandose en un punto. Proceso a y b.
a-->
<--b

Para saber hacia donde SI pueden moverse, es tan facil como obtener "donde" se encuentra la posicion del otro proceso, relativo al actual proceso que comprueba, de manera que el proceso "b" verá que colisiona con el proceso "a" por la izquierda, y justo la inversa para el otro proceso. Para determinar donde se encuentra el otro proceso, puedes utilizar get_angle() o fget_angle(), aun que puedes utilizar otros métodos.
http://wiki.bennugd.org/index.php?title=Get_angle
http://wiki.bennugd.org/index.php?title=Fget_angle

Espero haberte sido de utilidad,
Un saludo

5Leaps, el primer juego comercial desarrollado para BennuGD. http://www.5leaps.com

fulgorelizz

saludos!! algo parecido me acontecia con la programacion de juegos de plataforma y la gravedad, puedes programar la limitante de tu personaje desde tu enemigo, para ello te recomiendo el uso de variables locales declaradas desde el programa principal:


imports...

glocal

int idpers;//id delñ personaje principal

end

local

int velocidadx,velocidady;//en caso de que se presentebn casos similares

end

process main()

//--- todo el cuento que ya sabemos

personaje();//yo capturo el id desde el momento que se crea el proceso por si olvido hacerle la asignacion desde otra linea de codigo
objeto(x.....);//parametros que usaras


//proceso personaje...

process personaje()
begin
idpers=id;//capturo el id

//... todo el cuento de controles, los limites lo programaremos desde el objeto enemigo
loop

//si presiono el cursor derecho muevo a la derecha el personaje
if(key(_right))velocidadx=2;
else if(velocidadx>0)velocidadx=0;end //si se estaba movimendo a la derecha y dejo de presionar la tecla lo freno

if(key(_left))velocidadx=-2;//pasa lo mismo que con el cursor derecha pero a la inversa
else if(velocidadx<0)velocidadx=0;end

x+=velocidadx;//sumo la velocidadx a x para mover al personaje

frame;
end

end



//proceso que controlara limites segun colision
process objeto(x....)//parametros que ya sabes
begin

loop
//aqui empieza la locura
//desde aca controlare lo siguiente
//recomiendo comprobar si el personaje existe para evaluar las colisiones
if(exists(idpers))
//si se mueve a la derecha
//si el personaje se mueve a la derecha y el objeto a la izquierda ninguno puede moverse
if(idpers.velocidadx>0 and collision(type personaje) and velocidadx<0)
idpers.velocidadx=0;velocidadx=0;end

end//fin exists

x+=velocidadx;
frame;
end

end



espero te sirva!! pruebalo si tienes alguna duda escribe!! estamos para servirte 8)
Compiling code -- generating exe...

Raziel

Sinceramente ya no sé qué hacer  :-[  Pruebo con las diferentes funciones de ángulos y no puedo dar solución al problema. Hasta ahora vengo probando este trozo de código y no entiendo por qué no funciona:

loop

distancia = get_dist(idenem);
angulo = get_angle(idenem);
write_var(0, 50, 15, 0, angulo);
write_var(0, 550, 15, 0, distancia);

if (x - 15 > 0 && key (_LEFT) ) x = x - 2;  end
if (x + 15 < 640 && key (_RIGHT) && angulo != 0 && distancia != 30) x = x + 2;  end
if (y - 15 > 0 && key (_UP)) y = y - 2;  end
if (y + 15 < 480 && key (_DOWN)) y = y + 2;  end

Observen más que nada el RIGHT, dónde pongo que mientras el ángulo respecto del proceso enemigo sea distinto de 0 (es decir, no esté a la izquierda del enemigo) y la distancia sea distinta de 30 (porque cada imagen es de 30x30, y ya que los centros están en la mitad de cada gráfico, están a 15 píxeles del límite) no puede moverse. En fin, el operador lógico AND no hace que se cumplan debidamente todas las condiciones.

Disculpen si es un embrollo todo esto XD

fulgorelizz

dame unos minutitos!! descargue tu codigo!  8)
Compiling code -- generating exe...

fulgorelizz

Compiling code -- generating exe...

laghengar

#6
Yo al final lo resolví usando un mapa de durezas dinámico (no se si existe el concepto pero imagino que sí) evitando usar el collision para estos casos. Cada proceso pintaba en el mapa su localización y hacía que el resto de los procesos vigilaran que ahí no hay nada. Claro que tras cada frame hay que repintar para que cuando el proceso se desplace no quede esa zona ya pintada para siempre, quiero decir: Pintas, frame, repintas; desplazas el proceso, pintas, frame, repintas...

Es más, ya que estoy pongo otra cosa, esto del mapa de durezas dinámico lo puedes pintar con diferentes colores de forma que puedes hacer que el proceso actue de una u otra manera dependiendo del color con el que se encuentre, esto es: tienes una plataforma que se desplaza, pintas un rectángulo rojo en el mapa de durezas dinámico, haces que el proceso que manejas mire de que color es el pixel que tiene debajo, que es rojo, pues desplazamos nuestro proceso hacia el frente. Y si hacemos que la plataforma se desplace a la misma velocidad tenemos una bonita interacción entre nuestro proceso y la plataforma que lo transporta. Que pa colmo, si haces que el desplazamiento de nuestro personaje con las teclas se añada a la velocidad de la plataforma, nuestro personaje va más rápido. Cuidao que lo tiras.
!!!Blender Blender Blender yuhuuuuuuu¡¡¡ novato o_O

Raziel

Lo siento Laghenngar, pero soy todavía un completo novato y aún no he llegado a lo de mapa de durezas  :P Este "juego" que programé es tan sólo un base experimental gracias a la cual me saco dudas... pero esto de las colisiones aún no lo resuelvo. Si no es mucho pedir, ¿podrían elaborar un código sencillo donde un personaje no puede atravesar a un enemigo y viceversa? Y Fulgorelizz, es verdad, es un caso que me sorprendió bastante  :o Debido a que soy novato, me costará bastante ingeniarme algún sistema de direcciones propio XD

laghengar

Quote from: Raziel on February 21, 2013, 11:03:44 PM
Lo siento Laghenngar, pero soy todavía un completo novato y aún no he llegado a lo de mapa de durezas  :P Este "juego" que programé es tan sólo un base experimental gracias a la cual me saco dudas... pero esto de las colisiones aún no lo resuelvo. Si no es mucho pedir, ¿podrían elaborar un código sencillo donde un personaje no puede atravesar a un enemigo y viceversa? Y Fulgorelizz, es verdad, es un caso que me sorprendió bastante  :o Debido a que soy novato, me costará bastante ingeniarme algún sistema de direcciones propio XD

Pues si no lo entiendes, hay un problema, XD y mejor será que lo olvides. Es complicado de explicar y tienes que conocer las funciones de crear mapas, pintarlos, agregarlos a un fpg, etc, etc.

No se entiende por código, si no por práctica.
!!!Blender Blender Blender yuhuuuuuuu¡¡¡ novato o_O

Raziel

Jajaja Laghengar, todo lo que dijiste sí lo entiendo, sólo que no he llegado a manejar los mapas de durezas... Eso último es fácil XD

laghengar

#10
Joeeeee, pues ánimo hombre, verás que lo único que tiene es que hay que ser ordenado, y lo consigues, incluso lograrás hacer cosas muy guays.

Si vas a usar en el juego un mapa de durezas, para esto que te digo usa otro diferente, que esté vacio y solo sirva para pintar y repintar lo que te he comentado. De repintar me refiero a pintarlo de nuevo con el color original que tenía el mapa.

A ver si no te lio, la cosa iría así.


Process protagonista()

loop

                                                Miro en el mapa de durezas dinamico si hay algo rojo debajo
if(map_get_pixel(fpg_tal, mapa_durezas_dinamico, x_loquesea, y_loqueseadebajo) == rojo)
       que lo hay, pues le digo que lo tome en cuenta para que avance el muñecote.
       inc_x++;
end

if(key(palante))
       que pulso la tecla, pues el muñecote avanza más todavía.
       inc_x++;
end
....

muevo al muñeco

frame;

end
.....
y todos los end que te hagan falta


process plataforma()
.......


begin

muevo la plataforma

pinto el lugar de la plataforma en el mapa de durezas dinámico de rojo

frame;

repinto el lugar para dejarlo vacio, ya que si no lo haces lo que has pintado antes se queda para siempre, así que si vuelves con el personaje por ese sitio vas a ver que te detecta la plataforma aunque ya no esté allí.
 

end




Espero que lo hayas entendido, en fin, suerte.
!!!Blender Blender Blender yuhuuuuuuu¡¡¡ novato o_O

Raziel

#11
¡Buenas noticias! Si bien he tenido en cuenta sus sugerencias, después de horas y horas de probar (sí, horas  :o ) distintos códigos y después de enredarme un sinfín de veces, he dado con una manera bastante grotesca pero útil de detectar colisiones. Sin embargo, a pesar de detectar las colisiones desde arriba, abajo, izquierda, derecha, me di cuenta de que no lo hace diagonalmente (no sé si me explico). Les dejaré el nuevo código fuente con todos los recursos para - si no es molestia - que lo comprueben y vean cómo colisiona y las imprecisiones que tiene al hacerlo. XD

fulgorelizz

 8) nice que hayas conseguido solucion!! en un rato echo vista a tu codigo!! aqui te subi lo que pude hacer, espero te sea de utilidad!! es un codigo que simula la inercia!! ....
Compiling code -- generating exe...

fulgorelizz

Quote from: fulgorelizz on February 22, 2013, 03:55:37 PM
8) nice que hayas conseguido solucion!! en un rato echo vista a tu codigo!! aqui te subi lo que pude hacer, espero te sea de utilidad!! es un codigo que simula la inercia!! ....

en el mensaje esta adjunto el codigo nuevo, prueba_2.prg, copialo en tu directorio donde esta prueba.prg, saludos!!
Compiling code -- generating exe...

Erkosone

Has pensado en usar la mod_chipmunk para automatizar todo esto de las colisiones? es que hoy en día ya nadie trabaja como lo hacíamos en Div todo a mano, con un par de lineas creas el escenario y dejar que la librería de física resuelva todo esto que para eso se crearon jeje, te animo a que lo pruebes, si no sabes como solo tienes que preguntar por que la mod_chipmunk para hacer un juego tipo RPG o cualquier cosa así es muy buena, gasta infinito menos recursos de lo que gastará si lo haces a mano y realmente los resultados son de calidad.