mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
Updates tilemap renderer for extra autotiles
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -126,6 +126,10 @@ class Game_Map
|
||||
return @map.data;
|
||||
end
|
||||
|
||||
def tileset_id;
|
||||
return @map.tileset_id;
|
||||
end
|
||||
|
||||
def name
|
||||
ret = pbGetMessage(MessageTypes::MapNames, @map_id)
|
||||
ret.gsub!(/\\PN/, $Trainer.name) if $Trainer
|
||||
|
||||
@@ -47,7 +47,11 @@ class Spriteset_Map
|
||||
def initialize(map=nil)
|
||||
@map = (map) ? map : $game_map
|
||||
$scene.map_renderer.add_tileset(@map.tileset_name)
|
||||
@map.autotile_names.each { |filename| $scene.map_renderer.add_autotile(filename) }
|
||||
@map.autotile_names.each do |filename|
|
||||
$scene.map_renderer.add_autotile(filename)
|
||||
$scene.map_renderer.add_extra_autotiles(@map.tileset_id)
|
||||
end
|
||||
|
||||
@panorama = AnimatedPlane.new(@@viewport0)
|
||||
@fog = AnimatedPlane.new(@@viewport1)
|
||||
@fog.z = 3000
|
||||
@@ -77,7 +81,10 @@ class Spriteset_Map
|
||||
def dispose
|
||||
if $scene.is_a?(Scene_Map)
|
||||
$scene.map_renderer.remove_tileset(@map.tileset_name)
|
||||
@map.autotile_names.each { |filename| $scene.map_renderer.remove_autotile(filename) }
|
||||
@map.autotile_names.each do |filename|
|
||||
$scene.map_renderer.remove_autotile(filename)
|
||||
$scene.map_renderer.remove_extra_autotiles(@map.tileset_id)
|
||||
end
|
||||
end
|
||||
@panorama.dispose
|
||||
@fog.dispose
|
||||
|
||||
@@ -15,6 +15,8 @@ class TilemapRenderer
|
||||
DISPLAY_TILE_HEIGHT = Game_Map::TILE_HEIGHT rescue 32
|
||||
SOURCE_TILE_WIDTH = 32
|
||||
SOURCE_TILE_HEIGHT = 32
|
||||
ZOOM_X = DISPLAY_TILE_WIDTH / SOURCE_TILE_WIDTH
|
||||
ZOOM_Y = DISPLAY_TILE_HEIGHT / SOURCE_TILE_HEIGHT
|
||||
TILESET_TILES_PER_ROW = 8
|
||||
AUTOTILES_COUNT = 8 # Counting the blank tile as an autotile
|
||||
TILES_PER_AUTOTILE = 48
|
||||
@@ -23,6 +25,30 @@ class TilemapRenderer
|
||||
# seconds instead.
|
||||
AUTOTILE_FRAME_DURATION = 5 # In 1/20ths of a second
|
||||
|
||||
# Filenames of extra autotiles for each tileset. Each tileset's entry is an
|
||||
# array containing two other arrays (you can leave either of those empty, but
|
||||
# they must be defined):
|
||||
# - The first sub-array is for large autotiles, i.e. ones with 48 different
|
||||
# tile layouts. For example, "Brick path" and "Sea".
|
||||
# - The second is for single tile autotiles. For example, "Flowers1" and
|
||||
# "Waterfall"
|
||||
# The top tiles of the tileset will instead use these autotiles. Large
|
||||
# autotiles come first, in the same 8x6 layout as you see when you double-
|
||||
# click on a real autotile in RMXP. After that are the single tile autotiles.
|
||||
# Extra autotiles are only useful if the tiles are animated, because otherwise
|
||||
# you just have some tiles which belong in the tileset instead.
|
||||
|
||||
# Examples:
|
||||
# 1 => [["Sand shore"], ["Flowers2"]],
|
||||
# 2 => [[], ["Flowers2", "Waterfall", "Waterfall crest", "Waterfall bottom"]],
|
||||
# 6 => [["Water rock", "Sea deep"], []]
|
||||
|
||||
EXTRA_AUTOTILES = {
|
||||
# 23 => {
|
||||
# 384 => "flowers_pink",
|
||||
# }
|
||||
}
|
||||
|
||||
#=============================================================================
|
||||
#
|
||||
#=============================================================================
|
||||
@@ -34,6 +60,7 @@ class TilemapRenderer
|
||||
@bitmaps = {}
|
||||
@bitmap_wraps = {} # Whether each tileset is a mega texture and has multiple columns
|
||||
@load_counts = {}
|
||||
@bridge = 0
|
||||
@changed = true
|
||||
end
|
||||
|
||||
@@ -105,7 +132,7 @@ class TilemapRenderer
|
||||
@frame_counts = {} # Number of frames in each autotile
|
||||
@frame_durations = {} # How long each frame lasts per autotile
|
||||
@current_frames = {} # Which frame each autotile is currently showing
|
||||
@timer = 0.0
|
||||
@timer = 0.0#System.uptime
|
||||
end
|
||||
|
||||
def []=(filename, value)
|
||||
@@ -151,7 +178,7 @@ class TilemapRenderer
|
||||
bitmap = @bitmaps[filename]
|
||||
@frame_counts[filename] = [bitmap.width / SOURCE_TILE_WIDTH, 1].max
|
||||
if bitmap.height > SOURCE_TILE_HEIGHT && @bitmap_wraps[filename]
|
||||
@frame_counts[filename] /= 2 if @bitmap_wraps[filename]
|
||||
@frame_counts[filename] /= 2
|
||||
end
|
||||
end
|
||||
return @frame_counts[filename]
|
||||
@@ -162,9 +189,7 @@ class TilemapRenderer
|
||||
end
|
||||
|
||||
def current_frame(filename)
|
||||
if !@current_frames[filename]
|
||||
set_current_frame(filename)
|
||||
end
|
||||
set_current_frame(filename) if !@current_frames[filename]
|
||||
return @current_frames[filename]
|
||||
end
|
||||
|
||||
@@ -180,7 +205,6 @@ class TilemapRenderer
|
||||
def set_src_rect(tile, tile_id)
|
||||
return if nil_or_empty?(tile.filename)
|
||||
return if !@bitmaps[tile.filename]
|
||||
return if tile_id < TILES_PER_AUTOTILE # Blank tile
|
||||
frame = current_frame(tile.filename)
|
||||
if @bitmaps[tile.filename].height == SOURCE_TILE_HEIGHT
|
||||
tile.src_rect.x = frame * SOURCE_TILE_WIDTH
|
||||
@@ -202,7 +226,7 @@ class TilemapRenderer
|
||||
super
|
||||
@timer += Graphics.delta_s
|
||||
# Update the current frame for each autotile
|
||||
@bitmaps.keys.each do |filename|
|
||||
@bitmaps.each_key do |filename|
|
||||
next if !@bitmaps[filename] || @bitmaps[filename].disposed?
|
||||
old_frame = @current_frames[filename]
|
||||
set_current_frame(filename)
|
||||
@@ -216,6 +240,7 @@ class TilemapRenderer
|
||||
#=============================================================================
|
||||
class TileSprite < Sprite
|
||||
attr_accessor :filename
|
||||
attr_accessor :tile_id
|
||||
attr_accessor :is_autotile
|
||||
attr_accessor :animated
|
||||
attr_accessor :priority
|
||||
@@ -223,10 +248,13 @@ class TilemapRenderer
|
||||
attr_accessor :bridge
|
||||
attr_accessor :need_refresh
|
||||
|
||||
def set_bitmap(filename, autotile, animated, priority, bitmap)
|
||||
def set_bitmap(filename, tile_id, autotile, animated, priority, bitmap)
|
||||
self.bitmap = bitmap
|
||||
self.src_rect = Rect.new(0, 0, DISPLAY_TILE_WIDTH, DISPLAY_TILE_HEIGHT)
|
||||
self.src_rect = Rect.new(0, 0, SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT)
|
||||
self.zoom_x = ZOOM_X
|
||||
self.zoom_y = ZOOM_Y
|
||||
@filename = filename
|
||||
@tile_id = tile_id
|
||||
@is_autotile = autotile
|
||||
@animated = animated
|
||||
@priority = priority
|
||||
@@ -237,9 +265,8 @@ class TilemapRenderer
|
||||
end
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
#
|
||||
#=============================================================================
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def initialize(viewport)
|
||||
@tilesets = TilesetBitmaps.new
|
||||
@autotiles = AutotileBitmaps.new
|
||||
@@ -260,7 +287,7 @@ class TilemapRenderer
|
||||
@tiles_horizontal_count.times do |i|
|
||||
@tiles[i] = []
|
||||
@tiles_vertical_count.times do |j|
|
||||
@tiles[i][j] = Array.new(3) { TileSprite.new(@viewport) }
|
||||
@tiles[i][j] = Array.new(3) { TileSprite.new(@viewport) }
|
||||
end
|
||||
end
|
||||
@current_map_id = 0
|
||||
@@ -297,7 +324,7 @@ class TilemapRenderer
|
||||
return @disposed
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def add_tileset(filename)
|
||||
@tilesets.add(filename)
|
||||
@@ -315,28 +342,60 @@ class TilemapRenderer
|
||||
@autotiles.remove(filename)
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
def add_extra_autotiles(tileset_id)
|
||||
return if !EXTRA_AUTOTILES[tileset_id]
|
||||
EXTRA_AUTOTILES[tileset_id].each do |arr|
|
||||
arr.each { |filename| add_autotile(filename) }
|
||||
end
|
||||
end
|
||||
|
||||
def remove_extra_autotiles(tileset_id)
|
||||
return if !EXTRA_AUTOTILES[tileset_id]
|
||||
EXTRA_AUTOTILES[tileset_id].each do |arr|
|
||||
arr.each { |filename| remove_autotile(filename) }
|
||||
end
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def refresh
|
||||
@need_refresh = true
|
||||
end
|
||||
|
||||
def refresh_tile_bitmap(tile, map, tile_id)
|
||||
tile.tile_id = tile_id
|
||||
if tile_id < TILES_PER_AUTOTILE
|
||||
tile.set_bitmap("", false, false, 0, nil)
|
||||
tile.set_bitmap("", tile_id, false, false, 0, nil)
|
||||
tile.shows_reflection = false
|
||||
tile.bridge = false
|
||||
else
|
||||
terrain_tag = map.terrain_tags[tile_id] || 0
|
||||
terrain_tag_data = GameData::TerrainTag.try_get(terrain_tag)
|
||||
priority = map.priorities[tile_id] || 0
|
||||
if tile_id < TILESET_START_ID
|
||||
filename = map.autotile_names[tile_id / TILES_PER_AUTOTILE - 1]
|
||||
tile.set_bitmap(filename, true, @autotiles.animated?(filename),
|
||||
priority, @autotiles[filename])
|
||||
single_autotile_start_id = TILESET_START_ID
|
||||
true_tileset_start_id = TILESET_START_ID
|
||||
extra_autotile_arrays = EXTRA_AUTOTILES[map.tileset_id]
|
||||
if extra_autotile_arrays
|
||||
large_autotile_count = extra_autotile_arrays[0].length
|
||||
single_autotile_count = extra_autotile_arrays[1].length
|
||||
single_autotile_start_id += large_autotile_count * TILES_PER_AUTOTILE
|
||||
true_tileset_start_id += large_autotile_count * TILES_PER_AUTOTILE
|
||||
true_tileset_start_id += single_autotile_count
|
||||
end
|
||||
if tile_id < true_tileset_start_id
|
||||
filename = ""
|
||||
if tile_id < TILESET_START_ID # Real autotiles
|
||||
filename = map.autotile_names[(tile_id / TILES_PER_AUTOTILE) - 1]
|
||||
elsif tile_id < single_autotile_start_id # Large extra autotiles
|
||||
filename = extra_autotile_arrays[0][(tile_id - TILESET_START_ID) / TILES_PER_AUTOTILE]
|
||||
else # Single extra autotiles
|
||||
filename = extra_autotile_arrays[1][tile_id - single_autotile_start_id]
|
||||
end
|
||||
tile.set_bitmap(filename, tile_id, true, @autotiles.animated?(filename),
|
||||
priority, @autotiles[filename])
|
||||
else
|
||||
filename = map.tileset_name
|
||||
tile.set_bitmap(filename, false, false, priority, @tilesets[filename])
|
||||
tile.set_bitmap(filename, tile_id, false, false, priority, @tilesets[filename])
|
||||
end
|
||||
tile.shows_reflection = terrain_tag_data&.shows_reflections
|
||||
tile.bridge = terrain_tag_data&.bridge
|
||||
@@ -345,7 +404,7 @@ class TilemapRenderer
|
||||
end
|
||||
|
||||
def refresh_tile_src_rect(tile, tile_id)
|
||||
if tile_id < TILESET_START_ID
|
||||
if tile.is_autotile
|
||||
@autotiles.set_src_rect(tile, tile_id)
|
||||
else
|
||||
@tilesets.set_src_rect(tile, tile_id)
|
||||
@@ -360,8 +419,8 @@ class TilemapRenderer
|
||||
|
||||
# x and y are the positions of tile within @tiles, not a map x/y
|
||||
def refresh_tile_coordinates(tile, x, y)
|
||||
tile.x = x * DISPLAY_TILE_WIDTH - @pixel_offset_x
|
||||
tile.y = y * DISPLAY_TILE_HEIGHT - @pixel_offset_y
|
||||
tile.x = (x * DISPLAY_TILE_WIDTH) - @pixel_offset_x
|
||||
tile.y = (y * DISPLAY_TILE_HEIGHT) - @pixel_offset_y
|
||||
end
|
||||
|
||||
def refresh_tile_z(tile, map, y, layer, tile_id)
|
||||
@@ -382,7 +441,7 @@ class TilemapRenderer
|
||||
tile.need_refresh = false
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def check_if_screen_moved
|
||||
ret = false
|
||||
@@ -391,20 +450,21 @@ class TilemapRenderer
|
||||
if MapFactoryHelper.hasConnections?(@current_map_id)
|
||||
offsets = $MapFactory.getRelativePos(@current_map_id, 0, 0, $game_map.map_id, 0, 0)
|
||||
if offsets
|
||||
@tile_offset_x += offsets[0]
|
||||
@tile_offset_y += offsets[1]
|
||||
@tile_offset_x -= offsets[0]
|
||||
@tile_offset_y -= offsets[1]
|
||||
else
|
||||
ret = true # Need a full refresh
|
||||
end
|
||||
else
|
||||
ret = true
|
||||
end
|
||||
@current_map_id = $game_map.map_id
|
||||
ret = true
|
||||
end
|
||||
# Check for tile movement
|
||||
current_map_display_x = ($game_map.display_x.to_f / Game_Map::X_SUBPIXELS).round
|
||||
current_map_display_y = ($game_map.display_y.to_f / Game_Map::Y_SUBPIXELS).round
|
||||
new_tile_offset_x = current_map_display_x / DISPLAY_TILE_WIDTH
|
||||
new_tile_offset_y = current_map_display_y / DISPLAY_TILE_HEIGHT
|
||||
new_tile_offset_x = (current_map_display_x / SOURCE_TILE_WIDTH) * ZOOM_X
|
||||
new_tile_offset_y = (current_map_display_y / SOURCE_TILE_HEIGHT) * ZOOM_Y
|
||||
if new_tile_offset_x != @tile_offset_x
|
||||
if new_tile_offset_x > @tile_offset_x
|
||||
# Take tile stacks off the right and insert them at the beginning (left)
|
||||
@@ -453,8 +513,8 @@ class TilemapRenderer
|
||||
@tile_offset_y = new_tile_offset_y
|
||||
end
|
||||
# Check for pixel movement
|
||||
new_pixel_offset_x = current_map_display_x % SOURCE_TILE_WIDTH
|
||||
new_pixel_offset_y = current_map_display_y % SOURCE_TILE_HEIGHT
|
||||
new_pixel_offset_x = (current_map_display_x % SOURCE_TILE_WIDTH) * ZOOM_X
|
||||
new_pixel_offset_y = (current_map_display_y % SOURCE_TILE_HEIGHT) * ZOOM_Y
|
||||
if new_pixel_offset_x != @pixel_offset_x
|
||||
@screen_moved = true
|
||||
@pixel_offset_x = new_pixel_offset_x
|
||||
@@ -467,7 +527,7 @@ class TilemapRenderer
|
||||
return ret
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def update
|
||||
# Update tone
|
||||
@@ -483,7 +543,7 @@ class TilemapRenderer
|
||||
if @old_color != @color
|
||||
@tiles.each do |col|
|
||||
col.each do |coord|
|
||||
coord.each { |tile| tile.color = @tone }
|
||||
coord.each { |tile| tile.color = @color }
|
||||
end
|
||||
end
|
||||
@old_color = @color.clone
|
||||
@@ -500,6 +560,10 @@ class TilemapRenderer
|
||||
# Check whether the screen has moved since the last update
|
||||
@screen_moved = false
|
||||
@screen_moved_vertically = false
|
||||
if $PokemonGlobal.bridge != @bridge
|
||||
@bridge = $PokemonGlobal.bridge
|
||||
@screen_moved_vertically = true # To update bridge tiles' z values
|
||||
end
|
||||
do_full_refresh = true if check_if_screen_moved
|
||||
# Update all tile sprites
|
||||
visited = []
|
||||
@@ -510,7 +574,9 @@ class TilemapRenderer
|
||||
$MapFactory.maps.each do |map|
|
||||
# Calculate x/y ranges of tile sprites that represent them
|
||||
map_display_x = (map.display_x.to_f / Game_Map::X_SUBPIXELS).round
|
||||
map_display_x = ((map_display_x + (Graphics.width / 2)) * ZOOM_X) - (Graphics.width / 2) if ZOOM_X != 1
|
||||
map_display_y = (map.display_y.to_f / Game_Map::Y_SUBPIXELS).round
|
||||
map_display_y = ((map_display_y + (Graphics.height / 2)) * ZOOM_Y) - (Graphics.height / 2) if ZOOM_Y != 1
|
||||
map_display_x_tile = map_display_x / DISPLAY_TILE_WIDTH
|
||||
map_display_y_tile = map_display_y / DISPLAY_TILE_HEIGHT
|
||||
start_x = [-map_display_x_tile, 0].max
|
||||
@@ -521,13 +587,13 @@ class TilemapRenderer
|
||||
end_y = [end_y, map.height - map_display_y_tile - 1].min
|
||||
next if start_x > end_x || start_y > end_y || end_x < 0 || end_y < 0
|
||||
# Update all tile sprites representing this map
|
||||
for i in start_x..end_x
|
||||
(start_x..end_x).each do |i|
|
||||
tile_x = i + map_display_x_tile
|
||||
for j in start_y..end_y
|
||||
(start_y..end_y).each do |j|
|
||||
tile_y = j + map_display_y_tile
|
||||
@tiles[i][j].each_with_index do |tile, layer|
|
||||
tile_id = map.data[tile_x, tile_y, layer]
|
||||
if do_full_refresh || tile.need_refresh
|
||||
if do_full_refresh || tile.need_refresh || tile.tile_id != tile_id
|
||||
refresh_tile(tile, i, j, map, layer, tile_id)
|
||||
else
|
||||
refresh_tile_frame(tile, tile_id) if tile.animated && @autotiles.changed
|
||||
@@ -547,7 +613,7 @@ class TilemapRenderer
|
||||
col.each_with_index do |coord, j|
|
||||
next if visited[i][j]
|
||||
coord.each do |tile|
|
||||
tile.set_bitmap("", false, false, 0, nil)
|
||||
tile.set_bitmap("", 0, false, false, 0, nil)
|
||||
tile.shows_reflection = false
|
||||
tile.bridge = false
|
||||
end
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#=======================================================================
|
||||
# This module is a little fix that works around PC hardware limitations.
|
||||
# Since Essentials isn't working with software rendering anymore, it now
|
||||
# has to deal with the limits of the GPU. For the most part this is no
|
||||
# big deal, but people do have some really big tilesets.
|
||||
#===============================================================================
|
||||
# This module is a little fix that works around PC hardware limitations. Since
|
||||
# Essentials isn't working with software rendering anymore, it now has to deal
|
||||
# with the limits of the GPU. For the most part this is no big deal, but people
|
||||
# do have some really big tilesets.
|
||||
#
|
||||
# The fix is simple enough: If your tileset is too big, a new
|
||||
# bitmap will be constructed with all the excess pixels sent to the
|
||||
# image's right side. This basically means that you now have a limit
|
||||
# far higher than you should ever actually need.
|
||||
# The fix is simple enough: If your tileset is too big, a new bitmap will be
|
||||
# constructed with all the excess pixels sent to the image's right side. This
|
||||
# basically means that you now have a limit far higher than you should ever
|
||||
# actually need.
|
||||
#
|
||||
# Hardware limit -> max tileset length:
|
||||
# 1024px -> 4096px
|
||||
@@ -15,15 +15,13 @@
|
||||
# 4096px -> 65536px (enough to load pretty much any tileset)
|
||||
# 8192px -> 262144px
|
||||
# 16384px -> 1048576px (what most people have at this point)
|
||||
|
||||
# ~Roza/Zoroark
|
||||
#=======================================================================
|
||||
#===============================================================================
|
||||
class TilemapRenderer
|
||||
module TilesetWrapper
|
||||
TILESET_WIDTH = SOURCE_TILE_WIDTH * TILESET_TILES_PER_ROW
|
||||
# Looks useless, but covers weird numbers given to mkxp.json or a funky driver
|
||||
MAX_TEX_SIZE = (Bitmap.max_size / 1024) * 1024
|
||||
MAX_TEX_SIZE_BOOSTED = MAX_TEX_SIZE**2 / TILESET_WIDTH
|
||||
MAX_TEX_SIZE_BOOSTED = (MAX_TEX_SIZE**2) / TILESET_WIDTH
|
||||
|
||||
module_function
|
||||
|
||||
@@ -37,6 +35,7 @@ class TilemapRenderer
|
||||
end
|
||||
bmp = Bitmap.new(TILESET_WIDTH * columns, MAX_TEX_SIZE)
|
||||
remainder = height % MAX_TEX_SIZE
|
||||
remainder = MAX_TEX_SIZE if remainder == 0
|
||||
columns.times do |col|
|
||||
srcrect = Rect.new(0, col * MAX_TEX_SIZE, width, (col + 1 == columns) ? remainder : MAX_TEX_SIZE)
|
||||
bmp.blt(col * TILESET_WIDTH, 0, originalbmp, srcrect)
|
||||
@@ -49,13 +48,15 @@ class TilemapRenderer
|
||||
def getWrappedRect(src_rect)
|
||||
ret = Rect.new(0, 0, 0, 0)
|
||||
col = (src_rect.y / MAX_TEX_SIZE.to_f).floor
|
||||
ret.x = col * TILESET_WIDTH + src_rect.x.clamp(0, TILESET_WIDTH)
|
||||
ret.x = (col * TILESET_WIDTH) + src_rect.x.clamp(0, TILESET_WIDTH)
|
||||
ret.y = src_rect.y % MAX_TEX_SIZE
|
||||
ret.width = src_rect.width.clamp(0, TILESET_WIDTH - src_rect.x)
|
||||
ret.height = src_rect.height.clamp(0, MAX_TEX_SIZE)
|
||||
return ret
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
private
|
||||
|
||||
def blitWrappedPixels(destX, destY, dest, src, srcrect)
|
||||
@@ -67,11 +68,11 @@ class TilemapRenderer
|
||||
merge = (srcrect.y % MAX_TEX_SIZE) > ((srcrect.y + srcrect.height) % MAX_TEX_SIZE)
|
||||
srcrect_mod = getWrappedRect(srcrect)
|
||||
if merge
|
||||
# FIXME won't work on heights longer than two columns, but nobody should need
|
||||
# FIXME: won't work on heights longer than two columns, but nobody should need
|
||||
# more than 32k pixels high at once anyway
|
||||
side = {
|
||||
:a => MAX_TEX_SIZE - srcrect_mod.y,
|
||||
:b => srcrect_mod.height - MAX_TEX_SIZE + srcrect_mod.y
|
||||
:a => MAX_TEX_SIZE - srcrect_mod.y,
|
||||
:b => srcrect_mod.height - MAX_TEX_SIZE + srcrect_mod.y
|
||||
}
|
||||
dest.blt(destX, destY, src, Rect.new(srcrect_mod.x, srcrect_mod.y, srcrect_mod.width, side[:a]))
|
||||
dest.blt(destX, destY + side[:a], src, Rect.new(srcrect_mod.x + TILESET_WIDTH, 0, srcrect_mod.width, side[:b]))
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class TilemapRenderer
|
||||
module AutotileExpander
|
||||
MAX_TEXTURE_SIZE = (Bitmap.max_size / 1024) * 1024
|
||||
MAX_TEXTURE_SIZE = (Bitmap.max_size / 1024) * 1024
|
||||
|
||||
module_function
|
||||
|
||||
@@ -32,20 +35,20 @@ class TilemapRenderer
|
||||
case id
|
||||
when 1 # Top left corner
|
||||
new_bitmap.blt(dest_x, dest_y, bitmap,
|
||||
Rect.new(frame * SOURCE_TILE_WIDTH * 3, SOURCE_TILE_HEIGHT * 4,
|
||||
SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT))
|
||||
Rect.new(frame * SOURCE_TILE_WIDTH * 3, SOURCE_TILE_HEIGHT * 4,
|
||||
SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT))
|
||||
when 2 # Top right corner
|
||||
new_bitmap.blt(dest_x, dest_y, bitmap,
|
||||
Rect.new(SOURCE_TILE_WIDTH + frame * SOURCE_TILE_WIDTH * 3, SOURCE_TILE_HEIGHT * 4,
|
||||
SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT))
|
||||
Rect.new(SOURCE_TILE_WIDTH + (frame * SOURCE_TILE_WIDTH * 3), SOURCE_TILE_HEIGHT * 4,
|
||||
SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT))
|
||||
when 4 # Bottom right corner
|
||||
new_bitmap.blt(dest_x, dest_y, bitmap,
|
||||
Rect.new(SOURCE_TILE_WIDTH + frame * SOURCE_TILE_WIDTH * 3, SOURCE_TILE_HEIGHT * 5,
|
||||
SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT))
|
||||
Rect.new(SOURCE_TILE_WIDTH + (frame * SOURCE_TILE_WIDTH * 3), SOURCE_TILE_HEIGHT * 5,
|
||||
SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT))
|
||||
when 8 # Bottom left corner
|
||||
new_bitmap.blt(dest_x, dest_y, bitmap,
|
||||
Rect.new(frame * SOURCE_TILE_WIDTH * 3, SOURCE_TILE_HEIGHT * 5,
|
||||
SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT))
|
||||
Rect.new(frame * SOURCE_TILE_WIDTH * 3, SOURCE_TILE_HEIGHT * 5,
|
||||
SOURCE_TILE_WIDTH, SOURCE_TILE_HEIGHT))
|
||||
end
|
||||
next
|
||||
end
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class TileDrawingHelper
|
||||
attr_accessor :tileset
|
||||
attr_accessor :autotiles
|
||||
|
||||
AUTOTILE_PATTERNS = [
|
||||
[ [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] ]
|
||||
[[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]]
|
||||
]
|
||||
|
||||
# converts neighbors returned from tableNeighbors to tile indexes
|
||||
@@ -37,35 +40,52 @@ class TileDrawingHelper
|
||||
36, 24, 36, 24, 21, 6, 21, 4, 36, 24, 36, 24, 20, 2, 20, 0
|
||||
]
|
||||
|
||||
def self.tableNeighbors(data,x,y)
|
||||
def self.tableNeighbors(data, x, y, layer = nil)
|
||||
return 0 if x < 0 || x >= data.xsize
|
||||
return 0 if y < 0 || y >= data.ysize
|
||||
t = data[x,y]
|
||||
if layer.nil?
|
||||
t = data[x, y]
|
||||
else
|
||||
t = data[x, y, layer]
|
||||
end
|
||||
xp1 = [x + 1, data.xsize - 1].min
|
||||
yp1 = [y + 1, data.ysize - 1].min
|
||||
xm1 = [x - 1, 0].max
|
||||
ym1 = [y - 1, 0].max
|
||||
i = 0
|
||||
i |= 0x01 if data[ x, ym1] == t # N
|
||||
i |= 0x02 if data[xp1, ym1] == t # NE
|
||||
i |= 0x04 if data[xp1, y] == t # E
|
||||
i |= 0x08 if data[xp1, yp1] == t # SE
|
||||
i |= 0x10 if data[ x, yp1] == t # S
|
||||
i |= 0x20 if data[xm1, yp1] == t # SW
|
||||
i |= 0x40 if data[xm1, y] == t # W
|
||||
i |= 0x80 if data[xm1, ym1] == t # NW
|
||||
if layer.nil?
|
||||
i |= 0x01 if data[ x, ym1] == t # N
|
||||
i |= 0x02 if data[xp1, ym1] == t # NE
|
||||
i |= 0x04 if data[xp1, y] == t # E
|
||||
i |= 0x08 if data[xp1, yp1] == t # SE
|
||||
i |= 0x10 if data[ x, yp1] == t # S
|
||||
i |= 0x20 if data[xm1, yp1] == t # SW
|
||||
i |= 0x40 if data[xm1, y] == t # W
|
||||
i |= 0x80 if data[xm1, ym1] == t # NW
|
||||
else
|
||||
i |= 0x01 if data[ x, ym1, layer] == t # N
|
||||
i |= 0x02 if data[xp1, ym1, layer] == t # NE
|
||||
i |= 0x04 if data[xp1, y, layer] == t # E
|
||||
i |= 0x08 if data[xp1, yp1, layer] == t # SE
|
||||
i |= 0x10 if data[ x, yp1, layer] == t # S
|
||||
i |= 0x20 if data[xm1, yp1, layer] == t # SW
|
||||
i |= 0x40 if data[xm1, y, layer] == t # W
|
||||
i |= 0x80 if data[xm1, ym1, layer] == t # NW
|
||||
end
|
||||
return i
|
||||
end
|
||||
|
||||
def self.fromTileset(tileset)
|
||||
bmtileset=pbGetTileset(tileset.tileset_name)
|
||||
bmautotiles=[]
|
||||
for i in 0...7
|
||||
bmtileset = pbGetTileset(tileset.tileset_name)
|
||||
bmautotiles = []
|
||||
7.times do |i|
|
||||
bmautotiles.push(pbGetAutotile(tileset.autotile_names[i]))
|
||||
end
|
||||
return self.new(bmtileset,bmautotiles)
|
||||
return self.new(bmtileset, bmautotiles)
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def initialize(tileset, autotiles)
|
||||
if tileset.mega?
|
||||
@tileset = TilemapRenderer::TilesetWrapper.wrapTileset(tileset)
|
||||
@@ -79,17 +99,17 @@ class TileDrawingHelper
|
||||
end
|
||||
|
||||
def dispose
|
||||
@tileset.dispose if @tileset
|
||||
@tileset&.dispose
|
||||
@tileset = nil
|
||||
for i in 0...@autotiles.length
|
||||
@autotiles[i].dispose
|
||||
@autotiles.each_with_index do |autotile, i|
|
||||
autotile.dispose
|
||||
@autotiles[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
def bltSmallAutotile(bitmap,x,y,cxTile,cyTile,id,frame)
|
||||
def bltSmallAutotile(bitmap, x, y, cxTile, cyTile, id, frame)
|
||||
return if id >= 384 || frame < 0 || !@autotiles
|
||||
autotile = @autotiles[id / 48 - 1]
|
||||
autotile = @autotiles[(id / 48) - 1]
|
||||
return if !autotile || autotile.disposed?
|
||||
cxTile = [cxTile / 2, 1].max
|
||||
cyTile = [cyTile / 2, 1].max
|
||||
@@ -102,23 +122,23 @@ class TileDrawingHelper
|
||||
id %= 48
|
||||
tiles = AUTOTILE_PATTERNS[id >> 3][id & 7]
|
||||
src = Rect.new(0, 0, 0, 0)
|
||||
for i in 0...4
|
||||
4.times do |i|
|
||||
tile_position = tiles[i] - 1
|
||||
src.set(tile_position % 6 * 16 + anim, tile_position / 6 * 16, 16, 16)
|
||||
bitmap.stretch_blt(Rect.new(i % 2 * cxTile + x, i / 2 * cyTile + y, cxTile, cyTile),
|
||||
autotile, src)
|
||||
src.set(((tile_position % 6) * 16) + anim, (tile_position / 6) * 16, 16, 16)
|
||||
bitmap.stretch_blt(Rect.new((i % 2 * cxTile) + x, (i / 2 * cyTile) + y, cxTile, cyTile),
|
||||
autotile, src)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def bltSmallRegularTile(bitmap,x,y,cxTile,cyTile,id)
|
||||
def bltSmallRegularTile(bitmap, x, y, cxTile, cyTile, id)
|
||||
return if id < 384 || !@tileset || @tileset.disposed?
|
||||
rect = Rect.new((id - 384) % 8 * 32, (id - 384) / 8 * 32, 32, 32)
|
||||
rect = Rect.new(((id - 384) % 8) * 32, ((id - 384) / 8) * 32, 32, 32)
|
||||
rect = TilemapRenderer::TilesetWrapper.getWrappedRect(rect) if @shouldWrap
|
||||
bitmap.stretch_blt(Rect.new(x, y, cxTile, cyTile), @tileset, rect)
|
||||
end
|
||||
|
||||
def bltSmallTile(bitmap,x,y,cxTile,cyTile,id,frame=0)
|
||||
def bltSmallTile(bitmap, x, y, cxTile, cyTile, id, frame = 0)
|
||||
if id >= 384
|
||||
bltSmallRegularTile(bitmap, x, y, cxTile, cyTile, id)
|
||||
elsif id > 0
|
||||
@@ -126,15 +146,15 @@ class TileDrawingHelper
|
||||
end
|
||||
end
|
||||
|
||||
def bltAutotile(bitmap,x,y,id,frame)
|
||||
def bltAutotile(bitmap, x, y, id, frame)
|
||||
bltSmallAutotile(bitmap, x, y, 32, 32, id, frame)
|
||||
end
|
||||
|
||||
def bltRegularTile(bitmap,x,y,id)
|
||||
def bltRegularTile(bitmap, x, y, id)
|
||||
bltSmallRegularTile(bitmap, x, y, 32, 32, id)
|
||||
end
|
||||
|
||||
def bltTile(bitmap,x,y,id,frame=0)
|
||||
def bltTile(bitmap, x, y, id, frame = 0)
|
||||
if id >= 384
|
||||
bltRegularTile(bitmap, x, y, id)
|
||||
elsif id > 0
|
||||
@@ -147,82 +167,80 @@ end
|
||||
#
|
||||
#===============================================================================
|
||||
def createMinimap(mapid)
|
||||
map=load_data(sprintf("Data/Map%03d.rxdata",mapid)) rescue nil
|
||||
return BitmapWrapper.new(32,32) if !map
|
||||
bitmap=BitmapWrapper.new(map.width*4,map.height*4)
|
||||
black=Color.new(0,0,0)
|
||||
tilesets=$data_tilesets
|
||||
tileset=tilesets[map.tileset_id]
|
||||
map = load_data(sprintf("Data/Map%03d.rxdata", mapid)) rescue nil
|
||||
return Bitmap.new(32, 32) if !map
|
||||
bitmap = Bitmap.new(map.width * 4, map.height * 4)
|
||||
black = Color.black
|
||||
tilesets = $data_tilesets
|
||||
tileset = tilesets[map.tileset_id]
|
||||
return bitmap if !tileset
|
||||
helper=TileDrawingHelper.fromTileset(tileset)
|
||||
for y in 0...map.height
|
||||
for x in 0...map.width
|
||||
for z in 0..2
|
||||
id=map.data[x,y,z]
|
||||
id=0 if !id
|
||||
helper.bltSmallTile(bitmap,x*4,y*4,4,4,id)
|
||||
helper = TileDrawingHelper.fromTileset(tileset)
|
||||
map.height.times do |y|
|
||||
map.width.times do |x|
|
||||
3.times do |z|
|
||||
id = map.data[x, y, z]
|
||||
id = 0 if !id
|
||||
helper.bltSmallTile(bitmap, x * 4, y * 4, 4, 4, id)
|
||||
end
|
||||
end
|
||||
end
|
||||
bitmap.fill_rect(0,0,bitmap.width,1,black)
|
||||
bitmap.fill_rect(0,bitmap.height-1,bitmap.width,1,black)
|
||||
bitmap.fill_rect(0,0,1,bitmap.height,black)
|
||||
bitmap.fill_rect(bitmap.width-1,0,1,bitmap.height,black)
|
||||
bitmap.fill_rect(0, 0, bitmap.width, 1, black)
|
||||
bitmap.fill_rect(0, bitmap.height - 1, bitmap.width, 1, black)
|
||||
bitmap.fill_rect(0, 0, 1, bitmap.height, black)
|
||||
bitmap.fill_rect(bitmap.width - 1, 0, 1, bitmap.height, black)
|
||||
return bitmap
|
||||
end
|
||||
|
||||
def bltMinimapAutotile(dstBitmap,x,y,srcBitmap,id)
|
||||
return if id>=48 || !srcBitmap || srcBitmap.disposed?
|
||||
anim=0
|
||||
cxTile=3
|
||||
cyTile=3
|
||||
tiles = TileDrawingHelper::AUTOTILE_PATTERNS[id>>3][id&7]
|
||||
src=Rect.new(0,0,0,0)
|
||||
for i in 0...4
|
||||
def bltMinimapAutotile(dstBitmap, x, y, srcBitmap, id)
|
||||
return if id >= 48 || !srcBitmap || srcBitmap.disposed?
|
||||
anim = 0
|
||||
cxTile = 3
|
||||
cyTile = 3
|
||||
tiles = TileDrawingHelper::AUTOTILE_PATTERNS[id >> 3][id & 7]
|
||||
src = Rect.new(0, 0, 0, 0)
|
||||
4.times do |i|
|
||||
tile_position = tiles[i] - 1
|
||||
src.set(
|
||||
tile_position % 6 * cxTile + anim,
|
||||
tile_position / 6 * cyTile, cxTile, cyTile)
|
||||
dstBitmap.blt(i%2*cxTile+x,i/2*cyTile+y, srcBitmap, src)
|
||||
src.set((tile_position % 6 * cxTile) + anim,
|
||||
tile_position / 6 * cyTile, cxTile, cyTile)
|
||||
dstBitmap.blt((i % 2 * cxTile) + x, (i / 2 * cyTile) + y, srcBitmap, src)
|
||||
end
|
||||
end
|
||||
|
||||
def passable?(passages,tile_id)
|
||||
return false if tile_id == nil
|
||||
def passable?(passages, tile_id)
|
||||
return false if tile_id.nil?
|
||||
passage = passages[tile_id]
|
||||
return (passage && passage<15)
|
||||
return (passage && passage < 15)
|
||||
end
|
||||
|
||||
# Unused
|
||||
def getPassabilityMinimap(mapid)
|
||||
map = load_data(sprintf("Data/Map%03d.rxdata",mapid))
|
||||
map = load_data(sprintf("Data/Map%03d.rxdata", mapid))
|
||||
tileset = $data_tilesets[map.tileset_id]
|
||||
minimap = AnimatedBitmap.new("Graphics/Pictures/minimap_tiles")
|
||||
ret = Bitmap.new(map.width*6,map.height*6)
|
||||
passtable = Table.new(map.width,map.height)
|
||||
minimap = AnimatedBitmap.new("Graphics/UI/minimap_tiles")
|
||||
ret = Bitmap.new(map.width * 6, map.height * 6)
|
||||
passtable = Table.new(map.width, map.height)
|
||||
passages = tileset.passages
|
||||
for i in 0...map.width
|
||||
for j in 0...map.height
|
||||
pass=true
|
||||
for z in [2,1,0]
|
||||
if !passable?(passages,map.data[i,j,z])
|
||||
pass=false
|
||||
map.width.times do |i|
|
||||
map.height.times do |j|
|
||||
pass = true
|
||||
[2, 1, 0].each do |z|
|
||||
if !passable?(passages, map.data[i, j, z])
|
||||
pass = false
|
||||
break
|
||||
end
|
||||
end
|
||||
passtable[i,j]=pass ? 1 : 0
|
||||
passtable[i, j] = pass ? 1 : 0
|
||||
end
|
||||
end
|
||||
neighbors=TileDrawingHelper::NEIGHBORS_TO_AUTOTILE_INDEX
|
||||
for i in 0...map.width
|
||||
for j in 0...map.height
|
||||
if passtable[i,j]==0
|
||||
nb=TileDrawingHelper.tableNeighbors(passtable,i,j)
|
||||
tile=neighbors[nb]
|
||||
bltMinimapAutotile(ret,i*6,j*6,minimap.bitmap,tile)
|
||||
end
|
||||
neighbors = TileDrawingHelper::NEIGHBORS_TO_AUTOTILE_INDEX
|
||||
map.width.times do |i|
|
||||
map.height.times do |j|
|
||||
next if passtable[i, j] != 0
|
||||
nb = TileDrawingHelper.tableNeighbors(passtable, i, j)
|
||||
tile = neighbors[nb]
|
||||
bltMinimapAutotile(ret, i * 6, j * 6, minimap.bitmap, tile)
|
||||
end
|
||||
end
|
||||
minimap.disposes
|
||||
minimap.dispose
|
||||
return ret
|
||||
end
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user