/// <summary> /// Creates a new instance of this object for the object pool. /// </summary> /// <param name="active">if set to <c>true</c> [active].</param> /// <returns>OSPObject.</returns> public OSPObject CreateNewInstance(bool active) { OSPObject newObject = Instantiate(this); newObject.ObjectID = ObjectID; newObject.transform.parent = transform.parent; newObject.transform.localScale = transform.localScale; newObject.ParallaxScalar = ParallaxScalar; newObject.LeftTile = null; newObject.RightTile = null; newObject.TopTile = null; newObject.BottomTile = null; newObject.gameObject.SetActive(active); return(newObject); }
/// <summary> /// Returns the first inactive object in the pool. /// If this pool is allowed to grow, it will create a new object if no inactive ones are found. /// </summary> /// <returns>OSPObject.</returns> public OSPObject GetPooledObject() { for (int i = 0; i < Pool.Count; ++i) { if (!Pool[i].gameObject.activeInHierarchy) { return(Pool[i]); } } if (CanGrow) { OSPObject newObject = PooledObject.CreateNewInstance(true); TempPool.Add(newObject); return(newObject); } return(null); }
/// <summary> /// Gets the normalized parallax scalar for the layer using the distance from the camera to the furthest object's Z position /// to keep the movements all related to one another. This way, no matter where you are on the Z axis with your camera, we'll get /// consistent movement of the layers. /// </summary> /// <param name="obj">The object layer.</param> /// <returns>System.Single.</returns> float GetParallaxScalar(OSPObject obj) { // Find the Z distance between the camera and the parallax layer float distanceToCamera = Mathf.Abs(obj.transform.position.z - MainCamera.transform.position.z); float parallaxScalar; // If the camera is behind the camera somehow, and you're somehow rendering that, set the ratio to be > 1 // Otherwise, set the ratio for movement to be under one if (MainCamera.transform.position.z > obj.transform.position.z) { parallaxScalar = ((maxZ + distanceToCamera) / maxZ); } else { parallaxScalar = Mathf.Abs((maxZ - distanceToCamera) / maxZ); } return(parallaxScalar); }
/// <summary> /// Initializes a new instance of the <see cref="OSPPool"/> class. /// This initializes any lists and adds an amount equal to the InitialSize variable to the pool. /// </summary> /// <param name="pooledObject">The pooled object.</param> public OSPPool(OSPObject pooledObject) { PooledObject = pooledObject; ObjectID = pooledObject.ObjectID; InitialSize = pooledObject.PoolAmount; if (InitialSize < 1) { InitialSize = 1; } TempPool = new List <OSPObject>(); Pool = new List <OSPObject>(); Pool.Add(PooledObject); for (int i = 0; i < (InitialSize - 1); ++i) { OSPObject newObject = PooledObject.CreateNewInstance(false); Pool.Add(newObject); } }
/// <summary> /// Applies parallax movement to a layer. /// </summary> /// <param name="obj">The parallax object.</param> void ApplyParallax(OSPObject obj) { // Find out how much the camera has moved since the last frame Vector3 cameraDelta = MainCamera.transform.position - prevCameraPosition; // Calculate how much this layer should move on the X and Y axis and add it to the variables holding the new position offsets float parallaxX = (cameraDelta.x - (cameraDelta.x * obj.ParallaxScalar)) * obj.ParallaxSmoothingX * ParallaxSmoothingX; float parallaxY = (cameraDelta.y - (cameraDelta.y * obj.ParallaxScalar)) * obj.ParallaxSmoothingY * ParallaxSmoothingY; float addedX = 0; if (obj.UseParallaxOnXAxis) { addedX = parallaxX; } float addedY = 0; if (obj.UseParallaxOnYAxis) { addedY = parallaxY; } // If the object moves, add that to the offset as well // Dividing by ten normalizes the movement so you don't have to have numbers like 0.01 since 1 would be very fast otherwise if (obj.AutoMoveX) { addedX += obj.HorizontalSpeed / 10; } if (obj.AutoMoveY) { addedY += obj.VerticalSpeed / 10; } Vector3 addedPos = new Vector3(addedX, addedY, 0); obj.transform.position += addedPos; }
/// <summary> /// Sets the left, right, top, and bottom tiles for this new tile if any are found. /// Doing this on creation saves us numerous checks in the main parallax loop when we check if a neighbor exists. /// </summary> /// <param name="tile">The tile.</param> public void SetSiblings(OSPObject tile) { #region Left and Right siblings if (tile.AutoTileX) { if (Pool.Any(o => o.row == tile.row && o.col == (tile.col + 1) && o.gameObject.activeInHierarchy)) { var rightTile = Pool.Single(o => o.row == tile.row && o.col == (tile.col + 1) && o.gameObject.activeInHierarchy); rightTile.LeftTile = tile; tile.RightTile = rightTile; } else if (TempPool.Any(o => o.row == tile.row && o.col == (tile.col + 1) && o.gameObject.activeInHierarchy)) { var rightTile = TempPool.Single(o => o.row == tile.row && o.col == (tile.col + 1) && o.gameObject.activeInHierarchy); rightTile.LeftTile = tile; tile.RightTile = rightTile; } else { tile.RightTile = null; } if (Pool.Any(o => o.row == tile.row && o.col == (tile.col - 1) && o.gameObject.activeInHierarchy)) { var leftTile = Pool.Single(o => o.row == tile.row && o.col == (tile.col - 1) && o.gameObject.activeInHierarchy); leftTile.RightTile = tile; tile.LeftTile = leftTile; } else if (TempPool.Any(o => o.row == tile.row && o.col == (tile.col - 1) && o.gameObject.activeInHierarchy)) { var leftTile = TempPool.Single(o => o.row == tile.row && o.col == (tile.col - 1) && o.gameObject.activeInHierarchy); leftTile.RightTile = tile; tile.LeftTile = leftTile; } else { tile.LeftTile = null; } } else { tile.RightTile = null; tile.LeftTile = null; } #endregion #region Top and Bottom siblings if (tile.AutoTileY) { if (Pool.Any(o => o.row == (tile.row + 1) && o.col == tile.col && o.gameObject.activeInHierarchy)) { var bottomTile = Pool.Single(o => o.row == (tile.row + 1) && o.col == tile.col && o.gameObject.activeInHierarchy); bottomTile.TopTile = tile; tile.BottomTile = bottomTile; } else if (TempPool.Any(o => o.row == (tile.row + 1) && o.col == tile.col && o.gameObject.activeInHierarchy)) { var bottomTile = TempPool.Single(o => o.row == (tile.row + 1) && o.col == tile.col && o.gameObject.activeInHierarchy); bottomTile.TopTile = tile; tile.BottomTile = bottomTile; } else { tile.BottomTile = null; } if (Pool.Any(o => o.row == (tile.row - 1) && o.col == tile.col && o.gameObject.activeInHierarchy)) { var topTile = Pool.Single(o => o.row == (tile.row - 1) && o.col == tile.col && o.gameObject.activeInHierarchy); topTile.BottomTile = tile; tile.TopTile = topTile; } else if (TempPool.Any(o => o.row == (tile.row - 1) && o.col == tile.col && o.gameObject.activeInHierarchy)) { var topTile = TempPool.Single(o => o.row == (tile.row - 1) && o.col == tile.col && o.gameObject.activeInHierarchy); topTile.BottomTile = tile; tile.TopTile = topTile; } else { tile.TopTile = null; } } else { tile.TopTile = null; tile.BottomTile = null; } #endregion }
/// <summary> /// Creates a new tile in the given direction. /// </summary> /// <param name="tile">The parallax tile object.</param> /// <param name="direction">The direction we're creating a new tile in.</param> /// <param name="historyList">The history list for that layer.</param> void CreateNewTile(OSPObject tile, TileDirection direction, OSPRandomHistory historyList) { // Grab the object pool for this layer OSPPool pool = ParallaxPools.SingleOrDefault(p => p.ObjectID == tile.ObjectID); // Sometimes, a large image will have a slight gap that shows up on camera movement. This isn't the best fix, but it works. float gapOffset = 0.05f; // Figure out the scale of the sprite so we can figure out how far to move it in order to tile float spriteScaleX = tile.transform.localScale.x; if (tile.transform.parent != null) { spriteScaleX *= tile.transform.parent.localScale.x; } float spriteScaleY = tile.transform.localScale.y; if (tile.transform.parent != null) { spriteScaleY *= tile.transform.parent.localScale.y; } if (direction == TileDirection.LEFT || direction == TileDirection.RIGHT) { #region Left/Right Tiles float posOffset = (tile.SpriteWidth * (direction == TileDirection.LEFT ? -1 : 1) * spriteScaleX); gapOffset *= direction == TileDirection.LEFT ? 1 : -1; Vector3 newPosition = new Vector3( tile.transform.position.x + posOffset + gapOffset, tile.transform.position.y, tile.transform.position.z); if (direction == TileDirection.RIGHT) { // If we're randomizing the horizontal distance, get the offset and add it to the position if (tile.RandomizeHorizontalDistance) { newPosition.x += historyList.GetXOffsetForColumn(tile.col, tile.UseRandomHistory); // If we're randomizing the Y offset, get the offset and add it to the position if (tile.RandomizeHorizontalYAxis) { newPosition.y += historyList.GetYOffsetForColumn(tile.col, tile.UseRandomHistory); } } else { newPosition.x += tile.HorizontalDistance; } } else if (direction == TileDirection.LEFT) { // If we're randomizing the horizontal distance, get the offset and add it to the position if (tile.RandomizeHorizontalDistance) { newPosition.x -= historyList.GetXOffsetForColumn(tile.col - 1, tile.UseRandomHistory); // If we're randomizing the Y offset, get the offset and add it to the position if (tile.RandomizeHorizontalYAxis) { newPosition.y += historyList.GetYOffsetForColumn(tile.col - 1, tile.UseRandomHistory); } } else { newPosition.x -= tile.HorizontalDistance; } } // Get the new tile from the object pool. Abandon ship if it couldn't get a tile. var newTile = pool.GetPooledObject(); if (newTile == null) { return; } newTile.transform.position = newPosition; newTile.transform.rotation = tile.transform.rotation; // Set the new column for this tile if (direction == TileDirection.RIGHT) { newTile.row = tile.row; newTile.col = tile.col + 1; } else { newTile.row = tile.row; newTile.col = tile.col - 1; } // Set the left, right, top, and bottom tiles that connect to this one pool.SetSiblings(newTile); // Now that we're in position, set this tile active newTile.gameObject.SetActive(true); #endregion } else { #region Up/Down Tiles float posOffset = (tile.SpriteHeight * (direction == TileDirection.DOWN ? -1 : 1) * spriteScaleY); gapOffset *= direction == TileDirection.DOWN ? 1 : -1; Vector3 newPosition = new Vector3( tile.transform.position.x, tile.transform.position.y + posOffset + gapOffset, tile.transform.position.z); if (direction == TileDirection.UP) { // If we're randomizing the vertical distance, get the offset and add it to the position if (tile.RandomizeVerticalDistance) { newPosition.y += historyList.GetYOffsetForRow(tile.row, tile.UseRandomHistory); // If we're randomizing the X offset, get the offset and add it to the position if (tile.RandomizeVerticalXAxis) { newPosition.x += historyList.GetXOffsetForRow(tile.row, tile.UseRandomHistory); } } else { newPosition.y += tile.VerticalDistance; } } else if (direction == TileDirection.DOWN) { // If we're randomizing the vertical distance, get the offset and add it to the position if (tile.RandomizeVerticalDistance) { newPosition.y -= historyList.GetYOffsetForRow(tile.row - 1, tile.UseRandomHistory); // If we're randomizing the X offset, get the offset and add it to the position if (tile.RandomizeVerticalXAxis) { newPosition.x += historyList.GetXOffsetForRow(tile.row - 1, tile.UseRandomHistory); } } else { newPosition.y -= tile.VerticalDistance; } } // Get the new tile from the object pool. Abandon ship if it couldn't get a tile. var newTile = pool.GetPooledObject(); if (newTile == null) { return; } newTile.transform.position = newPosition; newTile.transform.rotation = tile.transform.rotation; // Set the new row for this tile if (direction == TileDirection.DOWN) { newTile.row = tile.row + 1; newTile.col = tile.col; } else { newTile.row = tile.row - 1; newTile.col = tile.col; } // Set the left, right, top, and bottom tiles that connect to this one pool.SetSiblings(newTile); // Now that we're in position, set this tile active newTile.gameObject.SetActive(true); #endregion } }