- 累计送礼:
- 0 个
- 累计收礼:
- 1 个
TA的每日心情 | 开心 3 天前 |
|---|
签到天数: 191 天 连续签到: 3 天 [LV.7]常住居民III

管理员
  
- VIP
- 7
- 卡币
- 17427
- OK点
- 16
- 推广点
- 0
- 同能卷
- 50
- 积分
- 20823


|
RUBY 代码 - #==============================================================================#
- # ** 染色与涂装系统 —— 装备变更行走图 Ace 版 附属脚本
- #------------------------------------------------------------------------------#
- # 作者:MrRuigi
- # 功能:
- # · 在物品备注中定义染料和涂装,通过菜单对已装备的武器/防具进行染色/涂装
- # · 染色采用色相旋转(hue_change),仅改变非透明像素的色调,保持透明背景
- # · 涂装采用正片叠底(Multiply)混合,平铺小图案,仅作用于装备非透明区域
- # · 装备外观变化会实时反映在玩家行走图中
- # · 无可用物品时自动返回上一级,避免卡操作感
- #==============================================================================#
- #==============================================================================#
- # ■ 配置模块
- #==============================================================================#
- module FalDyePaint
- # 菜单中显示的选项名称
- COMMAND_NAME = "染色/涂装"
- # 操作音效
- DYE_SE = "Heal6" # 染色成功
- PAINT_SE = "Item3" # 涂装成功
- CANCEL_SE = "Cancel2" # 取消操作
- ERROR_SE = "Buzzer1" # 错误提示
- # 默认颜色(无染色时视为白色,不影响色调)
- DEFAULT_COLOR = Color.new(255, 255, 255)
- # 预览窗口尺寸
- PREVIEW_WIDTH = 100
- PREVIEW_HEIGHT = 100
- # 染色模式:true = 色相旋转(推荐),false = 像素颜色混合(旧版效果)
- USE_HUE_CHANGE = true
- # 像素混合模式下的染色强度 (0-255),仅在 USE_HUE_CHANGE = false 时生效
- DYE_OPACITY = 160
- # 涂装图片存放文件夹(相对于 Graphics 目录)
- PAINTING_DIR = "Painting"
- end
- #==============================================================================#
- # ■ 装备变更行走图相关配置
- #==============================================================================#
- module EquipDisplay
- # 各个朝向对应的显示优先级,靠后的显示在最前
- Priority = {
- 0 => [:body, :armor, :helmet, :weapon, :shield], # 下
- 1 => [:weapon, :body, :armor, :helmet, :shield], # 左
- 2 => [:shield, :body, :armor, :helmet, :weapon], # 右
- 3 => [:body, :weapon, :shield, :armor, :helmet] # 上
- }
- end
- #==============================================================================#
- # ■ RPG::EquipItem (扩展)
- #==============================================================================#
- classRPG::EquipItem < RPG::BaseItem
- # 获取此装备当前的染色颜色(从系统数据中读取)
- def dye_color
- $game_system.dye_data(self)rescuenil
- end
- # 获取此装备当前的涂装图案文件名
- def paint_pattern
- $game_system.paint_data(self)rescuenil
- end
- # 获取行走图装备备注中的图片名
- def display_equip_part
- @note =~ //
- return $1
- end
- end
- #==============================================================================#
- # ■ RPG::Item (扩展)
- #==============================================================================#
- classRPG::Item < RPG::UsableItem
- # 判断是否为染料物品,并返回解析出的颜色(Color 对象)
- def dye_color
- @note =~ //i
- returnnilunless $1 && $2 && $3
- Color.new($1.to_i, $2.to_i, $3.to_i)
- end
- # 判断是否为涂装物品,并返回图案文件名
- def paint_pattern
- @note =~ //i
- return $1
- end
- # 是否为可用的外观物品(染料或涂装)
- def appearance_item?
- dye_color || paint_pattern
- end
- end
- #==============================================================================#
- # ■ Game_System (扩展)
- #==============================================================================#
- class Game_System
- # 初始化染色/涂装数据容器
- alias dye_paint_initialize initialize
- def initialize
- dye_paint_initialize
- @dye_data = {} # 格式: { equip_id => Color }
- @paint_data = {} # 格式: { equip_id => "pattern_name" }
- end
- # 获取装备的染色颜色
- def dye_data(equip)
- @dye_data[equip_id(equip)] || FalDyePaint::DEFAULT_COLOR
- end
- # 设置装备的染色颜色
- def set_dye_data(equip, color)
- @dye_data[equip_id(equip)] = color
- end
- # 获取装备的涂装图案
- def paint_data(equip)
- @paint_data[equip_id(equip)]
- end
- # 设置装备的涂装图案
- def set_paint_data(equip, pattern)
- @paint_data[equip_id(equip)] = pattern
- end
- # 清除装备的染色数据
- def clear_dye_data(equip)
- @dye_data.delete(equip_id(equip))
- end
- # 清除装备的涂装数据
- def clear_paint_data(equip)
- @paint_data.delete(equip_id(equip))
- end
- private
- # 生成装备的唯一标识符(类别 + ID)
- def equip_id(equip)
- "#{equip.class.name}_#{equip.id}"
- end
- end
- #==============================================================================#
- # ■ Game_Actor (扩展)
- #==============================================================================#
- class Game_Actor
- attr_accessor :equip_changed
- alias dye_paint_change_equip change_equip
- def change_equip(slot_id, item)
- dye_paint_change_equip(slot_id, item)
- @equip_changed = true
- end
- end
- #==============================================================================#
- # ■ Window_DyePaintHelp (自定义帮助窗口)
- #==============================================================================#
- class Window_DyePaintHelp < Window_Help
- def initialize(line_number = 2)
- super(line_number)
- end
- def set_actor(actor)
- set_text(actor ? "#{actor.name} 的装备" : "")
- end
- def set_equip(equip)
- text = equip ? equip.name : ""
- if equip
- dye = $game_system.dye_data(equip)
- pattern = $game_system.paint_data(equip)
- extra = []
- extra 0
- end
- definclude?(item)
- case@mode
- when:dye
- item.is_a?(RPG::Item) && item.dye_color != nil
- when:paint
- item.is_a?(RPG::Item) && item.paint_pattern != nil
- else
- false
- end
- end
- def enable?(item)
- $game_party.item_number(item) > 0
- end
- def update_help
- @help_window.set_item(item)if@help_window
- end
- end
- #==============================================================================#
- # ■ Window_DyePaintPreview (预览窗口)
- #==============================================================================#
- class Window_DyePaintPreview < Window_Base
- def initialize(x, y)
- super(x, y, FalDyePaint::PREVIEW_WIDTH + 32, FalDyePaint::PREVIEW_HEIGHT + 32)
- @equip = nil
- @dye_color = nil
- @paint_pattern = nil
- refresh
- end
- def set_preview(equip, dye_color = nil, paint_pattern = nil)
- returnif@equip == equip && @dye_color == dye_color && @paint_pattern == paint_pattern
- @equip = equip
- @dye_color = dye_color
- @paint_pattern = paint_pattern
- refresh
- end
- def clear
- @equip = nil
- @dye_color = nil
- @paint_pattern = nil
- refresh
- end
- def refresh
- contents.clear
- returnunless@equip
- draw_icon(@equip.icon_index, 0, 0)
- if@dye_color
- rect = Rect.new(24, 0, 24, 24)
- contents.fill_rect(rect, @dye_color)
- end
- if@paint_pattern
- contents.font.size = 16
- contents.draw_text(48, 0, contents_width - 48, 24, @paint_pattern)
- end
- contents.font.size = Font.default_size
- contents.draw_text(0, 30, contents_width, 24, "当前效果", 1)
- end
- end
- #==============================================================================#
- # ■ Scene_DyePaint (染色/涂装主场景)
- #==============================================================================#
- class Scene_DyePaint < Scene_MenuBase
- def start
- super
- create_help_window
- create_command_window
- create_actor_window
- create_equip_window
- create_item_window
- create_preview_window
- @help_window.height = 72
- @command_window.activate
- @mode = :dye
- end
- def create_help_window
- @help_window = Window_DyePaintHelp.new
- @help_window.viewport = @viewport
- end
- def create_command_window
- @command_window = Window_DyePaintCommand.new
- @command_window.viewport = @viewport
- @command_window.y = @help_window.height
- @command_window.set_handler(:dye, method(:command_dye))
- @command_window.set_handler(:paint, method(:command_paint))
- @command_window.set_handler(:cancel, method(:return_scene))
- end
- def create_actor_window
- y = @command_window.y + @command_window.height
- @actor_window = Window_DyePaintActor.new(0, y)
- @actor_window.viewport = @viewport
- @actor_window.help_window = @help_window
- @actor_window.set_handler(:ok, method(:on_actor_ok))
- @actor_window.set_handler(:cancel, method(:on_actor_cancel))
- @actor_window.deactivate
- end
- def create_equip_window
- x = @actor_window.width
- y = @actor_window.y
- @equip_window = Window_DyePaintEquip.new(x, y)
- @equip_window.viewport = @viewport
- @equip_window.help_window = @help_window
- @equip_window.set_handler(:ok, method(:on_equip_ok))
- @equip_window.set_handler(:cancel, method(:on_equip_cancel))
- end
- def create_item_window
- x = @actor_window.width + @equip_window.width
- y = @actor_window.y
- w = Graphics.width - x
- h = Graphics.height - y
- @item_window = Window_DyePaintItem.new(x, y, w, h)
- @item_window.viewport = @viewport
- @item_window.help_window = @help_window
- @item_window.set_handler(:ok, method(:on_item_ok))
- @item_window.set_handler(:cancel, method(:on_item_cancel))
- @item_window.mode = :dye
- end
- def create_preview_window
- x = Graphics.width - FalDyePaint::PREVIEW_WIDTH - 32
- y = @command_window.y
- @preview_window = Window_DyePaintPreview.new(x, y)
- @preview_window.viewport = @viewport
- end
- #--------------------------------------------------------------------------
- # * 命令处理
- #--------------------------------------------------------------------------
- def command_dye
- @mode = :dye
- @command_window.deactivate
- @actor_window.activate
- @item_window.mode = :dye
- @item_window.refresh
- update_preview
- end
- def command_paint
- @mode = :paint
- @command_window.deactivate
- @actor_window.activate
- @item_window.mode = :paint
- @item_window.refresh
- update_preview
- end
- #--------------------------------------------------------------------------
- # * 角色窗口处理
- #--------------------------------------------------------------------------
- def on_actor_ok
- @equip_window.actor = @actor_window.actor
- @actor_window.deactivate
- if@equip_window.item_max > 0
- @equip_window.activate
- else
- Sound.play_buzzer
- @actor_window.activate
- end
- update_preview
- end
- def on_actor_cancel
- @actor_window.deactivate
- @command_window.activate
- @preview_window.clear
- end
- #--------------------------------------------------------------------------
- # * 装备窗口处理
- #--------------------------------------------------------------------------
- def on_equip_ok
- @item_window.refresh
- if@item_window.item_max == 0
- Sound.play_buzzer
- @help_window.set_text("没有可用的#{@mode == :dye ? '染料' : '涂装'}物品")
- @equip_window.deactivate
- @actor_window.activate
- @preview_window.clear
- return
- end
- @equip_window.deactivate
- @item_window.activate
- update_preview
- end
- def on_equip_cancel
- @equip_window.deactivate
- @actor_window.activate
- @preview_window.clear
- @item_window.unselect
- end
- #--------------------------------------------------------------------------
- # * 物品窗口处理
- #--------------------------------------------------------------------------
- def on_item_ok
- item = @item_window.item
- equip = @equip_window.equip
- if item.nil?
- on_item_cancel
- return
- end
- if(@mode == :dye && item.dye_color) || (@mode == :paint && item.paint_pattern)
- apply_appearance(equip, item)
- else
- Sound.play_buzzer
- end
- end
- def on_item_cancel
- @item_window.deactivate
- @equip_window.activate
- @preview_window.set_preview(@equip_window.equip,
- $game_system.dye_data(@equip_window.equip),
- $game_system.paint_data(@equip_window.equip))
- end
- #--------------------------------------------------------------------------
- # * 应用染色/涂装
- #--------------------------------------------------------------------------
- def apply_appearance(equip, item)
- if@mode == :dye
- color = item.dye_color
- $game_system.set_dye_data(equip, color)
- RPG::SE.new(FalDyePaint::DYE_SE, 80).play
- else
- pattern = item.paint_pattern
- $game_system.set_paint_data(equip, pattern)
- RPG::SE.new(FalDyePaint::PAINT_SE, 80).play
- end
- $game_party.lose_item(item, 1)
- @item_window.refresh
- @equip_window.refresh
- update_preview
- @item_window.deactivate
- @equip_window.activate
- @equip_window.select(@equip_window.index)
- $game_player.refresh
- end
- #--------------------------------------------------------------------------
- # * 更新预览窗口
- #--------------------------------------------------------------------------
- def update_preview
- equip = @equip_window.equip
- if equip
- dye = $game_system.dye_data(equip)
- paint = $game_system.paint_data(equip)
- @preview_window.set_preview(equip, dye, paint)
- else
- @preview_window.clear
- end
- end
- #--------------------------------------------------------------------------
- # * 帧更新
- #--------------------------------------------------------------------------
- def update
- super
- if@item_window.active && @item_window.item
- item = @item_window.item
- equip = @equip_window.equip
- if equip
- if@mode == :dye && item.dye_color
- @preview_window.set_preview(equip, item.dye_color,
- $game_system.paint_data(equip))
- elsif@mode == :paint && item.paint_pattern
- @preview_window.set_preview(equip,
- $game_system.dye_data(equip),
- item.paint_pattern)
- else
- @preview_window.set_preview(equip,
- $game_system.dye_data(equip),
- $game_system.paint_data(equip))
- end
- end
- end
- end
- end
- #==============================================================================#
- # ■ Window_MenuCommand (在菜单中添加命令)
- #==============================================================================#
- class Window_MenuCommand < Window_Command
- alias dye_paint_add_original_commands add_original_commands
- def add_original_commands
- dye_paint_add_original_commands
- add_command(FalDyePaint::COMMAND_NAME, :dyepaint, true)
- end
- end
- #==============================================================================#
- # ■ Scene_Menu (增加菜单选项)
- #==============================================================================#
- class Scene_Menu < Scene_MenuBase
- alias dye_paint_create_command_window create_command_window
- def create_command_window
- dye_paint_create_command_window
- @command_window.set_handler(:dyepaint, method(:command_dyepaint))
- end
- def command_dyepaint
- SceneManager.call(Scene_DyePaint)
- end
- end
- #==============================================================================#
- # ■ Sprite_Player (装备变更行走图 + 染色/涂装叠加)
- #==============================================================================#
- class Sprite_Player < Sprite_Character
- EquipDisplayPriority = EquipDisplay::Priority
- def graphic_changed?
- super || equip_changed?
- end
- def equip_changed?
- @character.actor && @character.actor.equip_changed
- end
- def set_character_bitmap
- super
- setup_bitmap_display_equips
- end
- def setup_bitmap_display_equips
- w = @cw * 3
- h = @ch * 4
- i = @character.character_index
- orig_bitmap = Bitmap.new(w, h)
- orig_bitmap.blt(0, 0, self.bitmap, Rect.new(i%4*w, i/4*h, w, h))
- self.bitmap = Bitmap.new(w, h)
- bitmap_draw_equips(orig_bitmap)if@character.actor
- orig_bitmap.dispose
- end
- def bitmap_draw_equips(orig_bitmap)
- @character.actor.equip_changed = false
- temp_equip_bitmaps = []
- @character.actor.equips.each_with_indexdo |equip, index|
- img_name = equip ? equip.display_equip_part : nil
- if img_name
- base_bmp = equip_bitmap(img_name, index == 1 && equip.is_a?(RPG::Weapon))
- if base_bmp
- colored_bmp = apply_dye_and_paint(base_bmp, equip)
- temp_equip_bitmaps.push(colored_bmp)
- else
- temp_equip_bitmaps.push(nil)
- end
- else
- temp_equip_bitmaps.push(nil)
- end
- end
- btmp_rect = Rect.new(0, 0, @cw*3, @ch)
- 4.timesdo |i|
- btmp_rect.y = @ch * i
- EquipDisplayPriority[i].eachdo |part|
- btmp = equip_part_bitmap(part, temp_equip_bitmaps, orig_bitmap)
- self.bitmap.blt(0, btmp_rect.y, btmp, btmp_rect)if btmp
- end
- end
- temp_equip_bitmaps.each{|b| b.disposeif b}
- end
- #--------------------------------------------------------------------------
- # * 应用染色和涂装(染色:色相旋转;涂装:正片叠底 + 平铺)
- #--------------------------------------------------------------------------
- def apply_dye_and_paint(src_bitmap, equip)
- return src_bitmap unless equip
- new_bmp = Bitmap.new(src_bitmap.width, src_bitmap.height)
- # ----- 染色处理(色相旋转)-----
- dye_color = equip.dye_color
- if dye_color && dye_color != FalDyePaint::DEFAULT_COLOR
- ifFalDyePaint::USE_HUE_CHANGE
- hue = rgb_to_hue(dye_color.red, dye_color.green, dye_color.blue)
- new_bmp.blt(0, 0, src_bitmap, src_bitmap.rect)
- new_bmp.hue_change(hue)
- else
- new_bmp.blt(0, 0, src_bitmap, src_bitmap.rect)
- (0...new_bmp.width).eachdo |x|
- (0...new_bmp.height).eachdo |y|
- color = new_bmp.get_pixel(x, y)
- nextif color.alpha == 0
- r = (color.red * (255 - FalDyePaint::DYE_OPACITY) + dye_color.red * FalDyePaint::DYE_OPACITY) / 255
- g = (color.green * (255 - FalDyePaint::DYE_OPACITY) + dye_color.green * FalDyePaint::DYE_OPACITY) / 255
- b = (color.blue * (255 - FalDyePaint::DYE_OPACITY) + dye_color.blue * FalDyePaint::DYE_OPACITY) / 255
- new_bmp.set_pixel(x, y, Color.new(r, g, b, color.alpha))
- end
- end
- end
- else
- new_bmp.blt(0, 0, src_bitmap, src_bitmap.rect)
- end
- # ----- 涂装处理(正片叠底 + 平铺,仅作用于非透明区域)-----
- paint_pattern = equip.paint_pattern
- if paint_pattern
- paint_file = "Graphics/#{FalDyePaint::PAINTING_DIR}/#{paint_pattern}.png"
- ifFile.exist?(paint_file)
- paint_bmp = Bitmap.new(paint_file)
- # 创建平铺图层
- tile_bmp = Bitmap.new(new_bmp.width, new_bmp.height)
- tile_x = (new_bmp.width.to_f / paint_bmp.width).ceil
- tile_y = (new_bmp.height.to_f / paint_bmp.height).ceil
- tile_y.timesdo |y|
- tile_x.timesdo |x|
- tile_bmp.blt(x * paint_bmp.width, y * paint_bmp.height,
- paint_bmp, paint_bmp.rect)
- end
- end
- # 逐像素正片叠底
- (0...new_bmp.width).eachdo |x|
- (0...new_bmp.height).eachdo |y|
- src_color = src_bitmap.get_pixel(x, y)
- nextif src_color.alpha == 0 # 透明区域不处理
- paint_color = tile_bmp.get_pixel(x, y)
- nextif paint_color.alpha == 0 # 涂装透明像素跳过
- base_color = new_bmp.get_pixel(x, y)
- # 正片叠底公式: Result = (Base * Overlay) / 255
- r = (base_color.red * paint_color.red) / 255
- g = (base_color.green * paint_color.green) / 255
- b = (base_color.blue * paint_color.blue) / 255
- # 处理涂装的透明度(Alpha 混合)
- if paint_color.alpha < 255
- alpha_factor = paint_color.alpha / 255.0
- r = (base_color.red * (1 - alpha_factor) + r * alpha_factor).to_i
- g = (base_color.green * (1 - alpha_factor) + g * alpha_factor).to_i
- b = (base_color.blue * (1 - alpha_factor) + b * alpha_factor).to_i
- end
- new_bmp.set_pixel(x, y, Color.new(r, g, b, base_color.alpha))
- end
- end
- tile_bmp.dispose
- paint_bmp.dispose
- end
- end
- new_bmp
- end
- #--------------------------------------------------------------------------
- # * RGB 转色相 (0~360)
- #--------------------------------------------------------------------------
- def rgb_to_hue(r, g, b)
- r /= 255.0
- g /= 255.0
- b /= 255.0
- max = [r, g, b].max
- min = [r, g, b].min
- delta = max - min
- hue = 0.0
- if delta != 0
- case max
- when r
- hue = 60.0 * ((g - b) / delta % 6)
- when g
- hue = 60.0 * ((b - r) / delta + 2)
- when b
- hue = 60.0 * ((r - g) / delta + 4)
- end
- end
- hue = 0if hue < 0
- hue.to_i
- end
- def equip_part_bitmap(part, temp_equip_bitmaps, orig_bitmap)
- case part
- when:body; orig_bitmap
- when:weapon; temp_equip_bitmaps[0]
- when:shield; temp_equip_bitmaps[1]
- when:armor; temp_equip_bitmaps[2]
- when:helmet; temp_equip_bitmaps[3]
- end
- end
- def equip_bitmap(img_name, dual_weapon)
- if img_name
- img_file = "Graphics/DisplayEquips/#{img_name}"
- if dual_weapon
- img_dual = img_file + "_dual.png"
- File.exist?(img_dual) ? Bitmap.new(img_dual) : nil
- else
- Bitmap.new(img_file + ".png")rescuenil
- end
- else
- nil
- end
- end
- def update_src_rect
- pattern = @character.pattern < 3 ? @character.pattern : 1
- sx = pattern * @cw
- sy = (@character.direction - 2) / 2 * @ch
- self.src_rect.set(sx, sy, @cw, @ch)
- end
- def dispose
- bitmap.disposeif bitmap
- super
- end
- end
- #==============================================================================#
- # ■ Spriteset_Map (覆盖角色精灵创建)
- #==============================================================================#
- class Spriteset_Map
- def create_characters
- @character_sprites = []
- $game_map.events.values.eachdo |event|
- @character_sprites.push(Sprite_Character.new(@viewport1, event))
- end
- $game_map.vehicles.eachdo |vehicle|
- @character_sprites.push(Sprite_Character.new(@viewport1, vehicle))
- end
- $game_player.followers.reverse_eachdo |follower|
- @character_sprites.push(Sprite_Player.new(@viewport1, follower))
- end
- @character_sprites.push(Sprite_Player.new(@viewport1, $game_player))
- @map_id = $game_map.map_id
- end
- end
复制代码
注意:由于未知问题,不适用URGE,会导致无报错闪退
本帖来自P1论坛作者Ruigi,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址: https://rpg.blue/forum.php?mod=viewthread&tid=498805 若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|