// Orient for objects relative to parent public virtual void Orient(PlatformObject parent, Vector3 position, Quaternion rotation) { thisTransform.parent = parent.GetTransform(); Vector3 pos = Vector3.zero; float yAngle = rotation.eulerAngles.y; pos.Set(startPosition.x * Mathf.Cos(yAngle * Mathf.Deg2Rad) + startPosition.z * Mathf.Sin(yAngle * Mathf.Deg2Rad), startPosition.y, -startPosition.x * Mathf.Sin(yAngle * Mathf.Deg2Rad) + startPosition.z * Mathf.Cos(yAngle * Mathf.Deg2Rad)); pos += position; thisTransform.localPosition = parent.GetTransform().InverseTransformPoint(pos); thisTransform.rotation = startRotation; thisTransform.Rotate(0, rotation.eulerAngles.y, 0, Space.World); }
public Vector3 GetTurnOffset() { // add an offset so the character is always in the correct slot after a turn PlatformObject topPlatform = infiniteObjectHistory.GetTopInfiniteObject(ObjectLocation.Center, false) as PlatformObject; Vector3 offset = Vector3.zero; Vector3 position = topPlatform.GetTransform().position; int topPlatformIndex = infiniteObjectHistory.GetLastLocalIndex(ObjectLocation.Center, ObjectType.Platform); Quaternion lookRotation = Quaternion.LookRotation(spawnDirection); offset.x = (position.x + platformStartPosition[topPlatformIndex].x * (spawnDirection.z > 0 ? -1 : 1)) * -Mathf.Cos(lookRotation.eulerAngles.y * Mathf.Deg2Rad) * (spawnDirection.z > 0 ? -1 : 1); offset.z = (position.z + platformStartPosition[topPlatformIndex].x * (spawnDirection.x < 0 ? -1 : 1)) * Mathf.Sin(lookRotation.eulerAngles.y * Mathf.Deg2Rad) * (spawnDirection.x < 0 ? -1 : 1); return(offset); }
// returns true if there is still space on the platform for a collidable object to spawn private void SpawnCollidable(ObjectType objectType, Vector3 position, Vector3 direction, Direction locationDirection, PlatformObject platform, int platformLocalIndex, bool activateImmediately) { int collidablePositions = platform.numCollidables; // can't do anything if the platform doesn't accept any collidable object spawns if (collidablePositions == 0) { return; } Vector3 offset = platformSizes[platformLocalIndex] * 0.1f; float zDelta = platformSizes[platformLocalIndex].z * .8f / (1 + collidablePositions); for (int i = 0; i < collidablePositions; ++i) { if (platform.CanSpawnCollidable(i)) { spawnData.slotPositions = platform.GetSlotsAvailable(); int localIndex = ObjectPool.instance.GetNextObjectIndex(objectType, spawnData); if (localIndex != -1) { CollidableObject collidable = ObjectPool.instance.GetObjectFromPool(localIndex, objectType) as CollidableObject; Quaternion lookRotation = Quaternion.LookRotation(direction); Vector3 spawnSlot = collidable.GetSpawnSlot(platform.GetTransform().right *slotDistance, spawnData.slotPositions); collidable.Orient(platform, position + (offset.z + ((i + 1) * zDelta)) * direction + spawnSlot, lookRotation); if (activateImmediately) { collidable.Activate(); } int objectIndex = ObjectPool.instance.GetObjectIndexFromLocalIndex(localIndex, objectType); ObjectHistory.instance.ObjectSpawned(objectIndex, (offset.z + ((i + 1) * zDelta)), locationDirection, lookRotation.eulerAngles.y, objectType); platform.SpawnCollidable(i); // don't allow any more of the same collidable type if we are forcing a different collidable if (platform.hasDifferentCollidables) { break; } } } } spawnData.slotPositions = 0; }
// Turn left or right public bool Turn(bool rightTurn) { // prevent two turns from occurring really close to each other (for example, to prevent a 180 degree turn) if (Time.time - turnTime < simultaneousTurnPreventionTime) { return(false); } RaycastHit hit; // ensure we are over the correct platform if (Physics.Raycast(thisTransform.position + colliderCenterOffset, -thisTransform.up, out hit, Mathf.Infinity, platformLayer)) { PlatformObject platform = null; bool hasPlatform = (platform = hit.transform.GetComponent <PlatformObject>()) != null || (platform = hit.transform.parent.GetComponent <PlatformObject>()) != null; // update the platform object if (hasPlatform && platform != platformObject) { platformObject = platform; } } bool isAboveTurn = AboveTurn(); // if we are restricting a turn, don't turn unless we are above a turn platform if (restrictTurns && (!isAboveTurn || restrictTurnsToTurnTrigger)) { return(false); } turnTime = Time.time; Vector3 direction = platformObject.GetTransform().right *(rightTurn ? 1 : -1); prevTurnOffset = turnOffset; canUpdatePosition = ObjectGenerator.instance.UpdateSpawnDirection(direction, rightTurn, isAboveTurn, out turnOffset); targetRotation = Quaternion.LookRotation(direction); curveOffset.x = (thisTransform.position.x - (startPosition.x + turnOffset.x)) * Mathf.Abs(Mathf.Sin(targetRotation.eulerAngles.y * Mathf.Deg2Rad)); curveOffset.z = (thisTransform.position.z - (startPosition.z + turnOffset.z)) * Mathf.Abs(Mathf.Cos(targetRotation.eulerAngles.y * Mathf.Deg2Rad)); if (isAboveTurn) { UpdateTargetPosition(targetRotation.eulerAngles.y); } return(true); }
// An object run contains many platforms strung together with collidables: obstacles, power ups, and coins. If spawnObjectRun encounters a turn, // it will spawn the objects in the correct direction public void SpawnObjectRun(bool activateImmediately) { // spawn the center objects InfiniteObject prevPlatform = infiniteObjectHistory.GetTopInfiniteObject(ObjectLocation.Center, false); while ((prevPlatform == null || (Vector3.Scale(prevPlatform.GetTransform().position, spawnDirection)).sqrMagnitude < sqrHorizon) && (turnPlatform[(int)ObjectLocation.Center] == null || turnPlatform[(int)ObjectLocation.Center].straight)) { Vector3 position = Vector3.zero; if (prevPlatform != null) { int prevPlatformIndex = infiniteObjectHistory.GetLastLocalIndex(ObjectLocation.Center, ObjectType.Platform); position = prevPlatform.GetTransform().position - GetPrevPlatformStartPosition(prevPlatform, prevPlatformIndex, spawnDirection) + platformSizes[prevPlatformIndex].z / 2 * spawnDirection + platformSizes[prevPlatformIndex].y * Vector3.up; } PlatformObject platform = SpawnObjects(ObjectLocation.Center, position, spawnDirection, activateImmediately); if (platform == null) { return; } PlatformSpawned(platform, ObjectLocation.Center, spawnDirection, activateImmediately); prevPlatform = infiniteObjectHistory.GetTopInfiniteObject(ObjectLocation.Center, false); if (spawnFullLength) { SpawnObjectRun(activateImmediately); } } // spawn the left and right objects if (turnPlatform[(int)ObjectLocation.Center] != null) { Vector3 turnDirection = turnPlatform[(int)ObjectLocation.Center].GetTransform().right; // spawn the platform and scene objects for the left and right turns for (int i = 0; i < 2; ++i) { ObjectLocation location = (i == 0 ? ObjectLocation.Right : ObjectLocation.Left); bool canSpawn = (location == ObjectLocation.Right && turnPlatform[(int)ObjectLocation.Center].rightTurn) || (location == ObjectLocation.Left && turnPlatform[(int)ObjectLocation.Center].leftTurn); if (canSpawn && turnPlatform[(int)location] == null) { prevPlatform = infiniteObjectHistory.GetTopInfiniteObject(location, false); if (prevPlatform == null || (Vector3.Scale(prevPlatform.GetTransform().position, turnDirection)).sqrMagnitude < sqrHorizon) { infiniteObjectHistory.SetActiveLocation(location); Vector3 position = Vector3.zero; if (prevPlatform != null) { int prevPlatformIndex = infiniteObjectHistory.GetLastLocalIndex(location, ObjectType.Platform); position = prevPlatform.GetTransform().position - GetPrevPlatformStartPosition(prevPlatform, prevPlatformIndex, turnDirection) + platformSizes[prevPlatformIndex].z / 2 * turnDirection + platformSizes[prevPlatformIndex].y * Vector3.up; } else { PlatformObject centerTurn = turnPlatform[(int)ObjectLocation.Center]; int centerTurnIndex = turnIndex[(int)ObjectLocation.Center]; position = centerTurn.GetTransform().position - platformStartPosition[centerTurnIndex].x * turnDirection - Vector3.up * platformStartPosition[centerTurnIndex].y - platformStartPosition[centerTurnIndex].z * spawnDirection + centerTurn.centerOffset.x * turnDirection + centerTurn.centerOffset.z * spawnDirection + platformSizes[centerTurnIndex].y * Vector3.up; } PlatformObject platform = SpawnObjects(location, position, turnDirection, activateImmediately); if (platform == null) { return; } PlatformSpawned(platform, location, turnDirection, activateImmediately); } } turnDirection *= -1; } // reset infiniteObjectHistory.SetActiveLocation(ObjectLocation.Center); } }
// Spawn objects public void SpawnObjects(bool activateImmediately) { // Spawn objects in center direction BasicObject prevPlatform = ObjectHistory.instance.GetTopObject(Direction.Center, IS_PLATFORM); bool isWithinSpawnDistance = prevPlatform == null || Vector3.Scale(prevPlatform.GetTransform().position, spawnDirection).sqrMagnitude < sqrHorizon; bool hasStraightPath = turnPlatform[(int)Direction.Center] == null || (turnPlatform[(int)Direction.Center].isStraight); while (isWithinSpawnDistance && hasStraightPath) { Vector3 position = Vector3.zero; if (prevPlatform != null) { int prevPlatformIndex = ObjectHistory.instance.GetLastLocalIndex(Direction.Center, ObjectType.Platform); position = prevPlatform.GetTransform().position - GetPrevPlatformStartPosition(prevPlatform, prevPlatformIndex, spawnDirection) + platformSizes[prevPlatformIndex].z / 2 * spawnDirection + platformSizes[prevPlatformIndex].y * Vector3.up; } PlatformObject platform = SpawnPlatformAndCollidables(Direction.Center, position, spawnDirection, activateImmediately); if (platform == null) { return; } SpawnSceneForPlatform(platform, Direction.Center, spawnDirection, activateImmediately); prevPlatform = ObjectHistory.instance.GetTopObject(Direction.Center, IS_PLATFORM); // Refresh conditions isWithinSpawnDistance = prevPlatform == null || Vector3.Scale(prevPlatform.GetTransform().position, spawnDirection).sqrMagnitude < sqrHorizon; hasStraightPath = turnPlatform[(int)Direction.Center] == null || turnPlatform[(int)Direction.Center].isStraight; } // Spawn objects in the left and right direction if (turnPlatform[(int)Direction.Center] != null) { Vector3 turnDirection = turnPlatform[(int)Direction.Center].GetTransform().right; // spawn the platform and scene objects for the left and right turns for (int i = 0; i < 2; ++i) { Direction location = (i == 0 ? Direction.Right : Direction.Left); bool canSpawn = (location == Direction.Right && turnPlatform[(int)Direction.Center].isRightTurn) || (location == Direction.Left && turnPlatform[(int)Direction.Center].isLeftTurn); if (canSpawn && turnPlatform[(int)location] == null) { prevPlatform = ObjectHistory.instance.GetTopObject(location, IS_PLATFORM); isWithinSpawnDistance = prevPlatform == null || Vector3.Scale(prevPlatform.GetTransform().position, turnDirection).sqrMagnitude < sqrHorizon; if (isWithinSpawnDistance) { ObjectHistory.instance.SetActiveDirection(location); Vector3 position = Vector3.zero; if (prevPlatform != null) { int prevPlatformIndex = ObjectHistory.instance.GetLastLocalIndex(location, ObjectType.Platform); position = prevPlatform.GetTransform().position - GetPrevPlatformStartPosition(prevPlatform, prevPlatformIndex, turnDirection) + platformSizes[prevPlatformIndex].z / 2 * turnDirection + platformSizes[prevPlatformIndex].y * Vector3.up; } else { PlatformObject centerTurn = turnPlatform[(int)Direction.Center]; int centerTurnIndex = platformTurnIndex[(int)Direction.Center]; position = centerTurn.GetTransform().position - platformStartPositions[centerTurnIndex].x * turnDirection - Vector3.up * platformStartPositions[centerTurnIndex].y - platformStartPositions[centerTurnIndex].z * spawnDirection + centerTurn.centerOffset.x * turnDirection + centerTurn.centerOffset.z * spawnDirection + platformSizes[centerTurnIndex].y * Vector3.up; } PlatformObject platform = SpawnPlatformAndCollidables(location, position, turnDirection, activateImmediately); if (platform == null) { return; } SpawnSceneForPlatform(platform, location, turnDirection, activateImmediately); } } turnDirection *= -1; } // Reset ObjectHistory.instance.SetActiveDirection(Direction.Center); } }
// Turn left or right public bool Turn(bool rightTurn, bool fromInputManager) { // prevent two turns from occurring really close to each other (for example, to prevent a 180 degree turn) if (Time.time - turnTime < simultaneousTurnPreventionTime) { return(false); } RaycastHit hit; // ensure we are over the correct platform if (Physics.Raycast(thisTransform.position + capsuleCollider.center, -thisTransform.up, out hit, Mathf.Infinity, platformLayer)) { PlatformObject platform = null; // update the platform object if (((platform = hit.transform.GetComponent <PlatformObject>()) != null) || ((platform = hit.transform.parent.GetComponent <PlatformObject>()) != null)) { if (platform != platformObject) { platformObject = platform; CheckForCurvedPlatform(); } } } bool isAboveTurn = AbovePlatform(true); // if we are restricting a turn, don't turn unless we are above a turn platform if (restrictTurns && (!isAboveTurn || restrictTurnsToTurnTrigger)) { if (fromInputManager) { turnRequestTime = Time.time; turnRightRequest = rightTurn; return(false); } if (!powerUpManager.IsPowerUpActive(PowerUpTypes.Invincibility) && !powerUpManager.IsPowerUpActive(PowerUpTypes.SpeedIncrease) && !autoTurn && !WithinReviveGracePeriod()) { // turn in the direction that the player swiped rightTurn = turnRightRequest; // don't turn if restrict turns is on and the player hasn't swipped within the grace period time or if the player isn't above a turn platform if (!gameManager.godMode && (Time.time - turnRequestTime > turnGracePeriod || !isAboveTurn)) { return(false); } } } else if (!fromInputManager && !autoTurn && !gameManager.godMode && (!restrictTurns || Time.time - turnRequestTime > turnGracePeriod) && !powerUpManager.IsPowerUpActive(PowerUpTypes.Invincibility) && !powerUpManager.IsPowerUpActive(PowerUpTypes.SpeedIncrease) && !WithinReviveGracePeriod()) { return(false); } turnTime = Time.time; Vector3 direction = platformObject.GetTransform().right *(rightTurn ? 1 : -1); prevTurnOffset = turnOffset; canUpdatePosition = infiniteObjectGenerator.UpdateSpawnDirection(direction, platformObject.curveLength == 0, rightTurn, isAboveTurn, out turnOffset); if (canUpdatePosition && platformObject.curveLength > 0) { followCurve = true; } else { targetRotation = Quaternion.LookRotation(direction); curveOffset.x = (thisTransform.position.x - (startPosition.x + turnOffset.x)) * Mathf.Abs(Mathf.Sin(targetRotation.eulerAngles.y * Mathf.Deg2Rad)); curveOffset.z = (thisTransform.position.z - (startPosition.z + turnOffset.z)) * Mathf.Abs(Mathf.Cos(targetRotation.eulerAngles.y * Mathf.Deg2Rad)); if (isAboveTurn) { UpdateTargetPosition(targetRotation.eulerAngles.y); } } return(true); }