From 575af36b9ec3d3c39ffb027c13c5a9bd0b369f97 Mon Sep 17 00:00:00 2001 From: miepzerino <o.skotnik@gmail.com> Date: Sat, 05 Apr 2025 17:44:41 +0000 Subject: [PATCH] #47 background transition based on y-level --- Assets/BackgroundManager.cs | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 180 insertions(+), 0 deletions(-) diff --git a/Assets/BackgroundManager.cs b/Assets/BackgroundManager.cs new file mode 100644 index 0000000..2722ba7 --- /dev/null +++ b/Assets/BackgroundManager.cs @@ -0,0 +1,180 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class BackgroundManager : MonoBehaviour +{ + [System.Serializable] + public class BackgroundLayer + { + public float yThreshold; + public Sprite backgroundSprite; + public float transitionDistance = 3f; // Distance over which the transition occurs + [Range(0f, 1f)] public float parallaxEffect = 0.5f; + } + + [SerializeField] private SpriteRenderer spriteRenderer; + [SerializeField] private SpriteRenderer transitionRenderer; // Add this field + [SerializeField] private BackgroundLayer[] backgroundLayers; + [SerializeField] private Transform playerTransform; // Add this field + private bool isTransitioning = false; // Add this field + + private Transform cameraTransform; + private Vector3 lastCameraPosition; + private int currentLayerIndex = 0; + private float startPositionX; + + private float lastUpdatePlayerY = 0f; // Track the last Y position of the player + private bool isMovingUp = false; // Track if the player is moving up + + private void Start() + { + cameraTransform = Camera.main.transform; + lastCameraPosition = cameraTransform.position; + + if (spriteRenderer == null) + spriteRenderer = GetComponent<SpriteRenderer>(); + + // Set initial background based on player position + if (backgroundLayers != null && backgroundLayers.Length > 0) + { + float playerY = playerTransform.position.y; + int initialLayerIndex = 0; + + // Find the correct background layer for the player's position + for (int i = 0; i < backgroundLayers.Length; i++) + { + if (playerY > backgroundLayers[i].yThreshold) + { + initialLayerIndex = i; + break; + } + } + + spriteRenderer.sprite = backgroundLayers[initialLayerIndex].backgroundSprite; + currentLayerIndex = initialLayerIndex; + } + + if (transitionRenderer == null) + { + 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 + } + transitionRenderer.color = new Color(1, 1, 1, 0); // Start fully transparent + } + + private void Update() + { + // 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; + + transform.position = newPosition; + + // Check for background change + float currentY = cameraTransform.position.y; + int newLayerIndex = currentLayerIndex; + + for (int i = 0; i < backgroundLayers.Length; i++) + { + if (currentY > backgroundLayers[i].yThreshold) + { + newLayerIndex = i; + break; + } + } + + if (newLayerIndex != currentLayerIndex && !isTransitioning) // Add transition check + { + StartCoroutine(TransitionBackground(backgroundLayers[newLayerIndex])); + currentLayerIndex = newLayerIndex; + } + + lastCameraPosition = cameraTransform.position; + float lastUpdatePlayerYRounded = Mathf.Round(lastUpdatePlayerY * 10) / 10; + float playerYRounded = Mathf.Round(playerTransform.position.y * 10) / 10; + if (lastUpdatePlayerYRounded != playerYRounded) // Check if player has moved + { + if (lastUpdatePlayerYRounded > playerYRounded) // Check if player is moving down + { + isMovingUp = false; + } + else if (lastUpdatePlayerYRounded < playerYRounded) // Check if player is moving up + { + isMovingUp = true; + } + lastUpdatePlayerY = playerYRounded; // Update the last Y position + } + + } + + private float GetCurrentParallaxEffect() + { + if (backgroundLayers == null || backgroundLayers.Length == 0) + return 0.5f; + return backgroundLayers[currentLayerIndex].parallaxEffect; + } + + 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; + isTransitioning = true; + + // Setup transition renderer + transitionRenderer.sprite = newLayer.backgroundSprite; + transitionRenderer.transform.localPosition = Vector3.zero; + + bool initialMovingUp = isMovingUp; // Store the initial moving direction + float initialY = playerTransform.position.y; + //bool movingUp = playerTransform.position.y > initialY; + + // Fade in new sprite over old one + while (true) + { + float currentY = playerTransform.position.y; + + // Check if the direction has changed + if (initialMovingUp != isMovingUp && + ((initialMovingUp ? initialY > currentY : initialY < currentY) + )) + { + transitionRenderer.color = new Color(1, 1, 1, 0); + isTransitioning = false; + yield break; + } + + // Calculate the alpha based on the distance moved + float alpha = Mathf.Abs(currentY - initialY) / newLayer.transitionDistance; + transitionRenderer.color = new Color(1, 1, 1, Mathf.Clamp01(alpha)); + + // Check if transition is complete + if (alpha >= 1f) + break; + + yield return null; + } + + // Ensure the final alpha value is set correctly + transitionRenderer.color = new Color(1, 1, 1, 1); + + // Switch the sprites + spriteRenderer.sprite = newLayer.backgroundSprite; + transitionRenderer.color = new Color(1, 1, 1, 0); + + isTransitioning = false; + } +} -- Gitblit v1.9.3