Playable Game - Rocketing Outhouse, Escape the Earthquake!

Hello fellow developers!

Just finished building my Project Boost game in Unity! (Don’t worry, I’m sure I’ll get better LOL)

“After an incredible earthquake, farmer Hoggins is left stranded in the outhouse with no toilet paper! Help Farmer Hoggins find his missing TP, before another quake strikes!!” !

Controls:

SPACE = Thrust
A = Left
D = Right

Enjoy ! :slight_smile:

3 Likes

Here’s the code for the rocket ship. I did some searches outside the course to figure out how to program the lighting for the engines. I like the effect.

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

// fixed lighting bug from "Object Maps" tab on "Lighting"

public class Rocket2 : MonoBehaviour {
    // [SerializeField] reveals the variable in the inspector
    [SerializeField] float rotateMultiplier = 120f;
    [SerializeField] float thrustMultiplier = 700f;
    [SerializeField] float levelLoadTime = 1f;

    [SerializeField] AudioClip mainEngine;
    [SerializeField] AudioClip impact;
    [SerializeField] AudioClip death;
    [SerializeField] AudioClip success;

    /* This will expose particle system to Inspector
     * 1. SerializeField ParticleSystem
     * 2. Add particle system Prefab to rocket game object
     * 3. Drag child particle system game object to particle system in script
     * 4. Code .Play() or .Stop() for particle system
     */
    [SerializeField] ParticleSystem mainEngineParticlesL;
    [SerializeField] ParticleSystem mainEngineParticlesR;
    [SerializeField] ParticleSystem deathParticle;
    [SerializeField] ParticleSystem successParticle;

    [SerializeField] Light mainEngineLightL;
    [SerializeField] Light mainEngineLightR;

    GameObject leftThrustLight;
    GameObject rightThrustLight;

    Rigidbody rigidBody;
    AudioSource audioSource;

    int totalScenes;
    int nextScene;
    int currentScene;  // create an integer variable for storing the current scene index

    bool collisionsEnabled = true; // for debug code

    enum State { Alive, Dying, Transcending };
    State currentState = State.Alive;

    // Interpolate light color between two colors back and forth
    [SerializeField] float flickerDuration = 1.0f;
    Color color0 = Color.red;
    Color color1 = Color.yellow;

    // Use this for initialization
    void Start()
    {
        /* Accesses the RigidBody component within the context of where 
         * this script is being executed. In this case, <RigidBody> will
         * find the RigidBody component of the GameObject where Rocket.cs
         * is applied.
        */
        totalScenes = SceneManager.sceneCountInBuildSettings -1; // # scenes in build settings
        rigidBody = GetComponent<Rigidbody>(); // instantiating a variable
        audioSource = GetComponent<AudioSource>();

        currentScene = SceneManager.GetActiveScene().buildIndex;  // get the active scene's index, stored as int
        mainEngineLightL.enabled = !mainEngineLightL.enabled;
        mainEngineLightR.enabled = !mainEngineLightR.enabled;

        print("currentScene = " + currentScene);
        print("totalScenes = " + totalScenes);

    }
    // Update is called once per frame
    void Update()
    {
        Controls(); // player controls
        SetEngineLightColor(); // cycles engine light color

        if (Debug.isDebugBuild) {DebugGame();} // debug controls for build settings
    }

    void OnCollisionEnter(Collision collision) // detects collider contact of GameObject
    {
        if (!collisionsEnabled) { return;} // part of debug logic

        if (currentState == State.Alive)
        {
            switch (collision.gameObject.tag)
            {

                case "Friendly":
                    //do nothing
                    print("Touched friendly");
                    break;

                case "Finish":
                    //add Finished Level
                    StartLevelAdvanceSequence();
                    break;

                case "FinalPad":
                    // todo create game completion scene
                    print("You have completed the game!");
                    break;

                default:
                    //die
                    StartDeathSequence();
                    break;
            }
        }

    }

    private static void DestroyOutHouse() // currently unused
    {
        // destroy OutHouse. This also destroys the scripts currently running on the outhouse.
        // It means my game logic disappears with the outhouse...
        // todo separate game logic from player GameObject
        string name = "OutHouse";
        GameObject go = GameObject.Find(name);
        if (go)
        {
            Destroy(go.gameObject);
            Debug.Log(name + " has been destroyed");
        }
    }

    private void StartLevelAdvanceSequence()
    {
        print("Touched LandingPad");
        currentState = State.Transcending;
        audioSource.Stop();
        Invoke("LoadNextLevel", levelLoadTime); // run coroutine
        audioSource.PlayOneShot(success);
        successParticle.Play();
    }

    private void StartDeathSequence()
    {
        print("Bad touching. Dry death.");
        currentState = State.Dying;
        audioSource.Stop();
        audioSource.PlayOneShot(death);
        audioSource.PlayOneShot(impact);
        deathParticle.Play();

        Invoke("LoadNextLevel", 1f);
    }

    private void LoadNextLevel()
    {
        switch (currentState)
        {
            case State.Dying: // Dead, go back to beginning
                currentScene = 0;
                SceneManager.LoadScene(0);
                break;

            case State.Transcending: // Advance to next scene

                if (currentScene == totalScenes)
                {
                    currentScene = 0;
                    SceneManager.LoadScene(0);
                }
                else
                {
                    currentScene = SceneManager.GetActiveScene().buildIndex;
                    nextScene = ++currentScene; // increase the current level integer by one
                    SceneManager.LoadScene(nextScene); // load the next level, which is current level increased by 1
                    audioSource.Stop();
                    print("currentScene = " + currentScene);
                    print("nextScene = " + nextScene);
                    print("totalScenes = " + totalScenes);
                }
                break;

            default:
                Debug.LogError("Invalid State Entered");
                break;
        }
    }

    void DebugGame()
    {
        if (Input.GetKeyDown(KeyCode.L))
        {
            currentState = State.Transcending;
            LoadNextLevel();
        }
        else if (Input.GetKeyDown(KeyCode.C))
        {
            collisionsEnabled = !collisionsEnabled; // toggle collision enable/disable
        }
    }

    private void Controls() // player controls
    {
        if (currentState == State.Alive)
        {
            RespondToThrustInput();
            RespondToRotateInput();
        }
    }

    void RespondToThrustInput()
    {
        float thrustThisFrame = thrustMultiplier * Time.deltaTime;

        ApplyTrust(thrustThisFrame); // control thrust vector
        ApplyThrustLights(); // control thrust lights
        ApplyThrustParticles(); // control thrust particle
    }

    private void ApplyTrust(float thrustThisFrame)
    {
        if (Input.GetKey(KeyCode.Space))
        {
            rigidBody.AddRelativeForce(Vector3.up * thrustThisFrame);
            if (!audioSource.isPlaying)
            {
                audioSource.PlayOneShot(mainEngine);
            }
        }
        else
        {
            audioSource.Stop();
        }
    }

    private void ApplyThrustParticles()
    {
        if (Input.GetKey(KeyCode.Space))
        {
            mainEngineParticlesL.Play(); // Left Engine
            mainEngineParticlesR.Play(); // Right Engine
        }
        else
        {
            mainEngineParticlesL.Stop();
            mainEngineParticlesR.Stop();
        }
    } 

    void ApplyThrustLights()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            mainEngineLightL.enabled = !mainEngineLightL.enabled;
            mainEngineLightR.enabled = !mainEngineLightR.enabled;
        }
        if (Input.GetKeyUp(KeyCode.Space))
        {
            mainEngineLightL.enabled = !mainEngineLightL.enabled;
            mainEngineLightR.enabled = !mainEngineLightR.enabled;
        }
    }

    private void SetEngineLightColor()
    {
        // set light color
        float t = Mathf.PingPong(Time.time, flickerDuration) / flickerDuration;
        mainEngineLightL.color = Color.Lerp(color0, color1, t);
        mainEngineLightR.color = Color.Lerp(color0, color1, t);
    }
    
    private void RespondToRotateInput()
    {
        float rotateThisFrame = rotateMultiplier * Time.deltaTime;

        if (Input.GetKey(KeyCode.A)) //rotate LEFT
        {
            RotateManually(rotateThisFrame);
        }
        else if (Input.GetKey(KeyCode.D)) //rotate RIGHT
        {
            RotateManually(-rotateThisFrame);
        }
    }

    private void RotateManually(float rotateThisFrame)
    {
        rigidBody.freezeRotation = true; // take manual control of rotation
        transform.Rotate(Vector3.forward * rotateThisFrame);
        rigidBody.freezeRotation = false; // release manual control of rotation
    }
}

Ha, brilliant! I love the concept and details.

Thanks for sharing the code too. :slight_smile:

Awh man, this is cool. The rocket sound and particle effects are pretty awesome

Privacy & Terms