Class: Worldgen::PlateMap

Inherits:
Object
  • Object
show all
Defined in:
lib/worldgen/platemap.rb

Overview

A map that generates plates within a square map.

Defined Under Namespace

Classes: Plate

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(size) ⇒ PlateMap

Returns a new instance of PlateMap.



87
88
89
90
91
# File 'lib/worldgen/platemap.rb', line 87

def initialize size
  @size = size
  @plate_ids = nil
  @plates = nil
end

Instance Attribute Details

#sizeObject (readonly)

Returns the value of attribute size.



85
86
87
# File 'lib/worldgen/platemap.rb', line 85

def size
  @size
end

Instance Method Details

#each_plate_pointObject

Iterate across the entire map.

Usage:

each_plate_point do |x, y, plate_id|
  # do something with this information
end


129
130
131
132
133
134
135
# File 'lib/worldgen/platemap.rb', line 129

def each_plate_point
  (0...@size).each do |x|
    (0...@size).each do |y|
      yield x, y, @plate_ids[x][y]
    end
  end
end

#generate_plates!(num_plates, verbose = true) ⇒ Object

Generate plates within this map.

Arguments:

  • num_plates - the number of plates to generate

  • verbose (default: true) - output logging while we’re generating



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/worldgen/platemap.rb', line 142

def generate_plates! num_plates, verbose=true
  @plate_ids = Array.new(@size) { Array.new(@size) { -1 }}

  # Initialize plates in random spots
  @plates = (0...num_plates).map do |plate_num|
    # Find an unoccupied point
    point = nil
    while point == nil
      x, y = rand(@size), rand(@size)

      point = [x, y] if @plate_ids[x][y] < 0
    end

    x, y = point
    @plate_ids[x][y] = plate_num

    Plate.new.tap do |plate|
      plate.map = @plate_ids
      plate.id = plate_num
      plate.type = rand < 0.5 ? :continent : :ocean
      plate.seed = point
    end
  end

  num_points = self.num_points - num_plates
  valid_plates = @plates.select(&:has_frontier?)

  i = 0
  while valid_plates.length > 0
    if verbose and i % (num_points / 100) == 0
      puts "#{i}/#{num_points} #{(i.fdiv(num_points) * 100).round}%"
    end

    # Find a plate with neighbours
    loop do
      idx = choose_plate valid_plates
      plate = valid_plates[idx]

      # absorb a point from the frontier
      value = plate.absorb_frontier!

      if not value
        valid_plates.delete_at idx
        break if valid_plates.length == 0
      else
        # Did we just consume the last point of this plate?
        valid_plates.delete_at(idx) if not plate.has_frontier?
        break
      end
    end

    i += 1
  end
end

#num_pointsObject

Get the number of points in the map.



94
95
96
# File 'lib/worldgen/platemap.rb', line 94

def num_points
  @size * @size
end

#to_height_map(sea_gap) ⇒ Object

Convert to a height map - very simple, just give the continents one height and the oceans another height. This is controlled by a single parameter, ((sea_gap)), which will be the difference between the continents height and oceans height.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/worldgen/platemap.rb', line 102

def to_height_map sea_gap
  raise "Sea gap should be between 0 and 1" if sea_gap < 0 or sea_gap > 1

  plate_heights = @plates.map do |plate|
    if plate.type == :continent
      0.5 + sea_gap / 2
    else
      0.5 - sea_gap / 2
    end
  end

  map = HeightMap.new @size
  
  each_plate_point do |x, y, id|
    map[x, y] = plate_heights[id]
  end

  map
end