miepzerino
2025-04-07 ab5a24f4c0cffbc8e8f76e40293f2201027b7c50
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();
        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++)
        {
            for (int y = -verticalTiles; y <= verticalTiles; y++)
            {
                CreateTile(new Vector2Int(x, y));
            }
        }
        }
        if (transitionRenderer == null)
    private void CreateTile(Vector2Int gridPosition)
        {
            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
        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
            // Check if direction changed
            if (initialMovingUp != isMovingUp && 
                ((initialMovingUp ? initialY > currentY : initialY < currentY)
                ))
                ((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;
    }
}