Class: Doom::Map::MapData

Inherits:
Object
  • Object
show all
Defined in:
lib/doom/map/data.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ MapData

Returns a new instance of MapData.



81
82
83
84
85
86
87
88
89
90
91
# File 'lib/doom/map/data.rb', line 81

def initialize(name)
  @name = name
  @things = []
  @vertices = []
  @linedefs = []
  @sidedefs = []
  @sectors = []
  @segs = []
  @subsectors = []
  @nodes = []
end

Instance Attribute Details

#linedefsObject (readonly)

Returns the value of attribute linedefs.



79
80
81
# File 'lib/doom/map/data.rb', line 79

def linedefs
  @linedefs
end

#nameObject (readonly)

Returns the value of attribute name.



79
80
81
# File 'lib/doom/map/data.rb', line 79

def name
  @name
end

#nodesObject (readonly)

Returns the value of attribute nodes.



79
80
81
# File 'lib/doom/map/data.rb', line 79

def nodes
  @nodes
end

#sectorsObject (readonly)

Returns the value of attribute sectors.



79
80
81
# File 'lib/doom/map/data.rb', line 79

def sectors
  @sectors
end

#segsObject (readonly)

Returns the value of attribute segs.



79
80
81
# File 'lib/doom/map/data.rb', line 79

def segs
  @segs
end

#sidedefsObject (readonly)

Returns the value of attribute sidedefs.



79
80
81
# File 'lib/doom/map/data.rb', line 79

def sidedefs
  @sidedefs
end

#subsectorsObject (readonly)

Returns the value of attribute subsectors.



79
80
81
# File 'lib/doom/map/data.rb', line 79

def subsectors
  @subsectors
end

#thingsObject (readonly)

Returns the value of attribute things.



79
80
81
# File 'lib/doom/map/data.rb', line 79

def things
  @things
end

#verticesObject (readonly)

Returns the value of attribute vertices.



79
80
81
# File 'lib/doom/map/data.rb', line 79

def vertices
  @vertices
end

Class Method Details

.load(wad, map_name) ⇒ Object

Raises:



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/doom/map/data.rb', line 93

def self.load(wad, map_name)
  map = new(map_name)

  lump_idx = wad.directory.index { |e| e.name == map_name.upcase }
  raise Error, "Map #{map_name} not found" unless lump_idx

  map.load_things(wad.read_lump_at(wad.directory[lump_idx + 1]))
  map.load_linedefs(wad.read_lump_at(wad.directory[lump_idx + 2]))
  map.load_sidedefs(wad.read_lump_at(wad.directory[lump_idx + 3]))
  map.load_vertices(wad.read_lump_at(wad.directory[lump_idx + 4]))
  map.load_segs(wad.read_lump_at(wad.directory[lump_idx + 5]))
  map.load_subsectors(wad.read_lump_at(wad.directory[lump_idx + 6]))
  map.load_nodes(wad.read_lump_at(wad.directory[lump_idx + 7]))
  map.load_sectors(wad.read_lump_at(wad.directory[lump_idx + 8]))

  map
end

Instance Method Details

#load_linedefs(data) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/doom/map/data.rb', line 136

def load_linedefs(data)
  count = data.size / 14
  count.times do |i|
    offset = i * 14
    @linedefs << Linedef.new(
      data[offset, 2].unpack1('v'),
      data[offset + 2, 2].unpack1('v'),
      data[offset + 4, 2].unpack1('v'),
      data[offset + 6, 2].unpack1('v'),
      data[offset + 8, 2].unpack1('v'),
      data[offset + 10, 2].unpack1('s<'),
      data[offset + 12, 2].unpack1('s<')
    )
  end
end

#load_nodes(data) ⇒ Object



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/doom/map/data.rb', line 209

def load_nodes(data)
  count = data.size / 28
  count.times do |i|
    offset = i * 28
    bbox_right = Node::BBox.new(
      data[offset + 8, 2].unpack1('s<'),
      data[offset + 10, 2].unpack1('s<'),
      data[offset + 12, 2].unpack1('s<'),
      data[offset + 14, 2].unpack1('s<')
    )
    bbox_left = Node::BBox.new(
      data[offset + 16, 2].unpack1('s<'),
      data[offset + 18, 2].unpack1('s<'),
      data[offset + 20, 2].unpack1('s<'),
      data[offset + 22, 2].unpack1('s<')
    )
    @nodes << Node.new(
      data[offset, 2].unpack1('s<'),
      data[offset + 2, 2].unpack1('s<'),
      data[offset + 4, 2].unpack1('s<'),
      data[offset + 6, 2].unpack1('s<'),
      bbox_right,
      bbox_left,
      data[offset + 24, 2].unpack1('v'),
      data[offset + 26, 2].unpack1('v')
    )
  end
end

#load_sectors(data) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/doom/map/data.rb', line 167

def load_sectors(data)
  count = data.size / 26
  count.times do |i|
    offset = i * 26
    @sectors << Sector.new(
      data[offset, 2].unpack1('s<'),
      data[offset + 2, 2].unpack1('s<'),
      data[offset + 4, 8].delete("\x00").strip,
      data[offset + 12, 8].delete("\x00").strip,
      data[offset + 20, 2].unpack1('v'),
      data[offset + 22, 2].unpack1('v'),
      data[offset + 24, 2].unpack1('v')
    )
  end
end

#load_segs(data) ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/doom/map/data.rb', line 183

def load_segs(data)
  count = data.size / 12
  count.times do |i|
    offset = i * 12
    @segs << Seg.new(
      data[offset, 2].unpack1('v'),
      data[offset + 2, 2].unpack1('v'),
      data[offset + 4, 2].unpack1('s<'),
      data[offset + 6, 2].unpack1('v'),
      data[offset + 8, 2].unpack1('v'),
      data[offset + 10, 2].unpack1('s<')
    )
  end
end

#load_sidedefs(data) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/doom/map/data.rb', line 152

def load_sidedefs(data)
  count = data.size / 30
  count.times do |i|
    offset = i * 30
    @sidedefs << Sidedef.new(
      data[offset, 2].unpack1('s<'),
      data[offset + 2, 2].unpack1('s<'),
      data[offset + 4, 8].delete("\x00").strip,
      data[offset + 12, 8].delete("\x00").strip,
      data[offset + 20, 8].delete("\x00").strip,
      data[offset + 28, 2].unpack1('v')
    )
  end
end

#load_subsectors(data) ⇒ Object



198
199
200
201
202
203
204
205
206
207
# File 'lib/doom/map/data.rb', line 198

def load_subsectors(data)
  count = data.size / 4
  count.times do |i|
    offset = i * 4
    @subsectors << Subsector.new(
      data[offset, 2].unpack1('v'),
      data[offset + 2, 2].unpack1('v')
    )
  end
end

#load_things(data) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/doom/map/data.rb', line 111

def load_things(data)
  count = data.size / 10
  count.times do |i|
    offset = i * 10
    @things << Thing.new(
      data[offset, 2].unpack1('s<'),
      data[offset + 2, 2].unpack1('s<'),
      data[offset + 4, 2].unpack1('v'),
      data[offset + 6, 2].unpack1('v'),
      data[offset + 8, 2].unpack1('v')
    )
  end
end

#load_vertices(data) ⇒ Object



125
126
127
128
129
130
131
132
133
134
# File 'lib/doom/map/data.rb', line 125

def load_vertices(data)
  count = data.size / 4
  count.times do |i|
    offset = i * 4
    @vertices << Vertex.new(
      data[offset, 2].unpack1('s<'),
      data[offset + 2, 2].unpack1('s<')
    )
  end
end

#player_startObject



238
239
240
# File 'lib/doom/map/data.rb', line 238

def player_start
  @things.find { |t| t.type == 1 }
end

#sector_at(x, y) ⇒ Object

Find the sector at a given position by traversing the BSP tree



243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/doom/map/data.rb', line 243

def sector_at(x, y)
  subsector = subsector_at(x, y)
  return nil unless subsector

  # Get sector from first seg of subsector
  seg = @segs[subsector.first_seg]
  return nil unless seg

  linedef = @linedefs[seg.linedef]
  sidedef_idx = seg.direction == 0 ? linedef.sidedef_right : linedef.sidedef_left
  return nil if sidedef_idx < 0

  @sectors[@sidedefs[sidedef_idx].sector]
end

#subsector_at(x, y) ⇒ Object

Find the subsector containing a point



259
260
261
262
263
264
265
266
267
# File 'lib/doom/map/data.rb', line 259

def subsector_at(x, y)
  node_idx = @nodes.size - 1
  while (node_idx & Node::SUBSECTOR_FLAG) == 0
    node = @nodes[node_idx]
    side = point_on_side(x, y, node)
    node_idx = side == 0 ? node.child_right : node.child_left
  end
  @subsectors[node_idx & ~Node::SUBSECTOR_FLAG]
end