А за чем переменной события десятичная дробь? я лично не вижу как это можно использовать.
Вид для печати
А за чем переменной события десятичная дробь? я лично не вижу как это можно использовать.
Касаемо меня, я пока что ничего не думаю. Судя по постам на некоторых сайтах, в VX этот класс сильно изменился. Кроме того, на VX я не нашёл ни одной пользовательской реализации, а на XP сразу несколько. Пока надо спокойно изучить и посмотреть что к чему. Всё-таки надо его не просто переписать, а переписать так, чтобы он заработал на обоих мэйкерах.Цитата:
Господа, так что вы думаете касательно Tilemap?
Там же и приступим к тесту на практике.
Ну и нормально. Разве где-то они могут понадобиться?Цитата:
Кстати, вы замечали, что Maker на дух не переносит числа с плавающей точкой?
Естественно! Вот выдвигаешь ты окошко из-за границы экрана. Размер окошка произвольный, размер экрана произвольный, высчитываешь шаг и... окошко остается за границами экрана. А все потому, что при попытке сдвинуть его на 0.4 пикселя влево, вместо того чтобы запомнить 0.4 для следующих операций, мейкер его просто отбрасывает! Я когда писал скрипт системы диалогов специально под такие вычисления хэш заводил, для хранения дробной части.
Хм, мне казалось, что я спер этот скрипт именно с VX:
Впрочем, может, и ошибаюсь. Поскольку он закрыт и нам остаются лишь методы метапрограммирования для его изучения, то о том, что внутри самих методов остается лишь гадать. Следовательно, извлекаем интерфейсы, объединяем, пишем на основе получившегося интерфейса класс. И что там будет внутри - мейкеров не касается. :) Разная обработка тайлсета. Вероятно, будут различатсья ID автотайлов. По сути всё.Код:#===============================================================================
# Custom Tilemap v1.2
# Автор оригинала: poccil
# Над скриптом измывались: Equilibrium Keeper [ICQ: 470355387]
#===============================================================================
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
#===============================================================================
# Класс, управляющий картами тайла. Карты тайла - специализированное понятие в
# отображении карт 2D игр, созданный внутренне от множества спрайтов.
#===============================================================================
class Tilemap
#-----------------------------------------------------------------------------
# Константы
#-----------------------------------------------------------------------------
Resize_Factor = 1.0
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_reader :visible
attr_reader :viewport
attr_accessor :flash_data
attr_accessor :priorities
attr_accessor :ox
attr_accessor :oy
#-----------------------------------------------------------------------------
# Инициализация
# viewport :viewport - область просмотра
#-----------------------------------------------------------------------------
def initialize(viewport = nil)
@viewport = viewport ? viewport :
Viewport.new(0, 0, Graphics.width, Graphics.height)
@autotiles = CustomTilemapAutotiles.new
@visible = true # Refers to Tileset Visibleness
@ox = 0 # Bitmap Offsets
@oy = 0 # bitmap Offsets
@tiles = []
@autotileInfo = []
@regularTileInfo = []
@oldOx = 0
@oldOy = 0
@layer0 = Sprite.new(viewport)
@layer0.visible = true
@layer0.bitmap = Bitmap.new(@viewport.rect.width * 2, @viewport.rect.height * 2)
@layer0.ox = 0
@layer0.oy = 0
@oxLayer0 = 0
@oyLayer0 = 0
@oxFlash = 0
@oyFlash = 0
@layer0.z = 0
@priotiles = []
@prioautotiles = []
@autosprites = []
@framecount = []
@tileset_changed = true
@firsttime = true
@layer0clip = true
@firsttimeflash = true
end
#-----------------------------------------------------------------------------
# Возвращает TRUE, если карта тайлов была освобождёна.
#-----------------------------------------------------------------------------
def disposed?
return @disposed
end
#-----------------------------------------------------------------------------
# Освобождает карту тайлов. Если карта тайлов уже была освобождёна, не делает
# ничего.
#-----------------------------------------------------------------------------
def dispose
return if disposed?
@help.free
@autotileInfo.free
@regularTileInfo.free
@tiles.free
@autosprites.free
@layer0.free
@flash.free
self.autotiles.free
@priorities.free
@disposed = true
end
#-----------------------------------------------------------------------------
# Задает новое значение вспышки
#-----------------------------------------------------------------------------
def flash_data=(value)
@flash_data = value
@flash_changed = true
end
#-----------------------------------------------------------------------------
# Обновляет анимацию динамических тайлов и др. Как правило, этот метод
# вызывается один раз за кадр.
#-----------------------------------------------------------------------------
def update
if @autotiles.changed
refresh_autotiles
repaint_autotiles
end
if @flash_changed
refresh_flash
end
if @tileset_changed
refresh_tileset
end
if @flash.exists?
@flash.opacity = FlashOpacity[(Graphics.frame_count / 2) % 6]
end
unless (@oldOx == @ox && @oldOy == @oy && !@tileset_changed && !@autotiles.changed)
refresh
end
if (Graphics.frame_count % Animated_Autotiles_Frames == 0) && shown?
repaint_autotiles
refresh(false)
end
@nowshown = false
@autotiles.changed = false
@tileset_changed = false
end
#-----------------------------------------------------------------------------
# Задает новую таблицу приоритетов
#-----------------------------------------------------------------------------
def priorities=(value)
@priorities = value
@tileset_changed = true
end
#-----------------------------------------------------------------------------
# Задает новый тайлсет
#-----------------------------------------------------------------------------
def tileset=(value)
@tileset = value
@tileset_changed = true
end
#-----------------------------------------------------------------------------
# Отображено
#-----------------------------------------------------------------------------
def shown?
return false unless @visible
start_x = ((@ox / 32) - 1).limit(0, @map_data.xsize - 1)
start_y = ((@oy / 32) - 1).limit(0, @map_data.ysize - 1)
end_x = (((@ox + @viewport.rect.width) / 32) + 1).limit(0, @map_data.xsize - 1)
end_y = (((@oy + @viewport.rect.height) / 32) + 1).limit(0, @map_data.ysize - 1)
return (start_x < end_x && start_y < end_y)
end
#-----------------------------------------------------------------------------
# Рисует автотайлы
#-----------------------------------------------------------------------------
def bltAutotile(bitmap, x, y, id, frame)
return if frame < 0
autotile = @autotiles[id / 48 - 1]
return unless autotile
if autotile.height == 32
anim=frame*32
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 unless autotile.exists?
frames = 1
if autotile.height == 32
frames = autotile.width / 32
else
frames = autotile.width / 96
end
return frames
end
#-----------------------------------------------------------------------------
# ???
#-----------------------------------------------------------------------------
def autotileFrame(id)
autotile = @autotiles[id / 48 - 1]
return -1 unless autotile.exists?
frames = 1
if autotile.height == 32
frames = autotile.width / 32
else
frames = autotile.width / 96
end
return (Graphics.frame_count / Animated_Autotiles_Frames) % frames
end
#-----------------------------------------------------------------------------
# Перерисовка автотайлов
#-----------------------------------------------------------------------------
def repaint_autotiles
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]
unless 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 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.bitmap = RPG::Cache.tile(@tileset, id, 0)
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
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
@regularTileInfo.free
@priotiles.free
if @map_data.xsize > 100 || @map_data.ysize > 100
@fullyrefreshed = false
else
for z in 0...@map_data.zsize
for y in 0...@map_data.ysize
for x in 0...@map_data.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.exists?
@flash = Sprite.new(viewport)
@flash.visible = true
@flash.z = 1
@flash.blend_type = 1
@flash.bitmap = Bitmap.new(@viewport.rect.width * 2, @viewport.rect.height * 2)
@firsttimeflash = true
elsif !@flash_data && @flash.exists?
@flash.free
@firsttimeflash = false
end
end
#-----------------------------------------------------------------------------
# Освежаем автотайлы
#-----------------------------------------------------------------------------
def refresh_autotiles
@autotileInfo.free
@autosprites.free
@prioautotiles.free
hasanimated = false
for i in 0...7
numframes = autotileNumFrames(48 * (i + 1))
hasanimated = true if numframes >= 2
@framecount[i] = numframes
end
if hasanimated
if @map_data.xsize > 100 || @map_data.ysize > 100
@fullyrefreshedautos = false
else
for y in 0...@map_data.ysize
for x in 0...@map_data.xsize
haveautotile = false
for z in 0...@map_data.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
#-----------------------------------------------------------------------------
# Задаем новую map_data
#-----------------------------------------------------------------------------
def map_data=(value)
@map_data = value
@tileset_changed = true
end
#-----------------------------------------------------------------------------
# Освежаем спрайт вспышки
#-----------------------------------------------------------------------------
def refreshFlashSprite
return if !@flash.exists? || @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
start_x = (@oxFlash >> 5).correct(0, nil)
start_y = (@oyFlash >> 5).correct(0, nil)
end_x = (start_x + (width >> 5) + 1).correct(nil, xsize)
end_y = (start_y + (height >> 5) + 1).correct(nil, ysize)
if start_x < end_x && start_y < end_y
yrange = start_y...end_y
xrange = start_x...end_x
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 * 16, g * 16, b * 16)
bitmap.fill_rect(xpos, ypos, 32, 32, tmpcolor)
end
end
end
end
#-----------------------------------------------------------------------------
# Обновляем слой спрайтов
#-----------------------------------------------------------------------------
def refreshLayer0(autotiles = false)
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
return true if !shown?
start_x = (@oxLayer0 >> 5)
start_x = 0 if start_x < 0
start_y = (@oyLayer0 >> 5)
start_y = 0 if start_y < 0
end_x = start_x + (width >> 5) + 1
end_y = start_y + (height >> 5) + 1
end_x = xsize if end_x > xsize
end_y = ysize if end_y > ysize
return true if start_x >= end_x || start_y >= end_y
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
unless @fullyrefreshedautos
for y in start_y..end_y
for x in start_x..end_x
haveautotile = false
for z in range
id = @map_data[x, y, z]
break unless id
next if id < 48 || id >= 384 || @priorities[id] != 0 || !@priorities[id]
next if id == 0 || id >= 384 || @priorities[id] != 0 || !@priorities[id]
next if @framecount[id / 48 - 1] < 2
haveautotile = true
break
end
next unless haveautotile
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) % 8 * 32, (id - 384) / 8 * 32, 32, 32)
bitmap.blt(xpos, ypos, RPG::Cache.tileset(@tileset), temprect)
else
tilebitmap = @autotileInfo[id]
unless 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
else
for tile in @prioautotiles
x = tile[0]
y = tile[1]
next if x < start_x || x > end_x
next if y < start_y || y > end_y
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) % 8 * 32, (id - 384) / 8 * 32, 32, 32)
bitmap.blt(xpos, ypos, RPG::Cache.tileset(@tileset), temprect)
else
tilebitmap = @autotileInfo[id]
unless 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
start_x = (@oxLayer0 >> 5)
start_x = 0 if start_x < 0
start_y = (@oyLayer0 >> 5)
start_y = 0 if start_y < 0
end_x = start_x + (width >> 5) + 1
end_y = start_y + (height >> 5) + 1
end_x = xsize if end_x >= xsize
end_y = ysize if end_y >= ysize
if start_x < end_x && start_y < end_y
tmprect = Rect.new(0, 0, 0, 0)
yrange = start_y...end_y
xrange = start_x...end_x
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, RPG::Cache.tileset(@tileset), tmprect)
else
frame = autotileFrame(id)
bltAutotile(bitmap, xpos, ypos, id, frame)
end
end
end
end
Graphics.frame_reset
end
return true
end
#-----------------------------------------------------------------------------
# Задаем новое значение координате ox
#-----------------------------------------------------------------------------
def ox=(val)
val = (val * Resize_Factor).to_i
val = (val / Resize_Factor).to_i
wasshown = self.shown?
@ox = val.floor
@nowshown = (!wasshown && self.shown?)
end
#-----------------------------------------------------------------------------
# Задаем новое значение координате oy
#-----------------------------------------------------------------------------
def oy=(val)
val = (val * Resize_Factor).to_i
val = (val / Resize_Factor).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
min_x = ((@ox / 32) - 1).limit(0, xsize - 1)
min_y = ((@oy / 32) - 1).limit(0, ysize - 1)
max_x = (((@ox + @viewport.rect.width) / 32) + 1).limit(0, xsize - 1)
max_Y = (((@oy + @viewport.rect.height) / 32) + 1).limit(0, ysize - 1)
count = 0
if min_x < max_x && min_y < max_Y
@usedsprites = usesprites || @usedsprites
if @layer0
@layer0.visible = false if usesprites
end
if @fullyrefreshed
for prio in @priotiles
next if prio[0] < min_x || prio[0] > max_x
next if prio[1] < min_y || prio[1] > max_Y
id = prio[3]
xpos = (prio[0] << 5) - @ox
ypos = (prio[1] << 5) - @oy
count = addTile(@tiles, count, xpos, ypos, id)
end
else
for z in 0...@map_data.zsize
for y in min_y..max_Y
for x in min_x..max_x
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
Кстати да, с легкописностью общих слоев я погорячился. Все немножко сложнее - слоев будет не 3, а 3 * N, где N - количество возможных приоритетов. Но, в любом случае, лучше 18 спрайтов, чем 40000.
Как я понял ты имеешь в виду сделать неограниченное количество слоёв, используя много карт и как бы накладывая их друг на друга. Это можно сделать небольшим редактированием Spriteset_Map без всяких этих Rpg::Tilemap. Кстати это позволит использовать несколько тайлов одновременно. (но как это сделать для обоих мэйкеров мне неизвестно)
Насчёт десятичных дробей. Может в Window есть какой то скрытый round.
Andrew
Ты немного неверно понимаешь ситуацию. Тут идет переписывание базовых классов, включая Tilemap, и возможность наложения карт - не цель, а плюшка. (=
А хочу я оптимизировать тайловую систему мейкера, чтобы вместо сотен спрайтов с крошечными картинками, было несколько спрайтов с огромными картинками. Такой набор легче обрабатывать, как программисту, так и программе (тем более однопоточной). Это, конечно, в нормальном языке программирования. Мейкер может подложить свинью, если, к примеру, работа с большими изображениями изначально кривая. Тогда это наоборот выйдет боком. Надо тестить.
Код:module RPG
##
# Класс с данными игровой локации.
##
class Map
#==========================================================================
# Атрибуты
#==========================================================================
# ID набора тайлов, используемого в локации.
# @note Используется в XP.
# @return [Integer]
attr_accessor :tileset_id
# Ширина (в тайлах).
# @return [Integer]
attr_accessor :width
# Высота (в тайлах).
# @return [Integer]
attr_accessor :height
# Зацикливание (0: нет, 1: вертикальное, 2: горизонтальное, 3: оба)
# @note Используется в VX.
# @return [Integer]
attr_accessor :scroll_type
# Определяет, будет ли изменена фоновая музыка при переходе на локацию.
# @return [Boolean]
attr_accessor :autoplay_bgm
# Фоновая музыка.
# @return [RPG::AudioFile]
attr_accessor :bgm
# Определяет, будут ли изменены фоновые звуки при переходе на локацию.
# @return [Boolean]
attr_accessor :autoplay_bgs
# Фоновые звуки.
# @return [RPG::AudioFile]
attr_accessor :bgs
# Флаг активности опции "Бегать запрещено"
# @note Используется в VX.
# @return [Boolean]
attr_accessor :disable_dashing
# Список ID встречающихся на карте групп врагов.
# @return [Array<Integer>]
attr_accessor :encounter_list
# Количество шагов между встречами с врагами.
# @return [Integer]
attr_accessor :encounter_step
# Название файла, использующегося в качестве панорамы (графики фона) локации.
# @note Используется в VX.
# @return [String]
attr_accessor :parallax_name
# Определяет, зациклена ли панорама по горизонтале.
# @note Используется в VX.
# @return [Boolean]
attr_accessor :parallax_loop_x
# Определяет, зациклена ли панорама по вертикале.
# @note Используется в VX.
# @return [Boolean]
attr_accessor :parallax_loop_y
# Скорость движения панорамы по горизонтале. Знак определяет направление.
# @note Используется в VX.
# @return [Boolean]
attr_accessor :parallax_sx
# Скорость движения панорамы по вертикале. Знак определяет направление.
# @note Используется в VX.
# @return [Boolean]
attr_accessor :parallax_sy
# Определяет, следует ли отображать панораму в редакторе.
# @note Используется в VX.
# @return [Boolean]
attr_accessor :parallax_show
# Данные карты. 3-мерный массив ID тайлов.
# @return [Table]
attr_accessor :data
# События карты.
# @note Хэш, в котором ключ - ID события, значение - его экземпляр.
# @return [Hash<Integer, RPG::Event>]
attr_accessor :events
#==========================================================================
# Методы
#==========================================================================
##
# Инициализирует переменные экземпляра, присваивает им значения по умолчанию
#
# @param [Integer] width Ширина новой игровой локации (в тайлах).
# @param [Integer] height Высота новой игровой локации (в тайлах).
#
# @note Вызывается автоматически при создании нового экземпляра
#
# @return [NilClass]
##
def initialize(width, height)
@tileset_id = 1
@width = width
@height = height
@scroll_type = 0
@autoplay_bgm = false
@bgm = RPG::AudioFile.new
@autoplay_bgs = false
@bgs = RPG::AudioFile.new("", 80)
@disable_dashing = false
@encounter_list = []
@encounter_step = 30
@parallax_name = ""
@parallax_loop_x = false
@parallax_loop_y = false
@parallax_sx = 0
@parallax_sy = 0
@parallax_show = false
@data = Table.new(width, height, 3)
@events = {}
end
# -------------------------------------------------------------------------
end
# ---------------------------------------------------------------------------
end
Код:module RPG
##
# Класс с данными информации об игровой локации.
##
class MapInfo
#==========================================================================
# Атрибуты
#==========================================================================
# Название карты.
# @return [String]
attr_accessor :name
# ID родительской карты.
# @return [Integer]
attr_accessor :parent_id
# Индекс узла в дереве карт.
# @note Используется в редакторе.
# @return [Integer]
attr_accessor :order
# Определяет развернуто ли древо карт.
# @note Используется в редакторе.
# @return [Boolean]
attr_accessor :expanded
# Положение горизонтального ползунка прокрутки карты.
# @note Используется в редакторе.
# @return [Integer]
attr_accessor :scroll_x
# Положение вертикального ползунка прокрутки карты.
# @note Используется в редакторе.
# @return [Integer]
attr_accessor :scroll_y
#==========================================================================
# Методы
#==========================================================================
##
# Инициализирует переменные экземпляра, присваивает им значения по умолчанию
#
# @note Вызывается автоматически при создании нового экземпляра
#
# @return [NilClass]
##
def initialize
@name = ""
@parent_id = 0
@order = 0
@expanded = false
@scroll_x = 0
@scroll_y = 0
end
# -------------------------------------------------------------------------
end
# ---------------------------------------------------------------------------
end
Код:module RPG
##
# Класс с данными команды [Move] ("Переместить").
##
class MoveCommand(code = 0, parameters = [])
#==========================================================================
# Атрибуты
#==========================================================================
# Код комманды.
# @return [Integer]
attr_accessor :code
# Массив, содержащий аргументы команды [Move] ("Переместить").
# @note Содержание массива изменяется в зависимости от команды.
# @return [Array<Object>]
attr_accessor :parameters
#==========================================================================
# Методы
#==========================================================================
##
# Инициализирует переменные экземпляра, присваивает им значения по умолчанию
#
# @note Вызывается автоматически при создании нового экземпляра
#
# @return [NilClass]
##
def initialize
@code = code
@parameters = parameters
end
# -------------------------------------------------------------------------
end
# ---------------------------------------------------------------------------
end
Беру RPG::StateКод:module RPG
##
# Класс с данными маршрута движения.
##
class MoveRoute
#==========================================================================
# Атрибуты
#==========================================================================
# Флаг активности опции "Повторять действия".
# @return [Boolean]
attr_accessor :repeat
# Флаг активности опции "Перейти к следующему шагу, если движение невозможно",
# @return [Boolean]
attr_accessor :skippable
# Флаг активности опции "Ждать окончания движения".
# @note Используется в VX.
# @return [Boolean]
attr_accessor :wait
# Список комманд движения, определяющих маршрут следования.
# @return [Array<RPG::MoveCommand>]
attr_accessor :list
#==========================================================================
# Методы
#==========================================================================
##
# Инициализирует переменные экземпляра, присваивает им значения по умолчанию
#
# @note Вызывается автоматически при создании нового экземпляра
#
# @return [NilClass]
##
def initialize
@repeat = true
@skippable = false
@wait = false
@list = [RPG::MoveCommand.new]
end
# -------------------------------------------------------------------------
end
# ---------------------------------------------------------------------------
end
Господа, кто-нибудь, берите RPG::System и его подклассы. У меня времени не будет его сводить расписывать.
Ну-с? Что за затишье? Жду ответа. :)
Кип, я сейчас в раздумьях насчёт того, что нам может предложить VXAce. Если в нём будут исправления слоёв и тайлсетов — можно с гарантией утверждать, что XP и VX уйдут в прошлое.
Скорее всего в нём будут три разных RTP, а это позволяет с высокой степенью вероятности предположить возврат к тайлсетам XP. Надеюсь дебилизма с переключением между RTP не будет. Хотя и в этом случае можно придумать неплохое решение.
Переход на RGSS3 (а не 2.5) также говорит о том, что базовые классы подверглись суровой переписке под новый редактор. Тут есть два хороших момента.
Первый. Вполне возможно, что классы переписали более эффективно и они имеют больше возможностей (в VX такое было).
Второй. Очень вероятно, что в VXAce будет использоваться Ruby 1.9, который в разы быстрее 1.8.1 из VX и XP. Известно, что Ruby 1.9 вышел на несколько дней позже релиза VX, поэтому была использована старая версия. Но для VXAce, думаю, переход к новой ветке должен состояться. Надеюсь, по крайней мере.
И ещё один, последний тезис. В середине 2004-го вышел XP, затем спустя 3.5 года VX и ещё спустя 4 года готовится VXAce. Логично предположить выход следующего за ним мэйкера аж в конце 2015-го года.
Суммируя всё вышесказанное, предлагаю пару месяцев обождать, пока выйдет VXAce и посмотреть на его возможности. Хоть и верится с трудом, но он может стать довольно серьёзной вещью. И поскольку следующий мэйкер будет только через 4 года, то лучше всего продолжать наш проект с обязательной оглядкой на VXAce и только после его выхода. Не исключено, что концепция OpenRGSS3 может полностью измениться.
Разумеется, это всё я выдвинул в качестве предложения. Если решишь продолжить, то продолжим.
Не слышал о VXAce, так что полностью поддерживаю. Если он ничем не будет уступать XP (или это можно будет компенсировать), то за основу нужно будет брать его. Уйдут сотни килобайт кода ориентированного на совместимость. В общем, мы - ждем, а я - гуглю, это чудо. :)
Ну, а после выхода нужно будет в темпе вальса распотрошить сие чудо. Кстати, можно связаться с разрабами? Я, черт возьми, хочу поддержку высоких разрешений!
По причине выхода VXAce разработка OpenRGSS3 заморожена. Если она будет возобновлена, то уже в совсем ином ключе. Всем участникам - спасибо. :)