Project1
标题:
請幫忙修改下(Tilemap)
[打印本页]
作者:
david50407
时间:
2009-7-4 13:50
标题:
請幫忙修改下(Tilemap)
本帖最后由 david50407 于 2009-7-5 14:39 编辑
因為最近在嘗試RMXP+RGSS2
所以又回來研究tilemap
根據上次寫的腳本重新寫過
但flash_data部分遇到了問題:
加上了draw_flash後,fps被吃掉了,而且還顯示不出效果(??)
以下是我寫的腳本,請大家幫忙看下
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 #動畫等待時間(單位:畫格)
#畫自動元件用
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]
]
#畫面閃爍用
FlashOpacity=[110,100,90,80,90,100]
#--------------------------------------------------------------------------
# ● 定義外部變數
#--------------------------------------------------------------------------
attr_accessor :autotiles
attr_accessor :tileset
attr_accessor :ox
attr_accessor :oy
attr_reader :dispose
#attr_reader :disposed?
attr_reader :viewport
#--------------------------------------------------------------------------
# ● 初始化物件
# 內部使用以 @@ 開頭
#--------------------------------------------------------------------------
def initialize(viewport = Viewport.new())
@autotiles = []
@tileset = nil
@map_data = nil
@flash_data = nil
@priorities = nil
@visible = true
@ox = 0
@oy = 0
@dispose = nil
@viewport = viewport
@@sprite = {} #元件Sprite
@@cache = {} #元件Cache
@@ani_switch = {} #動畫開關
@@count = 0 #當前顯示動畫
@@counting = 0 #動畫等待畫格
@@flash_layer = {} #畫面閃爍用
@@last_ox = 0
@@last_oy = 0
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)
#繪製元件閃爍
draw_flash(x, y)
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(x, y)
return if @flash_data.nil?
return if @flash_data[x, y].nil?
unless @@flash_layer[[x,y]].nil?
@@flash_layer[[x,y]].x = x * AREA_W - @ox
@@flash_layer[[x,y]].y = y * AREA_H - @oy
@@flash_layer[[x,y]].opacity=FlashOpacity[(Graphics.frame_count/4) % FlashOpacity.size]
return
end
@@flash_layer[[x,y]] = Sprite.new(@viewport)
@@flash_layer[[x,y]].x = x * AREA_W - @ox
@@flash_layer[[x,y]].y = y * AREA_H - @oy
@@flash_layer[[x,y]].z = 1
@@flash_layer[[x,y]].opacity=FlashOpacity[(Graphics.frame_count/4) % FlashOpacity.size]
rgb = {}
%w(r g b).inject(@flash_data[x, y]) {|a,b| rest, rgb[b] = a.divmod(16); rest}
return if rgb == {'r'=>0,'g'=>0,'b'=>0}
tmpcolor = Color.new(rgb['r']*16,rgb['g']*16,rgb['b']*16,0)
if @@cache[-@flash_data[x, y]].nil?
@@cache[-@flash_data[x, y]] = Bitmap.new(AREA_W,AREA_H)
@@cache[-@flash_data[x, y]].fill_rect(0,0,AREA_W,AREA_H,tmpcolor)
end
@@flash_layer[[x,y]].bitmap = @@cache[-@flash_data[x, y]]
end
#--------------------------------------------------------------------------
# ● 設定地圖座標
#--------------------------------------------------------------------------
def ox=(ox)
return if @ox == ox
@@last_ox = @ox if @@last_ox == @ox
@ox = ox
return @ox
end
def oy=(oy)
return if @oy == oy
@@last_oy = @oy if @@last_oy == @oy
@oy = oy
return @oy
end
#--------------------------------------------------------------------------
# ● 設定地圖顯示
#--------------------------------------------------------------------------
def visible
return @visible
end
def visible=(value)
@visible = value
for i in @@sprite.values
i.visible = @visible
end
return @visible
end
#--------------------------------------------------------------------------
# ● 更新地圖元件閃爍
#--------------------------------------------------------------------------
def flash_data
return @flash_data
end
def flash_data=(data)
@flash_data = data
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
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
elsif @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
for i in @@flash_layer.values
i.opacity=FlashOpacity[(Graphics.frame_count/4) % FlashOpacity.size]
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
@@flash_layer[[x, y]].dispose unless @@flash_layer[[x, y]].nil?
@@flash_layer.delete([x, y])
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
#恢復閃爍偏移
unless @flash_data.nil?
if @ox >= (@map_data.xsize * AREA_W - WIN_W)
for i in @flash_data.keys
@@flash_layer[i].ox = 0
@@flash_layer[i].x = i[0] * AREA_W - @ox
if i[0] < (@ox / 32 - 1)
@@flash_layer[i].x += @map_data.xsize * AREA_W
elsif i[0] == -1
@@flash_layer[i].x = 0
end
end
else
for i in @@flash_layer.keys
@@flash_layer[i].ox = 0
@@flash_layer[i].x = i[0] * AREA_W - @ox
end
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)
draw_flash(x, y)
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
@@flash_layer[[x, y]].dispose unless @@flash_layer[[x, y]].nil?
@@flash_layer.delete([x, y])
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
#恢復閃爍偏移
unless @flash_data.nil?
if @oy >= (@map_data.ysize * AREA_H - WIN_H)
for i in @flash_data.keys
@@flash_layer[i].oy = 0
@@flash_layer[i].y = i[1] * AREA_H - @oy
if i[1] < (@oy / 32 - 1)
@@flash_layer[i].y += @map_data.ysize * AREA_H
elsif i[1] == -1
@@flash_layer[i].y = 0
end
end
else
for i in @@flash_layer.keys
@@flash_layer[i].oy = 0
@@flash_layer[i].y = i[1] * AREA_H - @oy
end
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)
draw_flash(x, y)
end
end
end
#繪製元件 END
end
end
复制代码
作者:
david50407
时间:
2009-7-5 14:38
已修改完畢
http://rpg.blue/viewthread.php?tid=127629
欢迎光临 Project1 (https://rpg.blue/)
Powered by Discuz! X3.1