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