ruby-perlin-2D-map-generator 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![2D-maps](https://github.com/matthewstyler/ruby-perlin-2D-map-generator/assets/4560901/89b4f623-53e3-445e-8e5b-96f4fcf67af5)
|
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: []
|