じ☆ve冰风 发表于 2024-4-19 16:39:22

支援RMXP的Tilemap

終於將RMXP的Tilemap研究出來了
跟原版的差不多
但在使用flash_data的部份有點卡
希望能討論下
畢竟RUBY不能贏VC
以下是腳本class TilemapWIN_W = 640WIN_H = 480AREA_W = 32AREA_H = 32AREA_X = WIN_W / AREA_WAREA_Y = WIN_H / AREA_HANI_T = 20#動畫等待時間(單位:畫格)FLA_T = 4   #閃爍等待時間(單位:畫格)FLA_O= #畫面閃爍變化#畫自動元件用AUTO_XY = [    , , , ,      , , , ,      , , , ,      , , , ,      , , , ,      , , , ,      , , , ,      , , , ,      , , , ,      , , , ,      , , , ,      , , , ]#--------------------------------------------------------------------------# ● 定義外部變數#--------------------------------------------------------------------------attr_accessor :autotilesattr_accessor :tilesetattr_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 = falseend#--------------------------------------------------------------------------# ● 釋放#--------------------------------------------------------------------------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 = trueenddef dispose?    return @@disposedend#--------------------------------------------------------------------------# ● 載入地圖資訊# 載入後繪製地圖#--------------------------------------------------------------------------def map_data    return @map_dataenddef 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)    #    end    #end    #end    # 建立地圖元件Cache(方法一) END    # 建立地圖元件Cache(方法二) BEGIN    # 元件圖較大時不適用    for auto in 0..6      next if @autotiles.nil?      for i in 0...48      cache_bitmap(auto * 48 + i)      end    end    if @tileset != nil      for y in / 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 = .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    return if id == 0    unless @@sprite[].nil?      @@sprite[].x = x0 * AREA_W - @ox      @@sprite[].y = y0 * AREA_H - @oy      return if @priorities.nil?      z = @priorities == 0 ? 0 : 32 * (1 + @@sprite[].y / AREA_H + @priorities)      z = 0 if z < 0       @@sprite[].z = z      return    end    @@sprite[] = Sprite.new(@viewport)    @@sprite[].x = x0 * AREA_W - @ox    @@sprite[].y = y0 * AREA_H - @oy    @@sprite[].z = l    @@sprite[].bitmap = cache_bitmap(id)    if id < 384      if @@cache.length > 1      #動畫      @@ani_switch[] = true      @@sprite[].bitmap = @@cache[@@count % @@cache.length]      end    end    return if @priorities.nil?    z = @priorities == 0 ? 0 : 32 * (1 + @@sprite[].y / AREA_H + @priorities)    z = 0 if z < 0   @@sprite[].z = zend#--------------------------------------------------------------------------# ● 繪製地圖元件閃爍#--------------------------------------------------------------------------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 @oxenddef oy    return @oyenddef 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 @oxenddef 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 @oyend#--------------------------------------------------------------------------# ● 設定地圖顯示#--------------------------------------------------------------------------def visible    return @visibleenddef visible=(value)    @visible = value    for i in @@sprite.values      i.visible = @visible    end    @@flash_layer.visible = @visible    return @visibleend#--------------------------------------------------------------------------# ● 更新地圖元件閃爍#--------------------------------------------------------------------------def flash_data    return @flash_dataenddef flash_data=(data)    return @flash_data if @flash_data == data    @flash_data = data    draw_flash    return @flash_dataend#--------------------------------------------------------------------------# ● 更新地圖元件#--------------------------------------------------------------------------def update    # 更新動畫等待畫格    if @@counting >= ANI_T      @@counting = 0      @@count += 1      for i in @@ani_switch.keys      id = @map_data, i, i]      @@sprite.bitmap = @@cache[@@count % @@cache.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,i]   if @priorities != 0       @@sprite.z = @priorities == 0 ? 0 : 32 * (1 + @@sprite.y / AREA_H + @priorities)       @@sprite.update   end    endend#--------------------------------------------------------------------------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..del_range_x      next if draw_range_x > x && x < draw_range_x      for y in del_range_y..del_range_y      next if draw_range_y > y && y < draw_range_y      for l in 0..2          next if @@sprite[].nil?          @@sprite[].dispose          @@sprite.delete()          @@ani_switch.delete()      end      end    end    #釋放元件 END    #恢復走路時候的偏移 BEGIN    if @ox >= (@map_data.xsize * AREA_W - WIN_W)      for i in @@sprite.keys      @@sprite.ox = 0      @@sprite.x = i * AREA_W - @ox      if i < (@ox / 32 - 1)          @@sprite.x += @map_data.xsize * AREA_W      elsif i == -1          @@sprite.x = 0      end      end    else      for i in @@sprite.keys      @@sprite.ox = 0      @@sprite.x = i * AREA_W - @ox      end    end    #恢復走路時候的偏移 END    #繪製元件 BEGIN    for x in draw_range_x..draw_range_x      for y in draw_range_y..draw_range_y      for l in 0..2          draw(x, y, l)      end      end    end    #繪製元件 ENDend#--------------------------------------------------------------------------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..del_range_x      next if draw_range_x > x && x < draw_range_x      for y in del_range_y..del_range_y      next if draw_range_y > y && y < draw_range_y      for l in 0..2          next if @@sprite[].nil?          @@sprite[].dispose          @@sprite.delete()          @@ani_switch.delete()      end      end    end    #釋放元件 END    #恢復走路時候的偏移 BEGIN    if @oy >= (@map_data.ysize * AREA_H - WIN_H)      for i in @@sprite.keys      @@sprite.oy = 0      @@sprite.y = i * AREA_H - @oy      if i < (@oy / 32 - 1)          @@sprite.y += @map_data.ysize * AREA_H      elsif i == -1          @@sprite.y = 0      end      end    else      for i in @@sprite.keys      @@sprite.oy = 0      @@sprite.y = i * AREA_H - @oy      end    end    #恢復走路時候的偏移 END    #繪製元件 BEGIN    for x in draw_range_x..draw_range_x      for y in draw_range_y..draw_range_y      for l in 0..2          draw(x, y, l)      end      end    end    #繪製元件 ENDendend复制代码ps:
640*480 fps 在38左右
800*600 fps 在35左右
             本帖来自P1论坛作者david50407,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg.blue/forum.php?mod=viewthread&tid=127629若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。
页: [1]
查看完整版本: 支援RMXP的Tilemap