From ad8af928065a506d0d28f98d51222d7afa1f47e2 Mon Sep 17 00:00:00 2001
From: miepzerino <o.skotnik@gmail.com>
Date: Sat, 05 Apr 2025 14:55:22 +0000
Subject: [PATCH] #47 background rework (static with transitions)

---
 Assets/Scripts/Managers/GameManager.cs |    2 
 Assets/Scenes/GameplayScene.unity      |  118 +++++++++++++++++++++++
 Assets/BackgroundManager.cs            |  121 ++++++++++++++++++++++++
 Assets/BackgroundManager.cs.meta       |   11 ++
 4 files changed, 248 insertions(+), 4 deletions(-)

diff --git a/Assets/BackgroundManager.cs b/Assets/BackgroundManager.cs
new file mode 100644
index 0000000..7679293
--- /dev/null
+++ b/Assets/BackgroundManager.cs
@@ -0,0 +1,121 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class BackgroundManager : MonoBehaviour
+{
+    [System.Serializable]
+    public class BackgroundLayer
+    {
+        public float yThreshold;
+        public Sprite backgroundSprite;
+        [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 float transitionDuration = 1f;
+    private bool isTransitioning = false; // Add this field
+
+    private Transform cameraTransform;
+    private Vector3 lastCameraPosition;
+    private int currentLayerIndex = 0;
+    private float startPositionX;
+
+    private void Start()
+    {
+        cameraTransform = Camera.main.transform;
+        lastCameraPosition = cameraTransform.position;
+        startPositionX = transform.position.x;
+
+        if (spriteRenderer == null)
+            spriteRenderer = GetComponent<SpriteRenderer>();
+
+        // Set initial background
+        if (backgroundLayers != null && backgroundLayers.Length > 0)
+            spriteRenderer.sprite = backgroundLayers[0].backgroundSprite;
+
+        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].backgroundSprite));
+            currentLayerIndex = newLayerIndex;
+        }
+
+        lastCameraPosition = cameraTransform.position;
+    }
+
+    private float GetCurrentParallaxEffect()
+    {
+        if (backgroundLayers == null || backgroundLayers.Length == 0)
+            return 0.5f;
+        return backgroundLayers[currentLayerIndex].parallaxEffect;
+    }
+
+    private IEnumerator TransitionBackground(Sprite newSprite)
+    {
+        if (isTransitioning) yield break;
+        isTransitioning = true;
+
+        // Setup transition renderer
+        transitionRenderer.sprite = newSprite;
+        transitionRenderer.transform.localPosition = Vector3.zero;
+
+        // Fade in new sprite over old one
+        float elapsedTime = 0;
+        while (elapsedTime < transitionDuration)
+        {
+            elapsedTime += Time.deltaTime;
+            float alpha = elapsedTime / transitionDuration;
+            transitionRenderer.color = new Color(1, 1, 1, alpha);
+            yield return null;
+        }
+
+        // Switch the sprites
+        spriteRenderer.sprite = newSprite;
+        transitionRenderer.color = new Color(1, 1, 1, 0);
+
+        isTransitioning = false;
+    }
+}
\ No newline at end of file
diff --git a/Assets/BackgroundManager.cs.meta b/Assets/BackgroundManager.cs.meta
new file mode 100644
index 0000000..2114e3a
--- /dev/null
+++ b/Assets/BackgroundManager.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 718d5e9be0a4bd647adb3ea9fc7cf477
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scenes/GameplayScene.unity b/Assets/Scenes/GameplayScene.unity
index e4a2244..5b06c17 100644
--- a/Assets/Scenes/GameplayScene.unity
+++ b/Assets/Scenes/GameplayScene.unity
@@ -599,7 +599,7 @@
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_AnchorMin: {x: 1, y: 1}
   m_AnchorMax: {x: 1, y: 1}
-  m_AnchoredPosition: {x: 0.000061035156, y: 0}
+  m_AnchoredPosition: {x: 0, y: 0}
   m_SizeDelta: {x: 200, y: 50}
   m_Pivot: {x: 1, y: 1}
 --- !u!222 &456454179
@@ -1860,7 +1860,7 @@
   m_Icon: {fileID: 0}
   m_NavMeshLayer: 0
   m_StaticEditorFlags: 0
-  m_IsActive: 0
+  m_IsActive: 1
 --- !u!4 &796676099
 Transform:
   m_ObjectHideFlags: 0
@@ -1878,6 +1878,7 @@
   - {fileID: 1049982787}
   - {fileID: 2045670860}
   - {fileID: 734382261}
+  - {fileID: 2136420133}
   m_Father: {fileID: 0}
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
 --- !u!1 &808172310
@@ -4057,7 +4058,7 @@
   m_Name: 
   m_EditorClassIdentifier: 
   m_TrackedObjectOffset: {x: 0, y: 0, z: 0}
-  m_LookaheadTime: 0.1
+  m_LookaheadTime: 0
   m_LookaheadSmoothing: 5
   m_LookaheadIgnoreY: 0
   m_XDamping: 0
@@ -5215,6 +5216,113 @@
   hasTopBuddy: 0
   hasBottomBuddy: 0
   reverseScale: 1
+--- !u!1 &2136420132
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2136420133}
+  - component: {fileID: 2136420135}
+  - component: {fileID: 2136420134}
+  m_Layer: 11
+  m_Name: Background
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &2136420133
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2136420132}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: -2}
+  m_LocalScale: {x: 5, y: 5, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 796676099}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!212 &2136420134
+SpriteRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2136420132}
+  m_Enabled: 1
+  m_CastShadows: 0
+  m_ReceiveShadows: 0
+  m_DynamicOccludee: 1
+  m_StaticShadowCaster: 0
+  m_MotionVectors: 1
+  m_LightProbeUsage: 1
+  m_ReflectionProbeUsage: 1
+  m_RayTracingMode: 0
+  m_RayTraceProcedural: 0
+  m_RenderingLayerMask: 1
+  m_RendererPriority: 0
+  m_Materials:
+  - {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
+  m_StaticBatchInfo:
+    firstSubMesh: 0
+    subMeshCount: 0
+  m_StaticBatchRoot: {fileID: 0}
+  m_ProbeAnchor: {fileID: 0}
+  m_LightProbeVolumeOverride: {fileID: 0}
+  m_ScaleInLightmap: 1
+  m_ReceiveGI: 1
+  m_PreserveUVs: 0
+  m_IgnoreNormalsForChartDetection: 0
+  m_ImportantGI: 0
+  m_StitchLightmapSeams: 1
+  m_SelectedEditorRenderState: 0
+  m_MinimumChartSize: 4
+  m_AutoUVMaxDistance: 0.5
+  m_AutoUVMaxAngle: 89
+  m_LightmapParameters: {fileID: 0}
+  m_SortingLayerID: 1963190711
+  m_SortingLayer: -2
+  m_SortingOrder: 0
+  m_Sprite: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_FlipX: 0
+  m_FlipY: 0
+  m_DrawMode: 0
+  m_Size: {x: 1, y: 1}
+  m_AdaptiveModeThreshold: 0.5
+  m_SpriteTileMode: 0
+  m_WasSpriteAssigned: 0
+  m_MaskInteraction: 0
+  m_SpriteSortPoint: 0
+--- !u!114 &2136420135
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2136420132}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 718d5e9be0a4bd647adb3ea9fc7cf477, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  spriteRenderer: {fileID: 2136420134}
+  transitionRenderer: {fileID: 0}
+  backgroundLayers:
+  - yThreshold: -1
+    backgroundSprite: {fileID: 21300000, guid: 7d5be99b0261348468ab492c35422f1b, type: 3}
+    parallaxEffect: 0.439
+  - yThreshold: -300
+    backgroundSprite: {fileID: 21300000, guid: 58a6eeb45a0e2674ab35114433129f28, type: 3}
+    parallaxEffect: 0.482
+  transitionDuration: 1
 --- !u!114 &18669457987763773
 MonoBehaviour:
   m_ObjectHideFlags: 0
@@ -13157,6 +13265,10 @@
       propertyPath: m_Name
       value: BackgroundAll
       objectReference: {fileID: 0}
+    - target: {fileID: 3961525155789603524, guid: bcc4a9d71ad64b340b222e078e04fe7c, type: 3}
+      propertyPath: m_IsActive
+      value: 0
+      objectReference: {fileID: 0}
     - target: {fileID: 6632530311481836413, guid: bcc4a9d71ad64b340b222e078e04fe7c, type: 3}
       propertyPath: m_LocalPosition.x
       value: 0
diff --git a/Assets/Scripts/Managers/GameManager.cs b/Assets/Scripts/Managers/GameManager.cs
index 6bbffac..7f543e9 100644
--- a/Assets/Scripts/Managers/GameManager.cs
+++ b/Assets/Scripts/Managers/GameManager.cs
@@ -92,7 +92,7 @@
         Debug.Log("done async map loading");
         levelChanger.GetComponent<Animator>().SetBool("SceneLoading", false);
         //Initialize background tiles after the tilemap is loaded
-        InitializeBackgroundTiles();
+        //InitializeBackgroundTiles();
         GameLoaded();
     }
     public void GameLoaded()

--
Gitblit v1.9.3