public override bool IsPassable() { AutoTileMap autoTileMap = AutoTileMap.Instance; if (autoTileMap.IsValidAutoTilePos(TileX, TileY)) { for( int iLayer = autoTileMap.GetLayerCount() - 1; iLayer >= 0; --iLayer ) { if( autoTileMap.MapLayers[iLayer].LayerType == AutoTileMap.eLayerType.Ground ) { AutoTileMap.AutoTile autoTile = autoTileMap.GetAutoTile(TileX, TileY, iLayer); AutoTileMap.eTileCollisionType collType = autoTile.Id >= 0 ? autoTileMap.Tileset.AutotileCollType[autoTile.Id] : AutoTileMap.eTileCollisionType.EMPTY; if( IsEmptyTilePassable && collType == AutoTileMap.eTileCollisionType.EMPTY || collType == AutoTileMap.eTileCollisionType.PASSABLE || collType == AutoTileMap.eTileCollisionType.WALL ) { return true; } else if( collType == AutoTileMap.eTileCollisionType.BLOCK || collType == AutoTileMap.eTileCollisionType.FENCE ) { return false; } } } } return false; }
//float now; float GetDistToTarget(AutoTileMap.AutoTile targetTile) { Vector3 target = RpgMapHelper.GetTileCenterPosition(targetTile.TileX, targetTile.TileY); target.z = transform.position.z; return((transform.position - target).magnitude); }
// special case for walls bool _IsWallPassable( MapTileNode neighNode ) { AutoTileMap autoTileMap = AutoTileMap.Instance; AutoTileMap.eTileCollisionType collType = AutoTileMap.eTileCollisionType.EMPTY; AutoTileMap.eTileCollisionType collTypeNeigh = AutoTileMap.eTileCollisionType.EMPTY; for (int iLayer = autoTileMap.GetLayerCount() - 1; iLayer >= 0; --iLayer) { if (autoTileMap.MapLayers[iLayer].LayerType == AutoTileMap.eLayerType.Ground) { AutoTileMap.AutoTile autoTile = autoTileMap.GetAutoTile(TileX, TileY, iLayer); AutoTileMap.AutoTile autoTileNeigh = autoTileMap.GetAutoTile(neighNode.TileX, neighNode.TileY, iLayer); if (autoTile.Id == autoTileNeigh.Id) // you can walk over two wall tiles if they have the same type { if (autoTile.Id >= 0) return true; else continue; } else { // collType will keep the first collision type found of type wall or passable if (collType != AutoTileMap.eTileCollisionType.PASSABLE && collType != AutoTileMap.eTileCollisionType.WALL) collType = autoTile.Id >= 0 ? autoTileMap.Tileset.AutotileCollType[autoTile.Id] : AutoTileMap.eTileCollisionType.EMPTY; if (collTypeNeigh != AutoTileMap.eTileCollisionType.PASSABLE && collTypeNeigh != AutoTileMap.eTileCollisionType.WALL) collTypeNeigh = autoTileNeigh.Id >= 0 ? autoTileMap.Tileset.AutotileCollType[autoTileNeigh.Id] : AutoTileMap.eTileCollisionType.EMPTY; if( collType == AutoTileMap.eTileCollisionType.PASSABLE && collTypeNeigh == AutoTileMap.eTileCollisionType.PASSABLE ) { return true; } else if (collType == AutoTileMap.eTileCollisionType.WALL || collTypeNeigh == AutoTileMap.eTileCollisionType.WALL) { return false; } } } } return true; }
/// <summary> /// Copy a section of the map and use it as drawing template /// </summary> /// <param name="tile_start_x"></param> /// <param name="tile_start_y"></param> /// <param name="tile_end_x"></param> /// <param name="tile_end_y"></param> /// <param name="_dragEndTileX"></param> /// <param name="_dragEndTileY"></param> /// <param name="isCtrlKeyHold"></param> public void RefreshBrushGizmo(int tile_start_x, int tile_start_y, int tile_end_x, int tile_end_y, int _dragEndTileX, int _dragEndTileY, bool isCtrlKeyHold) { Vector2 pivot = new Vector2(0f, 1f); SpriteRenderer[] aSprites = GetComponentsInChildren <SpriteRenderer>(); int sprIdx = 0; for (int tile_x = tile_start_x; tile_x <= tile_end_x; ++tile_x) { for (int tile_y = tile_start_y; tile_y <= tile_end_y; ++tile_y) { for (int tile_layer = 0; tile_layer < MyAutoTileMap.GetLayerCount(); ++tile_layer) { if ( (isCtrlKeyHold && tile_layer == SelectedLayer) || //copy all layers over the SelectedLayer !MyAutoTileMap.MapLayers[tile_layer].Visible // skip invisible layers ) { continue; } AutoTileMap.AutoTile autoTile = MyAutoTileMap.GetAutoTile(tile_x, tile_y, tile_layer); if (autoTile != null && autoTile.TilePartsIdx != null && autoTile.Id >= 0) { for (int partIdx = 0; partIdx < autoTile.TilePartsLength; ++partIdx, ++sprIdx) { SpriteRenderer spriteRender = sprIdx < aSprites.Length? aSprites[sprIdx] : null; if (spriteRender == null) { GameObject spriteObj = new GameObject(); spriteObj.transform.parent = transform; spriteRender = spriteObj.AddComponent <SpriteRenderer>(); } spriteRender.transform.gameObject.name = "BrushGizmoPart" + sprIdx; spriteRender.sprite = Sprite.Create(MyAutoTileMap.Tileset.AtlasTexture, MyAutoTileMap.Tileset.AutoTileRects[autoTile.TilePartsIdx[partIdx]], pivot, AutoTileset.PixelToUnits); spriteRender.sortingOrder = 50; //TODO: +50 temporal? see for a const number later spriteRender.color = new Color32(192, 192, 192, 192); // get last tile as relative position int tilePart_x = (tile_x - _dragEndTileX) * 2 + partIdx % 2; int tilePart_y = (tile_y - _dragEndTileY) * 2 + partIdx / 2; float xFactor = MyAutoTileMap.Tileset.TilePartWidth / AutoTileset.PixelToUnits; float yFactor = MyAutoTileMap.Tileset.TilePartHeight / AutoTileset.PixelToUnits; spriteRender.transform.localPosition = new Vector3(tilePart_x * xFactor, -tilePart_y * yFactor, spriteRender.transform.position.z); } } } } } // clean unused sprite objects while (sprIdx < aSprites.Length) { if (Application.isEditor) { DestroyImmediate(aSprites[sprIdx].transform.gameObject); } else { Destroy(aSprites[sprIdx].transform.gameObject); } ++sprIdx; } }
/// <summary> /// Reveal an area using as center, the tile over worldPosition and a sight length in tiles (sightLength) /// Uses a coroutine to make a fade transition /// </summary> /// <param name="worldPosition">The center tile</param> /// <param name="sightLength">The sight length in tiles</param> public static void RemoveFogOfWarWithFade(Vector3 worldPosition, int sightLength) { float sqrMaxDist = sightLength * sightLength * 4; int iFogLayer = AutoTileMap.Instance.MapLayers.FindIndex(x => x.LayerType == AutoTileMap.eLayerType.FogOfWar); if (iFogLayer >= 0) { AutoTileMap.AutoTile centerTile = RpgMapHelper.GetAutoTileByPosition(worldPosition, iFogLayer); for (int yf = -sightLength; yf <= sightLength; ++yf) { for (int xf = -sightLength; xf <= sightLength; ++xf) { int tx = centerTile.TileX + xf; int ty = centerTile.TileY + yf; if (AutoTileMap.Instance.IsValidAutoTilePos(tx, ty)) // This extra check is needed with fog of war layer { byte[] aFogAlpha = new byte[4]; for (int i = 0; i < aFogAlpha.Length; ++i) { //NOTE: for the fog level, each tile is divided in 4 tileparts. // The index i of each tile part is: // 0|2 // 1|3 int xf2 = 0; if (xf < 0) { xf2 = (i == 0 || i == 1) ? 2 * -xf : 2 * -xf - 1; //NOTE: 0, 1 are the left tile parts } else if (xf > 0) { xf2 = (i == 2 || i == 3) ? 2 * xf : 2 * xf - 1; } else //if( xf == 0 ) { xf2 = 0; } int yf2 = 0; if (yf < 0) { yf2 = (i == 0 || i == 2) ? 2 * -yf : 2 * -yf - 1; } else if (yf > 0) { yf2 = (i == 1 || i == 3) ? 2 * yf : 2 * yf - 1; } else //if( xf == 0 ) { yf2 = 0; } float sqrDist = xf2 * xf2 + yf2 * yf2; //NOTE: sqrDist = [0..(sightAreaSize*2)^2] float fAlphaFactor = Mathf.Clamp01(sqrDist / sqrMaxDist); fAlphaFactor *= fAlphaFactor; byte fogAlpha = (byte)(0xff * fAlphaFactor); aFogAlpha[i] = fogAlpha; } AutoTileMap.Instance.AddFogOfWarSetToQueue(tx + ty * AutoTileMap.Instance.MapTileWidth, aFogAlpha); } } } AutoTileMap.Instance.RefreshMinimapTexture(centerTile.TileX - sightLength, centerTile.TileY - sightLength, 2 * sightLength, 2 * sightLength); } }
void FillData() { m_animatedTiles.Clear(); m_animatedWaterfallTiles.Clear(); m_vertices = new Vector3[TileWidth * TileHeight * 4 * 4]; // 4 subtiles x 4 vertex per tile m_colors = new Color32[TileWidth * TileHeight * 4 * 4]; m_uv = new Vector2[m_vertices.Length]; m_triangles = new int[TileWidth * TileHeight * 4 * 2 * 3]; // 4 subtiles x 2 triangles per tile x 3 vertex per triangle int vertexIdx = 0; int triangleIdx = 0; //TODO: optimize updating only updated tiles inside the chunk for (int tileX = 0; tileX < TileWidth; ++tileX) { for (int tileY = 0; tileY < TileHeight; ++tileY) { AutoTileMap.AutoTile autoTile = MyAutoTileMap.GetAutoTile(StartTileX + tileX, StartTileY + tileY, MapLayerIdx); if (autoTile.Id >= 0) { int subTileXBase = tileX << 1; // <<1 == *2 int subTileYBase = tileY << 1; // <<1 == *2 for (int xf = 0; xf < 2; ++xf) { for (int yf = 0; yf < 2; ++yf) { int subTileX = subTileXBase + xf; int subTileY = subTileYBase + yf; float px0 = subTileX * (MyAutoTileMap.Tileset.TileWorldWidth / 2); float py0 = -subTileY * (MyAutoTileMap.Tileset.TileWorldHeight / 2); float px1 = (subTileX + 1) * (MyAutoTileMap.Tileset.TileWorldWidth / 2); float py1 = -(subTileY + 1) * (MyAutoTileMap.Tileset.TileWorldHeight / 2); m_vertices[vertexIdx + 0] = new Vector3(px0, py0, 0); m_vertices[vertexIdx + 1] = new Vector3(px0, py1, 0); m_vertices[vertexIdx + 2] = new Vector3(px1, py1, 0); m_vertices[vertexIdx + 3] = new Vector3(px1, py0, 0); m_colors[vertexIdx + 0] = new Color32(255, 255, 255, 255); m_colors[vertexIdx + 1] = new Color32(255, 255, 255, 255); m_colors[vertexIdx + 2] = new Color32(255, 255, 255, 255); m_colors[vertexIdx + 3] = new Color32(255, 255, 255, 255); m_triangles[triangleIdx + 0] = vertexIdx + 2; m_triangles[triangleIdx + 1] = vertexIdx + 1; m_triangles[triangleIdx + 2] = vertexIdx + 0; m_triangles[triangleIdx + 3] = vertexIdx + 0; m_triangles[triangleIdx + 4] = vertexIdx + 3; m_triangles[triangleIdx + 5] = vertexIdx + 2; float u0, u1, v0, v1; if (autoTile.Type == AutoTileMap.eTileType.OBJECTS || autoTile.Type == AutoTileMap.eTileType.NORMAL) { int spriteIdx = autoTile.TilePartsIdx[0]; Rect sprTileRect = MyAutoTileMap.Tileset.AutoTileRects[spriteIdx]; u0 = (((subTileX % 2) * sprTileRect.width / 2) + sprTileRect.x) / MyAutoTileMap.Tileset.AtlasTexture.width; u1 = (((subTileX % 2) * sprTileRect.width / 2) + sprTileRect.x + sprTileRect.width / 2) / MyAutoTileMap.Tileset.AtlasTexture.width; v0 = (((1 - subTileY % 2) * sprTileRect.height / 2) + sprTileRect.y + sprTileRect.height / 2) / MyAutoTileMap.Tileset.AtlasTexture.height; v1 = (((1 - subTileY % 2) * sprTileRect.height / 2) + sprTileRect.y) / MyAutoTileMap.Tileset.AtlasTexture.height; } else { int tilePartIdx = (subTileY % 2) * 2 + (subTileX % 2); int spriteIdx = autoTile.TilePartsIdx[tilePartIdx]; Rect sprTileRect = MyAutoTileMap.Tileset.AutoTileRects[spriteIdx]; u0 = sprTileRect.x / MyAutoTileMap.Tileset.AtlasTexture.width; u1 = (sprTileRect.x + sprTileRect.width) / MyAutoTileMap.Tileset.AtlasTexture.width; v0 = (sprTileRect.y + sprTileRect.height) / MyAutoTileMap.Tileset.AtlasTexture.height; v1 = sprTileRect.y / MyAutoTileMap.Tileset.AtlasTexture.height; if (MyAutoTileMap.Tileset.IsAutoTileAnimated(autoTile.Id)) { m_animatedTiles.Add(new AnimTileData() { VertexIdx = vertexIdx, U0 = u0, U1 = u1 }); } else if (MyAutoTileMap.Tileset.IsAutoTileAnimatedWaterfall(autoTile.Id)) { int subTileRow = (spriteIdx / 32); //32 = number of subtiles in a row; subTileRow %= 6; // make it relative to this autotile subTileRow -= 2; // remove top tiles m_animatedWaterfallTiles.Add(new AnimTileData() { VertexIdx = vertexIdx, V0 = v0, V1 = v1, SubTileRow = subTileRow }); } } m_uv[vertexIdx + 0] = new Vector3(u0, v0, 0); m_uv[vertexIdx + 1] = new Vector3(u0, v1, 0); m_uv[vertexIdx + 2] = new Vector3(u1, v1, 0); m_uv[vertexIdx + 3] = new Vector3(u1, v0, 0); // increment vectex and triangle idx vertexIdx += 4; triangleIdx += 6; } } } } } // resize arrays System.Array.Resize(ref m_vertices, vertexIdx); System.Array.Resize(ref m_colors, vertexIdx); System.Array.Resize(ref m_uv, vertexIdx); System.Array.Resize(ref m_triangles, triangleIdx); }
void FillFogOfWarData() { m_animatedTiles.Clear(); m_animatedWaterfallTiles.Clear(); m_vertices = new Vector3[TileWidth * TileHeight * 4 * 4]; // 4 subtiles x 4 vertex per tile m_colors = new Color32[TileWidth * TileHeight * 4 * 4]; m_uv = new Vector2[m_vertices.Length]; m_triangles = new int[TileWidth * TileHeight * 4 * 2 * 3]; // 4 subtiles x 2 triangles per tile x 3 vertex per triangle int vertexIdx = 0; int triangleIdx = 0; //TODO: optimize updating only updated tiles inside the chunk for (int tileX = 0; tileX < TileWidth; ++tileX) { for (int tileY = 0; tileY < TileHeight; ++tileY) { AutoTileMap.AutoTile autoTile = MyAutoTileMap.GetAutoTile(StartTileX + tileX, StartTileY + tileY, MapLayerIdx); byte[] fogColors = System.BitConverter.GetBytes(autoTile.Id); { int subTileXBase = tileX << 1; // <<1 == *2 int subTileYBase = tileY << 1; // <<1 == *2 int fogColorIdx = 0; for (int xf = 0; xf < 2; ++xf) { for (int yf = 0; yf < 2; ++yf, ++fogColorIdx) { int subTileX = subTileXBase + xf; int subTileY = subTileYBase + yf; float px0 = subTileX * (MyAutoTileMap.Tileset.TileWorldWidth / 2); float py0 = -subTileY * (MyAutoTileMap.Tileset.TileWorldHeight / 2); float px1 = (subTileX + 1) * (MyAutoTileMap.Tileset.TileWorldWidth / 2); float py1 = -(subTileY + 1) * (MyAutoTileMap.Tileset.TileWorldHeight / 2); m_vertices[vertexIdx + 0] = new Vector3(px0, py0, 0); m_vertices[vertexIdx + 1] = new Vector3(px0, py1, 0); m_vertices[vertexIdx + 2] = new Vector3(px1, py1, 0); m_vertices[vertexIdx + 3] = new Vector3(px1, py0, 0); m_colors[vertexIdx + 0] = new Color32(0, 0, 0, fogColors[fogColorIdx]); m_colors[vertexIdx + 1] = new Color32(0, 0, 0, fogColors[fogColorIdx]); m_colors[vertexIdx + 2] = new Color32(0, 0, 0, fogColors[fogColorIdx]); m_colors[vertexIdx + 3] = new Color32(0, 0, 0, fogColors[fogColorIdx]); m_triangles[triangleIdx + 0] = vertexIdx + 2; m_triangles[triangleIdx + 1] = vertexIdx + 1; m_triangles[triangleIdx + 2] = vertexIdx + 0; m_triangles[triangleIdx + 3] = vertexIdx + 0; m_triangles[triangleIdx + 4] = vertexIdx + 3; m_triangles[triangleIdx + 5] = vertexIdx + 2; float u0 = 0; float u1 = 0; float v0 = 1; float v1 = 1; m_uv[vertexIdx + 0] = new Vector3(u0, v0, 0); m_uv[vertexIdx + 1] = new Vector3(u0, v1, 0); m_uv[vertexIdx + 2] = new Vector3(u1, v1, 0); m_uv[vertexIdx + 3] = new Vector3(u1, v0, 0); // increment vectex and triangle idx vertexIdx += 4; triangleIdx += 6; } } } } } // resize arrays System.Array.Resize(ref m_vertices, vertexIdx); System.Array.Resize(ref m_colors, vertexIdx); System.Array.Resize(ref m_uv, vertexIdx); System.Array.Resize(ref m_triangles, triangleIdx); }
// Update is called once per frame void Update() { if (m_curNode != null) { MapTileNode curTileNode = m_curNode.Value as MapTileNode; AutoTileMap.AutoTile autoTile = RpgMapHelper.GetAutoTileByPosition(transform.position, 0); if ( (autoTile.TileX != curTileNode.TileX || autoTile.TileY != curTileNode.TileY) || GetDistToTarget(autoTile) > MinDistToMoveNextTarget // wait until min dist is reached ) { Vector3 vSeek = curTileNode.Position; vSeek.z = transform.position.z; // put at this object level if (m_movingBehavior) { if (m_curNode.Next != null) { m_movingBehavior.Seek(vSeek); } else { m_movingBehavior.Arrive(vSeek); } } } else { m_curNode = m_curNode.Next; } } //if (TargetPos != null) //TODO: TargetPos can't be null { int prevTileidx = m_startTileIdx; m_startTileIdx = RpgMapHelper.GetTileIdxByPosition(TargetPos); m_isUpdatePath |= prevTileidx != m_startTileIdx; if (m_isUpdatePath || !m_isComputing) { m_isUpdatePath = false; m_endTileIdx = RpgMapHelper.GetTileIdxByPosition(transform.position); //now = Time.realtimeSinceStartup; StopCoroutine("ComputePath"); StartCoroutine("ComputePath"); } } //+++ Debug for (LinkedListNode <IPathNode> it = Path.First; it != null; it = it.Next) { MapTileNode mapTileNode0 = it.Value as MapTileNode; if (it.Next != null) { MapTileNode mapTileNode1 = it.Next.Value as MapTileNode; Vector3 v0 = mapTileNode0.Position; Vector3 v1 = mapTileNode1.Position; v0.z = transform.position.z; v1.z = transform.position.z; Debug.DrawLine(v0, v1, Color.red); } } //--- }