diff --git a/Assets/Prefabs/Minigames/CardQualityControl/SortableGarbage.prefab b/Assets/Prefabs/Minigames/CardQualityControl/SortableGarbage.prefab index fb545b90..324e31d1 100644 --- a/Assets/Prefabs/Minigames/CardQualityControl/SortableGarbage.prefab +++ b/Assets/Prefabs/Minigames/CardQualityControl/SortableGarbage.prefab @@ -40,7 +40,7 @@ RectTransform: m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 200, y: 270} + m_SizeDelta: {x: 200, y: 200} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &2127389269465269351 MonoBehaviour: @@ -143,6 +143,7 @@ GameObject: - component: {fileID: 581410895551808339} - component: {fileID: 9061673992343081870} - component: {fileID: 2391223799317068879} + - component: {fileID: 3335061902473626590} m_Layer: 0 m_Name: Visual m_TagString: Untagged @@ -164,10 +165,10 @@ RectTransform: m_Children: [] m_Father: {fileID: 8730990344497138252} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 200, y: 200} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &581410895551808339 MonoBehaviour: @@ -220,6 +221,20 @@ MonoBehaviour: m_FillOrigin: 0 m_UseSpriteMesh: 0 m_PixelsPerUnitMultiplier: 1 +--- !u!114 &3335061902473626590 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3963317030246886356} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 86710e43de46f6f4bac7c8e50813a599, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.AspectRatioFitter + m_AspectMode: 1 + m_AspectRatio: 1 --- !u!1 &4127399957670380340 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Prefabs/Minigames/CardQualityControl/SortingBox.prefab b/Assets/Prefabs/Minigames/CardQualityControl/SortingBox.prefab index c808825f..5ae18508 100644 --- a/Assets/Prefabs/Minigames/CardQualityControl/SortingBox.prefab +++ b/Assets/Prefabs/Minigames/CardQualityControl/SortingBox.prefab @@ -55,7 +55,6 @@ MonoBehaviour: occupantScale: {x: 1, y: 1, z: 1} scaleTransitionDuration: 0.3 boxType: 0 - boxSprite: {fileID: 0} --- !u!1 &6923066319076554151 GameObject: m_ObjectHideFlags: 0 @@ -132,8 +131,8 @@ SpriteRenderer: m_AutoUVMaxAngle: 89 m_LightmapParameters: {fileID: 0} m_GlobalIlluminationMeshLod: 0 - m_SortingLayerID: -1132846201 - m_SortingLayer: 1 + m_SortingLayerID: 0 + m_SortingLayer: 0 m_SortingOrder: 0 m_Sprite: {fileID: -7843813406500067289, guid: bd1c641e7bfe53145820bb64b08f8fc8, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} diff --git a/Assets/Prefabs/Minigames/CardQualityControl/UI/MinigameHUD.prefab b/Assets/Prefabs/Minigames/CardQualityControl/UI/MinigameHUD.prefab index 8472a483..cab8b56b 100644 --- a/Assets/Prefabs/Minigames/CardQualityControl/UI/MinigameHUD.prefab +++ b/Assets/Prefabs/Minigames/CardQualityControl/UI/MinigameHUD.prefab @@ -35,7 +35,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 200, y: 50} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &6535475175108777945 CanvasRenderer: @@ -65,7 +65,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: 0000 + m_text: 'Score: 0' m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: 4aca0db6ec111b5418bdc747168f9474, type: 2} m_sharedMaterial: {fileID: -1441574381962284772, guid: 4aca0db6ec111b5418bdc747168f9474, type: 2} @@ -92,15 +92,15 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 100 - m_fontSizeBase: 100 + m_fontSize: 75 + m_fontSizeBase: 75 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 1 - m_HorizontalAlignment: 1 - m_VerticalAlignment: 256 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 @@ -171,7 +171,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 200, y: 50} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &6186147173729892847 CanvasRenderer: @@ -201,7 +201,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: 0% + m_text: 'Accuracy: 0%' m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: 4aca0db6ec111b5418bdc747168f9474, type: 2} m_sharedMaterial: {fileID: -1441574381962284772, guid: 4aca0db6ec111b5418bdc747168f9474, type: 2} @@ -228,15 +228,15 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 100 - m_fontSizeBase: 100 + m_fontSize: 75 + m_fontSizeBase: 75 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 1 - m_HorizontalAlignment: 1 - m_VerticalAlignment: 256 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 @@ -307,10 +307,10 @@ RectTransform: m_Father: {fileID: 707190640386266950} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 1, y: 1} + m_AnchorMax: {x: 0, y: 1} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 150} - m_Pivot: {x: 0.5, y: 1} + m_SizeDelta: {x: 1200, y: 94} + m_Pivot: {x: 0, y: 1} --- !u!114 &3416581373676611538 MonoBehaviour: m_ObjectHideFlags: 0 @@ -324,19 +324,98 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.HorizontalLayoutGroup m_Padding: - m_Left: 0 + m_Left: 150 m_Right: 0 - m_Top: 0 + m_Top: 50 m_Bottom: 0 m_ChildAlignment: 4 - m_Spacing: 150 - m_ChildForceExpandWidth: 0 + m_Spacing: 25 + m_ChildForceExpandWidth: 1 m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1 &3087548688493085045 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3245381937614859990} + - component: {fileID: 1428588550372337553} + - component: {fileID: 7088646692690443534} + m_Layer: 5 + m_Name: HealthBar + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3245381937614859990 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3087548688493085045} + 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: 3256183770156166523} + m_Father: {fileID: 707190640386266950} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 559.7, y: 150} + m_Pivot: {x: 1, y: 1} +--- !u!114 &1428588550372337553 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3087548688493085045} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.HorizontalLayoutGroup + m_Padding: + m_Left: 0 + m_Right: 50 + m_Top: 50 + m_Bottom: 0 + m_ChildAlignment: 2 + m_Spacing: 25 + m_ChildForceExpandWidth: 0 + m_ChildForceExpandHeight: 0 m_ChildControlWidth: 0 m_ChildControlHeight: 0 m_ChildScaleWidth: 0 m_ChildScaleHeight: 0 m_ReverseArrangement: 0 +--- !u!114 &7088646692690443534 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3087548688493085045} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e8bcb252540442e593cc6467c518ff75, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::Minigames.CardSorting.UI.LivesDisplay + layoutGroup: {fileID: 1428588550372337553} + animationDuration: 0.8 + scaleMultiplier: 1.5 --- !u!1 &5517642253100401386 GameObject: m_ObjectHideFlags: 0 @@ -372,7 +451,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 200, y: 50} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &6941393494789352809 CanvasRenderer: @@ -429,15 +508,15 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 100 - m_fontSizeBase: 100 + m_fontSize: 75 + m_fontSizeBase: 75 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 1 - m_HorizontalAlignment: 1 - m_VerticalAlignment: 256 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 @@ -473,6 +552,81 @@ MonoBehaviour: m_hasFontAssetChanged: 0 m_baseMaterial: {fileID: 0} m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &5874089027455915553 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3256183770156166523} + - component: {fileID: 8780034033757607403} + - component: {fileID: 5667348465997950205} + m_Layer: 5 + m_Name: Image + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3256183770156166523 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5874089027455915553} + 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: [] + m_Father: {fileID: 3245381937614859990} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &8780034033757607403 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5874089027455915553} + m_CullTransparentMesh: 1 +--- !u!114 &5667348465997950205 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5874089027455915553} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 6741082507358000137, guid: 2406a20d35d3e8946b1e3f83ecd269c2, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 --- !u!1 &7537653696112211670 GameObject: m_ObjectHideFlags: 0 @@ -503,6 +657,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: - {fileID: 8952171418799244803} + - {fileID: 3245381937614859990} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} diff --git a/Assets/Prefabs/Minigames/CardQualityControl/UI/ResultsScreen.prefab b/Assets/Prefabs/Minigames/CardQualityControl/UI/ResultsScreen.prefab index f439ba05..a5297c79 100644 --- a/Assets/Prefabs/Minigames/CardQualityControl/UI/ResultsScreen.prefab +++ b/Assets/Prefabs/Minigames/CardQualityControl/UI/ResultsScreen.prefab @@ -1059,8 +1059,8 @@ RectTransform: - {fileID: 5196078022198364906} m_Father: {fileID: 5616388183832902964} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.2, y: 0.12} - m_AnchorMax: {x: 0.9, y: 0.85} + m_AnchorMin: {x: 0.15, y: 0.15} + m_AnchorMax: {x: 0.9, y: 0.8} m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} @@ -1083,7 +1083,7 @@ MonoBehaviour: m_Bottom: 0 m_ChildAlignment: 0 m_Spacing: 10 - m_ChildForceExpandWidth: 1 + m_ChildForceExpandWidth: 0 m_ChildForceExpandHeight: 0 m_ChildControlWidth: 1 m_ChildControlHeight: 0 diff --git a/Assets/Scenes/MiniGames/CardQualityControl.unity b/Assets/Scenes/MiniGames/CardQualityControl.unity index bdbe0bc2..434599a5 100644 --- a/Assets/Scenes/MiniGames/CardQualityControl.unity +++ b/Assets/Scenes/MiniGames/CardQualityControl.unity @@ -160,6 +160,7 @@ MonoBehaviour: - {fileID: 254614580} - {fileID: 222800744} impulseSource: {fileID: 90351797} + livesDisplay: {fileID: 934831599} --- !u!4 &90351796 Transform: m_ObjectHideFlags: 0 @@ -1025,6 +1026,134 @@ MonoBehaviour: m_PostInfinity: 2 m_RotationOrder: 4 CustomBlends: {fileID: 0} +--- !u!114 &934831599 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 7088646692690443534, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} + m_PrefabInstance: {fileID: 384779534298969466} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e8bcb252540442e593cc6467c518ff75, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::Minigames.CardSorting.UI.LivesDisplay +--- !u!1 &1018422025 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1018422026} + - component: {fileID: 1018422030} + - component: {fileID: 1018422029} + - component: {fileID: 1018422028} + - component: {fileID: 1018422027} + m_Layer: 0 + m_Name: CanvasHitbox + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1018422026 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1018422025} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.010527978, y: 0.04, z: 0.08} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1020017635} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 800, y: 113.2} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1018422027 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1018422025} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 0.003921569} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1018422028 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1018422025} + m_CullTransparentMesh: 1 +--- !u!114 &1018422029 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1018422025} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.GraphicRaycaster + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!223 &1018422030 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1018422025} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 2 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 0 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 --- !u!1 &1020017633 GameObject: m_ObjectHideFlags: 0 @@ -1034,6 +1163,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 1020017635} + - component: {fileID: 1020017636} - component: {fileID: 1020017634} m_Layer: 0 m_Name: ConveyorBeltVisual @@ -1086,8 +1216,8 @@ SpriteRenderer: m_AutoUVMaxAngle: 89 m_LightmapParameters: {fileID: 0} m_GlobalIlluminationMeshLod: 0 - m_SortingLayerID: 0 - m_SortingLayer: 0 + m_SortingLayerID: 622133659 + m_SortingLayer: -1 m_SortingOrder: 0 m_Sprite: {fileID: -7171755534009967257, guid: b382c7219ff059c499bdeba018f5a93f, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} @@ -1109,15 +1239,36 @@ Transform: m_GameObject: {fileID: 1020017633} serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -10.39, z: 0} - m_LocalScale: {x: 7.5988007, y: 1.4, z: 1} + m_LocalPosition: {x: 0, y: -10.08, z: 0} + m_LocalScale: {x: 7.5988007, y: 2, z: 1} m_ConstrainProportionsScale: 0 m_Children: - {fileID: 1122663370} - {fileID: 1595343397} - {fileID: 1992305141} + - {fileID: 1018422026} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1020017636 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1020017633} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9304d17587314133a4d8d1e582cfbf81, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::Minigames.CardSorting.Core.ConveyorBeltSlot + slotIndex: -1 + isLocked: 0 + hideImageOnPlay: 0 + filterByType: 0 + allowedTypeNames: [] + occupantSizeMode: 0 + occupantScale: {x: 1, y: 1, z: 1} + scaleTransitionDuration: 0.3 --- !u!1 &1122663369 GameObject: m_ObjectHideFlags: 0 @@ -1438,34 +1589,6 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 1653089319504497253, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} - propertyPath: m_fontSize - value: 100 - objectReference: {fileID: 0} - - target: {fileID: 1653089319504497253, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} - propertyPath: m_enableAutoSizing - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1653089319504497253, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} - propertyPath: m_VerticalAlignment - value: 512 - objectReference: {fileID: 0} - - target: {fileID: 1653089319504497253, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} - propertyPath: m_HorizontalAlignment - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 1929638711813240478, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} - propertyPath: m_text - value: 'Accuracy: 0%' - objectReference: {fileID: 0} - - target: {fileID: 1929638711813240478, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} - propertyPath: m_VerticalAlignment - value: 512 - objectReference: {fileID: 0} - - target: {fileID: 1929638711813240478, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} - propertyPath: m_HorizontalAlignment - value: 2 - objectReference: {fileID: 0} - target: {fileID: 3193587684358315289, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} propertyPath: m_AnchorMax.y value: 0 @@ -1476,7 +1599,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 3193587684358315289, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} propertyPath: m_SizeDelta.x - value: 400 + value: 0 objectReference: {fileID: 0} - target: {fileID: 3193587684358315289, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} propertyPath: m_SizeDelta.y @@ -1490,25 +1613,21 @@ PrefabInstance: propertyPath: m_AnchoredPosition.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 3416581373676611538, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} - propertyPath: m_ChildControlHeight - value: 1 + - target: {fileID: 3256183770156166523, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} + propertyPath: m_AnchorMax.y + value: 0 objectReference: {fileID: 0} - - target: {fileID: 3416581373676611538, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} - propertyPath: m_ChildForceExpandHeight - value: 1 + - target: {fileID: 3256183770156166523, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} + propertyPath: m_AnchorMin.y + value: 0 objectReference: {fileID: 0} - - target: {fileID: 4139981089598238079, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} - propertyPath: m_text - value: 'Score: 0' + - target: {fileID: 3256183770156166523, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 objectReference: {fileID: 0} - - target: {fileID: 4139981089598238079, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} - propertyPath: m_VerticalAlignment - value: 512 - objectReference: {fileID: 0} - - target: {fileID: 4139981089598238079, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} - propertyPath: m_HorizontalAlignment - value: 2 + - target: {fileID: 3256183770156166523, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 objectReference: {fileID: 0} - target: {fileID: 4881154979794857029, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} propertyPath: m_AnchorMax.y @@ -1518,6 +1637,10 @@ PrefabInstance: propertyPath: m_AnchorMin.y value: 0 objectReference: {fileID: 0} + - target: {fileID: 4881154979794857029, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} - target: {fileID: 4881154979794857029, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} propertyPath: m_SizeDelta.y value: 0 @@ -1544,7 +1667,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 8294328820939081367, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} propertyPath: m_SizeDelta.x - value: 600 + value: 0 objectReference: {fileID: 0} - target: {fileID: 8294328820939081367, guid: acc5a752dcc18834b984fe78b6926dad, type: 3} propertyPath: m_SizeDelta.y @@ -2013,11 +2136,11 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 9145507277845748449, guid: c8846509eba59f84aa047197fe02375b, type: 3} propertyPath: m_SizeDelta.x - value: 1000 + value: 1200 objectReference: {fileID: 0} - target: {fileID: 9145507277845748449, guid: c8846509eba59f84aa047197fe02375b, type: 3} propertyPath: m_SizeDelta.y - value: 1000 + value: 1200 objectReference: {fileID: 0} - target: {fileID: 9145507277845748449, guid: c8846509eba59f84aa047197fe02375b, type: 3} propertyPath: m_LocalPosition.x diff --git a/Assets/Scripts/Core/Settings/CardSortingSettings.cs b/Assets/Scripts/Core/Settings/CardSortingSettings.cs index 6faf176b..5062eff4 100644 --- a/Assets/Scripts/Core/Settings/CardSortingSettings.cs +++ b/Assets/Scripts/Core/Settings/CardSortingSettings.cs @@ -55,10 +55,24 @@ namespace Core.Settings [Tooltip("Points deducted when item falls off belt")] [SerializeField] private int missedItemPenalty = -3; + [Header("Lives")] + [Tooltip("Maximum number of lives player has")] + [SerializeField] private int maxLives = 3; + [Header("Rewards")] [Tooltip("Booster packs awarded per correct sort")] [SerializeField] private int boosterPacksPerCorrectItem = 1; + [Header("Visual")] + [Tooltip("Size of spawned cards (width, height)")] + [SerializeField] private Vector2 cardSize = new Vector2(100f, 140f); + + [Tooltip("Random offset range for spawn distance X (min, max). Range: -10 to 10")] + [SerializeField] private Vector2 spawnOffsetX = new Vector2(-5f, 5f); + + [Tooltip("Random offset range for spawn Y position (min, max). Range: -10 to 10")] + [SerializeField] private Vector2 spawnOffsetY = new Vector2(-10f, 10f); + // Interface implementation public float GameDuration => gameDuration; @@ -75,7 +89,11 @@ namespace Core.Settings public int CorrectSortPoints => correctSortPoints; public int IncorrectSortPenalty => incorrectSortPenalty; public int MissedItemPenalty => missedItemPenalty; + public int MaxLives => maxLives; public int BoosterPacksPerCorrectItem => boosterPacksPerCorrectItem; + public Vector2 CardSize => cardSize; + public Vector2 SpawnOffsetX => spawnOffsetX; + public Vector2 SpawnOffsetY => spawnOffsetY; public override void OnValidate() { @@ -86,6 +104,15 @@ namespace Core.Settings maxBeltSpeed = Mathf.Max(initialBeltSpeed, maxBeltSpeed); correctSortPoints = Mathf.Max(0, correctSortPoints); boosterPacksPerCorrectItem = Mathf.Max(0, boosterPacksPerCorrectItem); + maxLives = Mathf.Max(1, maxLives); + cardSize.x = Mathf.Max(1f, cardSize.x); + cardSize.y = Mathf.Max(1f, cardSize.y); + + // Clamp spawn offsets between -10 and 10 + spawnOffsetX.x = Mathf.Clamp(spawnOffsetX.x, -10f, 10f); + spawnOffsetX.y = Mathf.Clamp(spawnOffsetX.y, -10f, 10f); + spawnOffsetY.x = Mathf.Clamp(spawnOffsetY.x, -10f, 10f); + spawnOffsetY.y = Mathf.Clamp(spawnOffsetY.y, -10f, 10f); } } } diff --git a/Assets/Scripts/Core/Settings/ICardSortingSettings.cs b/Assets/Scripts/Core/Settings/ICardSortingSettings.cs index 6d5636f4..a9693491 100644 --- a/Assets/Scripts/Core/Settings/ICardSortingSettings.cs +++ b/Assets/Scripts/Core/Settings/ICardSortingSettings.cs @@ -32,8 +32,16 @@ namespace Core.Settings int IncorrectSortPenalty { get; } int MissedItemPenalty { get; } + // Lives + int MaxLives { get; } + // Rewards int BoosterPacksPerCorrectItem { get; } + + // Visual + Vector2 CardSize { get; } + Vector2 SpawnOffsetX { get; } // Min/Max range for X offset (distance) + Vector2 SpawnOffsetY { get; } // Min/Max range for Y offset (position) } } diff --git a/Assets/Scripts/Minigames/CardSorting/Controllers/ConveyorBeltController.cs b/Assets/Scripts/Minigames/CardSorting/Controllers/ConveyorBeltController.cs index 632e17f5..00540d6b 100644 --- a/Assets/Scripts/Minigames/CardSorting/Controllers/ConveyorBeltController.cs +++ b/Assets/Scripts/Minigames/CardSorting/Controllers/ConveyorBeltController.cs @@ -4,6 +4,7 @@ using Data.CardSystem; using Minigames.CardSorting.Core; using Minigames.CardSorting.Data; using System.Collections.Generic; +using UI.DragAndDrop.Core; using UnityEngine; namespace Minigames.CardSorting.Controllers @@ -27,6 +28,8 @@ namespace Minigames.CardSorting.Controllers private HashSet missedItems = new HashSet(); // Items past visual end, moving to despawn private float currentSpeed; private SortableItem lastSpawnedItem; // Track last spawned item for distance-based spawning + private float cachedSpawnOffsetX; // Cached random offset for next spawn + private bool isGameOver = false; // Flag to stop conveyor when game ends // Events - conveyor owns item lifecycle public event System.Action OnItemSpawned; // Fired when new item spawns @@ -37,6 +40,7 @@ namespace Minigames.CardSorting.Controllers public float CurrentSpeed => currentSpeed; public int ActiveItemCount => activeItems.Count; + public bool IsGameOver => isGameOver; public ConveyorBeltController( Transform spawnPoint, @@ -55,6 +59,9 @@ namespace Minigames.CardSorting.Controllers this.currentSpeed = settings.InitialBeltSpeed; this.lastSpawnedItem = null; // No items spawned yet + + // Initialize first cached offset + this.cachedSpawnOffsetX = Random.Range(settings.SpawnOffsetX.x, settings.SpawnOffsetX.y); } /// @@ -62,6 +69,9 @@ namespace Minigames.CardSorting.Controllers /// public void Update(float deltaTime, float gameProgress) { + // Stop processing if game is over + if (isGameOver) return; + UpdateBeltSpeed(gameProgress); CheckItemsOffBelt(); CheckDistanceBasedSpawn(gameProgress); @@ -70,6 +80,7 @@ namespace Minigames.CardSorting.Controllers /// /// Check if we should spawn a new item based on distance from last spawn. /// Items spawn when last item has moved far enough from spawn point. + /// Uses cached random X offset for spawn distance variation. /// private void CheckDistanceBasedSpawn(float gameProgress) { @@ -77,15 +88,24 @@ namespace Minigames.CardSorting.Controllers if (lastSpawnedItem == null) { SpawnNewItem(gameProgress); + + // Generate new offset for next spawn + cachedSpawnOffsetX = Random.Range(settings.SpawnOffsetX.x, settings.SpawnOffsetX.y); return; } // Check if last spawned item is far enough from spawn point float distanceFromSpawn = Mathf.Abs(lastSpawnedItem.transform.position.x - spawnPoint.position.x); - if (distanceFromSpawn >= settings.SpawnDistance) // Using InitialSpawnInterval as distance threshold + // Use cached offset for required distance + float requiredDistance = settings.SpawnDistance + cachedSpawnOffsetX; + + if (distanceFromSpawn >= requiredDistance) { SpawnNewItem(gameProgress); + + // Generate new offset for next spawn + cachedSpawnOffsetX = Random.Range(settings.SpawnOffsetX.x, settings.SpawnOffsetX.y); } } @@ -145,16 +165,27 @@ namespace Minigames.CardSorting.Controllers GarbageItemDefinition garbage = SelectRandomGarbage(); - GameObject obj = Object.Instantiate(garbagePrefab, spawnPoint.position, Quaternion.identity); + // Apply random Y offset to spawn position + float randomOffsetY = Random.Range(settings.SpawnOffsetY.x, settings.SpawnOffsetY.y); + Vector3 spawnPos = spawnPoint.position + new Vector3(0f, randomOffsetY, 0f); + + GameObject obj = Object.Instantiate(garbagePrefab, spawnPos, Quaternion.identity); SortableItem item = obj.GetComponent(); if (item != null) { item.SetupAsGarbage(garbage); + // Apply card size (garbage items use same size as cards) + ApplyCardSize(item); + // Subscribe to item events item.OnItemDroppedInBox += HandleItemDroppedInBox; + item.OnItemDroppedOnFloor += HandleItemDroppedOnFloor; item.OnItemReturnedToConveyor += HandleItemReturnedToConveyor; + + // Subscribe to drag events to remove from tracking + item.OnDragStarted += HandleItemDragStarted; } else { @@ -177,16 +208,27 @@ namespace Minigames.CardSorting.Controllers return null; } - GameObject obj = Object.Instantiate(cardPrefab, spawnPoint.position, Quaternion.identity); + // Apply random Y offset to spawn position + float randomOffsetY = Random.Range(settings.SpawnOffsetY.x, settings.SpawnOffsetY.y); + Vector3 spawnPos = spawnPoint.position + new Vector3(0f, randomOffsetY, 0f); + + GameObject obj = Object.Instantiate(cardPrefab, spawnPos, Quaternion.identity); SortableItem item = obj.GetComponent(); if (item != null) { item.SetupAsCard(cardData); + // Apply card size + ApplyCardSize(item); + // Subscribe to item events item.OnItemDroppedInBox += HandleItemDroppedInBox; + item.OnItemDroppedOnFloor += HandleItemDroppedOnFloor; item.OnItemReturnedToConveyor += HandleItemReturnedToConveyor; + + // Subscribe to drag events to remove from tracking + item.OnDragStarted += HandleItemDragStarted; } else { @@ -296,55 +338,86 @@ namespace Minigames.CardSorting.Controllers } + /// + /// Handle when an item starts being dragged. + /// Remove from tracking to prevent "fell off belt" detection while dragging. + /// + private void HandleItemDragStarted(DraggableObject draggableObj) + { + SortableItem item = draggableObj as SortableItem; + if (item == null) return; + + RemoveItemFromTracking(item); + } + /// /// Handle when an item is dropped in a box (correct or incorrect). + /// Note: Item was already removed from activeItems when dragging started (HandleItemDragStarted). /// private void HandleItemDroppedInBox(SortableItem item, SortingBox box, bool correct) { - // Remove from tracking and unsubscribe - if (activeItems.Remove(item)) + // Clean up tracking (item already removed from activeItems when picked up) + activeItems.Remove(item); + missedItems.Remove(item); + + // Clear lastSpawnedItem reference if this was it + if (lastSpawnedItem == item) { - // Also remove from missed items if it was there - missedItems.Remove(item); - - // Clear lastSpawnedItem reference if this was it - if (lastSpawnedItem == item) - { - lastSpawnedItem = null; - } - - item.OnItemDroppedInBox -= HandleItemDroppedInBox; - item.OnItemReturnedToConveyor -= HandleItemReturnedToConveyor; - - // Emit event for game manager to handle scoring, passing box and correctness - OnItemSorted?.Invoke(item, box, correct); + lastSpawnedItem = null; + } + + // Unsubscribe from events + item.OnItemDroppedInBox -= HandleItemDroppedInBox; + item.OnItemDroppedOnFloor -= HandleItemDroppedOnFloor; + item.OnItemReturnedToConveyor -= HandleItemReturnedToConveyor; + item.OnDragStarted -= HandleItemDragStarted; + + // Emit event for game manager to handle scoring, passing box and correctness + OnItemSorted?.Invoke(item, box, correct); + } + + /// + /// Handle when an item is returned to conveyor (dropped back on conveyor belt). + /// Re-adds item to tracking so it continues moving along the belt. + /// + private void HandleItemReturnedToConveyor(SortableItem item) + { + if (item == null) return; + + // Re-add to active tracking + if (!activeItems.Contains(item)) + { + activeItems.Add(item); + Debug.Log($"[ConveyorBeltController] Item returned to conveyor: {item.CardData?.Name ?? item.GarbageItem?.DisplayName}"); } } /// - /// Handle when an item is returned to conveyor (dropped outside box). + /// Handle when an item is dropped on floor (dropped outside box). /// Item transitions to DroppedOnFloorState and gets destroyed. + /// Note: Item was already removed from activeItems when dragging started (HandleItemDragStarted). /// - private void HandleItemReturnedToConveyor(SortableItem item) + private void HandleItemDroppedOnFloor(SortableItem item) { - // Remove from tracking and unsubscribe (item will be destroyed) - if (activeItems.Remove(item)) + // Clean up tracking (item already removed from activeItems when picked up) + activeItems.Remove(item); + missedItems.Remove(item); + + if (lastSpawnedItem == item) { - missedItems.Remove(item); - - if (lastSpawnedItem == item) - { - lastSpawnedItem = null; - } - - item.OnItemDroppedInBox -= HandleItemDroppedInBox; - item.OnItemReturnedToConveyor -= HandleItemReturnedToConveyor; - - // Emit event for scoring - OnItemDroppedOnFloor?.Invoke(item); - - Debug.Log($"[ConveyorBeltController] Item dropped on floor: {item.CardData?.Name ?? item.GarbageItem?.DisplayName}"); + lastSpawnedItem = null; } + + // Unsubscribe from events + item.OnItemDroppedInBox -= HandleItemDroppedInBox; + item.OnItemDroppedOnFloor -= HandleItemDroppedOnFloor; + item.OnItemReturnedToConveyor -= HandleItemReturnedToConveyor; + item.OnDragStarted -= HandleItemDragStarted; + + // Emit event for scoring + OnItemDroppedOnFloor?.Invoke(item); + + Debug.Log($"[ConveyorBeltController] Item dropped on floor: {item.CardData?.Name ?? item.GarbageItem?.DisplayName}"); } private CardRarity DetermineRarity(float roll) @@ -365,6 +438,65 @@ namespace Minigames.CardSorting.Controllers { return settings.GarbageItems[Random.Range(0, settings.GarbageItems.Length)]; } + + /// + /// Apply configured card size to spawned item. + /// + private void ApplyCardSize(SortableItem item) + { + if (item == null || item.Context == null || item.Context.RootTransform == null) + return; + + // Get the RectTransform to resize (root object) + var rectTransform = item.Context.RootTransform.GetComponent(); + if (rectTransform != null) + { + rectTransform.sizeDelta = settings.CardSize; + } + } + + /// + /// Remove an item from tracking (called when picked up via event). + /// Prevents item from being subject to belt end detection while being dragged. + /// + private void RemoveItemFromTracking(SortableItem item) + { + if (item == null) return; + + bool wasTracked = activeItems.Remove(item); + missedItems.Remove(item); + + // Clear lastSpawnedItem reference if this was it + if (lastSpawnedItem == item) + { + lastSpawnedItem = null; + } + + if (wasTracked) + { + Debug.Log($"[ConveyorBeltController] Item removed from tracking (picked up): {item.CardData?.Name ?? item.GarbageItem?.DisplayName}"); + } + } + + /// + /// Stop the conveyor belt when game ends. + /// Disables dragging on all active items so they can't be interacted with. + /// + public void StopConveyor() + { + isGameOver = true; + + // Disable dragging on all active items + foreach (var item in activeItems) + { + if (item != null) + { + item.SetDraggingEnabled(false); + } + } + + Debug.Log("[ConveyorBeltController] Conveyor stopped - all items disabled"); + } } } diff --git a/Assets/Scripts/Minigames/CardSorting/Core/ConveyorBeltSlot.cs b/Assets/Scripts/Minigames/CardSorting/Core/ConveyorBeltSlot.cs new file mode 100644 index 00000000..a973948f --- /dev/null +++ b/Assets/Scripts/Minigames/CardSorting/Core/ConveyorBeltSlot.cs @@ -0,0 +1,35 @@ +using UI.DragAndDrop.Core; +using UnityEngine; + +namespace Minigames.CardSorting.Core +{ + /// + /// Slot component for the conveyor belt. + /// Allows detection when items are dropped back onto the conveyor. + /// Place this on a UI element (Image/Panel) that covers the conveyor belt area. + /// + public class ConveyorBeltSlot : DraggableSlot + { + /// + /// Check if this slot can accept a specific draggable type. + /// ConveyorBeltSlot accepts all SortableItems. + /// + public new bool CanAccept(DraggableObject draggable) + { + // Accept all sortable items + return draggable is SortableItem; + } + + /// + /// Called when an item is dropped on the conveyor. + /// Items dropped here should return to their conveyor state. + /// + public void OnItemDroppedOnConveyor(SortableItem item) + { + if (item == null) return; + + Debug.Log($"[ConveyorBeltSlot] Item dropped back on conveyor: {item.CardData?.Name ?? item.GarbageItem?.DisplayName}"); + } + } +} + diff --git a/Assets/Scripts/Minigames/CardSorting/Core/ConveyorBeltSlot.cs.meta b/Assets/Scripts/Minigames/CardSorting/Core/ConveyorBeltSlot.cs.meta new file mode 100644 index 00000000..acf2e671 --- /dev/null +++ b/Assets/Scripts/Minigames/CardSorting/Core/ConveyorBeltSlot.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9304d17587314133a4d8d1e582cfbf81 +timeCreated: 1763590821 \ No newline at end of file diff --git a/Assets/Scripts/Minigames/CardSorting/Core/SortableItem.cs b/Assets/Scripts/Minigames/CardSorting/Core/SortableItem.cs index 53f4a77d..711cf2c8 100644 --- a/Assets/Scripts/Minigames/CardSorting/Core/SortableItem.cs +++ b/Assets/Scripts/Minigames/CardSorting/Core/SortableItem.cs @@ -28,7 +28,8 @@ namespace Minigames.CardSorting.Core // Events - item emits notifications, conveyor subscribes public event System.Action OnItemDroppedInBox; - public event System.Action OnItemReturnedToConveyor; + public event System.Action OnItemDroppedOnFloor; + public event System.Action OnItemReturnedToConveyor; // Fired when dropped back on conveyor // Public accessors public SortableItemContext Context => context; @@ -142,9 +143,10 @@ namespace Minigames.CardSorting.Core { base.OnDragEndedHook(); - // Validate drop on sorting box + // Check what type of slot we're over if (CurrentSlot is SortingBox box) { + // Dropped in sorting box bool correctSort = box.ValidateItem(this); // Fire event IMMEDIATELY when card is released over bin @@ -162,10 +164,28 @@ namespace Minigames.CardSorting.Core ChangeState("SortedIncorrectlyState"); } } + else if (CurrentSlot is ConveyorBeltSlot conveyorSlot) + { + // Dropped back on conveyor - return to conveyor state + Logging.Debug("[SortableItem] Dropped back on conveyor, returning to OnConveyorState"); + + // Notify conveyor slot + conveyorSlot.OnItemDroppedOnConveyor(this); + + // Fire event for conveyor controller to re-add to tracking + OnItemReturnedToConveyor?.Invoke(this); + + // Return to conveyor state + ChangeState("OnConveyorState"); + } else { - // Dropped outside valid box - transition to dropped on floor state - Logging.Debug("[SortableItem] Dropped outside box, transitioning to floor state"); + // Dropped outside valid box or conveyor - fire event then transition to dropped on floor state + Logging.Debug("[SortableItem] Dropped outside box/conveyor, transitioning to floor state"); + + // Fire event for conveyor controller to handle scoring + OnItemDroppedOnFloor?.Invoke(this); + ChangeState("DroppedOnFloorState"); } } @@ -174,6 +194,7 @@ namespace Minigames.CardSorting.Core /// /// Detect which slot (if any) is under the pointer during drag. /// Updates CurrentSlot for drop detection. + /// Scans for both SortingBox and ConveyorBeltSlot. /// private void DetectSlotUnderPointer(UnityEngine.EventSystems.PointerEventData eventData) { @@ -181,29 +202,46 @@ namespace Minigames.CardSorting.Core var raycastResults = new System.Collections.Generic.List(); UnityEngine.EventSystems.EventSystem.current.RaycastAll(eventData, raycastResults); - SortingBox hoveredBox = null; + DraggableSlot hoveredSlot = null; - // Find first SortingBox in raycast results + // Find first slot (SortingBox or ConveyorBeltSlot) in raycast results foreach (var result in raycastResults) { + // Check for SortingBox first (higher priority) var box = result.gameObject.GetComponentInParent(); if (box != null) { - hoveredBox = box; + hoveredSlot = box; + break; + } + + // Check for ConveyorBeltSlot if no box found + var conveyorSlot = result.gameObject.GetComponentInParent(); + if (conveyorSlot != null) + { + hoveredSlot = conveyorSlot; break; } } // Update current slot (used in OnDragEndedHook) - if (hoveredBox != null && hoveredBox != CurrentSlot) + if (hoveredSlot != null && hoveredSlot != CurrentSlot) { - _currentSlot = hoveredBox; - Logging.Debug($"[SortableItem] Now hovering over {hoveredBox.BoxType} box"); + _currentSlot = hoveredSlot; + + if (hoveredSlot is SortingBox sortBox) + { + Logging.Debug($"[SortableItem] Now hovering over {sortBox.BoxType} box"); + } + else if (hoveredSlot is ConveyorBeltSlot) + { + Logging.Debug("[SortableItem] Now hovering over conveyor belt"); + } } - else if (hoveredBox == null && CurrentSlot != null) + else if (hoveredSlot == null && CurrentSlot != null) { _currentSlot = null; - Logging.Debug("[SortableItem] No longer over any box"); + Logging.Debug("[SortableItem] No longer over any slot"); } } diff --git a/Assets/Scripts/Minigames/CardSorting/Core/SortingGameManager.cs b/Assets/Scripts/Minigames/CardSorting/Core/SortingGameManager.cs index 3fb03567..df818c63 100644 --- a/Assets/Scripts/Minigames/CardSorting/Core/SortingGameManager.cs +++ b/Assets/Scripts/Minigames/CardSorting/Core/SortingGameManager.cs @@ -29,9 +29,15 @@ namespace Minigames.CardSorting.Core [Header("Effects")] [SerializeField] private CinemachineImpulseSource impulseSource; // Screen shake on incorrect sort + [Header("UI References")] + [SerializeField] private UI.LivesDisplay livesDisplay; + // Settings private ICardSortingSettings _settings; + // Lives tracking + private int currentLives; + // Controllers (lazy init) private ConveyorBeltController _conveyorController; private ConveyorBeltController Conveyor => _conveyorController ??= new ConveyorBeltController( @@ -43,6 +49,9 @@ namespace Minigames.CardSorting.Core _settings ); + // Public accessor for states to check game over status + public ConveyorBeltController ConveyorController => Conveyor; + private SortingScoreController _scoreController; private SortingScoreController Score => _scoreController ??= new SortingScoreController(_settings); @@ -152,6 +161,13 @@ namespace Minigames.CardSorting.Core // Reset score Score.Reset(); + // Initialize lives + currentLives = _settings.MaxLives; + if (livesDisplay != null) + { + livesDisplay.Initialize(currentLives); + } + OnGameStarted?.Invoke(); // Set input mode to game @@ -163,6 +179,61 @@ namespace Minigames.CardSorting.Core Logging.Debug("[SortingGameManager] Game started!"); } + /// + /// Unified feedback for wrong actions (trash penalties). + /// Plays blink animation on item and triggers camera shake. + /// + public void PlayWrongStateFeedback(SortableItem item) + { + // Camera shake + if (impulseSource != null) + { + impulseSource.GenerateImpulse(); + } + + // Blink the item red (if it still exists) + if (item != null && item.Context != null && item.Context.Animator != null) + { + UnityEngine.UI.Image imageToBlink = null; + + if (item.Context.CardDisplay != null) + { + imageToBlink = item.Context.CardDisplay.GetComponent(); + } + else if (item.Context.GarbageVisual != null) + { + imageToBlink = item.Context.GarbageVisual.GetComponent(); + } + + if (imageToBlink != null) + { + item.Context.Animator.BlinkRed(imageToBlink, 0.15f); + } + } + } + + /// + /// Lose a life. If lives reach 0, end the game. + /// + private void LoseLife() + { + currentLives--; + + if (livesDisplay != null) + { + livesDisplay.RemoveLife(); + } + + Logging.Debug($"[SortingGameManager] Life lost! Remaining lives: {currentLives}"); + + // Check for game over + if (currentLives <= 0) + { + Logging.Debug("[SortingGameManager] No lives remaining - Game Over!"); + EndGame(); + } + } + public void EndGame() { if (isGameOver) return; @@ -170,6 +241,9 @@ namespace Minigames.CardSorting.Core isGameOver = true; isGameActive = false; + // Stop the conveyor and disable all items + Conveyor.StopConveyor(); + // Calculate rewards int boosterReward = Score.CalculateBoosterReward(); @@ -201,7 +275,7 @@ namespace Minigames.CardSorting.Core /// Called when item reaches visual end of belt (via conveyor event). /// Item continues moving off-screen until despawn point. /// Scoring rules: - /// - Trash fell off: Negative score (penalty) + /// - Trash fell off: Negative score (penalty) + lose life /// - Card fell off: Neutral (no score change) /// private void OnConveyorItemFellOff(SortableItem item) @@ -211,6 +285,8 @@ namespace Minigames.CardSorting.Core if (item.IsGarbage) { Score.RecordMissedItem(); + PlayWrongStateFeedback(item); + LoseLife(); Logging.Debug($"[SortingGameManager] Trash fell off belt! {item.GarbageItem?.DisplayName} - PENALTY"); } else @@ -228,7 +304,7 @@ namespace Minigames.CardSorting.Core /// /// Called when item is dropped on floor (via conveyor event). /// Scoring rules: - /// - Trash dropped on floor: Negative score (penalty) + /// - Trash dropped on floor: Negative score (penalty) + lose life /// - Card dropped on floor: Neutral (no score change) /// private void OnConveyorItemDroppedOnFloor(SortableItem item) @@ -238,13 +314,9 @@ namespace Minigames.CardSorting.Core if (item.IsGarbage) { Score.RecordIncorrectSort(); + PlayWrongStateFeedback(item); + LoseLife(); Logging.Debug($"[SortingGameManager] Trash dropped on floor! {item.GarbageItem?.DisplayName} - PENALTY"); - - // Trigger screen shake for trash dropped on floor - if (impulseSource != null) - { - impulseSource.GenerateImpulse(); - } } else { @@ -270,7 +342,7 @@ namespace Minigames.CardSorting.Core /// Handles scoring only - the state (SortedCorrectlyState/SortedIncorrectlyState) handles animation and destruction. /// Scoring rules: /// - Correct sort: Positive score (cards or trash in correct box) - /// - Incorrect trash: Negative score (trash in wrong box) + /// - Incorrect trash: Negative score (trash in wrong box) + lose life /// - Incorrect card: Neutral (no score change) /// private void OnConveyorItemSorted(SortableItem item, SortingBox box, bool correct) @@ -290,16 +362,12 @@ namespace Minigames.CardSorting.Core if (item.IsGarbage) { Score.RecordIncorrectSort(); + PlayWrongStateFeedback(item); + LoseLife(); Logging.Debug($"[SortingGameManager] Incorrect trash sort! {item.GarbageItem?.DisplayName} - PENALTY"); // Fire global incorrect sort event for effects OnItemSortedIncorrectly?.Invoke(item); - - // Trigger screen shake - if (impulseSource != null) - { - impulseSource.GenerateImpulse(); - } } else { diff --git a/Assets/Scripts/Minigames/CardSorting/StateMachine/States/BeingDraggedState.cs b/Assets/Scripts/Minigames/CardSorting/StateMachine/States/BeingDraggedState.cs index 1827b1a5..cafc769c 100644 --- a/Assets/Scripts/Minigames/CardSorting/StateMachine/States/BeingDraggedState.cs +++ b/Assets/Scripts/Minigames/CardSorting/StateMachine/States/BeingDraggedState.cs @@ -13,10 +13,12 @@ namespace Minigames.CardSorting.StateMachine.States public class BeingDraggedState : AppleState { private SortableItemContext _context; + private SortableItem _item; private void Awake() { _context = GetComponentInParent(); + _item = GetComponentInParent(); } public override void OnEnterState() @@ -24,9 +26,7 @@ namespace Minigames.CardSorting.StateMachine.States if (_context == null) return; _context.IsOnConveyor = false; - - // Visual feedback: scale up root transform by 10% - // Use OriginalScale from context (captured at spawn, preserves world-space Canvas scale) + if (_context.RootTransform != null && _context.Animator != null) { Vector3 targetScale = _context.OriginalScale * 1.1f; diff --git a/Assets/Scripts/Minigames/CardSorting/StateMachine/States/DroppedOnFloorState.cs b/Assets/Scripts/Minigames/CardSorting/StateMachine/States/DroppedOnFloorState.cs index 567aefb8..ca06396f 100644 --- a/Assets/Scripts/Minigames/CardSorting/StateMachine/States/DroppedOnFloorState.cs +++ b/Assets/Scripts/Minigames/CardSorting/StateMachine/States/DroppedOnFloorState.cs @@ -25,45 +25,11 @@ namespace Minigames.CardSorting.StateMachine.States _context.IsOnConveyor = false; - Logging.Debug("[DroppedOnFloorState] Item dropped on floor, blinking red then disappearing"); + Logging.Debug("[DroppedOnFloorState] Item dropped on floor, disappearing"); - // Blink red briefly, then play disappear animation - StartBlinkThenDisappear(); - } - - private void StartBlinkThenDisappear() - { - if (_context.Animator == null || _item == null) return; - - // Get the image to blink - UnityEngine.UI.Image imageToBlink = null; - - if (_context.CardDisplay != null) - { - imageToBlink = _context.CardDisplay.GetComponent(); - } - else if (_context.GarbageVisual != null) - { - imageToBlink = _context.GarbageVisual.GetComponent(); - } - - if (imageToBlink != null) - { - // Blink red briefly (2-3 times), then stop and disappear - _context.Animator.BlinkRed(imageToBlink, 0.15f); // Fast blink - - // After brief delay, stop blinking and play disappear animation - _context.Animator.AnimateScale(_context.RootTransform.localScale, 0.5f, () => - { - _context.Animator.StopBlinking(); - PlayDisappearAnimation(); - }); - } - else - { - // No image found, just disappear directly - PlayDisappearAnimation(); - } + // Feedback (blink + shake) already triggered by game manager when scoring (for trash) + // Just play disappear animation + PlayDisappearAnimation(); } private void PlayDisappearAnimation() diff --git a/Assets/Scripts/Minigames/CardSorting/StateMachine/States/FellOffConveyorState.cs b/Assets/Scripts/Minigames/CardSorting/StateMachine/States/FellOffConveyorState.cs index b3d7a519..070e3443 100644 --- a/Assets/Scripts/Minigames/CardSorting/StateMachine/States/FellOffConveyorState.cs +++ b/Assets/Scripts/Minigames/CardSorting/StateMachine/States/FellOffConveyorState.cs @@ -44,6 +44,12 @@ namespace Minigames.CardSorting.StateMachine.States { if (_context == null || !_context.IsOnConveyor) return; + // Stop moving if game is over + if (SortingGameManager.Instance.ConveyorController.IsGameOver) + { + return; + } + // Continue moving item toward despawn point (same logic as OnConveyorState) Vector3 movement = Vector3.right * _context.ConveyorSpeed * Time.deltaTime; _context.RootTransform.position += movement; diff --git a/Assets/Scripts/Minigames/CardSorting/StateMachine/States/OnConveyorState.cs b/Assets/Scripts/Minigames/CardSorting/StateMachine/States/OnConveyorState.cs index da42ed7f..53e0fd7e 100644 --- a/Assets/Scripts/Minigames/CardSorting/StateMachine/States/OnConveyorState.cs +++ b/Assets/Scripts/Minigames/CardSorting/StateMachine/States/OnConveyorState.cs @@ -40,6 +40,12 @@ namespace Minigames.CardSorting.StateMachine.States { if (_context == null || !_context.IsOnConveyor) return; + // Stop moving if game is over + if (SortingGameManager.Instance.ConveyorController.IsGameOver) + { + return; + } + // Move item along conveyor (right direction) Vector3 movement = Vector3.right * _context.ConveyorSpeed * Time.deltaTime; _context.RootTransform.position += movement; diff --git a/Assets/Scripts/Minigames/CardSorting/StateMachine/States/SortedIncorrectlyState.cs b/Assets/Scripts/Minigames/CardSorting/StateMachine/States/SortedIncorrectlyState.cs index 79ab65f1..2675697b 100644 --- a/Assets/Scripts/Minigames/CardSorting/StateMachine/States/SortedIncorrectlyState.cs +++ b/Assets/Scripts/Minigames/CardSorting/StateMachine/States/SortedIncorrectlyState.cs @@ -26,45 +26,11 @@ namespace Minigames.CardSorting.StateMachine.States _context.IsOnConveyor = false; - Logging.Debug("[SortedIncorrectlyState] Item incorrectly sorted, blinking red then tweening to box"); + Logging.Debug("[SortedIncorrectlyState] Item incorrectly sorted, tweening to box then falling in"); - // Start blinking red briefly, then tween to box - StartBlinkThenTween(); - } - - private void StartBlinkThenTween() - { - if (_context.Animator == null || _item == null) return; - - // Get the image to blink - UnityEngine.UI.Image imageToBlink = null; - - if (_context.CardDisplay != null) - { - imageToBlink = _context.CardDisplay.GetComponent(); - } - else if (_context.GarbageVisual != null) - { - imageToBlink = _context.GarbageVisual.GetComponent(); - } - - if (imageToBlink != null) - { - // Blink red briefly (2-3 times), then stop and continue with tween - _context.Animator.BlinkRed(imageToBlink, 0.15f); // Fast blink - - // After brief delay, stop blinking and tween to box - _context.Animator.AnimateScale(_context.RootTransform.localScale, 0.5f, () => - { - _context.Animator.StopBlinking(); - TweenToBoxThenFall(); - }); - } - else - { - // No image found, just tween directly - TweenToBoxThenFall(); - } + // Feedback (blink + shake) already triggered by game manager when scoring + // Just proceed with animation + TweenToBoxThenFall(); } private void TweenToBoxThenFall() diff --git a/Assets/Scripts/Minigames/CardSorting/UI/LivesDisplay.cs b/Assets/Scripts/Minigames/CardSorting/UI/LivesDisplay.cs new file mode 100644 index 00000000..ee2c89c0 --- /dev/null +++ b/Assets/Scripts/Minigames/CardSorting/UI/LivesDisplay.cs @@ -0,0 +1,208 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +namespace Minigames.CardSorting.UI +{ + /// + /// Displays and animates lives for the card sorting minigame. + /// Manages a layout group of life icons with add/remove animations. + /// + public class LivesDisplay : MonoBehaviour + { + [Header("Configuration")] + [SerializeField] private LayoutGroup layoutGroup; + + [Header("Animation Settings")] + [SerializeField] private float animationDuration = 0.3f; + [SerializeField] private float scaleMultiplier = 1.5f; + + private GameObject lifeIconPrefab; + private List lifeIcons = new List(); + + private void Awake() + { + if (layoutGroup == null) + { + layoutGroup = GetComponent(); + } + + // Find the prefab (first child) if not assigned + if (lifeIconPrefab == null && layoutGroup != null && layoutGroup.transform.childCount > 0) + { + lifeIconPrefab = layoutGroup.transform.GetChild(0).gameObject; + } + } + + /// + /// Initialize the display with the maximum number of lives. + /// Clones the prefab element multiple times. + /// + public void Initialize(int maxLives) + { + // Clear existing lives + ClearAllLives(); + + if (lifeIconPrefab == null) + { + Debug.LogError("[LivesDisplay] No life icon prefab assigned!"); + return; + } + + if (layoutGroup == null) + { + Debug.LogError("[LivesDisplay] No layout group assigned!"); + return; + } + + // Ensure prefab is active to use as template + bool wasActive = lifeIconPrefab.activeSelf; + lifeIconPrefab.SetActive(true); + lifeIcons.Add(lifeIconPrefab); + + // Create life icons + for (int i = 0; i < maxLives - 1; i++) + { + GameObject icon = Instantiate(lifeIconPrefab, layoutGroup.transform); + icon.SetActive(true); + lifeIcons.Add(icon); + } + + // Hide the original prefab + lifeIconPrefab.SetActive(wasActive); + } + + /// + /// Remove a life with animation. + /// + public void RemoveLife() + { + if (lifeIcons.Count == 0) + { + Debug.LogWarning("[LivesDisplay] No lives left to remove!"); + return; + } + + GameObject icon = lifeIcons[0]; + lifeIcons.RemoveAt(0); + + // Play removal animation + StartCoroutine(AnimateLifeRemoval(icon)); + } + + /// + /// Add a life with animation. + /// + public void AddLife() + { + if (lifeIconPrefab == null || layoutGroup == null) + { + Debug.LogError("[LivesDisplay] Cannot add life - missing prefab or layout group!"); + return; + } + + // Create new life icon + GameObject icon = Instantiate(lifeIconPrefab, layoutGroup.transform); + icon.SetActive(true); + lifeIcons.Add(icon); + + // Play addition animation + StartCoroutine(AnimateLifeAddition(icon)); + } + + /// + /// Clear all lives (for reset). + /// + private void ClearAllLives() + { + foreach (var icon in lifeIcons) + { + if (icon != null) + { + Destroy(icon); + } + } + lifeIcons.Clear(); + } + + /// + /// Animate life removal: scale up, then scale down and destroy. + /// + private IEnumerator AnimateLifeRemoval(GameObject icon) + { + if (icon == null) yield break; + + Vector3 originalScale = icon.transform.localScale; + Vector3 targetScale = originalScale * scaleMultiplier; + + // Scale up + yield return AnimateScale(icon.transform, originalScale, targetScale, animationDuration * 0.5f); + + // Scale down to zero + yield return AnimateScale(icon.transform, targetScale, Vector3.zero, animationDuration * 0.5f); + + // Destroy + if (icon != null) + { + Destroy(icon); + } + } + + /// + /// Animate life addition: start at zero, scale up beyond target, then settle to normal. + /// + private IEnumerator AnimateLifeAddition(GameObject icon) + { + if (icon == null) yield break; + + Vector3 originalScale = icon.transform.localScale; + Vector3 overshootScale = originalScale * scaleMultiplier; + + // Start at zero + icon.transform.localScale = Vector3.zero; + + // Scale up to overshoot + yield return AnimateScale(icon.transform, Vector3.zero, overshootScale, animationDuration * 0.5f); + + // Settle back to original scale + yield return AnimateScale(icon.transform, overshootScale, originalScale, animationDuration * 0.5f); + } + + /// + /// Generic scale animation coroutine. + /// + private IEnumerator AnimateScale(Transform target, Vector3 from, Vector3 to, float duration) + { + float elapsed = 0f; + + while (elapsed < duration) + { + elapsed += Time.deltaTime; + float t = Mathf.Clamp01(elapsed / duration); + + // Use ease-in-out curve for smooth animation + t = t * t * (3f - 2f * t); // Smoothstep + + if (target != null) + { + target.localScale = Vector3.Lerp(from, to, t); + } + + yield return null; + } + + // Ensure final scale is set + if (target != null) + { + target.localScale = to; + } + } + + /// + /// Get the current number of lives displayed. + /// + public int CurrentLives => lifeIcons.Count; + } +} + diff --git a/Assets/Scripts/Minigames/CardSorting/UI/LivesDisplay.cs.meta b/Assets/Scripts/Minigames/CardSorting/UI/LivesDisplay.cs.meta new file mode 100644 index 00000000..5a4f5f1b --- /dev/null +++ b/Assets/Scripts/Minigames/CardSorting/UI/LivesDisplay.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e8bcb252540442e593cc6467c518ff75 +timeCreated: 1763586518 \ No newline at end of file diff --git a/Assets/Scripts/Minigames/CardSorting/UI/SortingGameHUD.cs b/Assets/Scripts/Minigames/CardSorting/UI/SortingGameHUD.cs index 56bfbdd0..11bcd5b7 100644 --- a/Assets/Scripts/Minigames/CardSorting/UI/SortingGameHUD.cs +++ b/Assets/Scripts/Minigames/CardSorting/UI/SortingGameHUD.cs @@ -99,7 +99,8 @@ namespace Minigames.CardSorting.UI { if (scoreText == null) return; - scoreText.text = $"Score: {newScore}"; + // Only display numerical value (label is separate UI element) + scoreText.text = $"Score: {newScore.ToString()}"; // Color based on positive/negative if (newScore >= 0) diff --git a/Assets/Scripts/Minigames/CardSorting/UI/SortingResultsScreen.cs b/Assets/Scripts/Minigames/CardSorting/UI/SortingResultsScreen.cs index 507ffebb..033aa661 100644 --- a/Assets/Scripts/Minigames/CardSorting/UI/SortingResultsScreen.cs +++ b/Assets/Scripts/Minigames/CardSorting/UI/SortingResultsScreen.cs @@ -1,4 +1,6 @@ -using Minigames.CardSorting.Core; +using System; +using Core; +using Minigames.CardSorting.Core; using TMPro; using UnityEngine; using UnityEngine.UI; @@ -70,26 +72,26 @@ namespace Minigames.CardSorting.UI if (gameManager == null) return; - // Populate data + // Populate data - only numerical values (labels are separate UI elements) if (finalScoreText != null) - finalScoreText.text = $"Final Score: {gameManager.CurrentScore}"; + finalScoreText.text = gameManager.CurrentScore.ToString(); if (correctSortsText != null) - correctSortsText.text = $"Correct: {gameManager.CorrectSorts}"; + correctSortsText.text = gameManager.CorrectSorts.ToString(); if (incorrectSortsText != null) - incorrectSortsText.text = $"Incorrect: {gameManager.IncorrectSorts}"; + incorrectSortsText.text = gameManager.IncorrectSorts.ToString(); if (missedItemsText != null) - missedItemsText.text = $"Missed: {gameManager.MissedItems}"; + missedItemsText.text = gameManager.MissedItems.ToString(); if (accuracyText != null) - accuracyText.text = $"Accuracy: {gameManager.Accuracy:P0}"; + accuracyText.text = gameManager.Accuracy.ToString("P0"); // Calculate boosters (already granted by manager) int boosters = gameManager.CorrectSorts; // Simple 1:1 ratio if (boostersEarnedText != null) - boostersEarnedText.text = $"Boosters Earned: {boosters}"; + boostersEarnedText.text = boosters.ToString(); // Show screen if (canvasGroup != null) @@ -104,7 +106,7 @@ namespace Minigames.CardSorting.UI } } - private void OnCloseClicked() + private async void OnCloseClicked() { // Hide screen if (canvasGroup != null) @@ -118,8 +120,9 @@ namespace Minigames.CardSorting.UI gameObject.SetActive(false); } - // Could also trigger scene transition, return to menu, etc. - Debug.Log("[SortingResultsScreen] Closed results screen"); + // TODO: Smarter replay? + var progress = new Progress(p => Logging.Debug($"Loading progress: {p * 100:F0}%")); + await SceneManagerService.Instance.ReloadCurrentScene(progress); } } } diff --git a/Assets/Settings/CardSortingSettings.asset b/Assets/Settings/CardSortingSettings.asset index 14f98302..a9454056 100644 --- a/Assets/Settings/CardSortingSettings.asset +++ b/Assets/Settings/CardSortingSettings.asset @@ -46,7 +46,11 @@ MonoBehaviour: rareCardWeight: 30 legendCardWeight: 20 garbageWeight: 40 - correctSortPoints: 10 - incorrectSortPenalty: -5 - missedItemPenalty: -3 + correctSortPoints: 1 + incorrectSortPenalty: -1 + missedItemPenalty: 0 + maxLives: 3 boosterPacksPerCorrectItem: 1 + cardSize: {x: 100, y: 140} + spawnOffsetX: {x: -5, y: 5} + spawnOffsetY: {x: -2.5, y: 2.5}