private void DoInitRenderProperty()
        {
            var minPosX = float.MaxValue;
            var minPosY = float.MaxValue;

            var maxPosX = float.MinValue;
            var maxPosY = float.MinValue;

            var tileWidthInUnit  = (float)mMapMeta.tileWidthInPixel / mRenderSetting.pixelsPreUnit;
            var tileHeightInUnit = (float)mMapMeta.tileHeightInPixel / mRenderSetting.pixelsPreUnit;


            mAllNeedRenderTileList = new List <ITU_RenderTileData>();
            mLayerMeta.chunkList.ForEach(chunk =>
            {
                for (var index = 0; index < chunk.data.Length; index++)
                {
                    var gid = chunk.data[index];
                    //为0的砖块则表示不需要渲染
                    if (gid == 0)
                    {
                        continue;
                    }

                    var renderTileData = new ITU_RenderTileData();
                    renderTileData.x   = chunk.startX + index % chunk.width;
                    renderTileData.y   = chunk.startY + (int)Mathf.Ceil(index / chunk.width);

                    ITU_TsxRootMeta _tilesetMeta;
                    ITU_TsxEachTileMeta _eachTileMeta;
                    ITU_Utils.GetTileMetaByGid(mMapMeta, gid, out _tilesetMeta, out _eachTileMeta);

                    _tilesetMeta.isUesdInRender = true;
                    renderTileData.tileMeta     = _eachTileMeta;
                    mAllNeedRenderTileList.Add(renderTileData);

                    Vector2 nowPos;
                    ITU_MathUtils.TileTopCorner2World(renderTileData.x, renderTileData.y, tileWidthInUnit, tileHeightInUnit, mMapMeta.IsIsoStaggered(), out nowPos);

                    minPosX = Mathf.Min(minPosX, nowPos.x);
                    minPosY = Mathf.Min(minPosY, nowPos.y);
                    maxPosX = Mathf.Max(maxPosX, nowPos.x);
                    maxPosY = Mathf.Max(maxPosY, nowPos.y);
                }
            });

            //左上和右下两个Bound是左边点向两边个扩充2.5个Tile,.5是为了让坐标点在中心. 2个Tile是增大Bound防止周围Tile未渲染
            //因为后续渲染会检测空Tile,所以区间扩充大一些没有关系
            mLeftTopCornerBound     = new Vector2(minPosX - tileWidthInUnit * 2.5f, maxPosY + tileHeightInUnit * mRenderSetting.renderChunkSize * 2.5f);
            mRightBottomCornerBound = new Vector2(maxPosX + tileWidthInUnit * 2.5f, minPosY - tileHeightInUnit * mRenderSetting.renderChunkSize * 2.5f);


            //此值不准确,只是为了大概显示一下进度条,防止界面卡顿导致以为是死机
            var xNum = Mathf.CeilToInt(Math.Abs(mRightBottomCornerBound.x - mLeftTopCornerBound.x) / (mRenderSetting.renderChunkSize * tileWidthInUnit));
            var yNum = Mathf.CeilToInt(Math.Abs(mRightBottomCornerBound.y - mLeftTopCornerBound.y) / (mRenderSetting.renderChunkSize * tileHeightInUnit * 0.5f));

            mMaxMayRenderChunkNum = (xNum + 4) * (yNum + 4);
        }
        private bool TryToRenderChunk(Vector2Int _topTile, int _chunkSize, int _chunkIndex)
        {
#if UNITY_EDITOR
            mFinishTryRenderChunkNum++;
            if (mFinishTryRenderChunkNum > mMaxMayRenderChunkNum)
            {
                UnityEditor.EditorUtility.DisplayProgressBar("Render Layer " + mLayerMeta.layerName,
                                                             string.Format("Please wait.... [{1}] {0}", mFinishTryRenderChunkNum, _chunkIndex), 1f);
            }
            else
            {
                UnityEditor.EditorUtility.DisplayProgressBar("Render Layer " + mLayerMeta.layerName,
                                                             string.Format("Please wait.... [{2}] {0}/{1}", mFinishTryRenderChunkNum, mMaxMayRenderChunkNum, _chunkIndex),
                                                             (float)mFinishTryRenderChunkNum / mMaxMayRenderChunkNum);
            }
#endif
            var renderTileList = new List <ITU_RenderTileData>();
            var lineFistTile   = _topTile;

            var lineTileNum = 1;
            for (var i = 0; i < _chunkSize; i++)
            {
                TryToPushLineRenderTileData(lineFistTile, lineTileNum, renderTileList);
                ITU_MathUtils.GetNowTileLeftBottomTileWithStep(lineFistTile.x, lineFistTile.y, 1, mMapMeta.IsIsoStaggered(), out lineFistTile);
                lineTileNum++;
            }

            //For循环最后一次时候向左下移动了一格,所以进入底部渲染时候需要先向右侧移动一格
            ITU_MathUtils.GetNowTileRightTileWithStep(lineFistTile.x, lineFistTile.y, 1, mMapMeta.IsIsoStaggered(), out lineFistTile);

            lineTileNum = _chunkSize - 1;
            for (var i = 0; i < _chunkSize - 1; i++)
            {
                TryToPushLineRenderTileData(lineFistTile, lineTileNum, renderTileList);
                ITU_MathUtils.GetNowTileRightBottomTileWithStep(lineFistTile.x, lineFistTile.y, 1, mMapMeta.IsIsoStaggered(), out lineFistTile);
                lineTileNum--;
            }

            if (renderTileList.Count <= 0)
            {
                return(false);
            }

            var chunkGo = new GameObject("Chunk_" + _chunkIndex);
            chunkGo.transform.parent        = mLayerRootGo.transform;
            chunkGo.transform.localPosition = Vector3.zero;
            DoRenderChunk(chunkGo, renderTileList);
            return(true);
        }
        /// <summary>
        /// 将给定线段长度的TileRenderData Push到需要渲染的渲染列表中去
        /// </summary>
        private void TryToPushLineRenderTileData(Vector2Int _startTile, int _count, List <ITU_RenderTileData> _list)
        {
            var nowPointTile = _startTile;

            for (var i = 0; i < _count; i++)
            {
                var tileData = mAllNeedRenderTileList.Find(data => data.x == nowPointTile.x && data.y == nowPointTile.y);
                if (tileData != null && !tileData.tileMeta.isImageCollectionAndNotRender)
                {
                    _list.Add(tileData);
                }

                ITU_MathUtils.GetNowTileRightTileWithStep(nowPointTile.x, nowPointTile.y, 1, mMapMeta.IsIsoStaggered(), out nowPointTile);
            }
        }
        private void DoPushTile(int _posX, int _posY, ITU_TsxEachTileMeta _tileMeta)
        {
            var tileWidthInUnit     = (float)mMapMeta.tileWidthInPixel / mRenderSetting.pixelsPreUnit;
            var tileHeighInUnit     = (float)mMapMeta.tileHeightInPixel / mRenderSetting.pixelsPreUnit;
            var halfTileWidthInUnit = tileWidthInUnit / 2;

            var tilesetHeightInUnit = (float)_tileMeta.tileHeightInPixel / mRenderSetting.pixelsPreUnit;

            Vector2 topCenterPos;

            ITU_MathUtils.TileTopCorner2World(_posX, _posY, tileWidthInUnit, tileHeighInUnit,
                                              mMapMeta.orientation == ITU_TmxRootMeta.ORIENTAION_STAGGERED, out topCenterPos);
            var bottomCenterPos = new Vector2(topCenterPos.x, topCenterPos.y - tileHeighInUnit);


            var v2 = new Vector3(bottomCenterPos.x - halfTileWidthInUnit, bottomCenterPos.y, 0);
            var v1 = new Vector3(bottomCenterPos.x + halfTileWidthInUnit, bottomCenterPos.y + tilesetHeightInUnit, 0);
            var v0 = new Vector3(v2.x, v1.y, 0);
            var v3 = new Vector3(v1.x, v2.y, 0);

            mVertices.Add(v0);
            mUVList.Add(_tileMeta.uv_p0);
            var indexV0 = mVertices.Count - 1;

            mVertices.Add(v1);
            mUVList.Add(_tileMeta.uv_p1);
            var indexV1 = mVertices.Count - 1;

            mVertices.Add(v2);
            mUVList.Add(_tileMeta.uv_p2);
            var indexV2 = mVertices.Count - 1;

            mVertices.Add(v3);
            mUVList.Add(_tileMeta.uv_p3);
            var indexV3 = mVertices.Count - 1;

            mTriangles.Add(indexV0);
            mTriangles.Add(indexV1);
            mTriangles.Add(indexV2);

            mTriangles.Add(indexV2);
            mTriangles.Add(indexV1);
            mTriangles.Add(indexV3);

            var tileIndex = new Vector2Int(_posX, _posY);

            mAllExtensionList.ForEach(x => x.OnRenderTile(tileIndex, topCenterPos, tileWidthInUnit, tileHeighInUnit, mLayerMeta, _tileMeta));
        }
Beispiel #5
0
        public void HandleMapPropertyAndObject()
        {
            if (mMapMeta == null)
            {
                Debug.LogError("ITU_Facade not load any map, please call LoadTxmFile function first");
                return;
            }

            //Begin
            mAllExtensionList.ForEach(x =>
            {
                x.SetRenderSetting(mRenderSetting);
                x.SetTmxMapMeta(mMapMeta);
                x.HandleMapPropertyAndObjectBegin();
            });

            //Map
            mAllExtensionList.ForEach(x =>
            {
                if (mMapMeta.property != null)
                {
                    x.HandleMapProperty(mMapMeta.property);
                }
            });

            //Layer
            mAllExtensionList.ForEach(x =>
            {
                mMapMeta.layerList.ForEach(layer =>
                {
                    if (layer.property != null)
                    {
                        x.HandleLayerProperty(layer, layer.property);
                    }
                });
            });

            //Object
            mAllExtensionList.ForEach(x => { mMapMeta.objectList.ForEach(x.HandleMapObject); });

            var pixelsPreUnit    = mRenderSetting != null ? mRenderSetting.pixelsPreUnit : 100;
            var tileWidthInUnit  = (float)mMapMeta.tileWidthInPixel / pixelsPreUnit;
            var tileHeightInUnit = (float)mMapMeta.tileHeightInPixel / pixelsPreUnit;

            //Tile
            mAllExtensionList.ForEach(x =>
            {
                mMapMeta.layerList.ForEach(layer =>
                {
                    layer.chunkList.ForEach(chunk =>
                    {
                        for (var index = 0; index < chunk.data.Length; index++)
                        {
                            var gid = chunk.data[index];
                            //为0的砖块则表示不需要渲染
                            if (gid == 0)
                            {
                                continue;
                            }
                            var tileMeta = ITU_Utils.GetTileMetaByGid(mMapMeta, gid);
                            if (tileMeta != null && !tileMeta.property.IsEmpty())
                            {
                                var tileX = chunk.startX + index % chunk.width;
                                var tileY = chunk.startY + (int)Mathf.Ceil(index / chunk.width);
                                Vector2 topPos;
                                ITU_MathUtils.TileTopCorner2World(tileX, tileY, tileWidthInUnit, tileHeightInUnit, mMapMeta.IsIsoStaggered(), out topPos);
                                x.HandelTileWithProperty(new Vector2Int(tileX, tileY), topPos, tileWidthInUnit, tileHeightInUnit, layer, tileMeta);
                            }
                        }
                    });
                });
            });

            //Finish
            mAllExtensionList.ForEach(x => { x.HandleMapPropertyAndObjectFinish(); });
        }
        private void DoRenderLayer()
        {
            //以最小点向左上移动两个Chunk大小区域为起点,逐行扫描每个Chunk,直到Chunk的TopTile 大于MaxTile为止
            //这样进行Chunk渲染保证了正确的渲染顺序,右压左,下压上.(每个Chunk之内的Tile渲染也需要按此顺序)

            var tileWidthInUnit  = (float)mMapMeta.tileWidthInPixel / mRenderSetting.pixelsPreUnit;
            var tileHeightInUnit = (float)mMapMeta.tileHeightInPixel / mRenderSetting.pixelsPreUnit;


            var chunkIndex  = 0;
            var renderStep  = mRenderSetting.renderChunkSize;
            var isStaggered = mMapMeta.IsIsoStaggered();

            Vector2Int startPos;

            ITU_MathUtils.World2Tile(mLeftTopCornerBound.x, mLeftTopCornerBound.y, tileWidthInUnit, tileHeightInUnit, mMapMeta.IsIsoStaggered(), out startPos);
            //IsometricMathUtils.GetNowTileLeftTopTileWithStep(startPos.x, startPos.y, renderStep * 2, isStaggered, out startPos);
            var isTurnLeft = true;

            var lineFistTile = startPos;
            var nowPointTile = lineFistTile;

            while (true)
            {
                //渲染一行
                while (true)
                {
                    //nowPointTile默认指向的是当前渲染Chunk的TopTile
                    //此Tile向左下方移动chunkSize大小则为当前Chunk的最左侧Tile
                    Vector2Int chunkMinLeftTile;
                    ITU_MathUtils.GetNowTileLeftBottomTileWithStep(nowPointTile.x, nowPointTile.y, renderStep, isStaggered, out chunkMinLeftTile);
                    Vector2 chunkCheckPos;
                    ITU_MathUtils.TileTopCorner2World(chunkMinLeftTile.x, chunkMinLeftTile.y, tileWidthInUnit, tileHeightInUnit, isStaggered, out chunkCheckPos);
                    //应该是上角点减去 tileWidthInUnit/2即可.此处只是为了容错.
                    if (chunkCheckPos.x - tileWidthInUnit > mRightBottomCornerBound.x)
                    {
                        break;
                    }

                    var isDrawChunk = TryToRenderChunk(nowPointTile, mRenderSetting.renderChunkSize, chunkIndex);
                    chunkIndex = isDrawChunk ? chunkIndex + 1 : chunkIndex;
                    ITU_MathUtils.GetNowTileRightTileWithStep(nowPointTile.x, nowPointTile.y, renderStep, isStaggered, out nowPointTile);
                }

                //移动到下一行
                if (isTurnLeft)
                {
                    ITU_MathUtils.GetNowTileLeftBottomTileWithStep(lineFistTile.x, lineFistTile.y, renderStep, isStaggered, out lineFistTile);
                }
                else
                {
                    ITU_MathUtils.GetNowTileRightBottomTileWithStep(lineFistTile.x, lineFistTile.y, renderStep, isStaggered, out lineFistTile);
                }

                nowPointTile = lineFistTile;
                isTurnLeft   = !isTurnLeft;

                Vector2 bottomCheckPos;
                ITU_MathUtils.TileTopCorner2World(nowPointTile.x, nowPointTile.y, tileWidthInUnit, tileHeightInUnit, isStaggered, out bottomCheckPos);

                //Unity坐标是反向的,所以要反向检测
                if (bottomCheckPos.y < mRightBottomCornerBound.y)
                {
                    break;
                }
            }
        }