top of page
Main_Menu (1).png

Bad Trip

In Advanced Game Development (CSDS 390), I worked with a team of 10 other members to develop a completely original game in 4 months. We created Bad Trip, a 2D sci-if puzzle game where the player’s spaceship has crashed and they need to solve puzzles to get all systems back online. We have created an innovative hex puzzle series with multiple possible game endings amongst many other features. Our game can be played online, for Mac, and for Windows at the attached link. Our gameplay runs from about 35 minutes for a first-time bare-minimum completion to an hour and a half for first-time full completion. Our game won the "Class Choice: Favorite Game" at our panelist night. Additionally, we received an overall score of 9/10 with two 10/10s from panelists from AAA and Indie studios.

What Makes Our Game Unique?

Color Shifting, Alien Spores, Multiple Endings

Spore Key.png
Untitled_Artwork 4 (1).png

Our game's main puzzle feature is our unique color-shifting mechanic. In our hex puzzles, pieces are either red, blue or green. These colors determine how much you can rotate that puzzle piece (ex. red is 60°, blue is 120°, and green is 180°). In addition to this, we also have a spore tile, which once click shifts all of the colors in the puzzle, allowing for new piece rotation opportunities. We have a similar mechanic in the environment, where doors around the ship are locked until their activation lights have been turned green.

 

My personal favorite feature of our game has to be the alien spores around the ship, which emit a glow and audibly react to the player when they are in close proximity. These spores have the power to change the player's perception of colors in their environment.

Another one of our features that allows for replayability is that we have implemented multiple endings to our game: "Ominous Ending," "Bad Ending," and "Secret Ending." The ominous ending happens when the player solves all puzzles and collects all lore notes, the bad ending happens when the player solves all puzzles but doesn't collect all lore notes, and the secret ending occurs when the player unlocks a secret escape pod hidden behind a set of lockers.

My Contributions

For this game, I was both the Project Manager and the Lead in Sound Design/Implementation. 

​

My contributions include:

  • Coding all audio implementation

  • Creating all Foley SFX

  • Creating all digital SFX

  • Composing and producing all game music

  • 61 pages of game documentation

  • Assigning team members work

  • Setting meeting dates, creating meeting agendas, leading meeting discussions, and sending out meeting recaps

  • Creating and presenting team presentations (concept presentation, prototype presentation, panelist presentation)

Screenshot 2023-12-01 at 16.29.18.png

Code Samples

I implemented audio and SFX in various ways throughout the development of this project. Some music required a script to continue music throughout scenes, while some sound effects needed to be randomized amongst other sound functionalities. Below are some samples of my larger C# script contributions to the game.

Music Continuity Player
Script used to ensure that audio doesn't reset on any menu screens and plays continuously until gameplay begins

image.png

using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;

public class MainTheme : MonoBehaviour
{

    //creating the audio source and instance variables
    public static MainTheme instance;

    public AudioSource audioSource;

    //awake section to make sure audio is set to this specific instance and that the game object doesn't get destroyed

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            gameObject.GetComponent<AudioSource>().enabled = false;
        }
        SceneManager.sceneLoaded += SceneLoaded;
    }

    //SceneLoaded function to track what scenes should start and stop the main theme music

     private void SceneLoaded(Scene scene, LoadSceneMode mode)
    {
        if (scene.name == "LightScene")
        {
            MainTheme.instance.audioSource.Stop();
        }
        else if (scene.name == "StartScene" && !MainTheme.instance.audioSource.isPlaying)
        {
            MainTheme.instance.audioSource.Play();
        }
        else if (scene.name == "CreditsScene" && !MainTheme.instance.audioSource.isPlaying)
        {
            MainTheme.instance.audioSource.Play();
        }
    }

    //PlayMusic function to trigger main music to start

    public void PlayMusic(AudioClip music)
    {
        audioSource.clip = music;
        audioSource.Play();
    }
}

 

Dead Crewmate SFX Fade
Script used to gradually fade out whispering of dead crewmate to avoid issues of audio suddenly cutting off

image.png
image.png

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CrewSounds : MonoBehaviour
{

    //creating audio variables and desired fadeout length
    public AudioClip crewClip;
    public AudioSource audioSource;
    public float fadeOut = 2f;

    //on start assigns the audio clip to the source

    void Start()
    {
        audioSource = GetComponent<AudioSource>();
        audioSource.clip = crewClip;
    }

    //when player enters the dead crewmate mirror room, trigger the sound effect

    void OnTriggerEnter2D(Collider2D other)
    {
            audioSource.Play();
    }

    //when player exits the dead crewmate mirror room, trigger the fade-out function

    void OnTriggerExit2D(Collider2D other)
    {
            StartCoroutine(StopSound());
    }

    //StopSound function which keeps track of fade-out timing and slowly fades out the crewmate SFX

    IEnumerator StopSound()
    {
        float startVolume = audioSource.volume;
        float time = 0f;

        while (time < fadeOut)
        {
            time += Time.deltaTime;
            audioSource.volume = Mathf.Lerp(startVolume, 0f, time / fadeOut);
            yield return null;
        }

        audioSource.Stop();
        audioSource.volume = startVolume;
    }
}

 

Spore SFX Trigger
Script used to play a random spore SFX when the player enters its vicinity

image.png
image.png

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SporeEffects : MonoBehaviour
{
    //sets up an array of possible SFX and audio variables
    public AudioClip[] audioClips;
    private AudioSource audioSource;

    //on start assign the audio source to the script

    void Start()
    {
       audioSource = GetComponent<AudioSource>();
    }

    //PlayEffect function that plays a random clip from the declared SFX array while making sure no audio gets suddenly cut off

    private void PlayEffect()
    {
        if (audioClips.Length > 0)
        {
            audioSource.clip = audioClips[Random.Range(0, audioClips.Length)];
            if (!audioSource.isPlaying)
            {
                audioSource.Play();
            }
        }
    }

    //function that triggers SFX when the player is close to the spore

    void OnTriggerEnter2D(Collider2D other)
    {
            PlayEffect();
    }

 

Volume Menu Controller
Script used to save and load volume slider settings for SFX and Music slider menu

Volume.png
image.png

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio; 
using UnityEngine.UI;

public class SetMusicVolume : MonoBehaviour
{

    //variables to set up the mixer being adjusted and the slider being adjusted
    public AudioMixer mixer;
    public string mixerVolume = "MusicVolume";
    public Slider slider;

    //on start, the previous volume gets loaded in from the player

    private void Start()
    {
        if (PlayerPrefs.HasKey("SavedMusicVolume"))
        {
            float savedVolume = PlayerPrefs.GetFloat("SavedMusicVolume");
            SetMusicMixerVolume(savedVolume);
            slider.value = savedVolume;
        }
    }

    //transfers the slider value to the actual volume in-game, while also saving/storing it

    public void SetMusicMixerVolume(float volume)
    {
        mixer.SetFloat(mixerVolume, Mathf.Log10(volume)*20);
        PlayerPrefs.SetFloat("SavedMusicVolume", volume);
    }

    //triggers the volume to be updated whenever the slider value is changed

    public void OnSliderValueChanged()
    {
        SetMusicMixerVolume(slider.value);
    }
}

 

Screenshot 2023-12-01 at 16.29.44.png

Documentation

I have created and organized 61 pages of comprehensive game design documentation for this project, which can be found in a PDF below or on Bad Trip's Website under the Downloads section. This documentation includes playtesting criteria, team roles, art, game mechanics descriptions, and more.

Screenshot 2023-12-01 at 16.29.44.png

Presentations

I have created and organized all 3 of our presentations: the concept presentation, the prototype presentation, and the final panelist presentation. I really enjoyed bringing our passion for the game to life for an audience and getting others excited about Bad Trip's gameplay. This was an important lesson in theming and advertising to the public for me.

image.png

Music Production

Main Theme

For the game music, I wanted to pay homage to traditional video game bit-tune music with a modern twist. Using digital synth instruments, I constructed a suspenseful and engaging main theme that builds throughout the player's time in the menus. At the beginning, I added drum beats to mimic the sound of a heartbeat to build suspense and gradually layered more synths as the track progressed. Personally, I am a huge fan of arpeggiated music, so I made sure to sneak that into all game variations to add some flair.

Game Theme Variation

Keeping with the same key and digital instruments as the main theme, the game theme is designed to be much more toned-down so as to not detract from the gameplay. Using warbling synths, I went for "droning" background music to add a general feeling of apprehension and suspense. This is the longest track out of the three running at about 4 minutes, and this was designed to limit the amount of repetition the player would hear while exploring the ship and solving puzzles. Similar to the main theme, there is a build with the amount of instruments and percussive elements but at a more minimalist level.

Ending Theme Variation

To close out the soundtrack and the game, the ending theme is a much more bouncy and upbeat rendition of the main theme. Again, the same instruments and key were kept to maintain a sense of continuity throughout all 3 theme variations.

Sound Design (SFX)

1

Foley

I had such a fun experience with creating Foley art for Bad Trip. It posed an interesting challenge to create sound effects for a large spaceship while balancing out the fact that it was a 2D pixel game. Using a variety of materials including cardboard, utensils, tools, metals, a TV, and my own voice, I created sound effects that had a balance between realism and cartoon feedback. These sound effects were mainly used for environment interaction, such as the doors or the dead crewmate. A few samples of my work can be played below.

Spore Skitter - Plastic Fork on a Briefcase
Dead Crewmate Whispers - Manipulated Vocals
Footsteps - Wood Block on TV Screen
Door - Metal Knife against Mason Jar Lid
Lore Note - Cardboard against Fridge Metal

2

Digital

For the more mechanical elements of the game that needed sound effects, I decided to go the route of digital sound effect production as I felt my experimentation of Foley art in these areas took away from the electronic components of the game. Using a variety of synths, I manipulated the audio of digital instruments to create a variety of mechanical SFX including puzzle piece effects, panel effects, and powering effects. A few samples of my work can be played below.

Button Press
Dialogue
Spore Growl
Spore Chant
Powering
Puzzle Reset
bottom of page