I've always loved playing games but I've never really understood how they were made at a code level. I've decided I want to learn from the ground up and decided to write a blog about my journey. Why not use Unity3D you say? Well I took a stab at it and decided to pump the brakes on that to understand the core essence of games first. I will definitely give Unity another try at some point in the future. This is part one of a series of blogs on my learning process on building an entire game with it's own engine.
When taking on 'building a game engine', you either have to be crazy or super curious. I'm probably both. It also requires a ton of ambition. How dare I decide to write a game engine when I have no idea how to do so? Since there's not really much in terms of resources online to build your own engine, I decided to try on my own based on my own set of skills. So I took stock of what I'm pretty good at:
- Software patterns
- Network interaction
- C# backend
- Windows Services
- Web frontend
- Cloud services
Based on that list, you'd think I'd naturally building a browser based game based on a web stack. And it does look attractive to do so, however I really like C# -- a lot. Therefore I wanted to see what I could outside of the traditional web stack. Another reason for shunning the web stack is that I've tried that before and crashed and burned.
I'm also good at Photoshop, but then I thought about the amount of time it takes to make a simple sprite animation; I began to think that perhaps I'll leave the game building to a large shop complete with artists.
I asked myself, "what if I wasn't too worried about flashy graphics?". That will free me from having to spend a ton of time on artwork just to get my engine running.
Also, "what if I had a dedicated client instead of assuming I had to use a web browser?".
I was starting to imagine a simple console application that displayed retro-like text in the form of the MUD games I used to play in the late 80's.
At this point I had no idea how to interact with a user. Perhaps a command line that took in commands?
One thing that bothered me was I didn't like the idea of an constantly vertically scrolling block of text.
Then I asked myself, "what if my client acted like a TV screen where it redrew each line over the top of the old lines?".
Can a console app on windows even do that??
So for my game, I'm simply going to try to create a game inside of a console application.
Structures and concepts
Once I got the idea that I can just redraw lines of text over old ones in a controlled manner, I figured I now unlocked the secret to making my game engine. For my first proof of concept I decided that a 'map' could simply be a two dimensional text file with rows and columns.
However I didn't want maps that could only fit on my console screen which is limited to font size and monitor size.
To facilitate large maps, I devised a way to load the 2D maps into a buffer and only display a small portion that I call the window (viewport).
Then I was faced with the issue of having a single 'view' for my game but I knew full well that I needed to do other things like show an options screen, a splash screen and perhaps an inventory screen.
The next structure for me to create was a scene. A scene is essentially just like a 'view' in the web world but without templating.
So if you think of a game as simply a series of scenes (start screen, explore a map screen, inventory screen), I just needed to switch between the scenes. Therefore I have a scene manager. It simply decides how to load a different scene.
One of my essential scenes it the ExploreMapScene. This handles many things inside:
- Rendering a map in a window
- Moving the player and handle any other valid input
- Detecting collision
The good news is that detecting collisions in a 2D world is pretty simple. The real design decision I had to make is what to do when I detected a collision. I started out with a simple if\then statement but that quickly becomes spaghetti code. Therefore I decided that I'd dynamically instantiate a handler class. Essentially, when you collide with a certain character; create and invoke a handler.
The other big issue I had was accepting input without blocking execution. That is actually easily done with code like the following: