Quais são as suas gemas de codificação específicas do jogo favoritas? [fechadas]


24

Vou começar com a raiz rápida e inversa do quadrado de John Carmack no 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;

}

6
Isso não é realmente uma pergunta - pelo menos, você pode declarar que esta é uma página wiki da comunidade ...
Rachel Blum

Feito, em comunidade.
gak

3
Dane-se isso! basta ir com todo e qualquer código criado pelo grande JC!
Adam Naylor

3
A propósito, observe que há um "número mágico" mais preciso para usar na função de raiz quadrada inversa rápida: 0x5f375a86 ( en.wikipedia.org/wiki/… )
Ricket

8
Observe também que não é de John Carmack.
Kaj 30/07

Respostas:


25

Função 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;
}

Ele pega um valor, converte-o em uma proporção dentro de um intervalo e depois o dimensiona em relação a outro intervalo. Como um lerp duplo.

Você pode usá-lo para normalizar coisas:

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

Ou você pode converter de um intervalo para outro:

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

Observe no segundo exemplo que o intervalo de saída é uma ordem diferente do intervalo de entrada.

Não parece muito, mas eu uso esse amiguinho em todo o lugar.


14

Ainda não consigo acreditar quantas vezes usei o Teorema de Pitágoras no código do meu jogo. Para mim, esta fórmula simples é uma jóia no desenvolvimento de jogos.

a ^ 2 + b ^ 2 = c ^ 2
(fonte: mathurl.com )

ou

texto alternativo
(fonte: mathurl.com )

e quando apenas a distância relativa importa, ele pode ser usado sem uma operação cara de raiz quadrada

texto alternativo
(fonte: mathurl.com )


Bem, para ser honesto, a matemática pitagórica é usada TODO o código do jogo, especialmente mecanismos, como código de física, código de renderização e IA.
Nick Bedford

11
Verdade. É por isso que é uma jóia. ;)
MrValdez

4
Uma variação interessante é quando você se importa apenas com as distâncias relativas . Em seguida, você pode pular a sqrtchamada potencialmente cara e simplesmente calcular distance2 = x^2 + y^2.
22710 mmmm

@ mmyers - Outra coisa maravilhosa: se você estiver trabalhando no espaço x ^ 2, a distância não é apenas relativa.
Steven Evers

Obrigado por mencionar o bit de distância relativa. Eu já vi muitas operações desnecessárias de raiz quadrada, assim como as pessoas que usam A * quando deveriam usar algo menos exato.
Ricket

13

O maior de mim foi ler sobre o sistema GameObject de Scott Bilas. Mesmo que eu não use um sistema de banco de dados como ele, ele me impediu de criar árvores de herança de 6 níveis e me levou a criar um sistema de componentes que é muito mais gerenciável e reutilizável.


10

Eu tenho que ir com o dispositivo de Duff . Foi o primeiro bloco de código que literalmente fez meu queixo cair. "Você pode fazer isso?!?"


AMD. Os óculos! Eles não fazem nada!
Raoul

O "fazer enquanto" aninhado dentro da "caixa de mudança" sempre me faz piscar. Mesmo 20 anos depois ...
Andreas

11
-1. Eu não gosto deste. A sua não é muito útil hoje (você usaria memcpyem vez disso, se você quer que outras pessoas para ser capaz de ler o seu código)
bobobobo

11
@JoeWreschnig porque não? O Memcpy sempre será mais legível, portátil e provavelmente mais otimizado.
kaoD

11
@kaoD: Como o memcpy não é equivalente ao dispositivo de Duff - não importa o quão "legível, portátil e provavelmente mais otimizado" seja se ele não fizer a mesma coisa! Os pipelines de CPU modernos provavelmente terão um desempenho melhor sem o dispositivo de Duff do que com ele devido à previsão de ramificação e ao cache de instruções, mas isso não tem nada a ver memcpy.

7

Um pequeno trecho de C / C ++ de um jogo que ajudei a escrever há muitos anos:

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

No meu primeiro jogo ( este ), eu precisava acessar mais de 1Mb de RAM e, isso antes da decolagem da Internet, eu não tinha documentação para XMS e EMS que os aplicativos DOS usavam para acessar a RAM extra.

Então, acabei usando um pequeno 'backdoor' que apareceu no 386 em relação aos registros de segmento. Normalmente, no modo real, o endereço foi calculado comoseg*16+off que limitava você a 1Mb.

No entanto, você pode alternar para o modo protegido, configurar um segmento para endereçar 4Mb, retornar e, desde que não tenha gravado no registrador de segmentos (o que foi bom, já que o DOS usou apenas os registradores de segmentos 8086), você pode acessar todo o 4 Mb como um espaço de endereço plano. Voltar ao modo real era necessário se você quisesse usar os serviços do DOS.

Também não havia muitos extensores DPMI disponíveis.


Quase funciona em C # (você precisa declarar um tipo delegado e inserir pelo menos um cast)
finnw

Você quer dizer com modos de endereçamento de 32 bits no modo real? (isto é, exigindo um prefixo de tamanho de endereço). Você tem certeza de que era necessário configurar um descritor de segmento e que ele realmente não usava o registrador de segmento como o 16 * FS + normal? Eu não achava que os segmentos tivessem limites no modo de 16 bits, apenas o endereço base (16 * o valor deles), então você não poderia simplesmente definir o FS para algo no modo de 16 bits e usar [fs:esi]o que quer que fosse para acessar o que quer que você procurado?
Peter Cordes

Eu não tentei isso ou escrevi nenhum código real para o modo de 16 bits, apenas 32 e 64 bits, mas parece estranho. Hmm, embora plausível. As CPUs modernas definitivamente armazenam em cache as coisas do segmento internamente, e apenas recarregam esses caches quando você escreve nos registros de segmento, talvez seja assim que ele manteve a base + limite do modo protegido (se foi realmente o que aconteceu, e você não estava apenas usando o 4 MB a partir de 16 * FS).
Peter Cordes

5

Pessoalmente, sou um grande fã do Mersenne Twister em busca de números aleatórios previsíveis, especialmente se você precisar criar várias instâncias de Rand de diferentes formas.

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


Mersenne Twister é bom no sentido de ser um bom gerador de números aleatórios, mas não é particularmente elegante ou legal (ou rápido ou fácil de implementar). Para isso, convém consultar en.wikipedia.org/wiki/Rule_30 .

11
BEM é geralmente melhor do que MT para a maioria dos usos .. en.wikipedia.org/wiki/Well_equidistributed_long-period_linear
Jari Komppa

5

Aqui está um mencionado por Chris Crawford (e aparentemente usado por Atari) que ele chama de 'A Graphics Trick':

LDA FIRST
EOR SECOND
AND CONTROL
EOR SECOND
STA OUTPUT

Leia o artigo completo para obter uma explicação.


11
Esse link agora está quebrado, portanto, ajudaria a ter uma explicação aqui.
finnw

Obrigado. Ele se foi e mudou seu site novamente. Eu atualizei o link.
Anthony

4

Por alguma razão, as pessoas geralmente subestimam o poder dos padrões de design nos jogos. Eu já vi quase todos os padrões GoF aplicados com sucesso aos jogos.


11
Uma das coisas que eu mais gosto na programação de jogos é ficar longe da maneira padrão de "correção" do GoF e focar apenas na velocidade adorável! Dito isto, já vi muitas implementações ruins do MVC em jogos que fazem mais mal do que bem.
Iain

Eu acho que os padrões de design têm o seu lugar. Não tanto em jogos, no entanto.
Bluesfreak #

@blissfreak: Não há nada de especial na programação de jogos que o torne um tipo de oeste selvagem, onde os padrões não são comuns. Eles são ridiculamente comuns e aqui estão alguns exemplos.
Steven Evers

4

Math.atan2 () é extremamente útil (junto com todos os trig).


É, nossa! Eu fiz muito 3D e nunca realmente precisei.
Skizz 29/07

+1, é a única maneira de passar dos componentes do vetor x + y para a direção do radiano.
RCIX 29/07

11
@RCIX: Meu argumento é que essa transformação é desnecessária, ou seja, (x, y) -> ângulo, existe uma solução vetorial para qualquer problema de ângulo.
Skizz 29/07

6
Eu realmente não chamaria uma função de biblioteca padrão simples de "jóia".

11
@ Skizz: Talvez para 3d, mas não conheço outra maneira de pegar um vetor normalizado e extrair um valor de direção de radianos. O que é uma boa parte dos jogos 2D.
RCIX 30/07/10

3

Para adicionar à gema pitagórica acima ...
Eu sempre digo às pessoas que, para a programação em 3D, elas precisam apenas saber:
- a ^ 2 + b ^ 2 = c ^ 2
- soscastoa (sin = lado oposto / lado inclinado, cos = lado anexado / lado inclinado, castanho = lado oposto / lado fixo)
- a. b = | a | * | b | * cos alfa
- a * b = | a | * | b | * sin alpha * vetor unitário
Ele pode resolver praticamente qualquer problema 3d (ou 2D) que você encontrar no desenvolvimento de jogos - 4 regras.
Claro, existem maneiras melhores, mas isso pode resolver todos eles - eu deveria saber, eu sou um hack que baseou uma carreira neles.


5
re: soscastoa Eu acho que a maioria das pessoas sabe disso como sohcahtoa (substituindo 'lado inclinado' pelo mais específico, se admitidamente mais obscuro, 'hipotenusa'). Sai da língua mais fácil, e acho que é mais fácil de lembrar.
Asmor 23/11

11
Eu sempre prefiro 'O velho árabe sentou-se em seu camelo e uivou', já que o ensino médio (idade do ensino médio) está impresso no meu cérebro.
George Duckett 12/10

Há também " S OMe O LD H ippy C ame Um nd H anúncio T rasgado ó n Um cid"
blissfreak

3

Um dos meus favoritos é a versão em linguagem assembly do 'Life', e toda a descrição de otimização, em " O Zen da otimização de código", de Michael Abrash.

Eu recomendaria qualquer um de seus livros para quem procura gemas de codificação.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.