Types cœur

Godot a une base riche de classes et templates qui forment son cœur, et tout est construit autours d'eux.

Cette référence tentera de les répertorier afin de mieux les comprendre.

Définitions

Godot utilise les types standard du C98, comme uint8_t, uint32_t, int64_t, etc. Ces derniers sont aujourd'hui supporté par tout les compilateurs. Réinventer la roue n'est ici pas amusant, en plus de rentre le code difficile à lire.

En général, on ne prend pas soin à utiliser le type le plus performant pour une tâche donnée, sauf s'il s'agit d'utiliser de grande structures ou de tableaux. int est utilisé dans la majorité du code, car aujourd'hui tout les appareilles fonctionnement au minimum avec un bus de 32bits et peuvent calculer de telles opérations en un cycle. Cela rend aussi le code plus lisible.

Pour les fichiers ou des tailles de mémoire on utilise size_t, il garranti d'être sur 64bits.

Pour les caractères Unicode, on utilise CharType au lieu de wchar_t, car de nombreuses architectures ont un wchar_t de 4 octets, alors que 2 octets pourraient être souhaitables. Cependant, par défaut, cela n'a pas été forcé et CharType correspond directement à wchar_t.

Références :

Modèle mémoire

Les ordinateurs sont de magnifiques architectures. Ces derniers ont souvent des gigabytes de mémoire vive (RAM), des terabytes de stockage et des gigahertz de processeur, lorsqu'une application a besoin de plus de ressources le système d'exploitation lui assignera les ressources inactives. D'autres architectures (comme les téléphones ou les consoles) sont en général plus limités.

Le modèle de mémoire le plus courant est le tas (heap), où une application demandera une région de la mémoire, et le système d'exploitation sous-jacent tentera de trouver un espace adapté et de le renvoyer. Cela est plus flexible et fonctionne souvent mieux, mais au fil des utilisations abusives, cela peut aboutir à une segmentation.

La segmentation crée lentement des troues qui sont trop petit pour la plupart de allocations, alors la mémoire est gaspillé. Il y a beaucoup de discussion autours du tas (heap) et de la segmentation, donc ce sujet ne sera pas plus développé ici. Les systèmes d'exploitation modernes répondent au problème en utilisant de la mémoire virtuelle paginé, cela aide mais cependant ne résout pas le problème .

Toutefois, de nombreuses études et tests montrent qu'avec une mémoire suffisante, si la taille maximale de l'allocation est inférieure à un seuil donné par rapport à la taille maximale du tas et à la proportion de mémoire destinée à être inutilisée, la segmentation ne posera pas de problème dans le temps car elle restera constante. En d'autres termes, laissez 10 à 20 % de votre mémoire libre et effectuez de petites allocations et tout ira bien.

Godot garantie que tout les objets qui sont alloués dynamiquement sont petit (tout au plus quelques kb). Mais que se passe-t-il si une allocation est trop grande (comme une image, un maillage gémotrique ou encore un grand tableau) ? Dans ce cas Godot peut utiliser des zones mémoires (memory pool). Cette mémoire a besoin d'être vérouiller pour être accéder, et si une allocation manque de mémoire alors la zone sera réorganisé et compacté. dépendamment des besoins du jeu, le programmeur peut configurer la taille dynamique de la zone mémoire.

Allouer de la mémoire

Godot a de nombreux outils pour traquer l'utilisation de la mémoire dans un jeu, spécialement lors du débogage. De ce fait, les allocateurs standard de C et C++ ne doivent pas être utilisés, d'autres sont fournis.

Pour les allocations style C, Godot fourni quelques macros :

memalloc()
memrealloc()
memfree()

Elles sont équivalentes au traditionnel malloc, realloc et free de la librairie standard de C.

Pour les allocations style C++, des macros spéciales sont fournis :

memnew( Class / Class(args) )
memdelete( instance )

memnew_arr( Class , amount )
memdelete_arr( pointer to array )

qui sont équivalente à new, delete, new[] et delete[].

memnew/memdelete utilise aussi un peu de lmagie du C++ pour notifier les Objets juste après leur création et juste avant leur destruction.

Pour de la mémoire dynamique, la classe template PoolVector est fourni. PoolVector est fourni comme un vecteur classique et il est très similaire à std::vector de C++. Pour construire un buffer PoolVector utilisez cela :

PoolVector<int> data;

PoolVector peut être consulté en utilisant l'opérateur [] et quelques helpers existent pour cela :

PoolVector<int>::Read r = data.read()
int someint = r[4]
PoolVector<int>::Write w = data.write()
w[4] = 22;

Ces opérations permettent des lectures/écriture rapide de PoolVectors et de le regarder vérouiller jusqu'à qu'elles sortent de la portée (scope). Cependant, les PoolVectors devraient être utilisé pour de petite oéprations dynamique de mémoire, car read() et write() sont trop lent pour un grand nombre d'accès.

Conteneurs

Godot propose aussi un ensemble de conteneurs classiques :

  • Vecteur
  • List
  • Définir
  • Map

Ils sont simple et fait pour être le plus minimal possible, comme les templates de C++ sont souveent inliné et rendent les binaires bien plus lourd, autant en symbols de débug que de code. List, Set et Map peuvent être itérés en utilisant des pointeurs, comme cela :

for(List<int>::Element *E=somelist.front();E;E=E->next()) {
    print_line(E->get()); // print the element
}

La classe template Vector a aussi quelques cool fonctionnalités :

  • Il copie en écriture, donc en faire des copies est peu coûteux marché tant qu'elles ne sont pas modifiées.
  • Il supporte le mutli-threading, en utilisant des opérations atomiques sur le compteur de référence.

Chaîne de caractères

Godot fournit aussi une classe String. Cette classe possède un grand nombre de fonctionnalités comme : un support de l'Unicode dans toute les fonctions et du parsing/extraction d'utf8, de même que les helpers pour la conversion et la visualisation.

Références :

StringName

Les StringNames sont comme une String, sauf qu'elles sont unique. Créer une StringName depuis une chaîne de caractères résulte en un seul pointeur en interne pour toute les chaînes égales. les StringNames sont utiles pour utiliser une chaîne de caractère comme un indentificateur, vu que les comparer revient à comparer des pointeurs.

La construction d'un StringName (surtout un nouveau) est lent, mais la comparaison est rapide.

Références :

Types mathématiques

Il existe plusieurs types de mathématiques linéaires disponibles dans le répertoire core/math.

Références :

NodePath

C'est un type spécial qui est utilisé pour stocker des echemins dans une scène arbre et les référencer rapidement.

Références :

RID

Les RIDs sont des identifiants de ressources. Les serveurs les utilisent pour référencer les données qu'ils stockent. Les RID sont opaques, ce qui signifie que les données qu'ils référencent ne sont pas directement accessibles. Les RIDs sont uniques, même pour des types de données référencées différents.

Références :