Murder Mansion is a 2D multiplayer role playing game that can host between 2 to 6 players. The game revolves around 2 roles: the Civilian and the Murderer, each having unique abilities, items, and weapons. Your objective is to try to survive the perils of the mansion as a civilian, or execute your scheme to put the F in Fear as the murderer.
This multiplayer role playing game involves cooperation between the civilians to survive the night, and strategical movements by the murderer to keep the civilians trapped in forever. Every match will be a different experience for the player. Experience the thrills of playing for either faction, riddled with surprise and suspense at every corner. The game provides a fully immersive experience, and it is highly recommended to play this game with earphones on in a dark room.
Can’t wait to uncover its mysteries? Download it here on Android! (bring along a couple of friends too, since it’s a multiplayer game!)
Murder mansion was a product of a module I took in SUTD, on the Elements of Software Construction. The course’s objective was to understand concurrency in Java, and how it is like to work in a software development team. We formed into groups of 4, and were tasked to create a multiplayer Android-based game.
In this article, I will be discussing the game design, software architecture, and the lessons learnt from this endeavour.
Murder Mansion was inspired by a map I used to play in Warcraft 3 custom maps. I can no longer find the title of that game, nor a copy, but it essentially was similar to a game of werewolf played out in Warcraft 3’s game engine. Hence, Murder Mansion was designed as a multiplayer RPG strategy game.
The game’s objective is for either the civilians to escape the mansion after an allotted time or kill the murderer, or for the murderer to kill all other civilians. We bring in an element of deceit and surprise by masking the identity of the murderer until he decides to reveal himself. In addition, each player is given an illuminated space around them where items and characters can only be revealed in. Along with the selection of ingame music and art style, we brought in an element of horror, suspense, and mystery, a genre I believe is lacking in mobile gaming.
Movement controls utilise a virtual joystick and 3 action slots are provided: ability, item, and weapon. We balanced the number of action slots to prevent over-complicating a mobile game but ensure varied play styles. The ability slot allowed the murderer to mask himself from the civilians while giving civilians the ability to sprint away from the murderer. The murderer needed a knife to assassinate his targets as well, while giving the civilians a bat that can stun its target for survivability. Since the map was fairly large, we gave the murderer a passive way to kill the civilians too, but being able to pick up and place traps. Conversely, the civilians can dismantle those traps with a dismantling kit.
Varying Play Styles
To ensure that the civilians are motivated to explore the map instead of hiding in a corner, we included the ability for the civilians to assemble a shotgun from shotgun parts – scaled by the number of players in the game. These shotgun parts also increased variability in play styles, as we placed them in risky, hard to reach places. During play testings, we found this element to be extremely important. Otherwise, the civilians will simply hide in various corners around the mansion and not feel the fear of being hunted.
On top of that, we wanted to make sure that every play through was different. We did so by randomly choosing spawn locations for the players, weapons, and items, and adding barriers in parts of the map that will disappear at different time intervals. The barriers served to expand the map as time went on, forcing players to go deeper into the mansion in search for greater prizes.
Software Development Model
We used a combination of waterfall and agile model here, since the main focus for this project was in development. We first scoped the project and analysed the types of gameplay and software architecture to implement, then proceeded with the coding. The project concluded with the roll out of the game itself. Should this have gone longer, it would have been a fully fledged agile model where we re-analyse the requirements of the game, and the gaming industry in general, and proceeded with updating Murder Mansion further.
What was important in this lesson, though, was the need to constantly test our assumptions and development. Will people have fun playing a horror game on their mobile? Are the controls and UI intuitive? Are the actions engaging and do they meet our objectives?
During the iterative process, we tested gameplay, assets, and interactions. Each item had multiple designs and were tested independently, with the chosen design used to merge with the winning designs of other items.
Our first iteration barely resembled the final product you see today. It was simply a triangle, a bunch of squares, and an unassuming virtual joystick in the corner. Through our play testing, we found that users were familiar and comfortable with the virtual joystick, and could easily interpret the movement of the triangle around the obstacles. Of course, this is a grossly simplified example of one of our iteration, and we had to progressively build up from there.
Testing game assets such as graphic style and music style was also important. A perfectly running code would be nothing without the right ambiance to enthrall the player. We ran through different designs, and finally landed with a graphics and music style which fit the theme.
We used LibGDX for the game engine as it was Java based (our main programming language) and was well supported. We used Zombie Bird, by kilobolt, as a tutorial to the LibGDX framework. It was also a great help in understand structured programming languages, or programming in generally.
Box2D and Tiled Maps was built on top of the LibGDX framework for creating the map and adding collision physics to it. Block Bunny, by ForeignGuyMike, was another useful tutorial for us.
One major element in our game was the visible radius around the characters, illuminated using Box2D Lights. Performance was good, but do note that there was no 3D support (duh). Box2D Map Object Parser by dermetfan gave us an easy way to trace the walls in our assets, and hit boxes as well, rather than coding out the polygons.
Here, we have a simplified structure of our class tree. We basically divided the code into 2 segments: the core classes where all the processing, rendering, and networking is done, and the gameplay classes where all the logic of the gameplay elements are stored. We decided to adopt a client-server model as well, where 1 player will be chosen to host the server, and everyone will connect to it via the client (including the host!). Processing is then done in the GameWorld, which doubles down as a standalone for single player as well. The renderer classes then renders the outputs of the GameWorld.
The client-server model was adopted as we wanted to prevent concurrency issues from happening. Concurrency issues happen when variables are written and read at the same time. Simply, imagine if you had a coworker editing the same word document as you. Your coworker may add to a passage, while you may delete the passage itself. In this case, which action do we decide to be final? As such, we needed to be sure that the risk of these issues were lessen, and a client-server model allowed us to control the flow of information more strictly than say, a peer to peer model.
Essentially, each player ran a single Game World logic unit, which sends and receive information from a messenger (Client). All these messages, movement, knife stabs, activating sprints, are sent and processed at the server, which is hosted by one of the players. The message is then passed back to all the clients, and processed again by the Game World.
This brings me to the point of separation of concern. It was important not only on a network architecture level that separation of concern was present, but also within your code and your team structure. By expressing the client’s actions on the server, we can ensure that all clients receive the same impact at the same time.
Similarly, in our code, each class is coded to do 1 function only. The Client was the player’s networking messenger, the GameWorld the logic unit, the renderer to render the assets, and the objects to provide the logic. If we had mixed the message passing unit with the GameWorld unit, it would have been difficult for multiple parties to be troubleshooting, should any errors arise, or code these units independently.
Our team was also divided to tackle parts of the game which can be developed independently from each other. While everyone else in the team can contribute ideas to a particular segment, only the person in charge of the individual component could make the final decision in implementation. This ensured that there was no conflict between what was said, and what was done, which smoothed out our development process.
Alas, we still ran into concurrency problems. When we were play testing, we found that as the game went on, the game became more lag and actions were not executed equally across all devices. We were perplexed as to why this was happening, but we later found out that it was because we were changing the parameters of the game (character position, etc.) when the Game World step was running.
Therefore, we used a Queue to funnel all messages coming in from the messenger unit to be processed in the main line of progression only after the World step was complete. Having done this, the game began to run perfectly.
If I Were To Do It Again…
…I would redesign the software architecture by creating a server side Box2D World. Our current model burdens all the clients by running and individual Box2D World on each device. One device is further burdened by running the server. Instead, we could have implemented a server side Box2D world instead, while the clients only output their controls and input the changes to the world. This could make synchronizing our data simpler, as only a single world will be reflected on all devices, rather than run the risk of having different world views on each client due to potential concurrency or latency issues.
…I would redesign how the player interacts with the game, perhaps with more intuitive touch controls. The use of the joystick and ability buttons are reminiscent of the Street Fighter arcade days, controls which are not native to the mobile screen. These interfaces only consume real estate space in an already limited mobile screen size. Instead, using the gyroscope or multi touch gestures could be explored to free up real estate space and stand out in the already crowded mobile gaming space.