diff --git a/Assets/Art/Sprites/WallTiles/WallTIle_1.prefab b/Assets/Art/Sprites/WallTiles/WallTIle_1.prefab
new file mode 100644
index 00000000..bb8d0cb4
--- /dev/null
+++ b/Assets/Art/Sprites/WallTiles/WallTIle_1.prefab
@@ -0,0 +1,209 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &864595161669782950
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 7111145574660306503}
+ - component: {fileID: 3889795708575321074}
+ m_Layer: 0
+ m_Name: Left_Tile2_0
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &7111145574660306503
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 864595161669782950}
+ serializedVersion: 2
+ m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+ m_LocalPosition: {x: -2.77, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 4925660644986369589}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!212 &3889795708575321074
+SpriteRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 864595161669782950}
+ 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_RayTracingAccelStructBuildFlagsOverride: 0
+ m_RayTracingAccelStructBuildFlags: 1
+ m_SmallMeshCulling: 1
+ 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: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+ m_Sprite: {fileID: 7559449286846427561, guid: e3d18475ab86b1246912f497417465f8, type: 3}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_FlipX: 0
+ m_FlipY: 0
+ m_DrawMode: 0
+ m_Size: {x: 2.37, y: 5}
+ m_AdaptiveModeThreshold: 0.5
+ m_SpriteTileMode: 0
+ m_WasSpriteAssigned: 1
+ m_MaskInteraction: 0
+ m_SpriteSortPoint: 0
+--- !u!1 &2171518497100337372
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1003080013996268193}
+ - component: {fileID: 4856205316150460481}
+ m_Layer: 0
+ m_Name: Right_Tile1_0
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &1003080013996268193
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2171518497100337372}
+ serializedVersion: 2
+ m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+ m_LocalPosition: {x: 2.95, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 4925660644986369589}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!212 &4856205316150460481
+SpriteRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2171518497100337372}
+ 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_RayTracingAccelStructBuildFlagsOverride: 0
+ m_RayTracingAccelStructBuildFlags: 1
+ m_SmallMeshCulling: 1
+ 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: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+ m_Sprite: {fileID: 3241551651087908563, guid: 8e7c95ebe5325df4395d97ea2ace65d7, type: 3}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_FlipX: 0
+ m_FlipY: 0
+ m_DrawMode: 0
+ m_Size: {x: 2.65, y: 5}
+ m_AdaptiveModeThreshold: 0.5
+ m_SpriteTileMode: 0
+ m_WasSpriteAssigned: 1
+ m_MaskInteraction: 0
+ m_SpriteSortPoint: 0
+--- !u!1 &2956826569642009690
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 4925660644986369589}
+ m_Layer: 0
+ m_Name: WallTIle_1
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &4925660644986369589
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2956826569642009690}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children:
+ - {fileID: 7111145574660306503}
+ - {fileID: 1003080013996268193}
+ m_Father: {fileID: 0}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
diff --git a/Assets/Scripts/BubbleS.meta b/Assets/Art/Sprites/WallTiles/WallTIle_1.prefab.meta
similarity index 57%
rename from Assets/Scripts/BubbleS.meta
rename to Assets/Art/Sprites/WallTiles/WallTIle_1.prefab.meta
index 286a34e8..7c644dde 100644
--- a/Assets/Scripts/BubbleS.meta
+++ b/Assets/Art/Sprites/WallTiles/WallTIle_1.prefab.meta
@@ -1,7 +1,6 @@
fileFormatVersion: 2
-guid: bcdb9a3fdaba40459aa46e01c956b531
-folderAsset: yes
-DefaultImporter:
+guid: 661c5018e2409034d92de025b7ac57b7
+PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
diff --git a/Assets/Scenes/MiniGames/DivingForPictures.unity b/Assets/Scenes/MiniGames/DivingForPictures.unity
index 9e948800..304c481f 100644
--- a/Assets/Scenes/MiniGames/DivingForPictures.unity
+++ b/Assets/Scenes/MiniGames/DivingForPictures.unity
@@ -1376,6 +1376,63 @@ MonoBehaviour:
verticalAmplitude: 0.5
velocitySmoothing: 10
rotationSmoothing: 10
+--- !u!1001 &5196505482686956487
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ serializedVersion: 3
+ m_TransformParent: {fileID: 0}
+ m_Modifications:
+ - target: {fileID: 2956826569642009690, guid: 661c5018e2409034d92de025b7ac57b7, type: 3}
+ propertyPath: m_Name
+ value: GameObject
+ objectReference: {fileID: 0}
+ - target: {fileID: 4925660644986369589, guid: 661c5018e2409034d92de025b7ac57b7, type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 4925660644986369589, guid: 661c5018e2409034d92de025b7ac57b7, type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 4925660644986369589, guid: 661c5018e2409034d92de025b7ac57b7, type: 3}
+ propertyPath: m_LocalPosition.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 4925660644986369589, guid: 661c5018e2409034d92de025b7ac57b7, type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 4925660644986369589, guid: 661c5018e2409034d92de025b7ac57b7, type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 4925660644986369589, guid: 661c5018e2409034d92de025b7ac57b7, type: 3}
+ propertyPath: m_LocalRotation.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 4925660644986369589, guid: 661c5018e2409034d92de025b7ac57b7, type: 3}
+ propertyPath: m_LocalRotation.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 4925660644986369589, guid: 661c5018e2409034d92de025b7ac57b7, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 4925660644986369589, guid: 661c5018e2409034d92de025b7ac57b7, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 4925660644986369589, guid: 661c5018e2409034d92de025b7ac57b7, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ m_RemovedComponents: []
+ m_RemovedGameObjects: []
+ m_AddedGameObjects: []
+ m_AddedComponents: []
+ m_SourcePrefab: {fileID: 100100000, guid: 661c5018e2409034d92de025b7ac57b7, type: 3}
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
@@ -1385,3 +1442,4 @@ SceneRoots:
- {fileID: 747976397}
- {fileID: 1003335105}
- {fileID: 2106431002}
+ - {fileID: 5196505482686956487}
diff --git a/Assets/Scripts/BubbleS/Bubble.cs b/Assets/Scripts/BubbleS/Bubble.cs
deleted file mode 100644
index 9464caf1..00000000
--- a/Assets/Scripts/BubbleS/Bubble.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-using UnityEngine;
-
-///
-/// Represents a single bubble, handling its movement, wobble effect, scaling, and sprite assignment.
-///
-public class Bubble : MonoBehaviour
-{
- public float speed = 1f;
- public float wobbleSpeed = 1f;
- private SpriteRenderer spriteRenderer;
- private SpriteRenderer bottleSpriteRenderer;
- private float timeOffset;
- private float minScale = 0.2f;
- private float maxScale = 1.2f;
-
- void Awake()
- {
- // Cache references and randomize time offset for wobble
- spriteRenderer = GetComponent();
- timeOffset = Random.value * 100f;
- // Find the child named "BottleSprite" and get its SpriteRenderer
- Transform bottleSpriteTransform = transform.Find("BubbleSprite");
- if (bottleSpriteTransform != null)
- {
- bottleSpriteRenderer = bottleSpriteTransform.GetComponent();
- }
- }
-
- void Update()
- {
- // Move bubble upward
- transform.position += Vector3.up * speed * Time.deltaTime;
- // Wobble effect (smooth oscillation between min and max scale)
- float t = (Mathf.Sin((Time.time + timeOffset) * wobbleSpeed) + 1f) * 0.5f; // t in [0,1]
- float newScale = Mathf.Lerp(minScale, maxScale, t);
- transform.localScale = Vector3.one * newScale;
- // Destroy when off screen
- if (transform.position.y > Camera.main.orthographicSize + 2f)
- {
- Destroy(gameObject);
- }
- }
-
- ///
- /// Sets the main sprite for the bubble.
- ///
- /// Sprite to assign.
- public void SetSprite(Sprite sprite)
- {
- if (spriteRenderer != null)
- spriteRenderer.sprite = sprite;
- }
-
- ///
- /// Sets the sprite for the child "BottleSprite" renderer.
- ///
- /// Sprite to assign.
- public void SetBottleSprite(Sprite sprite)
- {
- if (bottleSpriteRenderer != null)
- bottleSpriteRenderer.sprite = sprite;
- }
-
- ///
- /// Sets the minimum and maximum scale for the wobble effect.
- ///
- /// Minimum scale.
- /// Maximum scale.
- public void SetWobbleScaleLimits(float min, float max)
- {
- minScale = min;
- maxScale = max;
- }
-}
diff --git a/Assets/Scripts/BubbleS/BubbleSpawner.cs b/Assets/Scripts/BubbleS/BubbleSpawner.cs
deleted file mode 100644
index 6268b58b..00000000
--- a/Assets/Scripts/BubbleS/BubbleSpawner.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-using UnityEngine;
-
-///
-/// Spawns bubbles at intervals, randomizing their properties and assigning a random sprite to each.
-///
-public class BubbleSpawner : MonoBehaviour
-{
- public Bubble bubblePrefab;
- public Sprite[] bubbleSprites; // Assign in inspector
- public float spawnInterval = 0.3f;
- public Vector2 speedRange = new Vector2(0.5f, 2f);
- public Vector2 scaleRange = new Vector2(0.3f, 0.7f);
- public Vector2 wobbleSpeedRange = new Vector2(1f, 3f);
- public Vector2 wobbleAmountRange = new Vector2(0.05f, 0.15f);
- public float spawnXMin = -3.5f;
- public float spawnXMax = 3.5f;
- public float spawnY = -5f;
- public float wobbleMinScale = 0.2f;
- public float wobbleMaxScale = 1.2f;
-
- private float timer;
- private float nextSpawnInterval;
-
- void Start()
- {
- // Initialize the next spawn interval
- nextSpawnInterval = GetRandomizedInterval();
- }
-
- void Update()
- {
- timer += Time.deltaTime;
- if (timer >= nextSpawnInterval)
- {
- SpawnBubble();
- timer = 0f;
- nextSpawnInterval = GetRandomizedInterval();
- }
- }
-
- ///
- /// Returns a randomized interval for bubble spawning.
- ///
- /// Randomized interval in seconds.
- float GetRandomizedInterval()
- {
- return spawnInterval * Random.Range(0.8f, 1.2f);
- }
-
- ///
- /// Spawns a bubble with randomized properties and assigns a random sprite.
- ///
- void SpawnBubble()
- {
- float x = Random.Range(spawnXMin, spawnXMax);
- Vector3 spawnPos = new Vector3(x, spawnY, 0f);
- Bubble bubble = Instantiate(bubblePrefab, spawnPos, Quaternion.identity, transform);
- // Randomize bubble properties
- bubble.speed = Random.Range(speedRange.x, speedRange.y);
- bubble.wobbleSpeed = Random.Range(wobbleSpeedRange.x, wobbleSpeedRange.y);
- float scale = Random.Range(scaleRange.x, scaleRange.y);
- bubble.transform.localScale = Vector3.one * scale;
- // Assign random sprite to BottleSprite
- if (bubbleSprites != null && bubbleSprites.Length > 0)
- {
- Sprite randomSprite = bubbleSprites[Random.Range(0, bubbleSprites.Length)];
- bubble.SetBottleSprite(randomSprite);
- }
- // Random rotation
- bubble.transform.rotation = Quaternion.Euler(0f, 0f, Random.Range(0f, 360f));
- // Pass min/max scale for wobble clamping
- bubble.SetWobbleScaleLimits(wobbleMinScale, wobbleMaxScale);
- }
-}
diff --git a/Assets/Scripts/Minigames.meta b/Assets/Scripts/Minigames.meta
new file mode 100644
index 00000000..e64dc066
--- /dev/null
+++ b/Assets/Scripts/Minigames.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 966ee51822984f3c9eb370193d98ab17
+timeCreated: 1757488369
\ No newline at end of file
diff --git a/Assets/Scripts/Minigames/DivingForPictures.meta b/Assets/Scripts/Minigames/DivingForPictures.meta
new file mode 100644
index 00000000..5012b54b
--- /dev/null
+++ b/Assets/Scripts/Minigames/DivingForPictures.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 59dcc6f7af2c4e49a06f26fab743e664
+timeCreated: 1757488376
\ No newline at end of file
diff --git a/Assets/Scripts/Minigames/DivingForPictures/Bubble.cs b/Assets/Scripts/Minigames/DivingForPictures/Bubble.cs
new file mode 100644
index 00000000..a84c4907
--- /dev/null
+++ b/Assets/Scripts/Minigames/DivingForPictures/Bubble.cs
@@ -0,0 +1,77 @@
+using UnityEngine;
+
+namespace Minigames.DivingForPictures
+{
+ ///
+ /// Represents a single bubble, handling its movement, wobble effect, scaling, and sprite assignment.
+ ///
+ public class Bubble : MonoBehaviour
+ {
+ public float speed = 1f;
+ public float wobbleSpeed = 1f;
+ private SpriteRenderer spriteRenderer;
+ private SpriteRenderer bottleSpriteRenderer;
+ private float timeOffset;
+ private float minScale = 0.2f;
+ private float maxScale = 1.2f;
+
+ void Awake()
+ {
+ // Cache references and randomize time offset for wobble
+ spriteRenderer = GetComponent();
+ timeOffset = Random.value * 100f;
+ // Find the child named "BottleSprite" and get its SpriteRenderer
+ Transform bottleSpriteTransform = transform.Find("BubbleSprite");
+ if (bottleSpriteTransform != null)
+ {
+ bottleSpriteRenderer = bottleSpriteTransform.GetComponent();
+ }
+ }
+
+ void Update()
+ {
+ // Move bubble upward
+ transform.position += Vector3.up * speed * Time.deltaTime;
+ // Wobble effect (smooth oscillation between min and max scale)
+ float t = (Mathf.Sin((Time.time + timeOffset) * wobbleSpeed) + 1f) * 0.5f; // t in [0,1]
+ float newScale = Mathf.Lerp(minScale, maxScale, t);
+ transform.localScale = Vector3.one * newScale;
+ // Destroy when off screen
+ if (transform.position.y > Camera.main.orthographicSize + 2f)
+ {
+ Destroy(gameObject);
+ }
+ }
+
+ ///
+ /// Sets the main sprite for the bubble.
+ ///
+ /// Sprite to assign.
+ public void SetSprite(Sprite sprite)
+ {
+ if (spriteRenderer != null)
+ spriteRenderer.sprite = sprite;
+ }
+
+ ///
+ /// Sets the sprite for the child "BottleSprite" renderer.
+ ///
+ /// Sprite to assign.
+ public void SetBottleSprite(Sprite sprite)
+ {
+ if (bottleSpriteRenderer != null)
+ bottleSpriteRenderer.sprite = sprite;
+ }
+
+ ///
+ /// Sets the minimum and maximum scale for the wobble effect.
+ ///
+ /// Minimum scale.
+ /// Maximum scale.
+ public void SetWobbleScaleLimits(float min, float max)
+ {
+ minScale = min;
+ maxScale = max;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/BubbleS/Bubble.cs.meta b/Assets/Scripts/Minigames/DivingForPictures/Bubble.cs.meta
similarity index 100%
rename from Assets/Scripts/BubbleS/Bubble.cs.meta
rename to Assets/Scripts/Minigames/DivingForPictures/Bubble.cs.meta
diff --git a/Assets/Scripts/Minigames/DivingForPictures/BubbleSpawner.cs b/Assets/Scripts/Minigames/DivingForPictures/BubbleSpawner.cs
new file mode 100644
index 00000000..5ad09d36
--- /dev/null
+++ b/Assets/Scripts/Minigames/DivingForPictures/BubbleSpawner.cs
@@ -0,0 +1,78 @@
+using UnityEngine;
+
+namespace Minigames.DivingForPictures
+{
+ ///
+ /// Spawns bubbles at intervals, randomizing their properties and assigning a random sprite to each.
+ ///
+ public class BubbleSpawner : MonoBehaviour
+ {
+ public Bubble bubblePrefab;
+ public Sprite[] bubbleSprites; // Assign in inspector
+ public float spawnInterval = 0.3f;
+ public Vector2 speedRange = new Vector2(0.5f, 2f);
+ public Vector2 scaleRange = new Vector2(0.3f, 0.7f);
+ public Vector2 wobbleSpeedRange = new Vector2(1f, 3f);
+ public Vector2 wobbleAmountRange = new Vector2(0.05f, 0.15f);
+ public float spawnXMin = -3.5f;
+ public float spawnXMax = 3.5f;
+ public float spawnY = -5f;
+ public float wobbleMinScale = 0.2f;
+ public float wobbleMaxScale = 1.2f;
+
+ private float _timer;
+ private float _nextSpawnInterval;
+
+ void Start()
+ {
+ // Initialize the next spawn interval
+ _nextSpawnInterval = GetRandomizedInterval();
+ }
+
+ void Update()
+ {
+ _timer += Time.deltaTime;
+ if (_timer >= _nextSpawnInterval)
+ {
+ SpawnBubble();
+ _timer = 0f;
+ _nextSpawnInterval = GetRandomizedInterval();
+ }
+ }
+
+ ///
+ /// Returns a randomized interval for bubble spawning.
+ ///
+ /// Randomized interval in seconds.
+ float GetRandomizedInterval()
+ {
+ return spawnInterval * Random.Range(0.8f, 1.2f);
+ }
+
+ ///
+ /// Spawns a bubble with randomized properties and assigns a random sprite.
+ ///
+ void SpawnBubble()
+ {
+ float x = Random.Range(spawnXMin, spawnXMax);
+ Vector3 spawnPos = new Vector3(x, spawnY, 0f);
+ Bubble bubble = Instantiate(bubblePrefab, spawnPos, Quaternion.identity, transform);
+ // Randomize bubble properties
+ bubble.speed = Random.Range(speedRange.x, speedRange.y);
+ bubble.wobbleSpeed = Random.Range(wobbleSpeedRange.x, wobbleSpeedRange.y);
+ float scale = Random.Range(scaleRange.x, scaleRange.y);
+ bubble.transform.localScale = Vector3.one * scale;
+ // Assign random sprite to BottleSprite
+ if (bubbleSprites != null && bubbleSprites.Length > 0)
+ {
+ Sprite randomSprite = bubbleSprites[Random.Range(0, bubbleSprites.Length)];
+ bubble.SetBottleSprite(randomSprite);
+ }
+
+ // Random rotation
+ bubble.transform.rotation = Quaternion.Euler(0f, 0f, Random.Range(0f, 360f));
+ // Pass min/max scale for wobble clamping
+ bubble.SetWobbleScaleLimits(wobbleMinScale, wobbleMaxScale);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/BubbleS/BubbleSpawner.cs.meta b/Assets/Scripts/Minigames/DivingForPictures/BubbleSpawner.cs.meta
similarity index 100%
rename from Assets/Scripts/BubbleS/BubbleSpawner.cs.meta
rename to Assets/Scripts/Minigames/DivingForPictures/BubbleSpawner.cs.meta
diff --git a/Assets/Scripts/Minigames/DivingForPictures/PlayerController.cs b/Assets/Scripts/Minigames/DivingForPictures/PlayerController.cs
new file mode 100644
index 00000000..899fea46
--- /dev/null
+++ b/Assets/Scripts/Minigames/DivingForPictures/PlayerController.cs
@@ -0,0 +1,94 @@
+using UnityEngine;
+
+namespace Minigames.DivingForPictures
+{
+ ///
+ /// Handles endless descender movement in response to tap and hold input events.
+ /// Moves the character horizontally to follow the finger or tap position.
+ ///
+ public class PlayerController : MonoBehaviour, ITouchInputConsumer
+ {
+ private float _targetFingerX;
+ private bool _isTouchActive;
+ private float _originY;
+
+ void Awake()
+ {
+ _originY = transform.position.y;
+ }
+
+ void Start()
+ {
+ // Register as default consumer for input
+ InputManager.Instance?.SetDefaultConsumer(this);
+ // Initialize target to current position
+ _targetFingerX = transform.position.x;
+ _isTouchActive = false;
+ }
+
+ ///
+ /// Handles tap input. Moves to the tapped X position.
+ ///
+ public void OnTap(Vector2 worldPosition)
+ {
+ Debug.Log($"[EndlessDescenderController] OnTap at {worldPosition}");
+ _targetFingerX = Mathf.Clamp(worldPosition.x, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
+ _isTouchActive = true;
+ }
+
+ ///
+ /// Handles the start of a hold input. Begins tracking the finger.
+ ///
+ public void OnHoldStart(Vector2 worldPosition)
+ {
+ Debug.Log($"[EndlessDescenderController] OnHoldStart at {worldPosition}");
+ _targetFingerX = Mathf.Clamp(worldPosition.x, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
+ _isTouchActive = true;
+ }
+
+ ///
+ /// Handles hold move input. Updates the target X position as the finger moves.
+ ///
+ public void OnHoldMove(Vector2 worldPosition)
+ {
+ Debug.Log($"[EndlessDescenderController] OnHoldMove at {worldPosition}");
+ _targetFingerX = Mathf.Clamp(worldPosition.x, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
+ }
+
+ ///
+ /// Handles the end of a hold input. Stops tracking.
+ ///
+ public void OnHoldEnd(Vector2 worldPosition)
+ {
+ Debug.Log($"[EndlessDescenderController] OnHoldEnd at {worldPosition}");
+ _isTouchActive = false;
+ }
+
+ void Update()
+ {
+ if (!_isTouchActive) return;
+ float currentX = transform.position.x;
+ float lerpSpeed = GameManager.Instance.EndlessDescenderLerpSpeed;
+ float maxOffset = GameManager.Instance.EndlessDescenderMaxOffset;
+ float exponent = GameManager.Instance.EndlessDescenderSpeedExponent;
+ float targetX = _targetFingerX;
+ float offset = targetX - currentX;
+ offset = Mathf.Clamp(offset, -maxOffset, maxOffset);
+ float absOffset = Mathf.Abs(offset);
+ float t = Mathf.Pow(absOffset / maxOffset, exponent); // Non-linear drop-off
+ float moveStep = Mathf.Sign(offset) * maxOffset * t * Time.deltaTime * lerpSpeed;
+ // Prevent overshooting
+ moveStep = Mathf.Clamp(moveStep, -absOffset, absOffset);
+ float newX = currentX + moveStep;
+ newX = Mathf.Clamp(newX, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
+ float newY = _originY;
+ // Add vertical offset from WobbleBehavior if present
+ WobbleBehavior wobble = GetComponent();
+ if (wobble != null)
+ {
+ newY += wobble.VerticalOffset;
+ }
+ transform.position = new Vector3(newX, newY, transform.position.z);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/Scripts/Movement/EndlessDescenderController.cs.meta b/Assets/Scripts/Minigames/DivingForPictures/PlayerController.cs.meta
similarity index 100%
rename from Assets/Scripts/Movement/EndlessDescenderController.cs.meta
rename to Assets/Scripts/Minigames/DivingForPictures/PlayerController.cs.meta
diff --git a/Assets/Scripts/Movement/EndlessDescenderController.cs b/Assets/Scripts/Movement/EndlessDescenderController.cs
deleted file mode 100644
index b50fcf94..00000000
--- a/Assets/Scripts/Movement/EndlessDescenderController.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-using UnityEngine;
-
-///
-/// Handles endless descender movement in response to tap and hold input events.
-/// Moves the character horizontally to follow the finger or tap position.
-///
-public class EndlessDescenderController : MonoBehaviour, ITouchInputConsumer
-{
- private float targetFingerX;
- private bool isTouchActive;
- private float originY;
-
- void Awake()
- {
- originY = transform.position.y;
- }
-
- void Start()
- {
- // Register as default consumer for input
- InputManager.Instance?.SetDefaultConsumer(this);
- // Initialize target to current position
- targetFingerX = transform.position.x;
- isTouchActive = false;
- }
-
- ///
- /// Handles tap input. Moves to the tapped X position.
- ///
- public void OnTap(Vector2 worldPosition)
- {
- Debug.Log($"[EndlessDescenderController] OnTap at {worldPosition}");
- targetFingerX = Mathf.Clamp(worldPosition.x, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
- isTouchActive = true;
- }
-
- ///
- /// Handles the start of a hold input. Begins tracking the finger.
- ///
- public void OnHoldStart(Vector2 worldPosition)
- {
- Debug.Log($"[EndlessDescenderController] OnHoldStart at {worldPosition}");
- targetFingerX = Mathf.Clamp(worldPosition.x, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
- isTouchActive = true;
- }
-
- ///
- /// Handles hold move input. Updates the target X position as the finger moves.
- ///
- public void OnHoldMove(Vector2 worldPosition)
- {
- Debug.Log($"[EndlessDescenderController] OnHoldMove at {worldPosition}");
- targetFingerX = Mathf.Clamp(worldPosition.x, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
- }
-
- ///
- /// Handles the end of a hold input. Stops tracking.
- ///
- public void OnHoldEnd(Vector2 worldPosition)
- {
- Debug.Log($"[EndlessDescenderController] OnHoldEnd at {worldPosition}");
- isTouchActive = false;
- }
-
- void Update()
- {
- if (!isTouchActive) return;
- float currentX = transform.position.x;
- float lerpSpeed = GameManager.Instance.EndlessDescenderLerpSpeed;
- float maxOffset = GameManager.Instance.EndlessDescenderMaxOffset;
- float exponent = GameManager.Instance.EndlessDescenderSpeedExponent;
- float targetX = targetFingerX;
- float offset = targetX - currentX;
- offset = Mathf.Clamp(offset, -maxOffset, maxOffset);
- float absOffset = Mathf.Abs(offset);
- float t = Mathf.Pow(absOffset / maxOffset, exponent); // Non-linear drop-off
- float moveStep = Mathf.Sign(offset) * maxOffset * t * Time.deltaTime * lerpSpeed;
- // Prevent overshooting
- moveStep = Mathf.Clamp(moveStep, -absOffset, absOffset);
- float newX = currentX + moveStep;
- newX = Mathf.Clamp(newX, GameManager.Instance.EndlessDescenderClampXMin, GameManager.Instance.EndlessDescenderClampXMax);
- float newY = originY;
- // Add vertical offset from WobbleBehavior if present
- WobbleBehavior wobble = GetComponent();
- if (wobble != null)
- {
- newY += wobble.VerticalOffset;
- }
- transform.position = new Vector3(newX, newY, transform.position.z);
- }
-}