Discussion:Summer Camp Game
This project was our degree capstone. A swan song, if you will. It served as proof that we learned something in the four long years of higher education. This project effectively combined and utilized a multitude of computer science concepts and fundamentals.
Design Tracking Player Progression
From the beginning, me and my project partner wanted this game to have multiple endings based upon the players decisions. At the time we really had no idea on how to achieve this. There was no built-in functionality or library within GameMaker that would easily solve this problem for us. As the person who was in charge of the majority of programming and of the software architecture, it was up to me to figure this out. The solution was found within the subject of Design Patterns, specifically, singletons.Singletons allow the existence of a single static instance of a globally accessible object. With singletons, we are able to keep track of the players state across scenes/levels. Also, other objects/entities are able to get information from the global singleton about the state of the player and present different dialogue when the player interacts with them.
The Dialogue System
The dialogue system in this project is the single most complex system in the game. On its surface, a dialogue system seems quite simple:
- display message to player
- display player response options
- display next message based upon the players chosen response option.
{
"interaction_1": {
"node_1": {
"line0": "This is line 1 of interaction",
"line1": "This is line 2 of interaction",
"line2": "This is line 3 of interaction. Dialogue options should show up.",
"ResponseOption0": "Yes!",
"ResponseOption1": "No!"
},
"node_2": {
"line0": "This shows if you answer YES"
},
"node_3": {
"line0": "This shows if you answer NO"
}
}
.... More interactions ....
}
This original concept works because the next node in the tree is programmatically inferred based on the response option chosen.
But, what if you want to go back and repeat a node?
Well we add explicit next nodes. So now the JSON files look like this.
{
"interaction_2": {
"node_1": {
"line0": "This is line 1 of interaction",
"line1": "This is line 2 of interaction",
"line2": "This is line 3 of interaction. Dialogue options should show up.",
"ResponseOption0": "Yes!",
"ResponseOption1": "No!",
"NextNode0": 0, // this will loop, or rather start node_1 again
"NextNode1": 3 // This starts node_4
},
// Due to the next nodes property this is not going to be accessible
"node_2": {
"line0": "This shows if you answer YES"
},
// Due to the next nodes property this is not going to be accessible
"node_3": {
"line0": "This shows if you answer NO"
}
"node_4": {
"line0": "you chose option 1 "No!" "
}
}
}
As pointed out in the comments in the code. It is possible to for some nodes to be unaccessible.
But it will be fine as long as the next nodes are specified for each response.
So, at the start of each scene/level the interactions and their nodes are loaded into a hash table from the JSON.
Each interactable entity/character in the scene has string for their interaction that would map to the interaction in the hash.
This makes each interaction and its nodes accessible at a time complexity of: O(1)
Notable Feature
Rewind time effect As you can see from the clip, their is an interesting time rewind effect. (besides the CRT shader) How is this effect achieved? GameMaker has a built-in functionality to capture application surfaces and store them in video RAM. These surfaces are essentially "screen-shots" with zero compression. So we take these "screen-shots" store them in a stack data-structure, and when we are ready to rewind time we pop the frames off the stack and display them. Yes, filling up the "screen-shots" stack can take up alot of video RAM but adding to and popping a stack has a time complexity of: O(1)