ruby-perlin-2D-map-generator 0.0.2
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +99 -0
- data/bin/ruby-perlin-2D-map-generator +13 -0
- data/lib/CLI/command.rb +277 -0
- data/lib/ansi_colours.rb +31 -0
- data/lib/biome.rb +225 -0
- data/lib/flora.rb +13 -0
- data/lib/map.rb +27 -0
- data/lib/map_config.rb +61 -0
- data/lib/map_tile_generator.rb +69 -0
- data/lib/tile.rb +81 -0
- data/lib/tile_item.rb +22 -0
- data/lib/tile_perlin_generator.rb +46 -0
- metadata +132 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 59f285c1212afff796f6788a429ce6165cd782527330d9a2130f5bf444cae048
|
4
|
+
data.tar.gz: cb54ce932c804c506f26ad66523fa35e8ca37d274b89ab6a345c6a263dff75b0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d9790b03d89b999a94be35a5c0d7aff5a81d844c06a8a52fcfbdd63e4923aee49353e0319d69d1ab108d8b3de0e5a6a8998d396481c7014037a122dd4ed48e6a
|
7
|
+
data.tar.gz: f85761e76b1294b5ff318ddfd14d947f34586f1f4241ee61f42972cfa1f0c21649b288c3e48bb200134ba13338f2e3bb26fa1037d0fcf5e07c6ace87a5828592
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2023 Tyler Matthews
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# Ruby Perlin 2D Map Generator
|
2
|
+
A gem that procedurally generates seeded and customizable 2D map using perlin noise.
|
3
|
+
|
4
|
+
Include the gem in your project, or use the executable from the command line.
|
5
|
+
|
6
|
+
Map can be rendered in console using ansi colors or returned as 2D array of hashes describing each tile and binome. Completely customizable, use the --help option for full usage details.
|
7
|
+
|
8
|
+
|
9
|
+

|
10
|
+
|
11
|
+
# Customization examples
|
12
|
+
|
13
|
+
See Command line Usage for full customization, below are some examples. Alter the temperature, moisture or elevation seeds to alter these maps:
|
14
|
+
|
15
|
+
- Plains with random terrain evens: `ruby-perlin-2D-map-generator render`
|
16
|
+
- Desert (increase temperature, decrease moisture): `ruby-perlin-2D-map-generator render --temp=100 --moisture=-100`
|
17
|
+
- Mountainous with lakes (increase elevation, increase moisture) `ruby-perlin-2D-map-generator render --elevation=25 --moisture=25`
|
18
|
+
- Islands (decreaes elevation, increase moisture): `ruby-perlin-2D-map-generator render --elevation=-40 --moisture=25`
|
19
|
+
- Taiga map (decrease temperature, increase moisture): `ruby-perlin-2D-map-generator render --temp=-60 --moisture=30 `
|
20
|
+
|
21
|
+
## Common customization
|
22
|
+
```bash
|
23
|
+
--width=int The width of the generated map (default 128)
|
24
|
+
--height=int The height of the generated map (default 128)
|
25
|
+
|
26
|
+
--hs=int The seed for a terrains height perlin generation
|
27
|
+
(default 10)
|
28
|
+
--ms=int The seed for a terrains moist perlin generation
|
29
|
+
(default 300)
|
30
|
+
--ts=int The seed for a terrains temperature perlin generation
|
31
|
+
(default 3000)
|
32
|
+
|
33
|
+
--elevation=float Adjust each generated elevation by this percent (0 -
|
34
|
+
100) (default 0.0)
|
35
|
+
--moisture=float Adjust each generated moisture by this percent (0 -
|
36
|
+
100) (default 0.0)
|
37
|
+
--temp=float Adjust each generated temperature by this percent (0
|
38
|
+
- 100) (default 0.0)
|
39
|
+
```
|
40
|
+
|
41
|
+
# Full Command line Usage
|
42
|
+
```bash
|
43
|
+
$ ruby-perlin-2D-map-generator --help
|
44
|
+
```
|
45
|
+
```bash
|
46
|
+
Usage: ruby-perlin-2D-map-generator [OPTIONS] (DESCRIBE | RENDER)
|
47
|
+
|
48
|
+
Generate a seeded customizable procedurally generated 2D map.
|
49
|
+
Rendered in the console using ansi colours, or described as a 2D array of
|
50
|
+
hashes with each tiles information.
|
51
|
+
|
52
|
+
Arguments:
|
53
|
+
(DESCRIBE | RENDER) command to run: render prints the map to standard
|
54
|
+
output using ansi colors, while describe prints each
|
55
|
+
tiles bionome information in the map.
|
56
|
+
|
57
|
+
Options:
|
58
|
+
--elevation=float Adjust each generated elevation by this percent (0 -
|
59
|
+
100) (default 0.0)
|
60
|
+
--fhx=float The frequency for height generation across the x-axis
|
61
|
+
(default 2.5)
|
62
|
+
--fhy=float The frequency for height generation across the y-axis
|
63
|
+
(default 2.5)
|
64
|
+
--fmx=float The frequency for moist generation across the x-axis
|
65
|
+
(default 2.5)
|
66
|
+
--fmy=float The frequency for moist generation across the y-axis
|
67
|
+
(default 2.5)
|
68
|
+
--ftx=float The frequency for temp generation across the x-axis
|
69
|
+
(default 2.5)
|
70
|
+
--fty=float The frequency for temp generation across the y-axis
|
71
|
+
(default 2.5)
|
72
|
+
--gf=bool Generate flora, significantly affects performance
|
73
|
+
--height=int The height of the generated map (default 128)
|
74
|
+
-h, --help Print usage
|
75
|
+
--hs=int The seed for a terrains height perlin generation
|
76
|
+
(default 10)
|
77
|
+
--moisture=float Adjust each generated moisture by this percent (0 -
|
78
|
+
100) (default 0.0)
|
79
|
+
--ms=int The seed for a terrains moist perlin generation
|
80
|
+
(default 300)
|
81
|
+
--oh=int Octaves for height generation (default 3)
|
82
|
+
--om=int Octaves for moist generation (default 3)
|
83
|
+
--ot=int Octaves for temp generation (default 3)
|
84
|
+
--ph=float Persistance for height generation (default 1.0)
|
85
|
+
--pm=float Persistance for moist generation (default 1.0)
|
86
|
+
--pt=float Persistance for temp generation (default 1.0)
|
87
|
+
--temp=float Adjust each generated temperature by this percent (0
|
88
|
+
- 100) (default 0.0)
|
89
|
+
--ts=int The seed for a terrains temperature perlin generation
|
90
|
+
(default 3000)
|
91
|
+
--width=int The width of the generated map (default 128)
|
92
|
+
|
93
|
+
Examples:
|
94
|
+
Render with defaults
|
95
|
+
$ ruby-perlin-2D-map-generator render
|
96
|
+
|
97
|
+
Render with options
|
98
|
+
$ ruby-perlin-2D-map-generator render --elevation=-40 --moisture=25 --hs=1
|
99
|
+
```
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
lib_path = File.expand_path('../lib', __dir__)
|
5
|
+
$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
|
6
|
+
require 'CLI/command'
|
7
|
+
|
8
|
+
Signal.trap('INT') do
|
9
|
+
warn("\n#{caller.join("\n")}: interrupted")
|
10
|
+
exit(1)
|
11
|
+
end
|
12
|
+
|
13
|
+
CLI::Command.new.parse.run
|
data/lib/CLI/command.rb
ADDED
@@ -0,0 +1,277 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tty/option'
|
4
|
+
require 'map'
|
5
|
+
require 'map_config'
|
6
|
+
module CLI
|
7
|
+
class Command
|
8
|
+
include TTY::Option
|
9
|
+
|
10
|
+
usage do
|
11
|
+
program 'ruby-perlin-2D-map-generator'
|
12
|
+
|
13
|
+
no_command
|
14
|
+
|
15
|
+
desc 'Generate a seeded customizable procedurally generated 2D map. Rendered in the console ' \
|
16
|
+
' using ansi colours, or described as a 2D array of hashes with each tiles information.'
|
17
|
+
|
18
|
+
example 'Render with defaults',
|
19
|
+
' $ ruby-perlin-2D-map-generator render'
|
20
|
+
|
21
|
+
example 'Render with options',
|
22
|
+
' $ ruby-perlin-2D-map-generator render --elevation=-40 --moisture=25 --hs=1'
|
23
|
+
end
|
24
|
+
|
25
|
+
argument :command do
|
26
|
+
name '(describe | render)'
|
27
|
+
arity one
|
28
|
+
validate ->(v) { v.downcase == 'describe' || v.downcase == 'render' }
|
29
|
+
desc 'command to run: render prints the map to standard output using ansi colors, ' \
|
30
|
+
'while describe prints each tiles bionome information in the map.'
|
31
|
+
end
|
32
|
+
|
33
|
+
option :height_seed do
|
34
|
+
long '--hs int'
|
35
|
+
# or
|
36
|
+
long '--hs=int'
|
37
|
+
|
38
|
+
desc 'The seed for a terrains height perlin generation'
|
39
|
+
convert Integer
|
40
|
+
default MapConfig::DEFAULT_HEIGHT_SEED
|
41
|
+
end
|
42
|
+
|
43
|
+
option :moist_seed do
|
44
|
+
long '--ms int'
|
45
|
+
# or
|
46
|
+
long '--ms=int'
|
47
|
+
|
48
|
+
desc 'The seed for a terrains moist perlin generation'
|
49
|
+
convert Integer
|
50
|
+
default MapConfig::DEFAULT_MOIST_SEED
|
51
|
+
end
|
52
|
+
|
53
|
+
option :temp_seed do
|
54
|
+
long '--ts int'
|
55
|
+
# or
|
56
|
+
long '--ts=int'
|
57
|
+
|
58
|
+
desc 'The seed for a terrains temperature perlin generation'
|
59
|
+
convert Integer
|
60
|
+
default MapConfig::DEFAULT_TEMP_SEED
|
61
|
+
end
|
62
|
+
|
63
|
+
option :octaves_height do
|
64
|
+
long '--oh int'
|
65
|
+
long '--oh=int'
|
66
|
+
|
67
|
+
desc 'Octaves for height generation'
|
68
|
+
convert Integer
|
69
|
+
default MapConfig::DEFAULT_HEIGHT_OCTAVES
|
70
|
+
end
|
71
|
+
|
72
|
+
option :octaves_moist do
|
73
|
+
long '--om int'
|
74
|
+
long '--om=int'
|
75
|
+
|
76
|
+
desc 'Octaves for moist generation'
|
77
|
+
convert Integer
|
78
|
+
default MapConfig::DEFAULT_MOIST_OCTAVES
|
79
|
+
end
|
80
|
+
|
81
|
+
option :octaves_temp do
|
82
|
+
long '--ot int'
|
83
|
+
long '--ot=int'
|
84
|
+
|
85
|
+
desc 'Octaves for temp generation'
|
86
|
+
convert Integer
|
87
|
+
default MapConfig::DEFAULT_TEMP_OCTAVES
|
88
|
+
end
|
89
|
+
|
90
|
+
option :persistance_moist do
|
91
|
+
long '--pm float'
|
92
|
+
long '--pm=float'
|
93
|
+
|
94
|
+
desc 'Persistance for moist generation'
|
95
|
+
convert Float
|
96
|
+
default MapConfig::DEFAULT_MOIST_PERSISTANCE
|
97
|
+
end
|
98
|
+
|
99
|
+
option :persistance_height do
|
100
|
+
long '--ph float'
|
101
|
+
long '--ph=float'
|
102
|
+
|
103
|
+
desc 'Persistance for height generation'
|
104
|
+
convert Float
|
105
|
+
default MapConfig::DEFAULT_HEIGHT_PERSISTANCE
|
106
|
+
end
|
107
|
+
|
108
|
+
option :persistance_temp do
|
109
|
+
long '--pt float'
|
110
|
+
long '--pt=float'
|
111
|
+
|
112
|
+
desc 'Persistance for temp generation'
|
113
|
+
convert Float
|
114
|
+
default MapConfig::DEFAULT_TEMP_PERSISTANCE
|
115
|
+
end
|
116
|
+
|
117
|
+
option :width do
|
118
|
+
long '--width int'
|
119
|
+
long '--width=int'
|
120
|
+
|
121
|
+
desc 'The width of the generated map'
|
122
|
+
convert Integer
|
123
|
+
default MapConfig::DEFAULT_TILE_COUNT
|
124
|
+
end
|
125
|
+
|
126
|
+
option :height do
|
127
|
+
long '--height int'
|
128
|
+
long '--height=int'
|
129
|
+
|
130
|
+
desc 'The height of the generated map'
|
131
|
+
convert Integer
|
132
|
+
default MapConfig::DEFAULT_TILE_COUNT
|
133
|
+
end
|
134
|
+
|
135
|
+
option :perlin_height_horizontal_frequency do
|
136
|
+
long '--fhx float'
|
137
|
+
long '--fhx=float'
|
138
|
+
|
139
|
+
desc 'The frequency for height generation across the x-axis'
|
140
|
+
convert Float
|
141
|
+
default MapConfig::DEFAULT_HEIGHT_X_FREQUENCY
|
142
|
+
end
|
143
|
+
|
144
|
+
option :perlin_height_vertical_frequency do
|
145
|
+
long '--fhy float'
|
146
|
+
long '--fhy=float'
|
147
|
+
|
148
|
+
desc 'The frequency for height generation across the y-axis'
|
149
|
+
convert Float
|
150
|
+
default MapConfig::DEFAULT_HEIGHT_Y_FREQUENCY
|
151
|
+
end
|
152
|
+
|
153
|
+
option :perlin_temp_horizontal_frequency do
|
154
|
+
long '--ftx float'
|
155
|
+
long '--ftx=float'
|
156
|
+
|
157
|
+
desc 'The frequency for temp generation across the x-axis'
|
158
|
+
convert Float
|
159
|
+
default MapConfig::DEFAULT_TEMP_X_FREQUENCY
|
160
|
+
end
|
161
|
+
|
162
|
+
option :perlin_temp_vertical_frequency do
|
163
|
+
long '--fty float'
|
164
|
+
long '--fty=float'
|
165
|
+
|
166
|
+
desc 'The frequency for temp generation across the y-axis'
|
167
|
+
convert Float
|
168
|
+
default MapConfig::DEFAULT_TEMP_Y_FREQUENCY
|
169
|
+
end
|
170
|
+
|
171
|
+
option :perlin_moist_horizontal_frequency do
|
172
|
+
long '--fmx float'
|
173
|
+
long '--fmx=float'
|
174
|
+
|
175
|
+
desc 'The frequency for moist generation across the x-axis'
|
176
|
+
convert Float
|
177
|
+
default MapConfig::DEFAULT_MOIST_X_FREQUENCY
|
178
|
+
end
|
179
|
+
|
180
|
+
option :perlin_moist_vertical_frequency do
|
181
|
+
long '--fmy float'
|
182
|
+
long '--fmy=float'
|
183
|
+
|
184
|
+
desc 'The frequency for moist generation across the y-axis'
|
185
|
+
convert Float
|
186
|
+
default MapConfig::DEFAULT_MOIST_Y_FREQUENCY
|
187
|
+
end
|
188
|
+
|
189
|
+
option :generate_flora do
|
190
|
+
long '--gf bool'
|
191
|
+
long '--gf=bool'
|
192
|
+
|
193
|
+
desc 'Generate flora, significantly affects performance'
|
194
|
+
convert :bool
|
195
|
+
default MapConfig::DEFAULT_GENERATE_FLORA
|
196
|
+
end
|
197
|
+
|
198
|
+
option :temp do
|
199
|
+
long '--temp float'
|
200
|
+
long '--temp=float'
|
201
|
+
|
202
|
+
desc 'Adjust each generated temperature by this percent (0 - 100)'
|
203
|
+
convert ->(val) { val.to_f / 100.0 }
|
204
|
+
validate ->(val) { val >= -1.0 && val <= 1.0 }
|
205
|
+
default MapConfig::DEFAULT_TEMP_ADJUSTMENT
|
206
|
+
end
|
207
|
+
|
208
|
+
option :elevation do
|
209
|
+
long '--elevation float'
|
210
|
+
long '--elevation=float'
|
211
|
+
|
212
|
+
desc 'Adjust each generated elevation by this percent (0 - 100)'
|
213
|
+
convert ->(val) { val.to_f / 100.0 }
|
214
|
+
validate ->(val) { val >= -1.0 && val <= 1.0 }
|
215
|
+
default MapConfig::DEFAULT_HEIGHT_ADJUSTMENT
|
216
|
+
end
|
217
|
+
|
218
|
+
option :moisture do
|
219
|
+
long '--moisture float'
|
220
|
+
long '--moisture=float'
|
221
|
+
|
222
|
+
desc 'Adjust each generated moisture by this percent (0 - 100)'
|
223
|
+
convert ->(val) { val.to_f / 100.0 }
|
224
|
+
validate ->(val) { val >= -1.0 && val <= 1.0 }
|
225
|
+
default MapConfig::DEFAULT_MOIST_ADJUSTMENT
|
226
|
+
end
|
227
|
+
|
228
|
+
flag :help do
|
229
|
+
short '-h'
|
230
|
+
long '--help'
|
231
|
+
desc 'Print usage'
|
232
|
+
end
|
233
|
+
|
234
|
+
def run
|
235
|
+
if params[:help]
|
236
|
+
print help
|
237
|
+
elsif params.errors.any?
|
238
|
+
puts params.errors.summary
|
239
|
+
else
|
240
|
+
execute_command
|
241
|
+
# pp params.to_h
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
private
|
246
|
+
|
247
|
+
def execute_command
|
248
|
+
map = Map.new(map_config: MapConfig.new(
|
249
|
+
width: params[:width],
|
250
|
+
height: params[:height],
|
251
|
+
perlin_height_config: perlin_height_config,
|
252
|
+
perlin_moist_config: perlin_moist_config,
|
253
|
+
perlin_temp_config: perlin_temp_config,
|
254
|
+
generate_flora: params[:generate_flora]
|
255
|
+
))
|
256
|
+
case params[:command]
|
257
|
+
when 'render' then map.render
|
258
|
+
when 'describe' then puts map.describe
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def perlin_moist_config
|
263
|
+
MapConfig::PerlinConfig.new(*params.to_h.slice(:width, :height, :moist_seed, :octaves_moist,
|
264
|
+
:perlin_moist_horizontal_frequency, :perlin_moist_vertical_frequency, :persistance_moist, :moisture).values)
|
265
|
+
end
|
266
|
+
|
267
|
+
def perlin_height_config
|
268
|
+
MapConfig::PerlinConfig.new(*params.to_h.slice(:width, :height, :height_seed, :octaves_height,
|
269
|
+
:perlin_height_horizontal_frequency, :perlin_height_vertical_frequency, :persistance_height, :elevation).values)
|
270
|
+
end
|
271
|
+
|
272
|
+
def perlin_temp_config
|
273
|
+
MapConfig::PerlinConfig.new(*params.to_h.slice(:width, :height, :temp_seed, :octaves_temp,
|
274
|
+
:perlin_temp_horizontal_frequency, :perlin_temp_vertical_frequency, :persistance_temp, :temp).values)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
data/lib/ansi_colours.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnsiColours
|
4
|
+
module Background
|
5
|
+
WHITE = "\e[48;5;231m"
|
6
|
+
BLACK = "\033[40m"
|
7
|
+
DEEP_BLUE = "\033[48;5;23m"
|
8
|
+
BLUE = "\033[44m"
|
9
|
+
LIGHT_BLUE = "\033[48;5;117m"
|
10
|
+
SHOAL_BLUE = "\e[48;5;87m"
|
11
|
+
GREEN = "\033[102m"
|
12
|
+
LIGHT_GREEN = "\e[48;5;47m"
|
13
|
+
DESERT_YELLOW = "\e[48;5;220m"
|
14
|
+
DESERT_LIGHT_YELLOW = "\e[48;5;223m"
|
15
|
+
DESERT_DARK_YELLOW = "\e[48;5;214m"
|
16
|
+
GREEN_SWAMP = "\e[48;5;58m"
|
17
|
+
DARK_GREEN = "\033[42m"
|
18
|
+
BROWN = "\033[48;5;130m"
|
19
|
+
GREY = "\e[48;5;7m"
|
20
|
+
GREY_MOUNTAIN = "\033[38;5;240m"
|
21
|
+
SANDY = "\033[48;5;229m"
|
22
|
+
RED_BROWN = "\033[48;5;173m"
|
23
|
+
GRASSLAND = "\033[48;2;195;205;103m"
|
24
|
+
TAIGA_PLAIN = "\e[48;5;67m"
|
25
|
+
TAIGA_VALLEY = "\e[48;5;66m"
|
26
|
+
TAIGA_HIGHLAND = "\e[48;5;65m"
|
27
|
+
TAIGA_COAST = "\e[48;5;17m"
|
28
|
+
ICE = "\e[48;5;159m"
|
29
|
+
ANSI_RESET = "\033[0m"
|
30
|
+
end
|
31
|
+
end
|
data/lib/biome.rb
ADDED
@@ -0,0 +1,225 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ansi_colours'
|
4
|
+
require 'flora'
|
5
|
+
|
6
|
+
class Biome
|
7
|
+
attr_accessor :name, :flora_range, :colour
|
8
|
+
|
9
|
+
def initialize(name:, colour:, flora_range: nil)
|
10
|
+
@name = name
|
11
|
+
@flora_range = flora_range
|
12
|
+
@colour = colour
|
13
|
+
end
|
14
|
+
|
15
|
+
def water?
|
16
|
+
WATER_TERRAIN.include?(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def land?
|
20
|
+
LAND_TERRAIN.include?(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
def grassland?
|
24
|
+
GRASSLAND_TERRAIN.include?(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
def desert?
|
28
|
+
DESERT_TERRAIN.include?(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
def taiga?
|
32
|
+
TAIGA_TERRAIN.include?(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
def flora_available
|
36
|
+
!flora_range.nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
def flora
|
40
|
+
@flora ||=
|
41
|
+
if flora_available
|
42
|
+
if desert?
|
43
|
+
Flora.new(Flora::CACTUS)
|
44
|
+
elsif grassland?
|
45
|
+
Flora.new(Flora::DECIDUOUS_TREE)
|
46
|
+
elsif taiga?
|
47
|
+
Flora.new(Flora::EVERGREEN_TREE)
|
48
|
+
else
|
49
|
+
raise StandardError, "Unknown flora #{to_h}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_h
|
55
|
+
{
|
56
|
+
name: name,
|
57
|
+
flora_range: flora_range,
|
58
|
+
colour: colour
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.from(elevation, moist, temp)
|
63
|
+
terrain_selection(elevation, moist, temp)
|
64
|
+
end
|
65
|
+
|
66
|
+
SNOW = Biome.new(name: 'snow', flora_range: nil, colour: AnsiColours::Background::WHITE)
|
67
|
+
ROCKS = Biome.new(name: 'rocks', flora_range: nil, colour: AnsiColours::Background::GREY)
|
68
|
+
MOUNTAIN = Biome.new(name: 'mountain', flora_range: nil, colour: AnsiColours::Background::BROWN)
|
69
|
+
MOUNTAIN_FOOT = Biome.new(name: 'mountain_foot', flora_range: 10, colour: AnsiColours::Background::RED_BROWN)
|
70
|
+
GRASSLAND = Biome.new(name: 'grassland', flora_range: 1, colour: AnsiColours::Background::DARK_GREEN)
|
71
|
+
VALLEY = Biome.new(name: 'valley', flora_range: 1, colour: AnsiColours::Background::GREEN)
|
72
|
+
DEEP_VALLEY = Biome.new(name: 'deep_valley', flora_range: 1, colour: AnsiColours::Background::LIGHT_GREEN)
|
73
|
+
DESERT = Biome.new(name: 'desert', flora_range: 1, colour: AnsiColours::Background::DESERT_YELLOW)
|
74
|
+
DEEP_DESERT = Biome.new(name: 'deep_desert', flora_range: 1, colour: AnsiColours::Background::DESERT_LIGHT_YELLOW)
|
75
|
+
STEPPE_DESERT = Biome.new(name: 'steppe_desert', flora_range: 1, colour: AnsiColours::Background::DESERT_DARK_YELLOW)
|
76
|
+
SWAMP = Biome.new(name: 'swamp', flora_range: nil, colour: AnsiColours::Background::GREEN_SWAMP)
|
77
|
+
COASTLINE = Biome.new(name: 'coastline', flora_range: nil, colour: AnsiColours::Background::SANDY)
|
78
|
+
SHOAL = Biome.new(name: 'shoal', flora_range: nil, colour: AnsiColours::Background::SHOAL_BLUE)
|
79
|
+
OCEAN = Biome.new(name: 'ocean', flora_range: nil, colour: AnsiColours::Background::LIGHT_BLUE)
|
80
|
+
DEEP_OCEAN = Biome.new(name: 'deep_ocean', flora_range: nil, colour: AnsiColours::Background::BLUE)
|
81
|
+
TAIGA_PLAIN = Biome.new(name: 'taiga_plain', flora_range: 1.5, colour: AnsiColours::Background::TAIGA_PLAIN)
|
82
|
+
TAIGA_VALLEY = Biome.new(name: 'taiga_valley', flora_range: 1.5, colour: AnsiColours::Background::TAIGA_VALLEY)
|
83
|
+
TAIGA_HIGHLAND = Biome.new(name: 'taiga_highland', flora_range: 1.5, colour: AnsiColours::Background::TAIGA_HIGHLAND)
|
84
|
+
TAIGA_COAST = Biome.new(name: 'taiga_coast', flora_range: nil, colour: AnsiColours::Background::TAIGA_COAST)
|
85
|
+
ICE = Biome.new(name: 'ice', flora_range: nil, colour: AnsiColours::Background::ICE)
|
86
|
+
|
87
|
+
ALL_TERRAIN = [
|
88
|
+
SNOW,
|
89
|
+
ROCKS,
|
90
|
+
MOUNTAIN,
|
91
|
+
MOUNTAIN_FOOT,
|
92
|
+
GRASSLAND,
|
93
|
+
VALLEY,
|
94
|
+
COASTLINE,
|
95
|
+
SHOAL,
|
96
|
+
OCEAN,
|
97
|
+
DEEP_OCEAN,
|
98
|
+
DESERT,
|
99
|
+
DEEP_DESERT,
|
100
|
+
STEPPE_DESERT,
|
101
|
+
SWAMP,
|
102
|
+
TAIGA_PLAIN,
|
103
|
+
TAIGA_HIGHLAND,
|
104
|
+
TAIGA_VALLEY,
|
105
|
+
TAIGA_COAST,
|
106
|
+
ICE
|
107
|
+
].freeze
|
108
|
+
|
109
|
+
WATER_TERRAIN = [
|
110
|
+
SHOAL,
|
111
|
+
OCEAN,
|
112
|
+
DEEP_OCEAN
|
113
|
+
].freeze
|
114
|
+
|
115
|
+
DESERT_TERRAIN = [
|
116
|
+
DESERT,
|
117
|
+
DEEP_DESERT,
|
118
|
+
STEPPE_DESERT
|
119
|
+
].freeze
|
120
|
+
|
121
|
+
GRASSLAND_TERRAIN = [
|
122
|
+
GRASSLAND,
|
123
|
+
VALLEY,
|
124
|
+
DEEP_VALLEY,
|
125
|
+
MOUNTAIN_FOOT
|
126
|
+
].freeze
|
127
|
+
|
128
|
+
TAIGA_TERRAIN = [
|
129
|
+
TAIGA_PLAIN,
|
130
|
+
TAIGA_HIGHLAND,
|
131
|
+
TAIGA_VALLEY,
|
132
|
+
TAIGA_COAST
|
133
|
+
].freeze
|
134
|
+
|
135
|
+
LAND_TERRAIN = (ALL_TERRAIN - WATER_TERRAIN).freeze
|
136
|
+
|
137
|
+
class << self
|
138
|
+
private
|
139
|
+
|
140
|
+
def terrain_selection(elevation, moist, temp)
|
141
|
+
case elevation
|
142
|
+
when 0.95..1
|
143
|
+
SNOW
|
144
|
+
when 0.9..0.95
|
145
|
+
ROCKS
|
146
|
+
when 0.8..0.9
|
147
|
+
if moist < 0.9
|
148
|
+
MOUNTAIN
|
149
|
+
else
|
150
|
+
SHOAL
|
151
|
+
end
|
152
|
+
when 0.7..0.8
|
153
|
+
if moist < 0.9
|
154
|
+
MOUNTAIN_FOOT
|
155
|
+
else
|
156
|
+
SHOAL
|
157
|
+
end
|
158
|
+
when 0.6..0.7
|
159
|
+
if moist < 0.8
|
160
|
+
if desert_condition?(moist, temp)
|
161
|
+
STEPPE_DESERT
|
162
|
+
elsif taiga_condition?(moist, temp)
|
163
|
+
TAIGA_HIGHLAND
|
164
|
+
elsif moist > 0.75
|
165
|
+
SWAMP
|
166
|
+
else
|
167
|
+
GRASSLAND
|
168
|
+
end
|
169
|
+
else
|
170
|
+
SHOAL
|
171
|
+
end
|
172
|
+
when 0.3..0.6
|
173
|
+
if desert_condition?(moist, temp)
|
174
|
+
DESERT
|
175
|
+
elsif taiga_condition?(moist, temp)
|
176
|
+
TAIGA_PLAIN
|
177
|
+
else
|
178
|
+
VALLEY
|
179
|
+
end
|
180
|
+
when 0.2..0.3
|
181
|
+
if desert_condition?(moist, temp)
|
182
|
+
DEEP_DESERT
|
183
|
+
elsif taiga_condition?(moist, temp)
|
184
|
+
TAIGA_VALLEY
|
185
|
+
else
|
186
|
+
DEEP_VALLEY
|
187
|
+
end
|
188
|
+
when 0.15..0.2
|
189
|
+
if taiga_condition?(moist, temp)
|
190
|
+
TAIGA_COAST
|
191
|
+
else
|
192
|
+
COASTLINE
|
193
|
+
end
|
194
|
+
when 0.05..0.15
|
195
|
+
if taiga_condition?(moist, temp)
|
196
|
+
ICE
|
197
|
+
else
|
198
|
+
SHOAL
|
199
|
+
end
|
200
|
+
when 0.025..0.05
|
201
|
+
if taiga_condition?(moist, temp)
|
202
|
+
ICE
|
203
|
+
else
|
204
|
+
OCEAN
|
205
|
+
end
|
206
|
+
when 0.0..0.025
|
207
|
+
if taiga_condition?(moist, temp)
|
208
|
+
ICE
|
209
|
+
else
|
210
|
+
DEEP_OCEAN
|
211
|
+
end
|
212
|
+
else
|
213
|
+
raise ArgumentError, "unknown biome elevation: #{elevation} moisture: #{moist} temp: #{temp}"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def desert_condition?(moist, temp)
|
218
|
+
moist < 0.1 && temp > 0.5
|
219
|
+
end
|
220
|
+
|
221
|
+
def taiga_condition?(moist, temp)
|
222
|
+
moist > 0.6 && temp < 0.2
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
data/lib/flora.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tile_item'
|
4
|
+
|
5
|
+
class Flora < TileItem
|
6
|
+
CACTUS = "\u{1F335}"
|
7
|
+
EVERGREEN_TREE = "\u{1F332}"
|
8
|
+
DECIDUOUS_TREE = "\u{1F333}"
|
9
|
+
|
10
|
+
def initialize(render_symbol)
|
11
|
+
super self, render_symbol: render_symbol
|
12
|
+
end
|
13
|
+
end
|
data/lib/map.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'map_tile_generator'
|
4
|
+
require 'map_config'
|
5
|
+
|
6
|
+
class Map
|
7
|
+
attr_reader :config
|
8
|
+
|
9
|
+
def initialize(map_config: MapConfig.new)
|
10
|
+
@config = map_config
|
11
|
+
end
|
12
|
+
|
13
|
+
def describe
|
14
|
+
tiles.map { |row| row.map(&:to_h) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def render
|
18
|
+
tiles.each do |row|
|
19
|
+
row.each(&:render_to_standard_output)
|
20
|
+
puts
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def tiles
|
25
|
+
@tiles ||= MapTileGenerator.new(map: self).generate
|
26
|
+
end
|
27
|
+
end
|
data/lib/map_config.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class MapConfig
|
4
|
+
DEFAULT_TILE_COUNT = 128
|
5
|
+
DEFAULT_GENERATE_FLORA = true
|
6
|
+
|
7
|
+
DEFAULT_HEIGHT_SEED = 10
|
8
|
+
DEFAULT_HEIGHT_OCTAVES = 3
|
9
|
+
DEFAULT_HEIGHT_X_FREQUENCY = 2.5
|
10
|
+
DEFAULT_HEIGHT_Y_FREQUENCY = 2.5
|
11
|
+
DEFAULT_HEIGHT_PERSISTANCE = 1.0
|
12
|
+
DEFAULT_HEIGHT_ADJUSTMENT = 0.0
|
13
|
+
|
14
|
+
DEFAULT_MOIST_SEED = 300
|
15
|
+
DEFAULT_MOIST_OCTAVES = 3
|
16
|
+
DEFAULT_MOIST_X_FREQUENCY = 2.5
|
17
|
+
DEFAULT_MOIST_Y_FREQUENCY = 2.5
|
18
|
+
DEFAULT_MOIST_PERSISTANCE = 1.0
|
19
|
+
DEFAULT_MOIST_ADJUSTMENT = 0.0
|
20
|
+
|
21
|
+
DEFAULT_TEMP_SEED = 3000
|
22
|
+
DEFAULT_TEMP_OCTAVES = 3
|
23
|
+
DEFAULT_TEMP_PERSISTANCE = 1.0
|
24
|
+
DEFAULT_TEMP_Y_FREQUENCY = 2.5
|
25
|
+
DEFAULT_TEMP_X_FREQUENCY = 2.5
|
26
|
+
DEFAULT_TEMP_ADJUSTMENT = 0.0
|
27
|
+
|
28
|
+
PERLIN_CONFIG_OPTIONS = %i[width height noise_seed octaves x_frequency y_frequency persistance adjustment].freeze
|
29
|
+
PerlinConfig = Struct.new(*PERLIN_CONFIG_OPTIONS)
|
30
|
+
|
31
|
+
attr_reader :generate_flora, :perlin_height_config, :perlin_moist_config, :perlin_temp_config, :width, :height
|
32
|
+
|
33
|
+
def initialize(perlin_height_config: default_perlin_height_config, perlin_moist_config: default_perlin_moist_config, perlin_temp_config: default_perlin_temp_config, width: DEFAULT_TILE_COUNT,
|
34
|
+
height: DEFAULT_TILE_COUNT, generate_flora: DEFAULT_GENERATE_FLORA)
|
35
|
+
raise ArgumentError unless perlin_height_config.is_a?(PerlinConfig) && perlin_moist_config.is_a?(PerlinConfig)
|
36
|
+
|
37
|
+
@generate_flora = generate_flora
|
38
|
+
@perlin_height_config = perlin_height_config
|
39
|
+
@perlin_moist_config = perlin_moist_config
|
40
|
+
@perlin_temp_config = perlin_temp_config
|
41
|
+
@width = width
|
42
|
+
@height = height
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def default_perlin_height_config
|
48
|
+
PerlinConfig.new(DEFAULT_TILE_COUNT, DEFAULT_TILE_COUNT, DEFAULT_HEIGHT_SEED, DEFAULT_HEIGHT_OCTAVES,
|
49
|
+
DEFAULT_HEIGHT_X_FREQUENCY, DEFAULT_HEIGHT_Y_FREQUENCY, DEFAULT_HEIGHT_PERSISTANCE, DEFAULT_HEIGHT_ADJUSTMENT)
|
50
|
+
end
|
51
|
+
|
52
|
+
def default_perlin_moist_config
|
53
|
+
PerlinConfig.new(DEFAULT_TILE_COUNT, DEFAULT_TILE_COUNT, DEFAULT_MOIST_SEED, DEFAULT_MOIST_OCTAVES,
|
54
|
+
DEFAULT_MOIST_X_FREQUENCY, DEFAULT_MOIST_Y_FREQUENCY, DEFAULT_MOIST_PERSISTANCE, DEFAULT_MOIST_ADJUSTMENT)
|
55
|
+
end
|
56
|
+
|
57
|
+
def default_perlin_temp_config
|
58
|
+
PerlinConfig.new(DEFAULT_TILE_COUNT, DEFAULT_TILE_COUNT, DEFAULT_TEMP_SEED, DEFAULT_TEMP_OCTAVES,
|
59
|
+
DEFAULT_TEMP_X_FREQUENCY, DEFAULT_TEMP_Y_FREQUENCY, DEFAULT_TEMP_PERSISTANCE, DEFAULT_TEMP_ADJUSTMENT)
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tile'
|
4
|
+
require 'tile_perlin_generator'
|
5
|
+
|
6
|
+
class MapTileGenerator
|
7
|
+
attr_reader :map_config, :map, :height_perlin_generator, :moist_perlin_generator, :temp_perlin_generator
|
8
|
+
|
9
|
+
def initialize(map:, height_perlin_generator: nil, moist_perlin_generator: nil, temp_perlin_generator: nil)
|
10
|
+
@map = map
|
11
|
+
@map_config = map.config
|
12
|
+
@height_perlin_generator = height_perlin_generator || default_perlin_height_generator
|
13
|
+
@moist_perlin_generator = moist_perlin_generator || default_perlin_moist_generator
|
14
|
+
@temp_perlin_generator = temp_perlin_generator || default_perlin_temp_generator
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate
|
18
|
+
positive_quadrant_cartesian_plane
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def positive_quadrant_cartesian_plane
|
24
|
+
y_axis_array do |y|
|
25
|
+
x_axis_array do |x|
|
26
|
+
Tile.new(
|
27
|
+
map: map,
|
28
|
+
x: x,
|
29
|
+
y: y,
|
30
|
+
height: heights[y][x],
|
31
|
+
moist: moists[y][x],
|
32
|
+
temp: temps[y][x]
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def y_axis_array(&block)
|
39
|
+
Array.new(map_config.height, &block)
|
40
|
+
end
|
41
|
+
|
42
|
+
def x_axis_array(&block)
|
43
|
+
Array.new(map_config.width, &block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def default_perlin_height_generator
|
47
|
+
TilePerlinGenerator.new(map_config.perlin_height_config)
|
48
|
+
end
|
49
|
+
|
50
|
+
def default_perlin_moist_generator
|
51
|
+
TilePerlinGenerator.new(map_config.perlin_moist_config)
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_perlin_temp_generator
|
55
|
+
TilePerlinGenerator.new(map_config.perlin_temp_config)
|
56
|
+
end
|
57
|
+
|
58
|
+
def heights
|
59
|
+
@heights ||= height_perlin_generator.generate
|
60
|
+
end
|
61
|
+
|
62
|
+
def moists
|
63
|
+
@moists ||= moist_perlin_generator.generate
|
64
|
+
end
|
65
|
+
|
66
|
+
def temps
|
67
|
+
@temps ||= temp_perlin_generator.generate
|
68
|
+
end
|
69
|
+
end
|
data/lib/tile.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'biome'
|
4
|
+
require 'flora'
|
5
|
+
|
6
|
+
class Tile
|
7
|
+
attr_reader :x, :y, :height, :moist, :temp, :map
|
8
|
+
|
9
|
+
def initialize(map:, x:, y:, height: 0, moist: 0, temp: 0)
|
10
|
+
@x = x
|
11
|
+
@y = y
|
12
|
+
@height = height
|
13
|
+
@moist = moist
|
14
|
+
@temp = temp
|
15
|
+
@map = map
|
16
|
+
end
|
17
|
+
|
18
|
+
def surrounding_tiles(distance = 1)
|
19
|
+
@surround_cache ||= {}
|
20
|
+
@surround_cache[distance] ||= begin
|
21
|
+
left_limit = [0, x - distance].max
|
22
|
+
top_limit = [0, y - distance].max
|
23
|
+
|
24
|
+
map.tiles[left_limit..(x + distance)].map do |r|
|
25
|
+
r[top_limit..(y + distance)]
|
26
|
+
end.flatten
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def biome
|
31
|
+
@biome ||= Biome.from(height, moist, temp)
|
32
|
+
end
|
33
|
+
|
34
|
+
def items
|
35
|
+
@items ||= items_generated_with_flora_if_applicable
|
36
|
+
end
|
37
|
+
|
38
|
+
def render_to_standard_output
|
39
|
+
print biome.colour + (!items.empty? ? item_with_highest_priority.render_symbol : ' ')
|
40
|
+
print AnsiColours::Background::ANSI_RESET
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_item(tile_item)
|
44
|
+
raise ArgumentError, 'item should be a tile' unless tile_item.is_a?(TileItem)
|
45
|
+
|
46
|
+
items.push(tile_item)
|
47
|
+
end
|
48
|
+
|
49
|
+
def item_with_highest_priority
|
50
|
+
items.max_by(&:render_priority)
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_h
|
54
|
+
{
|
55
|
+
x: x,
|
56
|
+
y: y,
|
57
|
+
height: height,
|
58
|
+
moist: moist,
|
59
|
+
temp: temp,
|
60
|
+
biome: biome.to_h,
|
61
|
+
items: items.map(&:to_h)
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def items_generated_with_flora_if_applicable
|
68
|
+
if map.config.generate_flora && biome.flora_available
|
69
|
+
range_max_value = map.tiles[(y - biome.flora_range)...(y + biome.flora_range)]&.map do |r|
|
70
|
+
r[(x - biome.flora_range)...(x + biome.flora_range)]
|
71
|
+
end&.flatten&.map(&:height)&.max
|
72
|
+
if range_max_value == height
|
73
|
+
[biome.flora]
|
74
|
+
else
|
75
|
+
[]
|
76
|
+
end
|
77
|
+
else
|
78
|
+
[]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/tile_item.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class TileItem
|
4
|
+
DEFAULT_RENDER_PRIORITY = 0
|
5
|
+
attr_reader :obj, :id, :render_symbol, :colour, :render_priority
|
6
|
+
|
7
|
+
def initialize(obj, render_symbol:, id: object_id, render_priority: DEFAULT_RENDER_PRIORITY)
|
8
|
+
@obj = obj
|
9
|
+
@id = id
|
10
|
+
@render_symbol = render_symbol
|
11
|
+
@render_priority = render_priority
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_h
|
15
|
+
{
|
16
|
+
id: id,
|
17
|
+
type: obj.class.name.downcase,
|
18
|
+
render_symbol: render_symbol,
|
19
|
+
render_priority: render_priority
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'perlin'
|
4
|
+
|
5
|
+
class TilePerlinGenerator
|
6
|
+
attr_reader :perlin_config
|
7
|
+
|
8
|
+
def initialize(perlin_config)
|
9
|
+
@perlin_config = perlin_config
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate
|
13
|
+
Array.new(perlin_config.height) do |y|
|
14
|
+
Array.new(perlin_config.width) do |x|
|
15
|
+
nx = perlin_config.x_frequency * (x.to_f / perlin_config.width - 0.5)
|
16
|
+
ny = perlin_config.y_frequency * (y.to_f / perlin_config.height - 0.5)
|
17
|
+
with_adjustment((Math.cos(noise(nx, ny))**6))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def with_adjustment(result)
|
25
|
+
if perlin_config.adjustment != 0.0
|
26
|
+
result += perlin_config.adjustment
|
27
|
+
result = [result, 1.0].min
|
28
|
+
[result, 0.0].max
|
29
|
+
else
|
30
|
+
result
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def noise(x, y)
|
35
|
+
(noise_generator[x, y] / 2) + 0.5
|
36
|
+
end
|
37
|
+
|
38
|
+
def noise_generator
|
39
|
+
@noise_generator ||=
|
40
|
+
Perlin::Generator.new(
|
41
|
+
perlin_config.noise_seed,
|
42
|
+
perlin_config.persistance,
|
43
|
+
perlin_config.octaves
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-perlin-2D-map-generator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tyler Matthews (matthewstyler)
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-07-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: perlin
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: tty-option
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mocha
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: A gem that procedurally generates a seeded and customizable 2D map using
|
84
|
+
perlin noise. Map can be rendered in console using ansi colors or returned as 2D
|
85
|
+
array of hashes describing each tile and binome. Completelycustomizable, use the
|
86
|
+
--help option for full usage details.
|
87
|
+
email: matthews.tyl@gmail.com
|
88
|
+
executables:
|
89
|
+
- ruby-perlin-2D-map-generator
|
90
|
+
extensions: []
|
91
|
+
extra_rdoc_files: []
|
92
|
+
files:
|
93
|
+
- LICENSE
|
94
|
+
- README.md
|
95
|
+
- bin/ruby-perlin-2D-map-generator
|
96
|
+
- lib/CLI/command.rb
|
97
|
+
- lib/ansi_colours.rb
|
98
|
+
- lib/biome.rb
|
99
|
+
- lib/flora.rb
|
100
|
+
- lib/map.rb
|
101
|
+
- lib/map_config.rb
|
102
|
+
- lib/map_tile_generator.rb
|
103
|
+
- lib/tile.rb
|
104
|
+
- lib/tile_item.rb
|
105
|
+
- lib/tile_perlin_generator.rb
|
106
|
+
homepage: https://github.com/matthewstyler/ruby-perlin-2D-map-generator
|
107
|
+
licenses:
|
108
|
+
- MIT
|
109
|
+
metadata:
|
110
|
+
source_code_uri: https://github.com/matthewstyler/ruby-perlin-2D-map-generator
|
111
|
+
bug_tracker_uri: https://github.com/matthewstyler/ruby-perlin-2D-map-generator/issues
|
112
|
+
post_install_message:
|
113
|
+
rdoc_options: []
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '3.0'
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
requirements: []
|
127
|
+
rubygems_version: 3.2.3
|
128
|
+
signing_key:
|
129
|
+
specification_version: 4
|
130
|
+
summary: Procedurally generate seeded and customizable 2D maps, rendered with ansi
|
131
|
+
colours or described in a 2D array of hashes
|
132
|
+
test_files: []
|