# 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;
}
}
}
}
```