Loading game data from a text file map

Rather than, for every level of a game, having to create and place every GameObject on the screen by hand, a better approach can be to create the text files of rows, and columns of characters, where each character corresponds to the type of GameObject that is to be created in the corresponding location. In this recipe, we'll use a text file and set of prefab sprites to display a graphical version of a text-data file for a screen from the classic game called NetHack.

Loading game data from a text file map

Getting ready

In the 1362_10_08 folder, we have provided the following two files for this recipe:

  • level1.txt (a text file, representing a level)
  • absurd128.png (a 128 x 128 sprite sheet for Nethack).

The level data came from the Nethack Wikipedia page, and the sprite sheet came from SourceForge:

Note that we also included a Unity package with all the prefabs set up, since this can be a laborious task.

How to do it...

To load game data from a text file map, do the following:

  1. Import the text file called level1.txt, and the image file called absurd128.png.
  2. Select absurd128.png in the Inspector, and set Texture Type to Sprite (2D/uGUI), and Sprite Mode to Multiple.
  3. Edit this sprite in the Sprite Editor, choosing Type as Grid and Pixel Size as 128 x 128, and apply these settings.
    How to do it...
  4. In the Project panel, click on the right-facing white triangle to explode the icon, to show all the sprites in this sprite sheet individually.
    How to do it...
  5. Drag the Sprite called absurd128_175 onto the scene.
  6. Create a new Prefab named corpse_175 in the Project panel, and drag onto this blank prefab Sprite absurd128_175 from the scene. Now, delete the sprite instance from the scene. You have now created a prefab containing the Sprite 175.
  7. Repeat this process for the following sprites (that is, create prefabs for each one):
    1. floor_848
    2. corridor_849
    3. horiz_1034
    4. vert_1025
    5. door_844
    6. potion_675
    • chest_586
    • alter_583
    • stairs_up_994
    • stairs_down_993
    • wizard_287
  8. Select the Main Camera in the Inspector, and ensure that it is set to an Orthographic camera, sized 20, with Clear Flags as Solid Color and Background as Black.
  9. Attach the following C# code to the Main Camera as the script class called LoadMapFromTextfile:
    using UnityEngine;
    using System.Collections;
    
    using System.Collections.Generic;
    
    public class LoadMapFromTextfile : MonoBehaviour
    {
      public TextAsset levelDataTextFile;
    
      public GameObject floor_848;
      public GameObject corridor_849;
      public GameObject horiz_1034;
      public GameObject vert_1025;
      public GameObject corpse_175;
      public GameObject door_844;
      public GameObject potion_675;
      public GameObject chest_586;
      public GameObject alter_583;
      public GameObject stairs_up_994;
      public GameObject stairs_down_993;
      public GameObject wizard_287;	
    
      public Dictionary<char, GameObject> dictionary = new Dictionary<char, GameObject>();
    
      void Awake(){
        char newlineChar = '
    ';
    
        dictionary['.'] = floor_848;
        dictionary['#'] = corridor_849;
        dictionary['('] = chest_586;
        dictionary['!'] = potion_675;
        dictionary['_'] = alter_583;
        dictionary['>'] = stairs_down_993;
        dictionary['<'] = stairs_up_994;
        dictionary['-'] = horiz_1034;
        dictionary['|'] = vert_1025;
        dictionary['+'] = door_844;
        dictionary['%'] = corpse_175;
        dictionary['@'] = wizard_287;
    
        string[] stringArray = levelDataTextFile.text.Split(newlineChar);
        BuildMaze( stringArray );
      }
    
      private void BuildMaze(string[] stringArray){
        int numRows = stringArray.Length;
    
        float yOffset = (numRows / 2);
    
        for(int row=0; row < numRows; row++){
          string currentRowString = stringArray[row];
          float y = -1 * (row - yOffset);
          CreateRow(currentRowString, y);
        }
      }
    
      private void CreateRow(string currentRowString, float y) {
        int numChars = currentRowString.Length;
        float xOffset = (numChars/2);
    
        for(int charPos = 0; charPos < numChars; charPos++){
          float x = (charPos - xOffset);
          char prefabCharacter = currentRowString[charPos];
    
          if (dictionary.ContainsKey(prefabCharacter)){
            CreatePrefabInstance( dictionary[prefabCharacter], x, y);
          }
        }
      }
    
      private void CreatePrefabInstance(GameObject objectPrefab, float x, float y){
        float z = 0;
        Vector3 position = new Vector3(x, y, z);
        Quaternion noRotation = Quaternion.identity;
        Instantiate (objectPrefab, position, noRotation);
      }
    }
  10. With the Main Camera selected, drag the appropriate prefabs onto the prefabs slots in the Inspector, for the LoadMapFromTextfile Script component.
    How to do it...
  11. When you run the scene, you will see that a sprite-based Nethack map will appear, using your prefabs.

How it works...

The Sprite sheet was automatically sliced up into hundreds of 128 x 128 pixel Sprite squares. We created the prefab objects from some of these sprites, so that the copies can be created at runtime when needed.

The text file called level1.txt contains the lines of text characters. Each non-space character represents where a sprite prefab should be instantiated (column = X, row = Y). A C# dictionary variable named dictionary is declared and initialized in the Start() method to associate specific prefab GameObjects with some particular characters in the text file.

The Awake() method splits the string into an array using the newline character as a separator. So now, we have stringArray with an entry for each row of the text data. The BuildMase(…) method is called with the stringArray.

The BuildMaze(…) method interrogates the array to find its length (the number of rows of data for this level), and sets yOffSet to half this value. This is done to allow the placing of the prefabs half above Y = 0 and half below, so (0,0,0) is the center of the level map. A for-loop is used to read each row's string from the array. It passes it to the CreateRow(…) method along with the Y-value corresponding to the current row.

The CreateRow(…) method extracts the length of the string, and sets xOffSet to half this value. This is done to allow the placing of the prefabs half to the left of X = 0 and half to the right, so (0,0,0) is the center of the level map. A for-loop is used to read each character from the current row's string, and (if there is an entry in our dictionary for that character) then the CreatePrefabIInstance (…) method is called, passing the prefab reference in the dictionary for that character, and the x and y value.

The CreatePrefabInstance(…) method instantiates the given prefab at a position of (x, y, z) where z is always zero, and there is no rotation (Quarternion.identity).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.179.59