ruby-perlin-2D-map-generator 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/town_generator.rb +53 -27
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 25ba5741714e7132250486cdb48c6d0114e858aa272bdb68d90289af12643e3a
|
4
|
+
data.tar.gz: cc4ffc80e85167443d92fbf0755c7a70db4e5ef9cb824e86b98ec83792d82715
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b613588fb06e7bc82af707823e7a1b69b95a3fa670f337577c310bcdcd149b1a58610ae4673ac65b5d7d1415536d9e2c231b9265dbaf3b084060108a45b77e06
|
7
|
+
data.tar.gz: 1d7aaf0819fdf911705d0b18dfc480915a2869bbe994db13d9f91d43a861d14b1a9235f0823ff9d0c4cfb5f08f38267dc39ed49f8ef7544136622f8167069ad8
|
data/README.md
CHANGED
@@ -73,7 +73,7 @@ See Command line Usage for full customization, below are some examples. Alter th
|
|
73
73
|
Roads can be generated by providing a positive integer to the `roads=` argument. Roads are randomly seeded to begin
|
74
74
|
and start at an axis (but not the same axis).
|
75
75
|
|
76
|
-
A* pathfinding with a priority queue is used to generate the roads. The heuristic uses manhattan distance, and favours existing roads and similar elevations in adjacent tiles.
|
76
|
+
A* pathfinding with a priority queue, along with prim's algorithn and a minimum spanning tree is used to generate the roads. The heuristic uses manhattan distance, and favours existing roads and similar elevations in adjacent tiles.
|
77
77
|
|
78
78
|
Roads can be configured to include/exclude generating paths thorugh water, mountains and flora.
|
79
79
|
|
data/lib/town_generator.rb
CHANGED
@@ -8,6 +8,7 @@ require 'map_config'
|
|
8
8
|
#
|
9
9
|
# Generates building tile items using Poisson Disk Sampling for the given tiles
|
10
10
|
# Roads are generated between the buildings and between towns using A* pathfinding
|
11
|
+
# and a minimum tree spanning algorithm
|
11
12
|
#
|
12
13
|
class TownGenerator
|
13
14
|
attr_reader :sample_area, :road_generator
|
@@ -81,25 +82,66 @@ class TownGenerator
|
|
81
82
|
end
|
82
83
|
|
83
84
|
def generate_town_roads(points, town_num, verbose)
|
84
|
-
# TODO: slow, bad (complete graph) will update to use minimum tree spanning algorithm instead
|
85
85
|
puts "generating town #{town_num} roads..." if verbose
|
86
86
|
|
87
|
+
generate_roads_from_connected_pairs(build_minimum_spanning_tree(points, populate_distances_between_each_point(points)))
|
88
|
+
end
|
89
|
+
|
90
|
+
def generate_roads_from_connected_pairs(connected_pairs)
|
91
|
+
connected_pairs.each do |edge|
|
92
|
+
road_to_building_one = place_in_front_or_behind(edge.first)
|
93
|
+
road_to_building_two = place_in_front_or_behind(edge.last)
|
94
|
+
|
95
|
+
next if road_to_building_one.nil? || road_to_building_two.nil?
|
96
|
+
|
97
|
+
road_generator.generate_roads_from_coordinate_list(road_to_building_one.concat(road_to_building_two), false)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def build_minimum_spanning_tree(points, distances)
|
87
102
|
connected_pairs = Set.new
|
103
|
+
visited = Set.new([points.first]) # Create a set to keep track of visited nodes
|
104
|
+
until visited.size == points.size
|
105
|
+
edge = find_minimum_edge(distances, visited)
|
106
|
+
connected_pairs.add(edge)
|
107
|
+
visited.add(edge.last)
|
108
|
+
end
|
109
|
+
connected_pairs
|
110
|
+
end
|
111
|
+
|
112
|
+
def populate_distances_between_each_point(points)
|
113
|
+
distances = {}
|
88
114
|
points.each_with_index do |point_one, idx_one|
|
89
115
|
points[idx_one + 1..].each do |point_two|
|
90
|
-
|
116
|
+
distance = calculate_distance(point_one, point_two)
|
117
|
+
distances[[point_one, point_two]] = distance
|
118
|
+
distances[[point_two, point_one]] = distance
|
119
|
+
end
|
120
|
+
end
|
121
|
+
distances
|
122
|
+
end
|
91
123
|
|
92
|
-
|
93
|
-
|
124
|
+
def calculate_distance(point1, point2)
|
125
|
+
Math.sqrt((point1.y - point2.y)**2 + (point1.x - point2.x)**2)
|
126
|
+
end
|
94
127
|
|
95
|
-
|
96
|
-
|
128
|
+
def find_minimum_edge(distances, visited)
|
129
|
+
# method to find the minimum edge connecting visited and unvisited nodes
|
130
|
+
min_edge = nil
|
131
|
+
min_distance = Float::INFINITY
|
97
132
|
|
98
|
-
|
133
|
+
visited.each do |visited_node|
|
134
|
+
distances.each do |edge, distance|
|
135
|
+
next if visited.include?(edge.last) || edge.first != visited_node
|
99
136
|
|
100
|
-
|
137
|
+
if distance < min_distance
|
138
|
+
min_distance = distance
|
139
|
+
min_edge = edge
|
140
|
+
end
|
101
141
|
end
|
102
142
|
end
|
143
|
+
|
144
|
+
min_edge
|
103
145
|
end
|
104
146
|
|
105
147
|
def place_in_front_or_behind(point)
|
@@ -116,24 +158,8 @@ class TownGenerator
|
|
116
158
|
|
117
159
|
puts 'generating roads between towns...' if verbose
|
118
160
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
@all_town_points.each_with_index do |town_one, idx_one|
|
123
|
-
find_town_centroid(town_one)
|
124
|
-
|
125
|
-
@all_town_points[idx_one + 1..].each do |town_two|
|
126
|
-
next if connected_pairs.include?([town_one, town_two]) || connected_pairs.include?([town_two, town_one])
|
127
|
-
|
128
|
-
town_one_center_x, town_one_center_y = (town_centroids[town_one] ||= find_town_centroid(town_one))
|
129
|
-
town_two_center_x, town_two_center_y = (town_centroids[town_two] ||= find_town_centroid(town_two))
|
130
|
-
|
131
|
-
road_generator.generate_roads_from_coordinate_list([town_one_center_x, town_one_center_y, town_two_center_x, town_two_center_y], false)
|
132
|
-
|
133
|
-
connected_pairs.add([town_one, town_two])
|
134
|
-
connected_pairs.add([town_two, town_one])
|
135
|
-
end
|
136
|
-
end
|
161
|
+
centroids = @all_town_points.map { |town_points| find_town_centroid(town_points) }
|
162
|
+
generate_roads_from_connected_pairs(build_minimum_spanning_tree(centroids, populate_distances_between_each_point(centroids)))
|
137
163
|
end
|
138
164
|
|
139
165
|
def find_town_centroid(points)
|
@@ -149,6 +175,6 @@ class TownGenerator
|
|
149
175
|
average_x = total_x / num_coordinates.to_f
|
150
176
|
average_y = total_y / num_coordinates.to_f
|
151
177
|
|
152
|
-
|
178
|
+
OpenStruct.new(x: average_x, y: average_y)
|
153
179
|
end
|
154
180
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-perlin-2D-map-generator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tyler Matthews (matthewstyler)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: perlin
|
@@ -86,28 +86,28 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 13.0
|
89
|
+
version: 13.1.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 13.0
|
96
|
+
version: 13.1.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rubocop
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 1.
|
103
|
+
version: 1.58.0
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 1.
|
110
|
+
version: 1.58.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: simplecov
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|