27 points par GN⁺ 2026-03-23 | 2 commentaires | Partager sur WhatsApp
  • Sorti en 1999, RollerCoaster Tycoon est un jeu de simulation écrit presque entièrement en assembleur, capable de gérer en temps réel des milliers de visiteurs tout en conservant des performances stables
  • Le développeur Chris Sawyer a choisi le contrôle bas niveau plutôt qu’un langage de haut niveau, aboutissant à l’une des dernières grandes générations de jeux en assembleur maximisant l’efficacité des calculs CPU
  • Grâce au projet de fans OpenRCT2, les schémas d’optimisation précis et les techniques d’économie mémoire de l’original ont pu être analysés par rétro-ingénierie
  • Le jeu exploite les décalages de bits et une granularité fine des types de données pour améliorer la vitesse de calcul et l’efficacité du cache, et rend possible la simulation à grande échelle grâce à une limite de profondeur pour la recherche de chemin et à la suppression des calculs de collision
  • Cette architecture est un cas d’école d’optimisation tirant parti de contraintes techniques de façon créative, et montre encore aujourd’hui l’importance d’éliminer les calculs inutiles dès la phase de conception

Analyse de l’architecture d’optimisation de RollerCoaster Tycoon

  • Sorti en 1999, RollerCoaster Tycoon (RCT) est considéré comme un jeu écrit presque entièrement en assembleur (Assembly), capable de simuler en temps réel des milliers d’agents tout en conservant un framerate stable sur le matériel de l’époque
  • En s’appuyant sur un épisode du podcast allemand Stay Forever, l’article analyse en détail comment Chris Sawyer a atteint un niveau d’optimisation extrême
  • Le code source original n’a pas été publié, mais le projet de fans OpenRCT2 permet de vérifier par rétro-ingénierie la structure du code et les techniques d’optimisation employées
  • Maximisation des performances grâce à l’assembleur

    • RCT a été écrit en assembleur plutôt qu’en C ou en C++, ce qui permettait un contrôle des performances bien plus fin que dans la plupart des autres jeux de l’époque
      • Par exemple, Doom (1993) était majoritairement écrit en C, tandis que RCT a été implémenté presque entièrement en assembleur
      • Cette approche était déjà rare à la fin des années 1990, et RCT est souvent considéré comme l’un des derniers grands jeux en assembleur
    • À l’époque, l’optimisation automatique des compilateurs restait limitée, si bien que l’optimisation manuelle pouvait faire une énorme différence
  • Analyse du code via OpenRCT2

    • OpenRCT2 est un projet open source de fans qui a entièrement réimplémenté le jeu original, en réutilisant ses assets tout en conservant une compatibilité à 100 %
      • Les premières versions reproduisaient un comportement presque identique à celui du code original, avant d’intégrer diverses améliorations
    • Ce projet a permis d’observer de près les motifs d’optimisation très fins du code d’origine
    Publicité
  • Granularité des types de données — économie de mémoire

    • RCT stocke la taille des données monétaires différemment selon le contexte
      • Exemple : la valeur totale du parc utilise une variable de 4 octets, tandis que le prix d’une boutique tient sur 1 octet
    • Cette granularité visait à économiser la mémoire et à améliorer l’efficacité du cache ; sur les CPU modernes, l’écart de performance est presque nul, si bien qu’OpenRCT2 a unifié cela en une seule variable de 8 octets
  • Optimisation des opérations mathématiques avec les décalages de bits

    • Dans le code, des opérations comme NewValue = OldValue >> remplacent les divisions par des puissances de deux
    • Ce type d’optimisation n’est possible que lorsque les multiplications ou divisions portent sur des puissances de deux, ce qui laisse penser que les formules du jeu elles-mêmes ont été conçues pour respecter cette contrainte
    • Autrement dit, la structure mathématique du jeu a été pensée dès la conception pour l’efficacité des calculs CPU
  • Un game design pensé pour la performance

    • Comme Chris Sawyer était à la fois programmeur et unique game designer du projet, il a pu bâtir une structure tenant compte des performances dès la phase de conception
    • L’exemple le plus représentatif est le système des visiteurs (pathfinding)
      • Dans la plupart des jeux de simulation, les visiteurs choisissent une destination puis calculent un trajet ; dans RCT, ils marchent de façon aléatoire et découvrent les attractions par hasard
      • Cette approche évite les calculs de pathfinding à grande échelle, ce qui permet de traiter simultanément des milliers de visiteurs
    • Lorsque du pathfinding est nécessaire (par exemple, lorsqu’un mécanicien doit rejoindre une attraction en panne), une limite de profondeur de recherche est appliquée pour éviter les chutes de framerate
      • Les visiteurs ordinaires ne cherchent qu’à travers 5 intersections, les mécaniciens jusqu’à 8
      • Les visiteurs ayant acheté une carte voient cette limite passer à 7
    • Ces limites ne sont pas un simple compromis technique, mais une structure d’optimisation intégrée naturellement au gameplay
    Publicité
  • Gestion des foules et suppression de l’évitement des collisions

    • RCT supprime entièrement les collisions et calculs d’évitement entre visiteurs
      • Des milliers de visiteurs peuvent partager la même tuile de chemin
    • À la place, le jeu suit la densité de population locale, et si l’affluence est trop forte, le niveau de bonheur des visiteurs baisse
      • Le joueur doit donc toujours gérer la congestion, mais avec une charge de calcul bien plus faible
    • Cette méthode est considérée comme un excellent exemple de suppression de calculs physiques complexes tout en préservant l’expérience de jeu
  • Ce que cela apporte au développement moderne

    • L’optimisation de RCT est souvent citée comme un exemple d’utilisation créative des contraintes techniques
    • Une telle approche reste possible aujourd’hui, mais elle exige une collaboration étroite entre programmeurs et designers
    • Il peut parfois être plus efficace, plutôt que de résoudre un problème technique, de supprimer le problème lui-même dès la conception

2 commentaires

 
cadenzah 2026-03-24

S'il vous plaît, donnez beaucoup d'amour à RollerCoaster Tycoon.

 
GN⁺ 2026-03-23
Commentaires Hacker News
  • Warcraft 1, 2 et StarCraft utilisaient tous des cartes dont la taille était une puissance de deux
    Cela permettait d’obtenir de bonnes performances sur les CPU 386/486 lents en remplaçant divisions et multiplications par des décalages de bits
    Le rendu de la carte, les sprites, les polices, le brouillard, etc. étaient gérés par des milliers de lignes d’assembleur, tandis que le reste était du code portable écrit en C
    Pour Blackthorne, les versions SNES, Genesis et DOS avaient chacune été portées à la main avec un assembleur différent, et la version PC générait par macros 100 000 lignes de code de rendu pour le VGA Mode X
    Cette expérience a conduit Blizzard à retenir la leçon que « l’assembleur consomme beaucoup trop de temps de développement »
    Comanche: Maximum Overkill était un simulateur d’hélicoptère à voxels entièrement écrit en assembleur, mais le portage en mode protégé était si difficile que les versions suivantes sont passées au rendu polygonal

    • Un utilisateur de Reddit a retrouvé le code source gold master de StarCraft, mais c’est dommage qu’il l’ait rendu en échange de goodies Blizzard
      EA a publié le code source de la série Command & Conquer, mais Tiberian Sun et Red Alert 2 n’y figuraient pas
      Il aurait été bien que StarCraft soit lui aussi publié au nom de la préservation historique
    • Quand j’ai vu Comanche et Settlers 1 pour la première fois enfant, voir des graphismes sortir du mode texte DOS m’a semblé magique
      C’est à partir de là que je suis devenu complètement passionné de jeux vidéo
    • S’il a aussi travaillé sur Lost Vikings, j’aimerais lui dire merci pour toute la joie de mon enfance
      Je me demande aussi s’il a participé à la demoscene
    • Il y a eu chez Blizzard un incident où le serveur de code source a été perdu sans aucune sauvegarde ; je me demande s’il était là à cette époque
      J’y ai moi-même passé un court moment comme consultant vers la sortie de WC3
    • Maximum Overkill était vraiment un jeu incroyable, au point d’y avoir joué des centaines d’heures
  • Comme le mentionne l’article, on a l’impression que les résultats sont bien plus impressionnants quand le designer et le programmeur sont une seule et même personne
    Même avec la structure hiérarchique des grandes entreprises, on finit par sortir quelque chose en y mettant assez de monde, mais les résultats vraiment créatifs viennent souvent d’un esprit unique du début à la fin
    Je me demande si l’avenir des outils de développement IA ne va pas nous ramener à cette sorte d’« ère du développement en solo »

  • Les game designers doivent toujours tenir compte des caractéristiques numériques
    Les meilleurs designers savent que l’efficacité des calculs ou la précision peuvent avoir un impact sur l’équilibrage du jeu
    Beaucoup de développeurs l’ignorent aujourd’hui, mais cela peut devenir une cause cachée de baisse de qualité

    • Autrefois, je pensais moi aussi que ces micro-optimisations étaient essentielles, mais j’ai changé d’avis après avoir étudié l’architecture en pipeline des CPU modernes
      Aujourd’hui, on est plutôt à 1 cycle pour une addition, 3 pour une multiplication et 12 pour une division, avec plusieurs opérations traitées en parallèle
      À l’époque des anciens Pentium, c’était 46 cycles, avec des fréquences autour de 100 MHz
      Aujourd’hui, c’est surtout le layout mémoire qui compte — un seul cache miss peut coûter entre 100 et 1000 cycles
      Faire des calculs sur un int[] est bien plus rapide que sur un Monster[]
    • Je développe le noyau CAD csgrs, et j’ai l’impression que le calcul numérique reste un problème non résolu
      Il existe des compromis entre vitesse, précision, taille de stockage et complexité
      Des articles comme Toward an API for the Real Numbers proposent une approche progressive pour traiter ce genre de problème
      Il existe diverses méthodes — erreurs en virgule flottante, arithmétique d’intervalles, calcul symbolique — mais au final, si on ne comprend pas les compromis, on se fait piéger par le problème
    • Les jeux commerciaux sont des produits fabriqués à grande échelle, donc le fait qu’un designer comprenne les contraintes techniques constitue un vrai atout en termes de sens du design industriel
      Par exemple, Fumito Ueda a pris grand soin de la faisabilité technique dans Shadow of the Colossus, et Doom était lui aussi une fusion de créativité et de technique
      Voir cette interview
    • La qualité d’un jeu ne se résume pas à l’efficacité des performances d’exécution, c’est aussi une question de plaisir et de finition
      Les bugs, la cohérence du récit et l’immersion sont plus importants
      Bien sûr, de grosses chutes de framerate dégradent la qualité, mais si le jeu tourne de manière fluide sur le matériel visé, les améliorations devraient se concentrer sur d’autres aspects
    • En développant un produit basé sur un ARM Cortex-M4, j’ai créé un générateur de nombres aléatoires personnalisé
      Je l’ai ajusté pour pouvoir charger des constantes immédiatement avec les instructions Thumb-2, afin d’éviter les memory stalls
      Cela a permis d’utiliser des nombres aléatoires rapidement et efficacement, et tous les tests sont passés
      Mais plus tard, quand la cible a été changée pour un Cortex-M0, ce code a été abandonné
  • J’ai trouvé intéressant le fait de transformer les contraintes techniques en éléments de gameplay
    Cela m’a fait penser au système de Blood Moon dans The Legend of Zelda

  • L’explication disant que « remplacer /8 par >>3 permet d’économiser une division » est fausse avec les compilateurs modernes
    Si les types sont corrects, le compilateur optimise automatiquement cela en décalage de bits

    • En revanche, dans le cas des entiers signés (signed), des opérations supplémentaires sont ajoutées afin de respecter les règles d’arrondi du standard C
  • J’ai été surpris de voir l’explication selon laquelle « en binaire, un décalage à gauche revient à multiplier par deux »
    C’est curieux de voir à quel point ce concept de base peut paraître presque nouveau ou étrange en 2026

  • Dire que « le compilateur ne remplace pas une multiplication par une puissance de deux par un décalage » est une vieille blague
    Déjà dans les années 2000, les compilateurs optimisaient cela si évidemment qu’ils en bâilleraient presque

  • Lecture très plaisante. À propos de RCT, je recommande aussi les ressources ci-dessous

  • Je me demande s’il est possible, dans un grand studio, de sublimer les contraintes techniques pour en faire une caractéristique du jeu
    De la même façon qu’en narration, les obstacles rendent une histoire plus intéressante, un développeur solo peut transformer les limites techniques en éléments créatifs
    Par exemple, je pense à une approche qui réinterpréterait des bugs ou des glitches comme des mini-jeux

  • En voyant la partie sur le pathfinding de RCT, cela m’a rappelé la vidéo YouTube de Marcel Vos
    Il publie beaucoup de vidéos qui explorent en profondeur le fonctionnement interne de RCT