Starting today, we’ll be keeping a public log of what’s happing on our newest project, a yet-unnamed 2D sandbox game (codenamed Project Forge) with elements taken from action RPGs and dungeon crawlers.
First, I’d like to warn you that this post is going to be fairly dry. We’re far too early in development to show any actual gameplay, so this will mostly be me talking about what we’re doing and our motivations for doing things the way we are. I’m hoping that future devlogs will have some tutorial-style articles for the more technically inclined as well as some peeks into the art/gameplay as the game begins to take shape. I don’t expect future updates to be as long as this one.
Didn’t you just post about another game you were working on?
Yes and no. We posted a quick video of a simple “roguelite” we were working on in Unreal Engine; it was to be a very cut down version of a game we’ve been wanting to make since the very beginning. Our ideal game is going to take a lot more time and money to realise, but in the end, we decided we really didn’t want to settle for a watered down version if we could help it. So here we are, after the first week (and a half) of development, showing what’s been done so far.
What is Project Forge then?
We’re making a 2D tile-based sandbox game from a side-on perspective. The game will be all about building, crafting and combat. The most obvious comparison is Terraria, although we’re hoping to have a more complex (and possibly class-based) combat system in addition to a strong world-building element in our game. We’re hoping to have a lot of unique spells & items to keep the combat side of the game interesting. We’re also aiming to incorporate randomly generated dungeons separate from the overworld that can be entered through a central hub in the world itself.
So, what are the challenges? How is a 2D game such a monumental task? Well, on top of the base game that I (very) briefly explained, we want to build a strong cooperative (and possibly competitive) multiplayer experience. The real complexity though, comes with the fact that we want to make the game as mod-friendly as possible. We’d like players to be able to make their own items & structures in the game world itself and share their creations with other players. Beyond that, we’d like more experienced modders to be able to pick up some simple, yet powerful modding tools, and adjust any part of the game; adding new classes, additional game modes, unique spell effects, you name it. We’d love to make a game that we can expand over time ourselves, but also one that grows organically with the community. For all this, we really need to write a custom engine from scratch.
Why a custom game engine?
With so many game engines available now, it rarely makes sense to write a game from scratch. But there are some situations in which rolling your own engine is the best/only choice, this is one such situation.
Flexibility & Optimization
Firstly, commercial game engines are made with flexibility in mind. They’re made to work reasonably well with a wide variety of games. Tile-based worlds with complete creation/destruction capabilities really don’t fit well with the more general algorithms used in these engines; there are many specific optimizations that need to be done that obviously don’t come as standard in most game engines. There is the option in some engines (such as Unreal) to modify the source code to get the desired effect, but I’d rather purpose-build an engine than try to hammer an existing one into shape. There’s also a lot of overhead for all of the functionality you don’t need.
The next big issue is with physics. Building a platformer on top of a physics engine is already a painful process, but with the introduction of tilemaps, things get even uglier. There are so many hacks that would be needed in order to make an engine’s physics work for our game that by the time we’re done, the physics engine wouldn’t even slightly resemble what it used to be. We’ve made our own “physics” engine which allows for efficient collision detection & response against tile maps, as well as different physical properties (friction, restitution, etc) on a tile-by-tile basis. We’ve also made it easy to hook into the physics engine itself to customize behaviour from the gameplay code. This allows us to have all of the non-physics interactions for the character (movement speed not being limited by ground friction, wall gripping, stepping up onto tiles, etc).
This is a big one. We want the game to be easily moddable, and so far we haven’t come across a suitable engine with proper support for the kinds of things we want to do in the game. With our own engine, we can support arbitrary loading/unloading of content packages, visual scripting, and the loading of code plugins. In addition to this, most engines with proper source code access are programmed in C++; while fast, C++ isn’t exactly a very productive way to work, and it certainly isn’t something I’d want to subject potential modders to. I chose to write the engine in C# as it’s still extremely fast, but is also very productive to work with and is well used thanks to things like XNA/MonoGame and Unity.
So, what have you got so far?
With all that said, what have we actually got to show for our first week of development? Mostly engine stuff so far. It’s just me working on it for now since there’s only programming work to be done for the moment.
- Basic engine subsystems (input, logging, core data types)
- Beginnings of game & world structure (classes for World, Actor, Component, Controller, etc)
- Tilemap class with a wide array of manipulation methods (set/get, flip, extract, blit, rotate, resize, and flood-fill)
- Custom physics engine with support for efficient tilemap collisions and per-tile physical properties
- Optional callback & “hook” functions into the physics engine
- Override friction calculations (used to prevent characters sticking to walls)
- Optionally reject new contacts before resolving collisions (used to allow characters to “step up” onto one-tile-high areas, rather than getting stuck)
- Optional callback & “hook” functions into the physics engine
- Beginnings of world generation. Noise-based an multi-threaded (about 40 seconds to generate a large world: 4km x 1km [8000×2000 tiles])
- Some tile rendering optimizations (culling, chunk batching)
- Beginnings of CharacterMovement component. Handles platformer controls (reactive direction changing, air control, multi-jump, variable jump height, late/early jump tolerance)
- Profiler that calculates framerate and allows for tracking of time spent in arbitrary blocks of code
Hours of Work: 75.5
Lines of Code: 3,125