We’re a diverse bunch here at OVO - we have musicians, triathletes, DJs, volleyball players… the list goes on. For tech this is really important, given our diverse and evolving tech stack.
This year, I set myself the challenge of making and releasing a video game. I achieved that on the 8th of December, and this blog will be about the process behind designing and making a video game, and how that can be applied to what we do at OVO. I’ll be writing it from a fairly high-level, but basic knowledge of how programming and programs work is still an assumption I’m making.
How Games Work
To understand how to make a game, you first need to know the domain you’re working in. The main constraint for a game is the hardware it’s running on, and most critically the CPU, GPU and RAM. This is why a PC from the 90s won’t run the latest FIFA - it’s just not powerful enough.
A game tends to work using an “update loop”. In pseudocode, it will look a little like this:
while (true) {
updateLogic();
render();
}
The first thing that happens are logic updates. This can be anything from moving an object in game, to polling a networked player for any actions they want to perform. With so much going on in games these days (animations, physics calculations, complex AI, water simulation…), the updates have to happen in as optimal a way as possible, and be “stepped”, meaning if you want to move a character from point A to point B, one “update” may mean they only move 1% of the way to point B. I’ll explain why this happens a little more in a sec.
Once logic has been updated, the game is rendered to your screen. This involves a lot of complicated matrix maths to determine where everything is in “screen space”, what should and shouldn’t be rendered, and then on to what colours each pixel of the screen should be to give you the final picture. A common way to imagine this (though I’ve heard purists scoff at the term) would be a film camera following the player character. You can move the camera around, rotate and pan it, maybe even zoom, and so each time the camera moves, the things it’s looking at and the picture it takes changes too.
So how long does one update take? Typically, the target is 16ms or less. Why? It links back to the screen. The NTSC standard put the refresh rate (how often it takes for the screen to finish displaying the current “picture” from the GPU) at 60Hz, or 60 frames per second. 1/60 is 16.6666, and rather than round up and drop frames, it’s generally accepted that you have 16ms to update the game and push the latest “picture” to the GPU before the screen has finished rendering the current frame.
The whole topic of rendering goes way beyond the scope of this post, but it’s really fascinating how graphics programmers have solved problems over the years, innovating technology to the point we now have massive open-world games with near-realistic graphics.
In a nutshell then, that’s how a game works under the hood. I won’t go into the logic behind updating the game-state itself, but I will talk about what game engines do.
Unity - A Game Engine
If you ever want to make a game, there’s one very important piece of advice - don’t make a game engine! Games are very complicated pieces of software, involving plenty of matrix and vector math just to get something simple on screen. Beyond that, the disparity between hardware and the standards used by different manufacturers means that even if you want to show something on screen, you’ll have to implement at least two separate libraries to do so (DirectX on Windows, and OpenGL on Mac at the time of writing, though this is likely to change). Consoles may even have their own proprietary requirements for all of this.
Game engines provide a convenient way of wrapping most of the common functionality required in game development in a development environment. They make it much easier to get something running in a “higher level” way. Some don’t like this, as it abstract away so much of the pipework, giving you less control, but as with anything, having a higher-level view of things makes it so much quicker to just get things done.
Unity is a good middle-ground between this. The low-level stuff is done for you - things like worrying about how to grab a frame buffer to render to, or how to handle a PNG vs a JPEG. This allows you to focus on implementing the game’s logic, and makes it easy to get good looking and sounding content into the game. It recommends C# as its programming language of choice, a language that I was unfamiliar with, but with a Java background, picked up quickly.
Learning a game engine is one of the challenges of making games, so picking one and running with it is essential. Learn it inside out; know the best way to do things in it. These days, mastery of an IDE or framework is sometimes as important as knowing how to program.
If you’re keen on making games, I can recommend Unity. Though it has a nuanced approach to scripting, and has many features, the initially steep learning curve eventually flattens to a point that you could theoretically make almost any game in it. Even better, it’s completely free to make and ship games in Unity until you reach a certain revenue threshold, by which point you’ll have enough money to pay the license fee!
To play devil’s advocate: why wouldn’t you use a game engine? Some developers get the most joy out of learning how things work. Creating things at a low level does bring a certain amount of reward that sometimes just isn’t present when working with “mostly-there-already” solutions. The other major reason is performance. By abstracting away so much of the low-level stuff, game engines make a lot of assumptions about what a game developer wants to do, and by pleasing every platform (PS4, Xbox, PC, Mac, Android…), there is inevitably a performance loss somewhere. For something like an MMO or a game with thousands of enemies on screen at once, you may need something more performant, or just more bespoke for what you’re trying to do.
And for the sake of fairness, other game engines include: Unreal Engine, Cryengine, Cocos2D, Phaser, and Gamemaker.
Making Island Invasion
Island Invasion is the game I made - this isn’t the place to promote it so I’ll let you find it yourself - and I wanted to go over the steps that went into seeing it from concept to release.
Having made plenty of “prototypes” in the past, I knew that scoping was key. You may have a great idea in your head for a fully online real time strategy game based across an entire universe, but if it’s just you working on it, that’s never going to see the light of day. First thing for me then was “what can I make in a year that’s still fun and unique?” I settled on a tower defense game, as it’s fairly easy from a logic point of view, and, more importantly for me, the “models” are mechanical, and therefore simpler to create. By models, I mean the “entities” you see in game, like trees, characters, or weapons - these are 3D “models”. My skill in art is unfortunately still quite poor, but using a simple art style (low-poly in my case) you can achieve something quite appealing.
On art, I remember seeing a Twitter poll not long ago that asked people what they thought was most important in buying a game. Art/ looks came out at number one by quite a long way, followed by gameplay. Getting art right is difficult, so I went with a low-poly style. Polygons make up the 3D models on screen, so having a low-poly look just means using fewer polygons in those models. The models are easier to design this way, and the lack of detail, if done correctly, has a nice aesthetic. One game that I think does this particularly well is Kingdoms and Castles - it’s worth checking out!
Next I set up two things - version control and a Trello board. Version control is really useful for trying out features that you may later scrap, maintaining a reversible history of changes to your project, and at a really simple level, it’s a remote backup of your work. For games, the ability to try out features you may scrap is given to you by a version control system. I use Git out of familiarity, though you may want to consider Git LFS or Perforce given the types of assets you’ll be working with (large PNGs, 3D models and other raw data files). Trello (other project management software is available) is my management program of choice as it’s simple to use. The board for Island Invasion had the following columns:
- Ideas - things that popped up during development that might have been really cool, but would have taken ages to implement and may not have worked. This goes back to scope control - keep it tight, but have a place for all those cool ideas to live, just in case you’ve got some time to give them a go later.
- TODO - things I had to do to make a working game. This was done in a very waterfall manner, given that often one system had to exist before another (e.g. there’s no point having enemies if they don’t have a map to move around on).
- In Progress - big tasks went here so I didn’t have to context switch so much when coming back to the game the following weekend. I tended to work off the develop branch in Git, especially early on, so it was easier to track the bit of logic I was implementing on the “In Progress” column.
- Done - not essential, but I think it’s nice to see just how much has been done to date, particularly in a project as large as a game.
- Bugs - always track your bugs and tech debt!
From there it was a slog of coding my way to the finish line. I hired a few friends of mine to do the 2D art and sound, as I just don’t have the skill or time to create anything very good for that, and pretty much worked waterfall from the end of May to December the 10th, when the game was released. Promotion and working with Steam is out of the scope of this blog, but also took a considerable chunk of time, and for anyone doing this for a living is as big a piece of work as any amount of coding or asset design.
How this applies to OVO
I wanted to wrap this up by relating the game development process to what we do here at OVO. OVO Tech is made up of T-shaped people, and drawing inspiration and experience from what we do outside of work is, in my opinion, an essential part of that.
- An event-based architecture - we use Kafka at OVO to drive communication between our microsystems, and it’s a really powerful design that can be applied to games too. My event system is much simpler, using C# generics and event classes in place of schemas, but works in much the same way. This provides great flexibility, not just in terms of scalability, but also in terms of decoupling. For example, my GameOverEvent is consumed by the class that manages the enemies to stop them spawning, by the class that manages the music to play the “game over” track, and by the leaderboard manager to update the players score (and a few more classes but you get the idea). The class that detects that the player has run out of lives publishes the event to make those that care aware of that, but doesn’t know who, and that’s ideal. As an example in OVO’s world, the creation of a new customer is an important event, but the system that reports that shouldn’t also be responsible for setting up their direct debit, their comms and their contracts. Having this separation allows each team to focus on doing what they do best - improving, managing, and maintaining their own systems.
- Letting people do their job - one of the most attractive things about working at OVO is that you’re hired to do a job, and nobody’s going to tell you how to do it. Engineers are responsible for their own tech stacks, and while work pieces are prioritised by heads of department or business unit, how you solve the problem is up to you. When working with the artist and composer on Island Invasion, I told them what I wanted, and let them do their job. I gave them a general overview of what I wanted (and in fairness did tell the composer I wanted something “synthy”), but aside from that, let them get on with it. The results I got back made me smile every time, never what I expected but always what I wanted, and reinforces my belief that you should let people do what they’re good at.
- Effective planning - OVO Tech isn’t just made up of software engineers, but also SEMs, Agile coaches, and product owners. Tightening scope and planning the work ahead is essential to our success, just as much as it is in game development. With teams working on their own backlogs, it can be easy to lose focus of the bigger picture, which is why we use things like Tech Forums, Village Halls and Communities of Practice to keep everyone up to date. Being one person working on a game, a lot of this communication isn’t necessary, but it’s still important to keep track of where things are, what’s being worked on now, and what has been achieved.
- T-shaped people - I alluded to this earlier in the post, but in both OVO and game development, being “T-shaped” is a necessity. The range of tasks to perform means being just a C#/ Scala/ Salesforce developer isn’t enough. As a solo games developer, you are also responsible for creating 3D models, maintaining a Trello board, publicising, versioning, and so on. At OVO we create build pipelines, complex cloud-based ecosystems, and sometimes we even have to temporarily take on a completely unfamiliar role like product owner! Constant willingness to learn and adapt is key in both areas.
What next?
I’m hoping at this point you’re really keen to pump out a Tetris clone, or start on that 4X strategy game you’ve always dreamed of. I recommend starting with something small. Pick a game engine - Unity is a good all rounder, but there are plenty of others out there. Learn the engine, keep the scope in check, and you’ll have a game in no time!