Quels sont vos joyaux de codage spécifiques au jeu préférés? [fermé]

24

Je vais commencer par la racine carrée rapide inverse de John Carmack dans 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
la source
6
Ce n'est pas vraiment une question - à tout le moins, vous pourriez déclarer cela une page wiki communautaire ...
Rachel Blum
Terminé, mis en communauté.
gak
3
Vis ça! allez-y avec n'importe quel code conçu par le grand JC!
Adam Naylor du
3
Soit dit en passant, notez qu'il existe un "nombre magique" plus précis à utiliser dans la fonction de racine carrée inverse rapide: 0x5f375a86 ( en.wikipedia.org/wiki/… )
Ricket
8
Notez également qu'il ne s'agit pas de John Carmack.
Kaj

Réponses:

25

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

Il prend une valeur, la convertit en une proportion dans une plage, puis la met à l'échelle par rapport à une autre plage. Comme un double-lerp.

Vous pouvez l'utiliser pour normaliser des choses:

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

Ou vous pouvez convertir d'une plage à une autre:

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

Notez dans le deuxième exemple que la plage de sortie est un ordre différent de la plage d'entrée.

Cela ne ressemble pas beaucoup, mais j'utilise ce petit gars partout.

tenpn
la source
14

Je n'arrive toujours pas à croire combien de fois j'ai utilisé le théorème de Pythagore dans mon code de jeu. Pour moi, cette formule simple est un joyau dans le développement de jeux.

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

ou

texte alternatif
(source: mathurl.com )

et lorsque seule la distance relative est importante, elle peut être utilisée sans opération coûteuse de racine carrée

texte alternatif
(source: mathurl.com )

MrValdez
la source
Pour être honnête, les mathématiques de Pythagore sont utilisées partout dans le code du jeu, en particulier les moteurs, tels que le code physique, le code de rendu, l'IA.
Nick Bedford
1
Vrai. C'est pourquoi c'est un bijou. ;)
MrValdez
4
Une variation intéressante est lorsque vous ne vous souciez que des distances relatives . Ensuite, vous pouvez ignorer l' sqrtappel potentiellement coûteux et simplement calculer distance2 = x^2 + y^2.
mmyers
@mmyers - Une autre chose merveilleuse: si vous travaillez dans l'espace x ^ 2, la distance n'est pas seulement relative.
Steven Evers
Merci d'avoir mentionné le bit de distance relative. J'ai vu beaucoup trop d'opérations de racine carrée inutiles, tout comme les gens qui utilisent A * alors qu'ils devraient utiliser quelque chose de moins exact.
Ricket
13

Le plus gros de moi était la lecture du système GameObject de Scott Bilas. Même si je n'utilise pas de système de base de données comme lui, cela m'a empêché de créer des arbres d'héritage à 6 niveaux et m'a permis de créer un système de composants beaucoup plus gérable et réutilisable.

Ólafur Waage
la source
10

Je dois aller avec l'appareil de Duff . C'était le premier bloc de code qui a littéralement fait tomber ma mâchoire. "Vous pouvez le faire?!?"

Michael Kristofik
la source
OMG. Les lunettes! Ils ne font rien!
Raoul
Le "do-while" imbriqué dans le "switch-case" me fait toujours cligner des yeux. Même 20 ans plus tard ...
Andreas
1
-1. Je n'aime pas celui-ci. Ce n'est pas très utile aujourd'hui (vous l'utiliseriez à la memcpyplace, si vous voulez que d'autres personnes puissent lire votre code)
bobobobo
1
@JoeWreschnig pourquoi pas? Memcpy sera toujours plus lisible, portable et probablement plus optimisé.
kaoD le
1
@kaoD: Parce que memcpy n'est pas équivalent à l'appareil de Duff - peu importe comment il est "lisible, portable et probablement plus optimisé" s'il ne fait pas la même chose! Les pipelines de CPU modernes feront probablement mieux sans l'appareil de Duff qu'avec lui en raison de la prédiction de branche et de la mise en cache des instructions, mais cela n'a rien à voir avec memcpy.
7

Un petit extrait C / C ++ d'un jeu que j'ai aidé à écrire il y a plusieurs années:

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

Lors de mon premier match ( ce ), j'avais besoin d'accéder à plus de 1 Mo de RAM et, avant le décollage d'Internet, je n'avais aucune documentation pour XMS et EMS que les applications DOS utilisaient pour accéder à la RAM supplémentaire.

J'ai donc fini par utiliser une petite «porte dérobée» qui figurait dans le 386 en ce qui concerne les registres de segments. Normalement, en mode réel, l'adresse a été calculée comme suit:seg*16+off ce qui vous limitait à 1 Mo.

Cependant, vous pouvez passer en mode protégé, configurer un segment pour adresser 4 Mo, revenir en arrière et à condition de ne pas écrire dans le registre de segment (ce qui était bien puisque DOS n'utilisait que les registres de segment 8086), vous pouviez accéder à l'ensemble 4 Mo d'espace d'adressage plat. Revenir en mode réel était nécessaire si vous vouliez utiliser les services DOS.

Il n'y avait pas non plus beaucoup d'extendeurs DPMI disponibles.

Skizz
la source
Fonctionne presque en C # (vous devez déclarer un type de délégué et insérer au moins une distribution)
finnw
Vous voulez dire avec des modes d'adressage 32 bits en mode réel? (c'est-à-dire nécessitant un préfixe de taille d'adresse). Êtes-vous sûr qu'il était nécessaire de configurer un descripteur de segment et qu'il n'utilisait pas réellement le registre de segment comme 16 * FS + normal? Je ne pensais pas que les segments avaient même des limites en mode 16 bits, juste l'adresse de base (16 * leur valeur), donc ne pourriez-vous pas simplement définir FS sur quelque chose en mode 16 bits, et utiliser [fs:esi]ou autre pour accéder à tout ce que vous voulait?
Peter Cordes du
Je n'ai pas essayé cela, ni écrit de vrai code pour le mode 16 bits, seulement 32 et 64 bits asm, mais cela semble bizarre. Hmm, plausible cependant. Les processeurs modernes mettent définitivement en cache les éléments de segment en interne, et ne rechargent ces caches que lorsque vous écrivez dans les regs de segment, alors c'est peut-être ainsi que la base + limite en mode protégé est conservée (si c'est effectivement ce qui s'est passé, et que vous n'utilisiez pas simplement le 4 Mo à partir de 16 * FS).
Peter Cordes du
5

Personnellement, je suis un grand fan de Mersenne Twister pour les nombres aléatoires prévisibles, surtout si vous devez créer plusieurs instances de Rand différentes

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

Jeff
la source
Mersenne Twister est agréable dans le sens où c'est un bon générateur de nombres aléatoires, mais ce n'est pas particulièrement élégant ou cool (ou rapide ou facile à mettre en œuvre). Pour cela, vous voudrez peut-être consulter en.wikipedia.org/wiki/Rule_30 .
1
WELL est généralement meilleur que MT pour la plupart des utilisations. En.wikipedia.org/wiki/Well_equidistributed_long-period_linear
Jari Komppa
5

En voici un mentionné par Chris Crawford (et apparemment utilisé par Atari) qu'il appelle 'A Graphics Trick':

LDA FIRST
EOR SECOND
AND CONTROL
EOR SECOND
STA OUTPUT

Lisez l' article complet pour une explication.

anthony-arnold
la source
1
Ce lien est maintenant rompu, il serait donc utile d'avoir une explication ici.
finnw
Merci. Il est parti et a changé de nouveau son site Web. J'ai mis à jour le lien.
Anthony
4

Pour une raison quelconque, les gens sous-estiment souvent la puissance des modèles de conception dans les jeux. J'ai vu presque tous les modèles GoF appliqués avec succès aux jeux.

Steven Evers
la source
1
L'une des choses que j'aime dans la programmation de jeux est de s'éloigner de la méthode standard du GoF de «correction» et de se concentrer uniquement sur la vitesse pure! Cela dit, j'ai vu beaucoup de mauvaises implémentations de MVC dans les jeux qui font plus de mal que de bien.
Iain
Je pense que les modèles de conception ont leur place. Mais pas tellement dans les jeux.
blissfreak
@blissfreak: La programmation de jeux n'a rien de spécial qui en fait une sorte de Far West où les schémas ne sont pas courants. Ils sont ridiculement communs et voici quelques exemples.
Steven Evers
4

Math.atan2 () est extrêmement utile (avec tous les trig).

Alex Miller
la source
C'est, mon Dieu! J'ai fait beaucoup de 3D et n'en ai jamais vraiment eu besoin.
Skizz
+1, c'est le seul moyen de passer des composantes vectorielles x + y à la direction des radians.
RCIX
1
@RCIX: Mon point est que cette transformation n'est pas nécessaire, c'est-à-dire (x, y) -> angle, il existe une solution vectorielle à tout problème d'angle.
Skizz
6
Je n'appellerais pas vraiment une fonction de bibliothèque standard nue un "joyau".
1
@ Skizz: Peut-être pour la 3D, mais je ne connais pas d'autre moyen de prendre un vecteur normalisé et d'extraire une valeur de direction de radians. Ce qui représente beaucoup de valeur dans les jeux 2D.
RCIX
3

Pour ajouter au joyau pythagoricien ci-dessus ...
Je dis toujours aux gens que pour la programmation 3D, ils ont seulement besoin de savoir:
- a ^ 2 + b ^ 2 = c ^ 2
- soscastoa (sin = côté opposé / côté incliné, cos = côté attaché) / côté incliné, beige = côté opposé / côté attaché)
- a. b = | a | * | b | * cos alpha
- a * b = | a | * | b | * sin alpha * vector unit
Il peut résoudre à peu près n'importe quel problème 3d (ou 2d) que vous rencontrez dans le développement de jeux - 4 règles.
Bien sûr, il existe de meilleures façons, mais cela peut les résoudre tous - je dois savoir, je suis un hack qui a basé une carrière sur eux.

Kaj
la source
5
re: soscastoa Je pense que la plupart des gens le savent comme sohcahtoa (en remplaçant «côté incliné» par «hypoténuse» plus spécifique, bien que plus obscure). S'écoule de la langue plus facilement, et je pense donc plus facile à retenir.
Asmor
1
Je préférerai toujours "Le vieil arabe assis sur son chameau et hurlé", car depuis le secondaire (âge du lycée), il est imprimé dans mon cerveau.
George Duckett du
Il y a aussi " S ome O ld H ippy C amme A e H ad T arraché O n A cid"
blissfreak
3

Un de mes favoris est la version en langage assembleur de «Life», et toute la description de son optimisation, dans « Le zen de l'optimisation du code» de Michael Abrash.

Je recommanderais n'importe lequel de ses livres à tous ceux qui recherchent des gemmes de codage.

AShelly
la source