首页 > 代码库 > 【跟我一起学Unity3D】做一个2D的90坦克大战之地图编辑器

【跟我一起学Unity3D】做一个2D的90坦克大战之地图编辑器

从10月20号到现在,Unity3D也学了10天了,对于Unity3D也有了一个大致的了解,有必要做一个小游戏来检测一下自己的学习成果了。经过两天的努力,终于总算是做出来了一个可以玩的坦克大战了。首先讲讲我的设计目标:

1.地图编辑器
2.道具系统
3.简单AI系统
4.计分器

其中,最重要的就是地图编辑器了,其次到AI系统,其他几个都挺简单的。

------------------------------------------------------------------------------------------------------------------------------------------

地图编辑器

我的想法是在编辑器中编辑好地图后,直接打开游戏就可以玩。这样的话,就需要一个文件来存储这些地图元素。鉴于xml在C#上支持非常好,简单易用,就选它了。

然后我们规定一下地图的格式,首先地图是由一个一个item组成的,原版的item有普通的墙,坚固的墙,水和草丛(德玛西亚)。为了方便读取,就用一个名字来规定他们,其次,由于我们是2D的场景,所以存入的坐标是x与y。最后得到的数据存储格式如下:

 <item>
      <name>gras</name>
      <position_x>-1.2</position_x>
      <position_y>-3</position_y>
    </item>

整个文件大概是下面这样的结构:

<data>
  <items>
    <item>
      <name>gras</name>
      <position_x>-1.2</position_x>
      <position_y>-3</position_y>
    </item>
  </items>
</data>

对应的文件存入的函数为:

    bool SaveInXml()
    {
        if (File.Exists(m_sXmlPath))
        {
            File.Delete(m_sXmlPath);
        }
        XmlDocument xmlDoc = new XmlDocument();
        XmlElement data = http://www.mamicode.com/xmlDoc.CreateElement("data");>
然后就是对应的读取函数了(读取完直接实例化显示的):

    void ReadMap(XmlNode xml_items)
    {
        XmlNodeList items = xml_items.SelectNodes("item");
        foreach (XmlNode current_node in items)
        {
            XmlNode current_name = current_node.SelectSingleNode("name");
            XmlNode position_x = current_node.SelectSingleNode("position_x");
            XmlNode position_y = current_node.SelectSingleNode("position_y");

            Vector3 psition = new Vector3(float.Parse(position_x.InnerText), float.Parse(position_y.InnerText), -1);

            if (current_name.InnerText == "wall")
            {
                m_readItem = Instantiate(m_ItemWall, psition, Quaternion.identity) as GameObject;
            }

            else if (current_name.InnerText == "gras")
            {
                m_readItem = Instantiate(m_ItemGras, psition, Quaternion.identity) as GameObject;
            }

            else if (current_name.InnerText == "steel")
            {
                m_readItem = Instantiate(m_ItemSteel, psition, Quaternion.identity) as GameObject;
            }

            else if (current_name.InnerText == "water")
            {
                m_readItem = Instantiate(m_ItemWater, psition, Quaternion.identity) as GameObject;
            }

            else continue;

            m_readItem.name = current_name.InnerText;

            Debug.Log("要读取的数据:" + m_readItem.name + "位置:" + m_readItem.transform.position.x + "," + m_readItem.transform.position.y);

            m_Items.Add(m_readItem);
        }
    }

这样,就完成了一个基本的地图编辑器的核心部分了,剩下的就是拖拽控件了。

关于拖拽控件,设计的想法是,地图的item在右边,然后点击item会复制一个点击到的item,然后可以拖拽这个复制出来的item到地图上,下面是实现代码:

    void Update()
    {
        //检测鼠标左键的拾取  
        if (Input.GetMouseButtonDown(0))
        {
            //鼠标的屏幕坐标空间位置转射线  
            m_ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            m_rayhit = Physics2D.GetRayIntersection(m_ray);
            //射线检测,相关检测信息保存到RaycastHit 结构中  
            if (m_rayhit)
            {
                //打印射线碰撞到的对象的名称  
                Debug.Log(m_rayhit.collider.gameObject.name);
                if (m_rayhit.collider.gameObject.name == "walls" ||
                    m_rayhit.collider.gameObject.name == "grass" ||
                    m_rayhit.collider.gameObject.name == "steels" ||
                    m_rayhit.collider.gameObject.name == "waters")
                {
                    m_clickItem = Instantiate(m_rayhit.collider.gameObject, m_rayhit.collider.transform.position, Quaternion.identity) as GameObject;
                    m_clickItem.name = m_rayhit.collider.gameObject.name.Substring(0, m_rayhit.collider.gameObject.name.Length - 1);
                    //m_clickItem.tag = m_clickItem.name; //ERROR: not define tag in editor
					m_Items.Add(m_clickItem);
                }
                else if (m_rayhit.collider.gameObject.name == "wall" ||
                    m_rayhit.collider.gameObject.name == "gras" ||
                    m_rayhit.collider.gameObject.name == "steel" ||
                    m_rayhit.collider.gameObject.name == "water")
                {
                    m_clickItem = m_rayhit.collider.gameObject;
                }
                else
                {
                    m_clickItem = null;
                }
            }
            else
            {
                m_clickItem = null;
            }
        }
        if (Input.GetMouseButton(0))
        {
            if (m_clickItem != null)
            {
                m_clickItem.transform.position = SetPointInMap(new Vector3(camera.ScreenToWorldPoint(Input.mousePosition).x, camera.ScreenToWorldPoint(Input.mousePosition).y, -1));
            }
        }
        if (Input.GetMouseButtonUp(0))
        {
            if (m_clickItem != null)
            {
                Vector3 cur_point = SetPointInMap(new Vector3(camera.ScreenToWorldPoint(Input.mousePosition).x, camera.ScreenToWorldPoint(Input.mousePosition).y, -1));
                if (m_Map.collider2D.OverlapPoint(cur_point))
                {
                    m_clickItem.transform.position = cur_point;
                }
                else	//在地图外就销毁掉
                {
                    Destroy(m_clickItem);
                }
            }
        }
    }



这样,就完成了一个简单的地图编辑器的基本功能了。

【跟我一起学Unity3D】做一个2D的90坦克大战之地图编辑器