04-08-2013, 12:55 AM
For my benefit and others I think it would be a good idea to collect all the hidden classes known (not the ones layed out in the help doc) into one location on the web.
or
Audio
Bitmap
Color
Code:
#==============================================================================
# ■ Color
#------------------------------------------------------------------------------
# by vgvgf
#==============================================================================
class Color
def initialize(r, g, b, a = 255)
@red = r
@green = g
@blue = b
@alpha = a
end
def set(r, g, b, a = 255)
@red = r
@green = g
@blue = b
@alpha = a
end
def color
Color.new(@red, @green, @blue, @alpha)
end
def _dump(d = 0)
[@red, @green, @blue, @alpha].pack('d4')
end
def self._load(s)
Color.new(*s.unpack('d4'))
end
def inspect
sprintf("(%f, %f, %f, %f)", @red, @green, @blue, @alpha)
end
def to_s
self.inspect
end
attr_accessor(:red, :green, :blue, :alpha)
end
Font
Graphics
Input
Code:
# Found by Narzew
module Input
DOWN=2
LEFT=4
RIGHT=6
UP=8
A=11
B=12
C=13
X=14
Y=15
Z=16
L=17
R=18
SHIFT=21
CTRL=22
ALT=23
F5=25
F6=26
F7=27
F8=28
F9=29
# GetAsyncKeyState or GetKeyState will work here
@GetKeyState=Win32API.new("user32", "GetAsyncKeyState", "i", "i")
# Returns whether a key is being pressed
def self.getstate(key)
return (@GetKeyState.call(key)&0x8000)>0
end
def self.update
if @keystate
for i in 0...256
@newstate=self.getstate(i)
@triggerstate[i]=(@newstate&&@keystate[i]==0)
@releasestate[i]=(!@newstate&&@keystate[i]>0)
@keystate[i]=@newstate ? @keystate[i]+1 : 0
end
else
@keystate=[]
@triggerstate=[]
@releasestate=[]
for i in 0...256
@keystate[i]=self.getstate(i) ? 1 : 0
@triggerstate[i]=false
@releasestate[i]=false
end
end
end
def self.buttonToKey(button)
case button
when Input::DOWN
return [0x28] # Down
when Input::LEFT
return [0x25] # Left
when Input::RIGHT
return [0x27] # Right
when Input::UP
return [0x26] # Up
when Input::A
return [0x5A,0x10] # Z, Shift
when Input::B
return [0x58,0x1B] # X, ESC
when Input::C
return [0x43,0x0d,0x20] # C, ENTER, Space
when Input::X
return [0x41] # A
when Input::Y
return [0x53] # S
when Input::Z
return [0x44] # D
when Input::L
return [0x51,0x21] # Q, Page Up
when Input::R
return [0x57,0x22] # W, Page Up
when Input::SHIFT
return [0x10] # Shift
when Input::CTRL
return [0x11] # Ctrl
when Input::ALT
return [0x12] # Alt
when Input::F5
return [0x74] # F5
when Input::F6
return [0x75] # F6
when Input::F7
return [0x76] # F7
when Input::F8
return [0x77] # F8
when Input::F9
return [0x78] # F9
else
return []
end
end
def self.dir4
button=0
repeatcount=0
if self.press?(Input::DOWN) && self.press?(Input::UP)
return 0
end
if self.press?(Input::LEFT) && self.press?(Input::RIGHT)
return 0
end
for b in [Input::DOWN,Input::LEFT,Input::RIGHT,Input::UP]
rc=self.count(b)
if rc>0
if repeatcount==0 || rc<repeatcount
button=b
repeatcount=rc
end
end
end
return button
end
def self.dir8
buttons=[]
for b in [Input::DOWN,Input::LEFT,Input::RIGHT,Input::UP]
rc=self.count(b)
if rc>0
buttons.push([b,rc])
end
end
if buttons.length==0
return 0
elsif buttons.length==1
return buttons[0][0]
elsif buttons.length==2
# since buttons sorted by button, no need to sort here
if (buttons[0][0]==Input::DOWN && buttons[1][0]==Input::UP)
return 0
end
if (buttons[0][0]==Input::LEFT && buttons[1][0]==Input::RIGHT)
return 0
end
end
buttons.sort!{|a,b| a[1]<=>b[1]}
updown=0
leftright=0
for b in buttons
if updown==0 && (b[0]==Input::UP || b[0]==Input::DOWN)
updown=b[0]
end
if leftright==0 && (b[0]==Input::LEFT || b[0]==Input::RIGHT)
leftright=b[0]
end
end
if updown==Input::DOWN
return 1 if leftright==Input::LEFT
return 3 if leftright==Input::RIGHT
return 2
elsif updown==Input::UP
return 7 if leftright==Input::LEFT
return 9 if leftright==Input::RIGHT
return 8
else
return 4 if leftright==Input::LEFT
return 6 if leftright==Input::RIGHT
return 0
end
end
def self.count(button)
for btn in self.buttonToKey(button)
c=self.repeatcount(btn)
return c if c>0
end
return 0
end
def self.trigger?(button)
return self.buttonToKey(button).any? {|item| self.triggerex?(item) }
end
def self.repeat?(button)
return self.buttonToKey(button).any? {|item| self.repeatex?(item) }
end
def self.press?(button)
return self.count(button)>0
end
def self.repeatex?(key)
return false if !@keystate
return @keystate[key]==1 || (@keystate[key]>20 && (@keystate[key]&1)==0)
end
def self.releaseex?(key)
return false if !@releasestate
return @releasestate[key]
end
def self.triggerex?(key)
return false if !@triggerstate
return @triggerstate[key]
end
def self.repeatcount(key)
return 0 if !@keystate
return @keystate[key]
end
def self.pressex?(key)
return self.repeatcount(key)>0
end
end
Plane
Code:
#==============================================================================
# ■ SG::Plane
#------------------------------------------------------------------------------
# by Selwyn
#==============================================================================
module SG
class SG::Plane
attr_reader :ox, :oy
#--------------------------------------------------------------------------
# — initialize
#--------------------------------------------------------------------------
def initialize(viewport = nil)
@sprite = Sprite.new(viewport)
@max_width = 640
@max_height = 480
@bitmap = nil
@ox = 0
@oy = 0
end
#--------------------------------------------------------------------------
# ● z, zoom_x, zoom_y, opacity, blend_type, color, tone
# z=, zoom_x=, zoom_y=, opacity=, blend_type=, color=, tone=
#--------------------------------------------------------------------------
def method_missing(symbol, *args)
@sprite.method(symbol).call(*args)
end
#--------------------------------------------------------------------------
# ● bitmap=
#--------------------------------------------------------------------------
def bitmap=(bitmap)
@bitmap = bitmap
refresh
end
#--------------------------------------------------------------------------
# ● ox=
#--------------------------------------------------------------------------
def ox=(ox)
w = @sprite.viewport != nil ? @sprite.viewport.rect.width : @max_width
@ox = ox % w
@sprite.ox = @ox
end
#--------------------------------------------------------------------------
# ● oy=
#--------------------------------------------------------------------------
def oy=(oy)
h = @sprite.viewport != nil ? @sprite.viewport.rect.height : @max_height
@oy = oy % h
@sprite.oy = @oy
end
#--------------------------------------------------------------------------
# ● refresh
#--------------------------------------------------------------------------
def refresh
return if @bitmap.nil?
w = @sprite.viewport != nil ? @sprite.viewport.rect.width : @max_width
h = @sprite.viewport != nil ? @sprite.viewport.rect.height : @max_height
if @sprite.bitmap != nil
@sprite.bitmap.dispose
end
@sprite.bitmap = Bitmap.new(w * 2, h * 2)
max_x = w / @bitmap.width
max_y = h / @bitmap.height
for x in 0..max_x
for y in 0..max_y
@sprite.bitmap.blt(x * @bitmap.width, y * @bitmap.height,
@bitmap, Rect.new(0, 0, @bitmap.width, @bitmap.height))
end
end
for i in 1...4
x = i % 2 * w
y = i / 2 * h
@sprite.bitmap.blt(x, y, @sprite.bitmap, Rect.new(0, 0, w, h))
end
end
end
end
Rect
Sprite
Table
Code:
#==============================================================================
# ■ Table
#------------------------------------------------------------------------------
# by vgvgf
#==============================================================================
class Table
def initialize(x,y=1,z=1)
@xsize,@ysize,@zsize=x,y,z
@data=Array.new(x*y*z, 0)
end
def [](x,y=0,z=0)
@data[x+y*@xsize+z*@xsize*@ysize]
end
def []=(*args)
x=args[0]
y=args.size>2 ?args[1]:0
z=args.size>3 ?args[2]:0
v=args.pop
@data[x+y*@xsize+z*@xsize*@ysize]=v
end
def _dump(d=0)
s=[3].pack('L')
s+=[@xsize].pack('L')+[@ysize].pack('L')+[@zsize].pack('L')
s+=[@xsize*@ysize*@zsize].pack('L')
for z in 0...@zsize
for y in 0...@ysize
for x in 0...@xsize
s+=[@data[x+y*@xsize+z*@xsize*@ysize],0,0].pack('L')[0,2]
end
end
end
s
end
attr_reader(:xsize,:ysize,:zsize,:data)
class << self
def _load(s)
size=s[0,4].unpack('L')[0]
nx=s[4,4].unpack('L')[0]
ny=s[8,4].unpack('L')[0]
nz=s[12,4].unpack('L')[0]
data=[]
pointer=20
loop do
data.push((s[pointer,2]+"\000\000").unpack('L')[0])
pointer+=2
break if pointer > s.size-1
end
t=Table.new(nx,ny,nz)
n=0
for z in 0...nz
for y in 0...ny
for x in 0...nx
t[x,y,z]=data[n]
n+=1
end
end
end
t
end
end
end
Tilemap
Code:
#==============================================================================
# ** Tilemap (hidden class)
#------------------------------------------------------------------------------
# This class handles the map data to screen processing
#==============================================================================
#==============================================================================
#
# Yet another Tilemap Script (for any map size /w autotiles)
# by Meâ €žÂ¢ / Derk-Jan Karrenbeld (me@solarsoft.nl)
# version 1.0 released on 08 nov 08
# version 1.2
#
#==============================================================================
class Tilemap
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_reader :tileset
attr_reader :autotiles
attr_reader :flash_data
attr_reader :priorities
attr_reader :visible
attr_reader :ox, :oy
attr_writer :autotiles
#--------------------------------------------------------------------------
# * Constant Configuration
#--------------------------------------------------------------------------
# Window Rect - the visible Area of the Map (default: 640 x 480)
# Bitmap Rect - the active drawing Area of the Map (window tiles + 2 tiles)
# BitmapWindow offset - the invisible tile count on one side
WindowRect = Rect.new(0,0,640,480)
BitmapRect = Rect.new(0,0,640 + 64, 480 + 64) # Recommended
BitmapWindowOffset = (BitmapRect.height-WindowRect.height)/2/32
# Length in frames of one frame showing from autotile
AutotileLength = 10
# KillOutScreenSprite - Kills priority and autotile sprites out of screen
# EnableFlashingData - If activated, enables updating flashing data
KillOutScreenSprite = true
EnableFlashingData = false
# SingleFlashingSprite - Uses one Flashing sprite, instead of many
# SinglePrioritySprite - Uses one Priority sprite, instead of many
# SingleAutotileSprite - Uses one Autotile sprite, instead of many
SingleFlashingSprite = false
SinglePrioritySprite = false
SingleAutotileSprite = false
# This is the Autotile animation graphical index array. It contains numbers
# that point to the graphic part of an animating autotile.
Autotiles = [
[ [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] ]
]
#--------------------------------------------------------------------------
# * Object Initialization
# viewport : the drawing viewport
# rpgmap : the rpgmap object
#--------------------------------------------------------------------------
def initialize(viewport = nil, rpgmap = nil)
# Autotiles Array
@autotiles = Array.new(6, nil)
@oldautotiles = Array.new(6, nil)
# Tilemap Viewport
@viewport = viewport ? viewport : Viewport.new(WindowRect)
# Showing Region Rectangle
@region = Rect.new(0,0,BitmapRect.width/32, BitmapRect.height/32)
# Old Region Rect
@oldregion = nil
# Set TilemapSprite
@sprite = Sprite.new(@viewport)
# Set Bitmap on Sprite
@sprite.bitmap = Bitmap.new(BitmapRect.width, BitmapRect.height)
# Set FlashingSprite and bitmap
if SingleFlashingSprite
@flashsprite = Sprite.new(@viewport)
@flashsprite.bitmap = Bitmap.new(BitmapRect.width, BitmapRect.height)
end
# Set Informational Arrays/Hashes
@priority_ids = {} # Priority ids
@normal_tiles = {} # Non-auto tile bitmaps
@auto_tiles = {} # Autotile bitmaps
@priority_sprites = [] # Priority Sprites
@autotile_sprites = [] # Autotile Sprites
@flashing_sprites = [] # Flashing Sprites
# Disposal Boolean
@disposed = false
# Visibility Boolean
@visible = true
# Flashing Boolean
@flashing = true
# Disable Drawing Boolean
@can_draw = true
# Set Coords
@ox, @oy = 0, 0
# Create TileMap if rpgmap is provided
create_tilemap(rpgmap) if !rpgmap.nil?
end
#--------------------------------------------------------------------------
# * Get Bitmap Sprite
#--------------------------------------------------------------------------
def sprite_bitmap
return @sprite.bitmap
end
#--------------------------------------------------------------------------
# * Data Tileset Referer - loads if needed
#--------------------------------------------------------------------------
def data_tilesets
$data_tilesets ||= load_data("Data/Tilesets.rxdata")
end
#--------------------------------------------------------------------------
# * Check: Disposed?
#--------------------------------------------------------------------------
def disposed?
@disposed
end
#--------------------------------------------------------------------------
# * Dispose
#--------------------------------------------------------------------------
def dispose
# Dispose all sprites (and cached bitmaps for quick memory clearing)
for sprite in [@sprite] + @normal_tiles.values + @auto_tiles.values + @priority_sprites + @autotile_sprites + (SingleFlashingSprite ? [@flashsprite] : @flashing_sprites)
sprite = sprite[0] if sprite.is_a?(Array)
sprite.dispose if sprite.is_a?(Bitmap)
end
# Set Informational Arrays/Hashes
@priority_ids = {} # Priority ids
@normal_tiles = {} # Non-auto tile bitmaps
@priority_sprites = [] # Priority Sprites
@autotile_sprites = [] # Autotile Sprites
@flashing_sprites = [] # Flashing Sprites
# I am disposed
@disposed = true
end
#--------------------------------------------------------------------------
# * Checking: Drawing Allowed
#--------------------------------------------------------------------------
def drawing?
@can_draw
end
#--------------------------------------------------------------------------
# * Enable Drawing
#--------------------------------------------------------------------------
def enable_drawing
@can_draw = true
end
#--------------------------------------------------------------------------
# * Disable Drawing
#--------------------------------------------------------------------------
def disable_drawing
@can_draw = true
end
#--------------------------------------------------------------------------
# * Enable Flashing
#--------------------------------------------------------------------------
def enable_flashing
@flashing = true
end
#--------------------------------------------------------------------------
# * Disable Flashing
#--------------------------------------------------------------------------
def disable_flashing
@flashing = false
end
#--------------------------------------------------------------------------
# * Check: Flashing
#--------------------------------------------------------------------------
def flashing?
EnableFlashingData and @flashing and @flashing_sprites.size
end
#--------------------------------------------------------------------------
# * Check: Visible
#--------------------------------------------------------------------------
def visible?
@visible
end
#--------------------------------------------------------------------------
# * Check: Autotiles Changed
#--------------------------------------------------------------------------
def autotiles_changed?
@oldautotiles != @autotiles
end
#--------------------------------------------------------------------------
# * Set Visibility
# value: new value
#--------------------------------------------------------------------------
def visible=(value)
# Set Visibility value
@visible = value
# Update all sprites
for sprite in [@sprite] + @priority_sprites + @autotile_sprites + (SingleFlashingSprite ? [@flashsprite] : @flashing_sprites)
sprite = sprite[0] if sprite.is_a?(Array)
sprite.visible = value
end
end
#--------------------------------------------------------------------------
# * Set Tileset
# value : new RPG::Tileset, String or Bitmap
#--------------------------------------------------------------------------
def tileset=(value)
# Return on equal data
return if @tileset == value
# Set TilesetName
value = value.tileset_name if value.is_a?(RPG::Tileset)
# Cache Tileset
@tileset = RPG::Cache.tileset(value) if value.is_a?(String)
# Set Tileset
@tileset = value if value.is_a?(Bitmap)
# Draw Tileset
redraw_tileset if @can_draw
end
#--------------------------------------------------------------------------
# * Set Priorities
# value : new value
#--------------------------------------------------------------------------
def priorities=(value)
# Return on equal data
return if @priorities == value
# Set Priorities
@priorities = value
# Draw Tileset
redraw_priorities if @can_draw
end
#--------------------------------------------------------------------------
# * Set flash data
# coord[0] : x
# coord[1] : y
# value : Color or Hex
#--------------------------------------------------------------------------
def flash_data=(*coord, &value)
# Return on equal data
return if @flash_data[coord[0],coord[1]] == value
# Already Flashing this tile?
flashing = !@flash_data[x,y].nil?
# Set Flash Data
@flash_data[x,y] = value
return if !EnableFlashingData
# Take action and remove/change/add flash
if value.nil?
remove_flash(x,y)
elsif flashing
change_flash(x,y,value)
else
add_flash(x,y,value)
end
end
#--------------------------------------------------------------------------
# * Map Data referer
#--------------------------------------------------------------------------
def map_data
@map_data
end
#--------------------------------------------------------------------------
# * Set Map Data
# value : new Table value
#--------------------------------------------------------------------------
def map_data=(value)
# Return on equal data
return if @map_data == value
# Set New Map Data
@map_data = value
# Flash Data Table
@flash_data = Table.new(@map_data.xsize, @map_data.ysize)
# Redraw Current Region
draw_region if @can_draw and @priorities and @tileset
end
#--------------------------------------------------------------------------
# * Get Map width (in tiles)
#--------------------------------------------------------------------------
def map_tile_width
map_data.xsize
end
#--------------------------------------------------------------------------
# * Get Map height (in tiles)
#--------------------------------------------------------------------------
def map_tile_height
map_data.ysize
end
#--------------------------------------------------------------------------
# * Create Tilemap
# rpgmap : base object
#--------------------------------------------------------------------------
def create_tilemap(rpgmap)
# Return on invalid data
return if rpgmap.is_a?(RPG::Map) == false
# Restrict drawing
@can_draw = false
# Set Local Tileset Object (RPG::Tileset)
_tileset = data_tilesets[rpgmap.tileset_id]
# Return on invalid data
return if _tileset.is_a?(RPG::Tileset) == false
# Set Informational Arrays/Hashes
@priority_ids = {} # Priority ids
@normal_tiles = {} # Non-auto tile bitmaps
@priority_sprites = [] # Priority Sprites
@autotile_sprites = [] # Autotile Sprites
@flashing_sprites = [] # Flashing Sprites
# Set Tileset
tileset = _tileset.tileset_name
# Set AutoTiles
(0..6).each { |i| autotiles[i] = _tileset.autotile_names[i] }
# Set Priorities
priorities = _tileset.priorities
# Set Mapdata
map_data = rpgmap.map_data
# Reset drawing
@can_draw = true
# Reset disposed (need to reinit info variables)
@disposed = false
# Draw Region
draw_region
end
#--------------------------------------------------------------------------
# * Get Tile id
# x : x tile coord
# y : y tile coord
# z : z layer coord
#--------------------------------------------------------------------------
def tile_id(x, y, z)
return map_data[x, y, z]
end
#--------------------------------------------------------------------------
# * Get Priority
# args (1) : tile_id
# args (3) : x, y, z coord
#--------------------------------------------------------------------------
def priority(*args)
return @priorities[args[0]] if args.size == 1
return @priorities[tile_id(args[0], args[1], args[2])]
end
#--------------------------------------------------------------------------
# * Redraw Tileset (on change)
#--------------------------------------------------------------------------
def redraw_tileset
# Kill current bitmap
sprite_bitmap.clear
# Get rid of tile bitmaps
@normal_tiles.clear
# Get rid of autotile bitmaps
@auto_tiles.clear
# Dispose current tiles in screen
(@autotile_sprites + @priority_sprites).each { |sprite| sprite[0].dispose if !sprite[0].disposed? }
# Clear disposed graphics
@autotile_sprites.clear; @priority_sprites.clear
# Draw if allowed
draw_region if @can_draw and @priorities and @tileset
end
#--------------------------------------------------------------------------
# * Redraw Priorities (on change)
#--------------------------------------------------------------------------
def redraw_priorities
# Dispose current tiles in screen
(@autotile_sprites + @priority_sprites).each { |sprite| sprite[0].dispose if !sprite[0].disposed? }
# Clear disposed graphics
@priority_sprites.clear; @autotile_sprites.clear
# Clear Priority id information
@priority_ids.clear
# Do a one time check for all priorities (can't do @tileset.priorities
# because RPG::Tilemap is normally not passed trough, but if it were, you
# can do the following - just uncomment this part and command the next for
# loop:
## for tile_id in 0...@tileset.priorities.xsize
## next if @tileset.priorities[tile_id] == 0
## @priority_ids[tile_id] = @tileset.priorities[tile_id]
## end
# But because we don't have that data, just iterate trough the map and
# get seperate priority data for each tile, and save if there is one.
for z in 0...3
for y in 0...map_tile_height
for x in 0...map_tile_width
next if (id = tile_id(x, y, z)) == 0
next if (p = priority(id)) == 0
@priority_ids[id] = p
end
end
end
# Draw if allowed
draw_region if @can_draw and @priorities and @tileset
end
#--------------------------------------------------------------------------
# * Redraw autotiles (on change)
#--------------------------------------------------------------------------
def redraw_autotiles
# Clear autotile bitmaps
@auto_tiles.clear
# Dispose current autotiles on screen
@autotile_sprites.each { |sprite| sprite[0].dispose if !sprite[0].disposed? }
# Get rid of disposed sprites
@autotile_sprites.clear
# Save changes aka don't call this method again
@oldautotiles = @autotiles
# Draw if allowed
draw_region if @can_draw and @priorities and @tileset
end
#--------------------------------------------------------------------------
# * Draw new Visible region
#--------------------------------------------------------------------------
def draw_current_region
# Determine x and y coords for tile top left
left_x = @ox / 32
top_y = @oy / 32
# Set origin for bitmap
@sprite.ox = @ox % 32 + BitmapWindowOffset * 32
@sprite.oy = @oy % 32 + BitmapWindowOffset * 32
# Set New Region
@region.x, @region.y = left_x, top_y
# Set New Sprite Positions (pray for non disposed sprites: checking = cpu cost)
(@priority_sprites + @autotile_sprites).each { |sprite| sprite[0].x = (sprite[1] - left_x) * 32 ;
sprite[0].ox = @ox % 32; sprite[0].y = (sprite[2] - top_y) * 32; sprite[0].oy = @oy % 32;
unless (priority = @priority_ids[tile_id(sprite[1], sprite[2], sprite[3])]).nil? then sprite[0].z = @viewport.z + sprite[0].y + priority * 32 + 32 end}
# Return on old data
return if @oldregion == @region
# Draw complete region if new?
return draw_region if @oldregion.nil?
# Determine missing rect
first_drawing_x = [((left_x - @oldregion.x) >= 0 ? @region.width : 0) - (left_x - @oldregion.x)].max
drawing_rect_x = Rect.new(first_drawing_x, 0, ((left_x - @oldregion.x).abs), @region.height)
first_drawing_y = [((top_y - @oldregion.y) >= 0 ? @region.height : 0) - (top_y - @oldregion.y)].max
drawing_rect_y = Rect.new(0, first_drawing_y, @region.width, ((top_y - @oldregion.y).abs))
# Determine Rect that is still visible
stay_rect = Rect.new([(left_x-@oldregion.x) * 32,0].max, [(top_y-@oldregion.y) * 32,0].max, (@region.width - (left_x-@oldregion.x).abs) * 32,(@region.height - (top_y-@oldregion.y).abs) * 32)
# Dumplicate bitmap and clear Original
dump_bitmap = sprite_bitmap.dup; sprite_bitmap.clear
# Place Old bitmap on screen
sprite_bitmap.blt([(@oldregion.x-left_x) * 32, 0].max, [(@oldregion.y-top_y) * 32, 0].max,dump_bitmap, stay_rect)
# Remove Out of Range Sprites
if KillOutScreenSprite
_prio, _auto = @priority_sprites.dup, @autotile_sprites.dup; @priority_sprites, @autotile_sprites = [], []
for sprite in _prio do if (sprite[1]) < @region.x - BitmapWindowOffset or (sprite[1] - BitmapWindowOffset) > @region.width + @region.x or sprite[2] < @region.y - BitmapWindowOffset or (sprite[2] - BitmapWindowOffset) > @region.height + @region.y then sprite[0].dispose else @priority_sprites << sprite end end
for sprite in _auto do if (sprite[1]) < @region.x - BitmapWindowOffset or (sprite[1] - BitmapWindowOffset) > @region.width + @region.x or sprite[2] < @region.y - BitmapWindowOffset or (sprite[2] - BitmapWindowOffset) > @region.height + @region.y then sprite[0].dispose else @autotile_sprites << sprite end end
# Remove nil elements (error prevention)
@priority_sprites.compact!; @autotile_sprites.compact!;
end
# Draw New Columns
for x in 0...drawing_rect_x.width
for y in 0...drawing_rect_x.height
for z in 0..2
draw_tile(drawing_rect_x.x + x , drawing_rect_x.y + y, tile_id(left_x + drawing_rect_x.x + x - BitmapWindowOffset, top_y + y - BitmapWindowOffset, z), left_x + drawing_rect_x.x + x - BitmapWindowOffset, top_y + y - BitmapWindowOffset, z)
end
end
end
# Draw New Rows
for x in 0...drawing_rect_y.width
for y in 0...drawing_rect_y.height
for z in 0..2
draw_tile(drawing_rect_y.x + x , drawing_rect_y.y + y, tile_id(left_x + x - BitmapWindowOffset, top_y + drawing_rect_y.y + y - BitmapWindowOffset, z), left_x + x - BitmapWindowOffset, top_y + drawing_rect_y.y + y - BitmapWindowOffset, z)
end
end
end
# Set region sprite coords
@oldregion = Rect.new(left_x, top_y, @region.width, @region.height)
end
#--------------------------------------------------------------------------
# * Draw complete visible region
#--------------------------------------------------------------------------
def draw_region
# Clear Sprites
sprite_bitmap.clear
(@priority_sprites + @autotile_sprites).each { |sprite| sprite[0].dispose }
@priority_sprites.clear; @autotile_sprites.clear
# Determine x and y coords for tile top left
left_x = @ox / 32
top_y = @oy / 32
# Set Sprite ox/oy
@sprite.ox = BitmapWindowOffset * 32
@sprite.oy = BitmapWindowOffset * 32
# Set New Region
@region.x, @region.y = left_x, top_y
# Iterate through new xses
for x in 0...(@region.width)
for y in 0...(@region.height)
for z in 0..2
# Draw new tiles
draw_tile(x, y , tile_id(x + left_x - BitmapWindowOffset,y + top_y - BitmapWindowOffset,z), x + left_x - BitmapWindowOffset , y + top_y - BitmapWindowOffset, z)
end
end
end
# Set oldregion (sprite coords)
@oldregion = Rect.new(left_x, top_y, @region.width, @region.height)
# Update Sprite
@sprite.update
# Prevent Frame Skipping
Graphics.frame_reset
end
#--------------------------------------------------------------------------
# * Draw a tile
# x : x coord in tiles on screen
# y : y coord in tiles on screen
# tile_id : tile id
# tx : x coord in tiles on map
# ty : y coord in tiles on map
# tx : z layer on map
# src_... : bitmap to draw on
#--------------------------------------------------------------------------
def draw_tile(x, y, tile_id, tx, ty, tz, src_bitmap = nil)
# Return on invalid data
#return if @region.x < x or @region.y < y
#return if @region.width + @region.x > x or @region.height + @region.y > y
return if x < 0 or y < 0
return if tile_id == nil
return draw_autotile(x, y, tile_id, tx, ty, tz, bitmap = bitmap) if tile_id < 384
# First, Get Bitmap
if (src_bitmap = @normal_tiles[tile_id]).nil?
# Get Bitmap
src_bitmap = Bitmap.new(32, 32)
src_rect = Rect.new((tile_id - 384) % 8 * 32, (tile_id - 384) / 8 * 32,32,32)
src_bitmap.blt(0, 0, @tileset, src_rect)
# Save Bitmap
@normal_tiles[tile_id] = src_bitmap
end
# Now, if tile is not a priority tile...
if @priority_ids[tile_id].nil?
sprite_bitmap.blt(x * 32, y * 32, src_bitmap, Rect.new(0,0,32,32))
else
# ... Set Sprite and bitmap
sprite = Sprite.new(@viewport)
sprite.visible = visible
sprite.bitmap = src_bitmap
sprite.x, sprite.y = (tx - (@ox/32)) * 32, (ty - (@oy/32)) * 32
sprite.ox, sprite.oy = @ox % 32, @oy % 32
# Priority matches 32 (above normal) + value * 32 (priority) + tile y * 32
sprite.z = @viewport.z + y * 32 + @priority_ids[tile_id] * 32 + 32
# Add to sprites Array
@priority_sprites << [sprite, tx, ty, tz]
end
end
#--------------------------------------------------------------------------
# * Draw an autotile
# x : x coord in tiles on screen
# y : y coord in tiles on screen
# tile_id : tile id
# tx : x coord in tiles on map
# ty : y coord in tiles on map
# tx : z layer on map
# src_... : bitmap to draw on
#--------------------------------------------------------------------------
def draw_autotile(x, y, tile_id, tx, ty, tz, src_bitmap = nil)
# Kill invalid calls
return if x < 0 or y < 0
return if tile_id == nil or tile_id >= 384
return if tile_id == 0
# Get AutotileGraphic
autotile = @autotiles[tile_id/48-1]
return if autotile.nil? or autotile.disposed?
# Get Frame Data
frames = (autotile.height == 32 ? autotile.width / 32 : autotile.width / 96)
current_frame = (Graphics.frame_count/AutotileLength) % frames
# First Get Bitmap
if (src_bitmap_array = @auto_tiles[tile_id]).nil?
@auto_tiles[tile_id] = []
# If autotile is weird... :P
if autotile.height == 32
# Just iterate trough frames
for i in 0...frames
# Create a bitmap for this frame
this_frame_bitmap = Bitmap.new(32,32)
src_rect = Rect.new(i * 32, 0, 32, 32)
this_frame_bitmap.blt(0, 0, autotile, src_rect)
# Save this frame's bitmap
@auto_tiles[tile_id] << this_frame_bitmap
end
# Set the bitmap array to the created one
src_bitmap_array = @auto_tiles[tile_id]
else
# If autotile is normal, iterate
for i in 0...frames
# Create a new bitmap for this frame
this_frame_bitmap = Bitmap.new(32,32)
# Get the tiles from the Autotiles Array (tile_id corresponds
# to the autotile graphic, so left_top is different to center
tiles = Autotiles[(tile_id % 48)>>3][(tile_id % 48)&7]
# Iterate trough 0, 1, 2 and 3
for j in 0...4
# Get tile_position (to get from the graphic)
tile_position = tiles[j] - 1
src_rect = Rect.new(tile_position % 6 * 16 + i * 96, tile_position / 6 * 16, 16, 16)
this_frame_bitmap.blt(j % 2 * 16, j / 2 * 16 , autotile, src_rect)
end
@auto_tiles[tile_id][i] = this_frame_bitmap
end
src_bitmap_array = @auto_tiles[tile_id]
end
end
# Now Get Frame Bitmap
src_bitmap = src_bitmap_array[current_frame]
return if src_bitmap.nil?
# Now, if tile is not a priority tile...
if @priority_ids[tile_id].nil? and autotile.width == 32
sprite_bitmap.blt(x * 32, y * 32, src_bitmap, Rect.new(0,0,32,32))
else
priority = (@priority_ids[tile_id] or 0)
# ... Set Sprite and bitmap
sprite = Sprite.new(@viewport)
sprite.visible = visible
sprite.bitmap = src_bitmap
sprite.x, sprite.y = (tx - (@ox/32)) * 32, (ty - (@oy/32)) * 32
sprite.ox, sprite.oy = @ox % 32, @oy % 32
# Priority matches 32 (above normal) + value * 32 (priority) + tile y * 32
# Because this sprite is created later then the normal base sprite, it
# has a higher internal z value. We fix this by setting the z value to
# minus 2 + z value of this tile. This results in that a autotile is below
# minus 2 + z value of this tile. This results in that a autotile is below
# a normal sprite on the same priority
sprite.z = @viewport.z - 2 + tz # Fix for ltr drwn.
unless @priority_ids[tile_id].nil?
sprite.z = @viewport.z + y * 32 + @priority_ids[tile_id] * 32 + 32
end
# Add to sprites Array
@autotile_sprites << [sprite, tx, ty, tz]
end
end
#--------------------------------------------------------------------------
# * Get new autotile Bitmap
# tile_id : tile id
#--------------------------------------------------------------------------
def get_update_autotile(tile_id)
# Kill invalid Data
return if tile_id == nil or tile_id >= 384
return if tile_id == 0
# Get AutotileGraphic
autotile = @autotiles[tile_id/48-1]
return if autotile.nil? or autotile.disposed?
# Get Frame Data
frames = (autotile.height == 32 ? autotile.width / 32 : autotile.width / 96)
current_frame = (Graphics.frame_count/AutotileLength) % frames
# Now Get Frame Bitmap
src_bitmap = @auto_tiles[tile_id][current_frame]
return src_bitmap
end
#--------------------------------------------------------------------------
# * Set x origin value
# value : new value
#--------------------------------------------------------------------------
def ox=(value)
# Next line is needed if you want to do complex things if ox changes
return unless @ox != value
@ox = value
end
#--------------------------------------------------------------------------
# * Set y origin value
# value : new value
#--------------------------------------------------------------------------
def oy=(value)
# Next line is needed if you want to do complex things if oy changes
return unless @oy != value
@oy = value
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# Redraw autotiles if changed
redraw_autotiles if autotiles_changed?
# Cancel updating if invisible
return if not visible?
# Flash Tiles
update_flashing if flashing?
# Update autotiles
update_autotiles if (Graphics.frame_count % AutotileLength) == 0
# Draw Region
draw_current_region
end
#--------------------------------------------------------------------------
# * Update (flashing)
#--------------------------------------------------------------------------
def update_flashing
# To be released
end
#--------------------------------------------------------------------------
# * Update (autotiles)
#--------------------------------------------------------------------------
def update_autotiles
# Determine x and y coords for tile top left
left_x = @ox / 32
top_y = @oy / 32
# Iterate trough sprites
for sprite in @autotile_sprites
# Get Data from Array
real_sprite, tx, ty, tz = sprite
tile_id = tile_id(tx, ty, tz)
# Replace Bitmap (can't clear the bitmap, for some reason - don't try to)
real_sprite.bitmap = get_update_autotile(tile_id)
# We do not need to update the positions already, because it will be done
# the next method call (below update_autotiles, there is draw_current_...)
# so it will be 'fixed' there. No need to call something twice, right?
end
end
end
Code:
#Found by Narzew
class CustomTilemapAutotiles
attr_accessor :changed
def initialize
@changed=true
@tiles=[nil,nil,nil,nil,nil,nil,nil]
end
def []=(i,value)
@tiles[i]=value
@changed=true
end
def [](i)
return @tiles[i]
end
end
class CustomTilemap
Animated_Autotiles_Frames = 15
Autotiles = [
[ [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] ]
]
FlashOpacity=[100,90,80,70,80,90]
attr_reader :tileset
attr_reader :autotiles
attr_reader :map_data
attr_accessor :flash_data
attr_accessor :priorities
attr_reader :visible
attr_accessor :ox
attr_accessor :oy
attr_reader :viewport
attr_accessor :tone
attr_accessor :color
def graphicsHeight
return 480
end
def graphicsWidth
return 640
end
def initialize(viewport)
@tileset = nil # Refers to Map Tileset Name
@autotiles = CustomTilemapAutotiles.new
@map_data = nil # Refers to 3D Array Of Tile Settings
@flash_data = nil # Refers to 3D Array of Tile Flashdata
@priorities = nil # Refers to Tileset Priorities
@visible = true # Refers to Tileset Visibleness
@ox = 0 # Bitmap Offsets
@oy = 0 # bitmap Offsets
@plane = false
@tone=Tone.new(0,0,0,0)
@color=Color.new(0,0,0,0)
@oldtone=Tone.new(0,0,0,0)
@oldcolor=Color.new(0,0,0,0)
@selfviewport=Viewport.new(0,0,graphicsWidth,graphicsHeight)
@viewport=viewport ? viewport : @selfviewport
@tiles=[]
@autotileInfo=[]
@regularTileInfo=[]
@oldOx=0
@oldOy=0
@layer0=Sprite.new(viewport)
@layer0.visible=true
@nowshown=false
@layer0.bitmap=Bitmap.new([graphicsWidth*2,1].max,[graphicsHeight*2,1].max)
@flash=nil
@layer0.ox=0
@layer0.oy=0
@oxLayer0=0
@oyLayer0=0
@oxFlash=0
@oyFlash=0
@layer0.z=0
@priotiles=[]
@prioautotiles=[]
@autosprites=[]
@framecount=[]
@tilesetChanged=true
@flashChanged=false
@firsttime=true
@disposed=false
@usedsprites=false
@layer0clip=true
@firsttimeflash=true
@fullyrefreshed=false
@fullyrefreshedautos=false
end
def disposed?
return @disposed
end
def flash_data=(value)
@flash_data=value
@flashChanged=true
end
def update
if @oldtone!=@tone
@layer0.tone=@tone
@flash.tone=@tone if @flash
for sprite in @autosprites
sprite.tone=@tone
end
for sprite in @tiles
sprite.tone=@tone if sprite.is_a?(Sprite)
end
@oldtone=@tone.clone
end
if @oldcolor!=@color
@layer0.color=@color
@flash.color=@color if @flash
for sprite in @autosprites
sprite.color=@color
end
for sprite in @tiles
sprite.color=@color if sprite.is_a?(Sprite)
end
@oldcolor=@color.clone
end
if @autotiles.changed
refresh_autotiles
repaintAutotiles
end
if @flashChanged
refresh_flash
end
if @tilesetChanged
refresh_tileset
end
if @flash
@flash.opacity=FlashOpacity[(Graphics.frame_count/2) % 6]
end
if !(@oldOx==@ox && @oldOy==@oy &&
!@tilesetChanged &&
!@autotiles.changed)
refresh
end
if (Graphics.frame_count % Animated_Autotiles_Frames == 0) || @nowshown
repaintAutotiles
refresh(true)
end
@nowshown=false
@autotiles.changed=false
@tilesetChanged=false
end
def priorities=(value)
@priorities=value
@tilesetChanged=true
end
def tileset=(value)
@tileset=value
@tilesetChanged=true
end
def shown?
return false if !@visible
ysize=@map_data.ysize
xsize=@map_data.xsize
xStart=(@ox/32)-1
xEnd=((@ox+@viewport.rect.width)/32)+1
yStart=(@oy/32)-1
yEnd=((@oy+@viewport.rect.height)/32)+1
xStart=0 if xStart<0
xStart=xsize-1 if xStart>=xsize
xEnd=0 if xEnd<0
xEnd=xsize-1 if xEnd>=xsize
yStart=0 if yStart<0
yStart=ysize-1 if yStart>=ysize
yEnd=0 if yEnd<0
yEnd=ysize-1 if yEnd>=ysize
return (xStart<xEnd && yStart<yEnd)
end
def dispose
return if disposed?
@help.dispose if @help
@help=nil
i=0;len=@autotileInfo.length;while i<len
if @autotileInfo[i]
@autotileInfo[i].dispose
@autotileInfo[i]=nil
end
i+=1
end
i=0;len=@regularTileInfo.length;while i<len
if @regularTileInfo[i]
@regularTileInfo[i].dispose
@regularTileInfo[i]=nil
end
i+=1
end
i=0;len=@tiles.length;while i<len
@tiles[i].dispose
@tiles[i]=nil
i+=2
end
i=0;len=@autosprites.length;while i<len
@autosprites[i].dispose
@autosprites[i]=nil
i+=2
end
if @layer0
@layer0.bitmap.dispose if !@layer0.disposed?
@layer0.bitmap=nil if !@layer0.disposed?
@layer0.dispose
@layer0=nil
end
if @flash
@flash.bitmap.dispose if !@flash.disposed?
@flash.bitmap=nil if !@flash.disposed?
@flash.dispose
@flash=nil
end
for i in 0...7
self.autotiles[i]=nil
end
@tiles.clear
@autosprites.clear
@autotileInfo.clear
@regularTileInfo.clear
@tilemap=nil
@tileset=nil
@priorities=nil
@selfviewport.dispose
@selfviewport=nil
@disposed=true
end
def bltAutotile(bitmap,x,y,id,frame)
return if frame<0
autotile=@autotiles[id/48-1]
return if !autotile
if autotile.height==32
anim=frame<<5
src_rect=Rect.new(anim,0,32,32)
bitmap.blt(x,y,autotile,src_rect)
else
anim=frame*96
id%=48
tiles = Autotiles[id>>3][id&7]
src=Rect.new(0,0,0,0)
for i in 0...4
tile_position = tiles[i] - 1
src.set(
(tile_position % 6)*16 + anim,
(tile_position / 6)*16, 16, 16)
bitmap.blt(i%2*16+x,i/2*16+y, autotile, src)
end
end
end
def autotileNumFrames(id)
autotile=@autotiles[id/48-1]
return 0 if !autotile || autotile.disposed?
frames=1
if autotile.height==32
frames=autotile.width>>5
else
frames=autotile.width/96
end
return frames
end
def autotileFrame(id)
autotile=@autotiles[id/48-1]
return -1 if !autotile || autotile.disposed?
frames=1
if autotile.height==32
frames=autotile.width>>5
else
frames=autotile.width/96
end
return (Graphics.frame_count/Animated_Autotiles_Frames)%frames
end
def repaintAutotiles
for i in 0...@autotileInfo.length
next if !@autotileInfo[i]
frame=autotileFrame(i)
bltAutotile(@autotileInfo[i],0,0,i,frame)
end
end
def getAutotile(sprite,id)
anim=autotileFrame(id)
return if anim<0
bitmap=@autotileInfo[id]
if !bitmap
bitmap=Bitmap.new(32,32)
bltAutotile(bitmap,0,0,id,anim)
@autotileInfo[id]=bitmap
end
sprite.bitmap=bitmap if !sprite.equal?(bitmap) || sprite.bitmap!=bitmap
end
def getRegularTile(sprite,id)
if false
sprite.bitmap=@tileset if !sprite.equal?(@tileset) || sprite.bitmap!=@tileset
sprite.src_rect.set(((id - 384)&7)<<5,((id - 384)>>3)<<5,32,32)
else
bitmap=@regularTileInfo[id]
if !bitmap
bitmap=Bitmap.new(32,32)
rect=Rect.new(((id - 384)&7)<<5,((id - 384)>>3)<<5,32,32)
bitmap.blt(0,0,@tileset,rect)
@regularTileInfo[id]=bitmap
end
sprite.bitmap=bitmap if !sprite.equal?(bitmap) || sprite.bitmap!=bitmap
end
end
def addTile(tiles,count,xpos,ypos,id)
if id>=384
if count>=tiles.length
sprite=Sprite.new(@viewport)
tiles.push(sprite,0)
else
sprite=tiles[count]
tiles[count+1]=0
end
sprite.visible=@visible
sprite.x=xpos
sprite.y=ypos
sprite.tone=@tone
sprite.color=@color
getRegularTile(sprite,id)
spriteZ=(@priorities[id]==0||!@priorities[id]) ? 0 : ypos+@priorities[id]*32+32
sprite.z=spriteZ
count+=2
else
if count>=tiles.length
sprite=Sprite.new(@viewport)
tiles.push(sprite,1)
else
sprite=tiles[count]
tiles[count+1]=1
end
sprite.visible=@visible
sprite.x=xpos
sprite.y=ypos
sprite.tone=@tone
sprite.color=@color
getAutotile(sprite,id)
spriteZ=(@priorities[id]==0||!@priorities[id]) ? 0 : ypos+@priorities[id]*32+32
sprite.z=spriteZ
count+=2
end
return count
end
def refresh_tileset
i=0;len=@regularTileInfo.length;while i<len
if @regularTileInfo[i]
@regularTileInfo[i].dispose
@regularTileInfo[i]=nil
end
i+=1
end
@regularTileInfo.clear
@priotiles.clear
ysize=@map_data.ysize
xsize=@map_data.xsize
zsize=@map_data.zsize
if xsize>100 || ysize>100
@fullyrefreshed=false
else
for z in 0...zsize
for y in 0...ysize
for x in 0...xsize
id = @map_data[x, y, z]
next if id==0 || !@priorities[id]
next if @priorities[id]==0
@priotiles.push([x,y,z,id])
end
end
end
@fullyrefreshed=true
end
end
def refresh_flash
if @flash_data && !@flash
@flash=Sprite.new(viewport)
@flash.visible=true
@flash.z=1
@flash.blend_type=1
@flash.bitmap=Bitmap.new([graphicsWidth*2,1].max,[graphicsHeight*2,1].max)
@firsttimeflash=true
elsif !@flash_data && @flash
@flash.bitmap.dispose if @flash.bitmap
@flash.dispose
@flash=nil
@firsttimeflash=false
end
end
def refresh_autotiles
i=0;len=@autotileInfo.length;while i<len
if @autotileInfo[i]
@autotileInfo[i].dispose
@autotileInfo[i]=nil
end
i+=1
end
i=0;len=@autosprites.length;while i<len
if @autosprites[i]
@autosprites[i].dispose
@autosprites[i]=nil
end
i+=2
end
@autosprites.clear
@autotileInfo.clear
@prioautotiles.clear
hasanimated=false
for i in 0...7
numframes=autotileNumFrames(48*(i+1))
hasanimated=true if numframes>=2
@framecount[i]=numframes
end
if hasanimated
ysize=@map_data.ysize
xsize=@map_data.xsize
zsize=@map_data.zsize
if xsize>100 || ysize>100
@fullyrefreshedautos=false
else
for y in 0...ysize
for x in 0...xsize
haveautotile=false
for z in 0...zsize
id = @map_data[x, y, z]
next if id==0 || id>=384 || @priorities[id]!=0 || !@priorities[id]
next if @framecount[id/48-1]<2
haveautotile=true
break
end
@prioautotiles.push([x,y]) if haveautotile
end
end
@fullyrefreshedautos=true
end
else
@fullyrefreshedautos=true
end
end
def map_data=(value)
@map_data=value
@tilesetChanged=true
end
def refreshFlashSprite
return if !@flash || @flash_data.nil?
ptX=@ox-@oxFlash
ptY=@oy-@oyFlash
if !@firsttimeflash && !@usedsprites &&
ptX>=0 && ptX+@viewport.rect.width<=@flash.bitmap.width &&
ptY>=0 && ptY+@viewport.rect.height<=@flash.bitmap.height
@flash.ox=0
@flash.oy=0
@flash.src_rect.set(ptX.round,ptY.round,
@viewport.rect.width,@viewport.rect.height)
return
end
width=@flash.bitmap.width
height=@flash.bitmap.height
bitmap=@flash.bitmap
ysize=@map_data.ysize
xsize=@map_data.xsize
zsize=@map_data.zsize
@firsttimeflash=false
@oxFlash=@ox-(width>>2)
@oyFlash=@oy-(height>>2)
@flash.ox=0
@flash.oy=0
@flash.src_rect.set(width>>2,height>>2,
@viewport.rect.width,@viewport.rect.height)
@flash.bitmap.clear
@oxFlash=@oxFlash.floor
@oyFlash=@oyFlash.floor
xStart=(@oxFlash>>5)
xStart=0 if xStart<0
yStart=(@oyFlash>>5)
yStart=0 if yStart<0
xEnd=xStart+(width>>5)+1
yEnd=yStart+(height>>5)+1
xEnd=xsize if xEnd>=xsize
yEnd=ysize if yEnd>=ysize
if xStart<xEnd && yStart<yEnd
yrange=yStart...yEnd
xrange=xStart...xEnd
tmpcolor=Color.new(0,0,0,0)
for y in yrange
ypos=(y<<5)-@oyFlash
for x in xrange
xpos=(x<<5)-@oxFlash
id = @flash_data[x, y, 0]
r=(id>>8)&15
g=(id>>4)&15
b=(id)&15
tmpcolor.set(r<<4,g<<4,b<<4)
bitmap.fill_rect(xpos,ypos,32,32,tmpcolor)
end
end
end
end
def refreshLayer0(autotiles=false)
if autotiles
return true if !shown?
end
ptX=@ox-@oxLayer0
ptY=@oy-@oyLayer0
if !autotiles && !@firsttime && !@usedsprites &&
ptX>=0 && ptX+@viewport.rect.width<=@layer0.bitmap.width &&
ptY>=0 && ptY+@viewport.rect.height<=@layer0.bitmap.height
if @layer0clip
@layer0.ox=0
@layer0.oy=0
@layer0.src_rect.set(ptX.round,ptY.round,
@viewport.rect.width,@viewport.rect.height)
else
@layer0.ox=ptX.round
@layer0.oy=ptY.round
@layer0.src_rect.set(0,0,@layer0.bitmap.width,@layer0.bitmap.height)
end
return true
end
width=@layer0.bitmap.width
height=@layer0.bitmap.height
bitmap=@layer0.bitmap
ysize=@map_data.ysize
xsize=@map_data.xsize
zsize=@map_data.zsize
if autotiles
return true if @fullyrefreshedautos && @prioautotiles.length==0
xStart=(@oxLayer0>>5)
xStart=0 if xStart<0
yStart=(@oyLayer0>>5)
yStart=0 if yStart<0
xEnd=xStart+(width>>5)+1
yEnd=yStart+(height>>5)+1
xEnd=xsize if xEnd>xsize
yEnd=ysize if yEnd>ysize
return true if xStart>=xEnd || yStart>=yEnd
trans=Color.new(0,0,0,0)
temprect=Rect.new(0,0,0,0)
tilerect=Rect.new(0,0,32,32)
range=0...zsize
overallcount=0
count=0
if !@fullyrefreshedautos
for y in yStart..yEnd
for x in xStart..xEnd
haveautotile=false
for z in range
id = @map_data[x, y, z]
next if id<48 || id>=384 || @priorities[id]!=0 || !@priorities[id]
next if @framecount[id/48-1]<2
if !haveautotile
haveautotile=true
overallcount+=1
xpos=(x<<5)-@oxLayer0
ypos=(y<<5)-@oyLayer0
bitmap.fill_rect(xpos,ypos,0,0,trans) if overallcount<=2000
break
end
end
for z in range
id = @map_data[x,y,z]
next if id<48 || @priorities[id]!=0 || !@priorities[id]
if overallcount>2000
xpos=(x<<5)-@oxLayer0
ypos=(y<<5)-@oyLayer0
count=addTile(@autosprites,count,xpos,ypos,id)
next
elsif id>=384
temprect.set(((id - 384)&7)<<5,((id - 384)>>3)<<5,32,32)
xpos=(x<<5)-@oxLayer0
ypos=(y<<5)-@oyLayer0
bitmap.blt(xpos,ypos,@tileset,temprect)
else
tilebitmap=@autotileInfo[id]
if !tilebitmap
anim=autotileFrame(id)
next if anim<0
tilebitmap=Bitmap.new(32,32)
bltAutotile(tilebitmap,0,0,id,anim)
@autotileInfo[id]=tilebitmap
end
xpos=(x<<5)-@oxLayer0
ypos=(y<<5)-@oyLayer0
bitmap.blt(xpos,ypos,tilebitmap,tilerect)
end
end
end
end
else
for tile in @prioautotiles
x=tile[0]
y=tile[1]
next if x<xStart||x>xEnd
next if y<yStart||y>yEnd
overallcount+=1
xpos=(x<<5)-@oxLayer0
ypos=(y<<5)-@oyLayer0
bitmap.fill_rect(xpos,ypos,0,0,trans) if overallcount<=2000
for z in range
id = @map_data[x,y,z]
next if id<48 || @priorities[id]!=0 || !@priorities[id]
if overallcount>2000
count=addTile(@autosprites,count,xpos,ypos,id)
next
elsif id>=384
temprect.set(((id - 384)&7)<<5,((id - 384)>>3)<<5,32,32)
bitmap.blt(xpos,ypos,@tileset,temprect)
else
tilebitmap=@autotileInfo[id]
if !tilebitmap
anim=autotileFrame(id)
next if anim<0
tilebitmap=Bitmap.new(32,32)
bltAutotile(tilebitmap,0,0,id,anim)
@autotileInfo[id]=tilebitmap
end
bitmap.blt(xpos,ypos,tilebitmap,tilerect)
end
end
end
end
Graphics.frame_reset if overallcount>2000
@usedsprites=false
return true
end
return false if @usedsprites
@firsttime=false
@oxLayer0=@ox-(width>>2)
@oyLayer0=@oy-(height>>2)
if @layer0clip
@layer0.ox=0
@layer0.oy=0
@layer0.src_rect.set(width>>2,height>>2,
@viewport.rect.width,@viewport.rect.height)
else
@layer0.ox=(width>>2)
@layer0.oy=(height>>2)
end
@layer0.bitmap.clear
@oxLayer0=@oxLayer0.floor
@oyLayer0=@oyLayer0.floor
xStart=(@oxLayer0>>5)
xStart=0 if xStart<0
yStart=(@oyLayer0>>5)
yStart=0 if yStart<0
xEnd=xStart+(width>>5)+1
yEnd=yStart+(height>>5)+1
xEnd=xsize if xEnd>=xsize
yEnd=ysize if yEnd>=ysize
if xStart<xEnd && yStart<yEnd
tmprect=Rect.new(0,0,0,0)
yrange=yStart...yEnd
xrange=xStart...xEnd
for z in 0...zsize
for y in yrange
ypos=(y<<5)-@oyLayer0
for x in xrange
xpos=(x<<5)-@oxLayer0
id = @map_data[x, y, z]
next if id==0 || @priorities[id]!=0 || !@priorities[id]
if id>=384
tmprect.set((id - 384) % 8 * 32, (id - 384) / 8 * 32,32,32)
bitmap.blt(xpos,ypos,@tileset,tmprect)
else
frame=autotileFrame(id)
bltAutotile(bitmap,xpos,ypos,id,frame)
end
end
end
end
Graphics.frame_reset
end
return true
end
def getResizeFactor
return $ResizeFactor ? $ResizeFactor : 1.0
end
def ox=(val)
val=(val*getResizeFactor).to_i
val=(val/getResizeFactor).to_i
wasshown=self.shown?
@ox=val.floor
@nowshown=(!wasshown && self.shown?)
end
def oy=(val)
val=(val*getResizeFactor).to_i
val=(val/getResizeFactor).to_i
wasshown=self.shown?
@oy=val.floor
@nowshown=(!wasshown && self.shown?)
end
def visible=(val)
wasshown=@visible
@visible=val
@nowshown=(!wasshown && val)
end
def refresh(autotiles=false)
@oldOx=@ox
@oldOy=@oy
usesprites=false
if @layer0
@layer0.visible=@visible
usesprites=!refreshLayer0(autotiles)
if autotiles && !usesprites
return
end
else
usesprites=true
end
refreshFlashSprite
vpx=@viewport.rect.x
vpy=@viewport.rect.y
vpr=@viewport.rect.width+vpx
vpb=@viewport.rect.height+vpy
xsize=@map_data.xsize
ysize=@map_data.ysize
minX=(@ox/32)-1
maxX=((@ox+@viewport.rect.width)/32)+1
minY=(@oy/32)-1
maxY=((@oy+@viewport.rect.height)/32)+1
minX=0 if minX<0
minX=xsize-1 if minX>=xsize
maxX=0 if maxX<0
maxX=xsize-1 if maxX>=xsize
minY=0 if minY<0
minY=ysize-1 if minY>=ysize
maxY=0 if maxY<0
maxY=ysize-1 if maxY>=ysize
count=0
if minX<maxX && minY<maxY
@usedsprites=usesprites || @usedsprites
if @layer0
@layer0.visible=false if usesprites
end
if @fullyrefreshed
for prio in @priotiles
x=prio[0]
y=prio[1]
next if x<minX||x>maxX
next if y<minY||y>maxY
id=prio[3]
xpos=(x<<5)-@ox
ypos=(y<<5)-@oy
count=addTile(@tiles,count,xpos,ypos,id)
end
else
for z in 0...@map_data.zsize
for y in minY..maxY
for x in minX..maxX
id = @map_data[x, y, z]
next if id==0 || !@priorities[id]
next if @priorities[id]==0
xpos=(x<<5)-@ox
ypos=(y<<5)-@oy
count=addTile(@tiles,count,xpos,ypos,id)
end
end
end
end
end
if count<@tiles.length
bigchange=(count<=(@tiles.length*2/3)) && (@tiles.length*2/3)>25
j=count;len=@tiles.length;while j<len
sprite=@tiles[j]
@tiles[j+1]=-1
if bigchange
sprite.dispose
@tiles[j]=nil
@tiles[j+1]=nil
elsif !@tiles[j].disposed?
sprite.visible=false if sprite.visible
end
j+=2
end
@tiles.compact! if bigchange
end
end
end