Lightspeed Breakout

Reed Bowling, Benjamin Don, Elleis Souza, Ryan Zesch

CSC 476 - Spring 2020

Lightspeed Breakout is a two-stage escape game. You start out as a penguin rights activist on a hostile spaceship that really hates penguins. Armed with just a scavenged gun and some gravity boots, you must navigate the maze-like ship to free all the trapped penguins. You must also collect resources that will aid you in your eventual escape. Once all the penguins are freed, and you've crafted some powerups, you make your final escape. However, the hostile spacecraft notices you and so you must engage in a spacefight! Only by destroying all the enemy turrets while avoiding their shots can you defeat the penguin-haters and escape with your (and the penguin's) lives.

User Guide

Graphics Technologies

Game Cameras

Our game has two distinct sections with separate controls and unique cameras. The first section involves a normal first person camera, with camera pitch limited to 180 degrees. We used a sin and cos function to add view bob, as well as the camera matrix transforms to position the laser shotgun. The second part of the game required a more complex camera that had full 360 degrees of movement on all axes. To accomplish this whilst avoiding issues like gimbal lock, we implemented a quaternion based rotation scheme. Additionally, the camera moves on a slight spring when boost is activated, to give more of a sensation of speed.

Procedural World Generation

In order to increase replayability and difficulty of our game, we implemented procedural world generation. A starting room is created, and then rooms are placed adjacent to existing rooms in such a way to guarantee a spralling spaceship, until a specified number of rooms are placed. We designate five special rooms - the starting room, the exit room, and three rooms with penguins that must be freed before moving to the second game stage. Once rooms are placed, each is populated with decor including servers, power generators, and pipes, in addition to having collectibles placed for the player to find. Finally, turrets are placed in some rooms to provide additional difficulty for the player.

Instance Rendering

The game engine automatically will group together entities using the same vertex buffers and pass them to the gpu only once when performing draw calls. This way, the minimum amount of data transfers necessary occur in order to speed up performance. The main places in the game this technology is utilized is for drawing multiple rooms and laser shots.

Collision Detection & Physics

For collision detection in our game, we decided to implement an octree data structure. This data structure represents the world as a cube, which is then subdivided into octants recursively in order to classify where objects are in the game world. Every frame a new octree must be created, as objects may move between frames. The purpose of this data structure is two-fold - it is used both for collisions and for view frustum culling.
In the process of detecting colissions, the octree allows us to only check for detailed colissions between objects that are in close enough octants that they even have a chance to be colliding. Once two objects are close enough to check for a colission, we check if they are colliding in three different ways depending on if the collision would be sphere to sphere, bounding box to bounding box, or sphere to bounding box.
After collisions are determined, the physics system will then update the positions and velocities of the objects involved in collisions, with different ways of determing the new position and velocity for each colission type. Furthermore, if an object is involved in multiple collisions, the resultant velocity for the object is determined by a combination of all the collisions it is in by keeping track of a delta velocity due to each collision.

Shadows

Our game uses a single point-light which casts omnidirectional shadows. For performance reasons, we decided to only have one point-light and have it "follow" the player around by jumping to the nearest room to the player. To make the shadows, we first render the scene to a cubemap from the light's perspective, writing the depth values instead of color values. To do this, we use a geometry shader which is able to output primitives to all 6 faces of the cubemap in one render pass. We then use this depth cubemap when rendering the scene to determine if each fragment should be shadowed. We compare the depth of the current fragment to the stored depth in the cubemap. We also implemented Percentage-Closer Filtering to make our shadows have smoother edges.

View Frustum Culling

This game implements view frustum culling. We use the Octree that is generated for collision detection for performing the test to determine if an entity should be culled or not.

Cell Shading

A cell shading aesthetic is achived in two ways. Firstly, after lishting and shadow computation, the reultant color is binned in each of its RGB components. After color is binned, some specular light is added back in to prevent the world from looking too flat. Secondly, outlining of objects is done by writing to a depth map and then applying a Sobel edge detector in order to determine if a fragment is on an edge and should be colored black.

HUD

In order to update the player with vital information and improve the overall look and feel of the game, we implemented a fully dynamic hud. The first section's hud features a sprint and health bar that map the players actual values to screen coordinates to accurately display the player's current status. The player also has an inventory hot bar, which is used to display icons of each item that the player has collected. We also integrated FreeType to handle text-based needs such as the game timer, inventory item counts, and status messages. The second section's camera includes two semi-circular health bars that are incremented by an angle that changes over time. All of our hud elements were custom made in photoshop.

Bloom

Via the use of HDR buffers, the game engine naturally implements bloom for any extremely bright objects in the scene. This can be seen specifically in the lasers, however, the engine supports it for any bright objects. The bloom happens through a simple gaussian blur applied to a multiple-render-target-produced FBO containing objects over a certain threshold of brightness.

Gameplay

Resources