Enero 18, 2020, 08:28:11 PM Ultima modificación: Mayo 19, 2020, 06:04:04 AM por T789
Hola, estaba trabajando en un juego de plataformas y se me ocurrio una idea pero no se como hacerla ya que no se hacer colisiones propias

busco hacer una plataforma en la que pueda caminar y que cuando oprima la tecla de abajo mi jugador descienda de ella, seria muy parecido a una plataforma atravesable desde abajo pero lo que busco seria atravesarla desde abajo, luego caminar en ella y al oprimir abajo caerme de ella

alguna sugerencia o codigo que pueda usar

Lo que podés hacer es que el objeto en cuestion no sea solido y solamente verificar la colision cuando el personaje está cayendo, o que podría ser equivalente a decir vspeed > 0
entonces la coilsion no actua cuando se le da por debajo vspeed < 0 sino todo lo contrario.



Funcionaria bien pero el truco no seria que fuera solido para asi poder descender de la plataforma, pues eso ya arregla atravesar desde abajo la plataforma pero lo que busco tambien seria descender la plataforma y necesito verificarlo de alguna manera al oprimir la tecla en cuestion

Podrias usar una variable dentro de la plataforma que indique si tiene al personaje encima entonces verificar la colision.
Si el jugador presiona abajo, seterias la variable en false, y no tendria lugar la colision.

O hacerlo solido/no solido.



Bueno me parece mejor opcion lo que tu dices, pero como haria para hacer la colision pues usaba el decectuoso "move_contact_solid" y como ya no seria solido me apareceria error, digo el movimiento en la colision pues quiero que pueda hacer lo que en una plataforma normal

Hola T789

Lo ideal sería que usaras tu propio sistema de colisión.
Pero si prefieres usar el sistema integrado de game maker, lo que se me ocurre es que la plataforma sea sólida cuando el player esté por encima de la plataforma
y que sea NO sólida cuando el player está por debajo de la plataforma, además hacer la plataforma NO sólida cuando pulsas abajo.

Se me ocurre que en el STEP EVENT del objeto plataforma, añadas esto:
if object_exists(obj_player) { //Primero revisa si existe un objeto llamado "obj_player" en la room
if obj_player.bbox_bottom < bbox_top { solid = true } //Comprueba las coordenadas de la bounding box del player vs la plataforma. Si el player está arriba, la plataforma se hace sólida
else { solid = false } //Sino, la plataforma se hace NO sólida
}
if keyboard_check_pressed(vk_down) { //Cuando pulsas Abajo
solid = false //La plataforma ya no será sólida
}


Saludos

Gracias a funcionado perfecto solo he tenido que hacer algunas correciones en el codigo que me diste pero igual funciona a la maravilla

Un posible problema en cambiar la variable solid de la plataforma, es que si tenes por ejemplo 2 jugadores o un jugador y un enemigo, cuando atravieses la plataforma o quieras bajar el otro tambien lo hara.
Lo que yo hago es ver la colision solo en los pies del jugador, usando collision_line o collision_rectangle y solo cuando se esta bajando. Cuando quieras descender solo mueves al jugador 1 pixel hacia abajo.

Lo que dices es verdad todos los enemigos que esten parados sobre la plataforma también descenderan pero ya intentado utilizar el collision _rectangle y siempre sucede un error o falla la colision

Hola T789

Tienes razón, si quitas el estado "sólido" de la plataforma entonces todos los objetos de la room que interactúan con la plataforma se verán afectados.

Lo que se me ocurre es que hagas que las plataformas NO sean sólidas y uses la función "instance_place" para detectar la colisión. Esta función hace lo mismo que el "place_meeting", pero en vez de devolver "true/false", te devuelve el ID del objeto con el que colisionas (o "noone" si no colisionaste con ningún objeto).

Así podrás saber si colisionarás con una plataforma o no sin que la plataforma deba ser sólida.

[gml]var plataforma = instance_place(x,y+max(1,vspeed),obj_platform) //Esto guarda el ID de la plataforma con la que colisionas (o noone) en una variable local para no tener que repetir la condición después en el código. el objeto lo llamé "obj_platform", tú llámalo como lo hayas hecho tu.
var plataforma_debajo = false //Esto setea otra variable local llamada "plataforma_debajo" donde guardaremos "true" si debajo nuestro hay una plataforma o "false" si no lo hay. Por defecto su valor queda en false
if plataforma != noone { //Esto se ejecuta cuando el script detectó que debajo nuestro vamos a colisionar con una plataforma.
if !place_meeting(x,y,plataforma) { plataforma_debajo = true } //Esta línea hará la magia. En caso que abajo nuestro haya una plataforma y NO estés atravezándola, entonces la detecta como colisión. Si caes y atraviezas al menos 1 pixel de la plataforma, el código ya deja de detectarla como colisión, eso te permitirá atravezarlas al pulsar Abajo.
}

//Salto
if keyboard_check_pressed(vk_up) && (place_meeting(x,y+1,obj_block) || plataforma_debajo) { vspeed = -14 } //Si pulsas la flecha "arriba" y debajo tuyo hay un bloque sólido o debajo tuyo hay una plataforma, entonces te permite saltar.
//Aquí puse la tecla "arriba", nombré el objeto "obj_block" y asigné "vspeed" -14 como ejemplos, pero tú usa tus teclas, tu nombre de objeto y tu propio código de salto.

//Bajar las plataformas
if keyboard_check_pressed(vk_down) && !place_meeting(x,y+1,obj_block) && plataforma_debajo { y += 1; plataforma_debajo = false } //Si estás parado en una plataforma y apretas abajo, bajas 1 pixel para que el juego deje de detectar que estás sobre la plataforma y te deje atravezarla.

//Sino, primero colisiona con un bloque sólido
else if place_meeting(x,y+vspeed,obj_block) { while !place_meeting(x,y+sign(vspeed),obj_block) { y += sign(vspeed) }; vspeed = 0; } //Esta línea es un script de colisión precisa, hace lo mismo que el move_contact_solid pero funciona para colisionar contra objetos NO sólidos, en este caso le dije que chocara contra el "obj_block".
//Ahora colisiona con la plataforma (sólo si vas cayendo, si vas hacia arriba no hay ningún tipo de detección de colisión)
else if vspeed >= 0 { //sólo si caes
if plataforma_debajo { while !place_meeting(x,y+1,plataforma) { y += 1 }; vspeed = 0; } //Es el mismo código de colisión precisa.
}

//Caes por acción de la gravedad
if !place_meeting(x,y+1,obj_block) && !plataforma_debajo { gravity = 0.8 } //Si no hay nada debajo, caes por graverdad
else { gravity = 0 } //En cambio si había algo debajo, obviamente NO caes.[/gml]

Saludos

Bueno funciona correctamente, al principio no lo entendi pero ya si

gracias por solucionar mi problema

#11 Enero 24, 2020, 05:04:26 AM Ultima modificación: Enero 24, 2020, 05:08:41 AM por dixon
Hola,

No quería responder tarde, pero... Aquí les traigo un código simple que se coloca en el evento draw del player 1. Y no requiere mas nada

Imagen del ejecutable, se pueden ver dos players con forma de pelota verde y roja los cuales interactúan con las plataformas sin problemas.


Bueno, concretamente la plataforma traspasable que presento tiene las siguientes características.

1. Se verifica plataforma solo cuando esta cayendo el personaje como lo indica Black_cat.
2. Fue necesario crear un sistema de colisión como lo sugirió BssString
3. Dos players pueden estar en la misma plataforma sin afectar el movimiento de uno u otro. Como lo indica 3dgeminis
4. La plataforma puede tener cualquier forma, no necesariamente rectangular, puede ser ovoide, piramidal y sin forma definida.
5. La plataforma puede tener cualquier grosor, puede ser de un solo pixel de espesor
6. La plataforma puede girar sobre su eje sin alterar su funcionamiento.

El siguiente código se coloca en un evento draw del player1, mientras el player dos debe ser pariente del uno.
//simulando evento create dentro de eento draw
if(score<2)
{
//botones
b2=0
b4=0

//variables
s=0 //salto
d=1 //direccion
estado="aire" //estados del personaje, si esta en el aire o en el suelo
gravedad=15 //esto es la gravedad que impulsa al personaje al suelo
colision=0 //si se va a evaluar la colision entre la plataforma
player=0
if(score=0){player=1}
if(score=1){player=2}
}
score+=1

//botones
if(player=1)
{
if(keyboard_check(113))game_restart()
b1=keyboard_check(vk_left)
b2p=(b2=0)*keyboard_check(vk_up)
b2=keyboard_check(vk_up)
b3=keyboard_check(vk_right)
b4p=(b4=0)*keyboard_check(vk_down)
b4=keyboard_check(vk_down)
}

if(player=2)
{
//botones
if(keyboard_check(113))game_restart()
b1=keyboard_check(ord("A"))
b2p=(b2=0)*keyboard_check(ord("W"))
b2=keyboard_check(ord("W"))
b3=keyboard_check(ord("D"))
b4p=(b4=0)*keyboard_check(ord("S"))
b4=keyboard_check(ord("S"))
}
//estados del personaje, en el suelo o en el aire
if(place_free(x,y+gravedad)){estado="aire"}else{estado="suelo"}
if(colision){estado="suelo"}

//movimiento y
if(b2p*(s=0)*(estado="suelo"))s=gravedad*2
if(s)s-=1
while(!place_free(x,y-s))s-=1
if(s<0)s=0

y+=gravedad-s
while(!place_free(x,y+1))y-=1


if(colision=0)
{
for(i=0;i<=gravedad;i+=1)
{
if((place_meeting(x,y,object2)=0)*(y>yprevious))
  {
  if(place_meeting(x,y+i,object2)){colision=1}
  }
}
}

if(b4p)colision=0

if(colision){while(place_meeting(x,y+1,object2))y-=1}
if(colision*(place_meeting(x,y+gravedad,object2)=0))colision=0

//movimiento x
control=(b1+b3=1)
if(control)d=1-2*b1
v=floor(gravedad/3)*d
while(!place_free(x+v,y-5))v-=sign(v)
x+=v*control

//salir de la room
if(x>(room_width-10))x=10
if(x<10)x=room_width-10

//dibujo
dy=0

texto="Colision: "+string(colision)
draw_text(0,dy,texto)
dy+=20
texto="estado: "+string(estado)
draw_text(0,dy,texto)
dy+=20
draw_sprite(sprite_index,0,x,y)


Para que funcione:
1.   El código debe ser colocado en un evento draw del player 1, el player dos no requiere codigo.
2.   El player dos debe ser pariente del player 1
3.   El Object2 es la plataforma traspasable
4.   los player tienen un sprite sin secuencia de imágenes
5.   La plataforma traspasable no debe ser solida
6.   Las plataformas de los suelos y paredes si deben ser solidas

Pueden descargarlo también por aquí


Si Dios quiere; Limpiaré la oficina, puliré el piso y les serviré café a todos, luego, me enseñarán a programar e iré a comprarles más café.