The Making of a Scavenger Hunt
For the final blog post of the class, I've chosen to do a breakdown on the building of our game's scavenger hunt system! Fair warning to any programmers out there, when I prototype I strive for function over performance. The code could be done so much better, but it works and that's all I need.
Each room in our game hosts a scavenger hunt that takes place across two versions of the level: the normal world and the astral world. The first part of the puzzle is always figuring out how to access the astral world. Upon arriving in the astral world, Leela the Astral Cat is there to greet you and usually provides some cryptic explanation for what you need to do. The puzzles always end with Leela congratulating the player and telling them which object will send them home. In this post, I'll provide a brief breakdown explaining how this was built.
Every object in the game, from the fridge to the toilet, shares one script called object_base. When a new object is added to the game, the editor can give it a name for identification and two text fields called InteractText and ScavengerHuntText. Interact Text is the default text shown when the player interacts with the object. ScavengerHuntText stores the text to later be used in the scavenger hunt (we'll come back to this). Some objects, such as the TodoList and Microwave, are tagged as "startpoints" for their respective scavenger hunts. Whenever an object is interacted with, the script checks to see if this is a startpoint or a regular object. Startpoint objects will activate a new scavenger hunt and set it at the first "stage", while regular objects will check to see if they are part of an ongoing scavenger hunt. If the player is in a scavenger hunt, the object will check itself against the current stage of the puzzle. Each stage searches for a specific object by name, preventing the player from immediately solving the scavenger hunt by directly going to the final object, rather, requiring them to go through the different objects in their exact order. When the player interacts with the object the stage is looking for, the stage updates to ask for another. This is fundamentally how each of the scavenger hunts is constructed: startpoint object -> series of specific object stages -> return to Leela. Speaking of which...
Leela is essentially a very versatile game object. Where most objects only appear once in their respective rooms, Leela appears in every room's astral version. Rather than having a list of stages, Leela has a list of dialogue to check. She overwrites the game's dialogue system to allow for multiple consecutive textboxes. Most objects by default can only display a single block of text without trapping the player in a dialogue loop. Leela tracks her own dialogue in each room similar to how objects check themselves against the stage list. This works for Leela because she is one special object, rather than a series of defaults inheriting from the same script. The only other object that can do this is the TV (other objects would crash the game engine with no error message, I have no idea why it only works for the TV). Leela can also do one special thing that regular objects can't do: she can change object scripts. When the player completes their puzzle, Leela can transform any object into a portal that takes the player back to the regular world. This also has to do with Leela's consistency. Regular objects can't do this without generating errors since they are all based on the same object_base script, which risks transforming the wrong object at the wrong time (usually causing an error). Leela will never risk turning herself into a portal, so she can freely transform other objects at certain stages of the scavenger hunt (mainly the end).
The last element of building our scavenger hunts is the Global.gd script. Unlike other code, the Global code runs the moment the game starts and continues to run across every level. This helps overcome a major structural difficulty of building the game: moving between levels removes the previous level and generates the new one. When the player leaves the normal world, the level is destroyed and replaced with the astral world's corresponding level. The Global code is responsible for tracking the player's progress, of both the scavenger hunts completed and the present stage they're on. The Global code is also privy to the scavenger hunt stage, but because it's always running and doesn't need to be activated like an object, it also updates the game world to reflect the scavenger hunt's progress. Remember the ScavengerHuntText field that every object has? The Global code changes the normal InteractText to the ScavengerHuntText behind the scenes before the player interacts with the object. The reason for this has to do largely with how the dialogue system works.
The dialogue system is probably the most difficult part of the game code, while also being the shortest. The dialogue system controls the text and textbox on the screen. Whenever an object is interacted with, it calls upon the dialogue system to show what it wants. The dialogue system keeps track of the object showing its text, how much text it has to show, and closes the textbox when there's nothing else. This works fine when objects only have one piece of text to show at a time. Leela changes things a bit. Rather than have the player interact with Leela multiple times, once for each piece of text she has to show, the dialogue system was modified to include a continue button. The continue button allows multiple dialogues to be strung together by automatically re-interacting with the object. The problem here becomes pretty clear: How do you stop continuous dialogue? The dialogueCounter and dialogueTotal variables were introduced to define a breakpoint: the dialogue stops when the dialogueCounter matches the dialogueTotal. This doesn't always work as intended, but it does allow specific objects like Leela to have multiple lines of dialogue. Because of this continuous re-interaction, however, text needs to be updated before the loop starts, even when there's only one textbox to display. Objects largely lost the ability to update their own text before the textbox opens as an unintended consequence of creating objects with continuous dialogue. The Global code mentioned earlier, by virtue of always running, can act before the loop, making it perfect for remotely updating scavenger hunt text with every stage, before the player gets the chance to interact with the object.
I'll come back soon to add in the pictures and slap on a good conclusion.
Leave a comment
Log in with itch.io to leave a comment.