Jul 26, 2018

A swarm of bugs: small stories about the bugs and glitches of TUAT

11:22 AM Posted by Lucas Izumi No comments

When I joined the TUAT team many elements of the game were already done. There was already the outline of a basic inventory system, movement and a primitive dialogue system, among others. I have worked on some of these systems, polishing a few and correcting small errors. Systems that were working (apparently) I didn't touch and focused on implementing the new systems that were needed. If you're reading this, here's my tip: never do that. This week's post is all about the most bizarre bugs that happened in TUAT, due to my omission to the old code.

The troublemaker

There is an NPC that you find early in the game (whose identity is a mystery) and accompanies you throughout the scenarios. For a long time he was the "responsible" for the strangest bugs I had ever stumbled upon in my years of game development. It was amazing how everything seemed tied to him, making him pretty much an entity that conspired against the game working well.

1) The cross
Once, while correcting the game's initial inventory system (which appeared at the top of the screen), I had to identify the position of an item the character would collect.

Initial inventory system
Who gave this item to the player was, precisely, the NPC from the beginning. I had set the item to be visible by the time it was to be added to the inventory and ... when I talked to the NPC, it happened:

The misterious cross
The item had appeared, but something was strange: its image was superimposed over itself, but horizontally! I went back to the code, searched for a line where a second item, with a changed angle, was created. Nothing. I returned to the game, with the help of the Game Maker debugger, I now intended to count how many items of that type were being created, just to confirm. I performed the same steps as before and ... the "cross" appeared again, but there was only ONE item despite my eyes showing me clearly that there were two. How?

At that moment I was already attributing divine powers to that NPC. There could be some code inserted into some object in the game that "drew" a second item just as the other was created. Although it seemed absurd, it was a possibility. I decided to check something out before embarking on that hunt, though. I went to check the sprite of the item, the image that is used for it in the game. I opened the file and there it was: vertically, as it was meant to be. I also noticed that there was a second sprite in that file: one with the item in horizontal position. The pieces were starting to fit...

Do you already have an idea about what caused the bug? Leave your answer in the comments! At the end of next week's post I'll show you the causes and how they have been fixed!

2) Age reaches everyone
The dialogue system that we use in TUAT allows the branching of answers and options. For this purpose, whenever an NPC is "created" in the game, it loads the text file corresponding to the dialog tree that it needs to follow. Whenever a dialog is terminated, we "recreate" the NPC, thereby loading the new dialog.

The NPC from the beginning has an extensive dialog tree that is divided into several text files, something that always worked perfectly. Until you decide to move on to the next scenario, that is. Once the player solves all the Tomb puzzles, he can finally move on to the next scenario. The NPC, which serves as a guide throughout this time, has specific dialogues for all situations, including when the player succeeds in the Tomb.

A guide inside the tomb
The problem is that at that moment, when talking to the NPC, he simply repeats an earlier phrase - unrelated to the current scenario. If the player persists and talks to him again, then he speaks what he should from the beginning. Why did he repeat the phrase? And why only after the player completed the tomb?

3) "I want you away from me"
The mysterious NPC from the beginning of the game attacks again. This time he acted in an even more unusual way. One of the options for ending the dialogue with him was "I want you away from me." I was testing the routes of conversation and I opted for this option. My surprise was when he really walked away (more than expected).

"I left Egypt and now I'm a ninja."
I soon noticed that this happened every time I closed a dialogue (only with him). Everything worked so well before, why - out of nowhere - would he act like this?

At this point I learned that nothing happens "out of nowhere". I listed all the recent changes that had happened in the game and one soon caught my eye: the sprite of this NPC had recently changed. I even had to reposition him in the scenarios. That can only be it, right? But why would he be appearing on the floor and not in his old position?

Open your eyes

Inside the game we have a secret NPC named "Mehen". This NPC is able to "open the eyes" of the main character, revealing secrets about what is happening. All this at a price, of course. The interesting point of all this is that the bug attached to this NPC was responsible for opening my eyes, showing a problem that was masked by other NPCs and that was directly attacking the performance of the game.

4) The mirror of Mehen
This bug was also linked with the dialog system and consisted basically of creating a second screen - containing all the visual elements of the system - shifted slightly to the side.

Mehen and the duplicated interface
The interesting thing is that the text of the dialogues did not duplicate. It were just the visual elements that made up the interface. It is worth noting that the dialog system is implemented along the lines of the Object Orientation, that is, based on a pre-assembled model, "children" can be created, which inherit all attributes of the "parent" model. Thus, all NPCs in the game are linked to a "child" of the dialogue system. With Mehen it was no different and yet she was the only NPC that this problem was present.

Identifying the error was a bit tricky. It was the model of the dialog system that set up the whole interface and, after checking it a dozen times, everything seemed to be ok. I then went to the lower level: to look at element by element that made up this interface. Bingo!

The model created and drew an X element. This X element, in turn, also drawn itself. It may seem confusing, but since two different fonts were drawing the same element, it was to be expected that it would appear duplicated on the screen.

Yeah, but why is it shifting to the left? At TUAT we work with views. This means that a scenario may be much larger than the portion that is being displayed on your screen, but the game's camera is limited to only one region (otherwise the entire scenario would have to fit on your screen and that would mean it would be extremely small). Finally, when the X element is created, it does not calculate the position of the current portion of the screen (the model is the one responsible for this). Therefore, it uses the default coordinates based on the resolution of the screen in question and this makes it draw itself to the left.

By changing the elements in its base, the bug has been fixed - now only the model controls the dialog system interface.

An interesting point is that, analyzing with the debugger, this happened to all NPCs but the elements were all drawn exactly at the same point (one over the other). So there was no such visual hint that things were being duplicated. The only NPC that introduced this behavior was Mehen and the reason for that, so far, is still a mystery to me.


Quando eu entrei para o time do TUAT muitos elementos do jogo já estavam prontos. Já havia o esboço de um sistema básico de inventário, movimentação e um diálogo primitivo, entre outros. Eu trabalhei em cima de alguns desses sistemas, polindo alguns ou apenas corrigindo pequenos erros. O que funcionava (aparentemente) eu não toquei e foquei em implementar os novos sistemas que eram necessários. Se você está lendo isso, fica aqui a minha dica: nunca faça isso. O post dessa semana é todo sobre os bugs mais bizarros que aconteceram no TUAT, por conta da minha omissão para com o código antigo.

O encrenqueiro

Existe um NPC que você encontra logo no início do jogo (cuja identidade é um mistério) e que te acompanha ao longo dos cenários. Por um bom tempo ele foi o "responsável" pelos bugs mais estranhos que eu já havia trombado nos meus anos de desenvolvimento de jogos. Era impressionante como tudo parecia vinculado a ele, tornando-o praticamente uma entidade que conspirava contra o funcionamento do jogo.

1) A cruz
Certa vez, enquanto corrigia o sistema de inventário inicial do jogo (que aparecia no topo da tela), precisei identificar a posição de um item que o personagem iria coletar.

Sistema inicial de inventário
Quem dava esse item para o jogador era, justamente, o NPC do início. Eu tinha definido para o item ficar visível no momento em que ele estivesse para ser adicionado ao inventário e... quando conversei com o NPC, isso aconteceu:
A cruz misteriosa
O item havia aparecido, mas algo estava estranho: sua imagem estava sobreposta sobre ela mesmo, porém na horizontal! Eu voltei para o código, procurei por alguma linha onde um segundo item, com ângulo alterado, era criado. Nada. Voltei para o jogo, com a ajuda do debugger do Game Maker, eu agora pretendia contar quantos itens daquele tipo estavam sendo criados, só para confirmar. Executei os mesmos passos de antes e... a "cruz" apareceu de novo, porém, só havia UM item apesar dos meus olhos me mostrarem claramente que haviam dois. Como?

Nesse momento eu já estava atribuindo poderes divinos àquele NPC. Podia haver algum código inserido em algum objeto do jogo que "desenhava" um segundo item no exato momento que o outro era criado. Apesar de parecer absurdo, era uma possibilidade. Eu decidi checar algo antes de embarcar nessa caçada, entretanto. Fui verificar o sprite do item, a imagem que é usada para ele no jogo. Abri o arquivo e lá estava ele: na vertical, como era para ser. Notei também que havia um segundo sprite naquele arquivo: um com o item na horizontal. As peças começavam a se encaixar...

Você já tem uma ideia sobre o que causava o bug? Deixe sua resposta nos comentários! No final do post da semana que vem mostrarei as causas e como foram corrigidos!

2) A idade chega para todos
O sistema de diálogo que usamos no TUAT permite a ramificação de respostas e opções. Para tal efeito, sempre que um NPC é "criado" no jogo, ele carrega o arquivo de texto correspondente à árvore de diálogo que ele precisa seguir. Sempre que um diálogo é encerrado, nós "recriamos" o NPC, carregando assim o novo diálogo.

O NPC do início tem uma árvore de diálogos extensa e dividida em vários arquivos de texto, algo que sempre funcionou perfeitamente. Até o momento em que você decidia passar para o próximo cenário. Uma vez que o jogador resolve todos os puzzles da Tumba, ele pode enfim avançar e seguir para o próximo cenário. O NPC, que serve de guia durante todo esse tempo, tem diálogos específicos para todos os momentos, inclusive para quando o jogador tem êxito na Tumba.

Um guia dentro da tumba
O problema é que, nesse momento, ao falar com o NPC, ele simplesmente repete uma frase anterior - não relacionada com o cenário atual. Se o jogador insistir e falar com ele novamente, aí sim ele fala o que deveria desde o início. Por que ele repetia a frase? E por que só depois que o jogador completava a tumba?

3) "Quero você longe de mim"
O misterioso NPC do início do jogo ataca novamente. Desta vez ele agiu de uma forma mais inusitada ainda. Uma das opções para encerrar o diálogo com ele era "quero você longe de mim". Estava eu testando as rotas de conversa e optei por essa opção. A minha surpresa foi quando ele realmente se afastou (mais do que o esperado).

"Abandonei o Egito e agora virei ninja."
Logo notei que isso acontecia toda hora que eu encerrava um diálogo (apenas com ele). Tudo funcionava tão bem antes, por que - do nada - ele agiria assim?

Nesse ponto eu aprendi que nada acontece "do nada". Listei todas as mudanças recentes que tinham acontecido no jogo e uma logo me chamou a atenção: o sprite desse NPC havia sido alterado há pouco tempo. Eu tive até que reposicionar ele nos cenários. Só pode ser isso, certo? Mas por que ele estaria aparecendo no chão e não na posição antiga dele?

Abrindo os olhos

Dentro do jogo temos um NPC secreto chamado "Mehen". Esse NPC é capaz de "abrir os olhos" do personagem principal, revelando segredos sobre o que está acontecendo. Tudo isso à um preço, claro. O ponto interessante disso tudo é que o bug atrelado a esse NPC foi responsável por abrir os meus olhos, mostrando um problema que era mascarado por outros NPCs e que atacava diretamente a performance do jogo.

4) O espelho de Mehen
Esse bug também era ligado com o sistema de diálogo e consistia em, basicamente, criar uma segunda tela - contendo todos os elementos visuais do sistema - deslocada um pouco para o lado.

Mehen e a interface duplicada
O interessante é que o texto dos diálogos não se duplicava. Eram apenas os elementos visuais que compunham a interface. Vale notar que o sistema de diálogo é implementado nos moldes da Orientação à Objetos, ou seja, baseado em um modelo pré-montado, "filhos" podem ser criados, os quais herdam todos os atributos do modelo "pai". Sendo assim, todos os NPCs do jogo são vinculados a um "filho" do sistema de diálogo. Com a Mehen não foi diferente e, ainda assim, ela era o único NPC que esse problema se fazia presente.

Identificar o erro foi um pouco complicado. Era o modelo do sistema de diálogo que montava toda a interface e, após checar umas dezenas de vezes, tudo parecia estar ok. Passei então para o nível inferior: olhar elemento por elemento que compunha essa interface. Bingo!

O modelo criava e desenhava um elemento X. Esse elemento X, por sua vez, também se desenhava. Pode parecer confuso mas, uma vez que duas fontes diferentes desenhavam o mesmo elemento, era de se esperar que ele aparecesse duplicado na tela.

Tá, mas e por que ele está deslocado? Em TUAT nós trabalhamos com "views". Isso significa que um cenário pode ser bem maior que o trecho que está sendo exibido na sua tela, porém a câmera do jogo fica limitada à apenas uma região (caso contrário o cenário inteiro ia ter que caber na sua tela e isso significaria que ele ficaria extremamente pequeno para que isso fosse possível). Enfim, quando o elemento X é criado, ele não calcula a posição do trecho atual (quem faz isso é o modelo). Logo, ele usa as coordenadas padrão baseado na resolução da tela em questão e por isso fica mais à esquerda.

Alterando os elementos em sua base, o bug foi corrigido - agora apenas o modelo controla a interface do sistema de diálogo.

Um ponto interessante é que, analisando pelo debugger, isso acontecia com todos os NPCs, porém os elementos eram desenhados exatamente no mesmo ponto. Sendo assim não havia essa dica visual de que as coisas estavam sendo duplicadas. O único NPC que apresentou esse comportamento foi a Mehen e o porquê disso, até o momento, ainda é um mistério pra mim.