miepzerino
2025-04-05 575af36b9ec3d3c39ffb027c13c5a9bd0b369f97
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
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;
    }
}