设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 545|回复: 1
打印 上一主题 下一主题

[原创发布] XP事件行走图描边脚本260402

[复制链接]

Lv2.观梦者

梦石
0
星屑
509
在线时间
67 小时
注册时间
2025-5-4
帖子
3
跳转到指定楼层
1
发表于 2026-3-22 06:47:09 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 HFDange 于 2026-4-2 21:09 编辑

效果图:


2026.4.2更新:根据回帖建议优化了脚本,并增加了渐变描边功能。

RUBY 代码复制
  1. #==============================================================================
  2. # ■ XP行走图描边脚本 - Character Stroker 2026.3.21 By HFDange
  3. #------------------------------------------------------------------------------
  4. #   使用方法:在需要描边的事件名中添加“.stX”后缀。
  5. #             X为标记描边颜色的数字,如“.st0”为灰色描边、“.st1”为红色描边。
  6. #             若要更改描边颜色,在CSC_COLORSET中添加或修改。
  7. #
  8. #   2026.4.2更新:描边渐变
  9. #
  10. #   使用方法:事件名后缀“.stXgX”
  11. #             如“.st1g0”为红->灰->红渐变
  12. #
  13. #==============================================================================
  14.  
  15. #==============================================================================
  16. # ● 设置部分
  17. #==============================================================================
  18.  
  19. module CharSt_Config
  20.   # 是否八方向描边(默认FALSE)
  21.   CSC_IF_8_DIRECTIONS = FALSE
  22.   # 描边颜色表(RGBA),默认颜色为:灰 红 绿 蓝 黄 紫 青 白 黑
  23.   CSC_COLORSET = [
  24.     [64, 56, 56, 255], [255, 18, 18, 255], [18, 255, 18, 255],
  25.     [18, 18, 255, 255], [255, 255, 18, 255], [255, 18, 255, 255],
  26.     [18, 255, 255, 255], [255, 255, 255, 255], [0, 0, 0, 255]
  27.   ]
  28.   # 渐变周期长度 - 以帧为单位(默认20)
  29.   CSC_GRADIENT_CYCLE = 20
  30. end
  31.  
  32. #==============================================================================
  33. # ● 描边脚本
  34. #==============================================================================
  35.  
  36. module CharactorStroker
  37.   include CharSt_Config
  38.  
  39.   def self.need?(name) # 从事件名判断是否需要描边
  40.     return false if CharactorStroker.type(name) == nil
  41.     return name.include?(".st")
  42.   end
  43.  
  44.   def self.needgd?(name) # 判断描边是否需要渐变
  45.     reg = name.match(/\.st\d+g/)
  46.     return reg != nil
  47.   end
  48.  
  49.   def self.type(name) # 判断描边颜色
  50.     type = name.match(/(?<=\.st)\d+/)
  51.     return 0 unless type
  52.     return type[0].to_i
  53.   end
  54.  
  55.   def self.gdtype(name) # 判断描边渐变颜色
  56.     type = name.match(/\.st\d+g(\d+)/i)
  57.     return type[1].to_i
  58.   end
  59.  
  60.   def self.gdrate # 计算渐变比率 (0~1)
  61.     frame = Graphics.frame_count
  62.     prirate = frame % (CSC_GRADIENT_CYCLE * 2)
  63.     rate = prirate.to_f / CSC_GRADIENT_CYCLE if prirate < CSC_GRADIENT_CYCLE
  64.     rate = (CSC_GRADIENT_CYCLE * 2 - prirate.to_f) / CSC_GRADIENT_CYCLE if prirate >= CSC_GRADIENT_CYCLE
  65.     return rate
  66.   end
  67.  
  68.   def self.gdcolor(name) # 计算渐变颜色
  69.     col = CSC_COLORSET[CharactorStroker.type(name)]
  70.     colgd = CSC_COLORSET[CharactorStroker.gdtype(name)]
  71.     rate = CharactorStroker.gdrate
  72.     r = (col[0] + (colgd[0] - col[0]) * rate).to_i
  73.     g = (col[1] + (colgd[1] - col[1]) * rate).to_i
  74.     b = (col[2] + (colgd[2] - col[2]) * rate).to_i
  75.     a = (col[3] + (colgd[3] - col[3]) * rate).to_i
  76.     return [r, g, b, a]
  77.   end
  78.  
  79.   def self.sync(event, lists, states, viewport) # 事件描边同步行走图
  80.     id = event.id
  81.     lists[id].x = event.screen_x - 1
  82.     lists[id].y = event.screen_y - 1
  83.     lists[id].z = event.screen_z - 2
  84.     name = event.event.name
  85.     if CharactorStroker.needgd?(name)
  86.       gd = 1
  87.     else
  88.       gd = 0
  89.     end
  90.     new_state = [event.character_name, name, event.direction, event.pattern, gd]
  91.     if states[id] != new_state
  92.       if CharactorStroker.need?(name)
  93.         col = CharactorStroker.type(name)
  94.         CharactorStroker.draw(lists, states, col, id, viewport)
  95.       else
  96.         lists[id].bitmap.dispose
  97.         lists[id].dispose
  98.         lists.delete(id)
  99.         states.delete(id)
  100.       end
  101.     end
  102.   end
  103.   #--------------------------------------------------------------------------
  104.   # ● 绘制描边精灵图
  105.   #--------------------------------------------------------------------------
  106.   def self.draw(lists, states, col, id, viewport)
  107.     lists[id] = Sprite.new(viewport) if !lists[id] || lists[id].disposed?
  108.     lists[id].color.set(CSC_COLORSET[col][0],CSC_COLORSET[col][1],CSC_COLORSET[col][2],CSC_COLORSET[col][3])
  109.     tevent = $game_map.events[id]
  110.     if CharactorStroker.needgd?(tevent.event.name)
  111.       gd = 1
  112.     else
  113.       gd = 0
  114.     end
  115.     states[id] = [tevent.character_name, tevent.event.name, tevent.direction, tevent.pattern, gd]
  116.     t1 = RPG::Cache.character(tevent.character_name, tevent.character_hue)
  117.     rw = t1.width / 4
  118.     rh = t1.height / 4
  119.     lists[id].ox = rw / 2
  120.     lists[id].oy = rh
  121.     if lists[id].bitmap != nil && !lists[id].bitmap.disposed?
  122.       lists[id].bitmap.dispose
  123.     end
  124.     lists[id].bitmap = Bitmap.new(rw+2, rh+2)
  125.     rx = tevent.pattern * rw
  126.     case tevent.direction
  127.     when 2
  128.       dir = 0
  129.     when 4
  130.       dir = 1
  131.     when 6
  132.       dir = 2
  133.     when 8
  134.       dir = 3
  135.     end
  136.     ry = dir * rh
  137.     evcrect = Rect.new(rx, ry, rw, rh)
  138.     t2 = lists[id].bitmap
  139.     t2.blt(0, 1, t1, evcrect)
  140.     t2.blt(2, 1, t1, evcrect)
  141.     t2.blt(1, 0, t1, evcrect)
  142.     t2.blt(1, 2, t1, evcrect)
  143.     if CSC_IF_8_DIRECTIONS
  144.       t2.blt(2, 2, t1, evcrect)
  145.       t2.blt(0, 0, t1, evcrect)
  146.       t2.blt(2, 0, t1, evcrect)
  147.       t2.blt(0, 2, t1, evcrect)
  148.     end
  149.   end
  150.  
  151. end
  152.  
  153. #==============================================================================
  154. # ● 公开event变量
  155. #==============================================================================
  156.  
  157. class Game_Event < Game_Character
  158.  
  159.   attr_reader :event
  160.  
  161. end
  162.  
  163. #==============================================================================
  164. # ● 修改Spriteset_Map初始化、释放、刷新函数
  165. #==============================================================================
  166.  
  167. class Spriteset_Map
  168.  
  169.   alias cst_old_initialize initialize
  170.   alias cst_old_dispose dispose
  171.   alias cst_old_update update
  172.  
  173.   def initialize
  174.     cst_old_initialize
  175.     @cst_lists = {}
  176.     @cst_states = {}
  177.     cst_refresh
  178.   end
  179.  
  180.   def dispose
  181.     cst_old_dispose
  182.     @cst_lists.each_value{ |cstcheck|
  183.       next unless cstcheck.respond_to?(:dispose)
  184.       if cstcheck.bitmap && !cstcheck.bitmap.disposed?
  185.         cstcheck.bitmap.dispose
  186.       end
  187.       cstcheck.dispose unless cstcheck.disposed?
  188.     }
  189.     @cst_lists.clear
  190.     @cst_states.clear
  191.   end
  192.  
  193.   def update
  194.     cst_old_update
  195.     if @cst_lists
  196.       @cst_lists.each_key{ |cstid|
  197.         event = $game_map.events[cstid]
  198.         CharactorStroker.sync(event, @cst_lists, @cst_states, @viewport1)
  199.         if @cst_states[cstid][4] == 1
  200.           gdcol = CharactorStroker.gdcolor(event.event.name)
  201.           @cst_lists[cstid].color.set(gdcol[0], gdcol[1], gdcol[2], gdcol[3])
  202.         end
  203.       }
  204.     end
  205.   end
  206.  
  207.   def cst_refresh
  208.     @cst_lists.each_value{ |cstcheck|
  209.       next unless cstcheck.respond_to?(:dispose)
  210.       if cstcheck.bitmap && !cstcheck.bitmap.disposed?
  211.         cstcheck.bitmap.dispose
  212.       end
  213.       cstcheck.dispose unless cstcheck.disposed?
  214.     }
  215.     @cst_lists.clear
  216.     @cst_states.clear
  217.     $game_map.events.each_value{ |value|
  218.       event = value.event
  219.       name = event.name
  220.       if CharactorStroker.need?(name) && value.character_name != ""
  221.         col = CharactorStroker.type(name)
  222.         CharactorStroker.draw(@cst_lists, @cst_states, col, event.id, @viewport1)
  223.       end
  224.     }
  225.   end
  226.  
  227. end


范例工程:
描边脚本260402.zip (207.13 KB, 下载次数: 3)

Lv2.观梦者

梦石
0
星屑
683
在线时间
5 小时
注册时间
2017-1-20
帖子
5
2
发表于 2026-3-24 14:20:19 | 只看该作者
在 CharactorStroker.draw 方法中存在一个致命Bug:Bitmap内存泄漏。

在draw方法中,有这样一行代码:
lists[id].bitmap = Bitmap.new(rw+2, rh+2)
当事件行走或转身时,状态改变,sync会调用draw。每次调用draw,都会Bitmap.new生成一张新的位图赋值给Sprite。
但你没有释放旧的Bitmap。

建议将原本的这段代码:
RUBY 代码复制
  1. lists[id].ox = rw / 2
  2.     lists[id].oy = rh
  3.     lists[id].bitmap = Bitmap.new(rw+2, rh+2)
  4.     rx = tevent.pattern * rw


修改为:
RUBY 代码复制
  1. lists[id].ox = rw / 2
  2.     lists[id].oy = rh
  3.     if lists[id].bitmap != nil && !lists[id].bitmap.disposed?
  4.       lists[id].bitmap.dispose
  5.     end
  6.     lists[id].bitmap = Bitmap.new(rw+2, rh+2)
  7.     rx = tevent.pattern * rw
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2026-6-4 10:37

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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