5.4 C
New York
Saturday, March 15, 2025

c# – Isometric tilemap stairs and ramps


I am attempting to implement a multi-elevation tilemap in Godot, nevertheless I am can not appear to resolve an issue associated to stairs/ramps. These tiles appear to take up multiple tile area (about 4) and I can not discover a method to constantly map the mouse place to thei actual coordinates. This can even have an effect on my path discovering, as I might count on the steps to be neighbours to my common flat tiles.

I am utilizing Tile Map Layers.

TileSet settings:

  • Tile Form: Isometric
  • Tile Structure: Diamond Down
  • Tile Offset Axis: Vertical Offset
  • Tile Dimension: 32px – 16px

Here is my code:

public partial class MapManager : Node
{
    non-public const int TileWidth = 32;
    non-public const int TileHeight = 32;
    
    non-public readonly Dictionary _tilemaps = new();
    non-public readonly Dictionary _elevations = new();
    
    non-public readonly Dictionary _coordinatesToPoints = new();
    non-public readonly Dictionary _pointsToCoordinates = new();
    
    non-public readonly Vector2 _tileSize = new(TileWidth, TileHeight);
    non-public readonly AStar3D _astar = new();

    public override void _Ready()
    {
        SetupTilemaps();
        SetupAStar();
    }
    
    public override void _Process(double delta)
    {
        
        var tile = GetHoveredTile();

        if (tile != null)
        {
            var tilemap = _tilemaps[tile.Value.Z];
            var knowledge = tilemap.GetCellTileData(tile.Worth.ToVector2I());

            GD.Print((string)knowledge.GetCustomData("tile-name"));
        }
    }
    
    non-public Vector3I[] GetNeighbours(Vector3I level)
        => _astar.GetPointConnections(_coordinatesToPoints[point]).Choose(p => _pointsToCoordinates[p]).ToArray();
    
    non-public lengthy CoordsToId(Vector3I coords) 
        => _coordinatesToPoints[coords];

    non-public Vector3I IdToCoords(int id)
        => _pointsToCoordinateshttps://gamedev.stackexchange.com/q/212964;

    non-public void SetupTilemaps()
    {
        var tilemaps = this.GetChildrenOfType();
        var elevation = 0;

        foreach (var tilemap in tilemaps.Reverse())
        {
            _tilemaps[elevation--] = tilemap;
        }
    }

    non-public void SetupAStar()
    {
        _astar.Clear();
        
        foreach (var (elevation, tilemap) in _tilemaps)
        {
            foreach (var coords in tilemap.GetUsedCells())
            {
                var coords3D = new Vector3I(coords.X, coords.Y, elevation);
                var id = _astar.GetAvailablePointId();
                
                _coordinatesToPoints[coords3D] = id;
                _pointsToCoordinateshttps://gamedev.stackexchange.com/q/212964 = coords3D;

                _elevations[coords3D] = elevation;
                _astar.AddPoint(id, coords3D);
            }
        }
        
        foreach (var (elevation, tilemap) in _tilemaps)
        {
            foreach (var coords in tilemap.GetUsedCells())
            {
                ConnectNeighbors(new Vector3I(coords.X, coords.Y, elevation));
            }
        }
    }

    non-public void ConnectNeighbors(Vector3I coords)
    {
        var coords2d = new Vector2I(coords.X, coords.Y);
        var currentId = CoordsToId(coords);

        Vector3I[] neighbors = {
            // Identical elevation
            new(1, 0, 0), new(-1, 0, 0),
            new(0, 1, 0), new(0, -1, 0),
            
            // Beneath
            new(1, 0, -1), new(-1, 0, -1),
            new(0, 1, -1), new(0, -1, -1)
        };
        
        foreach (var offset in neighbors)
        {
            var neighborCoords = coords + offset;

            if (!_tilemaps.TryGetValue(neighborCoords.Z, out var tilemap))
            {
                proceed;
            }
            
            var neighbourCellId = tilemap.GetCellSourceId(new Vector2I(coords2d.X + offset.X, coords2d.Y + offset.Y));
            
            if (neighbourCellId == -1)
            {
                proceed;
            }

            if (IsValidConnection(coords, neighborCoords))
            {
                _astar.ConnectPoints(currentId, CoordsToId(neighborCoords), false);
            }
        }
    }
    
    non-public bool IsValidConnection(Vector3I currentCoords, Vector3I potentialNeighborCoords)
    {
        return true;
    }

    public Vector3I? GetHoveredTile()
    {
        // PROBLEM HERE
        
        foreach (var (elevation, tilemap) in _tilemaps)
        {
            var tileCoords = tilemap.LocalToMap(tilemap.GetLocalMousePosition());
            
            if (tilemap.CellExistsAtCoordinates(tileCoords))
            {
                return new Vector3I(tileCoords.X, tileCoords.Y, elevation);
            }
        }
        
        return null;
    }

    public Vector3[] FindAStarPath(Vector3I begin, Vector3I aim)
    {
        var startId = CoordsToId(begin);
        var goalId = CoordsToId(aim);

        if (!_astar.HasPoint(startId) || !_astar.HasPoint(goalId))
        {
            GD.PrintErr("No factors discovered for begin/aim");
            return Array.Empty();
        }
        
        return _astar.GetPointPath(startId, goalId);
    }
}

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles