CONCRETE ARCHITECTURE: SUPERTUXKART The Architects

Jake Gibbons – [email protected] Jacob Clarke-Mcrae – [email protected] Hassan Hanino – [email protected] Ryan Tse – [email protected] Dominique Flabbi – [email protected] Athena Fung – [email protected]

th November 11 , 2016 Table of Contents TABLE OF CONTENTS ...... 2 ABSTRACT ...... 3 INTRODUCTION ...... 3 ARCHITECTURE ...... 3 DERIVATION PROCESS ...... 3 CONCRETE ARCHITECTURE ...... 6 SUBSYSTEMS ...... 7 USE CASES ...... 11 NEW GAME ...... 11 DRIVE ...... 12 DIFFICULTIES ENCOUNTERED ...... 13 LESSONS LEARNED ...... 13 CONCLUSIONS ...... 13 GLOSSARY ...... 14 REFERENCES ...... 14

2 Abstract The goal of this study is to derive a concrete architecture for the game SuperTuxKart, and then compare it to our conceptual architecture, which was designed in our last study. After comparing the two architectures, we ended up slightly modifying our conceptual architecture to be more accurate to the of the game. The key parts of our paper consist of our redesigned conceptual architecture, our concrete architecture, descriptions of our subsystems, two sequence diagrams for common use cases, difficulties encountered and lessons learned. We were able to derive the concrete architecture of SuperTuxKart by using a tool called Understand. We uploaded the source code of SuperTuxCart and then grouped all the entities into their respective subsystems. Understand was then able to show us all the function calls or dependencies between our subsystems. This let us build a concrete architecture based on our conceptual architecture. We found that the layered style that we used for our conceptual architecture worked well to represent the actual architecture of the game’s source code. We believe this because when we used Understand to reveal the function calls from subsystem to subsystem, the dependencies included in our conceptual architecture (that is the dependencies from one layer down to the next layer) were usually the dependencies that had the most function calls. The layer to layer dependencies would on average have many more calls than dependencies going up or skipping layers. Once we used Understand to develop our concrete architecture, we were able to visualize how the subsystems actually interacted, and then were able to make changes to our conceptual architecture, making it more accurate. In the end, we had a redesigned layered conceptual architecture, as well as our layered concrete architecture. We continue to believe that the layered architecture style is ideal for the organization of source code in the game SuperTuxKart. Introduction The purpose of this report is to demonstrate the construction of the concrete architecture of the game, SuperTuxKart, in addition to the finalization of the conceptual architecture. With the use of a program called Understand, the game’s source code was mapped into source directories of the conceptual architecture. This process allowed the conceptual architecture to be refined and finalized. In describing the derivation towards the concrete architecture of the system, the report will describe the functionality of the system and the interactions between the subsystems. The discrepancies between the conceptual and concrete architecture will be discussed, particularly the additional dependencies which exist in the concrete architecture. Further analysis of the source code allowed us to describe the interdependencies of the subsystems, notably the unexpected dependencies which were revealed. Updated sequence diagrams are used to describe two of the use cases in detail for a better understanding of how the system and the updated architecture works. Architecture Derivation Process The following diagram is our revised Conceptual Architecture. Through the derivation process of separating entities to make our Concrete Architecture, we found that many of our subsystems were not necessary. This allowed us to refine our initial conceptual architecture and simplify it. By combining some subsystems together (like taking characters and simplifying it to become a “karts” component in the Game Settings subsystem), it actually made it easier for us to map the entities from the SuperTuxKart source code, into our concrete architecture. We decided to stay with a layered style of Conceptual Architecture, because it suited our components well and allowed for a concrete mapping that made the most sense. As seen in the next figure, our Concrete Architecture adopted more of a loose-layered style, but we still think that layered is a good idea because most of the function calls are

3 in-line with the layered style and only a few calls are skipping subsystems, or connecting back up the architecture.

4

Figure 1. Conceptual Architecture Figure 2. Concrete Architecture Concrete Architecture As seen in Figures 1 and 2, the Concrete Architecture is able to be adapted to fit in with our Conceptual Architecture very nicely and allows the mappings of entities into our Concrete Architecture to make a lot more sense. Below, in Figure 3, is the Concrete Architecture mapping given by Understand. This is the diagram at the highest level and following Figure 3 and 4, there is an explanation of each subsystem, and its interactions, in more detail. In Figure 4 we have included the mappings of each entity into the subsystems of our Conceptual Architecture. In addition to the entities seen in Figure 4, there are also some entities that have been put within entities to enforce greater interaction. These entities are listed below.

• Enet and Online: Both under the entity of Network within Memory Allocation subsystem • Irrlicht: Under the entity of Graphics within Game Resources subsystem • Bullet: Under the entity of Physics within Game Resources subsystem

Figure 3. Concrete Architecture as given by Understand

Figure 4. Entity Mappings in Understand Subsystems User Interface The User Interface subsystem controls everything to do with what the user sees, how it’s displayed, the design of all of the menus and screens, and how the user actually interacts with the game. In the conceptual model, User Interface is only dependent on Game Settings because Game Settings is dependent on the beginning of the architecture hierarchy to keep moving down. In constructing the concrete architecture, it was revealed that there were additional dependencies, including bidirectional dependencies between User Interface and most of the other subsystems. Despite not existing in the conceptual model, the bidirectional dependencies were expected and logically made sense.

7 User Interface works with most of the components within Game Settings so that it knows the options to display in terms of the game and race settings. For example, User Interface works with Race Manager within Race for its getNumberofKarts and getNumLocalPlayers functions to determine the number of karts and players under the current game settings. User Interface also works with Memory Allocation mostly for any required user configuration information or online multiplayer settings. It largely interacts with User Config within Config to determine any configuration required for the displayed information. It also works with Network to access any displays regarding the online multiplayer mode of the game. User Interface calls on Game Resources the most. From looking at the source code, it clearly depends on Game Resources for many of its utilities. One of which for example, is the insertValues function so that it can build lists for functions such as buildTrackList. User Interface also works with components such as Graphics within Game Resources for any required visual rendering.

The one dependency of User Interface which came as a surprise was the dependency on the Platform Independence Layer. Although it was evident that this dependency is not significant as there were only 60 calls to this subsystem, it was still unexpected and further analysis was required to figure out the reason for its existence. From looking at the source code, it was revealed that User Interface would only call on the WiiUse class, for support of the Nintendo Wii controllers, a feature we did not realize SuperTuxKart carried.

Game Settings The Game Settings subsystem controls all of the different choices that the user has when playing the game and setting up races. Similar to User Interface, the conceptual model only illustrates a dependency on Memory Allocation for Game Settings. The concrete architecture demonstrates interdependencies between Game Settings and all of the other subsystems, including bidirectional dependencies between most.

Game Settings calls on User Interface for any IO prompts related to selecting game settings. It also depends on Memory Allocation for any user management or saved information regarding game or race settings. It works with User Config and STK Config the most within Config, and also Online within Network to get online and access the online game settings. Game Settings calls on Game Resources the most. This behaviour is similar to User Interface, in that many of the calls are to Utilities for classes such as vector or class log so that it can call a function error.

The one unexpected dependency of Game settings was its dependency on the Platform Independence Layer. This dependency was even less significant as there were only three calls made to this subsystem. Once again, the source code was required to be analyzed in order to evaluate the few instances in which it would be called. This dependency only exists to handle Angelscript for its trackObject function.

Memory Allocation The Memory Allocation subsystem controls the user management and all of the local and online saved data. It also keeps track of the user’s progression and allows for the unlock of progression-based locked options. Memory Allocation only depended on Game Resources within our conceptual architecture as it would need the rendering, audio, physics, and animations components for anything that is loaded from memory management. Our concrete architecture shows that Memory Allocation depends on Game Resources, Game Settings, and User Interface. As anticipated, Memory Allocation depended on game resources with 1545 calls. Surprisingly, about 1200 calls were made to the utilities entity and about 300 were made to the graphics entity. After looking in the source code within utilities, Memory Allocation

8 required many debugging, random generation, and translation tools. The other expected dependency was towards the Game Settings subsystem. The rationale behind this was memory allocation would need to know every aspect of the game state to save it. These included specifications of the track, game mode, karts, and logistics. Evidently, 400 calls were made to the karts, race, and game mode entities. The unexpected dependency was towards the UI subsystem. Observing which calls were made to certain entities explained this dependency. Memory allocation made 625 calls to the UI subsystem, where 74 calls were made to ingame-UI to acquire fonts and GUI data and 551 were made to I/O. After viewing where the calls were made in I/O, it was shown that memory allocation needed a utf_writer file to store strings appropriately and a xml_node file. After discovering that the xml_node file was called the most, its purpose was to create containers which would store text, elements, attributes, and media objects. This made logical sense as memory allocation would use these containers to store any data it needed within memory.

Game Resources The Game Resources subsystem controlled all of the resources of the game including audio, physics controlling the gameplay rules, animation, and graphics and rendering, controlling all of the drawing to the screen that the user sees. In the conceptual architecture, Game Resources only depended on the Platform Independence Layer (PIL) because depending on the platform that was being used, the rendering and physics procedures would vary. Our concrete architecture differs as it shows game resources depending on the PIL, Game Settings, User Interface (UI), and Memory Allocation subsystems. Game resources made a total of 5697 calls to the PIL subsystem. As predicted, most of these calls (approximately 4800) were for rendering the graphics of the game which was handled within the “glew” entity. The rest of the calls (1000) were made to the Angelscript entity for compiling many of the function calls. It was expected that Game Resources would depend on Game Settings as it would need to know the specific karts, tracks, modes, etc. to set up the race as specified. This was confirmed was 959 calls were made to the tracks, karts, modes, and race entities. The last expected dependency was towards the UI subsystem. It was anticipated that Game Resources would need the input from the user to perform animations and rendering accordingly. As expected, approximately 450 calls were made to the I/O entity which would calculate appropriate output based on the input given. The rest of the calls were made to states_screens, guiengine, and font entities which would also be handled and displayed by the Game Resources subsystem. The only unexpected dependency was towards the Memory Allocation subsystem. It was questionable at first as to why Game Resources would depend on Memory Allocation for anything. After reviewing the calls and source code made to Memory Allocation, the dependency was understandable. About all of the calls (246) were made to the config entity. After reviewing the code within config, game resources required information on the player profile, such as saved content, player icon, and achievements.

Platform Independence Layer The Platform Independence Layer facilitates interoperability/Cross-platform compatibility. In our conceptual architecture the Platform Independence layer is at the bottom of the hierarchy, it depends on nothing. In the concrete architecture there is a bidirectional dependency between Game Resources and the Platform Independence Layer and User Interface also Depended on the Platform Independence Layer. These changes make sense because the Platform Independence Layer would process Input (User Interface) differently depending on the platform.

As we saw in our architecture, Game Resources was dependent on the Platform Independence Layer, this is because elements from game resources require communication with the cross-platform elements

9 of the Platform Independence Layer to process properly depending on the platform that they are being processed on. The “wiiuse” element of the Platform Independence Layer is the only element that interacts with the Input element of the User Interface subsystem. It was unexpected that the Game Settings subsystem depended on the Platform Independence Layer, however there were only three method calls to the Platform Independence Layer, this means that it can pretty much be disregarded as there are so little method calls. The reasoning for this was probably because of a quick hotfix that the amateur developer team may have deployed (Summer of Code students or open-source contributors).

10 Use Cases New Game

Figure 5. Sequence Diagram demonstrating the New Game use case

Starting Conditions: User has opened the game to the main menu screen.

The sequence diagram describes the interaction between the game subsystems to successfully load a new game. First, the user clicks Singleplayer which is processed by the Platform Independence Layer (PIL). The PIL contains the functionality to translate inputs and outputs to various operating systems, therefore, it is the starting point for all user inputs to the system. Sys_getEvent() translates the user’s input to instruction for the other subsystems. Sys_getConsoleKey() tracks either the click of a mouse or the press of a button, which is used to identify which starting conditions the user is choosing. This process is repeated again as the user selects a kart, difficulty, game mode, track, the number of laps, and the number of AI karts. The information is processed to Game Settings with processEvent() which creates a new world.

The render system is then activated and begins loading the level. At the same time as the system render, the sound system begins loading the appropriate audio for the world. Once both the rendered and sound subsystem are loaded, the data is processed by the Platform Independence Layer and the scene is displayed on the user’s interface.

Drive

Figure 6. Sequence diagram demonstrating the Drive use case

Starting Conditions: User has started a new game.

The sequence diagram describes the interaction between the game subsystems to successfully drive their kart. First the user presses a console button, which is received by Sys_getEvent() and then processed by the Game Settings subsystem via the Platform Independence Layer. Once the system is aware that the player would like to drive forward, the system begins to check if there are any objects blocking the player’s path include other karts, game items, and static bodies such as walls. Additionally, activateContactEntities() is called from the Physics component. This turns on the collisions between AI karts and other users with the player.

12 Once the user’s path is calculated and returned to the Game Settings subsystem, the information is passed to the Animation component to ensure that the displayed character’s animation is synchronized with the speed and friction calculated within the Physics component. The Animation component also gets the kart models from Game Settings which contains the kart scripts. An animation is returned and it is rendered to the screen with the updated view of the game world. Difficulties Encountered 1. Learned a lot about how to use Understand and, once the initial learning curve is achieved, found that it was an incredibly useful tool to figure out how each of the games’ subsystems actually interact and are related. Understand was very useful when designing our concrete architecture.

2. We found that we were able to further simplify our conceptual architecture by combining and relocating some subsystems. For example, we took Characters, Items, and Karts and moved them all into Game Settings. We also relocated animation to the Game Resources subsystem.

3. The source code contains a lot more dependencies than we initially thought, as well as some that we did not expect to see. For example, functions from Game Resources were called twice from the Platform Independence Layer, which we did not think of when deriving our conceptual architecture. Lessons Learned 1. We learned a lot about how to use Understand and once the initial learning curve is achieved, found that it was an incredibly useful tool to figure out how each of the games subsystems actually interact and are related. Understand was very useful when designing our concrete architecture.

2. We found that we were able to further simplify our conceptual architecture by combining and relocating some subsystems. For example, we took Characters, Items, and Karts and moved them all into Game Settings. We also relocated animation to the Game Resources subsystem.

3. The source code contains a lot more dependencies than we initially thought, as well as some that we did not expect to see. For example, functions from Game Resources were called twice from the Platform Independence Layer, which we did not think of when deriving our conceptual architecture. Conclusions Our concrete architecture was evidently different than our conceptual architecture as there were more dependencies between the subsystems than expected. We initially chose a layered/object-oriented architecture style and then switched to a completely layered architecture. The explanation for this was because there were outlying components such as animations and items that fit better in other subsystems. Additionally, moving the entire Characters subsystem into Game Settings was an improvement to creating a completely layered architecture. Of course, there were bidirectional dependencies within our concrete architecture from one subsystem to many, but this was expected as the concrete architecture would create a dependency if one call was made from one subsystem to another. This did not alter the choice of switching to a completely layered architecture as the number of calls moving down the architecture to an adjacent subsystem was significantly more than going up the architecture or skipping adjacent layers which establishes the layered architecture. Lastly, using Understand was difficult at first, but once understood it was a very useful tool along with the source code for explaining expected/unexpected dependencies between subsystems. These methods aided in deciding which entities fit best in our subsystems and our understanding of why each of our subsystems interact with each other. Glossary Platform Independence Layer: Facilitates interoperability/Cross-platform compatibility by hiding implementation details.

“Understand”: Software that assists with understanding the architecture of source code by creating a graph representation of dependencies based on method calls.

User Interface (UI): A visual communication system between the user and the game. References o http://supertuxkart.sourceforge.net/doxygen/?title=doxygen

o http://scitools.com/documents/manuals/pdf/understand.pdf

o https://en.wikipedia.org/wiki/Understand_(software)

14