赞 | 0 |
VIP | 40 |
好人卡 | 2 |
积分 | 1 |
经验 | 10932 |
最后登录 | 2016-5-17 |
在线时间 | 462 小时 |
Lv1.梦旅人
- 梦石
- 0
- 星屑
- 50
- 在线时间
- 462 小时
- 注册时间
- 2007-7-30
- 帖子
- 643
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 david50407 于 2009-7-5 14:55 编辑
終於將RMXP的Tilemap研究出來了
跟原版的差不多
但在使用flash_data的部份有點卡
希望能討論下
畢竟RUBY不能贏VC
以下是腳本- 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 <= WIN_W
- range_y = [range_y, WIN_H / AREA_H - 1].min if @map_data.ysize * AREA_H <= WIN_H
- for x in (@ox / AREA_W - 1)..range_x
- for y in (@oy / AREA_H - 1)..range_y
- for l in 0..2
- draw(x, y, l)
- end
- end
- end
- # 描繪地圖元件 END
- end
- #--------------------------------------------------------------------------
- # ● 載入地圖優先度
- # 載入後重整地圖元件Z座標
- #--------------------------------------------------------------------------
- def priorities
- return @priorities
- end
- def priorities=(value)
- @priorities = value
- return if @priorities.nil?
- for x in ([@ox / AREA_W - 1, 0].max)..((@ox + WIN_W) / AREA_W)
- for y in ([@oy / AREA_H - 1, 0].max)..((@oy + WIN_H) / AREA_H)
- for l in 0..2
- next if @@sprite[[x, y, l]].nil?
- id = @map_data[x, y, l]
- next if id.nil?
- next if id == 0
- 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
- end
- end
- end
- #--------------------------------------------------------------------------
- # ● 建立地圖元件Cache
- #--------------------------------------------------------------------------
- def cache_bitmap(id)
- if @@cache[id].nil?
- if id < 384 #自動元件的情況
- bitmapid = id / 48 - 1
- @@cache[id] = {}
- @@cache[id][0] = get_bitmap_a(id, bitmapid)
- if @autotiles[bitmapid].width > AREA_W * 3
- anis = @autotiles[bitmapid].width / AREA_W / 3
- for i in 1...anis
- @@cache[id][i] = get_bitmap_a(id, bitmapid, i)
- end
- end
- else #一般元件的情況
- @@cache[id] = get_bitmap(id)
- end
- end
- return @@cache[id][0] if @@cache[id].is_a?(Hash)
- return @@cache[id]
- end
- #--------------------------------------------------------------------------
- # ● 取得地圖元件Bitmap
- # get_bitmap : 取得一般地圖元件Bitmap
- # get_bitmap_a : 取得自動地圖元件Bitmap
- #--------------------------------------------------------------------------
- def get_bitmap(id)
- bitmap = Bitmap.new(AREA_W, AREA_H)
- rect = Rect.new((id - 384) % 8 * AREA_W, (id - 384) / 8 * AREA_H, AREA_W, AREA_H)
- bitmap.blt(0, 0, @tileset, rect)
- return bitmap
- end
- def get_bitmap_a(id, bitmapid, ani = 0)
- bitmap = Bitmap.new(AREA_W, AREA_H)
- pic_id = id % 48
- for i in 0..3
- rect_x = (AUTO_XY[pic_id][i] - 1) % 3
- rect_y = (AUTO_XY[pic_id][i] - 1) / 3
- rect_x *= AREA_W
- rect_y *= AREA_H
- x = i % 2
- y = i / 2
- x *= AREA_W / 2
- y *= AREA_H / 2
- rect = Rect.new(rect_x + x + (ani * AREA_W * 3), rect_y + y, AREA_W / 2, AREA_H / 2)
- bitmap.blt(x, y, @autotiles[bitmapid], rect)
- end
- return bitmap
- end
- #--------------------------------------------------------------------------
- # ● 繪製地圖元件
- #--------------------------------------------------------------------------
- def draw(x, y, l)
- x0 = x
- y0 = y
- # 數值修正
- x -= @map_data.xsize if x >= @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 <= -1 && @flash_data..ysize <= -1
- if @@flash_layer.nil?
- @@flash_layer = Plane.new(@viewport)
- @@flash_layer.blend_type = 1
- @@flash_layer.bitmap = Bitmap.new(@flash_data.xsize * AREA_W, @flash_data.ysize * AREA_H) if @@flash_layer.bitmap.nil?
- end
- @@flash_layer.z = 1
- tmpcolor = Color.new(0,0,0,0)
- for x in 0...@flash_data.xsize
- for y in 0...@flash_data.ysize
- rgb = {}
- %w(r g b).inject(@flash_data[x, y]) {|a,b| rest, rgb[b] = a.divmod(16); rest}
- next if rgb == {'r'=>0,'g'=>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
- end
- end
复制代码 ps:
640*480 fps 在38左右
800*600 fps 在35左右 |
|