added bridges
This commit is contained in:
@@ -16,11 +16,16 @@ type PointOfInterest struct {
|
|||||||
IsExit bool
|
IsExit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PathPoint struct {
|
||||||
|
Point image.Point
|
||||||
|
IsBridge bool
|
||||||
|
}
|
||||||
|
|
||||||
type Road struct {
|
type Road struct {
|
||||||
Start, End, Control *PointOfInterest
|
Start, End *PointOfInterest
|
||||||
Width int
|
Width int
|
||||||
Points []image.Point
|
Points []PathPoint
|
||||||
Importance int
|
Importance int
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image, allWaterPixels []image.Point, seed int64) ([]image.Point, *image.RGBA) {
|
func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image, allWaterPixels []image.Point, seed int64) ([]image.Point, *image.RGBA) {
|
||||||
@@ -34,18 +39,19 @@ func GenerateRoads(width, height int, settings *Settings, noiseImg image.Image,
|
|||||||
|
|
||||||
randSrc := rand.New(rand.NewSource(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}
|
||||||
|
bridgeColor := color.RGBA{R: 60, G: 42, B: 33, A: 255}
|
||||||
|
|
||||||
pois := generatePOIs(width, height, settings, allWaterPixels, randSrc)
|
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, randSrc)
|
roads := connectPOIs(pois, width, height, settings, randSrc, allWaterPixels)
|
||||||
assignRoadWidths(roads, settings)
|
assignRoadWidths(roads, settings)
|
||||||
|
|
||||||
var allRoadPixels []image.Point
|
var allRoadPixels []image.Point
|
||||||
for _, road := range roads {
|
for _, road := range roads {
|
||||||
roadPixels := drawRoad(img, road.Points, roadColor, road.Width)
|
roadPixels := drawRoad(img, road.Points, roadColor, bridgeColor, road.Width)
|
||||||
allRoadPixels = append(allRoadPixels, roadPixels...)
|
allRoadPixels = append(allRoadPixels, roadPixels...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +123,7 @@ func generatePOIs(width, height int, settings *Settings, allWaterPixels []image.
|
|||||||
return pois
|
return pois
|
||||||
}
|
}
|
||||||
|
|
||||||
func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings, randSrc *rand.Rand) []*Road {
|
func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings, randSrc *rand.Rand, allWaterPixels []image.Point) []*Road {
|
||||||
if len(pois) < 2 {
|
if len(pois) < 2 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -200,7 +206,7 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings,
|
|||||||
}
|
}
|
||||||
existingRoads[key] = true
|
existingRoads[key] = true
|
||||||
|
|
||||||
path := calculateRoadPath(fromNode, closest, settings.RoadCurvyness/100.0, avgDim, randSrc, numControlPoints)
|
path := calculateRoadPath(fromNode, closest, settings.RoadCurvyness/100.0, avgDim, randSrc, numControlPoints, allWaterPixels)
|
||||||
|
|
||||||
roads = append(roads, &Road{
|
roads = append(roads, &Road{
|
||||||
Start: fromNode,
|
Start: fromNode,
|
||||||
@@ -241,10 +247,16 @@ func assignRoadWidths(roads []*Road, settings *Settings) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawRoad(img *image.RGBA, points []image.Point, col color.Color, width int) []image.Point {
|
func drawRoad(img *image.RGBA, points []PathPoint, roadColor, bridgeColor color.Color, width int) []image.Point {
|
||||||
var roadPixels []image.Point
|
var roadPixels []image.Point
|
||||||
for i := 0; i < len(points)-1; i++ {
|
for i := 0; i < len(points)-1; i++ {
|
||||||
linePoints := drawLine(img, points[i].X, points[i].Y, points[i+1].X, points[i+1].Y, col, width)
|
p1 := points[i]
|
||||||
|
p2 := points[i+1]
|
||||||
|
c := roadColor
|
||||||
|
if p1.IsBridge && p2.IsBridge {
|
||||||
|
c = bridgeColor
|
||||||
|
}
|
||||||
|
linePoints := drawLine(img, p1.Point.X, p1.Point.Y, p2.Point.X, p2.Point.Y, c, width)
|
||||||
roadPixels = append(roadPixels, linePoints...)
|
roadPixels = append(roadPixels, linePoints...)
|
||||||
}
|
}
|
||||||
return roadPixels
|
return roadPixels
|
||||||
@@ -289,13 +301,18 @@ func bresenhamRoad(path []image.Point) []image.Point {
|
|||||||
return fullPath
|
return fullPath
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateRoadPath(start, end *PointOfInterest, curvyness, avgDim float64, randSrc *rand.Rand, numControlPoints int) []image.Point {
|
func calculateRoadPath(start, end *PointOfInterest, curvyness, avgDim float64, randSrc *rand.Rand, numControlPoints int, allWaterPixels []image.Point) []PathPoint {
|
||||||
dx := end.X - start.X
|
dx := end.X - start.X
|
||||||
dy := end.Y - start.Y
|
dy := end.Y - start.Y
|
||||||
dist := math.Sqrt(float64(dx*dx + dy*dy))
|
dist := math.Sqrt(float64(dx*dx + dy*dy))
|
||||||
|
|
||||||
|
waterMap := make(map[image.Point]bool)
|
||||||
|
for _, p := range allWaterPixels {
|
||||||
|
waterMap[p] = true
|
||||||
|
}
|
||||||
|
|
||||||
if dist == 0 {
|
if dist == 0 {
|
||||||
return []image.Point{{X: start.X, Y: start.Y}}
|
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 distance
|
// Adjust curviness based on distance
|
||||||
@@ -303,7 +320,12 @@ func calculateRoadPath(start, end *PointOfInterest, curvyness, avgDim float64, r
|
|||||||
adjustedCurvyness := curvyness * distanceFactor
|
adjustedCurvyness := curvyness * distanceFactor
|
||||||
|
|
||||||
if adjustedCurvyness == 0 {
|
if adjustedCurvyness == 0 {
|
||||||
return bresenhamRoad([]image.Point{{X: start.X, Y: start.Y}, {X: end.X, Y: end.Y}})
|
points := bresenhamRoad([]image.Point{{X: start.X, Y: start.Y}, {X: end.X, Y: end.Y}})
|
||||||
|
pathPoints := make([]PathPoint, len(points))
|
||||||
|
for i, p := range points {
|
||||||
|
pathPoints[i] = PathPoint{Point: p, IsBridge: waterMap[p]}
|
||||||
|
}
|
||||||
|
return pathPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
type wave struct {
|
type wave struct {
|
||||||
@@ -339,20 +361,29 @@ func calculateRoadPath(start, end *PointOfInterest, curvyness, avgDim float64, r
|
|||||||
t := float64(i) / float64(numControlPoints)
|
t := float64(i) / float64(numControlPoints)
|
||||||
x := float64(start.X) + t*float64(dx)
|
x := float64(start.X) + t*float64(dx)
|
||||||
y := float64(start.Y) + t*float64(dy)
|
y := float64(start.Y) + t*float64(dy)
|
||||||
perpX, perpY := -float64(dy)/dist, float64(dx)/dist
|
|
||||||
|
|
||||||
totalOffset := 0.0
|
p := image.Point{X: int(math.Round(x)), Y: int(math.Round(y))}
|
||||||
for _, w := range waves {
|
if !waterMap[p] {
|
||||||
totalOffset += math.Sin(t*w.numWaves*2*math.Pi+w.phase) * w.amplitude
|
perpX, perpY := -float64(dy)/dist, float64(dx)/dist
|
||||||
|
|
||||||
|
totalOffset := 0.0
|
||||||
|
for _, w := range waves {
|
||||||
|
totalOffset += math.Sin(t*w.numWaves*2*math.Pi+w.phase) * w.amplitude
|
||||||
|
}
|
||||||
|
totalOffset *= math.Sin(t * math.Pi)
|
||||||
|
|
||||||
|
x += totalOffset * perpX
|
||||||
|
y += totalOffset * perpY
|
||||||
}
|
}
|
||||||
totalOffset *= math.Sin(t * math.Pi)
|
|
||||||
|
|
||||||
x += totalOffset * perpX
|
|
||||||
y += totalOffset * perpY
|
|
||||||
controlPoints[i] = image.Point{X: int(math.Round(x)), Y: int(math.Round(y))}
|
controlPoints[i] = image.Point{X: int(math.Round(x)), Y: int(math.Round(y))}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bresenhamRoad(controlPoints)
|
points := bresenhamRoad(controlPoints)
|
||||||
|
pathPoints := make([]PathPoint, len(points))
|
||||||
|
for i, p := range points {
|
||||||
|
pathPoints[i] = PathPoint{Point: p, IsBridge: waterMap[p]}
|
||||||
|
}
|
||||||
|
return pathPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bresenham's line algorithm for drawing segments of the curve
|
// Bresenham's line algorithm for drawing segments of the curve
|
||||||
|
|||||||
Reference in New Issue
Block a user