Jakie są twoje ulubione klejnoty do gry? [Zamknięte]

24

Zacznę od Szybkiego odwrotnego pierwiastka Johna Carmacka w Quake III:

float Q_rsqrt(float number) {

  long i;
  float x2, y;
  const float threehalfs = 1.5F;

  x2 = number * 0.5F;
  y = number;
  i = * ( long * ) &y;
  i = 0x5f3759df - ( i >> 1 );
  y = * ( float * ) &i;
  y = y * ( threehalfs - ( x2 * y * y ) );

  return y;

}
Gerald Kaszuba
źródło
6
To naprawdę nie jest pytanie - przynajmniej możesz zadeklarować, że jest to strona wiki społeczności ...
Rachel Blum
Gotowe, opracowane przez społeczność.
gak
3
Chrzanić to! po prostu skorzystaj z dowolnego kodu stworzonego przez wielkiego JC!
Adam Naylor
3
Nawiasem mówiąc, zauważ, że w funkcji szybkiego odwrotnego pierwiastka kwadratowego jest dokładniejsza „liczba magiczna”: 0x5f375a86 ( en.wikipedia.org/wiki/… )
Ricket
8
Zauważ też, że to nie jest John Carmack.
Kaj

Odpowiedzi:

25

funkcja mapValue:

float mapValue( float inVal, float inFrom, float inTo, float outFrom, float outTo )
{
    float inScale = (inFrom != inTo) 
        ? ( ( inVal - inFrom ) / ( inTo - inFrom ) ) 
        : 0.0f;
    float outVal = outFrom + ( inScale * ( outTo - outFrom ) );
    outVal = (outFrom < outTo ) 
        ? clamp( outVal, outFrom, outTo ) 
        : clamp( outVal, outTo, outFrom );
    return outVal;
}

Pobiera wartość, konwertuje ją na proporcję w zakresie, a następnie skaluje ją względem innego zakresu. Jak podwójny lerp.

Możesz go użyć do normalizacji rzeczy:

float minDamage = 0.0f; float maxDamage = 300.0f;
float normalisedDamage = mapValue(damange, minDamage, maxDamage, 0.0f, 1.0f);

Lub możesz przekonwertować z jednego zakresu na inny:

float brakeStrength = mapValue(timeToCollision, 
    0.0f, 10.0f, // seconds
    1.0f, 0.2f // brake values 
    );

Zwróć uwagę w drugim przykładzie, że zakres wyjściowy jest inny niż zakres wejściowy.

Nie wygląda to zbyt wiele, ale używam tego małego faceta w każdym miejscu.

tenpn
źródło
14

Nadal nie mogę uwierzyć, ile razy użyłem twierdzenia Pitagorasa w moim kodzie gry. Dla mnie ta prosta formuła jest klejnotem w rozwoju gier.

a ^ 2 + b ^ 2 = c ^ 2
(źródło: mathurl.com )

lub

alternatywny tekst
(źródło: mathurl.com )

a gdy liczy się tylko odległość względna, można jej użyć bez kosztownej operacji pierwiastka kwadratowego

alternatywny tekst
(źródło: mathurl.com )

MrValdez
źródło
Cóż, szczerze mówiąc, matematyka pitagorejska jest używana WSZYSTKO w kodzie gry, szczególnie w silnikach, takich jak kod fizyki, kod renderowania, sztuczna inteligencja.
Nick Bedford
1
Prawdziwe. Dlatego to klejnot. ;)
MrValdez
4
Ciekawa odmiana polega na tym, że zależy ci tylko na odległościach względnych . Następnie możesz pominąć potencjalnie drogie sqrtpołączenie i po prostu wykonać obliczenia distance2 = x^2 + y^2.
mmyers
@mmyers - Kolejna cudowna rzecz: jeśli pracujesz w przestrzeni x ^ 2, odległość nie jest tylko względna.
Steven Evers
Dziękujemy za wzmiankę o względnym bicie odległości. Widziałem zbyt wiele niepotrzebnych operacji pierwiastka kwadratowego, podobnie jak ludzie używający A *, kiedy powinni używać czegoś mniej dokładnego.
Ricket
13

Największy ode mnie czytał o systemie GameObject Scotta Bilasa. Mimo że nie korzystam z systemu baz danych tak jak on, to powstrzymało mnie to od tworzenia 6-poziomowych drzew dziedziczenia i skłoniło mnie do stworzenia systemu komponentów, który jest o wiele łatwiejszy do zarządzania i wielokrotnego użytku.

Ólafur Waage
źródło
10

Muszę iść z urządzeniem Duffa . To był pierwszy blok kodu, który dosłownie spowodował opadnięcie szczęki. "Możesz to zrobić?!?"

Michael Kristofik
źródło
O mój Boże. Gogle! Oni nic nie robią!
Raoul
Zagnieżdżone „do-while” w „obudowie przełącznika” zawsze sprawia, że ​​mrugam. Nawet 20 lat później ...
Andreas
1
-1. Nie lubię tego. Nie jest dziś zbyt przydatny ( memcpyzamiast tego skorzystasz , jeśli chcesz, aby inni mogli czytać twój kod)
bobobobo
1
@JoeWreschnig dlaczego nie? Memcpy zawsze będzie bardziej czytelny, przenośny i prawdopodobnie bardziej zoptymalizowany.
kaoD
1
@kaoD: Ponieważ memcpy nie jest odpowiednikiem urządzenia Duffa - nie ma znaczenia, jak „czytelny, przenośny i prawdopodobnie bardziej zoptymalizowany”, jeśli nie robi tego samego! Współczesne potoki procesorów prawdopodobnie lepiej sobie radzą bez urządzenia Duffa niż z nim ze względu na przewidywanie gałęzi i buforowanie instrukcji, ale to nie ma nic wspólnego memcpy.
7

Mały fragment kodu C / C ++ z gry, którą napisałem wiele lat temu:

(fill ? FillRect : DrawRect) (x, y, w, h, colour);

Podczas mojej pierwszej gry ( tej ) potrzebowałem dostępu do ponad 1 MB pamięci RAM, a ponieważ przed uruchomieniem Internetu nie miałem dokumentacji dla XMS i EMS, z której korzystały aplikacje DOS w celu uzyskania dostępu do dodatkowej pamięci RAM.

Skończyłem więc na użyciu małego „backdoora”, który pojawił się w 386 w odniesieniu do rejestrów segmentów. Zwykle w trybie rzeczywistym adres został obliczony jako seg*16+offograniczenie do 1Mb.

Możesz jednak przejść do trybu chronionego, ustawić segment na adres 4Mb, przełączyć z powrotem i pod warunkiem, że nie zapisujesz do rejestru segmentów (co było w porządku, ponieważ DOS używał tylko rejestrów segmentów 8086), możesz uzyskać dostęp do całego 4 Mb jako płaska przestrzeń adresowa. Powrót do trybu rzeczywistego był konieczny, jeśli chcesz korzystać z usług DOS.

Nie było też wielu przedłużaczy DPMI.

Skizz
źródło
Prawie działa w języku C # (musisz zadeklarować typ delegata i wstawić co najmniej jedną obsadę)
finnw
Masz na myśli 32-bitowe tryby adresowania w trybie rzeczywistym? (tj. wymagający prefiksu rozmiaru adresu). Czy jesteś pewien, że konieczne było skonfigurowanie deskryptora segmentu i że tak naprawdę nie używał rejestru segmentu jako zwykłego 16 * FS + cokolwiek? Nie sądziłem, że segmenty mają nawet ograniczenia w trybie 16-bitowym, tylko adres podstawowy (16 * ich wartość), więc nie możesz po prostu ustawić FS na coś w trybie 16-bitowym i użyć [fs:esi]lub cokolwiek, aby uzyskać dostęp do czegokolwiek poszukiwany?
Peter Cordes
Nie próbowałem tego ani nie napisałem żadnego prawdziwego kodu dla trybu 16-bitowego, tylko 32- i 64-bitowy asm, ale brzmi to dziwnie. Hmm, choć prawdopodobne. Nowoczesne procesory zdecydowanie buforują elementy segmentów wewnętrznie i ponownie ładują te bufory tylko podczas pisania do segmentów reg, więc może w ten sposób utrzymywał podstawowy + limit trybu chronionego (jeśli tak naprawdę się stało, a nie korzystałeś tylko z 4 MB od 16 * FS).
Peter Cordes
5

Osobiście jestem wielkim fanem Mersenne Twister dla przewidywalnych liczb losowych, szczególnie jeśli potrzebujesz stworzyć kilka różnych odmian Randa

http://en.wikipedia.org/wiki/Mersenne_twister

Jeff
źródło
Mersenne Twister jest fajny w tym sensie, że jest dobrym generatorem liczb losowych, ale nie jest szczególnie elegancki ani fajny (ani szybki, ani łatwy do wdrożenia). W tym celu możesz zajrzeć na stronę en.wikipedia.org/wiki/Rule_30 .
1
Odwiert jest ogólnie lepsza niż dla większości zastosowań MT .. en.wikipedia.org/wiki/Well_equidistributed_long-period_linear
Jari Komppa
5

Oto jeden wspomniany przez Chrisa Crawforda (i najwyraźniej używany przez Atari), który nazywa „A Graphics Trick”:

LDA FIRST
EOR SECOND
AND CONTROL
EOR SECOND
STA OUTPUT

Przeczytaj cały artykuł, aby uzyskać wyjaśnienie.

Anthony-Arnold
źródło
1
Ten link jest teraz zepsuty, więc pomocne byłoby tutaj wyjaśnienie.
finnw 11.10.11
Dzięki. Odszedł i ponownie zmienił swoją stronę internetową. Zaktualizowałem link.
Anthony
4

Z jakiegoś powodu ludzie często nie doceniają siły wzorców projektowych w grach. Widziałem prawie każdy wzór GoF stosowany z sukcesem w grach.

Steven Evers
źródło
1
Jedną z rzeczy, które lubię w programowaniu gier, jest odejście od standardowego sposobu „poprawności” GoF i skupienie się na czystej uroczej prędkości! To powiedziawszy, widziałem wiele złych implementacji MVC w grach, które wyrządzają więcej szkody niż pożytku.
Iain
Myślę, że wzorce projektowe mają swoje miejsce. Jednak nie w grach.
blissfreak
@blissfreak: W programowaniu gier nie ma nic specjalnego, co sprawia, że ​​jest to rodzaj dzikiego zachodu, w którym wzorce nie są powszechne. Są absurdalnie powszechne i oto kilka przykładów.
Steven Evers,
4

Math.atan2 () jest niezwykle przydatny (wraz ze wszystkimi trig).

Alex Miller
źródło
Cholera! Zrobiłem dużo 3D i nigdy tak naprawdę go nie potrzebowałem.
Skizz
+1, to jedyny sposób, aby przejść z komponentów wektora x + y w kierunku radianów.
RCIX
1
@RCIX: Chodzi mi o to, że transformacja jest niepotrzebna, tzn. (X, y) -> kąt, istnieje rozwiązanie wektorowe dla dowolnego problemu z kątem.
Skizz
6
Tak naprawdę nie nazwałbym standardowej funkcji biblioteki „klejnotem”.
1
@Skizz: Może dla 3d, ale nie znam innego sposobu na przyjęcie znormalizowanego wektora i wyodrębnienie wartości kierunku radianów. Co jako duża wartość w grach 2D.
RCIX
3

Aby dodać do pitagorejskiego klejnotu powyżej ...
Zawsze mówię ludziom, że do programowania 3D muszą tylko wiedzieć:
- a ^ 2 + b ^ 2 = c ^ 2
- soscastoa (sin = strona przeciwna / strona nachylona, ​​cos = strona przyczepiona / strona nachylona, ​​tan = strona przeciwna / strona przyczepiona)
- a. b = | a | * | b | * cos alfa
- a * b = | a | * | b | * sin alpha * jednostka wektor
Może rozwiązać prawie każdy problem 3d (lub 2d), który napotkasz podczas tworzenia gry - 4 zasady.
Jasne, są lepsze sposoby, ale to może rozwiązać je wszystkie - powinienem wiedzieć, że jestem hakiem, który opierał na nich karierę.

Kaj
źródło
5
re: soscastoa Myślę, że większość ludzi wie, że to sohcahtoa (zastępując „nachyloną stronę” bardziej konkretnym, choć, co prawda, bardziej niejasnym, „przeciwprostokątnym”). Łatwiej spływa z języka i myślę, że w ten sposób łatwiej go zapamiętać.
Asmor
1
Zawsze wolę „The Old Arab Sat On His Camel And Howled”, ponieważ liceum (wiek liceum) zostało odciśnięte w moim mózgu.
George Duckett
Jest także " S OMe O LD H ippy C AME II H ad t zgrane O n cid"
blissfreak
3

Jedną z moich ulubionych jest asemblerowa wersja „Life” i cały opis jej optymalizacji w „ Zen of Code Optimization” Michaela Abrasha.

Poleciłbym każdą z jego książek każdemu, kto szuka klejnotów kodujących.

rev AShelly
źródło