Scripting Explorations: Turret Game
Over the past few months, between contract work and design tests, I have pursued ideas and projects that would bolster my skills as both a designer and as a scripter. This project is the result of some of those inquiries. During my time in education, I often found myself focusing more on the design aspects of game design as that is where I found my fun. Now, through these explorations I have cultivated my joy of scripting and figuring out simple solutions to complex problems.
This project began as a simple idea of wanting to create a spawning system. I had never done something like it before, so I decided to test myself. The goals for the project were as follows:
Create a simple spawning system
Have the system choose random spawning points
Once spawned, have the enemies move into a playspace of some kind.
Once the "encounter" was complete, open a door
Since I had never done a spawning system before, I felt this was a good series of objective to go after. I began by creating a simple list of things I would need to have in the encounter in order for the system to work. This list came out to:
What start points were specific to the encounter
Which endpoints its spawned enemies were supposed to use,
The type of enemy to spawn
The time between spawns
Thankfully, it is rather easy to spawn things through blueprint in Unreal 4. In little time, I had a simple spawning system that would create an "enemy", though it was just a box at the time, after a random delay. I even had the enemy spawning at a particular point. I even had an array of spawn points that the spawn system could select in order to spawn an enemy... except that was not what was happening. Instead, the system would either get fixateed on one spawn point, and ignore the others, or it would chose one or two other spawn points while prioritizing one. Ultimately, this was rather boring as it never left me guessing as to where my next enemy would come from. As such, I decided to start removing a spawn point from the array once it was used. This cause other problems as you are not supposed to mess with an array while it is being processed, or at leas that is what my professors believed. Additionally, because I wanted to have a spawn delay inside the loop, I was not able to use some of the other methods I had researched for spawning as the system would detect an infinite loop. These limitations caused me some headaches, however, I eventually discovered that by manually re-triggering the loop and I could get the result I wanted. While by far not an elegant solution, it achieved what I needed to do. However, I was still running into another problem, getting the spawning system to understand which spawn and end points to use.
My initial plan was to have the level blueprint hold all of the information. And while this initially worked out fairly well, I ran into complications quickly. First, I ran into complications trying to get the information from the Level Blueprint. I ended up having to create this awkward chain that began in the Level Blueprint creating the necessary arrays, pushing them to the player character, then the encounter accessing the information from the player character. Second, because the Level Blueprint was such an important part of that version, if I ever wanted to reuse the system for anything useful, I would pretty much have to rewire everything every time I put it into a new level. This would have been an annoying ordeal that I knew I could avoid if I explored other ideas. I tried storing various lists of start and end points in the Gamemode, and while that did work, it needlessly gummed up the game mode with extra information that other levels really did not need. Eventually, I took inspiration from the spawning system in the ALEX Protocol. While I did not work on that aspect of the game, I remember the programmers were able to designate arrays inside various blueprints. This lead me to the idea of each encounter holding all its own arrays of start and end points. This was a huge boon and soon lead to the panel that you see to the left. Once implemented, it allowed me to reuse the system any number of ways.
The last thing I decided to implement was the addition of random ending destination for the enemies. Having already solved some of the other major issues, this was an easy addition. The enemy first accessed the game mode to find the current encounter. Once found it accessed that encounter's endpoints, chose one at random, then moved to that point. It was simple, and easy to implement. Below is a video showing the spawning system in various situations.
Well, I now had a spawning system, but I needed something I could do with it. There were several ideas, but I wanted to keep it simple at first, make sure that something fun could be made, then move from there. After some deliberating, I decided to put together a simple turret game. The player would take the form of a turret in a level and enemies would rush either towards or past the player. The player would have to survive for a short amount of time, with difficulty increasing as they went. If the enemies got to the player or to the object the player was tasked with protecting, then the turret would explode and the game would end.
This seemed like a relatively simple expansion on my skills and a fun use of my spawning system. During the course of the project, I had to deal with a few strange issues. The first was the projectile. In my experience, when you create an object in Unreal 4, if it has a projectile movement component attached to it, then it moves forward based on the parameters in the projectile movement. For whatever reason, when I tried to spawn a projectile, the entity would just hang in space. The projectile would not die at the end of its lifespan, but still looked stretched out as it it were fired with a powerful force. Eventually I had the turret assigning the projectile a forward vector based on the information in the bullet's own projectile movement component, which allowed the bullet to fire.
Another interesting problem that I ran came with the spawning system. As originally built, the system really only supported spawn one entity at a time which is rather boring. The fun of this type of game comes from not knowing from where the next enemy will come even while more enemies are slowly encroaching on you. As such, I had to get creative. First, I cut the blueprint section that removed spawn points from the array and replaced it with a shuffle block so every time the system looped, the array would be different. Then, I added a simple Branch that checked whether the timer was below half. If not, the system went on as usual. However, should the time be below half, then the system would go fire a second spawning trigger, shuffle the array, then loop again. It was a simple way to add a bit more complexity to an otherwise simple system. You can see the blueprint in the pictures to the right.
Another interesting problem I ran into occurred when I first lost. For some unknown reason, even though the mine was still some distance away, at least a couple of hundred units, my failure state triggered complete with pausing the game and flashing a bright red GAME OVER onto the screen. I checked the player's collision volume, I checked the enemy's collision volume, nothing seemed out of place or strangely over-sized. After a few more tests, I eventually concluded that I even though I could not see what the problem was, I had to guard against it. I solved this problem with a simple series of checks. Since I was already destroying the enemy if it collided with a bullet, I made a branch off of the branch failure. If the enemy collided and it was not a bullet, then it would check if it had collided with the player character's collision capsule. If that was true, then and only then would it fire the Game Over.
After getting the major pieces of the project together, the spawning enemies, turret firing, I realized that one of the default settings for a projectile is whether or not it can bounce. Seeing an opportunity to create some interesting gameplay that was not just spin around as quickly as possible and see from where enemies are coming, I decided to add in a set of four walls. These energy walls allow enemies through, but will block a player's projectiles. By just adding in these slow moving walls, it creates moments where the player cannot interact with the enemies, forcing them to have to wait to fire. Meanwhile, enemies could be spawning all around them, slowly creeping closer. The player could abandon the current enemy and search for others, but they could not make it back in time to shoot them. These four simple walls create tension that otherwise would not be possible in such a simple game. By expanding upon this, there are hundreds of ways to make this simple title, into a nail-biting, exciting game.
The addition of the bouncing projectile is also a potential avenue for exploration. With proper timing and more enemies, players can easily find themselves in fun situations where they line up the right shot and hit multiple enemies in a row. I think there is plenty that can be explored with this simple foundation and look forward to seeing what I can do in the coming months.
Below, you can find a short, two minute gameplay video of the game in its current state.