The specialization course at The Game Assembly required us to plan out and work on a project to show off on our portfolio. The intent is to highlight what area of programming we are interested in. As such, I chose to work on implementing a gameplay feature into our 7th project.
For my specialization I chose to try and replicate the telekinetic ability in the game “Control” by Remedy Entertainment. This was a game I had been playing a lot lately and this was by far my favorite ability to use over and over and over again. Picking up an item, hearing that “whoosh” sound effect, and then throwing it with immense force at an enemy was just incredibly satisfying.
Most of my time during pre-production was spent doing research on what I would need and what I had available. I set out to recreate the telekinesis ability in our own engine as well as try and integrate it into our current project (although on a separate branch so as to avoid any bugs or conflicts), so it was important to know which parts of the ability were most important to nail down, and if our engine had the tools to do this.
For the Alpha sprint I wanted to try and implement all the basics of the ability as soon as possible so I could make sure I had a working framework that I could improve upon during later sprints. Things that were important to implement were:
- Detect if the player is aiming at an object that can be pulled.
- Pull the object towards a fixed point next to the player.
- Hold the object at that position and have it follow the player around.
- Throw the object towards where the player is aiming.
- Destroy the object when it collides with something and deal damage to whatever it hit.
Most things went pretty smoothly during this part of the project. The basic tools that I needed to actually get this working were already in the engine. Things such as PhysX, Rigidbodies, Raycasting, etc. Since we were using EnTT for our entity component system it was fairly easy to create a new “Telekinetic” component and just add it to any destructible object that the player was aiming at. After that it was just a matter of creating a system that would handle the behavior of telekinetic objects. A simple switch case and some manipulation of PhysX forces led to a pretty basic but decent result.
The original goal for this beta sprint was to expand the pull mechanic so that it would still pull items around the player even if they weren’t directly looking at a target. Not only that, I was planning on having it pull different items from the walls/floors and have them be a different type of object based on the material of the wall/floor. So for example trying to pull an object while looking at a wooden wall would result in you pulling out a sharp piece of wood that you can throw at a target.
This ended up being a bit overscoped. After speaking to one of my teachers I decided to focus on refining the basic mechanics and feel of pulling and throwing objects, rather than trying to add every feature that was in “Control”.
I ended up improving on things such as getting the objects you pull to stay on a fixed position next to the player without it looking too static when moving around or too juddery when trying to catch up with the player as they moved. I also added a slight delay to the pull of “heavier” objects such as the crate, to try and sell that it takes a bit of “force” to pull them towards you (although this isn’t as successful without any additional animations to the player).
Lastly, I added a simple switch case that would distinguish between the type of destructible component the player was about to pull and adjust damage and “explosion” radius accordingly. I also experimented with adjusting the damage objects do based on their mass but this wasn’t as successful since most of the items just used the default mass of 1.
I set out to do a couple of different things for this sprint. The main objective was to get the throwing to a better state, but there were obviously a couple of ways to go about doing that.
The first thing I tried was to make objects home-in on the nearest enemy. This was relatively easy to achieve but it presented a few problems: Thrown objects would not care if an enemy was behind a wall, outside the players view, or if the the player was aiming/shooting at a different target.
The last one was easy to solve. I used the same method for checking if an item could be pulled to check if the player was currently aiming at an enemy when an object was thrown. The other two… not so much. I had very little time left to get the project done (and also work on this website) and I could tell that solving those problems and also making it look nice would take too much time, so I decided to scrap the home-in mechanic and just keep the regular throw and aimed throw.
Working on this project gave me a new perspective on just how much polish and work goes into even the most basic aspects of a triple-A title. When I set out to do the planning I wasn’t sure if this feature would be “too simple” for a specialization or if I was gonna be way over my head. It ended up being a bit of both. Implementing the basics of the feature was quite simple and most of it was done in the first week or so of actual work. The rest of the time was spent refining the code to avoid any bugs (…There were a lot) and tweaking small aspects of the ability until it felt good to use.
Although the final version didn’t have every feature that I wanted to implement, and the ability itself doesn’t hold a candle to the excellent work the folks at Remedy did on Control, I am still pretty happy with what I managed to achieve. Playing through our game project “Fungal” I found myself doing the same thing I do in Control: Forgetting I have an actual gun and just trying to blast my way through the game by throwing objects everywhere.