Example #1
0
        //Again, use LateUpdate to solve some collision issues.
        void LateUpdate()
        {
            if (true)
            {
                float viewRotX = 0;
                //If we're not paused, update speed and rotation using player input.
                if (!state.MovementFrozen)
                {
                    state.deltaRotation = Vector3.zero;

                    //If they press the Y button, invert all Y axes
                    if (Input.GetAxis("Invert Button") > 0 && !invertKeyDown)
                    {
                        inverted     *= -1;
                        invertKeyDown = true;
                    }
                    //And if they released it, set the invertkeydown to false.
                    else if (!(Input.GetAxis("Invert Button") > 0))
                    {
                        invertKeyDown = false;
                    }

                    #region ControlScheme

                    //PLAYER MOVEMENT

                    //If we press W, move forward, if S, backwards.
                    //A adds speed to the left, D to the right. We're using FPS style controls
                    //Here's hoping they work.

                    //The acceleration relation is defined by the following equation
                    //vNew = (v+uParallel+ (uPerpendicular/gamma))/(1+(v*u)/c^2)

                    //Okay, so Gerd found a good equation that doesn't break when your velocity is zero, BUT your velocity has to be in the x direction.
                    //So, we're gonna reuse some code from our relativisticObject component, and rotate everything to be at the X axis.

                    //Cache our velocity
                    Vector3 playerVelocityVector = state.PlayerVelocityVector;

                    //Get our angle between the velocity and the X axis. Get the angle in degrees (radians suck)
                    float rotationAroundX = DEGREE_TO_RADIAN_CONST * Mathf.Acos(Vector3.Dot(playerVelocityVector, Vector3.right) / playerVelocityVector.magnitude);

                    //Make a Quaternion from the angle, one to rotate, one to rotate back.
                    Quaternion rotateX   = Quaternion.AngleAxis(rotationAroundX, Vector3.Cross(playerVelocityVector, Vector3.right).normalized);
                    Quaternion unRotateX = Quaternion.AngleAxis(rotationAroundX, Vector3.Cross(Vector3.right, playerVelocityVector).normalized);


                    //If the magnitude's zero just make these angles zero and the Quaternions identity Q's
                    if (playerVelocityVector.sqrMagnitude == 0)
                    {
                        rotationAroundX = 0;
                        rotateX         = Quaternion.identity;
                        unRotateX       = Quaternion.identity;
                    }


                    //Store our added velocity into temporary variable addedVelocity
                    Vector3 addedVelocity = Vector3.zero;

                    //Turn our camera rotation into a Quaternion. This allows us to make where we're pointing the direction of our added velocity.
                    //If you want to constrain the player to just x/z movement, with no Y direction movement, comment out the next two lines
                    //and uncomment the line below that is marked
                    float cameraRotationAngle = -DEGREE_TO_RADIAN_CONST *Mathf.Acos(Vector3.Dot(camTransform.forward, Vector3.forward));

                    Quaternion cameraRotation = Quaternion.AngleAxis(cameraRotationAngle, Vector3.Cross(camTransform.forward, Vector3.forward).normalized);

                    //UNCOMMENT THIS LINE if you would like to constrain the player to just x/z movement.
                    //Quaternion cameraRotation = Quaternion.AngleAxis(camTransform.eulerAngles.y, Vector3.up);


                    float temp;
                    //Movement due to left/right input
                    addedVelocity += new Vector3(0, 0, (temp = -Input.GetAxis("Vertical")) * ACCEL_RATE) * Time.deltaTime;
                    if (temp != 0)
                    {
                        state.keyHit = true;
                    }
                    addedVelocity += new Vector3((temp = -Input.GetAxis("Horizontal")) * ACCEL_RATE, 0, 0) * Time.deltaTime;
                    if (temp != 0)
                    {
                        state.keyHit = true;
                    }

                    //And rotate our added velocity by camera angle
                    addedVelocity = cameraRotation * addedVelocity;

                    //AUTO SLOW DOWN CODE BLOCK

                    //If we are not adding velocity this round to our x direction, slow down
                    if (addedVelocity.x == 0)
                    {
                        addedVelocity += new Vector3(-1 * SLOW_DOWN_RATE * playerVelocityVector.x, 0, 0) * Time.deltaTime;
                    }
                    //If we are not adding velocity this round to our z direction, slow down
                    if (addedVelocity.z == 0)
                    {
                        addedVelocity += new Vector3(0, 0, -1 * SLOW_DOWN_RATE * playerVelocityVector.z) * Time.deltaTime;
                    }
                    //If we are not adding velocity this round to our y direction, slow down
                    if (addedVelocity.y == 0)
                    {
                        addedVelocity += new Vector3(0, -1 * SLOW_DOWN_RATE * playerVelocityVector.y, 0) * Time.deltaTime;
                    }

                    /*
                     * IF you turn on this bit of code, you'll get head bob. It's a fun little effect, but if you make the magnitude of the cosine too large it gets sickening.
                     * if (!double.IsNaN((float)(0.2 * Mathf.Cos((float)GetComponent<GameState>().TotalTimePlayer) * Time.deltaTime)) && frames > 2)
                     * {
                     *  addedVelocity.y += (float)(0.2 * Mathf.Cos((float)GetComponent<GameState>().TotalTimePlayer) * Time.deltaTime);
                     * }
                     */

                    Vector3 totalAccel = Vector3.zero;
                    //Add the velocities here. remember, this is the equation:
                    //vNew = (1/(1+vOld*vAddx/cSqrd))*(Vector3(vAdd.x+vOld.x,vAdd.y/Gamma,vAdd.z/Gamma))
                    if (addedVelocity.sqrMagnitude != 0 || useGravity)
                    {
                        //Rotate our velocity Vector
                        Vector3 rotatedVelocity = rotateX * playerVelocityVector;

                        if (addedVelocity.sqrMagnitude != 0)
                        {
                            //Rotate our added Velocity
                            addedVelocity = rotateX * addedVelocity;

                            //get gamma so we don't have to bother getting it every time
                            float gamma = (float)state.SqrtOneMinusVSquaredCWDividedByCSquared;

                            //Do relativistic velocity addition as described by the above equation.
                            rotatedVelocity = (1 / (1 + (rotatedVelocity.x * addedVelocity.x) / (float)state.SpeedOfLightSqrd)) *
                                              (new Vector3(addedVelocity.x + rotatedVelocity.x, addedVelocity.y * gamma, gamma * addedVelocity.z));
                        }

                        //Unrotate our new total velocity
                        rotatedVelocity = unRotateX * rotatedVelocity;
                        totalAccel      = (addedVelocity / Time.deltaTime);
                        totalAccel      = totalAccel.Gamma() * totalAccel;

                        //Set it, depending on gravity
                        if (!useGravity)
                        {
                            state.PlayerVelocityVector = rotatedVelocity;
                        }
                        else
                        {
                            if (!isFalling)
                            {
                                if (rotatedVelocity.y > 0.0f)
                                {
                                    rotatedVelocity.y = 0.0f;
                                }
                                state.PlayerVelocityVector = rotatedVelocity;
                                totalAccel -= Physics.gravity;
                            }
                            else
                            {
                                state.PlayerVelocityVector = rotatedVelocity.AddVelocity((-Physics.gravity * Time.deltaTime).RapidityToVelocity());
                            }
                        }
                    }

                    state.PlayerAccelerationVector = totalAccel;

                    //CHANGE the speed of light

                    //Get our input axis (DEFAULT N, M) value to determine how much to change the speed of light
                    int temp2 = (int)(Input.GetAxis("Speed of Light"));
                    //If it's too low, don't subtract from the speed of light, and reset the speed of light
                    if (temp2 < 0 && speedOfLightTarget <= state.MaxSpeed)
                    {
                        temp2 = 0;
                        speedOfLightTarget = (int)state.MaxSpeed;
                    }
                    if (temp2 != 0)
                    {
                        speedOfLightTarget += temp2;

                        speedOfLightStep = Mathf.Abs((float)(state.SpeedOfLight - speedOfLightTarget) / 20);
                    }
                    //Now, if we're not at our target, move towards the target speed that we're hoping for
                    if (state.SpeedOfLight < speedOfLightTarget * .995)
                    {
                        //Then we change the speed of light, so that we get a smooth change from one speed of light to the next.
                        state.SpeedOfLight += speedOfLightStep;
                    }
                    else if (state.SpeedOfLight > speedOfLightTarget * 1.005)
                    {
                        //See above
                        state.SpeedOfLight -= speedOfLightStep;
                    }
                    //If we're within a +-.05 distance of our target, just set it to be our target.
                    else if (state.SpeedOfLight != speedOfLightTarget)
                    {
                        state.SpeedOfLight = speedOfLightTarget;
                    }

                    //MOUSE CONTROLS
                    //Current position of the mouse
                    //Difference between last frame's mouse position
                    //X axis position change
                    float positionChangeX = -(float)Input.GetAxis("Mouse X");

                    //Y axis position change
                    float positionChangeY = (float)inverted * Input.GetAxis("Mouse Y");

                    //Use these to determine camera rotation, that is, to look around the world without changing direction of motion
                    //These two are for X axis rotation and Y axis rotation, respectively
                    float viewRotY = 0;
                    if (Mathf.Abs(positionChangeX) <= 1 && Mathf.Abs(positionChangeY) <= 1)
                    {
                        //Take the position changes and translate them into an amount of rotation
                        viewRotX = (float)(-positionChangeX * Time.deltaTime * rotSpeed * mouseSensitivity * controllerBoost);
                        viewRotY = (float)(positionChangeY * Time.deltaTime * rotSpeed * mouseSensitivity * controllerBoost);
                    }
                    else
                    {
                        //Take the position changes and translate them into an amount of rotation
                        viewRotX = (float)(-positionChangeX * Time.deltaTime * rotSpeed * mouseSensitivity);
                        viewRotY = (float)(positionChangeY * Time.deltaTime * rotSpeed * mouseSensitivity);
                    }
                    //Perform Rotation on the camera, so that we can look in places that aren't the direction of movement
                    //Wait some frames on start up, otherwise we spin during the intialization when we can't see yet
                    if (frames > INIT_FRAME_WAIT)
                    {
                        camTransform.Rotate(new Vector3(0, viewRotX, 0), Space.World);
                        if ((camTransform.eulerAngles.x + viewRotY < 90 && camTransform.eulerAngles.x + viewRotY > 90 - 180) || (camTransform.eulerAngles.x + viewRotY > 270 && camTransform.eulerAngles.x + viewRotY < 270 + 180))
                        {
                            camTransform.Rotate(new Vector3(viewRotY, 0, 0));
                        }
                    }
                    else
                    {
                        //keep track of our frames
                        frames++;
                    }

                    //If we have a speed of light less than max speed, fix it.
                    //This should never happen
                    if (state.SpeedOfLight < state.MaxSpeed)
                    {
                        state.SpeedOfLight = state.MaxSpeed;
                    }


                    #endregion

                    //Send current speed of light to the shader
                    Shader.SetGlobalFloat("_spdOfLight", (float)state.SpeedOfLight);

                    if (Camera.main)
                    {
                        Shader.SetGlobalFloat("xyr", (float)Camera.main.pixelWidth / Camera.main.pixelHeight);
                        Shader.SetGlobalFloat("xs", (float)Mathf.Tan(Mathf.Deg2Rad * Camera.main.fieldOfView / 2f));

                        //Don't cull because at high speeds, things come into view that are not visible normally
                        //This is due to the lorenz transformation, which is pretty cool but means that basic culling will not work.
                        Camera.main.layerCullSpherical  = true;
                        Camera.main.useOcclusionCulling = false;
                    }
                }
            }
        }