diff --git a/Assets/GameUIController.cs b/Assets/GameUIController.cs index b602f67..14d15b5 100644 --- a/Assets/GameUIController.cs +++ b/Assets/GameUIController.cs @@ -17,11 +17,17 @@ public class GameUIController : MonoBehaviour [SerializeField] private Image profileImageB; [SerializeField] private Sprite[] profileImageSprites; //0. 기본 드래곤 1. 기본 호랑이 2.아이보리 드래곤 3. 아이보리 호랑이 [SerializeField] private Sprite[] indicatorSprites; //0. active 1. inactive - private Sprite _originalSpriteA; private Sprite _originalSpriteB; + private MultiplayManager _multiplayManager; + + private void Start() + { + _multiplayManager = GameManager.Instance.GetMultiplayManager(); + } + public void OnClickConfirmButton() { GameManager.Instance.OnClickConfirmButton(); @@ -36,9 +42,7 @@ public class GameUIController : MonoBehaviour { GameManager.Instance.panelManager.OpenConfirmPanel("항복 하시겠습니까?", () => { - //TODO: 서버에 항복 전달 및 기타 등등 - - GameManager.Instance.ChangeToMainScene(); + _multiplayManager.RequestSurrender(); }); } diff --git a/Assets/Resources/Prefabs/Audio Manager.prefab b/Assets/Resources/Prefabs/Audio Manager.prefab index 1fa43b9..47f54b7 100644 --- a/Assets/Resources/Prefabs/Audio Manager.prefab +++ b/Assets/Resources/Prefabs/Audio Manager.prefab @@ -10,7 +10,6 @@ GameObject: m_Component: - component: {fileID: 2402232447803946232} - component: {fileID: 3667565604047053759} - - component: {fileID: 841089304725320238} m_Layer: 0 m_Name: Audio Manager m_TagString: Untagged @@ -46,103 +45,16 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: mainBgm: {fileID: 8300000, guid: 1d9c7fb20aa822c48933d00b6bd6a757, type: 3} - gameBgm: {fileID: 8300000, guid: 6d4eda23943dd0b4099b86b28fa0840c, type: 3} + gameBgm: {fileID: 8300000, guid: 576c895328ccd5f4a91364f7fa42bea8, type: 3} clickSound: {fileID: 8300000, guid: cff2e6cf7f46a074d86955b3b6fd499a, type: 3} closeSound: {fileID: 8300000, guid: e7c0f32158a3e5b46bc3b59035aba898, type: 3} - sfxVolume: 0 ---- !u!82 &841089304725320238 -AudioSource: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2946408323859178723} - m_Enabled: 1 - serializedVersion: 4 - OutputAudioMixerGroup: {fileID: 0} - m_audioClip: {fileID: 0} - m_PlayOnAwake: 1 - m_Volume: 1 - m_Pitch: 1 - Loop: 0 - Mute: 0 - Spatialize: 0 - SpatializePostEffects: 0 - Priority: 128 - DopplerLevel: 1 - MinDistance: 1 - MaxDistance: 500 - Pan2D: 0 - rolloffMode: 0 - BypassEffects: 0 - BypassListenerEffects: 0 - BypassReverbZones: 0 - rolloffCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 1 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - - serializedVersion: 3 - time: 1 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - panLevelCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - spreadCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - reverbZoneMixCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 1 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 + coinsAddSound: {fileID: 8300000, guid: 1ec44182fa76a4b3eb1459c0a6d9a8ab, type: 3} + coinsEmptySound: {fileID: 8300000, guid: 908a78cb991984977bea42916bed8684, type: 3} + coinsRemoveSound: {fileID: 8300000, guid: 585a9de0fb7ee4163af5c559ba5b2364, type: 3} + winSound: {fileID: 8300000, guid: 1613a4bf934e4d043b4e50b1b74c16b5, type: 3} + loseSound: {fileID: 8300000, guid: 2a467daa72a01214384d2fa5677f668a, type: 3} + stoneSound: {fileID: 8300000, guid: 829ae38dccffa8f4ebf5829b8963ad31, type: 3} + bgmAudioSource: {fileID: 0} + sfxVolume: 1 + isPlayBGM: 0 + isPlaySFX: 0 diff --git a/Assets/Resources/Prefabs/Effects/Draw Effect Panel.prefab b/Assets/Resources/Prefabs/Effects/Draw Effect Panel.prefab index c7dccab..c1d50fe 100644 --- a/Assets/Resources/Prefabs/Effects/Draw Effect Panel.prefab +++ b/Assets/Resources/Prefabs/Effects/Draw Effect Panel.prefab @@ -527,6 +527,7 @@ GameObject: - component: {fileID: 8635639988778983738} - component: {fileID: 4545556044007292713} - component: {fileID: 6152865991947934791} + - component: {fileID: 3813612584874639807} m_Layer: 5 m_Name: Draw Effect Panel m_TagString: Untagged @@ -624,3 +625,48 @@ MonoBehaviour: tigerOpenEyes: {fileID: 1508819185250841244} tigerCloseEyes: {fileID: 399504369641388738} flipDuration: 0.3 +--- !u!61 &3813612584874639807 +BoxCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8383435151006156655} + m_Enabled: 1 + m_Density: 1 + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_ForceSendLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ForceReceiveLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ContactCaptureLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_CallbackLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_IsTrigger: 0 + m_UsedByEffector: 0 + m_UsedByComposite: 0 + m_Offset: {x: 0, y: 0} + m_SpriteTilingProperty: + border: {x: 0, y: 0, z: 0, w: 0} + pivot: {x: 0, y: 0} + oldSize: {x: 0, y: 0} + newSize: {x: 0, y: 0} + adaptiveTilingThreshold: 0 + drawMode: 0 + adaptiveTiling: 0 + m_AutoTiling: 0 + serializedVersion: 2 + m_Size: {x: 1, y: 1} + m_EdgeRadius: 0 diff --git a/Assets/Resources/Prefabs/Effects/Lose Effect Panel.prefab b/Assets/Resources/Prefabs/Effects/Lose Effect Panel.prefab index 82b84f5..d845fd9 100644 --- a/Assets/Resources/Prefabs/Effects/Lose Effect Panel.prefab +++ b/Assets/Resources/Prefabs/Effects/Lose Effect Panel.prefab @@ -450,6 +450,7 @@ GameObject: - component: {fileID: 8635639988778983738} - component: {fileID: 4545556044007292713} - component: {fileID: 3229800624310508893} + - component: {fileID: 6984539173991577744} m_Layer: 5 m_Name: Lose Effect Panel m_TagString: Untagged @@ -546,3 +547,48 @@ MonoBehaviour: characterOpenEyes: {fileID: 1632927645355555415} characterCloseEyes: {fileID: 3881260292094838299} depressedEffect: {fileID: 155037671892554820} +--- !u!61 &6984539173991577744 +BoxCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8383435151006156655} + m_Enabled: 1 + m_Density: 1 + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_ForceSendLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ForceReceiveLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ContactCaptureLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_CallbackLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_IsTrigger: 0 + m_UsedByEffector: 0 + m_UsedByComposite: 0 + m_Offset: {x: 0, y: 0} + m_SpriteTilingProperty: + border: {x: 0, y: 0, z: 0, w: 0} + pivot: {x: 0, y: 0} + oldSize: {x: 0, y: 0} + newSize: {x: 0, y: 0} + adaptiveTilingThreshold: 0 + drawMode: 0 + adaptiveTiling: 0 + m_AutoTiling: 0 + serializedVersion: 2 + m_Size: {x: 1, y: 1} + m_EdgeRadius: 0 diff --git a/Assets/Resources/Prefabs/Effects/Win Effect Panel.prefab b/Assets/Resources/Prefabs/Effects/Win Effect Panel.prefab index c8e9768..75a7c3f 100644 --- a/Assets/Resources/Prefabs/Effects/Win Effect Panel.prefab +++ b/Assets/Resources/Prefabs/Effects/Win Effect Panel.prefab @@ -788,6 +788,7 @@ GameObject: - component: {fileID: 8635639988778983738} - component: {fileID: 3127148509640414758} - component: {fileID: 4545556044007292713} + - component: {fileID: 7229651074095795597} m_Layer: 5 m_Name: Win Effect Panel m_TagString: Untagged @@ -866,7 +867,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 9b132148519758c42824252ec9a2d3a4, type: 3} m_Name: m_EditorClassIdentifier: - bannerObj: {fileID: 0} + bannerObj: {fileID: 7291411618834705046} bannerText: {fileID: 5108301403921453943} interval: 0.1 haloEffectImg: {fileID: 376994097320605198} @@ -890,6 +891,51 @@ CanvasGroup: m_Interactable: 1 m_BlocksRaycasts: 1 m_IgnoreParentGroups: 0 +--- !u!61 &7229651074095795597 +BoxCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8383435151006156655} + m_Enabled: 1 + m_Density: 1 + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_ForceSendLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ForceReceiveLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_ContactCaptureLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_CallbackLayers: + serializedVersion: 2 + m_Bits: 4294967295 + m_IsTrigger: 0 + m_UsedByEffector: 0 + m_UsedByComposite: 0 + m_Offset: {x: 0, y: 0} + m_SpriteTilingProperty: + border: {x: 0, y: 0, z: 0, w: 0} + pivot: {x: 0, y: 0} + oldSize: {x: 0, y: 0} + newSize: {x: 0, y: 0} + adaptiveTilingThreshold: 0 + drawMode: 0 + adaptiveTiling: 0 + m_AutoTiling: 0 + serializedVersion: 2 + m_Size: {x: 1, y: 1} + m_EdgeRadius: 0 --- !u!1 &8851077685063213123 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Resources/Prefabs/Panels/Coins Panel.prefab b/Assets/Resources/Prefabs/Panels/Coins Panel.prefab index 93b08f8..7596238 100644 --- a/Assets/Resources/Prefabs/Panels/Coins Panel.prefab +++ b/Assets/Resources/Prefabs/Panels/Coins Panel.prefab @@ -10,7 +10,6 @@ GameObject: m_Component: - component: {fileID: 1769668775421633028} - component: {fileID: 4222531876603999234} - - component: {fileID: 5499754916380040505} m_Layer: 5 m_Name: Coins Panel m_TagString: Untagged @@ -53,106 +52,6 @@ MonoBehaviour: m_EditorClassIdentifier: coinsRemoveImageObject: {fileID: 4198953742281733827} coinsCountText: {fileID: 2892066450466788586} - coinsRemoveAudioClip: {fileID: 8300000, guid: 585a9de0fb7ee4163af5c559ba5b2364, type: 3} - coinsAddAudioClip: {fileID: 8300000, guid: 1ec44182fa76a4b3eb1459c0a6d9a8ab, type: 3} - coinsEmptyAudioClip: {fileID: 8300000, guid: 908a78cb991984977bea42916bed8684, type: 3} - ShopPanel: {fileID: 8190964574954487140, guid: eb257b0a685b2254f860f294ce8cba54, type: 3} ---- !u!82 &5499754916380040505 -AudioSource: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 646100354038727038} - m_Enabled: 1 - serializedVersion: 4 - OutputAudioMixerGroup: {fileID: 0} - m_audioClip: {fileID: 0} - m_PlayOnAwake: 1 - m_Volume: 1 - m_Pitch: 1 - Loop: 0 - Mute: 0 - Spatialize: 0 - SpatializePostEffects: 0 - Priority: 128 - DopplerLevel: 1 - MinDistance: 1 - MaxDistance: 500 - Pan2D: 0 - rolloffMode: 0 - BypassEffects: 0 - BypassListenerEffects: 0 - BypassReverbZones: 0 - rolloffCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 1 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - - serializedVersion: 3 - time: 1 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - panLevelCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - spreadCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - reverbZoneMixCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 1 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 --- !u!1 &4198953742281733827 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Resources/Prefabs/Panels/Setting Panel.prefab b/Assets/Resources/Prefabs/Panels/Setting Panel.prefab index 61d981c..54538f0 100644 --- a/Assets/Resources/Prefabs/Panels/Setting Panel.prefab +++ b/Assets/Resources/Prefabs/Panels/Setting Panel.prefab @@ -13,9 +13,8 @@ GameObject: - component: {fileID: 5762671619601460934} - component: {fileID: 6789969287113785900} - component: {fileID: 413977444317235173} - - component: {fileID: 6428684691423417346} m_Layer: 5 - m_Name: Switch + m_Name: BGM Switch m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -148,103 +147,6 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: handleImage: {fileID: 6756679498073114696} - clickSound: {fileID: 8300000, guid: cff2e6cf7f46a074d86955b3b6fd499a, type: 3} ---- !u!82 &6428684691423417346 -AudioSource: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 212417647848747046} - m_Enabled: 1 - serializedVersion: 4 - OutputAudioMixerGroup: {fileID: 0} - m_audioClip: {fileID: 0} - m_PlayOnAwake: 1 - m_Volume: 1 - m_Pitch: 1 - Loop: 0 - Mute: 0 - Spatialize: 0 - SpatializePostEffects: 0 - Priority: 128 - DopplerLevel: 1 - MinDistance: 1 - MaxDistance: 500 - Pan2D: 0 - rolloffMode: 0 - BypassEffects: 0 - BypassListenerEffects: 0 - BypassReverbZones: 0 - rolloffCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 1 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - - serializedVersion: 3 - time: 1 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - panLevelCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - spreadCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - reverbZoneMixCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 1 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 --- !u!1 &1754413034098038561 GameObject: m_ObjectHideFlags: 0 @@ -859,9 +761,8 @@ GameObject: - component: {fileID: 2622934673103949083} - component: {fileID: 3464089222698319368} - component: {fileID: 8434701791193156984} - - component: {fileID: 9145795730378986889} m_Layer: 5 - m_Name: Switch + m_Name: SFX Switch m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -994,103 +895,6 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: handleImage: {fileID: 1822478720763898751} - clickSound: {fileID: 8300000, guid: cff2e6cf7f46a074d86955b3b6fd499a, type: 3} ---- !u!82 &9145795730378986889 -AudioSource: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5387157431517620447} - m_Enabled: 1 - serializedVersion: 4 - OutputAudioMixerGroup: {fileID: 0} - m_audioClip: {fileID: 0} - m_PlayOnAwake: 1 - m_Volume: 1 - m_Pitch: 1 - Loop: 0 - Mute: 0 - Spatialize: 0 - SpatializePostEffects: 0 - Priority: 128 - DopplerLevel: 1 - MinDistance: 1 - MaxDistance: 500 - Pan2D: 0 - rolloffMode: 0 - BypassEffects: 0 - BypassListenerEffects: 0 - BypassReverbZones: 0 - rolloffCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 1 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - - serializedVersion: 3 - time: 1 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - panLevelCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - spreadCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 0 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 - reverbZoneMixCustomCurve: - serializedVersion: 2 - m_Curve: - - serializedVersion: 3 - time: 0 - value: 1 - inSlope: 0 - outSlope: 0 - tangentMode: 0 - weightedMode: 0 - inWeight: 0.33333334 - outWeight: 0.33333334 - m_PreInfinity: 2 - m_PostInfinity: 2 - m_RotationOrder: 4 --- !u!1 &7654744771681034987 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Resources/Prefabs/Panels/Signup Panel.prefab b/Assets/Resources/Prefabs/Panels/Signup Panel.prefab index ce1a083..0e81082 100644 --- a/Assets/Resources/Prefabs/Panels/Signup Panel.prefab +++ b/Assets/Resources/Prefabs/Panels/Signup Panel.prefab @@ -1347,7 +1347,19 @@ MonoBehaviour: m_Calls: [] m_OnDeselect: m_PersistentCalls: - m_Calls: [] + m_Calls: + - m_Target: {fileID: 5818338764896528680} + m_TargetAssemblyTypeName: SignupPanelController, Assembly-CSharp + m_MethodName: OnChangeEndPassword + m_Mode: 0 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 m_OnTextSelection: m_PersistentCalls: m_Calls: [] @@ -2141,7 +2153,19 @@ MonoBehaviour: m_Calls: [] m_OnValueChanged: m_PersistentCalls: - m_Calls: [] + m_Calls: + - m_Target: {fileID: 5818338764896528680} + m_TargetAssemblyTypeName: SignupPanelController, Assembly-CSharp + m_MethodName: OnChangeNickname + m_Mode: 0 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 m_OnTouchScreenKeyboardStatusChanged: m_PersistentCalls: m_Calls: [] @@ -2791,10 +2815,34 @@ MonoBehaviour: m_Calls: [] m_OnSelect: m_PersistentCalls: - m_Calls: [] + m_Calls: + - m_Target: {fileID: 5818338764896528680} + m_TargetAssemblyTypeName: SignupPanelController, Assembly-CSharp + m_MethodName: OnSelectEmail + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 m_OnDeselect: m_PersistentCalls: - m_Calls: [] + m_Calls: + - m_Target: {fileID: 5818338764896528680} + m_TargetAssemblyTypeName: SignupPanelController, Assembly-CSharp + m_MethodName: OnChangeEndEmail + m_Mode: 0 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 m_OnTextSelection: m_PersistentCalls: m_Calls: [] diff --git a/Assets/Resources/Sounds.meta b/Assets/Resources/Sounds.meta new file mode 100644 index 0000000..faa8993 --- /dev/null +++ b/Assets/Resources/Sounds.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9fc9c29bf8c5aa040aaeace773096d1b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Click Sound.mp3 b/Assets/Resources/Sounds/Click Sound.mp3 similarity index 100% rename from Assets/Resources/Click Sound.mp3 rename to Assets/Resources/Sounds/Click Sound.mp3 diff --git a/Assets/Resources/Click Sound.mp3.meta b/Assets/Resources/Sounds/Click Sound.mp3.meta similarity index 100% rename from Assets/Resources/Click Sound.mp3.meta rename to Assets/Resources/Sounds/Click Sound.mp3.meta diff --git a/Assets/Resources/Close Sound.mp3 b/Assets/Resources/Sounds/Close Sound.mp3 similarity index 100% rename from Assets/Resources/Close Sound.mp3 rename to Assets/Resources/Sounds/Close Sound.mp3 diff --git a/Assets/Resources/Close Sound.mp3.meta b/Assets/Resources/Sounds/Close Sound.mp3.meta similarity index 100% rename from Assets/Resources/Close Sound.mp3.meta rename to Assets/Resources/Sounds/Close Sound.mp3.meta diff --git a/Assets/Resources/Coins_ADD_Sound.wav b/Assets/Resources/Sounds/Coins ADD Sound.wav similarity index 100% rename from Assets/Resources/Coins_ADD_Sound.wav rename to Assets/Resources/Sounds/Coins ADD Sound.wav diff --git a/Assets/Resources/Coins_ADD_Sound.wav.meta b/Assets/Resources/Sounds/Coins ADD Sound.wav.meta similarity index 100% rename from Assets/Resources/Coins_ADD_Sound.wav.meta rename to Assets/Resources/Sounds/Coins ADD Sound.wav.meta diff --git a/Assets/Resources/Coins_Empty_Sound.wav b/Assets/Resources/Sounds/Coins Empty Sound.wav similarity index 100% rename from Assets/Resources/Coins_Empty_Sound.wav rename to Assets/Resources/Sounds/Coins Empty Sound.wav diff --git a/Assets/Resources/Coins_Empty_Sound.wav.meta b/Assets/Resources/Sounds/Coins Empty Sound.wav.meta similarity index 100% rename from Assets/Resources/Coins_Empty_Sound.wav.meta rename to Assets/Resources/Sounds/Coins Empty Sound.wav.meta diff --git a/Assets/Resources/Coins_Remove_Sound.wav b/Assets/Resources/Sounds/Coins Remove Sound.wav similarity index 100% rename from Assets/Resources/Coins_Remove_Sound.wav rename to Assets/Resources/Sounds/Coins Remove Sound.wav diff --git a/Assets/Resources/Coins_Remove_Sound.wav.meta b/Assets/Resources/Sounds/Coins Remove Sound.wav.meta similarity index 100% rename from Assets/Resources/Coins_Remove_Sound.wav.meta rename to Assets/Resources/Sounds/Coins Remove Sound.wav.meta diff --git a/Assets/Resources/Sounds/Game bgm2.mp3 b/Assets/Resources/Sounds/Game bgm2.mp3 new file mode 100644 index 0000000..6e753a4 Binary files /dev/null and b/Assets/Resources/Sounds/Game bgm2.mp3 differ diff --git a/Assets/Resources/Sounds/Game bgm2.mp3.meta b/Assets/Resources/Sounds/Game bgm2.mp3.meta new file mode 100644 index 0000000..15e5280 --- /dev/null +++ b/Assets/Resources/Sounds/Game bgm2.mp3.meta @@ -0,0 +1,23 @@ +fileFormatVersion: 2 +guid: 576c895328ccd5f4a91364f7fa42bea8 +AudioImporter: + externalObjects: {} + serializedVersion: 7 + defaultSettings: + serializedVersion: 2 + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + preloadAudioData: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + loadInBackground: 0 + ambisonic: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/lose sound.mp3 b/Assets/Resources/Sounds/lose sound.mp3 similarity index 100% rename from Assets/Resources/lose sound.mp3 rename to Assets/Resources/Sounds/lose sound.mp3 diff --git a/Assets/Resources/lose sound.mp3.meta b/Assets/Resources/Sounds/lose sound.mp3.meta similarity index 100% rename from Assets/Resources/lose sound.mp3.meta rename to Assets/Resources/Sounds/lose sound.mp3.meta diff --git a/Assets/Resources/main bgm.mp3 b/Assets/Resources/Sounds/main bgm.mp3 similarity index 100% rename from Assets/Resources/main bgm.mp3 rename to Assets/Resources/Sounds/main bgm.mp3 diff --git a/Assets/Resources/main bgm.mp3.meta b/Assets/Resources/Sounds/main bgm.mp3.meta similarity index 100% rename from Assets/Resources/main bgm.mp3.meta rename to Assets/Resources/Sounds/main bgm.mp3.meta diff --git a/Assets/Resources/stone sound 3.mp3 b/Assets/Resources/Sounds/stone sound 3.mp3 similarity index 100% rename from Assets/Resources/stone sound 3.mp3 rename to Assets/Resources/Sounds/stone sound 3.mp3 diff --git a/Assets/Resources/stone sound 3.mp3.meta b/Assets/Resources/Sounds/stone sound 3.mp3.meta similarity index 100% rename from Assets/Resources/stone sound 3.mp3.meta rename to Assets/Resources/Sounds/stone sound 3.mp3.meta diff --git a/Assets/Resources/Sounds/win sound.mp3 b/Assets/Resources/Sounds/win sound.mp3 new file mode 100644 index 0000000..6c1153f Binary files /dev/null and b/Assets/Resources/Sounds/win sound.mp3 differ diff --git a/Assets/Resources/Sounds/win sound.mp3.meta b/Assets/Resources/Sounds/win sound.mp3.meta new file mode 100644 index 0000000..fb95f3c --- /dev/null +++ b/Assets/Resources/Sounds/win sound.mp3.meta @@ -0,0 +1,23 @@ +fileFormatVersion: 2 +guid: 1613a4bf934e4d043b4e50b1b74c16b5 +AudioImporter: + externalObjects: {} + serializedVersion: 7 + defaultSettings: + serializedVersion: 2 + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + preloadAudioData: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + loadInBackground: 0 + ambisonic: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Script/Common/AudioManager.cs b/Assets/Script/Common/AudioManager.cs index fcb7ff3..01465c9 100644 --- a/Assets/Script/Common/AudioManager.cs +++ b/Assets/Script/Common/AudioManager.cs @@ -1,41 +1,71 @@ -using UnityEngine; +using System.Collections.Generic; +using UnityEngine; using UnityEngine.SceneManagement; +using UnityEngine.Timeline; public class AudioManager : Singleton { - [Header("BGM")] - [SerializeField] private AudioClip mainBgm; - [SerializeField] private AudioClip gameBgm; - [Header("SFX")] - [SerializeField] private AudioClip clickSound; - [SerializeField] private AudioClip closeSound; + private AudioClip mainBgm; + private AudioClip gameBgm; - private AudioSource bgmAudioSource; // BGM을 위한 AudioSource + [HideInInspector] public AudioSource bgmAudioSource; // BGM을 위한 AudioSource private AudioSource sfxAudioSource; // SFX를 위한 AudioSource - [HideInInspector] public float sfxVolume = 1.0f; // SFX 볼륨 (기본값 1) + public float sfxVolume = 1.0f; // SFX 볼륨 (기본값 1) - private void Awake() + [HideInInspector]public bool isPlayBGM; + [HideInInspector]public bool isPlaySFX; + + private Dictionary audioClips = new Dictionary(); + + + protected override void Awake() { base.Awake(); // 부모 클래스의 Awake 호출 // BGM과 SFX를 위한 별도의 AudioSource 생성 bgmAudioSource = gameObject.AddComponent(); sfxAudioSource = gameObject.AddComponent(); + + //Sounds폴더 내의 모든 오디오클립 로드 + AudioClip[] clips = Resources.LoadAll("Sounds"); + + foreach (AudioClip clip in clips) + { + audioClips[clip.name] = clip; + } + + Debug.Log($"총 {audioClips.Count}개의 오디오클립이 로드됨."); + + } + + public AudioClip GetAudioClip(string clipName) + { + if (audioClips.TryGetValue(clipName, out AudioClip clip)) + { + return clip; + } + else + { + Debug.LogError($"패널 '{clipName}'을 찾을 수 없습니다."); + } + return null; } // 시작 시 BGM을 자동으로 재생 private void Start() { - if (UserManager.IsPlayBGM) // UserManager의 BGM 설정값에 따라 BGM을 재생 - { - PlayMainBGM(); // 기본 BGM을 재생 - } + isPlayBGM = UserManager.IsPlayBGM; + isPlaySFX = UserManager.IsPlaySFX; + + PlayBGM(); } // 메인 BGM을 재생하는 함수 public void PlayMainBGM() { + mainBgm = GetAudioClip("main bgm"); + if (bgmAudioSource != null && mainBgm != null && !bgmAudioSource.isPlaying) { bgmAudioSource.clip = mainBgm; @@ -44,18 +74,11 @@ public class AudioManager : Singleton bgmAudioSource.Play(); // BGM 재생 } } - - // BGM을 멈추는 함수 - public void StopMainBGM() - { - if (bgmAudioSource != null && bgmAudioSource.isPlaying) - { - bgmAudioSource.Stop(); // BGM을 멈춤 - } - } public void PlayGameBGM() { + gameBgm = GetAudioClip("Game bgm2"); + if (bgmAudioSource != null && gameBgm != null && !bgmAudioSource.isPlaying) { bgmAudioSource.clip = gameBgm; @@ -64,53 +87,103 @@ public class AudioManager : Singleton bgmAudioSource.Play(); // 게임 BGM 재생 } } + + public void PlayBGM() + { + if (isPlayBGM) + { + Scene currentScene = SceneManager.GetActiveScene(); + + if (currentScene.name == "Main") + { + StopBGM(); + PlayMainBGM(); + } + else if (currentScene.name == "Game") + { + StopBGM(); + PlayGameBGM(); + } + } + } - public void StopGameBGM() + public void StopBGM() { if (bgmAudioSource != null && bgmAudioSource.isPlaying) { bgmAudioSource.Stop(); // 게임용 BGM을 멈춤 } } + + // 씬이 로드될 때마다 호출되는 OnSceneLoaded 메서드 + protected override void OnSceneLoaded(Scene scene, LoadSceneMode mode) + { + PlayBGM(); + } // 클릭 사운드(SFX) 재생 public void PlayClickSound() { - if (sfxAudioSource != null) + if (isPlaySFX && sfxAudioSource != null) { - sfxAudioSource.PlayOneShot(clickSound, sfxVolume); + sfxAudioSource.PlayOneShot(GetAudioClip("Click Sound"), sfxVolume); } } // 닫기 사운드(SFX) 재생 public void PlayCloseSound() { - if (sfxAudioSource != null) + if (isPlaySFX && sfxAudioSource != null) { - sfxAudioSource.PlayOneShot(closeSound, sfxVolume); + sfxAudioSource.PlayOneShot(GetAudioClip("Close Sound"), sfxVolume); } } - // 씬이 로드될 때마다 호출되는 OnSceneLoaded 메서드 - protected override void OnSceneLoaded(Scene scene, LoadSceneMode mode) + public void PlayCoinsAddSound() { - if (scene.name == "Main") + if (isPlaySFX && sfxAudioSource!=null) { - StopGameBGM(); - - if (UserManager.IsPlayBGM) // BGM 설정값에 따라 메인 BGM을 재생 - { - PlayMainBGM(); - } + sfxAudioSource.PlayOneShot(GetAudioClip("Coins ADD Sound"), sfxVolume); } - else if (scene.name == "Game") + } + + public void PlayCoinsEmptySound() + { + if (isPlaySFX && sfxAudioSource!=null) { - StopMainBGM(); - - if (UserManager.IsPlayBGM) // BGM 설정값에 따라 게임 BGM을 재생 - { - PlayGameBGM(); - } + sfxAudioSource.PlayOneShot(GetAudioClip("Coins Empty Sound"), sfxVolume); + } + } + + public void PlayCoinsRemoveSound() + { + if (isPlaySFX && sfxAudioSource!=null) + { + sfxAudioSource.PlayOneShot(GetAudioClip("Coins Remove Sound"), sfxVolume); + } + } + + public void PlayLoseSound() + { + if (isPlaySFX && sfxAudioSource!=null) + { + sfxAudioSource.PlayOneShot(GetAudioClip("lose sound"), sfxVolume); + } + } + + public void PlayWinSound() + { + if (isPlaySFX && sfxAudioSource!=null) + { + sfxAudioSource.PlayOneShot(GetAudioClip("win sound"), sfxVolume); + } + } + + public void PlayStoneSound() + { + if (isPlaySFX && sfxAudioSource!=null) + { + sfxAudioSource.PlayOneShot(GetAudioClip("stone sound3"), sfxVolume); } } } \ No newline at end of file diff --git a/Assets/Script/Common/CoinsPanelController.cs b/Assets/Script/Common/CoinsPanelController.cs index a51c973..b184828 100644 --- a/Assets/Script/Common/CoinsPanelController.cs +++ b/Assets/Script/Common/CoinsPanelController.cs @@ -6,16 +6,11 @@ using UnityEngine.EventSystems; using UnityEngine.Serialization; using UnityEngine.UI; -[RequireComponent(typeof(AudioSource))] public class CoinsPanelController : MonoBehaviour { [SerializeField] private GameObject coinsRemoveImageObject; [SerializeField] private TMP_Text coinsCountText; - [SerializeField] private AudioClip coinsRemoveAudioClip; - [SerializeField] private AudioClip coinsAddAudioClip; - [SerializeField] private AudioClip coinsEmptyAudioClip; - private Color _coinsColor; private AudioSource _audioSource; private int _coinsCount; @@ -58,7 +53,7 @@ public class CoinsPanelController : MonoBehaviour _coinsRect.sizeDelta = new Vector2(100 + textLength * 30f, 100f); } - private void ChangeTextAnimation(bool isAdd, Action action) + private void ChangeTextAnimation(int coinAdd, bool isAdd, Action action) { float duration = 0.2f; float yPos = 40f; @@ -69,8 +64,8 @@ public class CoinsPanelController : MonoBehaviour if (isAdd) { var currentHeartCount = coinsCountText.text; - coinsCountText.text = (int.Parse(currentHeartCount) + 500).ToString(); - // 코인 텍스트 100씩 증가 + coinsCountText.text = (int.Parse(currentHeartCount) + coinAdd).ToString(); + // 코인 텍스트 증가 } else { @@ -103,26 +98,21 @@ public class CoinsPanelController : MonoBehaviour _canvasGroup.blocksRaycasts = false; //코인 중복 추가 방지 코드 Sequence sequence = DOTween.Sequence(); - // i += a 반복 횟수 조절, 100개 단위로 상승 차감 시 100으로 설정 - for (int i = 0; i < coinsCount; i+=500) + sequence.AppendCallback(() => { - sequence.AppendCallback(() => + ChangeTextAnimation(coinsCount,true, ()=> { - ChangeTextAnimation(true, ()=> - { - // TODO : 코인 수량 업데이트 - action?.Invoke(); - }); - - // 효과음 재생 - // TODO : if (UserInformation.IsPlaySFX) - _audioSource.PlayOneShot(coinsAddAudioClip); + _coinsCount += coinsCount; + action?.Invoke(); }); - sequence.AppendInterval(0.5f); - } + + // 효과음 재생 + AudioManager.Instance.PlayCoinsAddSound(); + }); + sequence.AppendInterval(0.5f); + sequence.OnComplete(() => { - _coinsCount += coinsCount; //추가된 코인 적용 _canvasGroup.blocksRaycasts = true; //구매 후 클릭 활성화 }); } @@ -130,8 +120,7 @@ public class CoinsPanelController : MonoBehaviour public void EmptyCoins() { // 효과음 재생 - // TODO: if (UserInformation.IsPlaySFX) - _audioSource.PlayOneShot(coinsEmptyAudioClip); + AudioManager.Instance.PlayCoinsEmptySound(); GetComponent().DOPunchPosition(new Vector3(20f, 0, 0), 1f, 7); } @@ -151,8 +140,7 @@ public class CoinsPanelController : MonoBehaviour } // 효과음 재생 - // TODO: if (UserInformation.IsPlaySFX) - _audioSource.PlayOneShot(coinsRemoveAudioClip); + AudioManager.Instance.PlayCoinsRemoveSound(); // 코인 사라지는 연출 coinsRemoveImageObject.SetActive(true); @@ -161,7 +149,7 @@ public class CoinsPanelController : MonoBehaviour coinsRemoveImageObject.transform.DOScale(3f, 1f); coinsRemoveImageObject.GetComponent().DOFade(0f, 1f) - .OnComplete( ()=>ChangeTextAnimation(false, ()=> + .OnComplete( ()=>ChangeTextAnimation(0,false, ()=> { //감소된 코인 적용 _coinsCount -= 100; diff --git a/Assets/Script/Common/Constants.cs b/Assets/Script/Common/Constants.cs index 0dda83a..a15f242 100644 --- a/Assets/Script/Common/Constants.cs +++ b/Assets/Script/Common/Constants.cs @@ -16,6 +16,9 @@ StartGame, // 생성한 방에 다른 유저가 참여해서 게임 시작 SwitchAI, // 15초 후 매칭 실패 시 AI 플레이로 전환 알림 ExitRoom, // 자신이 방을 빠져 나왔을 때 - EndGame // 상대방이 접속을 끊거나 방을 나갔을 때 + EndGame, // 상대방이 접속을 끊거나 방을 나갔을 때 + DoSurrender, // 상대방이 항복했을 때 + SurrenderConfirmed, // 항복 요청이 성공적으로 전송되었을 때 + ReceiveTimeout // 상대방이 타임 아웃일 때 }; } \ No newline at end of file diff --git a/Assets/Script/Game/GameLogic.cs b/Assets/Script/Game/GameLogic.cs index 4a710d8..61f7e79 100644 --- a/Assets/Script/Game/GameLogic.cs +++ b/Assets/Script/Game/GameLogic.cs @@ -12,17 +12,32 @@ public abstract class BasePlayerState public abstract void OnExit(GameLogic gameLogic); public abstract void HandleMove(GameLogic gameLogic, int row, int col); public abstract void HandleNextTurn(GameLogic gameLogic); + + protected string _roomId; + protected bool _isMultiplay; + protected MultiplayManager _multiplayManager; public void ProcessMove(GameLogic gameLogic, Enums.PlayerType playerType, int row, int col) { gameLogic.fioTimer.PauseTimer(); - gameLogic.SetNewBoardValue(playerType, row, col); gameLogic.CountStoneCounter(); + if (_isMultiplay) + { + _multiplayManager.SendPlayerMove(_roomId, new Vector2Int(row, col)); + } + if (gameLogic.CheckGameWin(playerType, row, col)) { var gameResult = playerType == Enums.PlayerType.PlayerA? Enums.GameResult.Win:Enums.GameResult.Lose; + if (gameLogic.gameType == Enums.GameType.MultiPlay) + { + if (gameLogic.firstPlayerState.GetType() != typeof(PlayerState)) + { + gameResult = gameResult == Enums.GameResult.Win ? Enums.GameResult.Lose : Enums.GameResult.Win; + } + } GameManager.Instance.panelManager.OpenEffectPanel(gameResult); gameLogic.EndGame(gameResult); } @@ -53,10 +68,6 @@ public class PlayerState : BasePlayerState private Enums.PlayerType _playerType; private bool _isFirstPlayer; - private MultiplayManager _multiplayManager; - private string _roomId; - private bool _isMultiplay; - public PlayerState(bool isFirstPlayer) { _isFirstPlayer = isFirstPlayer; @@ -64,17 +75,10 @@ public class PlayerState : BasePlayerState _isMultiplay = false; } - public PlayerState(bool isFirstPlayer, MultiplayManager multiplayManager, JoinRoomData data) - : this(isFirstPlayer) - { - _multiplayManager = multiplayManager; - _roomId = data.roomId; - _isMultiplay = true; - } - public PlayerState(bool isFirstPlayer, MultiplayManager multiplayManager, string roomId) : this(isFirstPlayer) { + _isFirstPlayer = isFirstPlayer; _multiplayManager = multiplayManager; _roomId = roomId; _isMultiplay = true; @@ -108,11 +112,6 @@ public class PlayerState : BasePlayerState public override void HandleMove(GameLogic gameLogic, int row, int col) { gameLogic.SetStoneSelectedState(row, col); - if (_isMultiplay) - { - Debug.Log("row: " + row + "col: " + col); - _multiplayManager.SendPlayerMove(_roomId, new Vector2Int(row, col)); - } } public override void HandleNextTurn(GameLogic gameLogic) @@ -178,7 +177,7 @@ public class MultiPlayerState: BasePlayerState gameLogic.UpdateForbiddenMoves(); #endregion - // gameLogic.currentTurn = _playerType; + gameLogic.currentTurn = _playerType; // gameLogic.stoneController.OnStoneClickedDelegate = (row, col) => // { // HandleMove(gameLogic, row, col); @@ -242,7 +241,7 @@ public class GameLogic : MonoBehaviour private int _lastRow; private int _lastCol; - private MultiplayManager _multiplayManager; + public MultiplayManager _multiplayManager; private string _roomId; #region Renju Members @@ -279,17 +278,24 @@ public class GameLogic : MonoBehaviour //timer 시간초과시 진행 함수 this.fioTimer.OnTimeout = () => { - if (currentTurn == Enums.PlayerType.PlayerA) + // 현재 턴의 플레이어가 로컬(유저)인지 확인 + bool isCurrentPlayerLocal = (currentTurn == Enums.PlayerType.PlayerA && firstPlayerState is PlayerState) || + (currentTurn == Enums.PlayerType.PlayerB && secondPlayerState is PlayerState); + + if (isCurrentPlayerLocal) // 내가 타임 오버일 때 { - GameManager.Instance.panelManager.OpenConfirmPanel($"Game Over: {Enums.PlayerType.PlayerB} Win", - () =>{}); + if (this.gameType == Enums.GameType.MultiPlay) // 멀티플레이인 경우 + { + _multiplayManager?.SendTimeout(); + } + GameManager.Instance.panelManager.OpenEffectPanel(Enums.GameResult.Lose); EndGame(Enums.GameResult.Lose); } - else if (currentTurn == Enums.PlayerType.PlayerB) + else // 로컬에서 자신의 타이머 기준으로 상대방이 타임 오버일 때 { - GameManager.Instance.panelManager.OpenConfirmPanel($"Game Over: {Enums.PlayerType.PlayerA} Win", - () =>{}); - EndGame(Enums.GameResult.Win); + // TODO: 컨펌 패널 OK 버튼 삭제? + GameManager.Instance.panelManager.OpenConfirmPanel("상대방의 응답을 기다리는 중입니다", + () => { } ); } }; } @@ -340,23 +346,42 @@ public class GameLogic : MonoBehaviour return; } - // TODO: 선공, 후공 처리 - if (joinRoomData.isBlack) - { - } + // 선공, 후공 처리 + bool isFirstPlayer = joinRoomData.isBlack; - firstPlayerState = new MultiPlayerState(true, _multiplayManager); - secondPlayerState = new PlayerState(false, _multiplayManager, joinRoomData); + if (isFirstPlayer) + { + Debug.Log("해당 플레이어가 선공 입니다"); + firstPlayerState = new PlayerState(true, _multiplayManager, joinRoomData.roomId); + secondPlayerState = new MultiPlayerState(false, _multiplayManager); + UnityMainThreadDispatcher.Instance().Enqueue(() => + { + GameManager.Instance.InitPlayersName(UserManager.Instance.Nickname, joinRoomData.opponentNickname); + GameManager.Instance.InitProfileImages(UserManager.Instance.imageIndex, joinRoomData.opponentImageIndex); + + // 리플레이 데이터 업데이트 + ReplayManager.Instance.InitReplayData(UserManager.Instance.Nickname, joinRoomData.opponentNickname, UserManager.Instance.imageIndex, joinRoomData.opponentImageIndex); + }); + } + else + { + Debug.Log("해당 플레이어가 후공 입니다"); + firstPlayerState = new MultiPlayerState(true, _multiplayManager); + secondPlayerState = new PlayerState(false, _multiplayManager, joinRoomData.roomId); + + UnityMainThreadDispatcher.Instance().Enqueue(() => + { + GameManager.Instance.InitPlayersName(joinRoomData.opponentNickname, UserManager.Instance.Nickname); + GameManager.Instance.InitProfileImages(joinRoomData.opponentImageIndex, UserManager.Instance.imageIndex); + + // 리플레이 데이터 업데이트 + ReplayManager.Instance.InitReplayData(joinRoomData.opponentNickname, UserManager.Instance.Nickname, joinRoomData.opponentImageIndex, UserManager.Instance.imageIndex); + }); + } // 메인 스레드에서 실행 - UI 업데이트는 메인 스레드에서 실행 필요 UnityMainThreadDispatcher.Instance().Enqueue(() => { - GameManager.Instance.InitPlayersName(UserManager.Instance.Nickname, joinRoomData.opponentNickname); - GameManager.Instance.InitProfileImages(UserManager.Instance.imageIndex, joinRoomData.opponentImageIndex); - - // 리플레이 데이터 업데이트 - ReplayManager.Instance.InitReplayData(UserManager.Instance.Nickname, joinRoomData.opponentNickname, UserManager.Instance.imageIndex, joinRoomData.opponentImageIndex); - // 로딩 패널 열려있으면 닫기 GameManager.Instance.panelManager.CloseLoadingPanel(); @@ -378,23 +403,41 @@ public class GameLogic : MonoBehaviour Debug.Log("Start Game 응답값이 null 입니다"); return; } - - // TODO: 선공, 후공 처리 - if (startGameData.isBlack) + // 선공, 후공 처리 + isFirstPlayer = startGameData.isBlack; + + if (isFirstPlayer) { + Debug.Log("해당 플레이어가 선공 입니다"); + firstPlayerState = new PlayerState(true, _multiplayManager, _roomId); + secondPlayerState = new MultiPlayerState(false, _multiplayManager); + UnityMainThreadDispatcher.Instance().Enqueue(() => + { + GameManager.Instance.InitPlayersName(UserManager.Instance.Nickname, startGameData.opponentNickname); + GameManager.Instance.InitProfileImages(UserManager.Instance.imageIndex, startGameData.opponentImageIndex); + + // 리플레이 데이터 업데이트 + ReplayManager.Instance.InitReplayData(UserManager.Instance.Nickname, startGameData.opponentNickname, UserManager.Instance.imageIndex, startGameData.opponentImageIndex); + }); + } + else + { + Debug.Log("해당 플레이어가 후공 입니다"); + firstPlayerState = new MultiPlayerState(true, _multiplayManager); + secondPlayerState = new PlayerState(false, _multiplayManager, _roomId); + UnityMainThreadDispatcher.Instance().Enqueue(() => + { + GameManager.Instance.InitPlayersName(startGameData.opponentNickname, UserManager.Instance.Nickname); + GameManager.Instance.InitProfileImages(startGameData.opponentImageIndex, UserManager.Instance.imageIndex); + + // 리플레이 데이터 업데이트 + ReplayManager.Instance.InitReplayData(startGameData.opponentNickname, UserManager.Instance.Nickname, startGameData.opponentImageIndex, UserManager.Instance.imageIndex); + }); } - firstPlayerState = new PlayerState(true, _multiplayManager, _roomId); - secondPlayerState = new MultiPlayerState(false, _multiplayManager); // 메인 스레드에서 실행 - UI 업데이트는 메인 스레드에서 실행 필요 UnityMainThreadDispatcher.Instance().Enqueue(() => { - GameManager.Instance.InitPlayersName(UserManager.Instance.Nickname, startGameData.opponentNickname); - GameManager.Instance.InitProfileImages(UserManager.Instance.imageIndex, startGameData.opponentImageIndex); - - // 리플레이 데이터 업데이트 - ReplayManager.Instance.InitReplayData(UserManager.Instance.Nickname, startGameData.opponentNickname, UserManager.Instance.imageIndex, startGameData.opponentImageIndex); - // 로딩 패널 열려있으면 닫기 GameManager.Instance.panelManager.CloseLoadingPanel(); @@ -410,6 +453,30 @@ public class GameLogic : MonoBehaviour Debug.Log("## End Game"); // TODO: End Room 처리 break; + case Constants.MultiplayManagerState.DoSurrender: + Debug.Log("상대방의 항복 요청 들어옴"); + UnityMainThreadDispatcher.Instance().Enqueue(() => + { + GameManager.Instance.panelManager.OpenEffectPanel(Enums.GameResult.Win); + EndGame(Enums.GameResult.Win); + }); + break; + case Constants.MultiplayManagerState.SurrenderConfirmed: + Debug.Log("항복 요청 전송 완료"); + UnityMainThreadDispatcher.Instance().Enqueue(() => + { + GameManager.Instance.panelManager.OpenEffectPanel(Enums.GameResult.Lose); + EndGame(Enums.GameResult.Lose); + }); + break; + case Constants.MultiplayManagerState.ReceiveTimeout: + Debug.Log("상대방이 타임 아웃 됨"); + UnityMainThreadDispatcher.Instance().Enqueue(() => + { + GameManager.Instance.panelManager.OpenEffectPanel(Enums.GameResult.Win); + EndGame(Enums.GameResult.Win); + }); + break; } ReplayManager.Instance.InitReplayData(UserManager.Instance.Nickname,"nicknameB"); @@ -440,6 +507,7 @@ public class GameLogic : MonoBehaviour // 기존 멀티플레이 상태 초기화 _multiplayManager = null; _roomId = null; + this.gameType = Enums.GameType.SinglePlay; // 싱글 플레이 상태로 변경 firstPlayerState = new PlayerState(true); diff --git a/Assets/Script/Game/GameManager.cs b/Assets/Script/Game/GameManager.cs index 6ebe1f1..90bacf5 100644 --- a/Assets/Script/Game/GameManager.cs +++ b/Assets/Script/Game/GameManager.cs @@ -19,13 +19,22 @@ public class GameManager : Singleton [NonSerialized] public PanelManager panelManager; [NonSerialized] public AudioManager audioManager; + + private MultiplayManager _multiplayManager; protected override void Awake() { base.Awake(); InitPanels(); } - + + public MultiplayManager GetMultiplayManager() + { + _multiplayManager = _gameLogic._multiplayManager; + if (_multiplayManager == null) Debug.Log("MultiplayManager가 null입니다"); + return _multiplayManager; + } + private void InitPanels() { if (panelManager == null) diff --git a/Assets/Script/Game/MultiplayManager.cs b/Assets/Script/Game/MultiplayManager.cs index 4c81e88..445dfa5 100644 --- a/Assets/Script/Game/MultiplayManager.cs +++ b/Assets/Script/Game/MultiplayManager.cs @@ -67,6 +67,8 @@ public class MultiplayManager : IDisposable private event Action _onMultiplayStateChanged; public Action OnOpponentMove; + private string _roomId; + public MultiplayManager(Action onMultiplayStateChanged) { _onMultiplayStateChanged = onMultiplayStateChanged; @@ -86,6 +88,9 @@ public class MultiplayManager : IDisposable _socket.On("exitRoom", ExitRoom); _socket.On("endGame", EndGame); _socket.On("doOpponent", DoOpponent); + _socket.On("doSurrender", DoSurrender); + _socket.On("surrenderConfirmed", SurrenderConfirmed); + _socket.On("receiveTimeout", ReceiveTimeout); _socket.Connect(); } @@ -109,6 +114,7 @@ public class MultiplayManager : IDisposable private void CreateRoom(SocketIOResponse response) { var data = response.GetValue(); + _roomId = data.roomId; _onMultiplayStateChanged?.Invoke(Constants.MultiplayManagerState.CreateRoom, data.roomId); } @@ -116,8 +122,7 @@ public class MultiplayManager : IDisposable { var data = response.GetValue(); Debug.Log($"룸에 참여: 룸 ID - {data.roomId}, 상대방 등급 - {data.opponentRating}, 상대방 이름 - {data.opponentNickname}, 흑/백 여부 - {data.isBlack}, 상대방 이미지 인덱스 - {data.opponentImageIndex}"); - - // 필요한 데이터 사용 + _roomId = data.roomId; _onMultiplayStateChanged?.Invoke(Constants.MultiplayManagerState.JoinRoom, data); } @@ -180,7 +185,62 @@ public class MultiplayManager : IDisposable public void LeaveRoom(string roomId) { - _socket.Emit("leaveRoom", new { roomId }); + if (string.IsNullOrEmpty(_roomId)) + { + Debug.LogError("LeaveRoom 호출 실패: _roomId가 설정되지 않음"); + return; + } + + _socket.Emit("leaveRoom", new { roomId = _roomId }); + _roomId = null; // 방 나가면 roomId 초기화 + } + + public void RequestSurrender() + { + if (string.IsNullOrEmpty(_roomId)) + { + Debug.LogError("LeaveRoom 호출 실패: _roomId가 설정되지 않음"); + return; + } + _socket.Emit("requestSurrender",new { roomId = _roomId }); + } + + private void DoSurrender(SocketIOResponse response) + { + var data = response.GetValue(); + + _onMultiplayStateChanged?.Invoke(Constants.MultiplayManagerState.DoSurrender, data.message); + } + + private void SurrenderConfirmed(SocketIOResponse response) + { + var data = response.GetValue(); + + _onMultiplayStateChanged?.Invoke(Constants.MultiplayManagerState.SurrenderConfirmed, data.message); + } + + /// + /// 타임 아웃 요청 + /// + public void SendTimeout() + { + if (string.IsNullOrEmpty(_roomId)) + { + Debug.LogError("LeaveRoom 호출 실패: _roomId가 설정되지 않음"); + return; + } + _socket.Emit("sendTimeout",new { roomId = _roomId }); + } + + /// + /// 타임 아웃 수신 + /// + /// + private void ReceiveTimeout(SocketIOResponse response) + { + var data = response.GetValue(); + + _onMultiplayStateChanged?.Invoke(Constants.MultiplayManagerState.ReceiveTimeout, data.message); } public void Dispose() diff --git a/Assets/Script/Main/NetworkManager.cs b/Assets/Script/Main/NetworkManager.cs index 2b7a83c..efb05d5 100644 --- a/Assets/Script/Main/NetworkManager.cs +++ b/Assets/Script/Main/NetworkManager.cs @@ -228,56 +228,13 @@ public class NetworkManager : Singleton } } - public void UpdateScore(int isWin, Action success, Action failure) + + public void GetLeaderboard(Action> success, Action failure) { - StartCoroutine(UpdateScoreCoroutine(isWin, success, failure)); - } - public IEnumerator UpdateScoreCoroutine(int isWin, Action success, Action failure) - { - string jsonString = "{\"isWin\": "+isWin.ToString() + "}"; - byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonString); - - using (UnityWebRequest www = - new UnityWebRequest(Constants.ServerURL + "/users/score-update", UnityWebRequest.kHttpVerbPOST)) - { - www.uploadHandler = new UploadHandlerRaw(bodyRaw); - www.downloadHandler = new DownloadHandlerBuffer(); - www.SetRequestHeader("Content-Type", "application/json"); - - string sid = PlayerPrefs.GetString("sid", ""); - if (!string.IsNullOrEmpty(sid)) - { - www.SetRequestHeader("Cookie", sid); - } - else - { - Debug.LogError("SID 값이 없습니다. 로그인 정보가 없습니다."); - GameManager.Instance.panelManager.OpenConfirmPanel("SID 값이 없습니다. 로그인 정보가 없습니다.", () => - { - failure?.Invoke(); - }); - yield break; // 더 이상 진행하지 않고 종료 - } - - yield return www.SendWebRequest(); - - if (www.result == UnityWebRequest.Result.ConnectionError || - www.result == UnityWebRequest.Result.ProtocolError) - { - Debug.LogError("Error: " + www.error); - failure?.Invoke(); - } - else - { - var result = www.downloadHandler.text; - var scoreResultInfo = JsonUtility.FromJson(result); - - success?.Invoke(scoreResultInfo); - } - } + StartCoroutine(GetLeaderboardCoroutine(success, failure)); } - public IEnumerator GetLeaderboard(Action success, Action failure) + public IEnumerator GetLeaderboardCoroutine(Action> success, Action failure) { using (UnityWebRequest www = new UnityWebRequest(Constants.ServerURL + "/leaderboard", UnityWebRequest.kHttpVerbGET)) @@ -305,10 +262,15 @@ public class NetworkManager : Singleton } else { - var result = www.downloadHandler.text; - var scores = JsonUtility.FromJson(result); - - success?.Invoke(scores); + // 성공적으로 데이터를 받아온 경우 + string jsonResponse = www.downloadHandler.text; // 응답으로 받은 JSON 데이터 + + // JSON을 ScoreInfo 리스트로 파싱 + ScoreListWrapper wrapper = JsonUtility.FromJson(jsonResponse); + List leaderboardItems = wrapper.leaderboardDatas; + + // Show 메서드를 통해 데이터를 표시 + success?.Invoke(leaderboardItems); } } } @@ -560,36 +522,54 @@ public class NetworkManager : Singleton } } } - - public void GetLeaderboardData(Action> success, Action failure) + + public void UpdateScore(int isWin, Action success, Action failure) { - StartCoroutine(GetLeaderboardDataCoroutine(success, failure)); + StartCoroutine(UpdateScoreCoroutine(isWin, success, failure)); } - - private IEnumerator GetLeaderboardDataCoroutine(Action> success, Action failure) + public IEnumerator UpdateScoreCoroutine(int isWin, Action success, Action failure) { - string url = Constants.ServerURL + "/leaderboard/"; // 서버의 리더보드 데이터 URL + string jsonString = "{\"isWin\": "+isWin.ToString() + "}"; + byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonString); - UnityWebRequest www = UnityWebRequest.Get(url); // GET 요청으로 데이터 받기 - yield return www.SendWebRequest(); // 요청 전송 대기 - - // 요청이 실패했을 때 - if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) + using (UnityWebRequest www = + new UnityWebRequest(Constants.ServerURL + "/users/score-update", UnityWebRequest.kHttpVerbPOST)) { - Debug.LogError("Error: " + www.error); - failure?.Invoke(); - } - else - { - // 성공적으로 데이터를 받아온 경우 - string jsonResponse = www.downloadHandler.text; // 응답으로 받은 JSON 데이터 - - // JSON을 ScoreInfo 리스트로 파싱 - ScoreListWrapper wrapper = JsonUtility.FromJson(jsonResponse); - List leaderboardItems = wrapper.leaderboardDatas; - - // Show 메서드를 통해 데이터를 표시 - success?.Invoke(leaderboardItems); + www.uploadHandler = new UploadHandlerRaw(bodyRaw); + www.downloadHandler = new DownloadHandlerBuffer(); + www.SetRequestHeader("Content-Type", "application/json"); + + string sid = PlayerPrefs.GetString("sid", ""); + if (!string.IsNullOrEmpty(sid)) + { + www.SetRequestHeader("Cookie", sid); + } + else + { + Debug.LogError("SID 값이 없습니다. 로그인 정보가 없습니다."); + GameManager.Instance.panelManager.OpenConfirmPanel("SID 값이 없습니다. 로그인 정보가 없습니다.", () => + { + failure?.Invoke(); + }); + yield break; // 더 이상 진행하지 않고 종료 + } + + yield return www.SendWebRequest(); + + if (www.result == UnityWebRequest.Result.ConnectionError || + www.result == UnityWebRequest.Result.ProtocolError) + { + Debug.LogError("Error: " + www.error); + failure?.Invoke(); + } + else + { + var result = www.downloadHandler.text; + var scoreResultInfo = JsonUtility.FromJson(result); + + success?.Invoke(scoreResultInfo); + } } } + } \ No newline at end of file diff --git a/Assets/Script/Main/SignupPanelController.cs b/Assets/Script/Main/SignupPanelController.cs index 2dff470..d2e22a0 100644 --- a/Assets/Script/Main/SignupPanelController.cs +++ b/Assets/Script/Main/SignupPanelController.cs @@ -1,5 +1,7 @@ +using System; using System.Collections; using System.Collections.Generic; +using System.Text.RegularExpressions; using TMPro; using UnityEngine; using UnityEngine.Networking; @@ -22,7 +24,9 @@ public class SignupPanelController : MonoBehaviour [SerializeField] private TMP_InputField confirmPasswordInputField; [SerializeField] private Toggle[] imageSelectToggles; private int _selectedImageIndex = 0; - + + private bool _emailValid = false; + private void Start() { SetToggleInit(); @@ -43,15 +47,37 @@ public class SignupPanelController : MonoBehaviour public void OnValueChanged(bool value, int index) { + // 현재 토글을 끄려고 할 때 (value가 false) + if (!value && index == _selectedImageIndex) + { + // 현재 켜져 있는 토글을 다시 켜지 않게 하고 + imageSelectToggles[index].onValueChanged.RemoveAllListeners(); + + // 다른 토글을 켬 (현재 선택된 인덱스가 아닌 다음 토글을 켬) + int nextIndex = (index + 1) % imageSelectToggles.Length; + _selectedImageIndex = nextIndex; + imageSelectToggles[nextIndex].isOn = true; + + // 이벤트 리스너 다시 추가 + int capturedIndex = index; + imageSelectToggles[index].onValueChanged.AddListener((bool val) => OnValueChanged(val, capturedIndex)); + return; + } + + // 새로운 토글을 선택했을 때 if (value) { + int previousIndex = _selectedImageIndex; _selectedImageIndex = index; - int previousIndex = (_selectedImageIndex == 0) ? 1 : 0; - imageSelectToggles[previousIndex].isOn = false; + + // 선택된 토글이 변경되었을 때만 이전 토글을 끔 + if (previousIndex != index) + { + imageSelectToggles[previousIndex].isOn = false; + } } } - public void OnClickConfirmButton() { var email = emailInputField.text; @@ -59,7 +85,7 @@ public class SignupPanelController : MonoBehaviour var password = passwordInputField.text; var confirmPassword = confirmPasswordInputField.text; - if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(nickname) || + if (string.IsNullOrEmpty(email) || !_emailValid || string.IsNullOrEmpty(nickname) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(confirmPassword)) { // 입력 내용 누락 팝업 표시 @@ -104,4 +130,63 @@ public class SignupPanelController : MonoBehaviour { Destroy(gameObject); } + + // 이메일 입력을 완료하면 유효성 검사를 진행함 + public void OnChangeEndEmail(string emailText) + { + const string emailPattern = @"^[^\s@]+@[^\s@]+\.[^\s@]+$"; + + // 입력이 끝났을 때 이메일 형식 검사 + _emailValid = Regex.IsMatch(emailText, emailPattern); + + // 이메일이 비어있지 않은 경우에만 색상 변경 + if (!string.IsNullOrEmpty(emailText)) + { + if (_emailValid) return; + emailInputField.textComponent.color = Color.red; + + // 이메일 유효하지 않음 + GameManager.Instance.panelManager.OpenConfirmPanel("올바른 이메일 주소를 입력하세요.", () => {}); + Debug.Log("이메일 유효성 X"); + } + + } + + // 이메일 인풋을 선택했을 때 이메일이 유효하지 않았으면 텍스트를 초기화함 + public void OnSelectEmail() + { + if (!_emailValid) + { + emailInputField.textComponent.color = Color.black; + emailInputField.text = String.Empty; + } + } + + // 닉네임 글자 6자 초과하면 마지막 글자를 잘라서 6자로 만듬 + public void OnChangeNickname(string nicknameText) + { + const int maxNicknameLength = 6; + + if (nicknameText.Length > maxNicknameLength) + { + // 글자수가 제한을 초과하면 처음 6글자만 남김 + string limitedText = nicknameText.Substring(0, maxNicknameLength); + nicknameInputField.text = limitedText; + } + } + + // 비밀번호 유효성 검사 + public void OnChangeEndPassword(string passwordText) + { + // 비밀번호가 비어 있으면 검사하지 않음 + if (string.IsNullOrEmpty(passwordText)) return; + + // 비밀번호 글자수 제한 확인 + if (passwordText.Length < 6 || passwordText.Length > 18) + { + // 비밀번호 글자 수 제한 + GameManager.Instance.panelManager.OpenConfirmPanel("비밀번호는 6자 이상 18자 이하로 입력해주세요.", () => {}); + Debug.Log("비밀번호 글자 수 제한"); + } + } } diff --git a/Assets/Script/Main/UserManager.cs b/Assets/Script/Main/UserManager.cs index d602895..793bdc5 100644 --- a/Assets/Script/Main/UserManager.cs +++ b/Assets/Script/Main/UserManager.cs @@ -100,14 +100,22 @@ public class UserManager : Singleton public static bool IsPlaySFX { get { return PlayerPrefs.GetInt("IsPlaySFX", 1) == 1; } - set { PlayerPrefs.SetInt("IsPlaySFX", value ? 1 : 0); } + set + { + PlayerPrefs.SetInt("IsPlaySFX", value ? 1 : 0); + AudioManager.Instance.isPlaySFX = value; + } } // 배경음악 재생 여부 public static bool IsPlayBGM { get { return PlayerPrefs.GetInt("IsPlayBGM", 1) == 1; } - set { PlayerPrefs.SetInt("IsPlayBGM", value ? 1 : 0); } + set + { + PlayerPrefs.SetInt("IsPlayBGM", value ? 1 : 0); + AudioManager.Instance.isPlayBGM = value; + } } protected override void OnSceneLoaded(Scene scene, LoadSceneMode mode) diff --git a/Assets/Script/UI/Effect/DrawEffectController.cs b/Assets/Script/UI/Effect/DrawEffectController.cs index 13302be..087645c 100644 --- a/Assets/Script/UI/Effect/DrawEffectController.cs +++ b/Assets/Script/UI/Effect/DrawEffectController.cs @@ -12,10 +12,11 @@ public class DrawEffectController : EffectController [SerializeField] private float flipDuration = 0.3f; protected override string fullText => "무승부 입니다"; - protected override void ShowEffect() + public override void ShowEffect(OnEffectPanelEnded onEffectPanelEnd) { gameObject.SetActive(true); cancellationTokenSource = new CancellationTokenSource(); + onEffectPanelEnded = onEffectPanelEnd; ShowPanel(); StartCoroutine(AnimateLoadingText()); diff --git a/Assets/Script/UI/Effect/EffectController.cs b/Assets/Script/UI/Effect/EffectController.cs index 08fbc57..a9492fb 100644 --- a/Assets/Script/UI/Effect/EffectController.cs +++ b/Assets/Script/UI/Effect/EffectController.cs @@ -3,9 +3,11 @@ using System.Threading; using DG.Tweening; using TMPro; using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UIElements; [RequireComponent(typeof(CanvasGroup))] -public abstract class EffectController : MonoBehaviour +public abstract class EffectController : MonoBehaviour, IPointerClickHandler { [SerializeField] protected GameObject bannerObj; [SerializeField] protected TextMeshProUGUI bannerText; @@ -14,14 +16,17 @@ public abstract class EffectController : MonoBehaviour protected CancellationTokenSource cancellationTokenSource; protected int currentLength = 0; + + public delegate void OnEffectPanelEnded(); + protected OnEffectPanelEnded onEffectPanelEnded; - protected virtual void Start() - { - ShowEffect(); - } + // protected virtual void Start() + // { + // ShowEffect(); + // } // 효과를 실행하는 메서드 (자식이 구현해야 함) - protected abstract void ShowEffect(); + public abstract void ShowEffect(OnEffectPanelEnded onEffectPanelEnded); // 공통 UI 애니메이션 (패널 표시) protected virtual void ShowPanel() @@ -59,7 +64,13 @@ public abstract class EffectController : MonoBehaviour cancellationTokenSource.Dispose(); cancellationTokenSource = null; } - + + onEffectPanelEnded?.Invoke(); gameObject.SetActive(false); } + + public void OnPointerClick(PointerEventData eventData) + { + HideEffect(); + } } \ No newline at end of file diff --git a/Assets/Script/UI/Effect/LoseEffectController.cs b/Assets/Script/UI/Effect/LoseEffectController.cs index c1cc3ce..e20cce3 100644 --- a/Assets/Script/UI/Effect/LoseEffectController.cs +++ b/Assets/Script/UI/Effect/LoseEffectController.cs @@ -12,10 +12,11 @@ public class LoseEffectController : EffectController protected override string fullText => "패배했습니다"; - protected override void ShowEffect() + public override void ShowEffect(OnEffectPanelEnded onEffectPanelEnd) { gameObject.SetActive(true); cancellationTokenSource = new CancellationTokenSource(); + onEffectPanelEnded = onEffectPanelEnd; ShowPanel(); StartCoroutine(AnimateLoadingText()); diff --git a/Assets/Script/UI/Effect/WinEffectController.cs b/Assets/Script/UI/Effect/WinEffectController.cs index 3aed378..1948fc9 100644 --- a/Assets/Script/UI/Effect/WinEffectController.cs +++ b/Assets/Script/UI/Effect/WinEffectController.cs @@ -14,10 +14,11 @@ public class WinEffectController : EffectController protected override string fullText => "승리했습니다!"; - protected override void ShowEffect() + public override void ShowEffect(OnEffectPanelEnded onEffectPanelEnd) { gameObject.SetActive(true); cancellationTokenSource = new CancellationTokenSource(); + onEffectPanelEnded = onEffectPanelEnd; ShowPanel(); StartCoroutine(AnimateLoadingText()); @@ -26,6 +27,16 @@ public class WinEffectController : EffectController Invoke(nameof(PopupObject), 0.3f); } + protected override void ShowPanel() + { + CanvasGroup canvasGroup = gameObject.GetComponent() ?? gameObject.AddComponent(); + + canvasGroup.alpha = 0f; + canvasGroup.DOFade(1f, 1f); + bannerObj.transform.DOScale(Vector3.zero, 0f); + bannerObj.transform.DOScale(Vector3.one, 1f); + } + private void RotateHaloObject() { // 무한 회전 효과 diff --git a/Assets/Script/UI/PanelChildController/SwitchController.cs b/Assets/Script/UI/PanelChildController/SwitchController.cs index 6045071..d95f4e5 100644 --- a/Assets/Script/UI/PanelChildController/SwitchController.cs +++ b/Assets/Script/UI/PanelChildController/SwitchController.cs @@ -6,11 +6,9 @@ using UnityEngine.UI; using DG.Tweening; [RequireComponent(typeof(Image))] -[RequireComponent(typeof(AudioSource))] public class SwitchController : MonoBehaviour { [SerializeField] private Image handleImage; - [SerializeField] private AudioClip clickSound; //스위치에 상태 변경 시 호출할 콜백 함수 public delegate void OnSwitchChangedDelegate(bool isOn); @@ -21,7 +19,6 @@ public class SwitchController : MonoBehaviour private RectTransform _handleRectTransform; private Image _backgroundImage; - private AudioSource _audioSource; private bool _isOn; @@ -29,7 +26,6 @@ public class SwitchController : MonoBehaviour { _handleRectTransform = handleImage.GetComponent(); _backgroundImage = GetComponent(); - _audioSource = GetComponent(); } private void Start() @@ -37,7 +33,15 @@ public class SwitchController : MonoBehaviour //초기 상태는 false _handleRectTransform.anchoredPosition = new Vector2(-14, 0); _backgroundImage.color = OffColor; - _isOn = false; + + if (gameObject.name == "SFX Switch") + { + _isOn = UserManager.IsPlaySFX; + } + else if (gameObject.name == "BGM Switch") + { + _isOn = UserManager.IsPlayBGM; + } } //스위치 상태 변경 함수 @@ -56,8 +60,7 @@ public class SwitchController : MonoBehaviour } // 효과음 재생 - if (clickSound != null) - _audioSource.PlayOneShot(clickSound); + AudioManager.Instance.PlayClickSound(); //이벤트 호출 OnSwitchChanged?.Invoke(isOn); diff --git a/Assets/Script/UI/PanelController/LeaderBoardController.cs b/Assets/Script/UI/PanelController/LeaderBoardController.cs index 6143beb..dd2de8f 100644 --- a/Assets/Script/UI/PanelController/LeaderBoardController.cs +++ b/Assets/Script/UI/PanelController/LeaderBoardController.cs @@ -27,7 +27,7 @@ public class LeaderBoardController : MonoBehaviour if (isLeaderboardLoaded) return; // 이미 리더보드가 로드되었으면 중복 호출 방지 leaderboardPanel.SetActive(true); - NetworkManager.Instance.GetLeaderboardData((leaderboardItems) => + NetworkManager.Instance.GetLeaderboard((leaderboardItems) => { Show(leaderboardItems); }, () => { }); diff --git a/Assets/Script/UI/PanelController/PanelManager.cs b/Assets/Script/UI/PanelController/PanelManager.cs index c872b5a..66d2eab 100644 --- a/Assets/Script/UI/PanelController/PanelManager.cs +++ b/Assets/Script/UI/PanelController/PanelManager.cs @@ -86,22 +86,30 @@ public class PanelManager : MonoBehaviour if (_canvas != null) { var winEffectPanelObject = GetEffectPanel("Win Effect Panel"); + winEffectPanelObject.GetComponent().ShowEffect(OnEffectPanelEnded); } break; case Enums.GameResult.Lose: if (_canvas != null) { - var winEffectPanelObject = GetEffectPanel("Lose Effect Panel"); + var loseEffectPanelObject = GetEffectPanel("Lose Effect Panel"); + loseEffectPanelObject.GetComponent().ShowEffect(OnEffectPanelEnded); } break; case Enums.GameResult.Draw: if (_canvas != null) { - var winEffectPanelObject = GetEffectPanel("Draw Effect Panel"); + var drawEffectPanelObject = GetEffectPanel("Draw Effect Panel"); + drawEffectPanelObject.GetComponent().ShowEffect(OnEffectPanelEnded); } break; } } + + private void OnEffectPanelEnded() + { + OpenRatingPanel(); + } #endregion public void OpenMainPanel() @@ -254,7 +262,7 @@ public class PanelManager : MonoBehaviour shopItems.Add(shopItem); } } - GameManager.Instance.panelManager.OpenShopPanel(shopItems); + OpenShopPanel(shopItems); } //승급 패널 생성 diff --git a/Assets/Script/UI/PanelController/SettingPanelController.cs b/Assets/Script/UI/PanelController/SettingPanelController.cs index ba9efb3..d568e8b 100644 --- a/Assets/Script/UI/PanelController/SettingPanelController.cs +++ b/Assets/Script/UI/PanelController/SettingPanelController.cs @@ -33,15 +33,15 @@ public class SettingsPanelController : PanelController // BGM을 끄는 경우 if (!value) { - GameManager.Instance.audioManager.StopMainBGM(); // BGM을 끄기 + AudioManager.Instance.StopBGM(); // BGM을 끄기 } // BGM을 켜는 경우 else { // 이미 BGM이 재생 중인 경우 새로 시작하지 않도록 체크 - if (!GameManager.Instance.audioManager.GetComponent().isPlaying) + if (!AudioManager.Instance.bgmAudioSource.isPlaying) { - GameManager.Instance.audioManager.PlayMainBGM(); // BGM을 켜기 + AudioManager.Instance.PlayBGM(); // BGM을 켜기 } } } diff --git a/Assets/Script/Utilty/SingleInteractableButtonHandler.cs b/Assets/Script/Utilty/SingleInteractableButtonHandler.cs new file mode 100644 index 0000000..fe272c8 --- /dev/null +++ b/Assets/Script/Utilty/SingleInteractableButtonHandler.cs @@ -0,0 +1,52 @@ +using UnityEngine; +using UnityEngine.UI; + +public class SingleInteractableButtonHandler : MonoBehaviour +{ + [Tooltip("이 버튼이 한 번만 클릭되도록 제한할지 여부")] + [SerializeField] private bool enableOneTimeClick = true; + + private Button _button; + + private bool hasBeenClicked = false; + + private void Awake() + { + // 버튼 컴포넌트 가져오기 + _button = GetComponent