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

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

using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Unity.VisualScripting;
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 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;
    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;

        //StartCoroutine(WaitMapdata());

        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)
    {
        if (mapName == "word")
        {
            return;
        }

        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))
        {
            isKeyUp = true;
            keyboard = 2;//同时有两个按键则返回
        }

        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);
                }
            }
            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)
                {
                    Debug.Log("方向不同");
                    currentStr = dir;
                }
            }

            //不可移动判断
            if (isKeyUp)
            {
                return;
            }
            if (tox < 0 || toy > 0) return;//防止移出边界
            if (tox > 254 || toy < -254) return;//防止移出边界


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

            for (int i = 0; i < player.Length; i++)
            {
                player[i].SetNextPos();//人物开始移动
            }

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

        }


    }


    //增加移动路径

    private bool NotMove()
    {
        int _tox = (int)tox;
        int _toy = (int)toy;

        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] == "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。
new MapConfig().laduo的二维地图数组封装在dll里面保点密不想直接在工程太显眼。
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是28,我们得到了它的精灵了:card.GetComponent().sprite = dSprite[28];
卡片的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,这个是一个卡片是32X32得来得,在NES里面截个图刚好是这个大小,NES里一张高清背景的大小是1024X896,所以我这里就设置了这个分辨率。
屏幕左上角坐标是(0,-0.5f),这个-0.5f是NES里面的重装机兵屏幕最上方(和下方)的卡片是显示半个;
屏幕右下角坐标是(15,-13.5f);
屏幕中心点通常第一个玩家的坐标是(8,-7);
摄像机坐标是(7.5f,-7,10);
这个是地图滚动运行结果:

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

下一章给出玩家队列在屏幕中心的一个跟随。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值