| | |
| | | [RequireComponent(typeof(SpriteRenderer))] |
| | | public class Tiling : MonoBehaviour |
| | | { |
| | | [System.Serializable] |
| | | public class HeightSpritePair |
| | | { |
| | | public float minHeight; |
| | | public float maxHeight; |
| | | public Sprite sprite; |
| | | } |
| | | |
| | | public int offsetX = 2; |
| | | public int offsetY = 2; |
| | | public HeightSpritePair[] heightSprites; |
| | | |
| | | public bool hasRightBuddy = false; |
| | | public bool hasLeftBuddy = false; |
| | |
| | | private float spriteHeight = 0f; |
| | | private Camera cam; |
| | | private Transform myTransform; |
| | | private SpriteRenderer spriteRenderer; |
| | | |
| | | private void Awake() |
| | | { |
| | | cam = Camera.main; |
| | | myTransform = transform; |
| | | spriteRenderer = GetComponent<SpriteRenderer>(); |
| | | } |
| | | // Start is called before the first frame update |
| | | |
| | | void Start() |
| | | { |
| | | SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>(); |
| | | UpdateSpriteForHeight(); |
| | | spriteWidth = spriteRenderer.sprite.bounds.size.x; |
| | | spriteHeight = spriteRenderer.sprite.bounds.size.y; |
| | | |
| | | //GenerateBackground(); |
| | | } |
| | | |
| | | // Update is called once per frame |
| | | void Update() |
| | | { |
| | | if (CheckOffscreenAndDestroy()) return; // Return early if destroyed |
| | | CheckHorizontalTiling(); |
| | | CheckVerticalTiling(); |
| | | } |
| | | |
| | | private void UpdateSpriteForHeight() |
| | | { |
| | | if (heightSprites == null || heightSprites.Length == 0) return; |
| | | |
| | | float worldY = transform.position.y; |
| | | Sprite oldSprite = spriteRenderer.sprite; |
| | | |
| | | foreach (HeightSpritePair pair in heightSprites) |
| | | { |
| | | if (pair.sprite == null) continue; // Skip invalid sprites |
| | | |
| | | if ((pair.minHeight == 0 && pair.maxHeight == 0) || |
| | | (worldY >= pair.minHeight && worldY <= pair.maxHeight)) |
| | | { |
| | | if (oldSprite != pair.sprite) |
| | | { |
| | | spriteRenderer.sprite = pair.sprite; |
| | | // Update sprite dimensions if sprite changed |
| | | spriteWidth = spriteRenderer.sprite.bounds.size.x; |
| | | spriteHeight = spriteRenderer.sprite.bounds.size.y; |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void CheckHorizontalTiling() |
| | | { |
| | | if (!hasLeftBuddy || !hasRightBuddy) |
| | | { |
| | | float camHorizontalExtend = cam.orthographicSize * Screen.width / Screen.height; |
| | | |
| | | float edgeVisiblePositionRight = (transform.position.x + spriteWidth / 2) - camHorizontalExtend; |
| | | float edgeVisiblePositionLeft = (transform.position.x - spriteWidth / 2) + camHorizontalExtend; |
| | | |
| | | if (cam.transform.position.x >= edgeVisiblePositionRight - offsetX && !hasRightBuddy) |
| | | { |
| | | MakeNewRightOrLeftBuddy(1); |
| | | MakeNewBuddy(1, 0); |
| | | hasRightBuddy = true; |
| | | } |
| | | else if (cam.transform.position.x <= edgeVisiblePositionLeft + offsetX && !hasLeftBuddy) |
| | | { |
| | | MakeNewRightOrLeftBuddy(-1); |
| | | MakeNewBuddy(-1, 0); |
| | | hasLeftBuddy = true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void MakeNewRightOrLeftBuddy(int rightOrLeft) |
| | | private void CheckVerticalTiling() |
| | | { |
| | | Vector3 newPosition = new Vector3(myTransform.position.x + spriteWidth * rightOrLeft, myTransform.position.y, myTransform.position.z); |
| | | if (!hasTopBuddy || !hasBottomBuddy) |
| | | { |
| | | float camVerticalExtend = cam.orthographicSize; |
| | | float edgeVisiblePositionTop = (transform.position.y + spriteHeight / 2) - camVerticalExtend; |
| | | float edgeVisiblePositionBottom = (transform.position.y - spriteHeight / 2) + camVerticalExtend; |
| | | |
| | | if (cam.transform.position.y >= edgeVisiblePositionTop - offsetY && !hasTopBuddy) |
| | | { |
| | | MakeNewBuddy(0, 1); |
| | | hasTopBuddy = true; |
| | | } |
| | | else if (cam.transform.position.y <= edgeVisiblePositionBottom + offsetY && !hasBottomBuddy) |
| | | { |
| | | MakeNewBuddy(0, -1); |
| | | hasBottomBuddy = true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void MakeNewBuddy(int rightOrLeft, int topOrBottom) |
| | | { |
| | | Vector3 newPosition = new Vector3( |
| | | myTransform.position.x + spriteWidth * rightOrLeft, |
| | | myTransform.position.y + spriteHeight * topOrBottom, |
| | | myTransform.position.z |
| | | ); |
| | | |
| | | Transform newBuddy = Instantiate(myTransform, newPosition, myTransform.rotation); |
| | | Tiling buddyTiling = newBuddy.GetComponent<Tiling>(); |
| | | |
| | | if (reverseScale) |
| | | { |
| | | newBuddy.localScale = new Vector3(newBuddy.localScale.x * -1, newBuddy.localScale.y, newBuddy.localScale.z); |
| | | newBuddy.localScale = new Vector3( |
| | | rightOrLeft != 0 ? newBuddy.localScale.x * -1 : newBuddy.localScale.x, |
| | | topOrBottom != 0 ? newBuddy.localScale.y * -1 : newBuddy.localScale.y, |
| | | newBuddy.localScale.z |
| | | ); |
| | | } |
| | | |
| | | newBuddy.parent = myTransform.parent; |
| | | newBuddy.name = myTransform.name; |
| | | |
| | | if (rightOrLeft > 0) |
| | | if (rightOrLeft > 0) buddyTiling.hasLeftBuddy = true; |
| | | else if (rightOrLeft < 0) buddyTiling.hasRightBuddy = true; |
| | | if (topOrBottom > 0) buddyTiling.hasBottomBuddy = true; |
| | | else if (topOrBottom < 0) buddyTiling.hasTopBuddy = true; |
| | | |
| | | buddyTiling.UpdateSpriteForHeight(); |
| | | } |
| | | |
| | | private bool CheckOffscreenAndDestroy() |
| | | { |
| | | newBuddy.GetComponent<Tiling>().hasLeftBuddy = true; |
| | | } |
| | | else if (rightOrLeft < 0) |
| | | Vector3 viewportPosition = cam.WorldToViewportPoint(transform.position); |
| | | float buffer = 1.5f; |
| | | |
| | | if (viewportPosition.x < -buffer || viewportPosition.x > 1 + buffer || |
| | | viewportPosition.y < -buffer || viewportPosition.y > 1 + buffer) |
| | | { |
| | | newBuddy.GetComponent<Tiling>().hasRightBuddy = true; |
| | | NotifyNeighbors(); |
| | | Destroy(gameObject); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | private void NotifyNeighbors() |
| | | { |
| | | // Use a slightly smaller size than the sprite to ensure we only hit immediate neighbors |
| | | Vector2 checkSize = new Vector2(spriteWidth * 0.9f, spriteHeight * 0.9f); |
| | | Vector2 position = transform.position; |
| | | ContactFilter2D filter = new ContactFilter2D().NoFilter(); |
| | | Collider2D[] results = new Collider2D[1]; |
| | | |
| | | // Check each direction using OverlapBox |
| | | // Right neighbor |
| | | if (Physics2D.OverlapBox(position + new Vector2(spriteWidth, 0), |
| | | checkSize, 0f, |
| | | filter, results) > 0) |
| | | { |
| | | Tiling rightTile = results[0].GetComponent<Tiling>(); |
| | | if (rightTile != null) rightTile.hasLeftBuddy = false; |
| | | } |
| | | |
| | | // Left neighbor |
| | | if (Physics2D.OverlapBox(position + new Vector2(-spriteWidth, 0), |
| | | checkSize, 0f, |
| | | filter, results) > 0) |
| | | { |
| | | Tiling leftTile = results[0].GetComponent<Tiling>(); |
| | | if (leftTile != null) leftTile.hasRightBuddy = false; |
| | | } |
| | | |
| | | // Top neighbor |
| | | if (Physics2D.OverlapBox(position + new Vector2(0, spriteHeight), |
| | | checkSize, 0f, |
| | | filter, results) > 0) |
| | | { |
| | | Tiling topTile = results[0].GetComponent<Tiling>(); |
| | | if (topTile != null) topTile.hasBottomBuddy = false; |
| | | } |
| | | |
| | | // Bottom neighbor |
| | | if (Physics2D.OverlapBox(position + new Vector2(0, -spriteHeight), |
| | | checkSize, 0f, |
| | | filter, results) > 0) |
| | | { |
| | | Tiling bottomTile = results[0].GetComponent<Tiling>(); |
| | | if (bottomTile != null) bottomTile.hasTopBuddy = false; |
| | | } |
| | | } |
| | | //private void OnDrawGizmos() |
| | | //{ |
| | | // if (!Application.isPlaying) return; |
| | | |
| | | // Vector2 checkSize = new Vector2(spriteWidth * 0.9f, spriteHeight * 0.9f); |
| | | // Gizmos.color = Color.yellow; |
| | | |
| | | // // Draw detection boxes for each direction |
| | | // Gizmos.DrawWireCube((Vector2)transform.position + new Vector2(spriteWidth, 0), checkSize); |
| | | // Gizmos.DrawWireCube((Vector2)transform.position + new Vector2(-spriteWidth, 0), checkSize); |
| | | // Gizmos.DrawWireCube((Vector2)transform.position + new Vector2(0, spriteHeight), checkSize); |
| | | // Gizmos.DrawWireCube((Vector2)transform.position + new Vector2(0, -spriteHeight), checkSize); |
| | | //} |
| | | } |