class Tilemap WIN_W = 640 WIN_H = 480 AREA_W = 32 AREA_H = 32 AREA_X = WIN_W / AREA_W AREA_Y = WIN_H / AREA_H ANI_T = 20 #動畫等待時間(單位:畫格) FLA_T = 4 #閃爍等待時間(單位:畫格) FLA_O=[110,100,90,80,70,80,90,100] #畫面閃爍變化 #畫自動元件用 AUTO_XY = [ [8, 8, 8, 8], [3, 8, 8, 8], [8, 3, 8, 8], [3, 3, 8, 8], [8, 8, 8, 3], [3, 8, 8, 3], [8, 3, 8, 3], [3, 3, 8, 3], [8, 8, 3, 8], [3, 8, 3, 8], [8, 3, 3, 8], [3, 3, 3, 8], [8, 8, 3, 3], [3, 8, 3, 3], [8, 8, 3, 3], [3, 3, 3, 3], [7, 7, 7, 7], [7, 3, 7, 7], [7, 7, 7, 3], [7, 3, 7, 3], [5, 5, 5, 5], [5, 5, 5, 3], [5, 5, 3, 5], [5, 5, 3, 3], [9, 9, 9, 9], [9, 9, 3, 9], [3, 9, 9, 9], [3, 9, 3, 9], [11, 11, 11, 11], [3, 11, 11, 11], [11, 3, 11, 11], [3, 3, 11, 11], [7, 9, 7, 9], [5, 5, 11, 11], [4, 4, 4, 4], [4, 4, 4, 3], [6, 6, 6, 6], [6, 6, 3, 6], [12, 12, 12, 12], [3, 12, 12, 12], [10, 10, 10, 10], [10, 3, 10, 10], [4, 6, 4, 6], [4, 4, 10, 10], [10, 12, 10, 12], [6, 6, 12, 12], [4, 6, 10, 12], [1, 1, 1, 1] ] #-------------------------------------------------------------------------- # ● 定義外部變數 #-------------------------------------------------------------------------- attr_accessor :autotiles attr_accessor :tileset attr_reader :viewport #-------------------------------------------------------------------------- # ● 初始化物件 # 內部使用以 @@ 開頭 #-------------------------------------------------------------------------- def initialize(viewport = Viewport.new(0,0,WIN_W,WIN_H)) @autotiles = [] @tileset = nil @map_data = nil @flash_data = nil @priorities = nil @visible = true @ox = 0 @oy = 0 @viewport = viewport @@sprite = {} #元件Sprite @@cache = {} #元件Cache @@ani_switch = {} #動畫開關 @@count = 0 #當前顯示動畫 @@counting = 0 #動畫等待畫格 @@flash_layer = nil #畫面閃爍用 @@flash_count = 0 #當前閃爍動畫 @@flash_counting = 0 #閃爍等待畫格 @@last_ox = 0 @@last_oy = 0 @@disposed = false end #-------------------------------------------------------------------------- # ● 釋放 #-------------------------------------------------------------------------- def dispose return if @@disposed for i in @@cache.values if i.is_a?(Bitmap) i.dispose else for j in i.values j.dispose end end end for i in @@sprite.values i.dispose end @@flash_layer.dispose if @@flash_layer != nil @@flash_layer.bitmap.dispose if @@flash_layer != nil @@disposed = true end def dispose? return @@disposed end #-------------------------------------------------------------------------- # ● 載入地圖資訊 # 載入後繪製地圖 #-------------------------------------------------------------------------- def map_data return @map_data end def map_data=(data) @map_data = data return if @map_data.nil? # 建立地圖元件Cache(方法一) BEGIN # 地圖較大時不適用 #for x in 0...@map_data.xsize # for y in 0...@map_data.ysize # for l in 0..2 # cache_bitmap(@map_data[x, y, l]) # end # end #end # 建立地圖元件Cache(方法一) END # 建立地圖元件Cache(方法二) BEGIN # 元件圖較大時不適用 for auto in 0..6 next if @autotiles[auto].nil? for i in 0...48 cache_bitmap(auto * 48 + i) end end if @tileset != nil for y in [email protected] / AREA_H yy = y * 8 for x in 0...8 cache_bitmap(yy + x + 384) end end end # 建立地圖元件Cache(方法二) END # 描繪地圖元件 BEGIN range_x = (@ox + WIN_W) / AREA_W range_y = (@oy + WIN_H) / AREA_H range_x = [range_x, WIN_W / AREA_W - 1].min if @map_data.xsize * AREA_W = @map_data.xsize x += @map_data.xsize if x < 0 y -= @map_data.ysize if y >= @map_data.ysize y += @map_data.ysize if y < 0 id = @map_data[x, y, l] return if id == 0 unless @@sprite[[x, y, l]].nil? @@sprite[[x, y, l]].x = x0 * AREA_W - @ox @@sprite[[x, y, l]].y = y0 * AREA_H - @oy return if @priorities.nil? z = @priorities[id] == 0 ? 0 : 32 * (1 + @@sprite[[x, y, l]].y / AREA_H + @priorities[id]) z = 0 if z < 0 @@sprite[[x, y, l]].z = z return end @@sprite[[x, y, l]] = Sprite.new(@viewport) @@sprite[[x, y, l]].x = x0 * AREA_W - @ox @@sprite[[x, y, l]].y = y0 * AREA_H - @oy @@sprite[[x, y, l]].z = l @@sprite[[x, y, l]].bitmap = cache_bitmap(id) if id < 384 if @@cache[id].length > 1 #動畫 @@ani_switch[[x, y, l]] = true @@sprite[[x, y, l]].bitmap = @@cache[id][@@count % @@cache[id].length] end end return if @priorities.nil? z = @priorities[id] == 0 ? 0 : 32 * (1 + @@sprite[[x, y, l]].y / AREA_H + @priorities[id]) z = 0 if z < 0 @@sprite[[x, y, l]].z = z end #-------------------------------------------------------------------------- # ● 繪製地圖元件閃爍 #-------------------------------------------------------------------------- def draw_flash return if @flash_data.nil? return if @flash_data.xsize 0,'b'=>0} tmpcolor.set(rgb['r']*16,rgb['g']*16,rgb['b']*16) @@flash_layer.bitmap.fill_rect(x*AREA_W,y*AREA_H,AREA_W,AREA_H,tmpcolor) end end @@flash_layer.opacity=FLA_O[@@flash_count] end #-------------------------------------------------------------------------- # ● 設定地圖座標 #-------------------------------------------------------------------------- def ox return @ox end def oy return @oy end def ox=(ox) return if @ox == ox @@last_ox = @ox if @@last_ox == @ox @ox = ox @@flash_layer.ox = ox % WIN_W if @@flash_layer != nil return @ox end def oy=(oy) return if @oy == oy @@last_oy = @oy if @@last_oy == @oy @oy = oy @@flash_layer.oy = oy % WIN_H if @@flash_layer != nil return @oy end #-------------------------------------------------------------------------- # ● 設定地圖顯示 #-------------------------------------------------------------------------- def visible return @visible end def visible=(value) @visible = value for i in @@sprite.values i.visible = @visible end @@flash_layer.visible = @visible return @visible end #-------------------------------------------------------------------------- # ● 更新地圖元件閃爍 #-------------------------------------------------------------------------- def flash_data return @flash_data end def flash_data=(data) return @flash_data if @flash_data == data @flash_data = data draw_flash return @flash_data end #-------------------------------------------------------------------------- # ● 更新地圖元件 #-------------------------------------------------------------------------- def update # 更新動畫等待畫格 if @@counting >= ANI_T @@counting = 0 @@count += 1 for i in @@ani_switch.keys id = @map_data[i[0], i[1], i[2]] @@sprite[i].bitmap = @@cache[id][@@count % @@cache[id].length] end else @@counting += 1 end # 更新閃爍等待畫格 @@flash_counting += 1 if @@flash_counting >= FLA_T @@flash_counting = 0 @@flash_count = (@@flash_count + 1) % FLA_O.size @@flash_layer.opacity=FLA_O[@@flash_count] if @@flash_layer != nil end if @ox != @@last_ox #人物走路時候 if @ox % (AREA_W / 2) != 0 for i in @@sprite.values i.ox = @ox - @@last_ox end else refreshox @@last_ox = @ox end end if @oy != @@last_oy #人物走路時候 if @oy % AREA_H != 0 for i in @@sprite.values i.oy = @oy - @@last_oy end else refreshoy @@last_oy = @oy end end for i in @@sprite.keys id = @map_data[i[0],i[1],i[2]] if @priorities[id] != 0 @@sprite[i].z = @priorities[id] == 0 ? 0 : 32 * (1 + @@sprite[i].y / AREA_H + @priorities[id]) @@sprite[i].update end end end #-------------------------------------------------------------------------- def refreshox #需要釋放的元件範圍 del_range_y = [(@@last_oy / AREA_H - 1), ((@@last_oy + WIN_H) / AREA_H)] if @ox > @@last_ox del_range_x = [(@@last_ox / AREA_W - 1), (@ox / AREA_W - 2)] else del_range_x = [((@ox + WIN_W) / AREA_W + 1), ((@@last_ox + WIN_W) / AREA_W)] end #需要繪製的元件範圍 draw_range_y = [(@oy / AREA_H - 1), ((@oy + WIN_H) / AREA_H)] if @ox > @@last_ox draw_range_x = [[((@@last_ox + WIN_W) / AREA_W + 1), (@ox / AREA_W - 1)].max, ((@ox + WIN_W) / AREA_W)] else draw_range_x = [(@ox / AREA_W - 1), ([(@@last_ox / AREA_W - 1),(@ox + WIN_W) / AREA_W + 1].min - 1)] end #釋放元件 BEGIN for x in del_range_x[0]..del_range_x[1] next if draw_range_x[0] > x && x < draw_range_x[1] for y in del_range_y[0]..del_range_y[1] next if draw_range_y[0] > y && y < draw_range_y[1] for l in 0..2 next if @@sprite[[x, y, l]].nil? @@sprite[[x, y, l]].dispose @@sprite.delete([x, y, l]) @@ani_switch.delete([x, y, l]) end end end #釋放元件 END #恢復走路時候的偏移 BEGIN if @ox >= (@map_data.xsize * AREA_W - WIN_W) for i in @@sprite.keys @@sprite[i].ox = 0 @@sprite[i].x = i[0] * AREA_W - @ox if i[0] < (@ox / 32 - 1) @@sprite[i].x += @map_data.xsize * AREA_W elsif i[0] == -1 @@sprite[i].x = 0 end end else for i in @@sprite.keys @@sprite[i].ox = 0 @@sprite[i].x = i[0] * AREA_W - @ox end end #恢復走路時候的偏移 END #繪製元件 BEGIN for x in draw_range_x[0]..draw_range_x[1] for y in draw_range_y[0]..draw_range_y[1] for l in 0..2 draw(x, y, l) end end end #繪製元件 END end #-------------------------------------------------------------------------- def refreshoy #需要釋放的元件範圍 del_range_x = [(@@last_ox / AREA_W - 1), ((@@last_ox + WIN_W) / AREA_W)] if @oy > @@last_oy del_range_y = [(@@last_oy / AREA_H - 1), (@oy / AREA_H - 2)] else del_range_y = [((@oy + WIN_H) / AREA_H + 1), ((@@last_oy + WIN_H) / AREA_H)] end #需要繪製的元件範圍 draw_range_x = [(@ox / AREA_W - 1), ((@ox + WIN_W) / AREA_W)] if @oy > @@last_oy draw_range_y = [[((@@last_oy + WIN_H) / AREA_H + 1), (@oy / AREA_H - 1)].max, ((@oy + WIN_H) / AREA_H)] else draw_range_y = [(@oy / AREA_H - 1), ([(@@last_oy / AREA_H - 1),(@oy + WIN_H) / AREA_H + 1].min - 1)] end #釋放元件 BEGIN for x in del_range_x[0]..del_range_x[1] next if draw_range_x[0] > x && x < draw_range_x[1] for y in del_range_y[0]..del_range_y[1] next if draw_range_y[0] > y && y < draw_range_y[1] for l in 0..2 next if @@sprite[[x, y, l]].nil? @@sprite[[x, y, l]].dispose @@sprite.delete([x, y, l]) @@ani_switch.delete([x, y, l]) end end end #釋放元件 END #恢復走路時候的偏移 BEGIN if @oy >= (@map_data.ysize * AREA_H - WIN_H) for i in @@sprite.keys @@sprite[i].oy = 0 @@sprite[i].y = i[1] * AREA_H - @oy if i[1] < (@oy / 32 - 1) @@sprite[i].y += @map_data.ysize * AREA_H elsif i[1] == -1 @@sprite[i].y = 0 end end else for i in @@sprite.keys @@sprite[i].oy = 0 @@sprite[i].y = i[1] * AREA_H - @oy end end #恢復走路時候的偏移 END #繪製元件 BEGIN for x in draw_range_x[0]..draw_range_x[1] for y in draw_range_y[0]..draw_range_y[1] for l in 0..2 draw(x, y, l) end end end #繪製元件 END endend复制代码