fixed rng

This commit is contained in:
Grimsace
2026-02-04 15:15:47 -06:00
parent 165a5f86f0
commit b3dc2d1258
3 changed files with 43 additions and 25 deletions
+12 -11
View File
@@ -110,16 +110,16 @@ func main() {
if canvasImg.Image == nil || heightmapImg.Image == nil { if canvasImg.Image == nil || heightmapImg.Image == nil {
// Initial image generation // Initial image generation
seedProvider := NewSeedProvider(settings.Seed)
noiseImg := GenerateHeightmap(settings.Width, settings.Height, int(settings.Detail), 100.0, settings.Seed) noiseImg := GenerateHeightmap(settings.Width, settings.Height, int(settings.Detail), 100.0, seedProvider.Next())
var lakeImage image.Image var lakeImage image.Image
lakeImage, lakes = GenerateLakes(settings.Width, settings.Height, settings.Lakes, settings.LakeSizeLower, settings.LakeSizeUpper, noiseImg, settings.Seed) lakeImage, lakes = GenerateLakes(settings.Width, settings.Height, settings.Lakes, settings.LakeSizeLower, settings.LakeSizeUpper, noiseImg, seedProvider.Next())
var riverImage image.Image var riverImage image.Image
riverImage, riverPixels = GenerateRivers(settings.Width, settings.Height, settings.Rivers, settings.MinRiverWidth, settings.MaxRiverWidth, settings.RiverCurvyness, lakeImage, lakes, settings.Seed, noiseImg) riverImage, riverPixels = GenerateRivers(settings.Width, settings.Height, settings.Rivers, settings.MinRiverWidth, settings.MaxRiverWidth, settings.RiverCurvyness, lakeImage, lakes, seedProvider.Next(), noiseImg)
finalImage := riverImage.(*image.RGBA) finalImage := riverImage.(*image.RGBA)
@@ -134,7 +134,7 @@ func main() {
} }
allWaterPixels := append(flatLakePixels, riverPixels...) allWaterPixels := append(flatLakePixels, riverPixels...)
roadPixels, roadImage = GenerateRoads(settings.Width, settings.Height, settings, noiseImg, allWaterPixels) roadPixels, roadImage = GenerateRoads(settings.Width, settings.Height, settings, noiseImg, allWaterPixels, seedProvider.Next())
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()
@@ -144,7 +144,7 @@ func main() {
} }
} }
treePixels = GenerateTrees(finalImage, allWaterPixels, roadPixels, settings.MinTreeSize, settings.MaxTreeSize, settings.TreeCoverage, settings.TreeClumpiness, settings.Seed) treePixels = GenerateTrees(finalImage, allWaterPixels, roadPixels, settings.MinTreeSize, settings.MaxTreeSize, settings.TreeCoverage, settings.TreeClumpiness, seedProvider.Next())
darkenedHeightmap := DarkenLakeAreas(noiseImg, allWaterPixels) darkenedHeightmap := DarkenLakeAreas(noiseImg, allWaterPixels)
@@ -378,13 +378,14 @@ func main() {
steps := 8 steps := 8
currentStep := 0 currentStep := 0
seedProvider := NewSeedProvider(settings.Seed)
// Step 1: Generating Heightmap // Step 1: Generating Heightmap
currentStep++ currentStep++
fyne.Do(func() { fyne.Do(func() {
progressBar.SetText(fmt.Sprintf("Step %d/%d: Generating Heightmap", currentStep, steps)) progressBar.SetText(fmt.Sprintf("Step %d/%d: Generating Heightmap", currentStep, steps))
progressBar.SetValue(float64(currentStep) / float64(steps)) progressBar.SetValue(float64(currentStep) / float64(steps))
}) })
noiseImg := GenerateHeightmap(settings.Width, settings.Height, int(settings.Detail), 100.0, settings.Seed) noiseImg := GenerateHeightmap(settings.Width, settings.Height, int(settings.Detail), 100.0, seedProvider.Next())
// Step 2: Generating Lakes // Step 2: Generating Lakes
currentStep++ currentStep++
@@ -393,7 +394,7 @@ func main() {
progressBar.SetValue(float64(currentStep) / float64(steps)) progressBar.SetValue(float64(currentStep) / float64(steps))
}) })
var lakeImage image.Image var lakeImage image.Image
lakeImage, lakes = GenerateLakes(settings.Width, settings.Height, settings.Lakes, settings.LakeSizeLower, settings.LakeSizeUpper, noiseImg, settings.Seed) lakeImage, lakes = GenerateLakes(settings.Width, settings.Height, settings.Lakes, settings.LakeSizeLower, settings.LakeSizeUpper, noiseImg, seedProvider.Next())
// Step 3: Generating Rivers // Step 3: Generating Rivers
currentStep++ currentStep++
@@ -402,7 +403,7 @@ func main() {
progressBar.SetValue(float64(currentStep) / float64(steps)) progressBar.SetValue(float64(currentStep) / float64(steps))
}) })
var riverImage image.Image var riverImage image.Image
riverImage, riverPixels = GenerateRivers(settings.Width, settings.Height, settings.Rivers, settings.MinRiverWidth, settings.MaxRiverWidth, settings.RiverCurvyness, lakeImage, lakes, settings.Seed, noiseImg) riverImage, riverPixels = GenerateRivers(settings.Width, settings.Height, settings.Rivers, settings.MinRiverWidth, settings.MaxRiverWidth, settings.RiverCurvyness, lakeImage, lakes, seedProvider.Next(), noiseImg)
finalImage := riverImage.(*image.RGBA) finalImage := riverImage.(*image.RGBA)
@@ -419,7 +420,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, allWaterPixels) // Draw roadImage over finalImage roadPixels, roadImage = GenerateRoads(settings.Width, settings.Height, settings, noiseImg, allWaterPixels, seedProvider.Next()) // 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()
@@ -451,7 +452,7 @@ func main() {
progressBar.SetText(fmt.Sprintf("Step %d/%d: Generating Trees", currentStep, steps)) progressBar.SetText(fmt.Sprintf("Step %d/%d: Generating Trees", currentStep, steps))
progressBar.SetValue(float64(currentStep) / float64(steps)) progressBar.SetValue(float64(currentStep) / float64(steps))
}) })
treePixels = GenerateTrees(finalImage, allWaterPixels, roadPixels, settings.MinTreeSize, settings.MaxTreeSize, settings.TreeCoverage, settings.TreeClumpiness, settings.Seed) treePixels = GenerateTrees(finalImage, allWaterPixels, roadPixels, settings.MinTreeSize, settings.MaxTreeSize, settings.TreeCoverage, settings.TreeClumpiness, seedProvider.Next())
// Step 8: Finalizing Images // Step 8: Finalizing Images
currentStep++ currentStep++
+14 -14
View File
@@ -22,7 +22,7 @@ type Road struct {
Importance int Importance int
} }
func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image, allWaterPixels []image.Point) ([]image.Point, *image.RGBA) { func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image, allWaterPixels []image.Point, seed int64) ([]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++ {
@@ -31,15 +31,15 @@ func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image,
} }
} }
rand.Seed(settings.Seed) randSrc := rand.New(rand.NewSource(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, allWaterPixels) pois := generatePOIs(width, height, settings, allWaterPixels, randSrc)
if len(pois) == 0 { if len(pois) == 0 {
return nil, img return nil, img
} }
roads := connectPOIs(pois, width, height, settings) roads := connectPOIs(pois, width, height, settings, randSrc)
assignRoadWidths(roads, settings) assignRoadWidths(roads, settings)
var allRoadPixels []image.Point var allRoadPixels []image.Point
@@ -51,7 +51,7 @@ func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image,
return allRoadPixels, img return allRoadPixels, img
} }
func generatePOIs(width, height int, settings *Settings, allWaterPixels []image.Point) []*PointOfInterest { func generatePOIs(width, height int, settings *Settings, allWaterPixels []image.Point, randSrc *rand.Rand) []*PointOfInterest {
numPOIs := settings.NumRoads / 2 numPOIs := settings.NumRoads / 2
if numPOIs == 0 { if numPOIs == 0 {
return nil return nil
@@ -80,24 +80,24 @@ func generatePOIs(width, height int, settings *Settings, allWaterPixels []image.
found := false found := false
for j := 0; j < 100; j++ { // 100 retries to find a land spot for j := 0; j < 100; j++ { // 100 retries to find a land spot
if i < numExits { if i < numExits {
side := rand.Intn(4) side := randSrc.Intn(4)
switch side { switch side {
case 0: // Top case 0: // Top
x = rand.Intn(width) x = randSrc.Intn(width)
y = 0 y = 0
case 1: // Bottom case 1: // Bottom
x = rand.Intn(width) x = randSrc.Intn(width)
y = height - 1 y = height - 1
case 2: // Left case 2: // Left
x = 0 x = 0
y = rand.Intn(height) y = randSrc.Intn(height)
case 3: // Right case 3: // Right
x = width - 1 x = width - 1
y = rand.Intn(height) y = randSrc.Intn(height)
} }
} else { } else {
angle := rand.Float64() * 2 * math.Pi angle := randSrc.Float64() * 2 * math.Pi
r := rand.Float64() * radius r := randSrc.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))
} }
@@ -115,7 +115,7 @@ func generatePOIs(width, height int, settings *Settings, allWaterPixels []image.
return pois return pois
} }
func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings) []*Road { func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings, randSrc *rand.Rand) []*Road {
if len(pois) < 2 { if len(pois) < 2 {
return nil return nil
} }
@@ -194,7 +194,7 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings)
midX := (fromNode.X + closest.X) / 2 midX := (fromNode.X + closest.X) / 2
midY := (fromNode.Y + closest.Y) / 2 midY := (fromNode.Y + closest.Y) / 2
dist := math.Sqrt(math.Pow(float64(fromNode.X-closest.X), 2) + math.Pow(float64(fromNode.Y-closest.Y), 2)) dist := math.Sqrt(math.Pow(float64(fromNode.X-closest.X), 2) + math.Pow(float64(fromNode.Y-closest.Y), 2))
offset := dist * (settings.RoadCurvyness / 100.0) * (rand.Float64() - 0.5) offset := dist * (settings.RoadCurvyness / 100.0) * (randSrc.Float64() - 0.5)
controlX := int(float64(midX) + offset) controlX := int(float64(midX) + offset)
controlY := int(float64(midY) + offset) controlY := int(float64(midY) + offset)
+17
View File
@@ -0,0 +1,17 @@
package main
import "math/rand"
type SeedProvider struct {
rand *rand.Rand
}
func NewSeedProvider(seed int64) *SeedProvider {
return &SeedProvider{
rand: rand.New(rand.NewSource(seed)),
}
}
func (sp *SeedProvider) Next() int64 {
return sp.rand.Int63()
}