private void PlaceNewTile(ushort tileType, MapId mapId, Vector2 position) { // tile can snap up to 0.75m away from grid var gridSearchBox = new Box2(-0.5f, -0.5f, 0.5f, 0.5f) .Scale(1.5f) .Translated(position); var gridsInArea = _mapManager.FindGridsIntersecting(mapId, gridSearchBox); IMapGrid closest = null; float distance = float.PositiveInfinity; Box2 intersect = new Box2(); foreach (var grid in gridsInArea) { // figure out closest intersect var gridIntersect = gridSearchBox.Intersect(grid.WorldBounds); var gridDist = (gridIntersect.Center - position).LengthSquared; if (gridDist >= distance) { continue; } distance = gridDist; closest = grid; intersect = gridIntersect; } if (closest != null) // stick to existing grid { // round to nearest cardinal dir var normal = new Angle(position - intersect.Center).GetCardinalDir().ToVec(); // round coords to center of tile var tileIndices = closest.WorldToTile(intersect.Center); var tileCenterWorld = closest.GridTileToWorldPos(tileIndices); // move mouse one tile out along normal var newTilePos = tileCenterWorld + normal * closest.TileSize; // you can always remove a tile if (Tile.Empty.TypeId != tileType) { var tileBounds = Box2.UnitCentered.Scale(closest.TileSize).Translated(newTilePos); var collideCount = _mapManager.FindGridsIntersecting(mapId, tileBounds).Count(); // prevent placing a tile if it overlaps more than one grid if (collideCount > 1) { return; } } var pos = closest.WorldToTile(position); closest.SetTile(pos, new Tile(tileType)); } else // create a new grid { var newGrid = _mapManager.CreateGrid(mapId); newGrid.WorldPosition = position + (newGrid.TileSize / 2f); // assume bottom left tile origin var tilePos = newGrid.WorldToTile(position); newGrid.SetTile(tilePos, new Tile(tileType)); } }