File: export_maps.rb

package info (click to toggle)
magicmaze 1.5.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 720 kB
  • sloc: ruby: 4,030; xml: 21; makefile: 2
file content (214 lines) | stat: -rw-r--r-- 5,109 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
require 'magicmaze/filemap'
require 'json'

require 'fileutils'

class MapExporter

  attr_reader :gamemap, :filemap  ##< Current map being processed.

  def initialize(filemap)
    @filemap = filemap
    @gamemap = filemap.to_gamemap
  end


  MAP_X_SIZE = ::MagicMaze::GameMap::MAP_X_SIZE
  MAP_Y_SIZE = ::MagicMaze::GameMap::MAP_Y_SIZE


  # https://github.com/bjorn/tiled/wiki/JSON-Map-Format
  def to_tiled_json
    @gamemap ||= filemap.to_gamemap

    {
      width:  MAP_X_SIZE,
      height: MAP_Y_SIZE,
      tilewidth: 32,
      tileheight: 32,
      orientation: 'orthogonal',  
      
      layers: [
        # The Background layer  # FIXME: What about invisible walls and hidden passages?
        {
          width:  MAP_X_SIZE,
          height: MAP_Y_SIZE,
          name: "Background",
          opacity: 1.0,
          type: "tilelayer",
          visible: true,
          x: 0,
          y: 0,
          properties: {},
          data:  background_layer_to_data
        },
        # TODO: Foreground layer separate?
        # Objects layer
        {
          width:  MAP_X_SIZE,
          height: MAP_Y_SIZE,
          name: "Objects",
          opacity: 1.0,
          type: "objectgroup",
          visible: true,
          x: 0,
          y: 0,
          properties: {},
          objects: object_layer_to_data,
          draworder: "topdown",
        },
        # Entities layer
        {
          width:  MAP_X_SIZE,
          height: MAP_Y_SIZE,
          name: "Entities",
          opacity: 1.0,
          type: "objectgroup",
          visible: true,
          x: 0,
          y: 0,
          objects: entity_layer_to_data,
          draworder: "topdown",
        },

      ],
      tilesets: [
        {
          firstgid: 1,  # NOTE: Tiled editor won't open if this is 0....
          image: "../../../data/gfx/sprites.png",
          imageheight: 288,
          imagewidth: 320,
          margin: 0,
          name: "sprites",
          properties:
            {
            },
          spacing: 0,
          tileheight: 32,
          tilewidth: 32,
          transparentcolor: "#000000"
        },

      ],
      backgroundcolor: "#222222", # string  Hex-formatted color (#RRGGBB) (Optional)
      # renderorder: "",  # string  Rendering direction (orthogonal maps only)
      properties: {
        start_x: gamemap.start_x,
        start_y: gamemap.start_y,
        title: filemap.title
      },
      nextobjectid: 1,  #  int Auto-increments for each placed object
      renderorder: "right-down",
      version: 1
    }
  end


  def background_layer_to_data
    data = []
    (0..gamemap.max_y).each do   |y|
      (0..gamemap.max_x).each do |x|
        tile =  gamemap.background.get( x, y )
        data << (tile && tile.sprite_id.to_i + 1) || 0
      end
    end
    unless data.size == 128*128
      raise "Data size inconsistent! #{ data.size } "
    end
    data
  end

  def object_layer_to_data
    list = []
    filemap.each_row do |row, y|  
      filemap.each_column do |x|
        obj =  gamemap.object.get( x, y )
        next unless obj
        data = 
            {
              gid: obj.sprite_id + 1, # FIXME: + ::MagicMaze::FileMap::MONSTER_NUMBER_BEGIN,
              x: x * 32,
              y: y * 32,
              height: 32, width: 32,
              type: obj.class.to_s.split(":").last,
              visible: true,
              properties: {
              },
            }
        list << data
      end
    end
    list
  end


  def entity_layer_to_data
    gamemap.active_entities.all.collect do |entity|
      {
        gid: entity.sprite_id + 1, # FIXME: + ::MagicMaze::FileMap::MONSTER_NUMBER_BEGIN,
        x: entity.location.x * 32,
        y: entity.location.y * 32,
        height: 32, width: 32,
        type: "Monster", # TODO: Any others here? # WAS: entity.class.to_s,
        visible: true,
        properties: {
        },
      }
    end
  end




  module ClassMethods
    # Iterate all default maps.
    def for_all_default_maps(upto=10)
      for_all_default_map_filenames(upto) {|filename|
        @filemap = MagicMaze::FileMap.new( filename )
        yield @filemap
        @filemap = nil
      }
    end

    ##
    # Iterate all default maps filenames.
    def for_all_default_map_filenames(upto=10)
      (1..upto).each do|level|
        @filename = sprintf "data/maps/mm_map.%03d", level
        yield @filename
        @filename = nil
      end
    end

    def perform
      output_dir = "data/maps/tiled/"
      map_count = 0

      FileUtils.mkdir_p(output_dir)

      for_all_default_maps do |map|
        map_count +=1 
        @filemap = map

        filename = output_dir + sprintf("mm_map%03d.json", map_count)

        tiled_map = self.new(map).to_tiled_json

        File.open(filename, 'w') do |output|
          puts "#{filename} ..."
          json_str = tiled_map.to_json
          # json_str = JSON.pretty_generate(tiled_map) # For debugging.
          output.puts json_str
        end
        @filemap = nil

      end
    end

  end # ClassMethods
  extend ClassMethods

end


MapExporter.perform