stopped point of interest on water

This commit is contained in:
Grimsace
2026-02-04 14:50:36 -06:00
parent b9173dd1f3
commit a68822ef4e
2 changed files with 72 additions and 58 deletions
+18 -29
View File
@@ -125,26 +125,6 @@ func main() {
var roadImage *image.RGBA var roadImage *image.RGBA
roadPixels, roadImage = GenerateRoads(settings.Width, settings.Height, settings, noiseImg)
// Draw roadImage over finalImage
for y := 0; y < roadImage.Bounds().Max.Y; y++ {
for x := 0; x < roadImage.Bounds().Max.X; x++ {
r, g, b, a := roadImage.At(x, y).RGBA()
if a > 0 {
finalImage.Set(x, y, color.RGBA{R: uint8(r >> 8), G: uint8(g >> 8), B: uint8(b >> 8), A: uint8(a >> 8)})
}
}
}
var flatLakePixels []image.Point var flatLakePixels []image.Point
for _, lake := range lakes { for _, lake := range lakes {
@@ -154,6 +134,15 @@ func main() {
} }
allWaterPixels := append(flatLakePixels, riverPixels...) allWaterPixels := append(flatLakePixels, riverPixels...)
roadPixels, roadImage = GenerateRoads(settings.Width, settings.Height, settings, noiseImg, allWaterPixels)
for y := 0; y < roadImage.Bounds().Max.Y; y++ {
for x := 0; x < roadImage.Bounds().Max.X; x++ {
r, g, b, a := roadImage.At(x, y).RGBA()
if a > 0 {
finalImage.Set(x, y, color.RGBA{R: uint8(r >> 8), G: uint8(g >> 8), B: uint8(b >> 8), A: uint8(a >> 8)})
}
}
}
treePixels = GenerateTrees(finalImage, allWaterPixels, settings.MinTreeSize, settings.MaxTreeSize, settings.TreeCoverage, settings.TreeClumpiness, settings.Seed) treePixels = GenerateTrees(finalImage, allWaterPixels, settings.MinTreeSize, settings.MaxTreeSize, settings.TreeCoverage, settings.TreeClumpiness, settings.Seed)
@@ -299,7 +288,7 @@ func main() {
treeClumpinessSlider.SetValue(settings.TreeClumpiness) treeClumpinessSlider.SetValue(settings.TreeClumpiness)
numRoadsLabel := widget.NewLabel(fmt.Sprintf("Number of Roads: %d", settings.NumRoads)) numRoadsLabel := widget.NewLabel(fmt.Sprintf("Number of Roads: %d", settings.NumRoads))
numRoadsSlider := widget.NewSlider(1, 1000) numRoadsSlider := widget.NewSlider(0, 1000)
numRoadsSlider.OnChanged = func(val float64) { numRoadsSlider.OnChanged = func(val float64) {
settings.NumRoads = int(val) settings.NumRoads = int(val)
numRoadsLabel.SetText(fmt.Sprintf("Number of Roads: %d", settings.NumRoads)) numRoadsLabel.SetText(fmt.Sprintf("Number of Roads: %d", settings.NumRoads))
@@ -332,7 +321,7 @@ func main() {
maxRoadWidthSlider.SetValue(settings.MaxRoadWidth) maxRoadWidthSlider.SetValue(settings.MaxRoadWidth)
roadExitsLabel := widget.NewLabel(fmt.Sprintf("Road Exits: %d", settings.RoadExits)) roadExitsLabel := widget.NewLabel(fmt.Sprintf("Road Exits: %d", settings.RoadExits))
roadExitsSlider := widget.NewSlider(1, 100) roadExitsSlider := widget.NewSlider(0, 100)
roadExitsSlider.OnChanged = func(val float64) { roadExitsSlider.OnChanged = func(val float64) {
if val > float64(settings.NumRoads) { if val > float64(settings.NumRoads) {
val = float64(settings.NumRoads) val = float64(settings.NumRoads)
@@ -417,6 +406,12 @@ func main() {
finalImage := riverImage.(*image.RGBA) finalImage := riverImage.(*image.RGBA)
var flatLakePixels []image.Point
for _, lake := range lakes {
flatLakePixels = append(flatLakePixels, lake...)
}
allWaterPixels := append(flatLakePixels, riverPixels...)
// Step 4: Generating Roads // Step 4: Generating Roads
currentStep++ currentStep++
fyne.Do(func() { fyne.Do(func() {
@@ -424,7 +419,7 @@ func main() {
progressBar.SetValue(float64(currentStep) / float64(steps)) progressBar.SetValue(float64(currentStep) / float64(steps))
}) })
var roadImage *image.RGBA var roadImage *image.RGBA
roadPixels, roadImage = GenerateRoads(settings.Width, settings.Height, settings, noiseImg) // Draw roadImage over finalImage roadPixels, roadImage = GenerateRoads(settings.Width, settings.Height, settings, noiseImg, allWaterPixels) // Draw roadImage over finalImage
for y := 0; y < roadImage.Bounds().Max.Y; y++ { for y := 0; y < roadImage.Bounds().Max.Y; y++ {
for x := 0; x < roadImage.Bounds().Max.X; x++ { for x := 0; x < roadImage.Bounds().Max.X; x++ {
r, g, b, a := roadImage.At(x, y).RGBA() r, g, b, a := roadImage.At(x, y).RGBA()
@@ -434,12 +429,6 @@ func main() {
} }
} }
var flatLakePixels []image.Point
for _, lake := range lakes {
flatLakePixels = append(flatLakePixels, lake...)
}
allWaterPixels := append(flatLakePixels, riverPixels...)
// Step 5: Darkening Water Areas // Step 5: Darkening Water Areas
currentStep++ currentStep++
fyne.Do(func() { fyne.Do(func() {
+38 -13
View File
@@ -22,7 +22,7 @@ type Road struct {
Importance int Importance int
} }
func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image) ([]image.Point, *image.RGBA) { func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image, allWaterPixels []image.Point) ([]image.Point, *image.RGBA) {
img := image.NewRGBA(image.Rect(0, 0, width, height)) img := image.NewRGBA(image.Rect(0, 0, width, height))
// Transparent background // Transparent background
for y := 0; y < height; y++ { for y := 0; y < height; y++ {
@@ -34,7 +34,7 @@ func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image)
rand.Seed(settings.Seed) rand.Seed(settings.Seed)
roadColor := color.RGBA{R: 139, G: 69, B: 19, A: 255} roadColor := color.RGBA{R: 139, G: 69, B: 19, A: 255}
pois := generatePOIs(width, height, settings) pois := generatePOIs(width, height, settings, allWaterPixels)
if len(pois) == 0 { if len(pois) == 0 {
return nil, img return nil, img
} }
@@ -51,18 +51,23 @@ func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image)
return allRoadPixels, img return allRoadPixels, img
} }
func generatePOIs(width, height int, settings *Settings) []*PointOfInterest { func generatePOIs(width, height int, settings *Settings, allWaterPixels []image.Point) []*PointOfInterest {
numPOIs := settings.NumRoads / 2 numPOIs := settings.NumRoads / 2
if numPOIs == 0 { if numPOIs == 0 {
return nil return nil
} }
waterMap := make(map[image.Point]bool)
for _, p := range allWaterPixels {
waterMap[p] = true
}
numExits := settings.RoadExits numExits := settings.RoadExits
if numExits > settings.NumRoads { if numExits > settings.NumRoads {
numExits = settings.NumRoads numExits = settings.NumRoads
} }
pois := make([]*PointOfInterest, numPOIs) pois := make([]*PointOfInterest, 0, numPOIs)
centerX := width / 2 centerX := width / 2
centerY := height / 2 centerY := height / 2
@@ -71,10 +76,11 @@ func generatePOIs(width, height int, settings *Settings) []*PointOfInterest {
radius := maxRadius * (settings.RoadDistribution / 100.0) radius := maxRadius * (settings.RoadDistribution / 100.0)
for i := 0; i < numPOIs; i++ { for i := 0; i < numPOIs; i++ {
// Handle exits var x, y int
found := false
for j := 0; j < 100; j++ { // 100 retries to find a land spot
if i < numExits { if i < numExits {
side := rand.Intn(4) side := rand.Intn(4)
var x, y int
switch side { switch side {
case 0: // Top case 0: // Top
x = rand.Intn(width) x = rand.Intn(width)
@@ -89,15 +95,21 @@ func generatePOIs(width, height int, settings *Settings) []*PointOfInterest {
x = width - 1 x = width - 1
y = rand.Intn(height) y = rand.Intn(height)
} }
pois[i] = &PointOfInterest{X: x, Y: y} } else {
continue
}
angle := rand.Float64() * 2 * math.Pi angle := rand.Float64() * 2 * math.Pi
r := rand.Float64() * radius r := rand.Float64() * radius
x := int(float64(centerX) + r*math.Cos(angle)) x = int(float64(centerX) + r*math.Cos(angle))
y := int(float64(centerY) + r*math.Sin(angle)) y = int(float64(centerY) + r*math.Sin(angle))
pois[i] = &PointOfInterest{X: x, Y: y} }
if !waterMap[image.Point{X: x, Y: y}] {
found = true
break
}
}
if found {
pois = append(pois, &PointOfInterest{X: x, Y: y})
}
} }
return pois return pois
@@ -119,6 +131,9 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings)
minDist := -1.0 minDist := -1.0
for _, poi := range pois { for _, poi := range pois {
if poi == nil {
continue
}
dist := math.Sqrt(math.Pow(float64(poi.X-centerX), 2) + math.Pow(float64(poi.Y-centerY), 2)) dist := math.Sqrt(math.Pow(float64(poi.X-centerX), 2) + math.Pow(float64(poi.Y-centerY), 2))
if startNode == nil || dist < minDist { if startNode == nil || dist < minDist {
minDist = dist minDist = dist
@@ -126,6 +141,10 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings)
} }
} }
if startNode == nil {
return nil
}
visited[startNode] = true visited[startNode] = true
for len(visited) < len(pois) { for len(visited) < len(pois) {
@@ -135,6 +154,9 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings)
for poi := range visited { for poi := range visited {
for _, other := range pois { for _, other := range pois {
if poi == nil || other == nil {
continue
}
if !visited[other] { if !visited[other] {
dist := math.Sqrt(math.Pow(float64(poi.X-other.X), 2) + math.Pow(float64(poi.Y-other.Y), 2)) dist := math.Sqrt(math.Pow(float64(poi.X-other.X), 2) + math.Pow(float64(poi.Y-other.Y), 2))
@@ -182,6 +204,9 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings)
End: closest, End: closest,
Control: &PointOfInterest{X: controlX, Y: controlY}, Control: &PointOfInterest{X: controlX, Y: controlY},
}) })
} else {
// No more reachable POIs
break
} }
} }