Jak zrobić coś, co częściej flashuję / mrugam, gdy zbliża się do znikania?

10

W mojej grze, kiedy zabijesz wroga, mogą upuścić coś takiego jak pakiet zdrowia lub złoto. Chcę, aby miało to limit czasowy, aby w końcu zniknęło, jeśli go nie odbierzesz. Chcę, aby przedmiot migał częściej, im bardziej kropla zbliża się do „śmierci”. Jak wykonujesz algorytm „częstszego flashowania”?

Daniel Kaplan
źródło

Odpowiedzi:

2

Moje obawy związane z jednym z obecnie oferowanych podejść polegają na tym, że oba doprowadzą do migania „zmiennej prędkości”, co może nie tylko rozpraszać graczy, ale także utrudniać dokładne określenie, jak długo obiekt pozostawił, zanim zniknie . Zamiast tego, gdzieś w swoich parametrach (czy to globalny mechanizm renderujący lub na zasadzie per-obiektu) Chciałbym mieć cztery stałe: slowBlinkTime, slowBlinkRate, fastBlinkTimei fastBlinkRate. Podczas renderowania, jeśli pozostały czas życia Twojego obiektu jest krótszy niż fastBlinkTime, mrugnij nim o fastBlinkRate; w przeciwnym razie, jeśli jest mniejszy slowBlinkTime, to mrugnij o slowBlinkRate. Jeśli chcesz pójść o krok dalej, możesz mieć szereg różnych blinkTimes iblinkRatei sprawdzaj je jeden po drugim, ale w praktyce może to być przesada, a wystarczą same ostrzeżenia i stany krytyczne. Kod wyglądałby mniej więcej tak:

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
}

Zauważ, że ten kod zakłada pół-włączony, pół-wyłączony cykl mrugania (to 0.5freprezentuje test), ale może być łatwo dostosowany do czegoś w rodzaju 2/3 włączenia, 1/3 wyłączenia tylko przez dostosowanie odpowiedniej stałej. To również nie robi nic, aby „zsynchronizować” miganie między szybkim i wolnym stanem, ale jest to stosunkowo proste do polerowania.

Powinno to być łatwe do podłączenia, a będzie miało znaczącą przewagę IMHO, że gracze będą mogli zobaczyć przejście z „wolnego” na „szybkie” mruganie i dokładnie wiedzieć, jak długo im pozostało. Chciałbym zacząć od wartości parametrów takich jak 5s dla slowBlinkTimei 0,5s dla slowBlinkRatei 2s / 0,25s dlafastBlinkTime i fastBlinkRate, ale to zdecydowanie zależy od konkretnej gry.

Steven Stadnicki
źródło
Nie rozumiem. Jeśli mruganie staje się coraz szybsze, czy nie byłby to lepszy wskaźnik do dokładnego czasu, jaki upłynął od obiektu, niż tylko 2 tryby?
Daniel Kaplan
1
@tieTYT Problem polega na tym, że szczególnie gdy częstotliwość mrugania jest zmienna, użytkownikom trudno (a) dokładnie określić, jak szybko obiekt mruga, i (b) skorelować to z tym, jak długo musi on żyć. Wyobraź sobie, że masz suwak od 0 do 100 w porównaniu z „przełącznikiem” z pozycjami na 0, 50 i 100; ludzie mogą odgadnąć wartość suwaka z dokładnością do 5-10%, ale będą wiedzieli dokładnie, na jakiej wartości jest włączony przełącznik - i znacznie trudniej jest ocenić wskaźnik niż pozycję.
Steven Stadnicki
Mimo sugestii głosów uważam, że to najlepsza odpowiedź. Ponadto jest znacznie łatwiejszy do wdrożenia (przynajmniej koncepcyjnie). Moja odpowiedź uzyskała więcej głosów, ale nadal nie jestem z niej zadowolona wizualnie. Twoje podejście da satysfakcjonujący wygląd.
Daniel Kaplan
14

Jeśli t spadnie z T do 0, możesz użyć czegoś takiego jak sin ((T - t) ²), a następnie jeśli liczba wynosi> 0, narysuj obiekt, jeśli jest to <0, nie zrobisz tego


Wypróbowałem to sam i musiałem majstrować przy tym. Dla mnie T było 100. To równanie sprawiło, że wszystko mrugało bardzo szybko przez cały czas. Aby spowolnić, zmieniłem równanie na sin (((T - t) / 10) ²). Było to po majstrowaniu przy liczbach takich jak / 6 i / 7.

Próbowałem także: sin ((T - t) ² * 1/100)

A potem nie podobało mi się, że kropla wydawała się niewidoczna prawie tak bardzo, jak była widoczna. Chciałem, żeby rzadko był niewidoczny. Osiągnąłem to, robiąc to: sin ((T - t) ² * 1/100) + .5 To + .5 przesuwa sinusoidę „w górę” tak, że nie staje się ona tak często <0.

Nic z tego nie działało dokładnie tak, jak chciałem. Problem polega na tym, że mruganie zacznie się zbyt wcześnie. Chciałem, aby kropla była widoczna przez 3 sekundy, a następnie zaczęła mrugać. Aby to osiągnąć, zrobiłem coś takiego:

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

To xbyłyby 3 sekundy.

Warto również zauważyć, że jest to narzędzie, którego używałem przez cały czas, aby wizualizować, jak wyglądałoby mruganie. Myślę, że bez narzędzia wizualnego zajęłoby to 5 razy dłużej.

Daniel Kaplan
źródło
Wspaniale, uwielbiam to rozwiązanie, Kolejny szybki sposób to zrobićsin(t * pow((t/T), 1.5))
Gustavo Maciel
4

Może przy pomocy innej zmiennej?

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

Jest to nieco dłużej niż rozwiązanie, które sam zaproponowałeś, ale oszczędzasz się na kosztach sini powoperacjach, i masz znacznie większą kontrolę nad tym, jak mruganie przebiega szybciej.

Panda Piżama
źródło