unity游戏开发(三):游戏地图的制作及地图信息的存储(LitJson)

游戏地图的制作:

ps:资源的获取自己定义

 

格子图片:

在游戏物体格子上挂载脚本:GridPoint,创建一个空物体,挂载MapMaker脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MapMaker : MonoBehaviour
{
    //是否画线
    public bool drawLine;
    
    //格子预制体
    public GameObject gridGO;

    //当前关卡索引
    public int bigLevelID;
    public int levelID;

    //地图
    public float mapWidth;
    public float mapHeight;

    //格子
    public float gridWidth;
    public float gridHeight;

    //全部的格子对象
    public GridPoint[,] gridPoints;

    //行列
    public int xColumn = 12;
    public int yRow = 8;

    private SpriteRenderer bgSR;
    private SpriteRenderer roadSR;

    /// 
    /// 怪物路径点
    /// 
    public List monsterPath;
    
    /// 
    /// 怪物路径点的具体位置
    /// 
    public List monsterPathPos;

    public static MapMaker _instance;
    public static MapMaker Instance
    {
        get { return _instance; }
    }


    private void Awake()
    {
        _instance = this;
        InitMapMaker();
    }

    //初始化地图
    public void InitMapMaker()
    {
        CalculateSize();
        gridPoints = new GridPoint[xColumn, yRow];
        monsterPath = new List();
        for (int x = 0; x < xColumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
                GameObject itemGo = Instantiate(gridGO,transform.position,transform.rotation);
                itemGo.transform.position = CorretPostion(x*gridWidth,y*gridHeight);
                itemGo.transform.SetParent(transform);
                gridPoints[x, y] = itemGo.GetComponent();
                gridPoints[x, y].gridIndex.xIndex = x;
                gridPoints[x, y].gridIndex.yIndex = y;
            }
        }
        bgSR = transform.Find("BG").GetComponent();
        roadSR = transform.Find("Road").GetComponent();
    }

    //纠正位置
    public Vector3 CorretPostion(float x, float y)
    {
        return new Vector3(x - mapWidth / 2 + gridWidth / 2, y - mapHeight / 2 + gridHeight / 2);
    }

    //计算地图格子宽高
    private void CalculateSize()
    {
        Vector3 leftDown = new Vector3(0, 0);
        Vector3 rightUp = new Vector3(1,1);

        Vector3 posOne = Camera.main.ViewportToWorldPoint(leftDown);
        Vector3 posTwo = Camera.main.ViewportToWorldPoint(rightUp);

        mapWidth = posTwo.x - posOne.x;
        mapHeight = posTwo.y - posOne.y;

        gridWidth = mapWidth / xColumn;
        gridHeight = mapHeight / yRow;
    }

    //画格子用于辅助设计
    private void OnDrawGizmos()
    {
        if (drawLine)
        {
            CalculateSize();
            Gizmos.color = Color.red;
            //画行
            for (int y = 0; y <= yRow; y++)
            {
                Vector3 endPos = new Vector3(mapWidth / 2, -mapHeight / 2 + y * gridHeight);
                Vector3 startPos = new Vector3(-mapWidth/2,-mapHeight/2+y*gridHeight);
                Gizmos.DrawLine(startPos,endPos);
            }
            //画列
            for (int x = 0; x < xColumn; x++)
            {
                Vector3 startPos = new Vector3(-mapWidth / 2 + gridWidth * x, mapHeight / 2);
                Vector3 endPos = new Vector3(-mapWidth / 2 + x * gridWidth, -mapHeight / 2);
                Gizmos.DrawLine(startPos, endPos);
            }
        }
    }


}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GridPoint : MonoBehaviour {

    //属性
    private SpriteRenderer spriteRenderer;
    public GridState gridState;
    public GridIndex gridIndex;

    //资源
    private Sprite gridSprite;//格子图片资源
    private Sprite monsterPathSprite;//怪物路点图片资源
    public GameObject[] itemPrefabs;//道具数组
    public GameObject currentItem;//当前格子持有道具

    //格子状态
    public struct GridState
    {
        public bool canBuild;
        public bool hasItem;
        public bool isMonsterPoint;
        public int itemID;
    }

    //格子索引
    public struct GridIndex
    {
        public int xIndex;
        public int yIndex;
    }

    private void Awake()
    {
        spriteRenderer = GetComponent();
        gridSprite = Resources.Load("Pictures/NormalMordel/Game/Grid");
        monsterPathSprite = Resources.Load("Pictures/NormalMordel/Game/1/Monster/6-1");
        itemPrefabs = new GameObject[10];
        string prefabsPath = "Prefabs/Game/" + MapMaker.Instance.bigLevelID.ToString() + "/Item/";
        for (int i = 0; i < itemPrefabs.Length; i++)
        {
            itemPrefabs[i] = Resources.Load(prefabsPath + i);
            if (!itemPrefabs[i])
            {
                Debug.Log("加载失败,失败路径:" + prefabsPath + i);
            }
        }
        InitGrid();
    }

    public void InitGrid()
    {
        gridState.canBuild = true;
        gridState.hasItem = false;
        gridState.isMonsterPoint = false;
        gridState.itemID = -1;
        spriteRenderer.sprite = gridSprite;
        Destroy(currentItem);
    }

    private void OnMouseDown()
    {
        //怪物路点
        if (Input.GetKey(KeyCode.P))
        {
            gridState.canBuild = false;
            spriteRenderer.enabled = true;
            gridState.isMonsterPoint = !gridState.isMonsterPoint;
            if (gridState.isMonsterPoint)
            {
                MapMaker.Instance.monsterPath.Add(gridIndex);
                spriteRenderer.sprite = monsterPathSprite;
            }
            else
            {
                MapMaker.Instance.monsterPath.Remove(gridIndex);
                spriteRenderer.sprite = gridSprite;
                gridState.canBuild = true;
            }
        }
        //道具
        else if (Input.GetKey(KeyCode.I))
        {
            gridState.itemID++;
            //当前格子从持有道具状态转化为没有道具
            if (gridState.itemID == itemPrefabs.Length)
            {
                gridState.hasItem = false;
                gridState.itemID = -1;
                Destroy(currentItem);
                return;
            }
            //本身没有道具
            if (currentItem == null)
            {
                CreateItem();
            }
            //本身就有道具
            else
            {
                Destroy(currentItem);
                CreateItem();
            }
            gridState.hasItem = true;
        }

        else if (!gridState.isMonsterPoint)
        {
            gridState.isMonsterPoint = false;
            gridState.canBuild = !gridState.canBuild;
            if (gridState.canBuild)
            {
                spriteRenderer.enabled = true;
            }
            else
            {
                spriteRenderer.enabled = false;
            }
        }
    }

    //生成道具
    public void CreateItem()
    {
        Vector3 createPos = transform.position;
        //游戏道具大小不同,只占一个格子就不用判断语句了!
        if (gridState.itemID <= 2)
        {
            createPos += new Vector3(MapMaker.Instance.gridWidth, -MapMaker.Instance.gridHeight) / 2;
        }
        else if (gridState.itemID <= 4)
        {
            createPos += new Vector3(MapMaker.Instance.gridWidth, 0) / 2;
        }
        GameObject itemGo = Instantiate(itemPrefabs[gridState.itemID], createPos, Quaternion.identity);
        currentItem = itemGo;
    }

}

运行后界面:(可按不同的键对地图进行编辑)

unity游戏开发(三):游戏地图的制作及地图信息的存储(LitJson)_第1张图片

 

地图信息的存储:

在GridPoint中加入更新格子状态信息的方法

    //更新格子状态
    public void UpdateGridState()
    {
        if (gridState.canBuild)
        {
            spriteRenderer.sprite = gridSprite;
            spriteRenderer.enabled = true;
            if (gridState.hasItem)
            {
                CreateItem();
            }
        }
        else
        {
            if (gridState.isMonsterPoint)
            {
                spriteRenderer.sprite = monsterPathSprite;
            }
            else
            {
                spriteRenderer.enabled = false;
            }
        }
    }

在MapMaker中声明有关地图信息的存储的方法:

    /// 
    /// 清除怪物路点
    /// 
    public void ClearMonsterPath()
    {
        monsterPath.Clear();
    }

    /// 
    /// 恢复地图编辑默认状态
    /// 
    public void RecoverMapDefaultState()
    {
        ClearMonsterPath();
        for (int x = 0; x < xColumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
                gridPoints[x, y].InitGrid();
            }
        }
    }

    /// 
    ///  初始化地图
    /// 
    public void InitMap()
    {
        bigLevelID = 0;
        levelID = 0;
        RecoverMapDefaultState();
        roundInfoList.Clear();
        bgSR = null;
        roadSR = null;
    }

    //生成LevelInfo对象用来保存文件
    public LevelInfo CreateLevelInfoGo()
    {
        LevelInfo levelInfo = new LevelInfo()
        {
            bigLevelID = this.bigLevelID,
            levelID = this.levelID
        };
        levelInfo.gridStateList = new List();
        for (int x = 0; x < xColumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
                levelInfo.gridStateList.Add(gridPoints[x, y].gridState);
            }
        }
        levelInfo.monsterPathList = new List();
        for (int i = 0; i < monsterPath.Count; i++)
        {
            levelInfo.monsterPathList.Add(monsterPath[i]);
        }
        levelInfo.roundInfoList = new List();
        for (int i = 0; i < roundInfoList.Count; i++)
        {
            levelInfo.roundInfoList.Add(roundInfoList[i]);
        }
        return levelInfo;
    }

    //保存当前关卡的数据文件
    public void SaveLevelFileByJson()
    {
        LevelInfo levelInfo = CreateLevelInfoGo();
        string filePath = Application.streamingAssetsPath + "/Json/Level/" + "Level" + bigLevelID.ToString() + "_" + levelID.ToString() + ".json";
        string saveJsonStr = JsonMapper.ToJson(levelInfo);
        StreamWriter sw = new StreamWriter(filePath);
        sw.Write(saveJsonStr);
        sw.Close();
    }

    public LevelInfo LoadLevelInfoFile(string fileName)
    {
        LevelInfo levelInfo = new LevelInfo();
        string filePath = Application.streamingAssetsPath + "/Json/Level/" + fileName;
        if (File.Exists(filePath))
        {
            StreamReader sr = new StreamReader(filePath);
            string jsonStr = sr.ReadToEnd();
            sr.Close();
            levelInfo = JsonMapper.ToObject(jsonStr);
            return levelInfo;
        }
        Debug.Log("文件加载失败,加载路径是" + filePath);
        return null;
    }

    public void LoadLevelFile(LevelInfo levelInfo)
    {
        bigLevelID = levelInfo.bigLevelID;
        levelID = levelInfo.levelID;
        for (int x = 0; x < xColumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
                gridPoints[x, y].gridState = levelInfo.gridStateList[y + x * yRow];
                //更新格子的状态
                gridPoints[x, y].UpdateGridState();
            }
        }
        monsterPath.Clear();
        for (int i = 0; i < levelInfo.monsterPathList.Count; i++)
        {
            monsterPath.Add(levelInfo.monsterPathList[i]);
        }
        roundInfoList = new List();
        for (int i = 0; i < levelInfo.roundInfoList.Count; i++)
        {
            roundInfoList.Add(levelInfo.roundInfoList[i]);
        }
       
    }

制作地图信息的工具类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;

//定义自定义编辑器类可以编辑的对象类型。
[CustomEditor(typeof(MapMaker))]
public class MapMakerTool : Editor
{
    private MapMaker mapMaker;
    //关卡文件列表
    private List fileList = new List();
    //文件名数组
    private string[] fileNameList;

    //当前编辑的关卡索引
    private int selectIndex = -1;

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        if (Application.isPlaying)
        {
            mapMaker = MapMaker.Instance;

            EditorGUILayout.BeginHorizontal();
            //获取操作的文件名
            fileNameList = GetNames(fileList);
            int currentIndex = EditorGUILayout.Popup(selectIndex, fileNameList);
            //获取操作的文件名
            if (currentIndex != selectIndex)
            {
                selectIndex = currentIndex;
                //实例化地图
                mapMaker.InitMap();
                //加载当前选择的level文件
                mapMaker.LoadLevelFile(mapMaker.LoadLevelInfoFile(fileNameList[selectIndex]));
            }
            if (GUILayout.Button("读取关卡列表"))
            {
                LoadLevelFiles();
            }

            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();

            if (GUILayout.Button("回复地图编辑器默认状态"))
            {
                mapMaker.RecoverMapDefaultState();
            }

            if (GUILayout.Button("清除怪物路点"))
            {
                mapMaker.ClearMonsterPath();
            }

            EditorGUILayout.EndHorizontal();

            if (GUILayout.Button("保存当前关卡数据文件"))
            {
                mapMaker.SaveLevelFileByJson();
            }

        }
    }

    //加载关卡数据
    private void LoadLevelFiles()
    {
        ClearList();
        fileList = GetLevelFiles();
    }

    //清除文件列表
    private void ClearList()
    {
        fileList.Clear();
        selectIndex = -1;
    }

    //具体读取关卡列表
    private List GetLevelFiles()
    {
        string[] files = Directory.GetFiles(Application.streamingAssetsPath + "/Json/Level/", "*.json");
        List list = new List();
        for (int i = 0; i < files.Length; i++)
        {
            FileInfo file = new FileInfo(files[i]);
            list.Add(file);
        }
        return list;
    }


    //获取关卡文件的文字
    public string[] GetNames(List files)
    {
        List names = new List();
        foreach (FileInfo file in files)
        {
            //存储关卡名字
            names.Add(file.Name);
        }
        return names.ToArray();
    }

}

运行后效果:unity游戏开发(三):游戏地图的制作及地图信息的存储(LitJson)_第2张图片

可对地图进行编辑:

点击保存当前关卡数据文件 按钮

再按恢复地图编辑器默认状态 按钮 则 清空界面为初始状态

最后按读取关卡列表,弹框中会出现你所有的关卡名称信息,选择关卡即可加载关卡。

unity游戏开发(三):游戏地图的制作及地图信息的存储(LitJson)_第3张图片

此时,JSON文件也会存储在你的文件夹中   (可在BeJson网站中校验JSON文件是否正确)

unity游戏开发(三):游戏地图的制作及地图信息的存储(LitJson)_第4张图片

地图编辑完成

 

 

 

 

 

 

你可能感兴趣的:(游戏开发)