Developer Blog: Open Source Movement

Posted on

We are pleased to announce that Project Borealis’ C++ movement code is now freely available under an open source MIT license! This is the first time we’ve published any part of our game’s code publicly, and we are super excited about it. We’re always looking for new ways to share our work and be an active part of the community, and plan to post more development blogs here about the technologies that power our game!

Right now, in our GitHub repo, you’ll find a robust Unreal Engine implementation of classic FPS movement mechanics from the Source Engine and Half-Life 2: Episode 2, along with a few improvements and bug fixes. We’re confident the game’s movement now feels just like Half-Life 2, quirks and all. This is just the code that defines the player’s movement in the game, and not other elements such as combat or the UI.

bunnyhopping

Getting the code to where it is today wasn’t a completely straightforward process, but we think it was well worth it. We hope documenting this will be useful to the community, so you can get an understanding of what went into writing this code – an effort largely undertaken by one person (@mastercoms) alongside the rest of the game’s development. Our journey began in late August and September 2017, when we first created the game repository. The base movement code, defining what the majority of players would notice, was implemented very quickly, with air strafing and Source-style input acceleration in the first few days. This was enough for most gameplay testing and standard development at the time, so focus was driven elsewhere – on building the game’s core features, with just occasional work relating to movement. In October 2017, we implemented accelerated backhopping, and added smooth crouching transitions and footstep sounds in November. This was all we needed for a long time, so besides some minor bug fixes here and there from internal playtesting feedback, movement development was largely paused for around a year.

In October 2018, we began playtesting with community members from Sourceruns, famous for their amazing speedruns of Source games like Half-Life 2 Done Quicker. They know Source movement inside out so we got great feedback from them, allowing us to iron out some of the final bugs with accelerated backhopping, and iterate on the movement code more generally. Some of the results of these playtests were accelerated backhopping not disallowing strafe bunnyhopping, better Half-Life 2-style damage boosting (rocket jumping), wall strafing, ramp sliding and surfing, over the course of a few months, totalling a few days worth of development time plus the playtesting screenshare sessions with speedrunners. At the end of our last group of playtesting sessions, we got some really positive feedback from our playtesters, including DeSinc, spikehunter, Centaurium, BobWombat, and waezone, saying that we were surprisingly accurate in recreating Source, and in some ways our movement built upon Source by removing annoyances and frustrating bugs.

accelerated back hopping

Let’s also go through the code so you can hit the ground running if you plan to use it, or just want a deeper understanding of how it works. The core of what makes classic FPS movement is in the UPBPlayerMovement::CalcVelocity() function. Before we explain the math in this function, we should introduce you to how we use Unreal Engine variables like their Quake/Source counterparts. The Source input system does a boolean check for +forward, +back, +moveleft and +moveright, and adds these values together according to their axis. So, +forward adds a scaled value to the forwardmove axis, and +back adds a scaled value to that same axis, for example. This scaled value is scaled by cl_forwardspeed for +forward, cl_backspeed for +back, and cl_sidespeed for +moveleft and +moveright. These are all set to 450 Hammer units in Half-Life 2. So, we decided to use the input vector as a consolidated way to store this data in Unreal Engine. The input vector is a unit vector in the direction of your summed key presses, so it stores the same data as Source usercmds for forward and side moves. Then, this input vector is passed into Acceleration as input vector * MaxAcceleration. In this case, we can set MaxAcceleration to 450 Hammer units (857.25 Unreal units, multiplying by 1.905). This process is done later in Source’s code, for each movement mode, where forward and side move values are translated to vector form, and then split up into the unit vector and magnitude, for wishdir and wishspeed. With our approach in Unreal Engine, we have all this information in a single vector variable.

Now, with that understanding, we can move into how we use Acceleration in CalcVelocity(). In our standard movement modes (not ladder or noclipping), we first clamp our Acceleration to the max speed limit, just like in Source, so that we limit how much we can contribute directly further to our velocity, instead of directly limiting velocity. Then, we find the projection of our Velocity onto our Acceleration direction (called Veer). Then, our Acceleration magnitude is reduced by the magnitude of Veer, to prevent changing velocity by too much (this was presumably the reason it was implemented like this in Quake) and this is called AddSpeed. Acceleration is also limited further by an AirSpeedCap of 30 Hammer units if you are in the air before this reduction (note: you are also considered to be in the air for a single frame on the ground, with bBrakingFrameTolerated). Then, we multiply Acceleration by our acceleration multiplier (sv_airaccelerate or sv_accelerate in Source), by the SurfaceFriction and DeltaTime so we only apply the necessary acceleration for this frame. Finally, we clamp this value by our AddSpeed. Now, we have our Acceleration, and we add it to our Velocity, in order to do our core movement functionality! Explaining all of the movement code would make this post far too long, but get in touch with us and we would be happy to help with understanding any other part of it!

surfing

So there you have it, we are now releasing this robust, battle-tested C++ movement code for Unreal Engine that implements classic FPS movement from Half-Life 2, for all to view and re-use under the MIT license. We really hope that this is useful, and we will be closely monitoring your feedback to guide our future plans!

If you use this code in your own games, or have any questions — please let us know! You can email us at [email protected], or chat with us on Discord. You can also go to our GitHub issues, create a new issue and label it as a question.

Please feel free to file Pull Requests and Issues to the repository, and if you’re an Unreal Engine programmer interested in getting more involved, consider applying to join the programming team at Project Borealis!

You can find a number of other Project Borealis code repositories, including our fork of Unreal Engine, in our Github organization. Guidance on accessing the Unreal Engine fork can be found here.