/// <summary> /// Colours a line of tiles starting from the given location and moving in the given direction. Line stops at blank tiles. /// </summary> /// <param name="loc">Location to start colouring from.</param> /// <param name="dir">Direction to move in.</param> /// <param name="col">Colour to use.</param> public void ColourLineFrom(IntVector.IntVector2 loc, Direction dir, ColourPicker.Colour col) { int dx = 0; int dy = 0; if (dir == Direction.Up) { dy = 1; } else if (dir == Direction.Down) { dy = -1; } else if (dir == Direction.Left) { dx = -1; } else if (dir == Direction.Right) { dx = 1; } while (loc.x >= 0 && loc.x < width && loc.y >= 0 && loc.y < height) { if (gridTiles[loc.x][loc.y].Type == Tile.TileType.Blank) // stop at blanks { break; } ColourTile(loc, col); loc.x += dx; loc.y += dy; } }
/// <summary> /// Constructor, creates a tile of the given type. /// </summary> /// <param name="t">type of tile</param> /// <param name="g">grid</param> /// <param name="x">x position of tile</param> /// <param name="y">y position of tile</param> public Tile(TileType t, GameObject g, int x, int y) { type = t; colour = ColourPicker.Colour.White; if (t == TileType.Blank) // no game object necessary if tile is blank { tileObject = null; } else // create appropriate game object for other tiles { int checker = (x + y) % 2; if (t == TileType.Default) { tileObject = ResourceLoader.GetSpriteGameObject(t + "Tile", g, (float)x, (float)y, "Tiles", 1, "Sprites/Tiles/Tile-Default-" + checker.ToString()); } else if (t == TileType.Ice) { tileObject = ResourceLoader.GetSpriteGameObject(t + "Tile", g, (float)x, (float)y, "Tiles", 1, "Sprites/Tiles/Tile-Ice-" + checker.ToString()); ResourceLoader.GetSpriteGameObject(t + "TileGlint", tileObject, 0.0f, 0.0f, "Tiles", 3, "Sprites/Tiles/Tile-Ice-Glint"); } else { tileObject = ResourceLoader.GetSpriteGameObject(t + "Tile", g, (float)x, (float)y, "Tiles", 1, "Sprites/Tiles/Tile-Dark-" + checker.ToString()); } // create outline ResourceLoader.GetSpriteGameObject(t + "TileOutline", tileObject, 0.0f, 0.0f, "Tiles", 0, "Sprites/Tiles/Tile-Outline"); } }
/// <summary> /// Constructor, creates a solution tile. /// </summary> /// <param name="col"></param> public Tile(ColourPicker.Colour col, GameObject g, int x, int y, TileType tt) { type = TileType.Default; colour = col; if (tt == TileType.Blank) // no game object necessary if tile is blank or a block { tileObject = null; } else // create appropriate game object for other colours { int checker = (x + y) % 2; if (tt == TileType.Default) { tileObject = ResourceLoader.GetSpriteGameObject(col + "Tile", g, (float)x, (float)y, "Tiles", 2, "Sprites/Tiles/Tile-Default-" + checker.ToString(), col); } else if (tt == TileType.Ice) { tileObject = ResourceLoader.GetSpriteGameObject(col + "Tile", g, (float)x, (float)y, "Tiles", 2, "Sprites/Tiles/Tile-Ice-" + checker.ToString()); tileObject.GetComponent <SpriteRenderer>().color = Grid.IceColourMap[col]; } else { tileObject = ResourceLoader.GetSpriteGameObject(col + "Tile", g, (float)x, (float)y, "Tiles", 2, "Sprites/Tiles/Tile-Dark-" + checker.ToString()); } } }
/// <summary> /// The player will now eraser instead of colour. /// </summary> public void BeginErase() { eraserOn = true; colour = ColourPicker.Colour.White; SpriteRenderer s = GetComponent <SpriteRenderer>(); s.color = Color.white; outline.sprite = ResourceLoader.GetSprite("Sprites/Player/Player-Eraser-Outline"); }
/// <summary> /// Initialization /// </summary> void Start() { isMoving = false; colour = ColourPicker.Colour.White; canMove = true; eraserOn = false; lastMove = extraMoveDirection = Grid.Direction.Left; extraMove = false; reset = false; paused = false; }
/// <summary> /// Updates the number of correct tiles when changing the colour of one tile. /// </summary> /// <param name="pos">Location of tile.</param> /// <param name="col">Colour that the tile will change to.</param> private void UpdateCorrectTiles(IntVector.IntVector2 pos, ColourPicker.Colour col) { if (gridTiles[pos.x][pos.y].Colour == solutionTiles[pos.x][pos.y].Colour && col != solutionTiles[pos.x][pos.y].Colour) // changing colour of tile that is already correct { correctTiles -= 1; } else if (gridTiles[pos.x][pos.y].Colour != solutionTiles[pos.x][pos.y].Colour && col == solutionTiles[pos.x][pos.y].Colour) // changing tile to correct colour { correctTiles += 1; } }
/// <summary> /// Colours the tile at the given position with the given colour. /// </summary> /// <param name="pos">Position of the tile.</param> /// <param name="col">Colour to use.</param> public void ColourTile(IntVector.IntVector2 pos, ColourPicker.Colour col) { // only default and ice tiles can be painted, colour of white will not affect tiles if ((gridTiles[pos.x][pos.y].Type == Tile.TileType.Default || gridTiles[pos.x][pos.y].Type == Tile.TileType.Ice) && col != ColourPicker.Colour.White) { // check if colour change affects currently correct tiles UpdateCorrectTiles(pos, col); gridTiles[pos.x][pos.y].Colour = col; } }
/// <summary> /// Constructor. /// </summary> /// <param name="x">x coordinate.</param> /// <param name="y">y coordinate.</param> /// <param name="col">Colour of the splash.</param> /// <param name="g">Grid the splash is on.</param> /// <param name="parent">Parent of the base object.</param> public Splash(int x, int y, ColourPicker.Colour col, Grid g, GameObject parent, int radius = 2) { location = new IntVector.IntVector2(x, y); colour = col; grid = g; splashRadius = radius; // create the game object GameObject splashObject = ResourceLoader.GetSpriteGameObject(colour + "Splash", parent, (float)x, (float)y, "Tools", 0, "Sprites/Tools/Splash", col); rotate = splashObject.AddComponent <AutoRotator>(); }
/// <summary> /// Colours the tiles around the given location. /// </summary> /// <param name="col">Colour to use.</param> /// <param name="location">Location of the center of the splash.</param> /// <param name="radius">Radius of the splash. Must be greater than zero.</param> public void Splash(IntVector.IntVector2 location, int radius, ColourPicker.Colour col) { IntVector.IntVector2 pos = location; for (int i = -radius; i <= radius; i += 1) { pos.x = location.x + i; for (int j = -radius; j <= radius; j += 1) { pos.y = location.y + j; if (withinGrid(pos) && (Mathf.Abs(i) + Mathf.Abs(j) <= radius)) { ColourTile(pos, col); } } } }
/// <summary> /// Constructor. /// </summary> /// <param name="x">x coordinate.</param> /// <param name="y">y coordinate.</param> /// <param name="g">Grid that the line-shot is on.</param> /// <param name="col">Colour of the line-shot.</param> /// <param name="dir">List of directions the line-shot will shoot at.</param> /// <param name="parent">Game object parent of the line-shot.</param> public LineShot(int x, int y, Grid g, ColourPicker.Colour col, List <Grid.Direction> dir, GameObject parent) { location = new IntVector.IntVector2(x, y); grid = g; colour = col; directions = dir; // size pulser settings float r = UnityEngine.Random.Range(0.1f, 0.9f); Vector2 small = new Vector2(0.95f, 0.95f); Vector2 big = new Vector2(1.05f, 1.05f); // create the game objects GameObject mainObject = new GameObject(); mainObject.name = col + "LineShot"; mainObject.transform.parent = parent.transform; Vector3 mainPos = mainObject.transform.localPosition; mainPos.x = (float)x; mainPos.y = (float)y; mainObject.transform.localPosition = mainPos; pulse = mainObject.AddComponent <SizePulser>(); pulse.SetParams(true, r, small, big); // line-shot base ResourceLoader.GetSpriteGameObject("LineShotBase", mainObject, 0.0f, 0.0f, "Tools", 0, "Sprites/Tools/LineShot", col); // arrows foreach (Grid.Direction d in dir) { GameObject arrow = ResourceLoader.GetSpriteGameObject(d + "LineShotArrow", mainObject, 0.0f, 0.0f, "Tools", 0, "Sprites/Tools/LineShot-Arrow", col); if (d == Grid.Direction.Left) { arrow.transform.Rotate(Vector3.forward, 90.0f); } else if (d == Grid.Direction.Right) { arrow.transform.Rotate(Vector3.forward, -90.0f); } else if (d == Grid.Direction.Down) { arrow.transform.Rotate(Vector3.forward, 180.0f); } } }
/// <summary> /// Constructor. /// </summary> /// <param name="x">x coordinate.</param> /// <param name="y">y coordinate.</param> /// <param name="parent">Parent game object.</param> /// <param name="o">Connected teleporter.</param> public Teleporter(int x, int y, Grid g, GameObject parent, Teleporter o = null) { location = new IntVector.IntVector2(x, y); grid = g; other = o; // size pulser settings float r = UnityEngine.Random.Range(0.1f, 0.9f); Vector2 small = new Vector2(1.0f, 0.95f); Vector2 big = new Vector2(1.0f, 1.05f); // create the teleporter ColourPicker.Colour col = (ColourPicker.Colour)((count / 2) % ColourPicker.ColourCount); GameObject teleObject = ResourceLoader.GetSpriteGameObject(col + "Teleporter", parent, (float)x, (float)y, "Tools", 1, "Sprites/Tools/Teleporter", col); pulse = teleObject.AddComponent <SizePulser>(); pulse.SetParams(true, r, small, big); // increment count count += 1; }
/// <summary> /// Default constructor, just creates a blank tile. /// </summary> public Tile() { type = TileType.Blank; colour = ColourPicker.Colour.White; tileObject = null; }
/// <summary> /// Creates a new game object with a sprite. /// </summary> /// <param name="name">Name of the object.</param> /// <param name="parent">Parent of the object.</param> /// <param name="localx">Local x coordinate.</param> /// <param name="localy">Local y coordinate.</param> /// <param name="sortLayer">Sorting layer of the sprite.</param> /// <param name="sortOrder">Sorting order of the sprite in the sorting layer.</param> /// <param name="path">Pathname for the sprite image.</param> /// <param name="col">Colour of the sprite.</param> /// <returns></returns> public static GameObject GetSpriteGameObject(string name, GameObject parent, float localx, float localy, string sortLayer, int sortOrder, string path, ColourPicker.Colour col = ColourPicker.Colour.White) { GameObject g = new GameObject(); g.name = name; g.transform.parent = parent.transform; g.transform.localPosition = new Vector2(localx, localy); g.AddComponent <SpriteRenderer>(); SpriteRenderer render = g.GetComponent <SpriteRenderer>(); render.sortingLayerName = sortLayer; render.sortingOrder = sortOrder; render.color = Grid.ColourMap[col]; render.sprite = ResourceLoader.GetSprite(path); return(g); }
/// <summary> /// Initializes and populates the grid. /// </summary> void Start() { // Initial settings puzzleFinished = false; winMessage.Hide(); Teleporter.ResetCount(); pauseMenu.SetActive(false); player.GetComponent <Player>().CanMove = true; // get level info TextAsset levelInfo = Level.LevelInfo; string[] txtLines = levelInfo.text.Split('\n'); // read in level info try { width = int.Parse(txtLines[0]); height = int.Parse(txtLines[1]); // create the puzzle grid and solution grid gridTiles = new Tile[width][]; solutionTiles = new Tile[width][]; for (int i = 0; i < width; i += 1) { gridTiles[i] = new Tile[height]; solutionTiles[i] = new Tile[height]; } // create grid game object gridObjects = new GameObject(); gridObjects.transform.parent = gameObject.transform; gridObjects.name = "GridObjects"; // create grid tiles, set default tile colours for (int i = 0; i < width; i += 1) { for (int j = 0; j < height; j += 1) { gridTiles[i][height - 1 - j] = new Tile(ReadTileType(txtLines[j + 2][i]), gridObjects, i, height - 1 - j); } } // place player at start location player.transform.parent = gridObjects.transform; playerStartLocation.x = playerCurrentLocation.x = int.Parse(txtLines[2 + height]); playerStartLocation.y = playerCurrentLocation.y = int.Parse(txtLines[3 + height]); player.transform.localPosition = new Vector2((float)playerStartLocation.x, (float)playerStartLocation.y); // read in tools #region Read in tools and create them int toolNum = int.Parse(txtLines[4 + height]); int lineNum = 5 + height; // create tools gridTools = new Dictionary <IntVector.IntVector2, Tool>(); for (int i = 0; i < toolNum; i += 1) { char toolType = txtLines[lineNum][0]; if (toolType == 'c') // colour picker { ColourPicker.Colour col = ReadColour(txtLines[lineNum][1]); IntVector.IntVector2 loc = new IntVector.IntVector2(int.Parse(txtLines[lineNum + 1]), int.Parse(txtLines[lineNum + 2])); ColourPicker cp = new ColourPicker(loc.x, loc.y, col, gridObjects); gridTools.Add(loc, cp); lineNum += 3; } else if (toolType == 's') // splash { ColourPicker.Colour col = ReadColour(txtLines[lineNum][1]); IntVector.IntVector2 loc = new IntVector.IntVector2(int.Parse(txtLines[lineNum + 1]), int.Parse(txtLines[lineNum + 2])); Splash s = new Splash(loc.x, loc.y, col, this, gridObjects); gridTools.Add(loc, s); lineNum += 3; } else if (toolType == 'l') // line shot { ColourPicker.Colour col = ReadColour(txtLines[lineNum][1]); int numDir = int.Parse(txtLines[lineNum + 1]); List <Direction> dir = new List <Direction>(); for (int j = 0; j < numDir; j += 1) { dir.Add(ReadDirection(txtLines[lineNum + 2][j])); } IntVector.IntVector2 loc = new IntVector.IntVector2(int.Parse(txtLines[lineNum + 3]), int.Parse(txtLines[lineNum + 4])); LineShot l = new LineShot(loc.x, loc.y, this, col, dir, gridObjects); gridTools.Add(loc, l); lineNum += 5; } else if (toolType == 'e') { IntVector.IntVector2 loc = new IntVector.IntVector2(int.Parse(txtLines[lineNum + 1]), int.Parse(txtLines[lineNum + 2])); Eraser e = new Eraser(loc.x, loc.y, gridObjects); gridTools.Add(loc, e); lineNum += 3; } else if (toolType == 't') { IntVector.IntVector2 loc1 = new IntVector.IntVector2(int.Parse(txtLines[lineNum + 1]), int.Parse(txtLines[lineNum + 2])); IntVector.IntVector2 loc2 = new IntVector.IntVector2(int.Parse(txtLines[lineNum + 3]), int.Parse(txtLines[lineNum + 4])); Teleporter t1 = new Teleporter(loc1.x, loc1.y, this, gridObjects); Teleporter t2 = new Teleporter(loc2.x, loc2.y, this, gridObjects, t1); t1.Other = t2; gridTools.Add(loc1, t1); gridTools.Add(loc2, t2); lineNum += 5; } else if (toolType == 'r') { Direction d = ReadDirection(txtLines[lineNum][1]); IntVector.IntVector2 loc = new IntVector.IntVector2(int.Parse(txtLines[lineNum + 1]), int.Parse(txtLines[lineNum + 2])); Redirection r = new Redirection(loc.x, loc.y, gridObjects, d); gridTools.Add(loc, r); lineNum += 3; } else { throw new System.Exception(); } } #endregion // create solution grid object and the mini-guide #region Read in solution and create overlay solutionGrid = new GameObject(); solutionGrid.name = "Solution"; solutionGrid.transform.parent = transform; // create mini-guide GameObject miniGuide = new GameObject(); miniGuide.name = "Mini-Guide"; GameObject guideOutline = new GameObject(); guideOutline.name = "GuideOutline"; guideOutline.transform.localPosition = new Vector2(0.0f, 0.0f); guideOutline.transform.parent = miniGuide.transform; GameObject guideTiles = new GameObject(); guideTiles.name = "GuideTiles"; guideTiles.transform.localPosition = new Vector2(0.0f, 0.0f); guideTiles.transform.parent = miniGuide.transform; // read in solution for (int i = 0; i < width; i += 1) { for (int j = 0; j < height; j += 1) { ColourPicker.Colour col = ReadColour(txtLines[lineNum + j][i]); int x = (i + height - 1 - j) % 2; // overlay solutionTiles[i][height - 1 - j] = new Tile(col, solutionGrid, i, height - 1 - j, gridTiles[i][height - 1 - j].Type); // mini guide Tile.TileType t = gridTiles[i][height - 1 - j].Type; if (t != Tile.TileType.Blank) { if (t == Tile.TileType.Default || t == Tile.TileType.Ice) { ResourceLoader.GetSpriteGameObject("GuideTile", guideTiles, i, height - 1 - j, "Guide", 1, "Sprites/Tiles/Tile-Default-" + x.ToString(), col); } else { ResourceLoader.GetSpriteGameObject("GuideTile", guideTiles, i, height - 1 - j, "Guide", 1, "Sprites/Tiles/Tile-Dark-" + x.ToString(), col); } ResourceLoader.GetSpriteGameObject("GuideOutline", guideOutline, i, height - 1 - j, "Guide", 0, "Sprites/Tiles/Tile-Outline"); } } } // set cursor cursor = ResourceLoader.GetSpriteGameObject("Cursor", miniGuide, playerCurrentLocation.x, playerCurrentLocation.y, "Guide", 2, "Sprites/Tiles/Cursor"); solutionGrid.SetActive(false); // set position and scale miniGuide.transform.position = new Vector2(transform.position.x + ((float)width) + 1.0f, ((float)height) / 4); miniGuide.transform.localScale = new Vector2(0.35f, 0.35f); #endregion // center the camera on the grid float aspectMultiplier = (16.0f / 9.0f) / ((float)Screen.width / Screen.height); cam.transform.position = new Vector3(((float)width) * 1.35f / 2.0f, ((float)height - 1) / 2.0f, -10.0f); cam.GetComponent <Camera>().orthographicSize = Mathf.Max(5.0f, (((float)width) * 0.5f + 0.5f) * aspectMultiplier, (((float)height) * 0.5f + 0.5f) * aspectMultiplier); // count number of correct tiles initially CountCorrectTiles(); defaultCorrectTiles = correctTiles; } catch { Debug.Log("Invalid level information."); } }