dartterm/lib/game/sitemode/fov.dart
2023-09-22 21:08:03 -07:00

82 lines
2.0 KiB
Dart

part of 'sitemode.dart';
const double fovMaxMovementCost = 10.0;
const double fovMaxMemoryDistance = 80.0;
extension FOVParts on SiteMode {
void fovMaintain() {
fovVisible = {};
shadowcast(playerPosition, _fovIsBlocking, (xy) => fovVisible.add(xy));
var oldFovMemory = fovMemory;
fovMemory = {};
oldFovMemory.addAll(fovVisible);
for (var xy in oldFovMemory) {
if (_fovMemorablyClose(xy)) {
fovMemory.add(xy);
}
}
fovMovable = {};
for (var r in dijkstra<geo.Offset>(playerPosition, _fovDijkstraNeighbors)) {
if (r.cost > fovMaxMovementCost) {
break;
}
fovMovable.add(r.item);
}
}
bool _fovMemorablyClose(geo.Offset other) {
var dx = (other.x - playerPosition.x).toDouble();
var dy = (other.y - playerPosition.y).toDouble();
return math.sqrt(dx * dx + dy * dy) < fovMaxMemoryDistance;
}
bool _fovKnown(geo.Offset other) {
return fovVisible.contains(other) || fovMemory.contains(other);
}
bool _fovIsBlocking(geo.Offset xy) {
switch (level.tiles.get(xy.x, xy.y)) {
case null:
return true;
case LevelTile.exit:
return true;
case LevelTile.openDoor:
case LevelTile.floor:
return false;
case LevelTile.wall:
return true;
case LevelTile.closedDoor:
return true;
}
}
Iterable<Edge<geo.Offset>> _fovDijkstraNeighbors(geo.Offset xy) sync* {
var tile = level.tiles.get(xy.x, xy.y);
if (tile == LevelTile.exit || tile == LevelTile.closedDoor) {
// can't go anywhere after this
return;
}
for (var (dx, dy) in [(-1, 0), (1, 0), (0, -1), (0, 1)]) {
var xy2 = geo.Offset(xy.x + dx, xy.y + dy);
// Only return visible or remembered tiles
if (!_fovKnown(xy2)) {
continue;
}
var tile = level.tiles.get(xy2.x, xy2.y);
if (tile == LevelTile.wall) {
continue;
}
// for now, because exiting isn't implemented
if (tile == LevelTile.exit) {
continue;
}
yield Edge(1.0, xy2);
}
}
}