Comunidad Game Maker

Ayuda => Preguntas y respuestas => Mensaje iniciado por: Hezz en Febrero 02, 2019, 04:53:12 AM

Título: Colision vertical del personaje en una plataforma móvil [SOLUCIONADO]
Publicado por: Hezz en Febrero 02, 2019, 04:53:12 AM
Buenas gente! Tengo un problema con la colision vertical entre una plataforma que se vaya moviendo por el nivel y el personaje. Mi idea es que el personaje se mueva "solo" (o sea, que la plataforma le lleve) al estar encima de la misma. Horizontalmente no tengo ningún problema, pero con las colisiones verticales se me complica.
Personaje: script de colisíon:
[gml]//Colisión vertical
if (place_meeting(x,y+vsp,argument0)){
    while(!place_meeting(x,y+sign(vsp),argument0)) {y += sign(vsp);}
    vsp = 0;
    on_ground = true;
}
//Colisión horizontal
if (place_meeting(x+hsp,y,argument0)){
    while(!place_meeting(x+sign(hsp),y,argument0)) {x += sign(hsp);}
    hsp = 0;
}

//Si atravesó la hitbox en el step anterior
if (place_meeting(x,y,argument0) && last_move != -1){
    switch (last_move){
        case 0:
            while(place_meeting(x-1,y,argument0)) {x++;} //Derecha
            x -= 1;
            break;
        case 1:
            while(place_meeting(x,y+1,argument0)) {y--;} //Arriba
            y -= 1;
            break;
        case 2:
            while(place_meeting(x+1,y,argument0)) {x--;} //Izquierda
            x += 1;
            break;
        case 3:
            while(place_meeting(x,y-1,argument0)) {y++;} //Abajo
            y += 1;
            break;
    }
}

//Actualizar variable
last_move = -1;

//Si atraviesa la hitbox48x48
if (place_meeting(x,y,argument0)){
    //Actualizar variables
    x_ = x;
    y_ = y;
    y_p = 0;
    y_n = 0;
    x_p = 0;
    x_n = 0;
    //Ver qué dirección es la más corta para salir de la colisión
    while(place_meeting(x,y-1,argument0)) {y++; y_p++;} //Desde arriba
    x = x_;
    y = y_;
    while(place_meeting(x,y+1,argument0)) {y--; y_n++;} //Desde abajo
    x = x_;
    y = y_;
    while(place_meeting(x-1,y,argument0)) {x++; x_p++;} //Desde izquierda
    x = x_;
    y = y_;
    while(place_meeting(x+1,y,argument0)) {x--; x_n++;} //Desde derecha
    x = x_;
    y = y_;

    //Mover al objeto a la posición
    var result = min(y_p,y_n,x_p,x_n);
    if (y_p == result) {y += y_p-1; last_move = 3;} //Abajo
    else if (y_n == result) {y -= y_n-1; last_move = 1;} //Arriba
    else if (x_p == result) {x += x_p-1; last_move = 0;} //Derecha
    else if (x_n == result) {x -= x_n-1; last_move = 2;} //Izquierda
}
[/gml]

Plataforma: Evento CREATE:
[gml]
///VALORES GENERALES
change_state = false;
state = true; //Si se está moviendo o no
go_to = 1; //Si es 1, va desde x1, y1 a x2, y2, y si es -1 va desde x2, y2 a x1, y1.
dist = 0; //Distancia entre el punto x, y hasta el destindo
_dist = 0; //Distancia entre el punto x, y desde la salida
dir = 0; //Ángulo entre el punto A y el punto B
hitbox = instance_create(x,y,obj_hitbox48x48); //ID del objeto hitbox que se usará como hitbox de la plataforma

spd = 0;
[/gml]
Plataforma: Evento STEP:
[gml]///CONTROL DE ESTADO
dir = point_direction(x1,y1,x2,y2);
//Cambiar de estado
if (change_state){
    change_state = false;
   
    //Cambiar estado
    if (state) {state = false;}
    else {state = true;}
}

//Comprobar el estado
if (state){
    //Desde qué punto hasta qué punto
    if (go_to == 1) {dist = point_distance(x,y,x2,y2); _dist = point_distance(x,y,x1,y1);}
    else if (go_to == -1) {dist = point_distance(x,y,x1,y1); _dist = point_distance(x,y,x2,y2);}
    //Moverse
    if (_dist < 48) {spd = log10(1.1+_dist/3)*go_to}
    else if (dist < 48) {spd = log10(1.1+dist/3)*go_to}
   
    //Detenerse
    if (dist < spd || (spd < 0.1 && spd > -0.1) && _dist >= 48){
        if (go_to == 1) {x = x2; y = y2; go_to = -1;}
        else if (go_to == -1) {x = x1; y = y1; go_to = 1;}
    }
}

//Colision con el personaje
//if (place_meeting(x,y-1,obj_character)){ ANTERIOR
if (y > obj_character.y - 0.1 && place_meeting(x,y-1,obj_character)){
    obj_character.x += spd * cos(degtorad(dir));
    obj_character.y += spd * -sin(degtorad(dir));
}

//Mover la plataforma
x += spd * cos(degtorad(dir));
y += spd * -sin(degtorad(dir));

//Mover la hitbox
if (hitbox != 0){
    hitbox.x = x;
    hitbox.y = y;
}
[/gml]

Adjunto un video para que se entienda mejor mi problema.
Cuando la imagen del personaje es azul es porque está cayendo. Cuando es roja es porque está quieto o "idle".
Título: Re:Colision vertical del personaje en una plataforma móvil
Publicado por: Clamud en Febrero 02, 2019, 08:05:58 PM
Yo preferiría no utilizar place_meeting, porque utiliza una hitbox con valores redondeados. Puedes crear tu propio sistema de hitbox o puedes utilizar un sistema como este que va almacenando los residuos no enteros de velocidad y solo verifica colisiones con números enteros
https://marketplace.yoyogames.com/assets/1724/moving-platforms

Lo que falta en tu código es hacer que la plataforma mueva al personaje antes de que el personaje se mueva. Si subes el proyecto sería más fácil probar el código.