设为首页收藏本站同能贴吧 切换语言 繁体中文
开启辅助访问 切换到窄版
扫描二维码关注官方公众号
返回列表
+ 发新帖
查看: 86|回复: 0

[转载发布] Extended Map Sprite Tiles & Autotiles (EMSTA)

[复制链接]
累计送礼:
0 个
累计收礼:
1 个
  • TA的每日心情
    开心
    前天 04:10
  • 签到天数: 209 天

    连续签到: 2 天

    [LV.7]常住居民III

    4471

    主题

    864

    回帖

    2万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    7
    卡币
    22949
    OK点
    16
    推广点
    0
    同能卷
    50
    积分
    28314

    灌水之王

    发表于 3 天前 | 显示全部楼层 |阅读模式
    Extended Map Sprite Tiles & Autotiles (EMSTA) allows inserting tile or autotile sprites on the map via script without layer limitations. It's basically like when you use an event as a tile, but in this case there's no event, so it causes much less lag.

    It doesn't affect the passability, but apart from that it is like a completely normal tile. In addition, in terms of passability, it can be easily solved by assigning an empty but not passable tile.

    So far I know it doesn't seem like a big deal, but what advantages does this have then?

    • More than 3 tiles per map coordinate without having to use an empty event (i.e. less lag)
    • More than 4 tiles per map coordinate; now it's unlimited.
    • More tile priorities; now unlimited, and it also accepts negative values.
    • More than 7 autotiles per tileset/map. [Check a tutorial about thathere]
    • The Cliff Bugfix can be used with EMSTA for more complex cliff interactions.
    • Battle animations applied on tile and autotile sprites, and other similar stuff.
    • Engine shortcuts. Assign a parameter to EMSTA sprites and apply changes on them by group.
    Authors: Wecoc & Eron
    First Release: February 2018
    Last Version: June 2020

    Terms of use
    - Giving credits (Wecoc & Eron) for using this script is optional, but appreciated.
    - You can repost this code.
    - You can edit this code freely, and distribute the edits as well.
    - This code can be used on commercial games.

    Code

                    Ruby:       
    #==============================================================================# ** [XP] Extended Map Sprite Tiles & Autotiles (EMSTA)#------------------------------------------------------------------------------# Authors: Wecoc & Eron (credits are optional)# Version: 1.1#==============================================================================# This script allows inserting tile and autotile sprites on the map.# They will look like normal tiles, but won't affect the passability.# Its advantage is you can define as many as you want per coordinate, and you# can get them from another tileset, so you can break the limit of autotiles# per map. Even with that it's a bit complicated to use so I recommend limiting# it to those cases where it's really necessary.#------------------------------------------------------------------------------# Note: When placing EMSTA sprites an ID is assigned, like with events. You can# use it as reference to directly control that sprite, for example removing it.#------------------------------------------------------------------------------# 1) Define a tile sprite on the map# $game_map.set_sprite_tile(x, y, tile_id)# $game_map.set_sprite_tile(x, y, tileset_id, tile_id)# $game_map.set_sprite_tile(x, y, tileset_id, tile_id, z)#     tile_id - Tile ID (position inside the tileset)#     tileset_id - Tileset ID on the Database (current tileset when non-defined)#     z - Tile priority (when non-defined uses default priority on the tileset)# Example: $game_map.set_sprite_tile(4, 10, 3, 384)# Note: You can also define a tag for this sprite# Example: $game_map.set_sprite_tile(4, 10, 3, 384, :tree)#------------------------------------------------------------------------------# 1) Define an autotile sprite on the map# $game_map.set_sprite_autotile(x, y, autotile_id, tile_id)# $game_map.set_sprite_autotile(x, y, tileset_id, autotile_id, tile_id)# $game_map.set_sprite_autotile(x, y, tileset_id, autotile_id, tile_id, z)#     autotile_id - Autotile index on the tileset, from 1 to 7#     tile_id - Subtile ID, from 0 to 47#     tileset_id - Tileset ID on the Database (current tileset when non-defined)#     z - Tile priority (when non-defined uses default priority on the tileset)# Example: $game_map.set_sprite_autotile(4, 10, 3, 1, 24)# Note: You can also define a tag for this sprite# Example: $game_map.set_sprite_autotile(4, 10, 3, 1, 24, :water)#------------------------------------------------------------------------------# 3) Change an autotile on the map for an EMSTA autotile sprite# (it will use the tile_id and Z of the reference autotile)# $game_map.change_autotile_sprite(x, y, layer, autotile_id)# $game_map.change_autotile_sprite(x, y, layer, tileset_id, autotile_id)#     layer - Map layer, from 0 to 2#     You can also define two extra arguments after the autotile_id:#       clear_tile_id - ID of the tile used to erase the reference autotile#       clear - Boolean defining if the reference autotile should be erased#       By default their values are 0 and true respectively.#       tag - Symbol used to categorize tiles, by default nil#------------------------------------------------------------------------------# 4) Change an autotile for an EMSTA sprite along the whole layer# $game_map.change_autotile_layer(autotile, layer, autotile_id)# $game_map.change_autotile_layer(autotile, layer, tileset_id, autotile_id)#     autotile - ID of the reference autotile, from 1 to 7#     It works exactly like in the previous case but along an entire layer#==============================================================================# FAQ## - How do I get an EMSTA sprite previously inserted?## Script call for a Tile:# $game_map.sprite_tiles[ID]# Script call for an Autotile:# $game_map.sprite_autotiles[ID]## - How do I get it if I don't know its ID but I know coordinate and tile ID?# This example was made with a Tile. Change X, Y and TILE_ID## tiles = $game_map.sprite_tiles.values# tile = tiles.select do |sprite|#   sprite[0] == X#   sprite[1] == Y#   sprite[3] == TILE_ID# end[0]## If tile is nil that means there's no sprite with those parameters## - Once I get the tile how do I get its ID?# id = $game_map.sprite_tiles.key(tile)## - How do I get all the sprites that share a tag?# tiles = $game_map.sprite_tiles.values# tiles = tiles.select do |sprite|#   sprite[-1] == TAG# end## - What incompatibilities does this script have?# It should be compatible with practically everything#==============================================================================#==============================================================================# ** EronAutotileCache#==============================================================================module EronAutotileCache  @@hash = {}  module_function  def hash    @@hash  endend#==============================================================================# ** Hash#==============================================================================class Hash  def key(value)    for k in self.keys      return k if self[k] == value    end    return nil  endend#==============================================================================# ** Game_Map#==============================================================================class Game_Map  #--------------------------------------------------------------------------  attr_accessor :sprite_tiles, :sprite_autotiles  #--------------------------------------------------------------------------  # * Setup  #--------------------------------------------------------------------------  alias sprite_tile_setup setup unless $@  def setup(*args)    sprite_tile_setup(*args)    @sprite_tiles = {}    @sprite_autotiles = {}  end  #--------------------------------------------------------------------------  # * [Internal] Get the next non-used index for a Tile or Autotile sprite  #--------------------------------------------------------------------------  def get_next_sprite_id(hash)    return 1 if hash.size == 0    for i in 1..(hash.size + 1)      return i if hash.nil?    end  end  #--------------------------------------------------------------------------  # * Show a Tile sprite on the map  #--------------------------------------------------------------------------  def set_sprite_tile(x, y, *args)    tag = args.pop if args[-1].is_a?(Symbol) || args[-1].nil?    case args.size    when 1 # tile_id      tileset_id = @map.tileset_id      tile_id = args[0]      z = nil    else # tileset_id, tile_id[, z]      tileset_id = args[0]      tile_id = args[1]      z = args[2]    end    id = get_next_sprite_id(@sprite_tiles)    if z == nil      tileset = $data_tilesets[tileset_id]      z = tileset.priorities[tile_id]    end    return if @sprite_tiles.values.include?([x, y, tileset_id, tile_id, z, tag])    @sprite_tiles[id] = [x, y, tileset_id, tile_id, z, tag]    return true  end  #--------------------------------------------------------------------------  # * Show an Auotitle sprite on the map  #--------------------------------------------------------------------------  def set_sprite_autotile(x, y, *args)    tag = args.pop if args[-1].is_a?(Symbol) || args[-1].nil?    case args.size    when 2 # autotile_id, tile_id      tileset_id = @map.tileset_id      autotile_id = args[0]      tile_id = args[1]    else # tileset_id, autotile_id, tile_id[, z]      tileset_id = args[0]      autotile_id = args[1]      tile_id = args[2]      z = args[3]    end    id = get_next_sprite_id(@sprite_autotiles)    if z == nil      tileset = $data_tilesets[tileset_id]      z = tileset.priorities[autotile_id * 48 + tile_id]    end    ary = @sprite_autotiles.values    return if ary.include?([x, y, tileset_id, autotile_id, tile_id, z, tag])    @sprite_autotiles[id] = [x, y, tileset_id, autotile_id, tile_id, z, tag]    return true  end  #--------------------------------------------------------------------------  # * Change an autotile to an EMSTA sprite on a specific coordinate  #--------------------------------------------------------------------------  def change_autotile_sprite(x, y, layer, *args)    tag = args.pop if args[-1].is_a?(Symbol) || args[-1].nil?    current_autotile = self.data[x, y, layer]    return if current_autotile == 0 or current_autotile >= 384    clear = true    clear_tile = 0    if args[-1].is_a?(TrueClass) or args[-1].is_a?(FalseClass)      clear = args.pop      clear_tile = args.pop    end    case args.size    when 1 # autotile_id      tileset_id = @map.tileset_id      autotile_id = args[0]    else # tileset_id, autotile_id      tileset_id = args[0]      autotile_id = args[1]    end    tile_id = current_autotile % 48    z = $data_tilesets[tileset_id].priorities[current_autotile]    set_sprite_autotile(x, y, tileset_id, autotile_id, tile_id, z, tag)    self.data[x, y, layer] = clear_tile if clear  end  #--------------------------------------------------------------------------  # * Change an autotile to an EMSTA sprite along a map layer  #--------------------------------------------------------------------------  def change_autotile_layer(autotile, layer, *args)    for iy in 0...self.height      for ix in 0...self.width        current = (self.data[ix, iy, layer].to_f / 48).floor        if current == autotile          change_autotile_sprite(ix, iy, layer, *args)        end      end    end  endend#==============================================================================# ** Sprite_Tile#==============================================================================class Sprite_Tile < RPG::Sprite  #--------------------------------------------------------------------------  attr_accessor :real_x, :real_y, :real_z  #--------------------------------------------------------------------------  # * Update  #--------------------------------------------------------------------------  def update    super    self.x = (@real_x - $game_map.display_x + 3) / 4 + 16    self.y = (@real_y - $game_map.display_y + 3) / 4 + 32    self.z = @real_z + (@real_y - $game_map.display_y + 3) / 4 + 32  endend#==============================================================================# ** Sprite_Autotile#==============================================================================class Sprite_Autotile < Sprite_Tile  #--------------------------------------------------------------------------  attr_accessor :complete_bitmap, :frame, :frames  #--------------------------------------------------------------------------  # * Update  #--------------------------------------------------------------------------  def update    super    if @frames > 1 && @current_frame != @frame      @current_frame = @frame      refresh_bitmap    end  end  #--------------------------------------------------------------------------  # * Refresh Bitmap  #--------------------------------------------------------------------------  def refresh_bitmap    self.bitmap = Bitmap.new(32, 32)    self.bitmap.blt(0, 0, @complete_bitmap, Rect.new(@frame * 32, 0, 32, 32))  endend#==============================================================================# ** Spriteset_Map#==============================================================================class Spriteset_Map  #--------------------------------------------------------------------------  # * Initialize  #--------------------------------------------------------------------------  alias sprite_tile_ini initialize unless $@  def initialize    @sprite_tiles = []    @sprite_autotiles = []    @sprite_tile_copy = {}    @sprite_autotile_copy = {}    sprite_tile_ini  end  #--------------------------------------------------------------------------  # * Dispose  #--------------------------------------------------------------------------  alias sprite_tile_dis dispose unless $@  def dispose    sprite_tile_dis    @sprite_tiles.each {|sprite| sprite.dispose}    @sprite_autotiles.each {|sprite| sprite.dispose}  end  #--------------------------------------------------------------------------  # * Refresh Sprite Tiles  #--------------------------------------------------------------------------  def refresh_sprite_tiles    for sprite in @sprite_tiles      sprite.dispose    end    @sprite_tiles.clear    for i in $game_map.sprite_tiles.keys      tile = $game_map.sprite_tiles      sprite = Sprite_Tile.new(@viewport1)      sprite.real_x = tile[0] * 128      sprite.real_y = tile[1] * 128      sprite.ox = 16      sprite.oy = 32      tileset = $data_tilesets[tile[2]]      sprite.bitmap = RPG::Cache.tile(tileset.tileset_name, tile[3], 0)      sprite.real_z = tile[4] * 32      @sprite_tiles.push(sprite)    end  end  #--------------------------------------------------------------------------  DECONSTRUCT_AUTOTILE_PARTS =    [27, 28,  5, 28, 27,  6,  5,  6, 27, 28,  5, 28, 27,  6,  5,  6,     33, 34, 33, 34, 33, 34, 33, 34, 33, 12, 33, 12, 33, 12, 33, 12,     27, 28,  5, 28, 27,  6,  5,  6, 27, 28,  5, 28, 27,  6,  5,  6,     11, 34, 11, 34, 11, 34, 11, 34, 11, 12, 11, 12, 11, 12, 11, 12,     25, 26, 25,  6, 25, 26, 25,  6, 15, 16, 15, 16, 15, 16, 15, 16,     31, 32, 31, 32, 31, 12, 31, 12, 21, 22, 21, 12, 11, 22, 11, 12,     29, 30, 29, 30,  5, 30,  5, 30, 39, 40,  5, 40, 39,  6,  5,  6,     35, 36, 11, 36, 35, 36, 11, 36, 45, 46, 45, 46, 45, 46, 45, 46,     25, 30, 15, 16, 13, 14, 13, 14, 17, 18, 17, 18, 41, 42,  5, 42,     31, 36, 45, 46, 19, 20, 19, 12, 23, 24, 11, 24, 47, 48, 47, 48,     37, 38, 37,  6, 13, 18, 13, 14, 37, 42, 17, 18, 13, 18,  1,  2,     43, 44, 43, 44, 19, 24, 43, 44, 43, 48, 47, 48, 43, 48,  7,  8]  #--------------------------------------------------------------------------  # * Refresh Sprite Autotiles  #--------------------------------------------------------------------------  def refresh_sprite_autotiles    for sprite in @sprite_autotiles      sprite.dispose    end    @sprite_autotiles.clear    for i in $game_map.sprite_autotiles.keys      autotile = $game_map.sprite_autotiles      sprite = Sprite_Autotile.new(@viewport1)      sprite.real_x = autotile[0] * 128      sprite.real_y = autotile[1] * 128      sprite.ox = 16      sprite.oy = 32      sprite.frame = 0      tileset = $data_tilesets[autotile[2]]      autotile_name = tileset.autotile_names[autotile[3] - 1]      bitmap = RPG::Cache.autotile(autotile_name)      case bitmap.height      when 32        sprite.complete_bitmap = bitmap        sprite.frames = bitmap.width / 32      when 128        frames = [bitmap.width / 96, 1].max        if EronAutotileCache.hash.include?(autotile_name)          result = EronAutotileCache.hash[autotile_name]        else          result = Bitmap.new(256, 192 * frames)          deconstruct_autotile(bitmap, result, frames)          EronAutotileCache.hash[autotile_name] = result        end        bitmap = Bitmap.new(32 * frames, 32)        for f in 0...frames          ix = (autotile[4] % 8) * 32          iy = ((autotile[4].to_f / 8).floor) * 32          bitmap.blt(f * 32, 0, result, Rect.new(ix, iy + 192 * f, 32, 32))        end        sprite.complete_bitmap = bitmap        sprite.frames = frames      end      sprite.bitmap = sprite.complete_bitmap if sprite.frames == 1      sprite.real_z = autotile[5] * 32      @sprite_autotiles.push(sprite)    end  end  #--------------------------------------------------------------------------  # * [Internal] Deconstruct Autotile  #--------------------------------------------------------------------------  def deconstruct_autotile(image, result, frames)    t = DECONSTRUCT_AUTOTILE_PARTS    for f in 0...frames      fx = 96 * f      fy = 192 * f      bitmaps = [nil]      for iy in 0...8        for ix in 0...6          bitmap = Bitmap.new(16, 16)          bitmap.blt(0, 0, image, Rect.new(fx + 16 * ix, 16 * iy, 16, 16))          bitmaps << bitmap        end      end      for iy in 0...12        for ix in 0...16          index = ix + iy * 16          bitmap = bitmaps[t[index]]          result.blt(ix * 16, fy + iy * 16, bitmap, bitmap.rect)        end      end    end    return result  end  #--------------------------------------------------------------------------  # * Update  #--------------------------------------------------------------------------  alias sprite_tile_upd update unless $@  def update    if @sprite_tile_copy != $game_map.sprite_tiles      @sprite_tile_copy = $game_map.sprite_tiles.clone      refresh_sprite_tiles    end    if @sprite_autotile_copy != $game_map.sprite_autotiles      @sprite_autotile_copy = $game_map.sprite_autotiles.clone      refresh_sprite_autotiles    end    @autotile_frame = 0 if @autotile_frame.nil?    @autotile_frame += 1    if @autotile_frame % 16 == 0      @sprite_autotiles.each do |sprite|        sprite.frame = (@autotile_frame / 16) % sprite.frames      end    end    for sprite in @sprite_tiles + @sprite_autotiles      sprite.update    end    sprite_tile_upd  endend




    本贴来自国际rpgmaker官方论坛作者:Wecoc处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/extended-map-sprite-tiles-autotiles-emsta.138583/
    天天去同能,天天有童年!
    回复 送礼论坛版权

    使用道具 举报

    文明发言,和谐互动
    文明发言,和谐互动
    高级模式
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    简体中文
    繁體中文
    English(英语)
    日本語(日语)
    Deutsch(德语)
    Русский язык(俄语)
    بالعربية(阿拉伯语)
    Türkçe(土耳其语)
    Português(葡萄牙语)
    ภาษาไทย(泰国语)
    한어(朝鲜语/韩语)
    Français(法语)
    关闭

    幸运抽奖

    社区每日抽奖来袭,快来试试你是欧皇还是非酋~

    立即查看

    聊天机器人
    Loading...

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2026-7-14 17:57 , Processed in 0.145528 second(s), 52 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表