In this article, I would like to share the development experience of my latest project, Mafia: The Game.
Mafia is a social mystery party game played by a group of people. It's also known as Werewolf, but if you are not familiar with it, check out this Wikipedia page.
Most of my experience in software engineering before this point had been in iOS app development. For this reason, I started this project with an iOS app built with Swift and SwiftUI. Naively, I believed just a CloudKit database would be enough to power the multiplayer capabilities of the game.
After many hours programming, I eventually did get the app working with only a database but the results were mixed:
- No need to learn server-side development
- All the code is client-side
- Push notifications are managed by the CloudKit server
- One device needs to be dedicated as the host (basically the server)
- No game files were used, only string messages to update state. This meant if a device missed a push notification (as is often the case), their game state would be completely wrong
Although I was proud of my work so far, I decided that it would be worthwhile to learn server-side as well.
Before this, I had never developed a REST API so I really didn't have a clue what languages or technologies I should be using. I began with a google search ("How to make a REST API") which led me to a tutorial for using Express.js.
I had used JS when building simple HTML-CSS-JS websites years ago so I was quite drawn to working with it. Perhaps the biggest pull to Express, however, was the fact I got up a simple API up and running within 20 minutes.
Excited by my new-found ability to make REST APIs, I rushed to develop the full feature set for making games, joining games and actually playing them. I thoroughly enjoyed this change of scene from iOS development but I do have several comments:
- Moving away from a strongly typed language such as Swift is hard. I was not prepared for the number of bugs and errors I would encounter because there was no compiler to pick up the errors at compile time. In hindsight, I should have invested more time to learn TypeScript and used that instead.
- I used simple file reading and writing to store the game files. Although this is still the current solution on my server, it is not great and I would recommend others take the time to use a proper database provider instead.
After I had the server developed, I was quite intent on using an AWS EC2 instance to deploy it because I had read about AWS in the past. However, I stumbled across Heroku in my research, and decided to use that instead. This was for three main reasons:
- A generous free plan. Yes, the server "goes to sleep" after 30 mins of inactivity, but I just added helpful error messages to my app explaining the 20 second wait for the server to start up again.
- Super simple setup. I have always dreaded actually setting up a server with only command line and no GUI to fall back on. With Heroku, this wasn't the case: I simply selected my repository and they managed the setup for me!
- GitHub repo integration. It has been amazing to have my server deployed almost instantly after every push to the production branch. (Perhaps this only seems so amazing to me because of my experience as a mobile dev. I've become accustomed to the long time it takes to pass app review, make screenshots, etc for each update.)
With my server up and running, it was time to go ahead and use it in the app.
Now the REST API was working, I decided to implement the client-side networking layer as a Swift Package to properly modularise my code. Although I was hesitant about using this within an Xcode project, to my surprise it went really well. I even used a hierarchy of Swift Packages to manage all the way from the API to the model to the UI. Key takeaway: Swift Package manager is awesome! 🎉
Other improvements I made were widgets to view stats from the home screen. Although this was only a short exercise, it was highly enjoyable to explore the new WidgetKit API.
I realised that to properly make this multiplayer game, I needed a way that everyone (whether they have an iPhone or not) would be able to play it. I briefly considered learning more about Kotlin and Android development but that didn't solve the problem of access from desktop computers.
In the end, I decided to give front-end development a try using React. To do this, I first used the Learn React course on Codecademy to get to grips with the basics.
I decided to use Chakra UI for styling. I really loved the experience of working with it as it avoided CSS files. I am not a designer but the website I produced was at least acceptable!
Another technology I used, was this counting API. It provided an easy way to keep track of page views without relying too heavily on third-parties such as Google and Facebook. I would recommend it to anyone as a simple way to achieve this.
I was surprised at how quickly I made the entire website, especially given that this was my first project using React. In the end I think it was down to great data-flow between components. I tried as much as possible to keep this uni-directional and it certainly paid off. The single source of truth is the game file which is provided to all the child components in their
After I had produced all the pages, I started to look at deployment methods. My first thought was GitHub Pages. However, the requirement to use a
HashRouter rather than a
BrowserRouter for navigation put me off. Eventually, I settled on trying out Netlify. This was great because they ran the correct commands to generate the build directory for me, so I just had to focus on pushing the code to the production branch. Like Heroku, this was an extremely easy experience.
Now the website was done, I returned to my Xcode project and decided to use my current codebase to add more Apple platforms to the game.
Firstly, I enabled Mac Catalyst. This allowed me to quickly make a Mac app without adding any extra code. One issue I did encounter, however, was to do with resizable windows; it resulted in a buggy UI that looked weird at extreme aspect ratios. To fix this issue, I decided to set a fixed window size.
I also built a simple tvOS version of the app. This allowed players to host games from their living room so everyone can see who's dead/alive and keep up to date on the latest in-game alerts. Using SwiftUI and Swift Packages, this required minimal code as well.
With that, my site was on the internet and my suite of apps were ready for the App Store!
There are so many gameplay features I would love to implement such as new player roles and a more interactive UI. Moving to a persistent database rather than the local filesystem on the Heroku server is another challenge that I am looking at undertaking.
My key findings:
- Don't be scared of server-side and web development. It's fun really.
- React and Chakra UI are AMAZING!
- Modularise code into packages from the start.
- Make a Mac Catalyst app for every iPad app - it takes so little time.
- Deployment via git for Netlify and Heroku is awesome.
I absolutely loved working on this project and I have learnt so much - Node.js, Express and React. If you have time, I would love it if you could check out my website or iOS app - it's free! I'd also really appreciate any feedback on ProductHunt.
Thank you and happy coding!
This article was originally published on my Hashnode blog.