Como implemento a desaceleração?

11

Eu digo "desaceleração" porque não estou usando aceleração no momento; o que quero dizer é mover a velocidade de volta ao zero, eventualmente parando.

Eu sou novo em vetores e não sou tão bom em física e coisas do tipo. Como a "desaceleração" é normalmente tratada?


O que eu tenho agora funciona, mas parece meio tolo .

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);
}

Eu usei 3 porque qualquer coisa menor exibe um comportamento estranho, acho que se eu aumentasse a velocidade, ele precisaria ser alterado.

Xavura
fonte
2
Também detalhes pouco semântica .. na declaração velocity.i += speed;o speedé de fato sua aceleração, ou seja, a taxa que a velocidade muda por. :)
Ipsquiggle
Flixel chama isso de "arrastar", caso você esteja procurando um termo independente da aceleração.
Gregory Avery-Weir
"Desaceleração" é aceleração negativa. Você fez cálculo?
3Dave
1
Na verdade, "desaceleração" não é algo real, nem "aceleração negativa". É tudo aceleração regular, apenas em direções diferentes.
MichaelHouse

Respostas:

16

Algo tão simples quanto

this.velocity.i *= 0.9;

funciona bem.

David Young
fonte
Heh, confiança me a complicar mais-it que ruim. Acabei de ler recentemente que você pode simular a resistência básica do ar multiplicando por 0,9 e ainda assim isso não veio à mente. Obrigado.
Xavura 20/10/10
Haha, uau, sim. Eu estava calculando um vetor inverso normal e multiplicando-o por um fator de desaceleração. Por que eu não fiz isso? Às vezes, as respostas realmente óbvias são as mais fáceis de perder.
CodexArcanum 20/10/10
7

No Pseudocódigo, eu faço variações disso:

Velocidade + = ((MoveDirection * MaximumSpeed) - Velocidade) * AccelerationFactor

Onde:

  • Velocidade é a velocidade atual em que a entidade está viajando no eixo atual.
  • MoveDirection é a direção em que a entidade está tentando viajar no eixo atual, 1 está para a frente, 0 está imóvel e -1 está para trás. Todos os valores intermediários são permitidos.
  • MaximumSpeed ​​é uma constante que determina o mais rápido que a entidade pode percorrer no eixo atual.
  • AccelerationFactor é uma constante entre 0 e 1 que representa a taxa de aceleração e desaceleração. 1 é instantâneo e 0 nunca será movido.

Que lida com a aceleração e a desaceleração de maneira agradável em uma curva, em vez de uma linha. Se você quiser diferentes taxas de aceleração e desaceleração, poderá fazer instruções IF que determinam se o jogador está tentando não se mover ou se mover na direção oposta.

earok
fonte
1
Essa é uma fórmula muito interessante. Vou ter que ter isso em mente para o futuro!
Ipsquiggle
+1 Parece interessante, acho que posso colocá-lo em algum código para vê-lo funcionar.
David Young
Fórmula muito boa. Eu vou usar isso. De onde você pegou isso? Ou você mesmo derivou?
Riki 25/09
Desculpe o atraso em responder, lembro-me vagamente de ter sido inspirado pelo código de uma das demos do Blitz3D, mas não lembro qual delas.
earok
3

As respostas aqui ( vel = vel * 0.9) são realmente amortecedoras , não o que eu consideraria 'desaceleração' .

Costumo desacelerar assim:

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);
    }
}

Alguns prós e contras vs. amortecimento:

Prós :

  • A aceleração da aceleração e a desaceleração são lineares, o que proporciona uma agradável sensação sutil de jogo que acho que o amortecimento não proporciona. Este é o importante parte .
  • O personagem chega a uma parada completa previsível após um número previsível de iterações.

Contras :

  • Isso é mais difícil de implementar se você estiver usando movimento não ortogonal (o que parece que você é?) Basicamente, é necessário obter um vetor de força alinhado com a velocidade, comparar comprimentos e subtrair ou zerar conforme apropriado. (Se você quiser que isso seja explicado com código, basta perguntar.)
Ipsquiggle
fonte
1

Simplificando, em pseudo-có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]

No entanto, você precisaria verificar se (velocidade atual <0,001f) ou algo assim e definido como 0.

O Pato Comunista
fonte
Eu imaginei que teria que colocar um cheque no lugar também, mas parece funcionar sem um.
Xavura 20/10/10