diff --git a/Assets/Prefabs/ChipPrefab.prefab b/Assets/Prefabs/ChipPrefab.prefab new file mode 100644 index 0000000..ec75299 --- /dev/null +++ b/Assets/Prefabs/ChipPrefab.prefab @@ -0,0 +1,399 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4478126490810938235 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2308229979791902274} + - component: {fileID: 2785177574404548980} + - component: {fileID: -5597252834244713330} + - component: {fileID: 4011524773098274618} + - component: {fileID: 8209685094204570851} + - component: {fileID: 581128120472889901} + m_Layer: 0 + m_Name: ChipPrefab + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2308229979791902274 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4478126490810938235} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1.15, y: 1.15, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1661318112489111391} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!96 &2785177574404548980 +TrailRenderer: + serializedVersion: 4 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4478126490810938235} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 0 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 0 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: fc368c70ff252e649adbbe3df84fdada, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: -5330059 + m_SortingLayer: 2 + m_SortingOrder: -1 + m_MaskInteraction: 0 + m_Time: 0.2 + m_PreviewTimeScale: 1 + m_Parameters: + serializedVersion: 3 + widthMultiplier: 1 + widthCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.97508717 + inSlope: -0.38808823 + outSlope: -0.38808823 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0.99767745 + - serializedVersion: 3 + time: 1 + value: 0.6 + inSlope: -0.38939682 + outSlope: -0.38939682 + tangentMode: 0 + weightedMode: 0 + inWeight: 1 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + colorGradient: + serializedVersion: 2 + key0: {r: 1, g: 0.47496206, b: 0, a: 1} + key1: {r: 1, g: 0.022731155, b: 0, a: 0} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 65535 + atime3: 65535 + atime4: 65535 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_ColorSpace: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + numCornerVertices: 5 + numCapVertices: 0 + alignment: 0 + textureMode: 0 + textureScale: {x: 1, y: 1} + shadowBias: 0.5 + generateLightingData: 0 + m_MinVertexDistance: 0 + m_Autodestruct: 0 + m_Emitting: 1 + m_ApplyActiveColorSpace: 1 +--- !u!82 &-5597252834244713330 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4478126490810938235} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 0} + m_Resource: {fileID: 8300000, guid: 97356cb5584c41849a213dd28906602f, type: 3} + m_PlayOnAwake: 0 + m_Volume: 1 + m_Pitch: 1.2 + 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!114 &4011524773098274618 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4478126490810938235} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5a33d20e192d63748be8104592f6ef66, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!54 &8209685094204570851 +Rigidbody: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4478126490810938235} + serializedVersion: 5 + m_Mass: 1 + m_LinearDamping: 0 + m_AngularDamping: 0.05 + m_CenterOfMass: {x: 0, y: 0, z: 0} + m_InertiaTensor: {x: 1, y: 1, z: 1} + m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ImplicitCom: 1 + m_ImplicitTensor: 1 + m_UseGravity: 1 + m_IsKinematic: 1 + m_Interpolate: 0 + m_Constraints: 0 + m_CollisionDetection: 0 +--- !u!114 &581128120472889901 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4478126490810938235} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: aa727783246783d45abdace8138c97fd, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Chip + linearSpeed: 50 + acceleration: 200 +--- !u!1 &7100645357252458328 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1661318112489111391} + - component: {fileID: 5157516706225878083} + m_Layer: 0 + m_Name: image + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1661318112489111391 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7100645357252458328} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 2308229979791902274} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &5157516706225878083 +SpriteRenderer: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7100645357252458328} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: -5330059 + m_SortingLayer: 2 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_Sprite: {fileID: 21300000, guid: 8d6432ff047c62946a41e3235f28ba57, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 1.6384, y: 1.6384} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_SpriteSortPoint: 0 diff --git a/Assets/Prefabs/ChipPrefab.prefab.meta b/Assets/Prefabs/ChipPrefab.prefab.meta new file mode 100644 index 0000000..1192060 --- /dev/null +++ b/Assets/Prefabs/ChipPrefab.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c349c741ed95e864ca8d5b3217c40598 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/GameScene3D.unity b/Assets/Scenes/GameScene3D.unity index 2dc9e5b..b65f516 100644 --- a/Assets/Scenes/GameScene3D.unity +++ b/Assets/Scenes/GameScene3D.unity @@ -6672,22 +6672,18 @@ MonoBehaviour: Rows: 5 Cols: 6 botsAmount: 5 - boardVersion: 1 stateMachine: {fileID: 259182281} - slotLeftTop: {fileID: 687989434} + board: {fileID: 1551328426} AdminPanel: {fileID: 581100730} NumberPanel: {fileID: 1124603895} - SettingsPointer: {fileID: 334401357} timerManager: {fileID: 259182288} rulesController: {fileID: 454272343} chipPointer: {fileID: 1615046714} gameMode: 0 coinPanel: {fileID: 1407544274} - board: {fileID: 1551328425} + boardTransform: {fileID: 1551328425} noPrizeLabel: {fileID: 1796045835} - mainMenu: {fileID: 1122363131} menuUi: {fileID: 1122363136} - russo_font: {fileID: 11400000, guid: 3f10bbcf486189d4f95b8de6dc2e2177, type: 2} player1score: 0 player2score: 0 vsBotScore: 0 @@ -6699,11 +6695,9 @@ MonoBehaviour: player1Chip: {fileID: 4478126490810938235, guid: 1e042d6979719a240abdf06769829f7f, type: 3} player2Chip: {fileID: 4478126490810938235, guid: 376ff57f7b90bd845a887cfd6ba95427, type: 3} botChip: {fileID: 4478126490810938235, guid: afe8782fb49b2254cbdae76f1a9f22a8, type: 3} + chipPrefab: {fileID: 581128120472889901, guid: c349c741ed95e864ca8d5b3217c40598, type: 3} currentChip: {fileID: 0} - selectedPanel: {fileID: 1304898661, guid: bff7731f029e97345b55849f0e330c32, type: 3} - deselectedPanel: {fileID: 1744797893, guid: 93e5f9833bed0474cb1481410d00191c, type: 3} EngamePanel: {fileID: 347852021} - TimerImage: {fileID: 0} smallPrizesOut: {fileID: 1279805983} ReplayButton: {fileID: 1482394973} MenuButton: {fileID: 2055613808} @@ -6714,16 +6708,11 @@ MonoBehaviour: winPanel: {fileID: 1029921558} currentPlayer: 1 currentColumnIndex: 0 - stepX: 1.444 - stepY: 1.48 - startY: 5 moveMade: 0 chipXSpeed: 50 - chipYSpeed: 0 chipAcceleration: 200 nameInput: {fileID: 1956417153} ValutaNameInput: {fileID: 5418903569610246314} - specialPrizeInput: {fileID: 0} NumberTech: {fileID: 1596344490} pricePveInput: {fileID: 7215466293005402346} pricePvpInput: {fileID: 2019841221} @@ -6733,8 +6722,6 @@ MonoBehaviour: valutaPerPulseInput: {fileID: 483216802} leaderboard: {fileID: 1784614873} CharactersConfigurator: {fileID: 141381088} - fastCheckCounters: {fileID: 0} - checkQrPanel: {fileID: 1614501702} avatarController: {fileID: 1851050354} pvpPointer: {fileID: 492468475} movesAndTimeCounter: {fileID: 1039507332} @@ -53287,6 +53274,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 1551328425} + - component: {fileID: 1551328426} m_Layer: 0 m_Name: Board m_TagString: Untagged @@ -53322,6 +53310,22 @@ Transform: - {fileID: 1304043906} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1551328426 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1551328423} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 040b26fb5ec466e4893b26086fd3f23f, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Board + topLeftCell: {fileID: 687989434} + pointer: {fileID: 1615046714} + cellOffset: {x: 1.444, y: 1.48} + stickedY: 5 --- !u!1 &1556574614 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Common/GameFSM/BotThinkingState.cs b/Assets/Scripts/Common/GameFSM/BotThinkingState.cs index c0861ad..20eb663 100644 --- a/Assets/Scripts/Common/GameFSM/BotThinkingState.cs +++ b/Assets/Scripts/Common/GameFSM/BotThinkingState.cs @@ -3,7 +3,6 @@ using UnityEngine; public class BotThinkingState : IState { - Thread calcThread; int calculatedColumn = -1; float startTime; @@ -40,9 +39,8 @@ public class BotThinkingState : IState } - int movesMade = GameManager.instance.GetMovesCount(); + int movesMade = GameManager.instance.board.MovesCount; currentPreset = currentPreset.GetPreset(movesMade); - //Debug.Log("Ходов: " + movesMade + " Пресет: " + currentPreset.Description); Solver.SetPreset(currentPreset); @@ -93,14 +91,10 @@ public class BotThinkingState : IState if (animationStarted && Time.time - startAnimTime > animLength) { //ставим фишку в расчитанную колонку (подготовка к следующему состоянию) - GameManager.instance.currentColumnIndex = calculatedColumn; - float targetY = GameManager.instance.startY; - float targetX = GameManager.instance.slotLeftTop.position.x + - GameManager.instance.currentColumnIndex * - GameManager.instance.stepX; - Vector2 targetPosition = new Vector2(targetX, targetY); + Vector2 targetPosition = GameManager.instance.board.GetStickedPosition(calculatedColumn); + targetPosition += Vector2.up * 5; - GameManager.instance.currentChip.transform.position = new Vector2(targetX, targetY + 5); + GameManager.instance.currentChip.transform.position = targetPosition; GameManager.instance.stateMachine.ChangeState(new ChipFallingState(0, calculatedColumn)); } } @@ -117,12 +111,12 @@ public class BotThinkingState : IState bool NeedSuperPreset = OnBossByScore && (IsHardCommonDifficulty || IsUpperCashDifficulty); if (NeedSuperPreset) { - calculatedColumn = SolverV2.FindBestMove(GameManager.fieldModel.FieldArray, GameManager.instance.currentPlayer); + calculatedColumn = SolverV2.FindBestMove(gm.board.GridToTeam(), GameManager.instance.currentPlayer); } else { - calculatedColumn = Solver.FindBestMove(GameManager.fieldModel.FieldArray, GameManager.instance.currentPlayer); + calculatedColumn = Solver.FindBestMove(gm.board.GridToTeam(), GameManager.instance.currentPlayer); } } -} +} \ No newline at end of file diff --git a/Assets/Scripts/Common/GameFSM/ChipFallingState.cs b/Assets/Scripts/Common/GameFSM/ChipFallingState.cs index 0243c29..8a5b0bd 100644 --- a/Assets/Scripts/Common/GameFSM/ChipFallingState.cs +++ b/Assets/Scripts/Common/GameFSM/ChipFallingState.cs @@ -2,46 +2,36 @@ using UnityEngine; public class ChipFallingState : IState { - const float MAX_ANGULAR_SPEED = 500; - - int rowIndex; + int targetRow; int targetColumn; - float angularSpeed; - float velocityY = 0; Vector2 targetPosition; - Transform chipTransform; + Chip chip; float startDelay = 0; bool delayCompleted = false; private GameManager gm; - public ChipFallingState(float startDelay, int col) + public ChipFallingState(float startDelay, int column) { gm = GameManager.instance; + chip = gm.currentChip; this.startDelay = startDelay; - targetColumn = col; - rowIndex = GameManager.fieldModel.GetColumnHeight(targetColumn); - } - private Vector2 CalculateTargetPosition() - { - float targetX = gm.slotLeftTop.position.x + targetColumn * gm.stepX; - float targetY = gm.slotLeftTop.transform.position.y - GameManager.instance.stepY * rowIndex; - return new Vector2(targetX, targetY); + this.targetColumn = column; + this.targetRow = gm.board.GetLowestEmptyRow(column); + } + public void enter() { - targetPosition = CalculateTargetPosition(); - GameManager.instance.StartCoroutine(DelayedEnter(startDelay)); - } - private void CacheFields() - { - chipTransform = GameManager.instance.currentChip.transform; - angularSpeed = Random.Range(-MAX_ANGULAR_SPEED, MAX_ANGULAR_SPEED); + gm.StartCoroutine(DelayedEnter(startDelay)); + chip.SetRandomRotationSpeed(); + targetPosition = gm.board.GetTargetPosition(targetColumn); } + private void PrepareForFalling() { - chipTransform.GetComponent().enabled = true; + chip.GetComponent().enabled = true; } private void InitialSound() => SoundManager.instance.playDropDown(); @@ -49,34 +39,25 @@ public class ChipFallingState : IState { if (!delayCompleted) return; - ChipFallProcess(); + bool reachedTarget = chip.MoveToAccelerated(targetPosition); + chip.Rotate(); - if (chipTransform.position.y == targetPosition.y) + if (reachedTarget) { - chipTransform.GetComponent().emitting = false; + chip.GetComponent().emitting = false; SoundManager.instance.playChipBounce(); CompleteChipLanding(); } } - private void ChipFallProcess() - { - velocityY += GameManager.instance.chipAcceleration * Time.deltaTime; - float delta = velocityY * Time.deltaTime; - chipTransform.position = Vector2.MoveTowards(chipTransform.position, targetPosition, delta); - chipTransform.transform.Rotate(0, 0, angularSpeed * Time.deltaTime); - } private void CompleteChipLanding() { - chipTransform.position = targetPosition; - GameManager.fieldModel.FieldArray[rowIndex, targetColumn] = GameManager.instance.currentPlayer; - GameManager.instance.setChipTransformToArray(rowIndex, targetColumn, chipTransform); + GameManager.instance.board.AttachChipToGrid(chip, targetColumn, targetRow); StateRouter.RouteAfterTurn(); } public void exit() { - velocityY = 0; AnnouncePlayerTurn(); } @@ -92,7 +73,6 @@ public class ChipFallingState : IState { yield return new WaitForSeconds(startDelay); - CacheFields(); PrepareForFalling(); InitialSound(); diff --git a/Assets/Scripts/Common/GameFSM/FieldCleaner.cs b/Assets/Scripts/Common/GameFSM/FieldCleaner.cs deleted file mode 100644 index 04672dc..0000000 --- a/Assets/Scripts/Common/GameFSM/FieldCleaner.cs +++ /dev/null @@ -1,58 +0,0 @@ -using UnityEngine; - -public static class FieldCleaner -{ - const string SORTLAYER_BACKGROUND = "Background"; - - const float EXPLOSION_FORCE = 30; - static readonly Vector3 EXPLOSION_ORIGIN = new Vector3(0, -2, -5); - const float EXPLOSION_RADIUS = 50; - - const float TIME_TO_DESTROY = 5; - - static Transform[,] field; - - - - - //передаем переходим мы в меню или нет. Если нет, то переход отсюда в новый раунд - //Надо еще сделать в конструкторе чтобы nextState указывать а то ж непонятно вообще - public static void Clear() - { - field = GameManager.instance.chipTransforms; - SoundManager.instance.playExplosion(); - - if (GameManager.instance.currentChip != null) - { - Object.Destroy(GameManager.instance.currentChip); - } - GameManager.fieldModel.makeEmptyField(width: GameManager.instance.Cols, height: GameManager.instance.Rows); - GameManager.instance.chipTransforms = new Transform[GameManager.instance.Rows, GameManager.instance.Cols]; - - - Explode(); - } - - private static void Explode() - { - for (int i = 0; i < GameManager.instance.Rows; i++) - { - for (int j = 0; j < GameManager.instance.Cols; j++) - { - Transform chipTransform = field[i, j]; - if (chipTransform != null) - { - Rigidbody rb = chipTransform.GetComponent(); - rb.isKinematic = false; - rb.AddExplosionForce(EXPLOSION_FORCE, EXPLOSION_ORIGIN, EXPLOSION_RADIUS, upwardsModifier: 1, ForceMode.Impulse); - - chipTransform.GetComponent().sortingLayerName = SORTLAYER_BACKGROUND; - chipTransform.GetChild(0).GetComponent().sortingLayerName = SORTLAYER_BACKGROUND; - Object.Destroy(chipTransform.gameObject, TIME_TO_DESTROY + Random.Range(-1f, 1f));//чтобы уничтожались не одновременно - } - } - } - } -} - - diff --git a/Assets/Scripts/Common/GameFSM/FieldCleaner.cs.meta b/Assets/Scripts/Common/GameFSM/FieldCleaner.cs.meta deleted file mode 100644 index 27dd0a8..0000000 --- a/Assets/Scripts/Common/GameFSM/FieldCleaner.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ae3604a5803730846bbf06830500a11e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scripts/Common/GameFSM/LeaderboardState.cs b/Assets/Scripts/Common/GameFSM/LeaderboardState.cs index a533745..b1a3057 100644 --- a/Assets/Scripts/Common/GameFSM/LeaderboardState.cs +++ b/Assets/Scripts/Common/GameFSM/LeaderboardState.cs @@ -34,8 +34,7 @@ public class LeaderboardState : IState if (In.GetButtonDownAnyPlayer(PlayerAction.left) && In.GetButtonDownAnyPlayer(PlayerAction.right)) { - FieldCleaner.Clear(); - //GameManager.instance.stateMachine.ChangeState(new MenuState(fromGameplay: true)); + GameManager.instance.board.MakeClearField(); GameManager.instance.stateMachine.ChangeState(new MenuState()); } } diff --git a/Assets/Scripts/Common/GameFSM/PositioningState.cs b/Assets/Scripts/Common/GameFSM/PositioningState.cs index bfdcbe7..af3914f 100644 --- a/Assets/Scripts/Common/GameFSM/PositioningState.cs +++ b/Assets/Scripts/Common/GameFSM/PositioningState.cs @@ -1,49 +1,59 @@ -using System.Collections.Generic; -using UnityEngine; +using UnityEngine; public class PositioningState : IState { - GameManager gm; - GameObject chip; + private GameManager gm; + private Chip chip; + private Board board; + private ChipPointer pointer; - int index; - int position; - bool chipOnPosition; + private int indexValidArr; + private int columnIndex; + private bool chipOnPosition; + private int[] validPositions; - const int DEFAULT_SPEED = 50; - - List validPositions; + private Vector2 stickedPosition; + private Vector2 targetPosition; public void enter() { gm = GameManager.instance; + board = gm.board; + pointer = gm.chipPointer; + + validPositions = board.GetNonFullColumns(); + + int centralIndex = validPositions.Length / 2; + indexValidArr = centralIndex; + columnIndex = validPositions[centralIndex]; + + stickedPosition = board.GetStickedPosition(validPositions[indexValidArr]); + targetPosition = board.GetTargetPosition(validPositions[indexValidArr]); + chip = gm.currentChip; + chip.transform.position = stickedPosition; chipOnPosition = true; - validPositions = GameManager.fieldModel.CollectNonFullCols(); + pointer.Show(); + pointer.SetColorByPlayer(gm.currentPlayer); + pointer.SetPosition(targetPosition); - int centralIndex = validPositions.Count / 2; - index = centralIndex; - position = validPositions[centralIndex]; - gm.currentColumnIndex = validPositions[centralIndex]; + if (gm.gameMode == GameMode.pvp) + { + gm.pvpPointer.SetColor(gm.currentPlayer); + gm.pvpPointer.SetVisibility(true); + gm.pvpPointer.MoveTo(stickedPosition); + } - float offsety = gm.startY; - if (gm.gameMode == GameMode.pvp) offsety = gm.startY + 5;//повыше - - float x = gm.slotLeftTop.position.x + validPositions[index] * gm.stepX; - float y = gm.startY + offsety; - chip.transform.position = new Vector3(x, y, 0); - - chip.SetActive(true); - - gm.chipPointer.Show(); - gm.chipPointer.SetColorByPlayer(gm.currentPlayer); + if (gm.gameMode == GameMode.pve) + gm.StartVsBotTimer(); } public void exit() { gm.pvpPointer.SetVisibility(false); - gm.chipPointer.Hide(); + gm.StopVsBotTimer(); + pointer.Hide(); } public void update() @@ -51,29 +61,9 @@ public class PositioningState : IState // вычисление ввода в зависимости от игрового режима var input = GetInputs(); - if (gm.gameMode == GameMode.pve) gm.vsBotThinkTime += Time.deltaTime; - + HandleChipMovement(input.direction); - Vector2 stickedPosition = GetStickedPosition(); - Vector2 targetPosition = GetTargetPosition(); - - gm.chipPointer.SetPosition(targetPosition); - - if (gm.gameMode == GameMode.pvp) - { - gm.pvpPointer.SetColor(gm.currentPlayer); - gm.pvpPointer.SetVisibility(true); - gm.pvpPointer.MoveTo(stickedPosition); - - stickedPosition += Vector2.up * 5;//повыше - } - - chip.transform.position = Vector2.MoveTowards(chip.transform.position, stickedPosition, DEFAULT_SPEED * Time.deltaTime); - - if ((Vector2)chip.transform.position == stickedPosition) - chipOnPosition = true; - else - chipOnPosition = false; + chipOnPosition = chip.MoveToLinear(stickedPosition); if (HandleDrop(input.action)) return; if (HandleExitToMenu()) return; @@ -81,23 +71,30 @@ public class PositioningState : IState private void HandleChipMovement(int direction) { - if (!chipOnPosition) return; + if (direction == 0 || !chipOnPosition) return; + + indexValidArr += direction; + indexValidArr = Mathf.Clamp(indexValidArr, 0, validPositions.Length - 1); + + columnIndex = validPositions[indexValidArr]; + + stickedPosition = gm.board.GetStickedPosition(columnIndex); + targetPosition = gm.board.GetTargetPosition(columnIndex); + + //перемещение указателей + pointer.SetPosition(targetPosition); + if (gm.gameMode == GameMode.pvp) + gm.pvpPointer.MoveTo(stickedPosition); - index = Mathf.Clamp(index + direction, 0, validPositions.Count - 1); - int prevPos = position; - position = validPositions[index]; - int dist = Mathf.Abs(position - prevPos); - gm.chipXSpeed = dist * DEFAULT_SPEED;//скорость зануляется - gm.currentColumnIndex = position; SoundManager.instance.playSwitch(); } private bool HandleExitToMenu() { bool exitPressed = In.GetButtonDown(ButtonPinMapping.startOnePlayer) || In.GetButtonDown(ButtonPinMapping.startTwoPlayers); - if (exitPressed && !gm.moveMade) + if (exitPressed && gm.canReturnToMenu) { - FieldCleaner.Clear(); + gm.board.MakeClearField(); PaymentSystem.ReturnCredits(gm.gameMode); GameManager.instance.timerManager.StopAllTimers(); GameManager.instance.stateMachine.ChangeState(new MenuState()); @@ -110,49 +107,27 @@ public class PositioningState : IState { if (!action) return false; - //todo: посмотреть нахуя currentColumnIndex зарыто в gm. разрыть. - - bool canDropInCurrentColumn = GameManager.fieldModel.GetColumnHeight(gm.currentColumnIndex) != -1; - + bool canDropInCurrentColumn = board.CanDrop(columnIndex); if (!(chipOnPosition && canDropInCurrentColumn)) { SoundManager.instance.playWrong(); return false; } - float delayBeforeStartFalling = 0; if (gm.gameMode == GameMode.pve) gm.vsBotMoves += 1; + float delayBeforeStartFalling = 0; if (gm.gameMode == GameMode.pvp) { AvatarEventBus.Instance.OnTurnEnd?.Invoke(gm.currentPlayer); delayBeforeStartFalling = DualAvatarController.Instance.CurrentAvatar.ChipSpawnTime; } - gm.moveMade = true; - Vector2 targetPosition = GetTargetPosition(); - gm.stateMachine.ChangeState(new ChipFallingState(startDelay: delayBeforeStartFalling, gm.currentColumnIndex)); + gm.canReturnToMenu = false; + gm.stateMachine.ChangeState(new ChipFallingState(startDelay: delayBeforeStartFalling, columnIndex)); return true; } - private Vector2 GetStickedPosition() - { - float targetX = gm.slotLeftTop.position.x + - gm.currentColumnIndex * - gm.stepX; - float targetY = gm.startY; - return new Vector2(targetX, targetY); - } - - private Vector2 GetTargetPosition() - { - float targetX = gm.slotLeftTop.position.x + - gm.currentColumnIndex * - gm.stepX; - float targetY = GameManager.instance.slotLeftTop.transform.position.y - GameManager.instance.stepY * GameManager.fieldModel.GetColumnHeight(gm.currentColumnIndex); - return new Vector2(targetX, targetY); - } - private (int direction, bool action) GetInputs() { bool left = false, diff --git a/Assets/Scripts/Common/GameFSM/ShowWinnerState.cs b/Assets/Scripts/Common/GameFSM/ShowWinnerState.cs index 1caa1c1..40e90bd 100644 --- a/Assets/Scripts/Common/GameFSM/ShowWinnerState.cs +++ b/Assets/Scripts/Common/GameFSM/ShowWinnerState.cs @@ -8,15 +8,8 @@ public class ShowWinnerState : IState Color empty = new Color(0, 0, 0, 0); CoinCounter coinCounter; - private GameManager gm; - GameManager GameManager - { - get - { - if (gm == null) gm = GameManager.instance; - return gm; - } - } + private GameManager gm = GameManager.instance; + public enum ShowWinnerSubstates { PanelFalling, HandlingInputs, PanelRising, ExitByTime } public ShowWinnerSubstates subState; @@ -35,7 +28,7 @@ public class ShowWinnerState : IState List winningChips; Color orange = new Color(1, 0.537794f, 0, 1f); - Color blue = new Color(0, 0.7181487f, 1, 0.5f); + TextMeshProUGUI TimerLabel; TextMeshProUGUI ToMenuLabel; @@ -48,7 +41,7 @@ public class ShowWinnerState : IState public ShowWinnerState() { - this.result = GameManager.lastResult; + this.result = gm.lastResult; subState = ShowWinnerSubstates.PanelFalling; GameManager.instance.ToMenuLabel.gameObject.SetActive(true); } @@ -61,22 +54,22 @@ public class ShowWinnerState : IState public void enter() { coinCounter = GameObject.FindAnyObjectByType(); - ToMenuLabel = GameManager.ToMenuLabel; - TimerLabel = GameManager.TimerLabel; + ToMenuLabel = gm.ToMenuLabel; + TimerLabel = gm.TimerLabel; //таймер - GameManager.timerManager.StopAllTimers(); + gm.timerManager.StopAllTimers(); - panel = GameManager.EngamePanel; - left = GameManager.ReplayButton; - right = GameManager.MenuButton; + panel = gm.EngamePanel; + left = gm.ReplayButton; + right = gm.MenuButton; InitPanel(); if (result.Draw) { - GameManager.DrawVisual.Show(); + gm.DrawVisual.Show(); } - if (GameManager.gameMode == GameMode.pvp) + if (gm.gameMode == GameMode.pvp) { if (!result.Draw) { @@ -84,39 +77,39 @@ public class ShowWinnerState : IState winningChips = new List(); CollectChipsList(result); - if (GameManager.player1score == 5)//полная победа 1 игрока + if (gm.player1score == 5)//полная победа 1 игрока { //обнулить очки и выдать приз - GameManager.player1score = 0; - GameManager.player2score = 0; + gm.player1score = 0; + gm.player2score = 0; //переход в приз } - else if (GameManager.player2score == 5)//полная победа 2 игрока + else if (gm.player2score == 5)//полная победа 2 игрока { //обнулить очки и выдать приз - GameManager.player1score = 0; - GameManager.player2score = 0; + gm.player1score = 0; + gm.player2score = 0; //переход в приз } } } - else if (GameManager.gameMode == GameMode.pve) + else if (gm.gameMode == GameMode.pve) { if (!result.Draw) { winningChips = new List(); CollectChipsList(result); - if (GameManager.currentPlayer == CellState.Player1)//Последный держал фишку игрок + if (gm.currentPlayer == CellState.Player1)//Последный держал фишку игрок { - if (GameManager.vsBotScore == 5)//5 побед над ботом + if (gm.vsBotScore == 5)//5 побед над ботом { - GameManager.vsBotScore = 0; + gm.vsBotScore = 0; } } } @@ -129,7 +122,7 @@ public class ShowWinnerState : IState ToMenuLabel.gameObject.SetActive(false); if (result.Draw) { - GameManager.DrawVisual.Hide(); + gm.DrawVisual.Hide(); return; } //вернуть альфу фишкам @@ -179,7 +172,7 @@ public class ShowWinnerState : IState //чистимся и топаем дальше в след раунд - FieldCleaner.Clear(); + gm.board.MakeClearField(); //Фишка ходит первой если ее не побеждали сегодня еще //текущий бот - последний @@ -239,7 +232,7 @@ public class ShowWinnerState : IState if (panel.localPosition == targetUpPosition)//панель дошла до верха { - if (GameManager.lastResult != null && !GameManager.lastResult.Draw) + if (gm.lastResult != null && !gm.lastResult.Draw) { foreach (SpriteRenderer chip in winningChips) { @@ -250,16 +243,16 @@ public class ShowWinnerState : IState switch (option) { case EndOption.Restart://чистим поле и перезапуск. Меняем игрока - AvatarEventBus.Instance.OnNewRoundStarted?.Invoke(GameManager.currentPlayer); - FieldCleaner.Clear(); + AvatarEventBus.Instance.OnNewRoundStarted?.Invoke(gm.currentPlayer); + gm.board.MakeClearField(); - CellState nextPlayer = GameManager.currentPlayer == CellState.Player1 ? CellState.Player2 : CellState.Player1; + CellState nextPlayer = gm.currentPlayer == CellState.Player1 ? CellState.Player2 : CellState.Player1; gm.PrepareRound(nextPlayer); break; case EndOption.Menu://чистим поле и переходим в меню с параметром чтобы панельки съехались обратно CharacterController.HideCharacter(); DualAvatarController.Instance.HideCharacters(); - FieldCleaner.Clear(); + gm.board.MakeClearField(); //GameManager.instance.stateMachine.ChangeState(new MenuState(fromGameplay: true)); GameManager.instance.stateMachine.ChangeState(new MenuState()); break; @@ -343,12 +336,12 @@ public class ShowWinnerState : IState right.transform.GetChild(0).GetComponent().color = empty; - GameManager.RestartButton.text = NeedToPay ? "Еще раз!" : "Продолжить!"; + gm.RestartButton.text = NeedToPay ? "Еще раз!" : "Продолжить!"; } private void DropPanel() { - panel = GameManager.EngamePanel; + panel = gm.EngamePanel; panel.transform.localPosition = Vector3.MoveTowards(panel.transform.localPosition, targetDownPosition, speedY * Time.deltaTime); speedY += acceleration * Time.deltaTime; @@ -370,8 +363,8 @@ public class ShowWinnerState : IState foreach (var index in result.WinningIndexes) { - GameManager.chipTransforms[index.row, index.col].rotation = Quaternion.identity; - var renderer = GameManager.chipTransforms[index.row, index.col].GetChild(0).GetComponent(); + gm.chipTransforms[index.row, index.col].rotation = Quaternion.identity; + var renderer = gm.chipTransforms[index.row, index.col].GetChild(0).GetComponent(); winningChips.Add(renderer); renderer.gameObject.AddComponent().speed = 8; } diff --git a/Assets/Scripts/Common/GameFSM/StateRouter.cs b/Assets/Scripts/Common/GameFSM/StateRouter.cs index 2092420..79eacf9 100644 --- a/Assets/Scripts/Common/GameFSM/StateRouter.cs +++ b/Assets/Scripts/Common/GameFSM/StateRouter.cs @@ -6,7 +6,7 @@ public static class StateRouter private static GameManager gm => GameManager.instance; public static void RouteAfterTurn() { - var checkResult = GameManager.fieldModel.Check(GameManager.instance.currentPlayer); + var checkResult = FieldChecker.Check(GameManager.instance.currentPlayer); gm.lastResult = checkResult;//это неправильно. Нужно при проверке записывать в поле. TurnEndingResult turnResult = EndOfTurnHandler.Evaluate(checkResult, gm.gameMode, gm.currentPlayer); @@ -149,7 +149,7 @@ public static class StateRouter public static IState ToMenu() { - FieldCleaner.Clear(); + gm.board.MakeClearField(); return new MenuState(); } diff --git a/Assets/Scripts/Common/GameManager.cs b/Assets/Scripts/Common/GameManager.cs index 6ecc2f4..c89a046 100644 --- a/Assets/Scripts/Common/GameManager.cs +++ b/Assets/Scripts/Common/GameManager.cs @@ -15,8 +15,7 @@ public class GameManager : MonoBehaviour [Header("General")] public GameStateMachine stateMachine; - public Transform slotLeftTop; - public static FieldModel fieldModel; + public Board board; public static GameManager instance; public GameObject AdminPanel, NumberPanel; public TimerManager timerManager; @@ -28,7 +27,7 @@ public class GameManager : MonoBehaviour public GameMode gameMode; public Transform coinPanel, - board, + boardTransform, noPrizeLabel; public UiManager menuUi; @@ -36,6 +35,7 @@ public class GameManager : MonoBehaviour [Header("Scores")] public int player1score = 0, player2score = 0, vsBotScore = 0; + private bool increaseVsBotTimer = false; public int vsBotMoves; public float vsBotThinkTime; @@ -49,7 +49,8 @@ public class GameManager : MonoBehaviour public GameObject player1Chip; public GameObject player2Chip; public GameObject botChip; - [HideInInspector] public GameObject currentChip; + public Chip chipPrefab; + [HideInInspector] public Chip currentChip; public RectTransform EngamePanel; public RectTransform smallPrizesOut; @@ -64,15 +65,8 @@ public class GameManager : MonoBehaviour [HideInInspector] public CellState currentPlayer = CellState.Player2; - public int currentColumnIndex = 0; - public float stepX = 1.215f; - public float stepY = 1.24f; - public float startY; - public bool moveMade = false; - - public float chipXSpeed = 10, - chipAcceleration = 20; + public bool canReturnToMenu = false; //todo: разобраться нафига эта переменная public Transform[,] chipTransforms; @@ -111,15 +105,13 @@ public class GameManager : MonoBehaviour { Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; - - Instantiate(new GameObject()).AddComponent(typeof(VfxPrefab)); - + soundManager.Initialize(); if (instance == null) { Application.targetFrameRate = DEFAULT_FRAME_RATE; instance = this; - fieldModel = new FieldModel(Cols, Rows); + board.Init(Cols, Rows); chipTransforms = new Transform[Rows, Cols]; } @@ -138,7 +130,6 @@ public class GameManager : MonoBehaviour ComWrapper.PaymentReceived += ProcessDifficultyCounter; SettingsManager.OnSettingsChanged.AddListener(ProcessDifficultyCounter); - soundManager.Initialize(); GetComponent().Initialize(); @@ -256,9 +247,9 @@ public class GameManager : MonoBehaviour } -#if UNITY_EDITOR private void Update() { +#if UNITY_EDITOR if (Input.GetKeyDown(KeyCode.G)) { PrizeSystemManager.GivePrize(PrizeUtils.CreatePrize(CountablePrizeType.Hopper, 1)); @@ -267,8 +258,12 @@ public class GameManager : MonoBehaviour { PlayerPrefs.SetInt("PrizeGivenBuffer", 1); } - } #endif + if (increaseVsBotTimer) vsBotThinkTime += Time.deltaTime; + } + + public void StartVsBotTimer() => increaseVsBotTimer = true; + public void StopVsBotTimer() => increaseVsBotTimer = false; public void SetupCoinPanel() @@ -285,7 +280,8 @@ public class GameManager : MonoBehaviour chipToSpawn = currentPlayer == CellState.Player1 ? player1Chip : botChip; - currentChip = Instantiate(chipToSpawn, new Vector2(0, 20), Quaternion.identity); + currentChip = Instantiate(chipPrefab, new Vector2(0, 20), Quaternion.identity); + currentChip.Team = currentPlayer; if (currentPlayer == CellState.Player2) currentChip.GetComponentInChildren().sprite = CharacterController.CurrentChipImage; } @@ -346,22 +342,6 @@ public class GameManager : MonoBehaviour } } - public int GetMovesCount() - { - if (chipTransforms == null) return 0; - - int count = 0; - int rows = chipTransforms.GetLength(0); - int cols = chipTransforms.GetLength(1); - - for (int r = 0; r < rows; r++) - for (int c = 0; c < cols; c++) - if (chipTransforms[r, c] != null) - count++; - - return count; - } - public void ProcessDifficultyCounter()//вызывается каждый раз, когда приходит COIN с платы или обновились настройки { string previous = PlayerPrefs.GetString("PreviousBaseBotDifficulty", "Обычная"); @@ -445,6 +425,7 @@ public class GameManager : MonoBehaviour public void ResetGameSession() { vsBotThinkTime = 0; + StopVsBotTimer(); vsBotMoves = 0; movesAndTimeCounter.SetVisibility(false); @@ -460,7 +441,7 @@ public class GameManager : MonoBehaviour VitrinaView.Instance.Deactivate(); - moveMade = false; + canReturnToMenu = true; } IEnumerator AddBotRecordEvery2Days() @@ -481,4 +462,6 @@ public class GameManager : MonoBehaviour } } + + } \ No newline at end of file diff --git a/Assets/Scripts/Common/SoundManager.cs b/Assets/Scripts/Common/SoundManager.cs index b3cd0f9..921fd7c 100644 --- a/Assets/Scripts/Common/SoundManager.cs +++ b/Assets/Scripts/Common/SoundManager.cs @@ -54,7 +54,6 @@ public class SoundManager : MonoBehaviour { Destroy(gameObject); } - Instantiate(new GameObject()).AddComponent(typeof(VfxPrefab)); } private void Start() diff --git a/Assets/Scripts/Gameplay/BackToMenuButton.cs b/Assets/Scripts/Gameplay/BackToMenuButton.cs index cce878c..5455c02 100644 --- a/Assets/Scripts/Gameplay/BackToMenuButton.cs +++ b/Assets/Scripts/Gameplay/BackToMenuButton.cs @@ -19,15 +19,15 @@ public class BackToMenuButton : MonoBehaviour { canvasGroup = GetComponent(); gm = GameManager.instance; - ActualState = gm.moveMade; + ActualState = !gm.canReturnToMenu; } void Update() { - if (ActualState != gm.moveMade) + if (ActualState == gm.canReturnToMenu) { - ActualState = gm.moveMade; + ActualState = !gm.canReturnToMenu; StopAllCoroutines(); StartCoroutine(changeState()); } diff --git a/Assets/Scripts/Gameplay/Board.cs b/Assets/Scripts/Gameplay/Board.cs new file mode 100644 index 0000000..00bc5ff --- /dev/null +++ b/Assets/Scripts/Gameplay/Board.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +public class Board : MonoBehaviour +{ + //визуал + [SerializeField] Transform topLeftCell; + [SerializeField] ChipPointer pointer; + [SerializeField] Vector2 cellOffset = new(1.444f, 1.48f); + [SerializeField] float stickedY = 5f; + + //состояние + public int columns; + public int rows; + public Chip[,] grid; + + public int MovesCount => GetMovesCount(); + + public void Init(int columns, int rows) + { + this.columns = columns; + this.rows = rows; + + MakeClearField(); + } + + public Vector2 GetStickedPosition(int column) => new Vector2(GetXPosition(column), stickedY); + + public Vector2 GetTargetPosition(int column) => new Vector2(GetXPosition(column), GetYPosition(column)); + + public void MakeClearField() + { + PerformClear(); + grid = new Chip[columns, rows]; + } + + public bool CanDrop(int column) => grid[column, 0] == null; + + public void AttachChipToGrid(Chip chip, int column, int row) + { + if (column < 0 || column >= columns) + { + Debug.LogError($"Попытка поставить фишку в колонку {column}. Колонок: {columns}"); + return; + } + if (row < 0 || row >= rows) + { + Debug.LogError($"Попытка поставить фишку в ряд {row}. Рядов: {rows}"); + return; + } + + grid[column, row] = chip; + } + + public int[] GetNonFullColumns() + { + List temp = new(); + for (int column = 0; column < columns; column++) + if (CanDrop(column)) + temp.Add(column); + return temp.ToArray(); + } + + public int GetLowestEmptyRow(int colIndex) + { + if (colIndex < 0 || colIndex >= columns) + throw new ArgumentOutOfRangeException($"Попытка проверить колонку {colIndex}. Колонок: {columns}"); + + for (int row = rows - 1; row >= 0; row--) + if (grid[colIndex, row] == null) + return row; + return -1; + } + + private float GetXPosition(int column) => topLeftCell.position.x + cellOffset.x * column; + + private float GetYPosition(int column) => topLeftCell.position.y - GetLowestEmptyRow(column) * cellOffset.y; + + + private void PerformClear() + { + SoundManager.instance.playExplosion(); + GameManager.instance.currentChip?.RemoveFromField(); + if (grid == null) return; + + foreach (Chip chip in grid) + chip?.RemoveFromField(); + } + + private int GetMovesCount() + { + if (grid == null) return 0; + int count = 0; + foreach (Chip chip in grid) + if (chip != null) count++; + return count; + } + + public CellState[,] GridToTeam() + { + CellState[,] res = new CellState[columns, rows]; + for (int col = 0; col < columns; col++) + { + for (int row = 0; row < rows; row++) + { + var chip = grid[col, row]; + if (chip == null) res[col, row] = CellState.Empty; + else res[col, row] = chip.Team; + } + } + return res; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Gameplay/Board.cs.meta b/Assets/Scripts/Gameplay/Board.cs.meta new file mode 100644 index 0000000..916f22f --- /dev/null +++ b/Assets/Scripts/Gameplay/Board.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 040b26fb5ec466e4893b26086fd3f23f \ No newline at end of file diff --git a/Assets/Scripts/Gameplay/Chip.cs b/Assets/Scripts/Gameplay/Chip.cs new file mode 100644 index 0000000..873ae78 --- /dev/null +++ b/Assets/Scripts/Gameplay/Chip.cs @@ -0,0 +1,42 @@ +using UnityEngine; + +public class Chip : MonoBehaviour +{ + public CellState Team; + [SerializeField] float linearSpeed = 50f; + [SerializeField] float acceleration = 200f; + [SerializeField] float maxFallingRotationSpeed = 500; + + private float chipVelocity = 0; + private float rotationSpeed = 0; + + public virtual void RemoveFromField() + { + Destroy(gameObject); + } + + public bool MoveToLinear(Vector2 target) + { + transform.position = Vector2.MoveTowards(transform.position, target, linearSpeed * Time.deltaTime); + if((Vector2)transform.position == target) + return true; + return false; + } + + public bool MoveToAccelerated(Vector2 target) + { + transform.position = Vector2.MoveTowards(transform.position, target, chipVelocity * Time.deltaTime); + chipVelocity += acceleration * Time.deltaTime; + + if ((Vector2)transform.position == target) + { + acceleration = 0; + return true; + } + return false; + } + + + public void SetRandomRotationSpeed() => rotationSpeed = Random.Range(-maxFallingRotationSpeed, maxFallingRotationSpeed); + public void Rotate() => transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime); +} \ No newline at end of file diff --git a/Assets/Scripts/Gameplay/Chip.cs.meta b/Assets/Scripts/Gameplay/Chip.cs.meta new file mode 100644 index 0000000..4925338 --- /dev/null +++ b/Assets/Scripts/Gameplay/Chip.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: aa727783246783d45abdace8138c97fd \ No newline at end of file diff --git a/Assets/Scripts/Gameplay/FieldModel.cs b/Assets/Scripts/Gameplay/FieldChecker.cs similarity index 72% rename from Assets/Scripts/Gameplay/FieldModel.cs rename to Assets/Scripts/Gameplay/FieldChecker.cs index 9231edc..c7f23e4 100644 --- a/Assets/Scripts/Gameplay/FieldModel.cs +++ b/Assets/Scripts/Gameplay/FieldChecker.cs @@ -5,29 +5,15 @@ public enum CellState { Empty, Player1, Player2 } -public class FieldModel +public static class FieldChecker { - //двумерный массив для поля - public CellState[,] FieldArray; - public int Height; - public int Width; - public int TargetLineLength = 4; + static GameManager gm => GameManager.instance; + public static Chip[,] FieldArray => gm.board.grid; + public static int Height => gm.board.rows; + public static int Width => gm.board.columns; + public static int TargetLineLength = 4; - public FieldModel(int width, int height) - { - //0 индекс для строк, 1 индекс для столбцов - Width = width; - Height = height; - makeEmptyField(width, height); - } - - public void makeEmptyField(int width, int height) - { - FieldArray = new CellState[height, width]; - Array.Clear(FieldArray, 0, FieldArray.Length); - } - - public CheckResult Check(CellState lastPlayer) + public static CheckResult Check(CellState lastPlayer) { HashSet<(int row, int col)> WinningIndexes = new(); @@ -55,7 +41,7 @@ public class FieldModel isDraw: true, WinningIndexes); } - else + else { return new CheckResult(end: false, isDraw: false, @@ -65,7 +51,7 @@ public class FieldModel } - private (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllRows(CellState targetCellState) + private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllRows(CellState targetTeam) { var winningCells = new HashSet<(int row, int col)>(); @@ -76,7 +62,8 @@ public class FieldModel for (int col = 0; col <= Width; col++) // теперь проходим до Width включительно { // Проверяем, не вышли ли за границы массива - bool isMatch = col < Width && FieldArray[row, col] == targetCellState; + var chip = FieldArray[col, row]; + bool isMatch = col < Width && chip != null && chip.Team == targetTeam; if (isMatch && start == -1) start = col; @@ -96,7 +83,7 @@ public class FieldModel return (winningCells.Count > 0, winningCells); } - private (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllColumns(CellState targetCellState) + private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllColumns(CellState targetTeam) { var winningCells = new HashSet<(int row, int col)>(); @@ -106,7 +93,8 @@ public class FieldModel for (int row = 0; row <= Height; row++) { - bool isMatch = row < Height && FieldArray[row, col] == targetCellState; + var chip = FieldArray[col, row]; + bool isMatch = row < Height && chip != null && chip.Team == targetTeam; if (isMatch && start == -1) start = row; @@ -127,7 +115,7 @@ public class FieldModel return (winningCells.Count > 0, winningCells); } - private (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllDiagonals(CellState targetCellState) + private static (bool hasWin, HashSet<(int row, int col)> winningIndexes) checkAllDiagonals(CellState targetCellState) { var winningCells = new HashSet<(int row, int col)>(); @@ -154,7 +142,7 @@ public class FieldModel return (winningCells.Count > 0, winningCells); } - private void CheckDiagonalStartingAt(int startRow, int startCol, int rowStep, int colStep, + private static void CheckDiagonalStartingAt(int startRow, int startCol, int rowStep, int colStep, CellState targetCellState, HashSet<(int, int)> winningCells) { int rows = Height; @@ -168,7 +156,8 @@ public class FieldModel while (currentRow >= 0 && currentRow < rows && currentCol >= 0 && currentCol < cols) { - bool isMatch = FieldArray[currentRow, currentCol] == targetCellState; + var chip = FieldArray[currentCol, currentRow]; + bool isMatch = chip != null && chip.Team == targetCellState; if (isMatch) { @@ -196,35 +185,13 @@ public class FieldModel currentCol += colStep; } } - public int GetColumnHeight(int colIndex) - { - for (int row = Height - 1; row >= 0; row--) - { - if (FieldArray[row, colIndex] == CellState.Empty) - { - return row; - } - } - return -1;//если не нашли, то больше добавить нельзя - } - public bool checkDraw() + public static bool checkDraw() { for (int col = 0; col < Width; col++) { - if (GetColumnHeight(col) != -1) return false; + if (gm.board.GetLowestEmptyRow(col) != -1) return false; } return true; } - - public List CollectNonFullCols() - { - var positions = new List(); - for (int i = 0; i < Width; i++) - if (GetColumnHeight(i) != -1) - positions.Add(i); - return positions; - } -} - - +} \ No newline at end of file diff --git a/Assets/Scripts/Gameplay/FieldModel.cs.meta b/Assets/Scripts/Gameplay/FieldChecker.cs.meta similarity index 100% rename from Assets/Scripts/Gameplay/FieldModel.cs.meta rename to Assets/Scripts/Gameplay/FieldChecker.cs.meta diff --git a/Assets/Scripts/Menu/UiManager.cs b/Assets/Scripts/Menu/UiManager.cs index 1a8317a..11dc865 100644 --- a/Assets/Scripts/Menu/UiManager.cs +++ b/Assets/Scripts/Menu/UiManager.cs @@ -83,7 +83,7 @@ public class UiManager : MonoBehaviour while (parametr < 1) { parametr += Time.deltaTime * 2; - gm.board.localPosition = Vector3.Lerp(sBoard, eBoard, parametr); + gm.boardTransform.localPosition = Vector3.Lerp(sBoard, eBoard, parametr); gm.noPrizeLabel.localPosition = Vector3.Lerp(sNoPrize + Vector2.left * 3500, eNoPrize, parametr); yield return null; @@ -107,7 +107,7 @@ public class UiManager : MonoBehaviour float parametr = 1; while (parametr >= 0) { - gm.board.localPosition = Vector3.Lerp(sBoard, eBoard, parametr); + gm.boardTransform.localPosition = Vector3.Lerp(sBoard, eBoard, parametr); gm.noPrizeLabel.localPosition = Vector3.Lerp(eNoPrize + Vector2.left * 3500, eNoPrize, parametr); parametr -= Time.deltaTime * 2; yield return null;