mirror of
https://github.com/cyberarm/i-mic-rts.git
synced 2025-12-13 06:52:33 +00:00
144 lines
3.6 KiB
Ruby
144 lines
3.6 KiB
Ruby
class IMICRTS
|
|
class TiledMap
|
|
attr_reader :width, :height, :tile_size
|
|
attr_reader :layers, :tilesets, :spawnpoints
|
|
def initialize(map_file)
|
|
@xml = Nokogiri::XML(File.read("#{IMICRTS::ASSETS_PATH}/#{map_file}"))
|
|
|
|
@width, @height = 0, 0
|
|
@tile_size = 32
|
|
|
|
@layers = []
|
|
@tilesets = []
|
|
@spawnpoints = []
|
|
|
|
@tiles = []
|
|
|
|
parse
|
|
|
|
terrain = @layers.find { |layer| layer.name.downcase == "terrain" }
|
|
@width, @height = terrain.width, terrain.height
|
|
|
|
@tilesets.each do |tileset|
|
|
@tiles.push(*tileset.tiles)
|
|
end
|
|
|
|
@xml = nil
|
|
end
|
|
|
|
def parse
|
|
@xml.search("//tileset").each do |tileset|
|
|
@tilesets << TileSet.new(tileset)
|
|
end
|
|
|
|
@xml.search("//layer").each do |layer|
|
|
@layers << Layer.new(layer)
|
|
end
|
|
|
|
@xml.search("//objectgroup").each do |objectgroup|
|
|
if objectgroup.attr("name") == "spawns"
|
|
objectgroup.children.each do |object|
|
|
next unless object.attr("name") && object.attr("name").downcase.strip == "spawn"
|
|
@spawnpoints << SpawnPoint.new(object)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def get_tile(tile_id)
|
|
return nil if tile_id < 0
|
|
|
|
@tiles.dig(tile_id)
|
|
end
|
|
|
|
|
|
|
|
class Layer
|
|
attr_reader :name, :width, :height
|
|
def initialize(xml_layer)
|
|
@name = xml_layer["name"]
|
|
@width, @height = Integer(xml_layer["width"]), Integer(xml_layer["height"])
|
|
@data = []
|
|
|
|
xml_layer.css("data").inner_html.each_line do |line|
|
|
@data.push(*line.strip.split(",").map { |id| Integer(id) })
|
|
end
|
|
end
|
|
|
|
def data(x, y)
|
|
@data[x + y * @width]
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
class TileSet
|
|
attr_reader :first_gid, :name, :tile_width, :tile_height, :tile_count, :columns, :rows
|
|
attr_reader :tiles
|
|
Tile = Struct.new(:image, :data)
|
|
def initialize(xml_tileset)
|
|
@first_gid = nil
|
|
@tiles = []
|
|
|
|
xml_tileset.attributes.each do |name, attrib|
|
|
case name
|
|
when "firstgid"
|
|
@first_gid = Integer(attrib.value)
|
|
when "source"
|
|
parse(attrib.value)
|
|
end
|
|
end
|
|
end
|
|
|
|
def parse(file)
|
|
xml = Nokogiri::XML(File.read("#{IMICRTS::ASSETS_PATH}/#{file.sub("../", "")}"))
|
|
tileset = xml.search("//tileset").first
|
|
|
|
data = {}
|
|
tileset.attributes.each { |attrib, value| data[attrib] = value.value }
|
|
|
|
data.each do |key, value|
|
|
case key
|
|
when "name"
|
|
@name = value
|
|
when "tilewidth"
|
|
@tile_width = Integer(value)
|
|
when "tileheight"
|
|
@tile_height = Integer(value)
|
|
when "tilecount"
|
|
@tile_count = Integer(value)
|
|
when "columns"
|
|
@columns = Integer(value)
|
|
when "rows"
|
|
@rows = Integer(value)
|
|
end
|
|
end
|
|
|
|
path = tileset.search("//image").first.attributes.detect { |a, v| a == "source" }.last.value
|
|
images = Gosu::Image.load_tiles("#{IMICRTS::ASSETS_PATH}/tilesets/#{path}", @tile_width, @tile_height, retro: true)
|
|
|
|
tileset.search("//tile").each_with_index do |xml, index|
|
|
tile = Tile.new
|
|
tile.image = images[index]
|
|
tile.data = FriendlyHash.new
|
|
|
|
xml.attributes.each do |name, data|
|
|
tile.data[name.to_sym] = data.value if name == "type"
|
|
end
|
|
|
|
@tiles << tile
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class SpawnPoint
|
|
attr_reader :x, :y
|
|
def initialize(xml_object)
|
|
@x, @y = Integer(xml_object.attr("x")), Integer(xml_object.attr("y"))
|
|
end
|
|
end
|
|
end
|
|
end |