Comunidad Game Maker

Ayuda => Preguntas y respuestas => Mensaje iniciado por: s_alamina en Julio 10, 2017, 04:56:06 AM

Título: Ayuda con colisiones
Publicado por: s_alamina en Julio 10, 2017, 04:56:06 AM
He tenido muchos problemas con las colisiones en un juego en el que estoy trabajando, me gustaría mucho si alguien pudiera ayudarme a arreglarlo.

Es un juego con vista top-down. El jugador es un personaje que tiene un arco y dispara flechas.

El código con el cual el personaje se mueve es el siguiente:

if place_free(obj_player.x-character_speed,y) {
    x -= character_speed;
}


Eso es para moverse hacia arriba. Y character_speed está definido como 3. Por lo que sé, la función place_free sirve con objetos sólidos únicamente, por lo cual los únicos objetos sólidos son las paredes y el personaje, ya que si el enemigo también es sólido, el jugador queda atascado en él.

Los enemigos tienen speed = 1.6 y siguen al jugador (cuando éste está en su campo de visión) con la función:

mp_potential_step(obj_player.x,obj_player.y,speed,false);

evitando así, solo los objetos sólidos, es decir, las paredes y no se enciman sobre el jugador, pero igual lo dañan. Sin embargo, hay problemas entre esas colisiones ya que los enemigos, como el jugador igual es sólido, a veces no atacan al jugador de una forma correcta.

Además, los enemigos se amontonan y quedan unos encima de otros, dándole un efecto un poco feo. Me gustaría que no se amontonaran entre ellos, que pudieran esquivarse alguna forma. Sin embargo, no los puedo hacer sólidos ya que eso, como dije antes, provocaría que el personaje se atascara en ellos y no se pueda mover. Y si ajusto el mp_potential_step para que eviten todos los objetos, incluyendo los que no son sólidos, esquivarán objetos en el mapa que están "sobre el suelo" y no tienen por qué esquivar, como monedas, flechas, etc, dándole otro efecto feo al juego.

El código con el cual se establecen las colisiones entre los enemigos y el personaje lo carga el personaje en el evento Step y es el siguiente:

if place_meeting(x,y,obj_enemy_xenemigo) { ... }

Entonces esos son los problemas, que los enemigos se amontonan, a veces no atacan al jugador, a veces hay problemas entre colisiones y es difícil arreglarlo todo sin afectar la jugabilidad,. Igualmente, me gustaría agregar knockback cuando los enemigos chocan con el jugador, ya que los enemigos sí cuentan con knockback, pues cuando una flecha les pega, su speed se convierte en un valor negativo por unos momentos (con ayuda de una alarma), pero no logro hacer un buen sistema de knockback para el jugador sin que se vea feo. Pues moverlo ciertos pixeles al lado contrario de donde fue atacado no se ve bien. Una vez intenté con el siguiente código, pero tampoco quedé muy convencido:

    direction = point_direction(x,y,EnemyWhoHitMe.x,EnemyWhoHitMe.y);
    speed = -5;
    alarm[X] = 8;


Y en alarm[X], para que volviera a la normalidad:

    direction = 0;
    speed = 0;


Espero alguien pueda ayudarme con ésto porque lo he intentado solucionar desde que empecé el juego lo más que he podido. Si necesitan más datos, háganmelo saber y les ayudaré a ayudarme :D. El juego no usa físicas ya que aún no las sé usar, pero si fueran a servir mucho mejor, igual háganmelo saber. Además, aún soy relativamente nuevo en todo esto de GameMaker, por lo que traten de ser lo más explícitos en sus respuestas, por favor :).
Título: Re:Ayuda con colisiones
Publicado por: Clamud en Julio 11, 2017, 06:08:50 PM
El personaje podría ser no-sólido para que los enemigos puedan tocarlo, el empalme se evitaría con código. Tengo un sistema en el que el personaje y los enemigos tienen máscaras de colisión rectangulares, pero reaccionan a las colisiones como si fuesen circulares.
(http://i.imgur.com/LHEM6YA.gif)
Es un script pequeño, pero necesitas conocer un poco de álgebra vectorial para entenderlo. Se coloca en un evento de colisión.
[gml]
///Colisión con un objeto movil
//Los objetos se desplazan de forma simetrica

d = point_distance( x,y, other.x,other.y ); //distancia
e = r + other.r - d; //empalme

if( e > 0 ) //si hay empalme
{
    dx = (x-other.x)*e/d/2; //componentes del
    dy = (y-other.y)*e/d/2; // desplazaminto
   
    x += dx;       //desplazar las dos
    y += dy;       // instancias en cantidas
    other.x -= dx; // iguales, pero en
    other.y -= dy; // direcciones opuestas
}
[/gml]
Es necesario que las dos instancias que colisionan tengan definida la variable r, que indica su radio.

Para realizar el knockback puedes usar las variables speed y friction, así el personaje se detiene automáticamente. Observa si eso no afecta el sistema de colisión que ya tienes establecido.