设为首页收藏本站同能贴吧 切换语言 繁体中文
开启辅助访问 切换到窄版
返回列表
+ 发新帖
查看: 88|回复: 0

[转载发布] 仿半条命/反恐精英喷绘系统New

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

    连续签到: 8 天

    [LV.7]常住居民III

    9099

    主题

    882

    回帖

    7万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

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

    灌水之王

    发表于 前天 01:19 | 显示全部楼层 |阅读模式
    [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

    帖子地址: 

    天天去同能,天天有童年!
    回复 送礼论坛版权

    使用道具 举报

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

    本版积分规则

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

    幸运抽奖

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

    立即查看

    聊天机器人
    Loading...

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

    GMT+8, 2026-10-14 04:21 , Processed in 0.138864 second(s), 63 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

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