From ab5a24f4c0cffbc8e8f76e40293f2201027b7c50 Mon Sep 17 00:00:00 2001 From: miepzerino <o.skotnik@gmail.com> Date: Mon, 07 Apr 2025 22:59:16 +0000 Subject: [PATCH] #49 added parallax and tiling to background --- Assets/BackgroundManager.cs | 203 +++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 166 insertions(+), 37 deletions(-) diff --git a/Assets/BackgroundManager.cs b/Assets/BackgroundManager.cs index 2722ba7..306cac4 100644 --- a/Assets/BackgroundManager.cs +++ b/Assets/BackgroundManager.cs @@ -14,27 +14,40 @@ } [SerializeField] private SpriteRenderer spriteRenderer; - [SerializeField] private SpriteRenderer transitionRenderer; // Add this field [SerializeField] private BackgroundLayer[] backgroundLayers; [SerializeField] private Transform playerTransform; // Add this field + [SerializeField] private float tileBuffer = 1f; // Extra tiles beyond camera view private bool isTransitioning = false; // Add this field private Transform cameraTransform; private Vector3 lastCameraPosition; private int currentLayerIndex = 0; + private int lastLayerIndex = 0; private float startPositionX; + private float startPositionY; private float lastUpdatePlayerY = 0f; // Track the last Y position of the player private bool isMovingUp = false; // Track if the player is moving up + private Dictionary<Vector2Int, SpriteRenderer> backgroundTiles = new Dictionary<Vector2Int, SpriteRenderer>(); + private Dictionary<Vector2Int, SpriteRenderer> transitionTiles = new Dictionary<Vector2Int, SpriteRenderer>(); + private Vector2 tileSize; + private Camera mainCamera; + private void Start() { - cameraTransform = Camera.main.transform; + mainCamera = Camera.main; + cameraTransform = mainCamera.transform; lastCameraPosition = cameraTransform.position; if (spriteRenderer == null) spriteRenderer = GetComponent<SpriteRenderer>(); + if (backgroundLayers != null && backgroundLayers.Length > 0) + { + Sprite firstSprite = backgroundLayers[0].backgroundSprite; + tileSize = new Vector2(firstSprite.bounds.size.x, firstSprite.bounds.size.y); + } // Set initial background based on player position if (backgroundLayers != null && backgroundLayers.Length > 0) { @@ -53,39 +66,77 @@ spriteRenderer.sprite = backgroundLayers[initialLayerIndex].backgroundSprite; currentLayerIndex = initialLayerIndex; + lastLayerIndex = currentLayerIndex; } + InitializeInitialTiles(); - if (transitionRenderer == null) + startPositionX = playerTransform.position.x; + startPositionY = playerTransform.position.y; + } + private void InitializeInitialTiles() + { + // Calculate visible area + float cameraHeight = 2f * mainCamera.orthographicSize; + float cameraWidth = cameraHeight * mainCamera.aspect; + + // Calculate number of tiles needed + int horizontalTiles = Mathf.CeilToInt(cameraWidth / tileSize.x) + 2; + int verticalTiles = Mathf.CeilToInt(cameraHeight / tileSize.y) + 2; + + // Create initial grid of tiles + for (int x = -horizontalTiles; x <= horizontalTiles; x++) { - var transitionObj = new GameObject("TransitionLayer"); - transitionObj.transform.parent = transform; - transitionObj.transform.localPosition = new Vector3(0, 0, -2); // Set Z to -2 - transitionObj.transform.localScale = Vector3.one; // Match scale - transitionRenderer = transitionObj.AddComponent<SpriteRenderer>(); - transitionRenderer.sortingOrder = spriteRenderer.sortingOrder + 1; - transitionRenderer.sortingLayerName = spriteRenderer.sortingLayerName; // Match background layer + for (int y = -verticalTiles; y <= verticalTiles; y++) + { + CreateTile(new Vector2Int(x, y)); + } } - transitionRenderer.color = new Color(1, 1, 1, 0); // Start fully transparent + } + + private void CreateTile(Vector2Int gridPosition) + { + if (backgroundTiles.ContainsKey(gridPosition)) + return; + + GameObject tileObj = new GameObject($"Tile_{gridPosition.x}_{gridPosition.y}"); + tileObj.transform.parent = transform; + + SpriteRenderer tileSR = tileObj.AddComponent<SpriteRenderer>(); + tileSR.sprite = backgroundLayers[currentLayerIndex].backgroundSprite; + tileSR.sortingOrder = spriteRenderer.sortingOrder; + tileSR.sortingLayerName = spriteRenderer.sortingLayerName; + + // Position the tile + Vector3 position = new Vector3( + gridPosition.x * tileSize.x, + gridPosition.y * tileSize.y, + transform.position.z + ); + tileObj.transform.localPosition = position; + tileObj.transform.localScale = Vector3.one; // Match scale + + backgroundTiles.Add(gridPosition, tileSR); } private void Update() { + UpdateTiles(); // Calculate parallax movement Vector3 cameraDelta = cameraTransform.position - lastCameraPosition; Vector3 newPosition = transform.position; - // Update X position with parallax float parallaxX = (cameraTransform.position.x - startPositionX) * GetCurrentParallaxEffect(); newPosition.x = startPositionX + parallaxX; // Update Y position to follow camera - newPosition.y = cameraTransform.position.y; + float parallaxY = (cameraTransform.position.y - startPositionY) * GetCurrentParallaxEffect(); + newPosition.y = startPositionY + parallaxY; transform.position = newPosition; // Check for background change - float currentY = cameraTransform.position.y; + float currentY = playerTransform.position.y; int newLayerIndex = currentLayerIndex; for (int i = 0; i < backgroundLayers.Length; i++) @@ -120,6 +171,57 @@ } } + private void UpdateTiles() + { + // Calculate visible area with buffer + float cameraHeight = 2f * mainCamera.orthographicSize * (1f + tileBuffer); + float cameraWidth = cameraHeight * mainCamera.aspect * (1f + tileBuffer); + + // Calculate parallax offset + float parallaxX = (cameraTransform.position.x - startPositionX) * GetCurrentParallaxEffect(); + float parallaxY = (cameraTransform.position.y - startPositionY) * GetCurrentParallaxEffect(); + + // Calculate grid positions that should be visible + Vector2 cameraPos = mainCamera.transform.position; + + // Adjust the buffer based on parallax effect + float parallaxBuffer = 1f; // Base buffer size + float effectiveBuffer = parallaxBuffer * (1f + GetCurrentParallaxEffect()); + + int minX = Mathf.FloorToInt((parallaxX - (cameraWidth / 2 * effectiveBuffer)) / tileSize.x); + int maxX = Mathf.CeilToInt((parallaxX + (cameraWidth / 2 * effectiveBuffer)) / tileSize.x); + int minY = Mathf.FloorToInt((parallaxY - (cameraHeight / 2 * effectiveBuffer)) / tileSize.y); + int maxY = Mathf.CeilToInt((parallaxY + (cameraHeight / 2 * effectiveBuffer)) / tileSize.y); + + // Create new tiles + for (int x = minX; x <= maxX; x++) + { + for (int y = minY; y <= maxY; y++) + { + CreateTile(new Vector2Int(x, y)); + } + } + + // Remove out-of-view tiles + List<Vector2Int> tilesToRemove = new List<Vector2Int>(); + foreach (var tile in backgroundTiles) + { + if (tile.Key.x < minX - 1 || tile.Key.x > maxX + 1 || + tile.Key.y < minY - 1 || tile.Key.y > maxY + 1) + { + tilesToRemove.Add(tile.Key); + } + } + + foreach (var tilePos in tilesToRemove) + { + if (!transitionTiles.ContainsKey(tilePos)) + { + Destroy(backgroundTiles[tilePos].gameObject); + backgroundTiles.Remove(tilePos); + } + } + } private float GetCurrentParallaxEffect() { @@ -130,51 +232,78 @@ private IEnumerator TransitionBackground(BackgroundLayer newLayer) { - // Check if the transition is already in progress or if the new sprite is the same as the current one - if (isTransitioning || newLayer.backgroundSprite.name == spriteRenderer.sprite.name) yield break; + if (isTransitioning || newLayer.backgroundSprite.name == backgroundLayers[lastLayerIndex].backgroundSprite.name) + yield break; + isTransitioning = true; - - // Setup transition renderer - transitionRenderer.sprite = newLayer.backgroundSprite; - transitionRenderer.transform.localPosition = Vector3.zero; - - bool initialMovingUp = isMovingUp; // Store the initial moving direction + bool initialMovingUp = isMovingUp; float initialY = playerTransform.position.y; - //bool movingUp = playerTransform.position.y > initialY; - // Fade in new sprite over old one + // Create transition renderers for all existing tiles + foreach (var tile in backgroundTiles) + { + GameObject transObj = new GameObject($"TransitionTile_{tile.Key.x}_{tile.Key.y}"); + transObj.transform.parent = transform; + transObj.transform.localPosition = tile.Value.transform.localPosition + new Vector3(0, 0, -0.1f); + transObj.transform.localScale = Vector3.one; + + SpriteRenderer transSR = transObj.AddComponent<SpriteRenderer>(); + transSR.sprite = newLayer.backgroundSprite; + transSR.sortingOrder = tile.Value.sortingOrder + 1; + transSR.sortingLayerName = tile.Value.sortingLayerName; + transSR.color = new Color(1, 1, 1, 0); + + transitionTiles.Add(tile.Key, transSR); + } + + // Fade in new sprites over old ones while (true) { float currentY = playerTransform.position.y; - // Check if the direction has changed - if (initialMovingUp != isMovingUp && - ((initialMovingUp ? initialY > currentY : initialY < currentY) - )) + // Check if direction changed + if (initialMovingUp != isMovingUp && + ((initialMovingUp ? initialY > currentY : initialY < currentY))) { - transitionRenderer.color = new Color(1, 1, 1, 0); + foreach (var transTile in transitionTiles.Values) + { + Destroy(transTile.gameObject); + } + transitionTiles.Clear(); isTransitioning = false; yield break; } - // Calculate the alpha based on the distance moved + // Calculate alpha float alpha = Mathf.Abs(currentY - initialY) / newLayer.transitionDistance; - transitionRenderer.color = new Color(1, 1, 1, Mathf.Clamp01(alpha)); + Color newColor = new Color(1, 1, 1, Mathf.Clamp01(alpha)); - // Check if transition is complete + // Update all transition tiles + foreach (var transTile in transitionTiles.Values) + { + transTile.color = newColor; + } + if (alpha >= 1f) break; yield return null; } - // Ensure the final alpha value is set correctly - transitionRenderer.color = new Color(1, 1, 1, 1); + // Switch sprites on all tiles + foreach (var tile in backgroundTiles.Values) + { + tile.sprite = newLayer.backgroundSprite; + } - // Switch the sprites - spriteRenderer.sprite = newLayer.backgroundSprite; - transitionRenderer.color = new Color(1, 1, 1, 0); + // Cleanup transition tiles + foreach (var transTile in transitionTiles.Values) + { + Destroy(transTile.gameObject); + } + transitionTiles.Clear(); isTransitioning = false; + lastLayerIndex = currentLayerIndex; } } -- Gitblit v1.9.3