【跟我一起学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 = xmlDoc.CreateElement("data");
        xmlDoc.AppendChild(data);
        //地图数据
        XmlElement xml_items = xmlDoc.CreateElement("items");
        data.AppendChild(xml_items);
        foreach (GameObject item in m_Items)
        {
            Debug.Log("要保存的数据:" + item.name + "位置:" + item.transform.position.x + "," + item.transform.position.y);

            //save in xml file
            XmlElement xml_item = xmlDoc.CreateElement("item");
            xml_items.AppendChild(xml_item);
            XmlElement name = xmlDoc.CreateElement("name");
            name.InnerText = item.name;
            xml_item.AppendChild(name);

            XmlElement position_x = xmlDoc.CreateElement("position_x");
            position_x.InnerText = item.transform.position.x.ToString();
            xml_item.AppendChild(position_x);

            XmlElement position_y = xmlDoc.CreateElement("position_y");
            position_y.InnerText = item.transform.position.y.ToString();
            xml_item.AppendChild(position_y);
        }
        xmlDoc.Save(m_sXmlPath);
        Debug.Log("创建XML完毕");
        m_Items.Clear();
        return true;
    }

然后就是对应的读取函数了(读取完直接实例化显示的):

    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);
                }
            }
        }
    }

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

时间: 10-29

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

【跟我一起学Unity3D】做一个2D的90坦克大战之导演以及道具系统

做游戏我还是习惯用一个导演类来控制游戏的进程,比如游戏的开始和结束,游戏的AI的产生,游戏的地图的绘制等等都放置在这么一个导演类里面. 然后这个导演类我把它放在MainCamera里面,作为它的组件. 首先在Start里面,需要初始化一些游戏的数据,例如读取地图,初始化AI等 void Start() { //初始化数据 m_iAICurTankCount = 0; m_iAITankCount = 1; m_iKillAICount = 0; m_iDirection = 0; m_iMyLi

【跟我一起学Unity3D】做一个2D的90坦克大战之AI系统

对于AI,我的初始想法很简单,首先他要能动,并且是在地图里面动, 懂得撞墙后转弯,然后懂得射击,其他的没有了,基于这个想法,我首先创建了一个MyTank类,用于管理玩家的坦克的活动,然后创建AITank类,AITank类继承MyTank类,这样的话,在AITank类上,只需要增加AI就可以了,具体的状态机实现,就放到MyTank类上即可. 首先来分析一下MyTank这个类,就从有限状态机开始吧. 一辆坦克的状态有下面几个: protected enum State { Idle, LeftWal

Unity3D开发一个2D横版射击游戏

教程基于http://pixelnest.io/tutorials/2d-game-unity/ , 这个例子感觉还是比较经典的, 网上转载的也比较多. 刚好最近也在学习U3D, 做的过程中自己又修改了一些地方, 写篇文和大家一起分享下, 同时也加深记忆. 有什么纰漏的地方还请大家多包涵. 1.创建第一个场景 新建工程,在Project面板创建文件夹, 是为了更好的规划管理资源文件. 接着在Hierarchy面板上创建多个空对象(这样的结构也是清晰了整个游戏的层次, 对象之间的关系一目了然),

Unity3D 创建一个简单的2D游戏

开始研究Unity3d 中的2D游戏. 首先创建出一个项目: 然后创建出一个场景: 然后添加一个背景: 然后创建一个主人公对象: 可以是自己做的素材,也可以是用unity裁剪的素材, 下面贴出裁剪素材的步奏 然会对图像进行裁剪,裁剪后进行保存: 有这样符号的就是裁剪后的素材: 然后将素材添加到游戏场景中(也就是拖到视图就可以了,如果是后期做碰撞的话,还要把此精灵变成刚体,然后加入碰撞检测,默认的时候还需要去除重力,并且和背景不在同一层): 这里变成刚体后会获得重力,要把重力去掉: 接下来就是写脚

马云:做一个静静的观察者 能学到更多

文/马云 前几天我在扎堆里关于如何看待“情绪排泄物”的文章,引来不少猜测和怀疑,还有很多自己往里面“找位置”的人.其实哪里来的那么复杂感受啊,我只是分享一下我对待负面,编造,中伤和各类有益无益的批评的态度和感受而已. 很多人总喜欢猜疑,捉摸,推测别人的一切行动和言论.似乎所有人的事情都有大阴谋在背后.抓住一切发表自己臆想的“独特”观点来显示自己的“砖家”地位. 其实也很正常,不自信和自作聪明的人总是花时间在揣摩别人或领导人身上.就像看魔术表演,很多人不断在怀疑和试图解释表演者,看电影看书,很多人

使用Multiplayer Networking做一个简单的多人游戏例子-2/3(Unity3D开发之二十六)

猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/51007512 使用Multiplayer Networking做一个简单的多人游戏例子-1/3 使用Multiplayer Networking做一个简单的多人游戏例子-2/3 使用Multiplayer Networking做一个简单的多人游戏例子-3/3 7. 在网络中控制Player移动 上一篇中,玩家操

新手学Unity3d的一些网站及相应学习路线

一.unity3d有什么优势 如果您对开发游戏感兴趣,而又没有决定选择哪一个游戏引擎,别犹豫了 unity3d是一个很好的选择! 就我来看unity3d优势主要有以下几方面:首先部署简单,自带了一个IDE monoDevelop:其次,unity3d是一个跨平台游戏引擎,无论是Android,ios还是pc发布都很方便:c#作为脚本支持,当然还有js和boo语言,其中js应该说是JavaScript for Unity与正常的JavaScript差别挺大,推荐最好还是选择c#语言,c#在编程效率

[Unity3D]做个小Demo学习Input.touches

[Unity3D]做个小Demo学习Input.touches 学不如做,下面用一个简单的Demo展示的Input.touches各项字段,有图有真相. 本项目已发布到Github,地址在(https://github.com/bitzhuwei/AndroidTouchDemo). 制作Demo 很简单,只需拉一个Text,然后添加一个脚本. 脚本如下. 1 using UnityEngine; 2 using System.Collections; 3 4 public class Disp

做一个不乖的孩子

收到一封来信,来信者是大学排行榜上位列全国前10的高校学生.她的处境,让我同情,在帮她度过这个难关方面,我也愿意更进一步做些什么.她的事例,该讲给为人父母的去听,让孩子自己做决定,底线是该放手时就放手,高一些的境界是在放手之前,让他/她具备应对的能力.而现实中,的确有为数不少的父母,以爱的名义将孩子囚禁,而在某个时候,主动地,或者被动地,突然间就将一个异常复杂的世界交给孩子孤独地面对. 所以我希望所有人,当带着自己年幼的孩子长大时,将自家的孩子当一个成长的人看待,切不要包办代办,只须陪他长大即可