Hola.

Estoy creando un plataforma de estilo Super Mario Bros. original, de hecho lo estoy intentando imitar al pié de la letra, pero con mi propio código, y tengo dudas con los saltos.

El caso es que no sé como crear un salto, por así decirlo coherente.

Por citar los puntos que veo más importantes, busco:
-Que el salto no se detenga hasta que deje de pulsar el botón de salto o hasta que llegue a una determinada altura, p.ej. el doble de la altura del personaje (que creo que es la máxima altura que alcanza Super Mario después de usar un champiñón).
-Y que al comienzo del salto tenga más velocidad vertical y que a medida que vaya avanzando, esta velocidad vaya disminuyendo, primero más sutilmente y de forma más brusca al final.

Básicamente busco las mismas mecánicas que en dicho juego.

De momento este es el código que he escrito para el salto:

//Movimiento vertical

key_jump    =   keyboard_check(vk_space);
ground        =   place_meeting(x,y+vspeed,obj_wall)

if key_jump
{
    if vspeed >= -12
    {
        vspeed -= 0.75;
    }
}
if key_jump = 0
{
    if vspeed <= 16
    {
        vspeed += 1;
    }
    if ground
    {
        vspeed = 0;
    }
}

Con esto el salto queda tosco, no tiene límite vertical positivo, y además el salto comienza lento y aumenta su velocidad con el tiempo, consiguiendo lo contrario de lo que quiero.


Por otro lado tengo un pequeño problema con los sprites. Y es que al cambiar el sprite de salto al sprite en el suelo, hay como cierto retraso desde que el objeto entra en contacto con el suelo, hasta que cambia al sprite adecuado.

Aquí dejo el código que utilicé para el cambio del sprite.

ground      =   place_meeting(x,y+vspeed,obj_wall)
if !ground
{
    sprite_index = spr_salto;   
}


Les agradecería una respuesta explicita a los puntos que he tratado con el tema del salto o que tal vez me recomienden algún tipo de script para la aceleración, o lo que os parezca más adecuado.

Gracias de antemano.

Proba de esta forma
[gml]
key_jump=keyboard_check(vk_space)

if (keyboard_check_released(vk_space) and vspeed<0) {vspeed=0}

ground=place_meeting(x, y+1, obj_wall)

if ground {gravity=0} else {gravity=0.6}

if (ground and key_jump) {vspeed=-10}
[/gml]
Ademas en el evento de colision con la pared
[gml]
y=yprevious
while !place_meeting(x, y+sign(vspeed), other) {y+=sign(vspeed)}
vspeed=0
[/gml]

Gracias por responder.

El salto ya ocurre como buscaba. Aunque hice una modificación al código que mostraste.
Debajo de:

if ground {gravity=0}

Escribí:

while(!place_meeting(x,y+sign(vspeed),obj_wall))
    {
        y += sign(vspeed);
    }
    vspeed = 0;

Solucionando además el pequeño lag que ocurría al cambiar del sprite salto al sprite en el suelo.

El código de colisión con el suelo no fue necesario.