cleaned up comments

This commit is contained in:
Grimsace
2026-02-18 15:26:29 -06:00
parent 710c05f716
commit 266b93639c
7 changed files with 91 additions and 278 deletions
+17 -42
View File
@@ -11,20 +11,20 @@ import (
"unsafe"
)
// PointOfInterest represents a location on the map where roads may start, end, or intersect.
// PointOfInterest represents a location where roads may start, end, or intersect
type PointOfInterest struct {
X, Y int
Connections int
IsExit bool
}
// PathPoint represents a single point in a road's path, with a flag to indicate if it's a bridge.
// PathPoint represents a single point in a road's path with bridge flag
type PathPoint struct {
Point image.Point
IsBridge bool
}
// Road represents a connection between two Points of Interest.
// Road represents a connection between two Points of Interest
type Road struct {
Start, End *PointOfInterest
Width int
@@ -32,9 +32,8 @@ type Road struct {
Importance int
}
// GenerateRoads is the main function for creating roads on the map.
// GenerateRoads creates roads on the map
func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image, allWaterPixels []image.Point, seed int64) ([]image.Point, []image.Point, *image.RGBA) {
// Step 1: Initialize a transparent image for drawing roads
img := image.NewRGBA(image.Rect(0, 0, width, height))
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
@@ -42,23 +41,18 @@ func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image,
}
}
// Step 2: Set up random number generator and colors
randSrc := rand.New(rand.NewSource(seed))
roadColor := color.RGBA{R: 139, G: 69, B: 19, A: 255}
bridgeColor := color.RGBA{R: 60, G: 42, B: 33, A: 255}
// Step 3: Generate Points of Interest (POIs)
pois := generatePOIs(width, height, settings, allWaterPixels, randSrc)
if len(pois) == 0 {
return nil, nil, img
}
// Step 4: Connect POIs to form roads
roads := connectPOIs(pois, width, height, settings, randSrc, allWaterPixels)
// Step 5: Assign widths to the roads based on their importance
assignRoadWidths(roads, settings)
// Step 6: Draw the roads on the image
var allRoadPixels []image.Point
var allBridgePixels []image.Point
for _, road := range roads {
@@ -70,7 +64,7 @@ func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image,
return allRoadPixels, allBridgePixels, img
}
// generatePOIs creates the initial set of points where roads will originate.
// generatePOIs creates initial points where roads will originate
func generatePOIs(width, height int, settings *Settings, allWaterPixels []image.Point, randSrc *rand.Rand) []*PointOfInterest {
numPOIs := settings.NumRoads / 2
if numPOIs == 0 {
@@ -91,33 +85,30 @@ func generatePOIs(width, height int, settings *Settings, allWaterPixels []image.
centerX := width / 2
centerY := height / 2
// Distribution affects the radius of POI generation
maxRadius := math.Min(float64(width)/2, float64(height)/2)
radius := maxRadius * (settings.RoadDistribution / 100.0)
for i := 0; i < numPOIs; i++ {
var x, y int
found := false
for j := 0; j < 100; j++ { // Retries to find a land spot
for j := 0; j < 100; j++ {
if i < numExits {
// Create POIs at the map edges
side := randSrc.Intn(4)
switch side {
case 0: // Top
case 0:
x = randSrc.Intn(width)
y = 0
case 1: // Bottom
case 1:
x = randSrc.Intn(width)
y = height - 1
case 2: // Left
case 2:
x = 0
y = randSrc.Intn(height)
case 3: // Right
case 3:
x = width - 1
y = randSrc.Intn(height)
}
} else {
// Create POIs within the map
angle := randSrc.Float64() * 2 * math.Pi
r := math.Sqrt(randSrc.Float64()) * radius
x = int(float64(centerX) + r*math.Cos(angle))
@@ -138,7 +129,7 @@ func generatePOIs(width, height int, settings *Settings, allWaterPixels []image.
return pois
}
// connectPOIs creates roads by connecting the generated Points of Interest.
// connectPOIs creates roads by connecting Points of Interest
func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings, randSrc *rand.Rand, allWaterPixels []image.Point) []*Road {
if len(pois) < 2 {
return nil
@@ -151,7 +142,6 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings,
visited := make(map[*PointOfInterest]bool)
existingRoads := make(map[string]bool)
// Find the center-most POI to start connecting from
centerX := width / 2
centerY := height / 2
var startNode *PointOfInterest
@@ -174,11 +164,9 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings,
visited[startNode] = true
// Use average dimension for controlling road path calculation
avgDim := float64(width+height) / 2.0
numControlPoints := max(int(avgDim*0.03), 60)
// Connect all POIs using a minimum spanning tree-like algorithm
for len(visited) < len(pois) {
var closest *PointOfInterest
var fromNode *PointOfInterest
@@ -192,7 +180,6 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings,
if !visited[other] {
dist := math.Sqrt(math.Pow(float64(poi.X-other.X), 2) + math.Pow(float64(poi.Y-other.Y), 2))
// Check if a road already exists between these two POIs
key := fmt.Sprintf("%p-%p", poi, other)
if uintptr(unsafe.Pointer(poi)) > uintptr(unsafe.Pointer(other)) {
key = fmt.Sprintf("%p-%p", other, poi)
@@ -201,7 +188,6 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings,
continue
}
// Avoid connecting two exit points directly
if poi.IsExit && other.IsExit {
continue
}
@@ -220,7 +206,6 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings,
fromNode.Connections++
closest.Connections++
// Add road to existing roads map to prevent duplicates
key := fmt.Sprintf("%p-%p", fromNode, closest)
if uintptr(unsafe.Pointer(fromNode)) > uintptr(unsafe.Pointer(closest)) {
key = fmt.Sprintf("%p-%p", closest, fromNode)
@@ -238,7 +223,6 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings,
}
}(fromNode, closest)
} else {
// No more reachable POIs, break the loop
break
}
}
@@ -252,7 +236,6 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings,
roads = append(roads, road)
}
// Calculate road importance based on the number of connections at its endpoints
for _, road := range roads {
road.Importance = road.Start.Connections + road.End.Connections
}
@@ -260,13 +243,12 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings,
return roads
}
// assignRoadWidths sets the width of each road based on its importance.
// assignRoadWidths sets road width based on importance
func assignRoadWidths(roads []*Road, settings *Settings) {
if len(roads) == 0 {
return
}
// Sort roads by importance in descending order
sort.Slice(roads, func(i, j int) bool {
return roads[i].Importance > roads[j].Importance
})
@@ -278,13 +260,12 @@ func assignRoadWidths(roads []*Road, settings *Settings) {
widthStep = (maxWidth - minWidth) / float64(len(roads)-1)
}
// Assign widths, with more important roads being wider
for i, road := range roads {
road.Width = int(maxWidth - float64(i)*widthStep)
}
}
// drawRoad draws a single road on the image, including bridges.
// drawRoad draws a single road on the image including bridges
func drawRoad(img *image.RGBA, points []PathPoint, roadColor, bridgeColor color.Color, width int) ([]image.Point, []image.Point) {
var roadPixels []image.Point
var bridgePixels []image.Point
@@ -306,7 +287,7 @@ func drawRoad(img *image.RGBA, points []PathPoint, roadColor, bridgeColor color.
return roadPixels, bridgePixels
}
// bresenhamRoad uses Bresenham's line algorithm to create a path between control points.
// bresenhamRoad creates a path between control points using Bresenham's algorithm
func bresenhamRoad(path []image.Point) []image.Point {
if len(path) < 2 {
return path
@@ -346,7 +327,7 @@ func bresenhamRoad(path []image.Point) []image.Point {
return fullPath
}
// calculateRoadPath computes the path for a road, including curves and bridges.
// calculateRoadPath computes the path for a road including curves and bridges
func calculateRoadPath(start, end *PointOfInterest, curvyness, avgDim float64, randSrc *rand.Rand, numControlPoints int, allWaterPixels []image.Point) []PathPoint {
dx := end.X - start.X
dy := end.Y - start.Y
@@ -361,7 +342,6 @@ func calculateRoadPath(start, end *PointOfInterest, curvyness, avgDim float64, r
return []PathPoint{{Point: image.Point{X: start.X, Y: start.Y}, IsBridge: waterMap[image.Point{X: start.X, Y: start.Y}]}}
}
// Adjust curviness based on the distance between the POIs
distanceFactor := math.Min(1.0, dist/(avgDim*0.5))
adjustedCurvyness := curvyness * distanceFactor
@@ -374,7 +354,6 @@ func calculateRoadPath(start, end *PointOfInterest, curvyness, avgDim float64, r
return pathPoints
}
// Use sine waves to create curves in the road
type wave struct {
amplitude float64
numWaves float64
@@ -389,21 +368,18 @@ func calculateRoadPath(start, end *PointOfInterest, curvyness, avgDim float64, r
}
baseNumWaves := (dist / mainWavelength) * adjustedCurvyness
// Main wave for overall curve
waves[0] = wave{
amplitude: amp,
numWaves: baseNumWaves * (0.75 + randSrc.Float64()*0.5),
phase: randSrc.Float64() * 2 * math.Pi,
}
// Smaller wave for minor detours and a more natural look
waves[1] = wave{
amplitude: amp / 4,
numWaves: baseNumWaves * 4 * (0.75 + randSrc.Float64()*0.5),
phase: randSrc.Float64() * 2 * math.Pi,
}
// Generate control points for the curve
controlPoints := make([]image.Point, numControlPoints+1)
for i := 0; i <= numControlPoints; i++ {
t := float64(i) / float64(numControlPoints)
@@ -426,7 +402,6 @@ func calculateRoadPath(start, end *PointOfInterest, curvyness, avgDim float64, r
controlPoints[i] = image.Point{X: int(math.Round(x)), Y: int(math.Round(y))}
}
// Create the final path using Bresenham's algorithm between control points
points := bresenhamRoad(controlPoints)
pathPoints := make([]PathPoint, len(points))
for i, p := range points {
@@ -435,7 +410,7 @@ func calculateRoadPath(start, end *PointOfInterest, curvyness, avgDim float64, r
return pathPoints
}
// drawLine draws a line with a specified width on the image.
// drawLine draws a line with specified width on the image
func drawLine(img *image.RGBA, x0, y0, x1, y1 int, col color.Color, width int) []image.Point {
var points []image.Point
dx := abs(x1 - x0)
@@ -478,7 +453,7 @@ func drawLine(img *image.RGBA, x0, y0, x1, y1 int, col color.Color, width int) [
return points
}
// abs returns the absolute value of an integer.
// abs returns the absolute value of an integer
func abs(x int) int {
if x < 0 {
return -x