mirror of
				https://github.com/boudji-ludwig-pett/cnam-geometry-dash.git
				synced 2025-06-27 11:58:51 +02:00 
			
		
		
		
	fix: edit a level (#66)
Co-authored-by: Djelal BOUDJI <djelal@gmail.com> Co-authored-by: Théo LUDWIG <contact@theoludwig.fr>
This commit is contained in:
		| @@ -1,7 +1,4 @@ | ||||
| using System.IO; | ||||
| using UnityEngine; | ||||
| using UnityEngine.SceneManagement; | ||||
|  | ||||
|  | ||||
| public class NormalGameMode : IGameMode | ||||
| { | ||||
| @@ -18,7 +15,6 @@ public class NormalGameMode : IGameMode | ||||
|  | ||||
|         if (player.IsColliding && Input.GetKey(JumpKey) && !isRotating) | ||||
|         { | ||||
|             Debug.Log("Player is Jumping"); | ||||
|             Jump(player); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -51,6 +51,10 @@ public class LevelEditor : MonoBehaviour | ||||
|         HandleBlockDeletion(); | ||||
|     } | ||||
|  | ||||
|     void OnDestroy() | ||||
|     { | ||||
|         ClearEditor(); | ||||
|     } | ||||
|     #region UI | ||||
|  | ||||
|     void LoadPrefabs() | ||||
| @@ -176,7 +180,6 @@ public class LevelEditor : MonoBehaviour | ||||
|         foreach (var h in hits) | ||||
|         { | ||||
|             if (h == col) continue; | ||||
|             if (h.CompareTag("Ground")) continue; | ||||
|             if (h.transform.IsChildOf(currentBlock.transform)) continue; | ||||
|             return false; | ||||
|         } | ||||
| @@ -198,7 +201,7 @@ public class LevelEditor : MonoBehaviour | ||||
|             currentBlock = sel; | ||||
|             isPlacingBlock = true; | ||||
|             currentScale = currentBlock.transform.localScale; | ||||
|             Debug.Log($"🟢 Sélection : {sel.name}"); | ||||
|             Debug.Log($"Sélection : {sel.name}"); | ||||
|         } | ||||
|     } | ||||
|     void PlaceBlock() | ||||
| @@ -211,7 +214,7 @@ public class LevelEditor : MonoBehaviour | ||||
|             // 1) Bloquer si on perçoit un spike de même type dans la direction de snap | ||||
|             if (IsBlockedBySameTypeInSnapDirection()) | ||||
|             { | ||||
|                 Debug.LogError("❌ Impossible de poser un spike sur un autre spike !"); | ||||
|                 Debug.LogError("Impossible de poser un spike sur un autre spike !"); | ||||
|                 Destroy(currentBlock); | ||||
|             } | ||||
|             else | ||||
| @@ -219,7 +222,7 @@ public class LevelEditor : MonoBehaviour | ||||
|                 // 2) On snap dans la direction (down/left/up/right), et on détruit si aucun support | ||||
|                 if (!SnapSpikeByRotation()) | ||||
|                 { | ||||
|                     Debug.LogError("❌ Impossible de poser un spike dans le vide !"); | ||||
|                     Debug.LogError("Impossible de poser un spike dans le vide !"); | ||||
|                     Destroy(currentBlock); | ||||
|                 } | ||||
|                 else | ||||
| @@ -370,7 +373,7 @@ public class LevelEditor : MonoBehaviour | ||||
|         else if (dir == Vector2.right) p.x = bestHit.point.x - hw; | ||||
|  | ||||
|         currentBlock.transform.position = new Vector3(p.x, p.y, -1f); | ||||
|         Debug.Log($"📌 Spike snapé {dir} sur « {bestHit.collider.name} » à {currentBlock.transform.position}"); | ||||
|         Debug.Log($"Spike snapé {dir} sur « {bestHit.collider.name} » à {currentBlock.transform.position}"); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @@ -403,7 +406,7 @@ public class LevelEditor : MonoBehaviour | ||||
|             ? ResizeAxis.Horizontal | ||||
|             : ResizeAxis.Vertical; | ||||
|         isResizing = true; | ||||
|         Debug.Log($"🧰 Début redim {tgt.name} (axe {currentResizeAxis})"); | ||||
|         Debug.Log($"Début redim {tgt.name} (axe {currentResizeAxis})"); | ||||
|     } | ||||
|  | ||||
|     void PerformResizing() | ||||
| @@ -419,14 +422,14 @@ public class LevelEditor : MonoBehaviour | ||||
|         if (IsOverlapping(resizingTarget)) | ||||
|         { | ||||
|             resizingTarget.transform.localScale = originalScale; | ||||
|             Debug.Log("❌ Redim annulé : collision"); | ||||
|             Debug.Log("Redim annulé : collision"); | ||||
|         } | ||||
|         if (Input.GetMouseButtonUp(0)) | ||||
|         { | ||||
|             isResizing = false; | ||||
|             resizingTarget = null; | ||||
|             currentResizeAxis = ResizeAxis.None; | ||||
|             Debug.Log("✅ Fin redim"); | ||||
|             Debug.Log("Fin redim"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -452,7 +455,7 @@ public class LevelEditor : MonoBehaviour | ||||
|                 toD = toD.transform.parent.gameObject; | ||||
|             if (toD == currentBlock) { currentBlock = null; isPlacingBlock = false; } | ||||
|             Destroy(toD); | ||||
|             Debug.Log($"🗑️ Supprimé {toD.name}"); | ||||
|             Debug.Log($"Supprimé {toD.name}"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -470,45 +473,88 @@ public class LevelEditor : MonoBehaviour | ||||
|         var col = currentBlock.GetComponent<Collider2D>(); | ||||
|         var b = col.bounds; | ||||
|         float snapDistance = 1f; | ||||
|         float verticalEps = 0.05f; // petite marge pour exclure trop hauts ou trop bas | ||||
|         float verticalEps = 0.1f; | ||||
|  | ||||
|         // Taille et positions des deux zones de recherche latérales | ||||
|         Vector2 boxSize = new Vector2(snapDistance, b.size.y - verticalEps * 2f); | ||||
|         // à droite | ||||
|         // === SNAP HORIZONTAL (droite) | ||||
|         Vector2 hBoxSize = new Vector2(snapDistance, b.size.y - verticalEps * 2f); | ||||
|         Vector2 rightCenter = new Vector2(b.max.x + snapDistance / 2f, b.center.y); | ||||
|         // à gauche | ||||
|         Vector2 leftCenter = new Vector2(b.min.x - snapDistance / 2f, b.center.y); | ||||
|  | ||||
|         // Cherche à droite | ||||
|         var hits = Physics2D.OverlapBoxAll(rightCenter, boxSize, 0f); | ||||
|         var hits = Physics2D.OverlapBoxAll(rightCenter, hBoxSize, 0f); | ||||
|         foreach (var h in hits) | ||||
|         { | ||||
|             if (h != null && h.gameObject != currentBlock && !h.isTrigger) | ||||
|             { | ||||
|             if (IsInvalidSnapTarget(h)) continue; | ||||
|             float newX = h.bounds.min.x - b.extents.x; | ||||
|             currentBlock.transform.position = new Vector3(newX, currentBlock.transform.position.y, -1f); | ||||
|                 Debug.Log($"↔️ Snap horizontal à droite contre {h.name}"); | ||||
|             Debug.Log($"Snap horizontal à droite contre {h.name}"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // === SNAP HORIZONTAL (gauche) | ||||
|         Vector2 leftCenter = new Vector2(b.min.x - snapDistance / 2f, b.center.y); | ||||
|         hits = Physics2D.OverlapBoxAll(leftCenter, hBoxSize, 0f); | ||||
|         foreach (var h in hits) | ||||
|         { | ||||
|             if (IsInvalidSnapTarget(h)) continue; | ||||
|             float newX = h.bounds.max.x + b.extents.x; | ||||
|             currentBlock.transform.position = new Vector3(newX, currentBlock.transform.position.y, -1f); | ||||
|             Debug.Log($"Snap horizontal à gauche contre {h.name}"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // === SNAP VERTICAL (dessous) | ||||
|         Vector2 downBoxSize = new Vector2(b.size.x - 0.1f, snapDistance); | ||||
|         Vector2 downCenter = new Vector2(b.center.x, b.min.y - snapDistance / 2f); | ||||
|         hits = Physics2D.OverlapBoxAll(downCenter, downBoxSize, 0f); | ||||
|         foreach (var h in hits) | ||||
|         { | ||||
|             if (IsInvalidSnapTarget(h)) continue; | ||||
|             float newY = h.bounds.max.y + b.extents.y; | ||||
|             currentBlock.transform.position = new Vector3(currentBlock.transform.position.x, newY, -1f); | ||||
|             Debug.Log($"Snap vertical (bas) contre {h.name}"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // === SNAP VERTICAL (au-dessus) | ||||
|         Vector2 upCenter = new Vector2(b.center.x, b.max.y + snapDistance / 2f); | ||||
|         hits = Physics2D.OverlapBoxAll(upCenter, downBoxSize, 0f); | ||||
|         foreach (var h in hits) | ||||
|         { | ||||
|             if (IsInvalidSnapTarget(h)) continue; | ||||
|             float newY = h.bounds.min.y - b.extents.y; | ||||
|             currentBlock.transform.position = new Vector3(currentBlock.transform.position.x, newY, -1f); | ||||
|             Debug.Log($"Snap vertical (haut) contre {h.name}"); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         // Cherche à gauche | ||||
|         hits = Physics2D.OverlapBoxAll(leftCenter, boxSize, 0f); | ||||
|         foreach (var h in hits) | ||||
|     bool IsInvalidSnapTarget(Collider2D h) | ||||
|     { | ||||
|             if (h != null && h.gameObject != currentBlock && !h.isTrigger) | ||||
|         if (h == null || h.gameObject == currentBlock || h.isTrigger) return true; | ||||
|  | ||||
|         var t = h.transform; | ||||
|         if (t.parent != null && t.parent.name.Contains("ObstacleBlock")) | ||||
|         { | ||||
|                 float newX = h.bounds.max.x + b.extents.x; | ||||
|                 currentBlock.transform.position = new Vector3(newX, currentBlock.transform.position.y, -1f); | ||||
|                 Debug.Log($"↔️ Snap horizontal à gauche contre {h.name}"); | ||||
|                 return; | ||||
|             if (t.name.Contains("ObstacleKiller") || t.name.Contains("ObstacleSafer")) | ||||
|                 return true; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     // Filtrage des enfants parasites | ||||
|     bool IsChildOfObstacleBlock(Collider2D col) | ||||
|     { | ||||
|         var t = col.transform; | ||||
|         if (t.parent == null) return false; | ||||
|  | ||||
|         bool isNamedObstacleChild = t.name.Contains("ObstacleSafer") || t.name.Contains("ObstacleKiller"); | ||||
|         bool parentIsBlock = t.parent.name.Contains("ObstacleBlock"); | ||||
|         return isNamedObstacleChild && parentIsBlock; | ||||
|     } | ||||
|  | ||||
|     void HandleBlockRotation() | ||||
|     { | ||||
|         currentBlock.transform.Rotate(0, 0, -90f); | ||||
|         Debug.Log("🔄 Rotation 90°!"); | ||||
|         Debug.Log("Rotation 90°!"); | ||||
|     } | ||||
|  | ||||
|     void InstantiateAndPrepare(GameObject prefab, Vector3? scaleOverride = null) | ||||
| @@ -523,8 +569,25 @@ public class LevelEditor : MonoBehaviour | ||||
|  | ||||
|     public void Save() | ||||
|     { | ||||
|         // TODO | ||||
|     } | ||||
|  | ||||
|     #endregion | ||||
|  | ||||
|     public void ClearEditor() | ||||
|     { | ||||
|         if (persistentBlockContainer == null) return; | ||||
|  | ||||
|         foreach (Transform child in persistentBlockContainer) | ||||
|         { | ||||
|             Destroy(child.gameObject); | ||||
|         } | ||||
|  | ||||
|         Debug.Log("Éditeur vidé."); | ||||
|  | ||||
|         currentBlock = null; | ||||
|         isPlacingBlock = false; | ||||
|         currentPage = 0; | ||||
|         ClearCurrentButtons(); | ||||
|         GenerateButtons(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -13,7 +13,12 @@ public class LevelLoader : MonoBehaviour | ||||
|  | ||||
|     private GameObject GetPrefab(string type) | ||||
|     { | ||||
|         return Resources.Load<GameObject>("Prefabs/" + type); | ||||
|         var prefab = Resources.Load<GameObject>("Prefabs/" + type); | ||||
|         if (prefab == null) | ||||
|         { | ||||
|             Debug.LogError($"Prefab introuvable pour : {type}"); | ||||
|         } | ||||
|         return prefab; | ||||
|     } | ||||
|  | ||||
|     private void LoadAudio() | ||||
| @@ -28,29 +33,95 @@ public class LevelLoader : MonoBehaviour | ||||
|         { | ||||
|             musicSource.volume = 1f; | ||||
|         } | ||||
|  | ||||
|         musicSource.Play(); | ||||
|     } | ||||
|  | ||||
|     private void LoadElements() | ||||
|     { | ||||
|         Level current = levelsLoader.levelCurrent; | ||||
|  | ||||
|         foreach (var element in current.elements) | ||||
|         { | ||||
|             GameObject prefab = GetPrefab(element.type); | ||||
|             GameObject instance = Instantiate(prefab, new Vector3(element.x, element.y, 0), Quaternion.identity); | ||||
|             if (prefab == null) continue; | ||||
|  | ||||
|             if (prefab.CompareTag("Kill")) | ||||
|             GameObject instance = Instantiate( | ||||
|                 prefab, | ||||
|                 new Vector3(element.x, element.y, 0), | ||||
|                 Quaternion.identity | ||||
|             ); | ||||
|  | ||||
|             if (editMode) | ||||
|             { | ||||
|                 Instantiate(Resources.Load<GameObject>("AICollider"), new Vector3(element.x - 1, element.y, 0), Quaternion.identity); | ||||
|                 foreach (Transform child in instance.transform) | ||||
|                 { | ||||
|                     if (child.name.Contains("ObstacleKiller")) | ||||
|                     { | ||||
|                         var col = child.GetComponent<BoxCollider2D>(); | ||||
|                         if (col != null && col.size.y > 2f) // Trop grand | ||||
|                         { | ||||
|                             Debug.LogWarning($"⚠️ Collider {child.name} trop grand, réduction appliquée."); | ||||
|                             col.size = new Vector2(col.size.x, 1f); | ||||
|                             col.offset = new Vector2(col.offset.x, -2f); // Ajuste selon ton design | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|  | ||||
|  | ||||
|             // En mode jeu/test uniquement → ajout du AICollider | ||||
|             if (!editMode) | ||||
|             { | ||||
|                 if (prefab.CompareTag("Kill")) | ||||
|                 { | ||||
|                     Instantiate( | ||||
|                         Resources.Load<GameObject>("AICollider"), | ||||
|                         new Vector3(element.x - 1, element.y, 0), | ||||
|                         Quaternion.identity | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Appliquer l'échelle personnalisée | ||||
|             Vector3 originalScale = instance.transform.localScale; | ||||
|             float newScaleX = element.scaleX > 0 ? element.scaleX : originalScale.x; | ||||
|             float newScaleY = element.scaleY > 0 ? element.scaleY : originalScale.y; | ||||
|  | ||||
|             instance.transform.localScale = new Vector3(newScaleX, newScaleY, originalScale.z); | ||||
|         } | ||||
|  | ||||
|         // Sol uniquement en mode jeu | ||||
|         if (!editMode) | ||||
|         { | ||||
|             GameObject groundPrefab = GetPrefab("Ground"); | ||||
|             if (groundPrefab != null) | ||||
|             { | ||||
|                 GameObject groundInstance = Instantiate( | ||||
|                     groundPrefab, | ||||
|                     new Vector3(current.LastX / 2, groundY, 0), | ||||
|                     Quaternion.identity | ||||
|                 ); | ||||
|                 groundInstance.transform.localScale = new Vector3(current.LastX / 5f * 2, 1, 1); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Mur de fin toujours placé | ||||
|         GameObject winWall = GetPrefab("WinnerWall"); | ||||
|         if (winWall != null) | ||||
|         { | ||||
|             Instantiate( | ||||
|                 winWall, | ||||
|                 new Vector3(current.LastX, 0, 0), | ||||
|                 Quaternion.Euler(0, 0, 90) | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void Awake() | ||||
|     { | ||||
|         levelsLoader = GameObject.FindGameObjectWithTag("LevelsLoader").GetComponent<LevelsLoader>(); | ||||
|         Level current = levelsLoader.levelCurrent; | ||||
|         createMode = PlayerPrefs.GetInt("CreateMode", 0) == 1; | ||||
|         if (!editMode) | ||||
|         { | ||||
|             GameObject groundPrefab = GetPrefab("Ground"); | ||||
| @@ -63,10 +134,12 @@ public class LevelLoader : MonoBehaviour | ||||
|  | ||||
|     public void Start() | ||||
|     { | ||||
|         createMode = PlayerPrefs.GetInt("CreateMode", 0) == 1; | ||||
|         if (!createMode) | ||||
|         { | ||||
|             levelsLoader = GameObject.FindGameObjectWithTag("LevelsLoader").GetComponent<LevelsLoader>(); | ||||
|             levelsLoader = GameObject | ||||
|                 .FindGameObjectWithTag("LevelsLoader") | ||||
|                 .GetComponent<LevelsLoader>(); | ||||
|  | ||||
|             levelsLoader.IncreaseTotalAttempts(); | ||||
|  | ||||
|             LoadElements(); | ||||
| @@ -79,8 +152,7 @@ public class LevelLoader : MonoBehaviour | ||||
|     { | ||||
|         if (!editMode) | ||||
|         { | ||||
|             Level current = levelsLoader.levelCurrent; | ||||
|             progressionText.text = current.ProgressionPercent + "%"; | ||||
|             progressionText.text = levelsLoader.levelCurrent.ProgressionPercent + "%"; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										0
									
								
								Assets/Scripts/LevelsSelect/LevelEditor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								Assets/Scripts/LevelsSelect/LevelEditor
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										7
									
								
								Assets/Scripts/LevelsSelect/LevelEditor.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Assets/Scripts/LevelsSelect/LevelEditor.meta
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 588b3f9ce673f764b8a3a81842ed9f46 | ||||
| DefaultImporter: | ||||
|   externalObjects: {} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
| @@ -91,22 +91,25 @@ public class Player : MonoBehaviour | ||||
|     { | ||||
|         CurrentGameMode?.OnCollisionEnter(this, collision); | ||||
|  | ||||
|         if (collision.gameObject.CompareTag("Kill")) | ||||
|         { | ||||
|             if (editMode) | ||||
|         if (editMode && (collision.gameObject.CompareTag("Kill") || collision.gameObject.CompareTag("Win"))) | ||||
|         { | ||||
|             GameObject spawn = new GameObject("AutoSpawnPoint"); | ||||
|             spawn.transform.position = new Vector3(-16, -3, 0f); | ||||
|             transform.position = spawn.transform.position; | ||||
|             RigidBody.linearVelocity = Vector2.zero; | ||||
|             SpeedMultiplier = 1f; | ||||
|             CurrentGameMode = new NormalGameMode(); | ||||
|             SpriteRenderer.sprite = Resources.Load<Sprite>("Shapes/BaseSquare"); | ||||
|             return; | ||||
|         } | ||||
|             else | ||||
|  | ||||
|         if (collision.gameObject.CompareTag("Kill")) | ||||
|         { | ||||
|  | ||||
|             sfxSource.clip = Resources.Load<AudioClip>(Path.Combine("Sounds", "death")); | ||||
|             sfxSource.Play(); | ||||
|             StartCoroutine(LevelHomeButton.PlaySoundAndLoadScene(sfxSource, SceneManager.GetActiveScene().name)); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         if (collision.gameObject.CompareTag("Win")) | ||||
|   | ||||
| @@ -76,6 +76,8 @@ public class TestManager : MonoBehaviour | ||||
|         } | ||||
|  | ||||
|         currentPlayer.transform.position = spawnPoint.position; | ||||
|         currentPlayer.transform.rotation = Quaternion.Euler(0f, 0f, 0f); | ||||
|         currentPlayer.RigidBody.freezeRotation = true; | ||||
|         currentPlayer.RigidBody.linearVelocity = Vector2.zero; | ||||
|         currentPlayer.SpeedMultiplier = 1f; | ||||
|         // currentPlayer.SpriteRenderer.sprite = Resources.Load<Sprite>("Shapes/BaseSquare"); | ||||
| @@ -93,7 +95,7 @@ public class TestManager : MonoBehaviour | ||||
|             currentPlayer.SpriteRenderer.enabled = true; | ||||
|  | ||||
|         if (currentPlayer.Particle != null) | ||||
|             currentPlayer.Particle.Play(); // ✅ Démarrer la particule | ||||
|             currentPlayer.Particle.Play(); // Démarrer la particule | ||||
|  | ||||
|         Debug.Log("[TestManager] Test du niveau démarré !"); | ||||
|     } | ||||
| @@ -110,7 +112,7 @@ public class TestManager : MonoBehaviour | ||||
|             currentPlayer.SpeedMultiplier = 0f; | ||||
|  | ||||
|             if (currentPlayer.Particle != null) | ||||
|                 currentPlayer.Particle.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); // ✅ Arrêter proprement | ||||
|                 currentPlayer.Particle.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); // Arrêter proprement | ||||
|  | ||||
|             if (currentPlayer.SpriteRenderer != null) | ||||
|                 currentPlayer.SpriteRenderer.enabled = false; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user