ruby-perlin-2D-map-generator 0.0.4 → 0.0.6

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.
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'poisson_disk_sampling/sampler'
4
+ require 'poisson_disk_sampling/sample_area'
5
+ require 'road_generator'
6
+ require 'map_config'
7
+
8
+ #
9
+ # Generates building tile items using Poisson Disk Sampling for the given tiles
10
+ # Roads are generated between the buildings and between towns using A* pathfinding
11
+ #
12
+ class TownGenerator
13
+ attr_reader :sample_area, :road_generator
14
+
15
+ def initialize(tiles, seed: MapConfig::DEFAULT_TOWN_SEED)
16
+ @sample_area = PoissonDiskSampling::SampleArea.new(grid: tiles)
17
+ @road_generator = RoadGenerator.new(tiles)
18
+ @seed = seed
19
+ @all_town_points = []
20
+ end
21
+
22
+ def generate_random_towns(config)
23
+ return if config.towns <= 0
24
+
25
+ puts "generating #{config.towns} random towns..." if config.verbose
26
+
27
+ @all_town_points.concat(iterate_through_towns(config.towns) do |n|
28
+ generate_random_town(n, config.verbose)
29
+ end)
30
+
31
+ generate_roads_between_towns(config.verbose)
32
+ end
33
+
34
+ def generate_towns_from_coordinate_list(config)
35
+ return unless (config.towns_to_make.length % 4).zero?
36
+
37
+ puts "generating #{config.towns_to_make.length / 4} coordinate towns..." if config.verbose
38
+
39
+ @all_town_points.concat(iterate_through_towns((config.towns_to_make.length / 4)) do |n|
40
+ town_values = config.towns_to_make[(n - 1) * 4..].take(4)
41
+ generate_town(n, town_values[2], town_values[3], [sample_area[town_values[0], town_values[1]]], config.verbose)
42
+ end)
43
+
44
+ generate_roads_between_towns(config.verbose)
45
+ end
46
+
47
+ private
48
+
49
+ def iterate_through_towns(num_of_towns)
50
+ (1..num_of_towns).map do |n|
51
+ town_points = yield n
52
+ @seed += 1000
53
+ town_points
54
+ end
55
+ end
56
+
57
+ def generate_random_town(town_num, verbose)
58
+ random_town_gen = Random.new(@seed)
59
+ generate_town(town_num, random_town_gen.rand(10..40), random_town_gen.rand(2..4), nil, verbose)
60
+ end
61
+
62
+ def generate_town(town_num, num_of_points, radius, initial_coords, verbose)
63
+ puts "generating town #{town_num}..." if verbose
64
+
65
+ points = generate_points_for_town(num_of_points, radius, initial_coords)
66
+ generate_town_roads(points, town_num, verbose)
67
+ points
68
+ end
69
+
70
+ def generate_points_for_town(num_of_points, radius, intial_coordinates)
71
+ points =
72
+ PoissonDiskSampling::Sampler.new(
73
+ sample_area: sample_area,
74
+ seed: @seed
75
+ ).generate_points(num_of_points, radius, intial_coordinates)
76
+ points.each do |point|
77
+ @seed += 1
78
+ point.add_town_item(@seed)
79
+ end
80
+ points
81
+ end
82
+
83
+ def generate_town_roads(points, town_num, verbose)
84
+ # TODO: slow, bad (complete graph) will update to use minimum tree spanning algorithm instead
85
+ puts "generating town #{town_num} roads..." if verbose
86
+
87
+ connected_pairs = Set.new
88
+ points.each_with_index do |point_one, idx_one|
89
+ points[idx_one + 1..].each do |point_two|
90
+ next if connected_pairs.include?([point_one, point_two]) || connected_pairs.include?([point_two, point_one])
91
+
92
+ road_to_building_one = place_in_front_or_behind(point_one)
93
+ road_to_building_two = place_in_front_or_behind(point_two)
94
+
95
+ connected_pairs.add([point_one, point_two])
96
+ connected_pairs.add([point_two, point_one])
97
+
98
+ next if road_to_building_one.nil? || road_to_building_two.nil?
99
+
100
+ road_generator.generate_roads_from_coordinate_list(road_to_building_one.concat(road_to_building_two), false)
101
+ end
102
+ end
103
+ end
104
+
105
+ def place_in_front_or_behind(point)
106
+ return [point.x, point.y - 1] if sample_area.point_within_bounds_and_can_have_road?(point.x, point.y - 1)
107
+ return [point.x, point.y + 1] if sample_area.point_within_bounds_and_can_have_road?(point.x, point.y + 1)
108
+ return [point.x - 1, point.y] if sample_area.point_within_bounds_and_can_have_road?(point.x - 1, point.y)
109
+ return [point.x + 1, point.y] if sample_area.point_within_bounds_and_can_have_road?(point.x + 1, point.y)
110
+
111
+ nil
112
+ end
113
+
114
+ def generate_roads_between_towns(verbose)
115
+ return if @all_town_points.length < 2
116
+
117
+ puts 'generating roads between towns...' if verbose
118
+
119
+ connected_pairs = Set.new
120
+ town_centroids = {}
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
137
+ end
138
+
139
+ def find_town_centroid(points)
140
+ total_x = 0
141
+ total_y = 0
142
+ num_coordinates = points.length
143
+
144
+ points.each do |point|
145
+ total_x += point.x
146
+ total_y += point.y
147
+ end
148
+
149
+ average_x = total_x / num_coordinates.to_f
150
+ average_y = total_y / num_coordinates.to_f
151
+
152
+ [average_x, average_y]
153
+ end
154
+ 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
4
+ version: 0.0.6
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-07-09 00:00:00.000000000 Z
11
+ date: 2023-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: perlin
@@ -58,14 +58,28 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 2.0.4
61
+ version: 2.1.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 2.0.4
68
+ version: 2.1.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.10.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.10.1
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rake
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +100,14 @@ dependencies:
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: 1.54.1
103
+ version: 1.56.0
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: 1.54.1
110
+ version: 1.56.0
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: simplecov
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -108,10 +122,10 @@ dependencies:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
124
  version: 0.22.0
111
- description: A gem that procedurally generates a seeded and customizable 2D map using
112
- perlin noise. Map can be rendered in console using ansi colors or returned as 2D
113
- array of hashes describing each tile and binome. Completelycustomizable, use the
114
- --help option for full usage details.
125
+ description: A gem that procedurally generates a seeded and customizable 2D map with
126
+ optional roads using perlin noise. Map can be rendered in console using ansi colors
127
+ or returned as 2D array of hashes describing each tile and binome. Completely customizable,
128
+ use the --help option for full usage details.
115
129
  email: matthews.tyl@gmail.com
116
130
  executables:
117
131
  - ruby-perlin-2D-map-generator
@@ -124,20 +138,30 @@ files:
124
138
  - lib/CLI/command.rb
125
139
  - lib/ansi_colours.rb
126
140
  - lib/biome.rb
141
+ - lib/building.rb
127
142
  - lib/flora.rb
143
+ - lib/flora_generator.rb
128
144
  - lib/map.rb
129
145
  - lib/map_config.rb
130
146
  - lib/map_tile_generator.rb
147
+ - lib/pathfinding/a_star_finder.rb
148
+ - lib/pathfinding/grid.rb
149
+ - lib/pathfinding/priority_queue.rb
150
+ - lib/poisson_disk_sampling/sample_area.rb
151
+ - lib/poisson_disk_sampling/sampler.rb
152
+ - lib/road_generator.rb
131
153
  - lib/tile.rb
132
154
  - lib/tile_item.rb
133
155
  - lib/tile_perlin_generator.rb
156
+ - lib/town_generator.rb
134
157
  homepage: https://github.com/matthewstyler/ruby-perlin-2D-map-generator
135
158
  licenses:
136
159
  - MIT
137
160
  metadata:
138
161
  source_code_uri: https://github.com/matthewstyler/ruby-perlin-2D-map-generator
139
162
  bug_tracker_uri: https://github.com/matthewstyler/ruby-perlin-2D-map-generator/issues
140
- post_install_message:
163
+ post_install_message: Thanks for installing! Star on github if you found this useful,
164
+ or raise issues and requests.
141
165
  rdoc_options: []
142
166
  require_paths:
143
167
  - lib
@@ -155,6 +179,6 @@ requirements: []
155
179
  rubygems_version: 3.2.3
156
180
  signing_key:
157
181
  specification_version: 4
158
- summary: Procedurally generate seeded and customizable 2D maps, rendered with ansi
159
- colours or described in a 2D array of hashes
182
+ summary: Procedurally generate seeded and customizable 2D maps with optional roads
183
+ and towns, rendered with ansi colours or described in a 2D array of hashes
160
184
  test_files: []