Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Tilemap script. Needed some feedback

Athlon x2 4200 (2.8 GHz)
Ram 2 GB Dual-channel
No video card (I toasted it, D:)
Windows XP SP2


First Map: 29-32 FPS
Second Map: 27-30 FPS
 

arev

Sponsor

38-39 FPS on both maps.
4GB RAM | Quad Core 2,4GHz | GeForce 7900 GS 512MB | Vista 64bit

Let me just say it's great to see so many of tilemap scripts. Some time ago it was a real pain in the ass to evercome it : )
 

RTH

Member

Here is another version of Tilemap class that i made long ago, it can update the autotiles either and the lag is even smaller. (But still got some in my PC that is a bit old)

Code:
#==============================================================================
# Tilemap
#------------------------------------------------------------------------------
# Author of THIS VERSION: RTH
#==============================================================================

class Tilemap
  
  # Autotile Update Rate
  AUTOTILE_UPDATE = 10
  
  # Autotiles Index (Dont Change these numbers)
  INDEX = [
    [ [27, 28, 33, 34], [ 5, 28, 33, 34], [27,  6, 33, 34], [ 5,  6, 33, 34],
      [27, 28, 33, 12], [ 5, 28, 33, 12], [27,  6, 33, 12], [ 5,  6, 33, 12] ],
    [ [27, 28, 11, 34], [ 5, 28, 11, 34], [27,  6, 11, 34], [ 5,  6, 11, 34],
      [27, 28, 11, 12], [ 5, 28, 11, 12], [27,  6, 11, 12], [ 5,  6, 11, 12] ],
    [ [25, 26, 31, 32], [25,  6, 31, 32], [25, 26, 31, 12], [25,  6, 31, 12],
      [15, 16, 21, 22], [15, 16, 21, 12], [15, 16, 11, 22], [15, 16, 11, 12] ],
    [ [29, 30, 35, 36], [29, 30, 11, 36], [ 5, 30, 35, 36], [ 5, 30, 11, 36],
      [39, 40, 45, 46], [ 5, 40, 45, 46], [39,  6, 45, 46], [ 5,  6, 45, 46] ],
    [ [25, 30, 31, 36], [15, 16, 45, 46], [13, 14, 19, 20], [13, 14, 19, 12],
      [17, 18, 23, 24], [17, 18, 11, 24], [41, 42, 47, 48], [ 5, 42, 47, 48] ],
    [ [37, 38, 43, 44], [37,  6, 43, 44], [13, 18, 19, 24], [13, 14, 43, 44],
      [37, 42, 43, 48], [17, 18, 47, 48], [13, 18, 43, 48], [ 1,  2,  7,  8] ]
  ]
  
  attr_accessor :ox
  attr_accessor :oy
  attr_accessor :tileset
  attr_accessor :autotiles
  attr_accessor :priorities
  attr_accessor :map_data
  
  def initialize(viewport)
    @viewport = viewport
    @swidth = (@viewport.rect.width / 32)
    @sheight = (@viewport.rect.height / 32)
    @data = nil
    @data_priorities = nil
    @priorities = nil
    @map_data = nil
    @tileset = nil
    @autotiles = []
    @sprites = {}
    @bitmaps = {}
    @cache = {}
    @need_counters = []
    @counter = []
    @max_counters = []
    @ox = 0
    @oy = 0
    @time_counter = 1
    @need_refresh = false
  end
  
  def refresh
    @need_refresh = false
    @table = Table.new(384)
    @size = 0
    @data = @map_data
    @data_priorities = @priorities
    min_x = [@ox / 32 - 1, 0].max
    min_y = [@oy / 32 - 1, 0].max
    max_x = [min_x + @swidth + 1 * 2, @data.xsize - 1].min
    max_y = [min_y + @sheight + 1 * 2, @data.ysize - 1].min
    (min_x..max_x).each {|x|
      (min_y..max_y).each {|y|
        (0..2).each {|z|
          tile_id = @data[x, y, z]
          next if tile_id == 0
          priority = @priorities[tile_id]
          key = [x, y, z, priority]
          @sprites[key] = Sprite.new(@viewport)
          @sprites[key].x = x * 32 - @ox
          @sprites[key].y = y * 32 - @oy
          @sprites[key].z = (y * 32 - @oy) + ((priority + 1) * 32)
          if tile_id < 384
            tile = get_autotile(tile_id)
          else
            tile = get_tile(tile_id)
          end
          @sprites[key].bitmap = tile
        }
      }
    }
  end
  
  def get_autotile(tile_id)
    if tile_id >= 384
      return get_tile(tile_id)
    end
    autotile = @autotiles[(tile_id/48) - 1]
    n = (autotile.width / 96)
    if @bitmaps[tile_id].nil?
      @bitmaps[tile_id] = []
    end
    if n > 1
      if @table[tile_id] == 0
        @counter[tile_id] = 0
        @max_counters[tile_id] = n
        @table[tile_id] = 1
        @size += 1
      end
    end
    for i in 0...n
      @bitmaps[tile_id][i] = get_tile(tile_id, i)
    end
    if @counter[tile_id].nil?
      return @bitmaps[tile_id][0]
    end
    return @bitmaps[tile_id][@counter[tile_id]]
  end
  
  def get_tile(tile_id, c=0)
    key = [tile_id, c]
    if @cache[key].nil?
      @cache[key] = Bitmap.new(32, 32)
      if tile_id < 384
        anim = c * 96
        id = tile_id % 48
        tiles = INDEX[id >> 3][id % 8]
        autotile = @autotiles[(tile_id/48) - 1]
        for i in 0...4
          tile_position = tiles[i] - 1
          rect = Rect.new(tile_position % 6 * 16 + anim, tile_position / 6 * 16, 16, 16)
          @cache[key].blt((i%2) * 16, (i/2) * 16, autotile, rect)
        end
      else
        @cache[key].blt(0, 0, @tileset, Rect.new((tile_id - 384) % 8 * 32, (tile_id - 384) / 8 * 32, 32, 32))
      end
    end
    return @cache[key]
  end
  
  def tileset=(valor)
    for v in @cache.values
      v.dispose
    end
    @cache = {}
    @tileset = valor
    @need_refresh = true
  end
  
  def dispose
    @cache.values.each {|v| v.dispose }
    @cache = {}
    @bitmaps.values.each {|a|
      next if a.nil?
      a.each {|v|
        next if v.nil?
        v.dispose unless v.disposed?
      }
    }
    @sprites.values.each {|sprite|
      next if sprite.nil?
      sprite.dispose
    }
    @sprites = {}
  end
  
  def update
    if @data != @map_data or @priorities != @data_priorities or @need_refresh
      refresh
      return
    end
    min_x = [@ox / 32 - 1, 0].max
    min_y = [@oy / 32 - 1, 0].max
    max_x = [min_x + @swidth + 1 * 2, @data.xsize - 1].min
    max_y = [min_y + @sheight + 1 * 2, @data.ysize - 1].min
    if AUTOTILE_UPDATE > 0
      @time_counter = (@time_counter + 1) % AUTOTILE_UPDATE
    end
    checked = []
    for x in min_x..max_x
      rx = ((x * 32) - @ox)
      cx = (rx < 0 or rx > (@swidth - 32))
      ax = (((rx + 32) < 0) or (rx > @viewport.rect.width))
      for y in min_y..max_y
        ry = ((y * 32) - @oy)
        cy = (ry < 0 or ry > (@sheight - 32))
        ay = (((ry + 32) < 0) or (ry > @viewport.rect.height))
        for z in 0..2
          tile_id = @data[x, y, z]
          next if tile_id == 0
          priority = @priorities[tile_id]
          key = [x, y, z, priority]
          if ay or ax
            if @sprites[key] != nil
              @sprites[key].dispose 
              @sprites[key] = nil
            end
            next
          end
          if @sprites[key].nil?
            @sprites[key] = Sprite.new(@viewport)
            @sprites[key].x = rx
            @sprites[key].y = ry
            @sprites[key].z = ry + ((priority + 1) * 32)
            if tile_id < 384
              tile = get_autotile(tile_id)
            else
              tile = get_tile(tile_id)
            end
            @sprites[key].bitmap = tile
            next
          end
          if @changed_ox or cy
            if @sprites[key].x != rx
              @sprites[key].x = rx
            end
          end
          if @changed_oy or cx
            if @sprites[key].y != ry
              @sprites[key].y = ry
              @sprites[key].z = ry + ((priority + 1) * 32)
            end
          end
          next if (@time_counter != 0)
          if @table[tile_id] == 1
            if checked[tile_id] != true
              @counter[tile_id] = (@counter[tile_id] + 1) % @max_counters[tile_id]
              checked[tile_id] = true
            end
            @sprites[key].bitmap = @bitmaps[tile_id][@counter[tile_id]]
          end
        end
      end
    end 
    if @changed_ox
      @changed_ox = false
    end
    if @changed_oy
      @changed_oy = false
    end
  end
  
  def ox=(valor)
    return if @ox == valor
    @ox = valor
    @changed_ox = true
  end
  
  def oy=(valor)
    return if @oy == valor
    @oy = valor
    @changed_oy = true
  end
  
end
 
Thanks to all for the feedback, it seems that it is very laggy, if you don't have a good computer. I will not use this version of Tilemap for RPG Advanced Editor, but maybe I can improve it or maybe not...

poccil, you fixed version of the script looks good and better than mine, maybe I can use a edited version(For some features, like the new layer system I am creating) of it for my RPG Advanced Editor.
RTH, I will test your script, if it is better than poccil's script, maybe I will use it insteand of poccil's script for my RPG Advanced Editor.
If I add one of your scripts(poccil, and RTH) in my RPG Advanced Editor as a default script and distributing the script with it, you will be credited for creating the script. Some questions, before using the script:
Do you have any problem if I use it for the RPG Advanced Editor default scripts?
Do you have any problem if someone use it for commercial games?

Me(tm), he uses the INDEX array in: "tiles = INDEX[id >> 3][id % 8]" in the method get_tile
 
2GB Ram
2.4Ghz processor (dual core)
7600GS graphics card

It ran mostly smoothly with both maps
It was consistant with 30-38fps with the 500x500 map

However it lagged occasionally with the smaller map, and went down to 15 and jumped back up to 38 a couple of seconds later.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top