Leveling Up Project8088

Leveling Up Project8088

Part A

Introduction

When first starting out developing Project8088, I rushed head on into this new world of game development. Even with 30 years of development experience in the web world, building a game is a different beast. But there are many overlapping concepts, because in the end, a game is presenting data to a user and processing input.

As I was building the first level for Project8088, my goal was to create a tutorial area where the player could learn the style of the game and how to play it. The game itself isn't complicated - basically an entry level FPS. But I wanted the tutorial to go through 4 or 5 levels of the same map allowing the player to get comfortable with the game and, from a developer perspective, get some mileage out of the level itself.

While developing the first level, I made some key decisions on how I wanted to implement the game. The first was deciding that each level would be broken down into phases. Each phase would describe the phase objective and what the player was to in order to determine if the phase was complete. And once completed, the game would automatically move to the next phase.

During early development, these phases materialized as blocks of Blueprint nodes. Each phase, the first level had 5 of them, had their own set of nodes determining the parameters and checking for a completed phase. This paradigm would have been fine if just creating a single level game. But what would happen when levels 2, 3, and 4 were added in. I could see very quickly that the EventGraph would become unwieldy, difficult to enhance and maintain.

I took a step back and reviewed what I had done so far. That last thing I wanted to do was to trade technical debt for development speed full well knowing it would become a problem later down the road.

Levels and Phases

My first step was to breakdown the level and phases into a array of objects - not unlike JSON. I looked into Unreal Engine's JSON plugin, but I did not find it very intuitive to use. So I decided to just stick with the standard array and struct objects. The first object I created was the phase struct which contained elements of a phase.

This is the latest iteration of the phase structure. It contains strings for when the player begins the phases, helps them with what to do, and a placeholder for a message when the phase is complete. The phase struct also has a Boolean to indicate if the phase has been completed and a rules struct for how the phase plays out.

In the original design of the PhaseObjective struct the rules were listed out. But as I was working with the phase, I felt the rules should get their own struct.

The phase rules are a bit more extensive as they are the core parameters that determine gameplay. Many of the keys in the phase rules begin with Spawn... which determine number of enemies of that type to spawn at the named ProbeSpawner.

CommsCodeBegin and CommsCodeEnd, if set, indicate that the communication chips in the level need to be reset to match CommsCodeEnd binary code. RestoreQuantumField tells the player to recharge their health bar to the specified value. BarrierWall indicated that once the phase is completed, the named barrier will turn off.

DestroyAllEnemies means that the player must destroy all enemies before moving to the next phase. WeaponEquipped determines if their weapon is available to the player. IfOpenPortal and OpenPortalLevelName are set, then the portal will open taking the player back to the named level.

Each phase of the game will use one or more of these key value pairs in the rules. Once the gameplay rules have been satisfied, the phase is marked complete and the Level Blueprint moves onto the next phase. (Part B will cover how that is handled.)

As each phase is defined, it goes into an array of phases. Then, the phase array is added to the level.

The LevelStruct stores data elements about a level including it's name and description. There is a struct for storing LevelStats, which for now, is mostly a placeholder for future stats. The level struct also defines whether the level is a portal level and, if so, what map to load when going through the portal.

But most importantly are the Phases which is an array of PhaseObjectives which contains the PhaseRules.

All the level and phase data are loaded via Game Instance. Because the player is moving in and out of maps | [UE] levels, this data is more easily managed in the game instance. Since the game instance is loaded before a level loads, the game will already have the information it needs to set the level up for the player.

Loading levels is a fairly simple process. The game instance has a custom event (although these I may make these functions) that starts by clearing a reused Phase Array variable for holding the phases as we build them. Next, a PhaseRule struct variable is used to capture the rules for the phase. For example, the first phase of level 2 will spawn 8 parity probes, turn off all the Comms chips and equip the weapon. The phase is completed when the player's Comms code matches the expected Comms code.

Next, the PhaseRules are added to the Phase. And then the phase is added the Phase Array. This process is repeated for all phases in the level until all are added.

The Phase Array is then added to the level. The last step add the level to the Levels array in the game instance.

When looking at the game instance from a distance, we can see how levels 1-5 are laid out. I've recently discovered that nodes can be collapsed as you may be able to see level 1 (the top level). So once levels 2-5 are completed, I will give them the same treatment.

Each of these levels are loaded by a LoadLevelDefinitions event.

The LoadLevelDefinitions event is kicked off via the Event Init event in the game instance.

Part B of this article will show how the levels and phases are processed by the Level Blueprint. (sign up to be notified when Part B posts)

All in all, I think this will be a good long term system for the game. While the level and phase definitions are defined in the game instance, each Level Blueprint will handle processing those definitions. This yields a lot of flexibility within the game while maintaining a baseline structure for the gameplay.

Subscribe to electricDust

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe