Balloon Popper - Michael Freaney



Overview

A small game about popping balloons in the mountains.

Made as a final project for CSCE 489: Computer Animation

Features

Procedurally Generated Environment

Overview

One of the biggest concepts I wanted to tackle with this game was creating an environment that was procedurally generated. I put together a combination of generating Perlin Noise and spline surfacing to interpolate between noise heights. This allowed me to write a highly adjustable algorithm where I could adjust the size of the individual spline surfaces and decide to either use more noise points or more spline interpolation. Either way, the result of this was a mountainous region where some parts of the map were less mountainous than others. It really added to the exploration, and kept flying around very refreshing.

The code for the Perlin noise generation was adapted from here. This site also helped very much with my understanding behind how the noise works.

The Algorithm

  1. Generate a grid of points using Perlin noise to map their coordinates to height.
  2. Taking 16 of those points at a time, generate connecting B-spline surfaces.
  3. Iterate over (u,v) for the surfaces and create triangles by calculating spline heights.
  4. Track the min height and max height so we can normalize the values for a shader.
  5. Color the fragments based on their height from 0 to 1.

Media





Fully Controllable Helicopter

Basics

Focusing on the controls of the helicopter was an important detail I wanted to get right, as well. I began with a fundamental concept used in any 3D movement, which is keeping track of our controllable player's forward, right, and up vectors. By initializing these in certain directions, we can then update our character's local space by rotating all of those vectors every frame when the player inputs say so. By rotating this space, we can now use a "lookAt" function to move the camera to the proper position. All that's left is to render the helicopter in front of it!

Adding Weight to the Controls

These controls so far are interesting, but they don't have the proper weight that controlling an actual aircraft would bring. So, let's introduce acceleration that eases our aircraft in and out of its turning. When a key is held down to signify turning in some direction, our step function will then add delta time to the "magnitude" value of that specific rotational value. Likewise, when letting go of a key, the magnitude eases out by having the timer decrease by delta time. This gives turning quite a lot of weight to it.

Visual Effects

In addition, we can add visual effects to the helicopter when performing these turns. Now that we're keeping track of the magnitudes of the helicopter's roll, pitch, and yaw, we can utilize those values in adding a slight rotation to the rendered helicopter on screen. So, when the helicopter is turning left, the model will rotate a little bit in that direction. This serves no mechanical purpose, but it makes the movement look much more realistic.

Media





Shootable Balloons

Projectile

With all the values we're keeping track of, the rest of our mechanics are actually rather simple. To fire a projectile, we can set its "forward" vector to be the exact same as the helicopter's. In the projectile's step function, it then travels in that direction at a speed much greater than the helicopter's. It will also never change directions and continue moving. To ensure we don't lose track of the memory this program takes up, I have implemented it so that there can only exist 5 missile pointers at once, and on attempting to fire a 6th, we reuse the first one and set its position and forward vector to the helicopter's on that particular frame.

Collision Detection & Optimization

Detecting collision with balloons is much simpler - if a projectile is within 10 units of the balloon's position (the radius of the sphere we render for it), then the balloon stops being rendered, and we decrement the number of remaining balloons. Unfortunately, with a large amount of balloons and 5 missiles, this can be a bit messy in terms of optimization. Thus, let's say that on top of only being allowed to have 5 missiles at once, they can only exist for up to 1000 units away from the helicopter, and any balloon further than that from the helicopter will not check for collision. Because there isn't much satisfaction in shooting a balloon that's so far away it can't be seen, it makes sense for this distance cap to exist, and it lets our program run very smoothly!

Media





Particle System

Using Lab 08 as a guide, I made a customizable particle system with inspiration drawn from the method used by Unreal Engine - a particle system that can be called to play at any position given to it. With this, I used GL_POINTS to draw a set of particles that are affected by gravity. By also opening up the input for a color, we can have the particles be any color we like. As a side note, some textures had to be rotated and mirrored to display correctly, hence why some might look like that in the project files.





UI

With an orthographic projection matrix, I also drew up some UI to be tracked in a separate manager. While it's a bit of an antiquated method of drawing numbers in UI, I kept textures of every digit from 0-9, and devised a method for drawing them based on a number being tracked in the UI manager (that is, the number of remaining balloons). Whenever a balloon would be popped by a projectile, the number would decrement, and the UI manager would simply draw the new number to the screen instead. For ease of use, I used GL_POINTS, similar to how I did particles, which made it a very easy process.





Resources