IceDragon200

TMX Tilemap (WIP)

Aug 24th, 2011
223
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 9.33 KB | None | 0 0
  1. class ISS::TMX_Tilemap
  2.  
  3.   A1SID = 1
  4.   A2SID = 769
  5.   A3SID = 1537
  6.   A4SID = 2049
  7.   A5SID = 3009
  8.   BSID  = 3521
  9.   CSID  = 4545
  10.   DSID  = 5569
  11.   ESID  = 6593
  12.  
  13.   PARENT_IDS = []
  14.   TILESET = []
  15.  
  16.   PARENT_IDS[0] = 0
  17.   TILESET[0] = 5
  18.   (A1SID...A2SID).to_a.each { |i|
  19.     PARENT_IDS[i] = A1SID
  20.     TILESET[i] = 0#:a1
  21.   }
  22.   (A2SID...A3SID).to_a.each { |i|
  23.     PARENT_IDS[i] = A2SID
  24.     TILESET[i] = 1#:a2
  25.   }  
  26.   (A3SID...A4SID).to_a.each { |i|
  27.     PARENT_IDS[i] = A3SID
  28.     TILESET[i] = 2#:a3
  29.   }
  30.   (A4SID...A5SID).to_a.each { |i|
  31.     PARENT_IDS[i] = A4SID
  32.     TILESET[i] = 3#:a4
  33.   }
  34.   (A5SID...BSID).to_a.each { |i|
  35.     PARENT_IDS[i] = A5SID
  36.     TILESET[i] = 4#:a5
  37.   }
  38.   (BSID...CSID).to_a.each { |i|
  39.     PARENT_IDS[i] = BSID
  40.     TILESET[i] = 5#:b
  41.   }
  42.   (CSID...DSID).to_a.each { |i|
  43.     PARENT_IDS[i] = CSID
  44.     TILESET[i] = 6#:c
  45.   }
  46.   (DSID...ESID).to_a.each { |i|
  47.     PARENT_IDS[i] = DSID
  48.     TILESET[i] = 7#:d
  49.   }
  50.   (ESID...(ESID+2024)).to_a.each { |i|
  51.     PARENT_IDS[i] = ESID
  52.     TILESET[i] = 8#:e
  53.   }
  54.  
  55.   TILESIZE = 16
  56.  
  57.   BoxStruct = Struct.new( :width, :height )
  58.  
  59.   class MapStruct
  60.    
  61.     class LayerStruct
  62.       attr_accessor :group, :type, :map_zs, :parameters
  63.     end
  64.    
  65.     attr_accessor :map_data, :layer_props, :bitmaps
  66.     attr_accessor :layer_structs
  67.     attr_accessor :total_layers
  68.    
  69.     def width()  ; return self.map_data.xsize ; end
  70.     def height() ; return self.map_data.ysize ; end
  71.      
  72.     def setup_layers()
  73.       @layer_structs = [] # // Each key is the layer group
  74.       @total_layers = 0      
  75.       for i in 0...(self.layer_props.size)
  76.         a = self.layer_props[i] # // a subarray
  77.         @__lg = nil
  78.         # // First check is to setup the struct
  79.         a.each { |e|
  80.           case e[0]
  81.           when :layergroup
  82.             @layer_structs[e[1]] ||= LayerStruct.new()
  83.             (@layer_structs[e[1]].map_zs ||= []) << i
  84.             @__lg = e[1]
  85.             @layer_structs[@__lg].parameters ||= []
  86.             @layer_structs[@__lg].group ||= @__lg
  87.             @layer_structs[@__lg].type ||= :normal
  88.           end
  89.         }  
  90.         # // Second check is for sub properties  
  91.         a.each { |e|  
  92.           case e[0]
  93.           when :animlayer  
  94.             @layer_structs[@__lg].parameters << [i, e[1]]
  95.             @layer_structs[@__lg].type = :anim
  96.           end  
  97.         }
  98.       end
  99.       @total_layers = ((@layer_structs.inject([]) { |r, i| r << i.group }).max) + 1
  100.       @layer_structs.each { |e|
  101.         e.parameters.sort! { |a, b| a[1] <=> b[1] } if e.type == :anim
  102.       }
  103.     end
  104.    
  105.     def layer_type( l ) ; return @layer_structs[l].type ; end
  106.     def layer_bmp_count( l )
  107.       return 1 unless layer_type( l ) == :anim
  108.       return (@layer_structs[l].parameters.inject(0) { |r, pz|
  109.        r = pz[1] if pz[1] > r ; r }) + 1
  110.     end  
  111.    
  112.   end
  113.  
  114.   def self.get_tilebit( index, sbitmap )
  115.     bitmap = Bitmap.new( TILESIZE, TILESIZE )
  116.     bitmap.blt( 0, 0,
  117.       sbitmap, Rect.new(
  118.        TILESIZE * (index % (sbitmap.width/TILESIZE)),
  119.        TILESIZE * (index / (sbitmap.width/TILESIZE)),
  120.        TILESIZE, TILESIZE )
  121.     )
  122.     return bitmap
  123.   end
  124.  
  125.   def self.read_tileset_tmx( filename )
  126.     File.open( filename ) { |f|
  127.       f.each_line { |l|
  128.         case l
  129.         when /<image source="(.*)" width="(\d+)" height="(\d+)"\/>/i
  130.           return $1
  131.         end  
  132.       }
  133.     }
  134.   end
  135.  
  136.   def self.read_tmx( filename )
  137.     @__layer_id   = -1
  138.     @__read_layer = 0
  139.     @__tcount     = 0
  140.     @__x_count    = 0
  141.     @__y_count    = 0
  142.     @__layers     = []
  143.     @__bitmaps    = []
  144.     @__layerprops = []
  145.     @__readprops  = 0
  146.     File.open( filename ) { |f|
  147.       f.each_line { |l|
  148.         #puts l
  149.         case l
  150.         when /<map version="(.*)" orientation="(\w+)" width="(\d+)" height="(\d+)" tilewidth="(\d+)" tileheight="(\d+)">/i
  151.           @__map = Table.new( $3.to_i, $4.to_i, 1 ) { 0 }
  152.           @__box = BoxStruct.new( $3.to_i, $4.to_i )
  153.         when /<layer name="(.*)" width="(\d+)" height="(\d+)"/i # >
  154.           @__layer_id += 1
  155.           @__layerprops[@__layer_id] ||= []
  156.           @__layers[@__layer_id] = Table.new( @__map.xsize, @__map.ysize )
  157.           @__tcount = 0
  158.         when /<properties>/i
  159.           @__readprops = 1
  160.         when /<\/properties>/i
  161.           @__readprops = 0  
  162.         when /<property name="(.*)" value="(.*)"\/>/i
  163.           next unless @__readprops == 1
  164.           pr, vl = $1, $2
  165.           case pr.upcase
  166.           when "LAYERGROUP"
  167.             @__layerprops[@__layer_id] << [:layergroup, vl.to_i]
  168.           when "ANIMLAYER"  
  169.             @__layerprops[@__layer_id] << [:animlayer, vl.to_i]
  170.           end  
  171.         when /<tileset firstgid="(\d+)" source="(.*)"\/>/i
  172.           @__bitmaps << read_tileset_tmx("Graphics/System/extra_tiles/"+$2)
  173.         when /<data>/i
  174.           @__read_layer = 1
  175.         when /<\/data>/i
  176.           @__read_layer = 0
  177.         when /<tile gid="(\d+)"\/>/i
  178.           tid = $1.to_i
  179.           next unless @__read_layer == 1
  180.           @__x_count = (@__tcount % @__box.width)
  181.           @__y_count = (@__tcount / @__box.width)
  182.           @__layers[@__layer_id][@__x_count, @__y_count] = tid
  183.           @__tcount += 1
  184.         end  
  185.       }
  186.     }
  187.     @__map.resize( @__box.width, @__box.height, @__layers.size )
  188.     for x in 0...@__map.xsize
  189.       for y in 0...@__map.ysize
  190.         for z in 0...@__map.zsize
  191.           @__map[x, y, z] = @__layers[z][x, y]
  192.         end
  193.       end
  194.     end
  195.     ms = MapStruct.new()
  196.     ms.map_data    = @__map
  197.     ms.layer_props = @__layerprops
  198.     ms.bitmaps     = @__bitmaps
  199.     ms.setup_layers()
  200.     return ms
  201.   end
  202.  
  203.   attr_accessor :ox
  204.   attr_accessor :oy
  205.   attr_accessor :z
  206.   attr_reader :viewport
  207.  
  208.   def initialize( viewport )
  209.     @viewport        = viewport
  210.     @disposed        = false
  211.     @layers          = []
  212.     @layer_bitmaps   = []
  213.     @bitmaps         = []
  214.     @ox, @oy         = 0, 0
  215.     @z               = 0
  216.     @map_struct      = nil
  217.     @anim_rate       = 12
  218.     @anim_index      = Graphics.frame_count / @anim_rate
  219.     @last_anim_index = -1
  220.   end
  221.  
  222.   def viewport=( newview )
  223.     @viewport = newview
  224.     @layers.each { |l| l.viewport = @viewport }
  225.   end
  226.  
  227.   def create_layer_bitmap()
  228.     return Bitmap.new(@map_data.xsize*TILESIZE, @map_data.ysize*TILESIZE)
  229.   end
  230.  
  231.   # // MapStruct
  232.   def setup( map_struct )
  233.     @map_struct = map_struct
  234.     @map_data   = map_struct.map_data
  235.     bitmaps     = map_struct.bitmaps
  236.     @layers.each { |l| l.dispose() } ; @layers.clear()
  237.     @layer_bitmaps.each { |a| a.each { |b| b.dispose() } } ; @layer_bitmaps.clear()
  238.     ans = @map_struct.total_layers
  239.     ans.times { |i|
  240.       @layers[i] = Plane.new()
  241.       @layer_bitmaps[i] = []
  242.       case @map_struct.layer_type(i)
  243.       when :anim
  244.         @map_struct.layer_bmp_count(i).times { @layer_bitmaps[i] << create_layer_bitmap() }
  245.       when :normal  
  246.         @layer_bitmaps[i] = [create_layer_bitmap()]
  247.       end  
  248.     }
  249.     @layers.each { |l| l.viewport = @viewport }
  250.     @bitmaps = bitmaps.inject([]) { |r, e| r << Cache.system("extra_tiles/"+e) }
  251.     refresh_layer_bitmaps()
  252.     refresh()
  253.   end
  254.  
  255.   def layer_z( i )
  256.     @map_struct.layer_structs[i].group * 50
  257.   end
  258.  
  259.   def refresh_layer_bitmaps
  260.     for i in 0...@layers.size ; refresh_layer_bitmap( i ) ; end
  261.   end
  262.  
  263.   def refresh_layer_bitmap( i )
  264.     @layers[i].bitmap = @layer_bitmaps[i][@anim_index%@layer_bitmaps[i].size]
  265.   end
  266.  
  267.   def draw_tile( x, y, tile_id, bitmap )
  268.     b = self.class.get_tilebit( tile_id-PARENT_IDS[tile_id], @bitmaps[TILESET[tile_id]] )
  269.     bitmap.blt( x*TILESIZE, y*TILESIZE, b, b.rect ) ; b.dispose()
  270.   end
  271.  
  272.   def get_layer_id( z )
  273.     return @map_struct.layer_props[z].inject( 0 ) { |r,a|
  274.       r = a[1] if a[0] == :layergroup ; r
  275.     }
  276.   end
  277.  
  278.   def refresh()
  279.     for x in 0...@map_data.xsize
  280.       for y in 0...@map_data.ysize
  281.         for ly in 0...@map_struct.total_layers
  282.           case @map_struct.layer_type(ly)
  283.           when :anim
  284.             for ma in @map_struct.layer_structs[ly].parameters
  285.               z = ma[0]
  286.               next unless @map_data[x, y, z] > 0
  287.               draw_tile( x, y,
  288.                @map_data[x, y, z], @layer_bitmaps[get_layer_id(z)][ma[1]] )
  289.             end  
  290.           when :normal
  291.             for mz in @map_struct.layer_structs[ly].map_zs
  292.               next unless @map_data[x, y, mz] > 0
  293.               draw_tile( x, y,
  294.                @map_data[x, y, mz], @layer_bitmaps[get_layer_id(mz)][0] )
  295.             end
  296.           end            
  297.         end
  298.       end
  299.     end
  300.   end
  301.  
  302.   def disposed?() ; return @disposed ; end
  303.    
  304.   def dispose()
  305.     @layers.each { |l| l.dispose() }
  306.     @disposed = true
  307.   end
  308.  
  309.   def update()
  310.     @anim_index = Graphics.frame_count / @anim_rate
  311.     for i in 0...@layers.size
  312.       refresh_layer_bitmap( i ) if @last_anim_index != @anim_index
  313.       @layers[i].ox, @layers[i].oy, @layers[i].z = self.ox, self.oy, self.z + layer_z(i)
  314.     end
  315.     @last_anim_index = @anim_index
  316.   end
  317.  
  318. end  
  319.  
  320. mp = ISS::TMX_Tilemap.read_tmx( "testmap.tmx" )
  321. tilemap = ISS::TMX_Tilemap.new( Viewport.new( 0, 0, mp.width*16, mp.height*16 ) )
  322. tilemap.setup( mp ) # // MapStruct
  323. tilemap.z = 100
  324.  
  325. loop do
  326.  
  327.   Graphics.update()
  328.   tilemap.update
  329.   #tilemap.ox += 1
  330.   #tilemap.oy += 1
  331.  
  332. end
Advertisement
Add Comment
Please, Sign In to add comment