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

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


|
[Ruby] 纯文本查看 复制代码 #==============================================================================
# ** HL1 喷绘系统
#------------------------------------------------------------------------------
# 半条命风格喷绘系统,支持菜单选择图案、颜色调整和快速喷绘
# 作者:Ruigi
# - 喷绘图片放在 Graphics/Sprays/ 文件夹(PNG 格式)
# - 按 A 键快速喷绘
# - 按住 Shift 同时喷绘,喷绘出现在玩家前方一格(墙上喷绘)
# - 主菜单 -> 喷绘 进入设置界面
# - 可配置喷绘混合模式(BLEND_TYPE)
#==============================================================================
module HL1_Spray
#--------------------------------------------------------------------------
# * 配置
#--------------------------------------------------------------------------
FOLDER_PATH = "Graphics/Sprays/" # 喷绘图片文件夹
SE_NAME = "Spray" # 喷绘音效文件名(不含扩展名)
SE_VOLUME = 80 # 音量 (0-100)
SE_PITCH = 100 # 音调 (50-150)
MAX_SPRAYS = 10 # 地图上最多保留喷绘数量(超出移除最旧)
SPRAY_OFFSET_X = 0
# 原地喷绘相对于玩家屏幕坐标的 X 偏移
SPRAY_OFFSET_Y = 0 # 原地喷绘 Y 偏移(负值向上,通常放在脚底)
SPRAY_Z = 99 # Z 坐标(高于角色,低于天气)
SPRAY_KEY = 0x48 # 虚拟键码 0x48 = H 键
FALLBACK_KEY = Input::X # Win32API 不可用时的备用键(X 键)
COLOR_EDIT_KEY = Input::Y # 切换颜色编辑的按键(Y 键)
COLOR_EDIT_KEY_NAME = "Y" # 颜色编辑键的显示名称
#--------------------------------------------------------------------------
# * 混合模式
# 0 = 正常混合
# 1 = 加法混合(变亮)
# 2 = 减法混合(变暗,近似正片叠底)
#--------------------------------------------------------------------------
BLEND_TYPE = 0 # 设置为 2 实现正片叠底效果
#--------------------------------------------------------------------------
# * 墙上喷绘偏移(前方一格喷绘时的微调)
#--------------------------------------------------------------------------
WALL_SPRAY_OFFSET_X = 0 # 前方一格喷绘的 X 偏移(像素)
WALL_SPRAY_OFFSET_Y = 0 # 前方一格喷绘的 Y 偏移(像素)
#--------------------------------------------------------------------------
# * 内部变量
#--------------------------------------------------------------------------
@spray_list = [] # 喷绘文件名列表(不含路径和扩展名)
@current_index = 0 # 当前选中的喷绘索引
@spray_color = Color.new(255,255,255,255) # 当前喷绘颜色 (RGBA)
@initialized = false # 是否已加载列表
@h_was_down = false # 喷绘键上一帧状态(用于触发检测)
# 尝试加载 Win32API(用于检测 H 键)
begin
require 'Win32API'
GET_ASYNC_KEY_STATE = Win32API.new('user32', 'GetAsyncKeyState', 'i', 'i')
USE_WIN32API = true
rescue LoadError
GET_ASYNC_KEY_STATE = nil
USE_WIN32API = false
end
class << self
#------------------------------------------------------------------------
# * 加载喷绘文件列表
#------------------------------------------------------------------------
def load_sprays
@spray_list.clear
Dir.glob(FOLDER_PATH + "*.png").sort.each do |path|
@spray_list << File.basename(path, ".png")
end
@initialized = true
p "[喷绘系统] 已加载 #{@spray_list.size} 个喷绘图片。" if $TEST
end
#------------------------------------------------------------------------
# * 获取喷绘名称列表
#------------------------------------------------------------------------
def spray_list
load_sprays unless @initialized
@spray_list
end
#------------------------------------------------------------------------
# * 获取/设置当前喷绘索引
#------------------------------------------------------------------------
def current_index
load_sprays unless @initialized
@current_index
end
def current_index=(index)
load_sprays unless @initialized
@current_index = index.clamp(0, [spray_list.size - 1, 0].max)
end
#------------------------------------------------------------------------
# * 获取/设置当前喷绘颜色
#------------------------------------------------------------------------
def spray_color
@spray_color
end
def spray_color=(color)
@spray_color = color
end
#------------------------------------------------------------------------
# * 获取当前喷绘位图(失败返回 nil)
#------------------------------------------------------------------------
def current_bitmap
return nil if spray_list.empty?
name = spray_list[current_index]
return nil unless name
path = FOLDER_PATH + name + ".png"
begin
bitmap = Bitmap.new(path)
p "[喷绘系统] 成功加载图片: #{path}" if $TEST
return bitmap
rescue => e
p "[喷绘系统] 加载图片失败: #{path} - #{e.message}" if $TEST
return nil
end
end
#------------------------------------------------------------------------
# * 设置当前喷绘(兼容旧接口)
#------------------------------------------------------------------------
def set_spray(index)
self.current_index = index
end
#------------------------------------------------------------------------
# * 打开喷绘选择场景(脚本调用兼容)
#------------------------------------------------------------------------
def choose_spray
SceneManager.call(Scene_SpraySelect)
end
#------------------------------------------------------------------------
# * 检测喷绘键是否刚按下(触发)
#------------------------------------------------------------------------
def h_trigger?
if USE_WIN32API
down = (GET_ASYNC_KEY_STATE.call(SPRAY_KEY) & 0x8000) != 0
trigger = down && !@h_was_down
@h_was_down = down
p "[喷绘系统] 喷绘键按下: #{trigger}" if $TEST && trigger
trigger
else
Input.trigger?(FALLBACK_KEY)
end
end
#------------------------------------------------------------------------
# * 执行喷绘
#------------------------------------------------------------------------
def spray
return unless SceneManager.scene_is?(Scene_Map)
p "[喷绘系统] 尝试喷绘..." if $TEST
bitmap = current_bitmap
if bitmap.nil?
RPG::SE.new("Buzzer1", 80, 100).play
p "[喷绘系统] 没有可用的喷绘图片!" if $TEST
return
end
# 根据 Shift 键状态决定喷绘位置
if Input.press?(Input::SHIFT)
# 前方一格喷绘(墙上喷绘)
tx = $game_player.x
ty = $game_player.y
case $game_player.direction
when 2 then ty += 1 # 下
when 4 then tx -= 1 # 左
when 6 then tx += 1 # 右
when 8 then ty -= 1 # 上
end
map_x = tx * 32 + 16 + HL1_Spray::WALL_SPRAY_OFFSET_X
map_y = ty * 32 + 16 + HL1_Spray::WALL_SPRAY_OFFSET_Y
p "[喷绘系统] 前方一格喷绘,格子(#{tx}, #{ty})" if $TEST
else
# 原地喷绘
screen_x = $game_player.screen_x + HL1_Spray::SPRAY_OFFSET_X
screen_y = $game_player.screen_y + HL1_Spray::SPRAY_OFFSET_Y
map_x = screen_x + $game_map.display_x * 32
map_y = screen_y + $game_map.display_y * 32
p "[喷绘系统] 原地喷绘" if $TEST
end
spriteset = SceneManager.scene.instance_variable_get(:@spriteset)
if spriteset
spriteset.add_spray(map_x, map_y, bitmap, spray_color)
RPG::SE.new(SE_NAME, SE_VOLUME, SE_PITCH).play
p "[喷绘系统] 喷绘已添加,坐标: (#{map_x}, #{map_y})" if $TEST
else
p "[喷绘系统] 找不到 Spriteset!" if $TEST
bitmap.dispose
end
end
end
end
#==============================================================================
# ** 喷绘列表窗口(继承自 Window_Selectable,但屏蔽内置输入处理)
#==============================================================================
class Window_SprayList < Window_Selectable
#--------------------------------------------------------------------------
# * 初始化
#--------------------------------------------------------------------------
def initialize(x, y, width, height)
super
@data = HL1_Spray.spray_list
self.contents = Bitmap.new(width - 32, [height - 32, 1].max)
refresh
self.index = HL1_Spray.current_index
activate
end
#--------------------------------------------------------------------------
# * 获取项目数
#--------------------------------------------------------------------------
def item_max
@data ? @data.size : 0
end
#--------------------------------------------------------------------------
# * 绘制项目
#--------------------------------------------------------------------------
def draw_item(index)
rect = item_rect(index)
self.contents.clear_rect(rect)
name = @data[index]
self.contents.draw_text(rect, name, 1)
end
#--------------------------------------------------------------------------
# * 刷新
#--------------------------------------------------------------------------
def refresh
self.contents.clear
draw_all_items
end
#--------------------------------------------------------------------------
# * 重写 update,阻止内置方向键等处理
#--------------------------------------------------------------------------
def update
# 留空,不调用 super,完全由场景手动控制
end
end
#==============================================================================
# ** 喷绘预览窗口
#==============================================================================
class Window_SprayPreview < Window_Base
#--------------------------------------------------------------------------
# * 初始化
#--------------------------------------------------------------------------
def initialize(x, y, width, height)
super
@sprite = Sprite.new
@sprite.bitmap = nil
@sprite.x = x + 16
@sprite.y = y + 16
@sprite.z = 200
@sprite.blend_type = HL1_Spray::BLEND_TYPE # 应用混合模式
refresh
end
#--------------------------------------------------------------------------
# * 刷新预览
#--------------------------------------------------------------------------
def refresh
bitmap = HL1_Spray.current_bitmap
if bitmap.nil?
@sprite.bitmap = nil
self.contents.clear
self.contents.font.color = crisis_color
self.contents.draw_text(0, 0, contents_width, 24, "未找到图片", 1)
return
end
@sprite.bitmap = bitmap
@sprite.color = HL1_Spray.spray_color
self.contents.clear
end
#--------------------------------------------------------------------------
# * 更新预览(外部调用)
#--------------------------------------------------------------------------
def update_preview
refresh
end
#--------------------------------------------------------------------------
# * 释放资源
#--------------------------------------------------------------------------
def dispose
@sprite.bitmap.dispose if @sprite.bitmap
@sprite.dispose
super
end
end
#==============================================================================
# ** 颜色调整窗口
#==============================================================================
class Window_SprayColor < Window_Base
attr_reader :red, :green, :blue
attr_accessor :index # 0=红, 1=绿, 2=蓝
def initialize(x, y, width, height)
super
@red, @green, [url=home.php?mod=space&uid=8492]@blue[/url] = HL1_Spray.spray_color.red, HL1_Spray.spray_color.green, HL1_Spray.spray_color.blue
@index = 0
self.contents = Bitmap.new(width - 32, height - 32)
refresh
end
def refresh
self.contents.clear
labels = ["红:", "绿:", "蓝:"]
values = [@red, @green, @blue]
labels.each_with_index do |label, i|
y = i * 28
if i == @index
self.contents.font.color = crisis_color
self.contents.fill_rect(0, y, contents_width, 24, Color.new(255,255,255,80))
else
self.contents.font.color = system_color
end
self.contents.draw_text(0, y, 60, 24, label)
self.contents.font.color = normal_color
self.contents.draw_text(70, y, 60, 24, values[i].to_s, 2)
bar_color = case i
when 0 then Color.new(@red, 0, 0)
when 1 then Color.new(0, @green, 0)
when 2 then Color.new(0, 0, @blue)
end
self.contents.fill_rect(140, y + 4, 100, 16, bar_color)
end
end
def change_color(delta)
case @index
when 0 then [url=home.php?mod=space&uid=71174]@red[/url] = (@red + delta).clamp(0, 255)
when 1 then @green = (@green + delta).clamp(0, 255)
when 2 then @blue = (@blue + delta).clamp(0, 255)
end
HL1_Spray.spray_color = Color.new(@red, @green, @blue, 255)
refresh
end
end
#==============================================================================
# ** 喷绘设置场景
#==============================================================================
class Scene_SpraySelect < Scene_MenuBase
def start
super
create_background
create_list_window
create_preview_window
create_color_window
create_help_window
@list_window.index = HL1_Spray.current_index
@color_mode = false
update_preview
p "[喷绘系统] 设置场景已启动。列表项: #{HL1_Spray.spray_list.size}" if $TEST
end
def create_list_window
@list_window = Window_SprayList.new(0, 48, 240, Graphics.height - 48 - 120)
@list_window.activate
end
def create_preview_window
@preview_window = Window_SprayPreview.new(240, 48, Graphics.width - 240, 200)
end
def create_color_window
@color_window = Window_SprayColor.new(240, 248, Graphics.width - 240, 120)
end
def create_help_window
@help_window = Window_Help.new(1)
@help_window.set_text("选择喷绘图案。按 #{HL1_Spray::COLOR_EDIT_KEY_NAME} 或 Enter 编辑颜色。")
end
def update_preview
@preview_window.update_preview
end
def update
super
@preview_window.update
@color_window.update
@help_window.update
# 注意:不调用 @list_window.update,因为其 update 已被重写为空
if !@color_mode
# 列表编辑模式
if Input.trigger?(Input::UP) || Input.trigger?(Input::DOWN)
if Input.trigger?(Input::UP)
@list_window.index = (@list_window.index - 1) % @list_window.item_max
else
@list_window.index = (@list_window.index + 1) % @list_window.item_max
end
# 同步全局当前索引
HL1_Spray.current_index = @list_window.index
@list_window.refresh
update_preview
Sound.play_cursor
end
if Input.trigger?(Input::C) || Input.trigger?(HL1_Spray::COLOR_EDIT_KEY)
@color_mode = true
@list_window.deactivate
@help_window.set_text("调整颜色:上下键选择分量,左右键调整数值。Enter 保存,Esc 返回。")
end
if Input.trigger?(Input::B)
return_scene
end
else
# 颜色编辑模式
if Input.trigger?(Input::B)
@color_mode = false
@list_window.activate
@help_window.set_text("选择喷绘图案。按 #{HL1_Spray::COLOR_EDIT_KEY_NAME} 或 Enter 编辑颜色。")
end
if Input.trigger?(Input::C)
HL1_Spray.current_index = @list_window.index # 保存最终选择
return_scene
end
if Input.trigger?(Input::UP) || Input.trigger?(Input::DOWN)
if Input.trigger?(Input::UP)
@color_window.index = (@color_window.index - 1) % 3
else
@color_window.index = (@color_window.index + 1) % 3
end
@color_window.refresh
Sound.play_cursor
end
if Input.repeat?(Input::RIGHT)
@color_window.change_color(5)
update_preview
elsif Input.repeat?(Input::LEFT)
@color_window.change_color(-5)
update_preview
end
end
end
def terminate
super
@list_window.dispose
@preview_window.dispose
@color_window.dispose
@help_window.dispose
end
end
#==============================================================================
# ** 主菜单场景
#==============================================================================
class Scene_Menu < Scene_MenuBase
alias hl1_spray_create_command_window create_command_window
def create_command_window
hl1_spray_create_command_window
@command_window.set_handler(:spray, method(:command_spray))
end
def command_spray
SceneManager.call(Scene_SpraySelect)
end
end
#==============================================================================
# ** 菜单命令窗口
#==============================================================================
class Window_MenuCommand < Window_Command
alias hl1_spray_make_command_list make_command_list
def make_command_list
hl1_spray_make_command_list
add_command("喷绘", :spray)
end
end
#==============================================================================
# ** 地图精灵集合
#==============================================================================
class Spriteset_Map
alias hl1_spray_initialize initialize
alias hl1_spray_update update
alias hl1_spray_dispose dispose
def initialize
@spray_sprites = []
hl1_spray_initialize
end
def update
hl1_spray_update
update_spray_sprites
end
def update_spray_sprites
@spray_sprites.each do |entry|
sprite, map_x, map_y = entry
screen_x = map_x - $game_map.display_x * 32
screen_y = map_y - $game_map.display_y * 32
sprite.x = screen_x + HL1_Spray::SPRAY_OFFSET_X
sprite.y = screen_y + HL1_Spray::SPRAY_OFFSET_Y
end
end
def add_spray(map_x, map_y, bitmap, color = Color.new(255,255,255,255))
sprite = Sprite.new(@viewport1)
sprite.bitmap = bitmap
sprite.ox = bitmap.width / 2
sprite.oy = bitmap.height / 2
sprite.z = HL1_Spray::SPRAY_Z
sprite.color = color
sprite.blend_type = HL1_Spray::BLEND_TYPE # 应用混合模式
screen_x = map_x - $game_map.display_x * 32
screen_y = map_y - $game_map.display_y * 32
sprite.x = screen_x + HL1_Spray::SPRAY_OFFSET_X
sprite.y = screen_y + HL1_Spray::SPRAY_OFFSET_Y
@spray_sprites << [sprite, map_x, map_y]
while @spray_sprites.size > HL1_Spray::MAX_SPRAYS
old_entry = @spray_sprites.shift
old_entry[0].bitmap.dispose
old_entry[0].dispose
end
end
def dispose
@spray_sprites.each do |entry|
entry[0].bitmap.dispose
entry[0].dispose
end
@spray_sprites.clear
hl1_spray_dispose
end
end
#==============================================================================
# ** 地图场景
#==============================================================================
class Scene_Map
alias hl1_spray_update update
def update
hl1_spray_update
if HL1_Spray.h_trigger?
HL1_Spray.spray
end
end
end
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|