Como faço para fazer algo que eu pisco / pisque com mais frequência à medida que se aproxima do desaparecimento?

10

No meu jogo, quando você mata um inimigo, ele pode cair algo como um pacote de saúde ou ouro. Eu quero que isso tenha um limite de tempo para que eventualmente desapareça se você não o atender. Eu quero que o item pisque com mais frequência quanto mais perto a gota chegar da "morte". Como você faz o algoritmo "piscando com mais frequência"?

Daniel Kaplan
fonte

Respostas:

2

Minha preocupação com qualquer uma das abordagens atualmente oferecidas é que ambas levem a piscar com 'velocidade variável', o que pode não apenas distrair os jogadores, mas também dificulta a medição exata de quanto tempo um objeto resta antes de desaparecer . Em vez disso, em algum lugar em seus parâmetros (sejam eles global para o renderizador ou em uma base per-objeto) eu teria quatro constantes: slowBlinkTime, slowBlinkRate, fastBlinkTimee fastBlinkRate. Ao renderizar, se a vida restante do seu objeto for menor que fastBlinkTime, pisque-o em fastBlinkRate; caso contrário, se for menor que slowBlinkTime, então pisque slowBlinkRate. Se você quiser ir um passo mais longe, então você pode ter uma variedade de diferentes blinkTimes eblinkRatee verifique-os um por um, mas, na prática, é provável que exagere e apenas ter estados de 'aviso' e 'crítico' deve ser suficiente. O código ficaria assim:

float blinkCycle;
if ( entity.timeLeft < fastBlinkTime ) {
  blinkCycle = entity.timeLeft/fastBlinkRate;
} else if ( entity.timeLeft < slowBlinkTime ) {
  blinkCycle = entity.timeLeft/slowBlinkRate;
}
blinkCycle = blinkCycle - floor(blinkCycle); // find blinkCycle 'mod 1'
if ( (entity.timeLeft < slowBlinkTime) && (blinkCycle < 0.5f) ) {
  renderBlinked(entity); // this should be the 'blinked' state, whether flashed or missing
} else {
  renderNormal(entity); // the normal render for the entity
}

Observe que esse código pressupõe um ciclo intermitente de meia-meia-meia-meia (é o que o 0.5fteste representa), mas pode ser facilmente ajustado para algo como dois terços ligados, um terço desligado apenas ajustando a constante apropriada. Isso também não faz nada para 'sincronizar' o piscar entre os estados rápido e lento, mas é relativamente simples de polir.

Isso deve ser fácil de conectar, e terá a vantagem substancial do IMHO de que os jogadores possam ver a mudança de 'lento' para 'rápido' piscando e saber exatamente quanto tempo resta. Eu começaria com valores de parâmetros como 5s para slowBlinkTimee 0,5s para slowBlinkRatee 2s / 0,25s para fastBlinkTimee fastBlinkRate, mas isso definitivamente depende do seu jogo em particular.

Steven Stadnicki
fonte
Eu não entendo Se o piscar ficar cada vez mais rápido, isso não seria um medidor melhor para exatamente quanto tempo o objeto resta do que apenas dois modos?
Daniel Kaplan
1
@tieTYT O problema é que, especialmente quando a taxa de intermitência é variável, é difícil para os usuários (a) determinar exatamente com que rapidez um objeto está piscando e (b) correlacionar isso com quanto tempo ele dura. Imagine ter um controle deslizante de 0 a 100 vs. um 'switch' com posições em 0, 50 e 100; as pessoas podem adivinhar o valor do controle deslizante entre 5 e 10%, mas saberão exatamente qual é o valor do comutador - e é muito mais difícil medir uma taxa do que uma posição.
Steven Stadnicki
Apesar do que os votos sugerem, acho que esta é a melhor resposta. Além disso, é muito mais fácil de implementar (pelo menos conceitualmente). Minha resposta obteve mais votos, mas ainda não estou satisfeita visualmente. Sua abordagem dará uma aparência satisfatória.
22413 Daniel Kaplan
14

Se t descer de T para 0, você pode usar algo como sin ((T - t) ²); se o número for> 0, você desenha o objeto; se for <0, não


Eu mesmo tentei e tive que mexer com isso. Para mim, T era 100. Essa equação fazia as coisas piscarem super rápido o tempo todo. Então, para diminuir a velocidade, mudei a equação para sin (((T - t) / 10) ²)). Isso foi depois de mexer nos números como / 6 e / 7.

Eu também tentei o seguinte: sin ((T - t) ² * 1/100)

E então eu não gostei de como a gota parecia ser invisível quase tanto quanto era visível. Eu queria que isso raramente fosse invisível. Eu consegui isso fazendo o seguinte: sin ((T - t) ² * 1/100) + .5 Isso + .5 desloca a "linha" do seno para que ele não se torne <0 com tanta frequência.

Nada disso funcionou exatamente do jeito que eu queria. O problema é que o piscar começaria muito cedo. Eu queria que a gota ficasse visível por 3 segundos e depois comece a piscar. Para fazer isso, fiz algo assim:

isVisible(drop)
  if drop.t > x
    return true
  else
    sin((T - x - drop.t * 1/100) + .5 >= 0

Que xseriam os 3 segundos.

Também digno de nota é que esta é a ferramenta que usei o tempo todo para visualizar como ficaria o piscar. Eu acho que isso levaria 5x mais tempo sem a ferramenta visual.

Daniel Kaplan
fonte
Impressionante, eu amo essa solução, uma outra maneira rápida seria fazersin(t * pow((t/T), 1.5))
Gustavo Maciel
4

Talvez com a ajuda de outra variável?

current_length = 4
length_decrease = 0.5
current_time = current_length

function update(delta_time)
    if current_time > 0 then
        draw()
    end
    current_time -= delta_time
    if current_time < -current_length then
        current_length -= length_decrease -- feel free to get creative here
        if current_length < 0 then
            disable_object()
        end
        current_time += current_length * 2
    end
end

É um pouco mais longo que a solução que você propôs, mas economiza custos sine powoperações, e você tem muito mais controle sobre como o piscar fica mais rápido.

Panda Pajama
fonte