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;
|
}
|
}
|