# Worm Puzzle Code **For** [[DESIGNS/ToyWorldsAtlas/G-Atlas_Doc|Worm Puzzle]] at [[NEPOBJEDIVI/GAME DESIGN/Toy Worlds Atlas|Toy Worlds Atlas]] ### Puzzle Script **Nov 17, 2025** ```cs using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Linq; using UnityEngine.UI; using TMPro; public class Puzzle_G : MonoBehaviour { // UI public TMP_InputField nameInputField; public string nextSceneName; // UI - specific for G public Button orangeryButton; public TMP_Text expRulesObj; public string rulesDescr_1; public string rulesDescr_2; // Objects public GameObject Worm_I; // for the first selection of colours; doesn't go to the Orangery public GameObject Worm_II; // the plankton on the scene public JsonObj_Atlas atlasJsonScript_I; // doesn't go in the orangery public JsonObj_Atlas atlasJsonScript_II; // goes to the orangery // To deactivate buttons during the victory animation, // and to assign OnButtonClicked method public List<Button> colorantButtonsList; private bool[] buttonFlagsList = new bool[8]; public int timesFilled; // two allow the colouring twice private Victory victoryScript; // To access atlasCorrect bool (the victory condition) // Specific to this atlas public GameObject[] panelList; // to de/activate all types of the pressed button // Colouring blink private SpriteRenderer[] allBodyParts; // to colour all body parts for a moment when the button is pressed private Coroutine currentBlinkCoroutine; public float fadeDuration = 0.3f; // for the coroutine private int currentPressIndex = 0; // to colour worm's segments in the succession of player's selection // To colour animated worms public List<GameObject> Worm_I_Objects; public List<GameObject> Worm_II_Objects; private List<int> g1_colourCodesList; private List<int> g2_colourCodesList; // Flags to sequence of worms' appearance and animations private bool filledOnce; // To be able to turn buttons true when they all got turned false private bool filledTwice; // Animations (specific to G) public Animator G1_animator; public Animator G2_animator; public string G1_AnimationBool_1; public string G2_AnimationBool_1; private void Start() { victoryScript = gameObject.GetComponent<Victory>(); // to get access to atlasCorrect bool in CheckVictory(); victoryScript.atlasCorrect = false; // restarts the win-condition // To assign selected colours after completion g1_colourCodesList = Worm_I.GetComponent<JsonObj_Atlas>().colourCodes; g2_colourCodesList = Worm_II.GetComponent<JsonObj_Atlas>().colourCodes; } private void Update() { CheckVictory_andFill(); } private void CheckVictory_andFill() { if (buttonFlagsList.All(flag => flag == true)) { timesFilled++; } if (timesFilled == 1 && !filledOnce) { StartCoroutine(FirstFillSequence()); for (int i = 0; i < buttonFlagsList.Length; i++) { buttonFlagsList[i] = false; } filledOnce = true; } else if (timesFilled == 2 && !filledTwice) { StartCoroutine(AssignSelectedColours()); GenerateProfileText(); for (int i = 0; i < buttonFlagsList.Length; i++) { buttonFlagsList[i] = false; } filledTwice = true; } } private IEnumerator FirstFillSequence() { yield return new WaitForSeconds(1.8f); foreach (GameObject panel in panelList) { panel.SetActive(true); } Worm_I.SetActive(false); // deactivates the worm with the first selection of colours Worm_II.SetActive(true); // activates the worm for the second selection of colours expRulesObj.text = rulesDescr_2; expRulesObj.color = new Color(0.294f, 0.686f, 1f); } private IEnumerator AssignSelectedColours() { orangeryButton.interactable = false; yield return new WaitForSeconds(1.8f); expRulesObj.text = ""; // Activates both versions of the worm Worm_I.SetActive(true); Worm_II.SetActive(true); // Activates the 1st animation for both atlases // (they go in parallel) G1_animator.SetBool(G1_AnimationBool_1, true); G2_animator.SetBool(G2_AnimationBool_1, true); // Waits until the first part of the animation finishes, // and the worm starts to wing its tail yield return new WaitForSeconds(7f); // Assigns selected colours to both worms (unsevered parts) with a delay // The first colour assigns ColourSeveredParts(g1_colourCodesList, Worm_I_Objects[7], g1_colourCodesList[7]); ColourSeveredParts(g2_colourCodesList, Worm_II_Objects[0], g2_colourCodesList[0]); yield return new WaitForSeconds(0.75f); // The second colour ColourSeveredParts(g1_colourCodesList, Worm_I_Objects[6], g1_colourCodesList[6]); ColourSeveredParts(g2_colourCodesList, Worm_II_Objects[1], g2_colourCodesList[1]); yield return new WaitForSeconds(0.75f); // The third colour ColourSeveredParts(g1_colourCodesList, Worm_I_Objects[5], g1_colourCodesList[5]); ColourSeveredParts(g2_colourCodesList, Worm_II_Objects[2], g2_colourCodesList[2]); yield return new WaitForSeconds(0.75f); // The fourth ColourSeveredParts(g1_colourCodesList, Worm_I_Objects[4], g1_colourCodesList[4]); ColourSeveredParts(g2_colourCodesList, Worm_II_Objects[3], g2_colourCodesList[3]); // Assigns to severed parts // The fifth ColourSeveredParts(g1_colourCodesList, Worm_I_Objects[3], g1_colourCodesList[3]); ColourSeveredParts(g2_colourCodesList, Worm_II_Objects[4], g2_colourCodesList[4]); ColourSeveredParts(g1_colourCodesList, Worm_I_Objects[2], g1_colourCodesList[2]); ColourSeveredParts(g2_colourCodesList, Worm_II_Objects[5], g2_colourCodesList[5]); ColourSeveredParts(g1_colourCodesList, Worm_I_Objects[1], g1_colourCodesList[1]); ColourSeveredParts(g2_colourCodesList, Worm_II_Objects[6], g2_colourCodesList[6]); ColourSeveredParts(g1_colourCodesList, Worm_I_Objects[0], g1_colourCodesList[0]); ColourSeveredParts(g2_colourCodesList, Worm_II_Objects[7], g2_colourCodesList[7]); yield return new WaitForSeconds(3f); // In 6.2 seconds the button rolls, // and InputWindow appears victoryScript.atlasCorrect = true; // Play the second animation } private void ColourSeveredParts(List<int> colourList, GameObject sliceG, int colourG) { // Take colour indexes from json and colour the worm // Colours both worms bc the method is called twice each time if (colourList[colourG] == 0) sliceG.GetComponent<ColorantManager>().OnBtnColor0(); if (colourList[colourG] == 1) sliceG.GetComponent<ColorantManager>().OnBtnColor1(); if (colourList[colourG] == 2) sliceG.GetComponent<ColorantManager>().OnBtnColor2(); if (colourList[colourG] == 3) sliceG.GetComponent<ColorantManager>().OnBtnColor3(); if (colourList[colourG] == 4) sliceG.GetComponent<ColorantManager>().OnBtnColor4(); if (colourList[colourG] == 5) sliceG.GetComponent<ColorantManager>().OnBtnColor5(); if (colourList[colourG] == 6) sliceG.GetComponent<ColorantManager>().OnBtnColor6(); if (colourList[colourG] == 7) sliceG.GetComponent<ColorantManager>().OnBtnColor7(); } private void GenerateProfileText() { // Or just send a boolean in a separate script // Generates a personalised profile // based on the player's choice of colours } public void OnButtonClicked(int index) { // For the worm's segments to fill in the succession of the player's selection if (Worm_I.activeSelf) { atlasJsonScript_I.colourCodes[currentPressIndex] = index; currentPressIndex++; } else if (Worm_II.activeSelf) { if (currentPressIndex >= 8) currentPressIndex = 0; atlasJsonScript_II.colourCodes[currentPressIndex] = index; currentPressIndex++; } switch (index) { case 0: panelList[0].SetActive(false); // Black buttonFlagsList[0] = true; break; case 1: panelList[1].SetActive(false); // Magenta buttonFlagsList[1] = true; break; case 2: panelList[2].SetActive(false); // Red buttonFlagsList[2] = true; break; case 3: panelList[3].SetActive(false); // Grey buttonFlagsList[3] = true; break; case 4: panelList[4].SetActive(false); // Brown buttonFlagsList[4] = true; break; case 5: panelList[5].SetActive(false); // Blue buttonFlagsList[5] = true; break; case 6: panelList[6].SetActive(false); // Yellow buttonFlagsList[6] = true; break; case 7: panelList[7].SetActive(false); // Green buttonFlagsList[7] = true; break; } // If another button is pressed during the current coroutine, // stop this coroutine if (currentBlinkCoroutine != null) StopCoroutine(currentBlinkCoroutine); // Start the new coroutine currentBlinkCoroutine = StartCoroutine(ColourBlink(index)); } private IEnumerator ColourBlink(int index) { if (Worm_I.activeSelf) { allBodyParts = Worm_I.GetComponentsInChildren<SpriteRenderer>(); } else if (Worm_II.activeSelf) { allBodyParts = Worm_II.GetComponentsInChildren<SpriteRenderer>(); } foreach (SpriteRenderer bodyPart in allBodyParts) { if (bodyPart.CompareTag("Colourable")) { switch (index) { case 0: bodyPart.GetComponent<ColorantManager>().OnBtnColor0(); break; case 1: bodyPart.GetComponent<ColorantManager>().OnBtnColor1(); break; case 2: bodyPart.GetComponent<ColorantManager>().OnBtnColor2(); break; case 3: bodyPart.GetComponent<ColorantManager>().OnBtnColor3(); break; case 4: bodyPart.GetComponent<ColorantManager>().OnBtnColor4(); break; case 5: bodyPart.GetComponent<ColorantManager>().OnBtnColor5(); break; case 6: bodyPart.GetComponent<ColorantManager>().OnBtnColor6(); break; case 7: bodyPart.GetComponent<ColorantManager>().OnBtnColor7(); break; } } } // Turns back to blank white foreach (SpriteRenderer bodyPart in allBodyParts) { if (bodyPart.CompareTag("Colourable")) { Color starColour = bodyPart.color; float elapsed = 0f; while (elapsed < fadeDuration) { elapsed += Time.deltaTime; float t = elapsed / fadeDuration; bodyPart.color = Color.Lerp(starColour, Color.white, t); yield return null; } if (bodyPart.CompareTag("Colourable")) bodyPart.color = Color.white; } } } } ```