Ejemplo n.º 1
0
    // NOTE: CURRENTLY ONLY WORKS WITH A SINGLE TILED TILESET

    public void LoadLevel()
    {
        // *New* Clear both editor console and all children in "ground", "turret" and "wall" holder parents.
        ClearEditorConsole();
        DestroyChildren(groundHolder);
        DestroyChildren(turretHolder);
        DestroyChildren(wallHolder);

        // Thanks to the script below, rather than having to find the exact location of the TMX file by hand
        // each time it needs to be used, the script below will instead automatically go into the game's data folder
        // through "Data/Maps/" and return the directory location of the TMX file we need using only the TMX filename.
        {
            gameDirectory = Environment.CurrentDirectory;
            dataDirectory = GetJoinedUnixPath(Directory.GetParent(gameDirectory).FullName, "Data");
            mapsDirectory = GetJoinedUnixPath(dataDirectory, "Maps");
            TMXFile       = GetJoinedUnixPath(mapsDirectory, TMXFilename);
        }


        // The script below is, overall, used to parse the XML data of our TMX file for use within Unity.
        {
            //Clear any current map data
            mapData.Clear();

            //Create a string and fill it with all text contained within our TMX file.
            string content = File.ReadAllText(TMXFile);

            // XMLreader is used to turn the given string information from an XML file and translate it into
            // a format where a user can actually read and understand whats present.
            using (XmlReader reader = XmlReader.Create(new StringReader(content))) {
                // Read through the content, and translate the mapColumns and MapRows into Ints to be set underneath the
                // "width" and "height" for the map.
                reader.ReadToFollowing("map");
                mapColumns = Convert.ToInt32(reader.GetAttribute("width"));
                mapRows    = Convert.ToInt32(reader.GetAttribute("height"));

                // Perform the same operation as above, only creating an int value for tileset giving the height in pixels
                // for the attributes "tilewidth" and "tileheight"
                reader.ReadToFollowing("tileset");
                tileWidthInPixels  = Convert.ToInt32(reader.GetAttribute("tilewidth"));
                tileHeightInPixels = Convert.ToInt32(reader.GetAttribute("tileheight"));

                // Grab an int of the overall tile count of the sheet, and the number of tiles in the column.
                // Rather than doing the same for the rows, one can simply divide the overall tile count by the columns
                // and get the number of rows as the result.
                int spriteSheetTileCount = Convert.ToInt32(reader.GetAttribute("tilecount"));
                spriteSheetColumns = Convert.ToInt32(reader.GetAttribute("columns"));
                spriteSheetRows    = spriteSheetTileCount / spriteSheetColumns;

                // Read until "image" has been hit, then return the full file path of the sprite sheet file.
                reader.ReadToFollowing("image");
                spriteSheetFile = GetJoinedUnixPath(mapsDirectory, reader.GetAttribute("source"));

                // Read up to "layer". This will be used later for multiple layers.
                reader.ReadToFollowing("layer");

                // Read to "data" and "encoding" to set "mapDataFormat" to base64 or csv depending on what the xml reads as.
                reader.ReadToFollowing("data");
                string encodingType = reader.GetAttribute("encoding");

                switch (encodingType)
                {
                case "base64":
                    mapDataFormat = MapDataFormat.Base64;
                    break;

                case "csv":
                    mapDataFormat = MapDataFormat.CSV;
                    break;
                }

                // trims away any leading and trailing whitespace from our "reader" string value.
                mapDataString = reader.ReadElementContentAsString().Trim();

                // *New* Reset all turrent/wall positions and wall sizes currently in place.
                turretPositions.Clear();
                wallPositions.Clear();
                wallSizes.Clear();

                // If the reader contains an "objectgroup" setting, then, so long as there are objects to read,
                // set their x and y turrent positions based on the attribute as found in the XML file.
                if (reader.ReadToFollowing("objectgroup"))
                {
                    if (reader.ReadToDescendant("object"))
                    {
                        do
                        {
                            float x = Convert.ToSingle(reader.GetAttribute("x")) / (float)pixelsPerUnit;
                            float y = Convert.ToSingle(reader.GetAttribute("y")) / (float)pixelsPerUnit;
                            turretPositions.Add(new Vector3(x, -y, 0));
                        } while (reader.ReadToNextSibling("object"));
                    }
                }

                // *New* The same as above, taking care of the next object group "Walls", obtaining both each wall's position as well as its size.
                if (reader.ReadToFollowing("objectgroup"))
                {
                    if (reader.ReadToDescendant("object"))
                    {
                        do
                        {
                            float x = Convert.ToSingle(reader.GetAttribute("x")) / (float)pixelsPerUnit;
                            float y = Convert.ToSingle(reader.GetAttribute("y")) / (float)pixelsPerUnit;
                            wallPositions.Add(new Vector3(x, -y, 0));
                            float x2 = Convert.ToSingle(reader.GetAttribute("width")) / (float)pixelsPerUnit;
                            float y2 = Convert.ToSingle(reader.GetAttribute("height")) / (float)pixelsPerUnit;
                            wallSizes.Add(new Vector2(x2, y2));
                        } while (reader.ReadToNextSibling("object"));
                    }
                }
            }

            // Parse the xml data differently based on what format the file has been made in
            switch (mapDataFormat)
            {
            // in Base64, the information is represented in 64 bits, and as such must be converted from that format into
            // a readable string.
            case MapDataFormat.Base64:

                byte[] bytes = Convert.FromBase64String(mapDataString);
                int    index = 0;
                while (index < bytes.Length)
                {
                    int tileID = BitConverter.ToInt32(bytes, index) - 1;
                    mapData.Add(tileID);
                    index += 4;
                }
                break;


            case MapDataFormat.CSV:
                // in CSV, or "Comma Separated Values", every piece of information is split using quotations and commas.
                // The below methods account for this and put the information into a readoable format from this.
                string[] lines = mapDataString.Split(new string[] { " " }, StringSplitOptions.None);
                foreach (string line in lines)
                {
                    string[] values = line.Split(new string[] { "," }, StringSplitOptions.None);
                    foreach (string value in values)
                    {
                        int tileID = Convert.ToInt32(value) - 1;
                        mapData.Add(tileID);
                    }
                }
                break;
            }
        }


        {
            // Simple math is used to obtain tile width and height from the overall pixels per unit and the width/height in pixels.
            tileWidth  = (tileWidthInPixels / (float)pixelsPerUnit);
            tileHeight = (tileHeightInPixels / (float)pixelsPerUnit);

            //take half ot the tile width and height to find the center of each, similarily to find center offset.
            tileCenterOffset = new Vector3(.5f * tileWidth, -.5f * tileHeight, 0);
            mapCenterOffset  = new Vector3(-(mapColumns * tileWidth) * .5f, (mapRows * tileHeight) * .5f, 0);
        }



        // Create a new 2D texture, size 2 by 2, loading the image in "spriteSheetFile" and settign the texture's
        // filter mode to point and wrap mode to clamp. Point keeps the pixels looking crisp (though blocky up close), and
        // Clamp can help reduce artifacts foun on the edges of the texture.
        {
            spriteSheetTexture = new Texture2D(2, 2);
            spriteSheetTexture.LoadImage(File.ReadAllBytes(spriteSheetFile));
            spriteSheetTexture.filterMode = FilterMode.Point;
            spriteSheetTexture.wrapMode   = TextureWrapMode.Clamp;
        }


        // Clear current sprite list, then, using the sprite sheet, create a new sprite for each and every tile within the sheet.
        // The definition of each tile is based on createed rectangles using current location on the sprite sheet, the height/width
        // of each pixel, and a pivot in the middle of each sprite. This repeats until each part of hte sprite sheet has been accounted for.
        {
            mapSprites.Clear();

            for (int y = spriteSheetRows - 1; y >= 0; y--)
            {
                for (int x = 0; x < spriteSheetColumns; x++)
                {
                    Sprite newSprite = Sprite.Create(spriteSheetTexture, new Rect(x * tileWidthInPixels, y * tileHeightInPixels, tileWidthInPixels, tileHeightInPixels), new Vector2(0.5f, 0.5f), pixelsPerUnit);
                    mapSprites.Add(newSprite);
                }
            }
        }

        // Clear current tile list. Then perform the following; take the current x and y int value as the location of the sprite to be loaded,
        // and make an int "tileID" based on the tile ID from our map data. Then, instantiate a new tile at the given location, taking into
        // account the offset of the map. Change the sprite of the instantiated object to one that matches the tile data from our XML file.
        // Finally, make the instantiate sprite a child of he "groundHolder" script, and add that game object to the "tiles" list.
        {
            tiles.Clear();

            for (int y = 0; y < mapRows; y++)
            {
                for (int x = 0; x < mapColumns; x++)
                {
                    int mapDatatIndex = x + (y * mapColumns);
                    int tileID        = mapData[mapDatatIndex];

                    GameObject tile = Instantiate(tilePrefab, new Vector3(x * tileWidth, -y * tileHeight, 0) + mapCenterOffset + tileCenterOffset, Quaternion.identity) as GameObject;
                    tile.transform.GetChild(0).GetComponent <SpriteRenderer>().sprite = mapSprites[tileID];
                    tile.transform.parent = groundHolder;
                    tiles.Add(tile);
                }
            }
        }


        // For every given turret position in our turret positions list, instantiage a turret prefab at that location, name
        // the game object "turret" and make it a child of the "turretHolder" game object.
        {
            foreach (Vector3 turretPosition in turretPositions)
            {
                GameObject turret = Instantiate(turretPrefab, turretPosition + mapCenterOffset, Quaternion.identity) as GameObject;
                turret.name             = "Turret";
                turret.transform.parent = turretHolder;
            }
        }

        // *New* For each given wall position in our wallPositions list, instantiate a wall at that location, name
        // the game object "wall" and adjust the size of its collider to match the size set in Tiled, making it a child of the
        // "wallHolder" game object
        for (int i = 0; i < wallPositions.Count; i++)
        {
            GameObject wall = Instantiate(wallPrefab, wallPositions[i] + mapCenterOffset, Quaternion.identity) as GameObject;
            wall.transform.position = new Vector3(wall.transform.position.x + (wallSizes[i].x / 2), wall.transform.position.y - (wallSizes[i].y / 2), 0);
            BoxCollider2D boxCol = wall.GetComponent <BoxCollider2D>() as BoxCollider2D;
            boxCol.size           = new Vector2(wallSizes[i].x, wallSizes[i].y);
            wall.name             = "Wall";
            wall.transform.parent = wallHolder;
        }

        // Obtain the current time, then print it into the console to determine at what time the level was loaded.
        DateTime localDate = DateTime.Now;

        print("Level loaded at: " + localDate.Hour + ":" + localDate.Minute + ":" + localDate.Second);
    }
    // NOTE: CURRENTLY ONLY WORKS WITH A SINGLE TILED TILESET

    public void LoadLevel()
    {
        ClearEditorConsole();
        DestroyChildren(groundHolder);
        DestroyChildren(turretHolder);

        //
        {
            gameDirectory = Environment.CurrentDirectory;
            dataDirectory = GetJoinedUnixPath(Directory.GetParent(gameDirectory).FullName, "Data");
            mapsDirectory = GetJoinedUnixPath(dataDirectory, "Maps");
            TMXFile       = GetJoinedUnixPath(mapsDirectory, TMXFilename);
        }


        //
        {
            mapData.Clear();

            string content = File.ReadAllText(TMXFile);

            using (XmlReader reader = XmlReader.Create(new StringReader(content))) {
                reader.ReadToFollowing("map");
                mapColumns = Convert.ToInt32(reader.GetAttribute("width"));
                mapRows    = Convert.ToInt32(reader.GetAttribute("height"));

                reader.ReadToFollowing("tileset");
                tileWidthInPixels  = Convert.ToInt32(reader.GetAttribute("tilewidth"));
                tileHeightInPixels = Convert.ToInt32(reader.GetAttribute("tileheight"));

                int spriteSheetTileCount = Convert.ToInt32(reader.GetAttribute("tilecount"));
                spriteSheetColumns = Convert.ToInt32(reader.GetAttribute("columns"));
                spriteSheetRows    = spriteSheetTileCount / spriteSheetColumns;


                reader.ReadToFollowing("image");
                spriteSheetFile = GetJoinedUnixPath(mapsDirectory, reader.GetAttribute("source"));


                reader.ReadToFollowing("layer");


                reader.ReadToFollowing("data");
                string encodingType = reader.GetAttribute("encoding");

                switch (encodingType)
                {
                case "base64":
                    mapDataFormat = MapDataFormat.Base64;
                    break;

                case "csv":
                    mapDataFormat = MapDataFormat.CSV;
                    break;
                }

                mapDataString = reader.ReadElementContentAsString().Trim();


                turretPositions.Clear();

                if (reader.ReadToFollowing("objectgroup"))
                {
                    if (reader.ReadToDescendant("object"))
                    {
                        do
                        {
                            float x = Convert.ToSingle(reader.GetAttribute("x")) / (float)pixelsPerUnit;
                            float y = Convert.ToSingle(reader.GetAttribute("y")) / (float)pixelsPerUnit;
                            turretPositions.Add(new Vector3(x, -y, 0));
                        } while (reader.ReadToNextSibling("object"));
                    }
                }
            }


            switch (mapDataFormat)
            {
            case MapDataFormat.Base64:

                byte[] bytes = Convert.FromBase64String(mapDataString);
                int    index = 0;
                while (index < bytes.Length)
                {
                    int tileID = BitConverter.ToInt32(bytes, index) - 1;
                    mapData.Add(tileID);
                    index += 4;
                }
                break;


            case MapDataFormat.CSV:

                string[] lines = mapDataString.Split(new string[] { " " }, StringSplitOptions.None);
                foreach (string line in lines)
                {
                    string[] values = line.Split(new string[] { "," }, StringSplitOptions.None);
                    foreach (string value in values)
                    {
                        int tileID = Convert.ToInt32(value) - 1;
                        mapData.Add(tileID);
                    }
                }
                break;
            }
        }


        {
            tileWidth  = (tileWidthInPixels / (float)pixelsPerUnit);
            tileHeight = (tileHeightInPixels / (float)pixelsPerUnit);

            tileCenterOffset = new Vector3(.5f * tileWidth, -.5f * tileHeight, 0);
            mapCenterOffset  = new Vector3(-(mapColumns * tileWidth) * .5f, (mapRows * tileHeight) * .5f, 0);
        }



        //
        {
            spriteSheetTexture = new Texture2D(2, 2);
            spriteSheetTexture.LoadImage(File.ReadAllBytes(spriteSheetFile));
            spriteSheetTexture.filterMode = FilterMode.Point;
            spriteSheetTexture.wrapMode   = TextureWrapMode.Clamp;
        }


        //
        {
            mapSprites.Clear();

            for (int y = spriteSheetRows - 1; y >= 0; y--)
            {
                for (int x = 0; x < spriteSheetColumns; x++)
                {
                    Sprite newSprite = Sprite.Create(spriteSheetTexture, new Rect(x * tileWidthInPixels, y * tileHeightInPixels, tileWidthInPixels, tileHeightInPixels), new Vector2(0.5f, 0.5f), pixelsPerUnit);
                    mapSprites.Add(newSprite);
                }
            }
        }

        //
        {
            tiles.Clear();

            for (int y = 0; y < mapRows; y++)
            {
                for (int x = 0; x < mapColumns; x++)
                {
                    int mapDatatIndex = x + (y * mapColumns);
                    int tileID        = mapData[mapDatatIndex];

                    GameObject tile = Instantiate(tilePrefab, new Vector3(x * tileWidth, -y * tileHeight, 0) + mapCenterOffset + tileCenterOffset, Quaternion.identity) as GameObject;
                    tile.transform.GetChild(0).GetComponent <SpriteRenderer>().sprite = mapSprites[tileID];
                    tile.transform.parent = groundHolder;
                    tiles.Add(tile);
                }
            }
        }


        //
        {
            foreach (Vector3 turretPosition in turretPositions)
            {
                GameObject turret = Instantiate(turretPrefab, turretPosition + mapCenterOffset, Quaternion.identity) as GameObject;
                turret.name             = "Turret";
                turret.transform.parent = turretHolder;
            }
        }


        DateTime localDate = DateTime.Now;

        print("Level loaded at: " + localDate.Hour + ":" + localDate.Minute + ":" + localDate.Second);
    }