Разработать навигатор для игры? Смотрите! (часть 3.4)

14561 узел и 18612 ребер, или как карта стала road_graph.json

Когда маска очищена и превращена в скелет, начинается сборка графа. Граф - это не просто набор точек. Это сеть дорог, по которой можно искать путь. В итоговом `road_graph.json` получилось 14561 узел и 18612 ребер. Шаг сжатия скелета - около 6.595 px. У каждого ребра есть длина и стоимость. Стоимость важнее, чем кажется: навигатор должен не просто найти кратчайший путь по пикселям, а предпочитать нормальные дороги и не влюбляться в сомнительные заплатки.

```python COST = { "white": 1.00, "orange": 1.08, "orange_dashed": 2.60, "unknown": 9.50, } def add_edge(a: int, b: int, length: float, cls: str) -> None: edges.append({ "from": nodes[a]["id"], "to": nodes[b]["id"], "length": round(length, 3), "cost": round(length * COST.get(cls, COST["unknown"]), 3), "road_class": cls, }) ```

На бытовом языке это значит так: - белая дорога - почти базовая; - оранжевая магистраль - тоже нормальная; - пунктир - дороже; - неизвестные куски - почти “не надо, но если очень надо”.

Именно на этом этапе маршрут перестал быть линией на экране. За линией на телефоне теперь лежит настоящая дорожная сеть. Когда пользователь выбирает цель, сервер приклеивает старт и финиш к графу, ищет путь и возвращает polyline. Фронтенд уже просто рисует результат. Самое смешное: снаружи это выглядит как “появилась линия”. Внутри - маска, OpenCV, ручной редактор, скелетизация, граф, веса, A* и много мелких решений, о которых никто не должен думать, пока оно работает.

Если вам интересно посмотреть проект целиком - ссылка на мой GitHub в описании профиля.