unity复刻重装机兵(二)地图加载及滚动复杂模式

直接上地图加载和如何滚动的代码:

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;
using ZzjbSrc;

public class TownMap : MonoBehaviour
{
    public float moveSpeed = 3;
    public Player[] player;

    Texture2D texMap;
    Sprite[] spritesmap;

    string alphabet = "0123456789abcdefghijklmnopqrstuvwxyz";
    public static string[,] mapdataRoad;
    string[,] mapUpdate;

    int row = 0;
    int col = 0;

    //设置字典,保存每个卡片的精灵和ID,而每个ID对应唯一卡片坐标
    public Dictionary<int, Sprite> dSprite = new Dictionary<int, Sprite>();

    //------------地图滚动---------------
    int STEP = 0;//移动步数
    public string mapName = "laduo";

    [HideInInspector]
    public float animTimer = 0;//动画帧


    [HideInInspector]
    public string dir = "";//移动方向
    string currentStr = "DOWN";//默认方向
    Vector2 myCoordinate;//探路动画坐标
    [HideInInspector]
    public bool isKeyUp = true;
    [HideInInspector]
    public bool isMoving = false;
    int keyboard = 0;

    int tox = 12;
    int toy = -8;

    int mapMoveX = 0;
    int mapMoveY = 0;

    Vector2 centerPos;
    public Vector2 mapCenterPos;

    Vector2 mapNextPos;

    //----------UI处理------------
    [HideInInspector]
    public bool UIOpen = false;

    int player2WSAD = -1;//二号玩家位置,-1代表在中心

    void Start()
    {
        for (int i = 0; i < 272; i++)
        {
            GameObject item = new GameObject("card");
            item.AddComponent<SpriteRenderer>();
            item.GetComponent<SpriteRenderer>().drawMode = SpriteDrawMode.Sliced;
            item.transform.GetComponent<SpriteRenderer>().size = new Vector2(1, 1);
            item.transform.SetParent(transform);
            item.SetActive(false);
        }
        tox = 8;
        toy = -7;

        centerPos = new Vector2(8, -7);
        myCoordinate = centerPos;

        InitMapData("laduo", new MapConfig().laduo, 17, 26);

    }


    public void InitMapData(string _mapName, string mapData, int mapRow, int mappCol)
    {
        mapName = _mapName;
        string strAll = mapData;
        row = mapRow;
        col = mappCol;
        texMap = Resources.Load<Texture2D>("sprite/mm1_locate_general");
        //拆分图片获取编号,从左上角编号零开始根据像素拆分
        GetMapSprite();

        string result = strAll.ToString().Replace("\n", "");
        string str2 = Regex.Replace(result, @"\s", "");
        //拆分地图数据给二维数组
        string[] parts = str2.Split(',');
        string[,] mapArray = new string[col, row];
        mapdataRoad = new string[col, row];//其他脚本引用使用

        for (int i = 0; i < col; i++)
        {
            for (int j = 0; j < row; j++)
            {
                mapArray[i, j] = parts[i + (col * j)];

            }
        }
        mapUpdate = mapArray;
        dSprite.Clear();
        string[,] map = mapUpdate;

        int cardCount = -1;

        for (int y = 0; y < row; y++)
        {
            for (int x = 0; x < col; x++)
            {
                cardCount++;
                string tileType = map[x, y];

                //给精灵图片赋值
                foreach (Sprite s in spritesmap)
                {
                    if (s.name == tileType)
                    {
                        dSprite.Add(cardCount, s);
                        break;
                    }
                }
                mapdataRoad[x, y] = tileType;
            }
        }

        LoadMapData();
    }

    public void LoadMapData()
    {
        //player.GetComponent<PlayerController>().mapName = mapName;
        int _x = (int)mapCenterPos.x;
        int _y = (int)mapCenterPos.y;

        int xCount = 8 - _x;
        int yCount = -7 - _y;

        int childID = -1;
        for (int x = _x - 8; x <= _x + 8; x++)
        {
            for (int y = _y - 8; y < _y + 8; y++)
            {
                if (x >= 0 && x < col)
                {
                    if (y <= 0 && y > -row)
                    {
                        int SpriteID = (x + (col * -y));
                        childID++;
                        Transform card = transform.GetChild(childID);
                        card.position = new Vector2(x + xCount, y + yCount);
                        card.GetComponent<SpriteRenderer>().sprite = dSprite[SpriteID];
                        card.GetComponent<SpriteRenderer>().size = new Vector2(1, 1);
                        card.gameObject.SetActive(true);
                    }
                    else
                    {
                        childID++;
                        Transform card = transform.GetChild(childID);
                        card.position = new Vector2(x + xCount, y + yCount);
                        card.GetComponent<SpriteRenderer>().sprite = spritesmap[0];
                        card.GetComponent<SpriteRenderer>().size = new Vector2(1, 1);
                        card.gameObject.SetActive(true);
                    }
                }
                else
                {
                    childID++;
                    Transform card = transform.GetChild(childID);
                    card.position = new Vector2(x + xCount, y + yCount);
                    card.GetComponent<SpriteRenderer>().sprite = spritesmap[0];
                    card.GetComponent<SpriteRenderer>().size = new Vector2(1, 1);
                    card.gameObject.SetActive(true);
                }

            }
        }

    }

    void GetMapSprite()
    {
        int index = -1;
        int row = texMap.height / 32;
        int col = texMap.width / 32;
        spritesmap = new Sprite[row * col];

        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < col; j++)
            {
                index++;
                Sprite sp = Sprite.Create(texMap, new Rect(j * 32, (row - 1 - i) * 32, 32, 32), new Vector2(0.5f, 0.5f));
                spritesmap[index] = sp;
                int dex = index / 10;
                string str = alphabet[dex].ToString();
                str = str + "" + (index % 10).ToString();
                spritesmap[index].name = str;

            }
        }
    }

    //移动后更新卡片
    public void ShowMapSprite(int posX, int posY)
    {

        for (int i = 0; i < transform.childCount; i++)
        {

            if (dir == "UP")
            {
                if (transform.GetChild(i).position.y == posY - 9)
                {
                    Transform trans = transform.GetChild(i);
                    trans.position = new Vector2(trans.position.x, trans.position.y + 16);
                    NextBoardCard(trans);
                }

            }
            else if (dir == "DOWN")
            {
                if (transform.GetChild(i).position.y == posY + 9)
                {
                    Transform trans = transform.GetChild(i);
                    trans.position = new Vector2(trans.position.x, trans.position.y - 16);
                    NextBoardCard(trans);
                }
            }
            else if (dir == "LEFT")
            {
                if (transform.GetChild(i).position.x == posX + 9)
                {
                    Transform trans = transform.GetChild(i);
                    trans.position = new Vector2(trans.position.x - 17, trans.position.y);
                    NextBoardCard(trans);
                }
            }
            else if (dir == "RIGHT")
            {
                if (transform.GetChild(i).position.x == posX - 10)
                {
                    Transform trans = transform.GetChild(i);
                    trans.position = new Vector2(trans.position.x + 17, trans.position.y);
                    NextBoardCard(trans);
                }
            }
        }
    }


    void NextBoardCard(Transform trans)
    {

        int xCount = 8 - (int)mapCenterPos.x;//中心点X轴偏移总单位
        int yCount = -7 - (int)mapCenterPos.y;//中心点Y轴偏移总单位

        int x = (int)trans.position.x - xCount;//映射这个卡片在地图数组中的X坐标
        int y = (int)trans.position.y - yCount;//映射这个卡片在地图数组中的X坐标
        int SpriteID = (x + (col * -y));

        if (x >= 0 && x < col)
        {
            if (y <= 0 && y > -row)
            {
                Transform card = trans;
                card.GetComponent<SpriteRenderer>().sprite = dSprite[SpriteID];
            }
            else
            {

                trans.GetComponent<SpriteRenderer>().sprite = spritesmap[0];
            }
        }
        else
        {
            trans.GetComponent<SpriteRenderer>().sprite = spritesmap[0];
        }

    }

    void Update()
    {

        if (Input.GetKeyUp(KeyCode.S) || Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.D) || Input.GetKeyUp(KeyCode.W))
        {
            keyboard = 0;
            isKeyUp = true;
        }

        if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.S)
            || Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.A)
             || Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.D)
             || Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.A)
             || Input.GetKey(KeyCode.S) && Input.GetKey(KeyCode.D)
             || Input.GetKey(KeyCode.A) && Input.GetKey(KeyCode.D))
        {
            keyboard = 2;//同时有两个按键则返回
            isKeyUp = true;
        }

        if (!isMoving)
        {
            if (Input.GetKey(KeyCode.W))
            {
                isKeyUp = false;
                dir = "UP";
            }
            else if (Input.GetKey(KeyCode.S))
            {
                isKeyUp = false;
                dir = "DOWN";
            }
            else if (Input.GetKey(KeyCode.A))
            {
                isKeyUp = false;
                dir = "LEFT";
            }
            else if (Input.GetKey(KeyCode.D))
            {
                isKeyUp = false;
                dir = "RIGHT";

            }
            for (int i = 0; i < player.Length; i++)
            {
                player[i].dir = dir;
            }
        }

        //多个方向同时按键则急停
        switch (dir)
        {
            case "UP":
                if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D) || Input.GetKeyUp(KeyCode.W))
                {
                    isKeyUp = true;
                }
                break;
            case "LEFT":
                if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.D) || Input.GetKeyUp(KeyCode.A))
                {
                    isKeyUp = true;
                }
                break;
            case "RIGHT":
                if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.W) || Input.GetKeyUp(KeyCode.D))
                {
                    isKeyUp = true;
                }
                break;
            case "DOWN":
                if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D) || Input.GetKeyUp(KeyCode.S))
                {
                    isKeyUp = true;
                }
                break;
        }
        if (myCoordinate == centerPos)
        {
            if (isMoving)
            {
                int moveX = (int)transform.position.x;
                int moveY = (int)transform.position.y;
                transform.position = Vector2.zero;
                for (int i = 0; i < transform.childCount; i++)
                {
                    transform.GetChild(i).position = new Vector2(transform.GetChild(i).position.x + moveX, transform.GetChild(i).position.y + moveY);
                }

                //二号玩家位置
                if (player[1].transform.localPosition.y == 1)
                {
                    player2WSAD = 0;
                }
                else if (player[1].transform.localPosition.y == -1)
                {
                    player2WSAD = 1;
                }
                else if (player[1].transform.localPosition.x == -1)
                {
                    player2WSAD = 2;
                }
                else if (player[1].transform.localPosition.x == 1)
                {
                    player2WSAD = 3;
                }

                //人物移动完毕需要朝向跟随的目标
                for (int i = 1; i < player.Length; i++)
                {
                    player[i].PlayerLateAnim(0);
                    player[i].player2WSAD = player2WSAD;
                }

                //Debug.Log(player2WSAD);
                //TODO 到了目标点执行任务
                MyNextTask();
            }
            isMoving = false;

            switch (dir)
            {
                case "UP":
                    tox = (int)myCoordinate.x;
                    toy = (int)myCoordinate.y + 1;
                    break;
                case "LEFT":
                    tox = (int)myCoordinate.x - 1;
                    toy = (int)myCoordinate.y;
                    break;
                case "RIGHT":
                    tox = (int)myCoordinate.x + 1;
                    toy = (int)myCoordinate.y;
                    break;
                case "DOWN":
                    tox = (int)myCoordinate.x;
                    toy = (int)myCoordinate.y - 1;
                    break;
            }

            if (currentStr != dir)
            {
                if (keyboard < 2)
                {
                    player[0].PlayerAnim(0);//多个障碍可以原地转向

                    currentStr = dir;
                }
            }

            //不可移动判断
            if (isKeyUp)
            {
                return;
            }

            //加载移动路径,其他为障碍物
            if (NotMove())
            {
                //return;//注销取消障碍
            }

            animTimer = 0;
            STEP++;
            //所有队列移动步数重置
            for (int i = 1; i < player.Length; i++)
            {
                player[i].currentStep = STEP;
            }

            ShowMapSprite(tox, toy);

            mapMoveX = tox - (int)myCoordinate.x;
            mapMoveY = toy - (int)myCoordinate.y;

            myCoordinate = new Vector2(tox, toy);
            mapCenterPos = new Vector2(mapCenterPos.x + mapMoveX, mapCenterPos.y + mapMoveY);

            mapNextPos = new Vector2(transform.position.x - mapMoveX, transform.position.y - mapMoveY);

        }
        else
        {

            isMoving = true;
            myCoordinate = Vector2.MoveTowards(myCoordinate, centerPos, moveSpeed * Time.deltaTime);

            transform.position = Vector2.MoveTowards(transform.position, mapNextPos, moveSpeed * Time.deltaTime);

            //处理所有玩家切换地图后在中心重合的情况
            for (int i = 1; i < player.Length; i++)
            {
                //player[i].ItemMoving();//队伍跟随
            }

            //处理玩家移动动画
            if (animTimer < moveSpeed)
            {
                animTimer += moveSpeed * Time.deltaTime;

                if (animTimer < 0.5f)
                {
                    player[0].PlayerAnim(1);
                    for (int i = 1; i < player.Length; i++)
                    {
                        player[i].PlayerAnim(1);
                    }
                }
                else
                {
                    player[0].PlayerAnim(0);
                    for (int i = 1; i < player.Length; i++)
                    {
                        player[i].PlayerAnim(0);
                    }
                }
            }
        }
    }

    private void MyNextTask()
    {
        int boardX = (int)mapCenterPos.x;
        int boardY = (int)mapCenterPos.y;//第四象限

        if (mapName == "laduo")
        {
            if (boardX <= 0 || boardY >= 0 || boardX >= 25 || boardY <= -16)
            {
                //切换到世界地图
            }
            else
            {
                //TODO
                //到屋子里面去

            }

        }
    }

    //增加移动路径

    private bool NotMove()
    {

        int _tox = (int)mapCenterPos.x + tox - (int)myCoordinate.x;
        int _toy = Mathf.Abs((int)mapCenterPos.y + toy - (int)myCoordinate.y);//数组行为正数
        int _toy2 = (int)mapCenterPos.y + toy - (int)myCoordinate.y;//第四象限
        if (_tox < 0 || _toy2 > 0)
        {
            return true;//防止移出边界
        }
        if (_tox > 254 || _toy2 < -254)
        {
            return true;//防止移出边界
        }

        if (mapName == "laduo")
        {
            if (_tox < 26 && _toy < 17)
            {
                if (mapdataRoad[_tox, _toy] == "00") return false;
                if (mapdataRoad[_tox, _toy] == "01") return false;
                if (mapdataRoad[_tox, _toy] == "15") return false;
                if (mapdataRoad[_tox, _toy] == "30") return false;
                if (mapdataRoad[_tox, _toy] == "32") return false;
                if (mapdataRoad[_tox, _toy] == "33") return false;
                if (mapdataRoad[_tox, _toy] == "36") return false;
                if (mapdataRoad[_tox, _toy] == "41") return false;
                if (mapdataRoad[_tox, _toy] == "43") return false;
                if (mapdataRoad[_tox, _toy] == "53") return false;
                if (mapdataRoad[_tox, _toy] == "62") return false;
                if (mapdataRoad[_tox, _toy] == "75") return false;
                if (mapdataRoad[_tox, _toy] == "82") return false;
                if (mapdataRoad[_tox, _toy] == "83") return false;

            }
            else
            {
                return true;
            }
        }
        else if (mapName == "word")
        {

            if (mapdataRoad[_tox, _toy] == "01") return false;
            if (mapdataRoad[_tox, _toy] == "08") return false;
            if (mapdataRoad[_tox, _toy] == "09") return false;
            if (mapdataRoad[_tox, _toy] == "12") return false;
            if (mapdataRoad[_tox, _toy] == "13") return false;
            if (mapdataRoad[_tox, _toy] == "27") return false;
            if (mapdataRoad[_tox, _toy] == "28") return false;
            if (mapdataRoad[_tox, _toy] == "39") return false;
            if (mapdataRoad[_tox, _toy] == "44") return false;
            if (mapdataRoad[_tox, _toy] == "45") return false;
            if (mapdataRoad[_tox, _toy] == "50") return false;
            if (mapdataRoad[_tox, _toy] == "51") return false;
            if (mapdataRoad[_tox, _toy] == "52") return false;
            if (mapdataRoad[_tox, _toy] == "53") return false;
            if (mapdataRoad[_tox, _toy] == "60") return false;
            if (mapdataRoad[_tox, _toy] == "65") return false;
            if (mapdataRoad[_tox, _toy] == "66") return false;
            if (mapdataRoad[_tox, _toy] == "68") return false;
            if (mapdataRoad[_tox, _toy] == "69") return false;
            if (mapdataRoad[_tox, _toy] == "70") return false;
            if (mapdataRoad[_tox, _toy] == "71") return false;
            if (mapdataRoad[_tox, _toy] == "b7") return false;
            if (mapdataRoad[_tox, _toy] == "b8") return false;
            if (mapdataRoad[_tox, _toy] == "b9") return false;
            if (mapdataRoad[_tox, _toy] == "c0") return false;
            if (mapdataRoad[_tox, _toy] == "c1") return false;
            if (mapdataRoad[_tox, _toy] == "c2") return false;
            if (mapdataRoad[_tox, _toy] == "c3") return false;
            if (mapdataRoad[_tox, _toy] == "c4") return false;
            if (mapdataRoad[_tox, _toy] == "c7") return false;
            if (mapdataRoad[_tox, _toy] == "d2") return false;
            if (mapdataRoad[_tox, _toy] == "d5") return false;
            if (mapdataRoad[_tox, _toy] == "e0") return false;
            if (mapdataRoad[_tox, _toy] == "e1") return false;
            if (mapdataRoad[_tox, _toy] == "e2") return false;
            if (mapdataRoad[_tox, _toy] == "e3") return false;
            if (mapdataRoad[_tox, _toy] == "e9") return false;
            if (mapdataRoad[_tox, _toy] == "f0") return false;

        }

        return true;
    }


}

这个模式是摄像机和中心玩家固定不动,移动的是背景。
代码分析:
GetMapSprite();//拆分图片获取编号,从左上角编号零开始根据像素拆分下图:
用工具分析拆分图片如下做了记号:

多出来的两列是刻意PS来保留的为了保持是10列的整数。对于没有背景底色的卡片自己动手PS了底色,之前是复制了一个背景色块在底部有同样效果,这样会多消耗一个卡片资源没有采用此方法。
GetMapSprite()函数得到了每一个编号的卡片保存到内存中。
开始加载拉多地图InitMapData(“laduo”, new MapConfig().laduo, 17, 26);
地图名字"laduo",地图数据new MapConfig().laduo,地图行17和列26。
ShowMapSprite(tox, toy):地图每移动一步需要更新让一个距离中心的一个单位的探路坐标myCoordinate向中心点移动。
dSprite.Add(cardCount, s);这个方法获取二维数组每一个编号精灵,每次移动我们获取屏幕玩家中心点在数组的第几行第几列即:
mapCenterPos = new Vector2(mapCenterPos.x + mapMoveX, mapCenterPos.y + mapMoveY);
地图滚动思路是有一个所有卡片父节点A,按下方向键A移动一步,移动一步完了之后重置A的世界坐标为(0,0):见
transform.position = Vector2.zero;
然后重新偏移映射所有卡片:

       for (int i = 0; i < transform.childCount; i++)
       {
           transform.GetChild(i).position = 
           new Vector2(transform.GetChild(i).position.x + moveX, transform.GetChild(i).position.y + moveY);
       }

防止它们的世界坐标移动后发生变化。
NextBoardCard(Transform trans)方法是更新背景卡片的核心代码,
我这里故意让超出屏幕的地图右边多了一列和下边多了一行,

只要红色屏幕区域在整个正方形区域里面滚动啥也不用处理,如果此时红色区域向上或者向左,我们在移动之前马上把黑色区域移动到要去的地方,比如向左移动一格,右边那一列马上向左移动16个格子(也许是17吧,此时屏幕也在移动所以距离要偏移一个单位)到屏幕的左边即可,其他同理。移动之后马上给这些移动的卡片精灵赋值到二维数组对应卡片。我把超出二维数组的卡片赋值了一个沙漠卡片背景:
trans.GetComponent().sprite = spritesmap[0];
没有超出边界的给了这个赋值:
card.GetComponent().sprite = dSprite[SpriteID];
看这个二维数组:

这个红圈里面的17编号在二维数组对应的ID是一个26列+2个列,它的ID是27,我们得到了它的精灵了:card.GetComponent().sprite = dSprite[27];
卡片的ID在移动后这样获取的:

        int xCount = 8 - (int)mapCenterPos.x;//中心点X轴偏移总单位
        int yCount = -7 - (int)mapCenterPos.y;//中心点Y轴偏移总单位

        int x = (int)trans.position.x - xCount;//映射这个卡片在地图数组中的X坐标
        int y = (int)trans.position.y - yCount;//映射这个卡片在地图数组中的X坐标
        int SpriteID = (x + (col * -y));

NotMove();增加移动路径,固定编号可以前进,比如草是mapdataRoad[_tox, _toy] == “00”,玩家可以停在这个卡片上,其他卡片则禁止。

屏幕分辨率1024X896,在NES里面截个图刚好是这个大小,我这里的NES里一张高清背景的大小是1024X896,所以我这里就设置了这个分辨率。
屏幕左上角坐标是(0,-0.5f),这个-0.5f是NES里面的重装机兵屏幕最上方(和下方)的卡片是显示半个;
屏幕右下角坐标是(15,-13.5f);
屏幕中心点通常第一个玩家的坐标是(8,-7);
摄像机坐标是(7.5f,-7,10)。

这个是地图滚动运行结果:

重装机兵屏幕中心地图滚动

这个模式想实现人物跟随代码量非常大,需要枚举各种情况,还是滚动摄像机来更新地图比较友好。
下一章unity复刻重装机兵(三)地图的切换和队列简单跟随

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值