Contexte matériel

Le premier SimCity indique comme configuration minimale un Intel 386SX fonctionnant à 16 MHz. Cette fréquence était déjà considérée comme élevée en 1989, mais reste mille fois inférieure aux gigahertz actuels. Le jeu doit donc gérer la totalité de la ville – trafic, incendies, énergie, criminalité – avec un nombre très limité d’opérations par seconde.

Mécanisme de répartition temporelle

Le cœur de la simulation réside dans la fonction Simulate() du fichier s_sim.c. Au lieu d’appeler chaque sous‑système à chaque image, le code utilise un compteur mod16 qui boucle de 0 à 15. Selon la valeur courante, seules certaines parties du modèle sont actualisées :

void Simulate(int mod16) {
    if (mod16 == 0) CrimeScan();
    if (mod16 == 1) FireAnalysis();
    if (mod16 == 2) CollectTax();
    // …
    if (mod16 == 15) UpdatePowerGrid();
}

Cette technique répartit le travail sur 16 frames. En moyenne, chaque système met 8 frames à réagir à une action du joueur, avec un maximum de 15 frames. Sur un affichage de 30 fps, le délai maximal correspond à 0,5 s, ce qui reste imperceptible pour la plupart des décisions de gestion de ville.

Analyse des performances et limites

Le gain principal provient de la réduction du nombre d’appels de fonctions par seconde. Sur un processeur 386SX, chaque appel de sous‑système consomme plusieurs centaines de cycles; en les espaçant, le CPU reste en dessous de sa capacité maximale, évitant ainsi les dépassements de temps de calcul qui provoqueraient des saccades. Le compromis est un lag contrôlé, acceptable dans un jeu où les décisions sont rarement instantanées. Cependant, si le même schéma était appliqué à un jeu d’action, le retard de 0,5 s serait catastrophique.

Extension à d’autres domaines

Le même principe apparaît dans Assetto Corsa (2014). Le rendu des cubemaps utilise la variable FACES_PER_FRAME pour n’actualiser qu’une partie des six faces à chaque image, limitant ainsi le coût de calcul de la réflexion. De façon plus générale, les moteurs modernes comme Unreal Lumen découpent les calculs d’éclairage sur plusieurs frames, ce qui explique les artefacts temporaires mais conserve une charge CPU gérable. La leçon pour les développeurs est claire : identifier les tâches qui tolèrent une mise à jour différée et les répartir dans le temps permet de faire tourner des systèmes complexes sur du matériel limité.