¿Cómo implemento la desaceleración?

11

Digo "desaceleración" porque no estoy usando aceleración en este momento; Lo que quiero decir es mover la velocidad de regreso a cero, y finalmente detenerse.

Soy nuevo en vectores y no soy tan bueno con la física y demás. ¿Cómo se maneja normalmente la "desaceleración"?


Lo que tengo ahora funciona, pero parece un poco hackear .

update:function(Game, t, dt) {
    var speed = Game.Input.isKeyDown('shift') ? 8 : 4;

    if (Game.Input.isKeyDown('a')) {
        this.velocity.i -= speed;
    }
    else if (Game.Input.isKeyDown('d')) {
        this.velocity.i += speed;
    }
    else {
        if (Math.abs(this.velocity.i) > 3) {
            this.velocity.i += (this.velocity.i > 0) ? -speed : speed;
        }
        else {
            this.velocity.i = 0;
        }
    }

    if (Game.Input.isKeyDown('w')) {
        this.velocity.j -= speed;
    }
    else if (Game.Input.isKeyDown('s')) {
        this.velocity.j += speed;
    }
    else {
        if (Math.abs(this.velocity.j) > 3) {
            this.velocity.j += (this.velocity.j > 0) ? -speed : speed;
        }
        else {
            this.velocity.j = 0;
        }
    }

    this.updateVectors(dt);
}

Usé 3 porque cualquier cosa más baja exhibe un comportamiento extraño, supongo que si aumentara la velocidad, entonces necesitaría ser cambiado.

Xavura
fuente
2
También detalle poco .. semántica en la cuenta de velocity.i += speed;la speedes, de hecho, su aceleración, es decir, la tasa que la velocidad cambia por. :)
Ipsquiggle
Flixel llama a esto "arrastre", en caso de que esté buscando un término que sea independiente de la aceleración.
Gregory Avery-Weir
La "desaceleración" es la aceleración negativa. ¿Has tomado cálculo?
3Dave
1
En realidad, la "desaceleración" no es algo real, ni lo es la "aceleración negativa". Todo es aceleración regular, solo en diferentes direcciones.
MichaelHouse

Respuestas:

16

Algo tan simple como

this.velocity.i *= 0.9;

funciona bien

David Young
fuente
Je, confía en mí a un exceso de complicarlo que mal. Hace poco leí que puedes simular la resistencia básica del aire al multiplicar por 0.9 y aún así eso no me vino a la mente. Gracias.
Xavura
Jaja, oh wow, sí. Estaba calculando un vector inverso normal y multiplicándolo por un factor de desaceleración. ¿Por qué no hice esto? A veces, las respuestas realmente obvias son las más fáciles de perder.
CodexArcanum
7

En Pseudocódigo, hago variaciones de esto:

Velocidad + = ((MoveDirection * MaximumSpeed) - Speed) * AccelerationFactor

Dónde:

  • La velocidad es la velocidad actual a la que viaja la entidad en el eje actual.
  • MoveDirection es la dirección en la que la entidad está tratando de viajar en el eje actual, 1 es hacia adelante, 0 está quieto y -1 está hacia atrás. Todos los valores intermedios están permitidos.
  • MaximumSpeed ​​es una constante que determina lo más rápido que la entidad puede viajar en el eje actual.
  • AccelerationFactor es una constante entre 0 y 1 que representa la tasa de aceleración y desaceleración. 1 es instantáneo y 0 nunca se moverá.

Que maneja tanto la aceleración como la desaceleración en una curva, en lugar de una línea. Si desea diferentes tasas de aceleración y desaceleración, puede hacer declaraciones IF que determinen si el jugador está intentando no moverse o moverse en la dirección opuesta.

Earok
fuente
1
Esa es una fórmula muy interesante. ¡Tendré que tener eso en cuenta para el futuro!
Ipsquiggle
+1 Parece interesante, creo que podría incluirlo en algún código para verlo funcionar.
David Young
Muy buena formula. Voy a usar esto ¿De donde lo sacaste? ¿O lo derivaste tú mismo?
Riki
Perdón por la demora en responder, recuerdo vagamente que me inspiró el código de una de las demos de Blitz3D, aunque no recuerdo cuál.
Ganó el
3

Las respuestas aquí ( vel = vel * 0.9) son realmente amortiguadoras , no lo que yo consideraría 'desaceleración' .

A menudo hago la desaceleración de esta manera:

if ( Game.Input.isKeyDown( "w" ) )
{
    this.velocity.i = Math.max( -WALKSPEED, this.velocity.i - WALKFORCE);
}
else if ( Game.Input.isKeyDown( "d" ) )
{
    this.velocity.i = Math.min( WALKSPEED, this.velocity.i + WALKFORCE);
}
else
{
    if (this.velocity.i < 0)
    {
        this.velocity.i = Math.min( 0, this.velocity.i + WALKFORCE);
    }
    else if (this.velocity.i > 0)
    {
        this.velocity.i = Math.max( 0, this.velocity.i - WALKFORCE);
    }
}

Algunos pros y contras frente a la amortiguación:

Pros :

  • La aceleración de aceleración y la aceleración de desaceleración son lineales, lo que da una agradable 'sensación de juego' sutil que creo que la amortiguación no proporciona. Esta es la parte importante .
  • El personaje se detiene completamente después de un número predecible de iteraciones.

Contras :

  • Esto es más complicado de implementar si está utilizando un movimiento no ortogonal (¿qué suena como si lo fuera?) Básicamente, debe obtener un vector de fuerza que esté alineado con la velocidad, comparar longitudes y restar o poner a cero según sea apropiado. (Si desea que eso se explique con el código, solo pregunte).
Ipsquiggle
fuente
1

En pocas palabras, en pseudocódigo:

if(no movement keys pressed) [Meaning we want to start to decelerate]
current speed *= 0.85 [Or some number between 0 and 1, the smaller the faster the deceleration]

Sin embargo, deberá verificar si (velocidad actual <0.001f) o algo y establecerlo en 0.

El pato comunista
fuente
Pensé que también tendría que poner un cheque, pero parece funcionar sin uno.
Xavura