82 lines
2.0 KiB
Dart
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);
|
||
|
}
|
||
|
}
|
||
|
}
|