27 pontos por GN⁺ 2026-03-23 | 2 comentários | Compartilhar no WhatsApp
  • RollerCoaster Tycoon, lançado em 1999, é um jogo de simulação escrito quase inteiramente em assembly que manteve desempenho estável mesmo processando milhares de visitantes em tempo real
  • O desenvolvedor Chris Sawyer escolheu controle de baixo nível em vez de linguagens de alto nível, criando uma das últimas grandes gerações de jogos em assembly com eficiência máxima de CPU
  • Por meio do projeto de fãs OpenRCT2, os padrões precisos de otimização e as técnicas de economia de memória do original foram analisados por engenharia reversa
  • O jogo usa operações de deslocamento de bits e detalhamento de tipos de dados para aumentar a velocidade de cálculo e a eficiência de cache, além de tornar possível uma simulação em larga escala com limites na profundidade de pathfinding e remoção de cálculos de colisão
  • Essa estrutura é um exemplo clássico de otimização que usa restrições técnicas de forma criativa e ainda hoje mostra a importância de eliminar cálculos desnecessários já na fase de projeto

Análise da estrutura de otimização de RollerCoaster Tycoon

  • RollerCoaster Tycoon (RCT), lançado em 1999, foi escrito quase inteiramente em assembly (Assembly) e é avaliado como um jogo que conseguiu manter frames estáveis no hardware da época enquanto simulava milhares de agentes em tempo real
  • Com base no conteúdo abordado no podcast alemão sobre jogos Stay Forever, o texto analisa em detalhes como Chris Sawyer alcançou um nível extremo de otimização
  • O código-fonte original não foi publicado, mas o projeto feito por fãs OpenRCT2 permite verificar por engenharia reversa a estrutura do código e as técnicas de otimização
  • Maximização de desempenho com base em assembly

    • RCT foi escrito em assembly em vez de C ou C++, o que permitiu um controle de desempenho muito mais detalhado do que em outros jogos da época
      • Por exemplo, Doom (1993) foi escrito majoritariamente em C, enquanto RCT foi implementado quase inteiramente em assembly
      • Essa abordagem já era rara no fim dos anos 1990, e RCT é considerado um dos últimos grandes jogos em assembly
    • Como a otimização automática dos compiladores ainda era limitada na época, a otimização manual fazia grande diferença no desempenho
  • Análise de código por meio do OpenRCT2

    • OpenRCT2 é um projeto open source em que fãs reimplementaram completamente o jogo original, usando os mesmos assets e mantendo 100% de compatibilidade
      • As versões iniciais reproduziam um comportamento quase idêntico ao do código original, e depois várias melhorias foram adicionadas
    • Esse projeto permitiu observar os padrões minuciosos de otimização do código original
  • Detalhamento de tipos de dados — economia de memória

    • RCT armazena dados monetários em tamanhos diferentes conforme o contexto
      • Ex.: o valor total do parque usa uma variável de 4 bytes, enquanto o preço de uma loja usa uma variável de 1 byte
    • Esse detalhamento foi feito para economizar memória e melhorar a eficiência de cache, mas como em CPUs modernas a diferença de desempenho é quase nula, no OpenRCT2 isso foi unificado em uma única variável de 8 bytes
  • Otimização de operações matemáticas com deslocamento de bits

    • No código, a operação NewValue = OldValue >> substitui divisões por potências de 2
    • Como essa otimização só é possível quando multiplicações e divisões envolvem potências de 2, parece que as próprias fórmulas do jogo foram projetadas para atender a essa condição
    • Em outras palavras, a estrutura matemática já considerava a eficiência de CPU desde a etapa de design do jogo
  • Design de jogo orientado a desempenho

    • Como Chris Sawyer participou de RCT como programador e único game designer, foi possível criar uma estrutura que já levava desempenho em conta desde o início do projeto
    • Um exemplo representativo é o sistema de visitantes (pathfinding)
      • Na maioria dos jogos de simulação, os visitantes definem um destino e calculam uma rota, mas em RCT os visitantes andam aleatoriamente e encontram atrações por acaso
      • Essa abordagem evita cálculos de pathfinding em larga escala e permite processar milhares de visitantes ao mesmo tempo
    • Quando o pathfinding é necessário (ex.: um mecânico indo até uma atração quebrada), há um limite na profundidade da busca para evitar queda de frames
      • Visitantes comuns procuram apenas até 5 cruzamentos, mecânicos até 8
      • Visitantes que compraram um mapa têm o limite de busca aumentado para 7
    • Essas limitações não são apenas um compromisso técnico, mas uma estrutura de otimização integrada naturalmente ao gameplay
  • Processamento de multidões e omissão de desvio de colisão

    • RCT remove completamente os cálculos de colisão e desvio entre visitantes
      • Milhares de visitantes podem compartilhar o mesmo tile de caminho
    • Em vez disso, o jogo acompanha a densidade populacional ao redor e faz com que a felicidade dos visitantes diminua quando o nível de lotação é alto
      • O jogador ainda precisa gerenciar aglomerações, mas o volume de cálculo é muito menor
    • Essa abordagem é considerada um exemplo representativo de como remover cálculos físicos complexos sem prejudicar a experiência de jogo
  • Lições para o desenvolvimento moderno

    • A otimização de RCT é vista como um caso de uso criativo de restrições técnicas
    • Ainda hoje, essa abordagem é possível, mas exige colaboração estreita entre programadores e designers
    • Em alguns casos, em vez de resolver um problema técnico, eliminar o próprio problema já na etapa de design pode trazer ganhos de desempenho ainda maiores

2 comentários

 
cadenzah 2026-03-24

Por favor, deem muito amor ao RollerCoaster Tycoon.

 
GN⁺ 2026-03-23
Comentários no Hacker News
  • Warcraft 1, 2 e StarCraft usavam mapas com tamanho em potências de 2
    Isso permitia ganhar desempenho em CPUs 386/486 lentas usando operações de shift em vez de divisão e multiplicação
    Renderização de mapa, sprites, fontes e efeitos de neblina eram tratados com milhares de linhas de assembly, e o restante era código altamente portável escrito em C
    No caso de Blackthorne, as versões de SNES, Genesis e DOS foram portadas manualmente com assembly diferente para cada uma, e a versão de PC gerou por macro 100 mil linhas de código de renderização para VGA Mode X
    Essa experiência levou a Blizzard à lição de que “assembly consome tempo demais de desenvolvimento”
    Comanche: Maximum Overkill era um simulador de helicóptero baseado em voxels escrito inteiramente em assembly, mas a migração para modo protegido era tão difícil que as versões seguintes passaram para renderização por polígonos

    • Um usuário do Reddit encontrou o código-fonte gold master de StarCraft, mas foi uma pena que o tenha devolvido em troca de brindes da Blizzard
      A EA abriu o código-fonte da série Command & Conquer, mas Tiberian Sun e Red Alert 2 ficaram de fora
      Seria bom se StarCraft também fosse aberto por uma questão de preservação histórica
    • Quando vi Comanche e Settlers 1 pela primeira vez na infância, parecia magia ver gráficos saindo do modo texto do DOS
      Foi aí que fiquei completamente fascinado por jogos
    • Se a pessoa também trabalhou em Lost Vikings, queria agradecer por ter proporcionado tanta diversão na infância
      Também fico curioso se ela participou da demoscene
    • Houve um incidente na Blizzard em que perderam o servidor de código-fonte e não havia backup; queria saber se ela estava lá nessa época
      Eu estive por pouco tempo como consultor perto do lançamento de WC3
    • Maximum Overkill foi um jogo incrível, a ponto de eu jogar centenas de horas
  • Como o texto menciona, parece que os resultados mais impressionantes surgem quando designer e programador são a mesma pessoa
    Mesmo com a estrutura hierárquica de grandes empresas, dá para empurrar algo com bastante gente, mas resultados realmente criativos muitas vezes nascem completos na cabeça de uma pessoa só
    Também fico pensando se o futuro das ferramentas de desenvolvimento com IA pode acabar sendo um retorno a essa “era do desenvolvimento solo”

  • Designers de jogos ainda precisam considerar características numéricas
    Quanto melhor o designer, mais ele entende que fatores como eficiência computacional e precisão influenciam o balanceamento do jogo
    Hoje em dia há muitos desenvolvedores que ignoram isso, mas às vezes esse é um motivo oculto para a queda de qualidade do jogo

    • Antigamente eu também achava que esse tipo de micro-otimização era importante, mas mudei de ideia depois de estudar a estrutura de pipeline das CPUs modernas
      Hoje uma soma leva 1 ciclo, uma multiplicação 3 ciclos e uma divisão 12 ciclos, e várias operações são processadas em paralelo ao mesmo tempo
      Na era do Pentium antigo, eram 46 ciclos e clock de 100 MHz
      Hoje o layout de memória é muito mais importante — um único cache miss pode custar de 100 a 1000 ciclos
      Fazer operações com int[] é muito mais rápido do que com Monster[]
    • Estou desenvolvendo o kernel CAD csgrs e sinto que cálculo numérico ainda é um problema em aberto
      Há trade-offs entre velocidade, precisão, tamanho de armazenamento e complexidade
      Artigos como Toward an API for the Real Numbers propõem abordagens graduais para resolver esse tipo de problema
      Existem vários métodos, como erro de ponto flutuante, aritmética intervalar e cálculo simbólico, mas no fim, se você não entender os trade-offs, o problema vai te engolir
    • Jogos comerciais são produtos fabricados em massa, então o fato de o designer entender restrições técnicas é uma grande vantagem em termos de sensibilidade de design industrial
      Por exemplo, Fumito Ueda considerou com muito cuidado a viabilidade técnica em Shadow of the Colossus, e Doom também foi uma combinação de criatividade com tecnologia
      Vale ver esta entrevista relacionada
    • A qualidade de um jogo não é apenas questão de desempenho eficiente em runtime, mas de diversão e acabamento
      Bugs, consistência da história e imersão são mais importantes
      Claro, quedas severas de frame prejudicam a qualidade, mas se roda de forma fluida no hardware-alvo, o foco da melhoria deve ir para outros pontos
    • Ao desenvolver um produto baseado em ARM Cortex-M4, criei um gerador de números aleatórios customizado
      Ajustei para que constantes pudessem ser carregadas imediatamente com instruções Thumb-2, evitando stalls de memória
      Com isso, foi possível usar números aleatórios de forma rápida e eficiente, e todos os testes passaram
      Mas depois o projeto mudou para Cortex-M0 e esse código acabou descartado
  • Achei interessante a parte de transformar restrições técnicas em elementos de gameplay
    Isso me fez lembrar do sistema de Blood Moon de The Legend of Zelda

  • A explicação de que “usar >>3 em vez de /8 economiza uma divisão” não é verdadeira em compiladores modernos
    Se o tipo estiver correto, o compilador otimiza automaticamente para operação de shift

    • Porém, no caso de inteiros com sinal (signed), entram operações extras para respeitar a regra de arredondamento do padrão C
  • Fiquei surpreso ao ver a explicação de que “em binário, shift à esquerda dobra o valor”
    É curioso como em 2026 esse conceito tão básico pode parecer quase estranho de novo

  • Dizer que “o compilador não troca multiplicações por potências de 2 por shifts” é uma piada antiga
    Já nos anos 2000 os compiladores bocejavam diante desse tipo de código e otimizavam isso automaticamente

  • Gostei da leitura. Sobre RCT, também recomendo estes materiais

  • Fico pensando se, em grandes estúdios, ainda dá para transformar restrições técnicas em características do jogo
    Assim como obstáculos deixam a narrativa mais interessante, um desenvolvedor solo pode converter limitações técnicas em elementos criativos
    Dá para imaginar abordagens como reinterpretar bugs ou glitches como minigames

  • Ao ver a parte sobre pathfinding em RCT, lembrei do vídeo do Marcel Vos no YouTube
    Ele publica muitos vídeos explorando a fundo o funcionamento interno de RCT