I’m currently taking the course Big Game Project at Uppsala University – Campus Gotland, where the goal is to have, after 10 weeks, a working vertical slice of a game which might have the potential to become a product worth selling at a later stage.
We’re now four weeks into the production of the game Warpers, and this time I’ll write a little about how the composition of the objects in space is handled. Since Warpers is a 2D game, it can get quite difficult to render a scene which doesn’t look flat. The solution to that particular problem is called “Parallaxes“.
Parallaxes can be explained as:
“The method of displacing objects by a different amount depending on what depth they are considered to be in”
This is no real quote, but my own definition so take it with a grain of salt.
That means that when the camera moves, objects that are further away from the camera moves slower and can almost be seen as static while objects closer to the camera move as fast or faster than the camera depending on if the camera’s view target is closer or further away from the object that is a parallax.
When developing the parallax system I wanted to give the designers a simple and intuitive way of creating the different space scenes. As such I made it so that the designer only needed to think of a couple of things when placing props.
Before I explain how the parallax works, you need to know how the in-game layers (Y-Axis value, due to our game being oriented in the XZ-plane) are categorized.
- Background Decoration (-20 000): This is where the parallax layers resides. Between layer -10 000 and -20 000.
- Ship Exterior (-10 000): This is the layer on which all space interactions happen. Asteroids, enemy fighters etc. All the space action take place on this layer.
- Occluder (-1 000): There is only one thing on this layer. A huge, entirely black sprite which hides the space layers from the ship interior layer. Without this layer, the background would be visible behind the ship when a player is inside it.
- Ship Interior (0): This is the layer that players are located at when their player avatar is not a spaceship.
The parallax layers are located between the layers, -20 000 and -10 000. Objects located at a lower value are considered further away and move much slower than those at higher values.
There are three variables which are the most important in the parallax system.
- InitialLocation: This is an vector which holds the location that the designer originally placed the parallax object at.
- Scale: This float value is how much the object should deviate from its InitialLocation. A lower value means that the object is closer to the view-target and a value with higher Scale value is further away from the view-target.
- centerPoint: This vector is a globally accessible variable that defines where the view-target is currently located. All parallax use the same centerPoint to determine their final location.
When the parallax object first gets created, this short code snippet gets executed:
NOTE: Code snippets are very much simplified for sake of readability
Scale = 10 000; InitialLocation = GetActorLocation(); InitialLocation.Y += 10000.f; Scale = InitialLocation.Y / Scale; Scale *= -1.f;
The InitalLocation value gets the value of the current position of the object and its Y component gets incremented by 10 000 since the values are between -10 000 and -20 000. This means that the Y component ends up between 0 and -10 000 instead. Scale is then set to the InitialLocation Y component divided by Scale. The Scale value is initially is set to 10 000 due to that being the depth range that the parallax objects are located in. Lastly the Scale is inverted because the depth is considered to be at a negative value.
Next, this is the code that is executed every time that the variable is changed.
location.X = InitialLocation.X + centerPoint.X*Scale; location.Z = InitialLocation.Z + centerPoint.Z*Scale;
This code shouldn’t need much explaining since it’s only basic math going here. The parallax object is moved closer to the view-target’s location the higher Scale value it has.
Example: Say you want to have a static background. You then place that background on the (0,-20 000,0) location and the location update code takes care of the rest. Initialization Scale = 10 000 InitialLocation.Y = -20 000 + 10 000 InitialLocation.Y = -10 000 Scale = -10 000 / Scale Scale = -1 * -1; Scale = 1 Updating centerPoint = (5 000, -10 000, 12 000) location.X = 0 + (5 000 * 1) location.Y = 0 + (12 000 * 1) location = (5 000, -10 000, 5 000) Resulting behavior: Parallax object location is the same as centerLocation when object is placed at depth -20 000.
The above example demonstrates that objects placed at a depth of -20 000 becomes viewed as static ones because they retain the same location as the view target due to the Scale value being 1. But if the object is placed at a depth other than -20 000 and offset from the middle on either the X or Y axis, then the farther away from the middle an object is placed, the greater chance that the object won’t be within view for the player. Due to relative offset from InitialLocation.
The above image demonstrates that objects that are located at a lower Y value have higher risk of being out of view from the player, but also that this declines as the values are closer to -10 000. This is something that the designers that are building the solar systems need to think about in order to prevent placement of invisible parallax objects.
The method of using parallaxes is a great way to easily create depth in an image but it come with one downside which, as of writing this, haven’t been resolved yet.
The downside is that only one camera location is allowed at one time as there is no way of updating the parallax locations before rendering each separate camera. And as this game have strong focus on co-operative play in a split-screen setup there is currently no way to have multiple separate space views on different locations. This is an issue which needs to be resolved before we allow multiple player-controlled ships to be utilized. This wouldn’t be an issue if there was a way of updating the parallax objects before each camera render, but it appears that currently there isn’t any way to do this in Unreal Engine 4.
~Lead Designer and Programmer, Per “Gimmic” Johansson