|
rey meustrus wrote: Tileset! I've got an RMXP implementation for you right here. Well...it will probably take some modification, because the viewport code uses other systems I wrote and it is designed for GOSU rather than plain OpenGL. You probably don't want to split the images into individual textures like this, you want to load it as one texture (if you can) and draw with UVs. But you can do this I think. The only part that needs explaining is that `Gosu::Image.load_tiles` creates an array of textures, in this case all 32x32 pixel tiles, row-by-row (so the first row would be tiles 0-7, the next 8-15, etc). Every time I come back to this I am again disappointed that I did not do the GL calls myself in this way. Oh well. This should help you get started though.
- # RMXP Tilemap (gosu)
- #
- # Readable/Writable Attributes :
- # - viewport : Viewport used for sprites
- # - map_data : 3D Table of Tile ID Data
- # - flash_data : 3D Table of Tile Color Data
- # - priorities : 3D Table of Tile Priorities
- # - ox, oy : Tilemap layer offsets
- # - zoom : Zoom value as fraction
- # - tilesize : Zoom value as size of individual tile (normal is 32.0)
- # - visible : Tilemap Visible Flag
- # - is_a_plane : Behaves like a Plane (loops around edges)
- # - tileset : Name of Bitmap
- # - autotiles : Array of Autotile Filenames
- class Tilemap
- include Disposable
- VP = 2 # Number of tiles beyond viewport to refresh
- FA = 64 # Alpha value of the color of flash data
- Autotile_Speed = 20 # Number of frames between autotile animations
- Autotiles = [
- [416,432,512,528], [ 64,432,512,528], [416, 80,512,528], [ 64, 80,512,528],
- [416,432,512,176], [ 64,432,512,176], [416, 80,512,176], [ 64, 80,512,176],
- [416,432,160,528], [ 64,432,160,528], [416, 80,160,528], [ 64, 80,160,528],
- [416,432,160,176], [ 64,432,160,176], [416, 80,160,176], [ 64, 80,160,176],
- [384,400,480,496], [384, 80,480,496], [384,400,480,176], [384, 80,480,176],
- [224,240,320,336], [224,240,320,176], [224,240,160,336], [224,240,160,176],
- [448,464,544,560], [448,464,160,560], [ 64,464,544,560], [ 64,464,160,560],
- [608,624,704,720], [ 64,624,704,720], [608, 80,704,720], [ 64, 80,704,720],
- [384,464,480,560], [224,240,704,720], [192,208,288,304], [192,208,288,176],
- [256,272,352,368], [256,272,160,368], [640,656,736,752], [ 64,656,736,752],
- [576,592,672,688], [576, 80,672,688], [192,272,288,368], [192,208,672,688],
- [576,656,672,752], [256,272,736,752], [192,272,672,752], [ 0, 16, 96,112]
- ]
- DEFAULTS = {:tileset => nil, :autotiles => [], :map_data => nil,
- :flash_data => nil, :priorities => nil, :visible => true,
- :ox => 0, :oy => 0, :zoom => 1.0, :is_a_plane => true,
- :manager => nil}
-
- # Public Instance Variables
- attr_reader :gosuwindow # Instance of Gosu::Window it's drawing to
- attr_reader :tileset # Tileset Image
- attr_reader :autotiles # Array of Autotile Images
- attr_accessor :map_data # 3D Table of Tile Settings
- attr_reader :flash_data # 3D Table of Sprite Flash Colors
- attr_accessor :priorities # 3D Table of Tileset Priorities
- attr_accessor :visible # Tilemap Visibility
- attr_accessor :ox # Bitmap Offsets
- attr_accessor :oy # Bitmap Offsets
- attr_accessor :zoom # Zoom Fraction
- attr_accessor :is_a_plane # Loops around edges
-
- # Object Initialization
- def initialize(manager = nil, opts = {})
- @gosuwindow = $GameWindow
- DEFAULTS.merge!(opts).each do |sym, val|
- instance_variable_set("@#{sym}", val)
- end
- @manager = manager unless manager.nil?
- @autotiles_cache = @autotiles
- self.flash_data = @flash_data
- @tiles = []
- @frame = 0
- (@manager.nil? ? @gosuwindow.draw_manager : @manager).manage(self)
- end
-
- # Get "viewport"
- def viewport
- @manager
- end
-
- # Set "viewport"
- def viewport=(manager)
- (@manager.nil? ? @gosuwindow.draw_manager : @manager).unmanage(self)
- (manager.nil? ? @gosuwindow.draw_manager : manager).manage(self)
- @manager = manager
- end
-
- # Get Tile Size
- def tilesize
- (zoom * 32).to_i
- end
-
- # Set Tile Size
- def tilesize=(tilesize)
- self.zoom = tilesize / 32.0
- end
-
- # Set tileset graphic. Recaches the internal tileset.
- def tileset=(tileset)
- @tiles[384..-1] = Gosu::Image.load_tiles(@gosuwindow, tileset, 32, 32, true)
- @tileset = tileset
- end
-
- # Set list of autotiles. Recaches the internal tileset.
- def autotiles=(autotiles)
- autotiles.each_with_index do |autotile, i|
- Autotiles.each_with_index do |tiles, j|
- key = (i + 1) * 48 + j
- @tiles[key] = []
- # Draws Auto-Tile Rects
- for f in 0..(autotile.width / 96)
- bmp = Gosu::Image.new(@gosuwindow,
- TexPlay::EmptyImageStub.new(32, 32), true)
- tiles.each_with_index do |pos, k|
- opts = {:crop => [x1 = pos%96+f*96, x2=pos / 96, x1 + 16, x2 + 16]}
- bmp.splice(k % 2 * 16, k / 2 * 16, autotile, opts)
- end
- @tiles[key][f] = bmp
- end
- end
- end
- @autotiles = @autotiles_cache = autotiles
- end
-
- # Set flash data. For speed we maintain a separate list of GOSU::Color
- # object for actual display.
- def flash_data=(flash_data)
- @flash_data = flash_data
- if flash_data.nil?
- @flash_data_colors = nil
- else
- @flash_data_colors = Hash.new
- for y in 0...flash_data.ysize
- for x in 0...flash_data.xsize
- hex = @flash_data[x, y]
- @flash_data_colors[[x, y]] =
- Gosu::Color.rgba((hex<<8)*16, ((hex<<4)%16)*16, (hex%16)*16, FA))
- end
- end
- end
- end
-
- # Dispose
- def dispose
- @visible = false
- super
- end
-
- # Update autotile animation
- def update
- @frame += 1
- end
-
- # Per-frame draw function
- def draw
- return if @map_data.nil? or @priorities.nil? or !@visible
-
- self.autotiles = @autotiles if @autotiles != @autotiles_cache
- ts = tilesize
- frame = @frame / Autotile_Speed
- xmax = (((@viewport.nil? ? @gosuwindow : @viewport.rect).width + @ox) / ts)
- ymax = (((@viewport.nil? ? @gosuwindow : @viewport.rect).height + @oy) / ts)
- ydts = @oy / ts
- yrange = ydts - VP...ymax + VP
- xrange = (@ox / ts) - VP...xmax + VP
-
- for y in yrange
- ytop = y - ydts
- if y < 0 or y >= @map_data.ysize
- next unless @is_a_plane
- y %= @map_data.ysize
- y += @map_data.ysize if y < 0
- end
- draw_y = y * ts - @oy
-
- for x in xrange
- if x < 0 or x >= @map_data.xsize
- next unless @is_a_plane
- x %= @map_data.xsize
- x += @map_data.xsize if x < 0
- end
- draw_x = x * ts - @ox
-
- for layer in 0...@map_data.zsize
- id = @map_data[x, y, layer]
- next if id == 0
- z = (ytop + z) * 32 + 64 unless (z = @priorities[id]) == 0
- tile = @tiles[id]
- tile = @tiles[id][frame % tile.size] if tile.is_a?(Array)
- tile.draw(draw_x, draw_y, z, @zoom, @zoom)
- end
- unless @flash_data.nil?
- c = @flash_data_colors[[x, y]]
- @gosuwindow.draw_quad(draw_x, draw_y, c, draw_x+ts, draw_y, c,
- draw_x, draw_y+ts, c, draw_x+ts, draw_y+ts, c)
- end
- end # for x
- end # for y
- end
- end
-
Expand to see the code.
Woa! Interesting. I'll try to play with it, thanks. One question though, your implementation works in RMVXAce as it is?
|
|