查看: 1518|回复: 9

[有事请教] 【VA脚本】有没有功能非常简单的气泡对话框脚本?

[复制链接]
梦石
0
星屑
976
在线时间
121 小时
注册时间
2019-3-2
回帖
32
发表于 2025-11-8 19:27:45 | 显示全部楼层 |阅读模式
悬赏200星屑已解决
本帖最后由 sansy 于 2025-11-9 00:52 编辑

如题,我的主要需求是需要一个没有任何特殊功能,能显示文本就够了的气泡对话框脚本。
满足以下条件即可:
1.作为气泡对话框,自然就是在事件头顶显示文本的对话框,如果事件正在移动,那这个对话框自然要跟随事件移动。
2.不覆盖原版或是其他插件提供的主要对话框,我的需求是龙套NPC使用气泡进行对话,而主要剧情依然使用大型对话框与立绘,因此这个气泡对话框除非主动调用,否则不会默认覆盖掉原版的对话框。

最佳答案

查看完整内容

啊这...... 那用这版吧...... [pre lang="ruby"] #============================================================================== # ★ RGSS3_村人のつぶやき Ver0.13a #============================================================================== =begin 作者:tomoaky webサイト:ひきも記は閉鎖しました。 (http://hikimoki.sakura.ne.jp/) キャラクターの頭上にフキダシメッ ...
梦石
0
星屑
29896
在线时间
5733 小时
注册时间
2016-3-8
回帖
1653
发表于 2025-11-8 19:27:46 | 显示全部楼层
sansy 发表于 2025-11-8 23:43
该脚本在以事件为主体使用时,在一个气泡显示完毕后会在第199行报错NoMethodError
undefinded method “x ...


啊这......
那用这版吧......
[pre lang="ruby"]    #==============================================================================
    # ★ RGSS3_村人のつぶやき Ver0.13a
    #==============================================================================
=begin
     
    作者:tomoaky
    webサイト:ひきも記は閉鎖しました。 (http://hikimoki.sakura.ne.jp/)
     
    キャラクターの頭上にフキダシメッセージを表示します。
     
    イベント名、あるいは実行内容の先頭に注釈コマンドでメッセージを設定します。
      <mrbt 少年>
        メッセージタイプを 少年 に設定します、メッセージタイプは
        自由に編集、追加することができます。
        
      イベントコマンドのスクリプトを使い、手動でメッセージを表示することもできます。
      mrbt(0, "動き理解した?")
        最初の数値でメッセージを表示するイベントを指定してください、
        0 で実行中のイベント、-1 でプレイヤー、1 以上でそのIDのイベントが対象です。
        
    メッセージには以下の制御文字が利用できます、内容は文章の表示コマンドと同様です。
      \V[1] / \N[1] / \P / \C[2] / \G
      上記以外に \L で手動での改行が可能です。
      
    注意事項
      イベント名と注釈コマンドの両方でメッセージタイプを指定した場合は
      注釈コマンドが優先されます。注釈コマンドでの指定がないイベントページでのみ
      イベント名による指定が有効になります。
     
    動作に必要な画像
      Graphics/System/mrbt_window.png
      
    2014.11.18  Ver0.13a
      ・トリガー『並列処理』が機能しなくなる致命的な不具合を修正
     
    2014.11.04  Vew0.12a
      ・イベントのページ切り替えとつぶやき表示が連動しない不具合を修正
      ・別シーンからの復帰時につぶやき表示がおかしくなる不具合を修正
     
    2013.08.27  Ver0.11a
      出現条件を満たしていないイベントがあるとエラー落ちする不具合を修正
      
    2013.08.20 Ver0.1a
      公開
     
=end
     
    #==============================================================================
    # ■ 設定項目
    #==============================================================================
    module TMMRBT
      FONT_SIZE = 16                  # フォントサイズ
      BACK_OPACITY = 192              # つぶやきウィンドウの不透明度
      MESSAGE_DURATION = 240          # つぶやきの表示時間(フレーム)
     
      MIN_INTERVAL = 180              # 次のつぶやきまでの最小間隔(フレーム)
      MAX_INTERVAL = 360              # 次のつぶやきまでの最大間隔(フレーム)
     
      # メッセージタイプの設定
      # メッセージは '' で囲み、カンマで区切って必要な数だけ設定します
      DATABASE = {}
      DATABASE["少年"] = ['わーい!', '\C[2]動き\C[0]理解した?', '\N[1]さん!\Lこんにちは!']
      DATABASE["盗賊"] = ['げへへへ', 'ひゃっはーー!!']
    end
     
    #==============================================================================
    # ■ Game_Character
    #==============================================================================
    class Game_Character
      #--------------------------------------------------------------------------
      # ● 公開インスタンス変数
      #--------------------------------------------------------------------------
      attr_accessor :mrbt                     # つぶやきテキスト
    end
     
    #==============================================================================
    # ■ Game_Event
    #==============================================================================
    class Game_Event
      #--------------------------------------------------------------------------
      # ● イベントページの設定をクリア
      #--------------------------------------------------------------------------
      alias tmmrbt_game_event_clear_page_settings clear_page_settings
      def clear_page_settings
        tmmrbt_game_event_clear_page_settings
        @mrbt_type = nil
        @mrbt = nil
      end
      #--------------------------------------------------------------------------
      # ● イベントページの設定をセットアップ
      #--------------------------------------------------------------------------
      alias tmmrbt_game_event_setup_page_settings setup_page_settings
      def setup_page_settings
        tmmrbt_game_event_setup_page_settings
        set_next_mrbt_count
        @mrbt_type = /<mrbt\s+(\S+?)>/i =~ @event.name ? $1 : nil
        @mrbt = nil
        if @list
          @list.each do |list|
            if list.code == 108 || list.code == 408
              @mrbt_type = $1 if /<mrbt\s+(\S+?)>/i =~ list.parameters[0]
            else
              break
            end
          end
        end
      end
      #--------------------------------------------------------------------------
      # ● フレーム更新
      #--------------------------------------------------------------------------
      alias tmmrbt_game_event_update update
      def update
        tmmrbt_game_event_update
        update_mrbt
      end
      #--------------------------------------------------------------------------
      # ○ つぶやきの更新
      #--------------------------------------------------------------------------
      def update_mrbt
        if @mrbt_count && @mrbt_count > 0
          @mrbt_count -= 1
          if @mrbt_count == 0
            @mrbt = get_random_mrbt
            set_next_mrbt_count
          end
        end
      end
      #--------------------------------------------------------------------------
      # ○ ランダムつぶやきの内容取得
      #--------------------------------------------------------------------------
      def get_random_mrbt
        return nil unless @mrbt_type && TMMRBT::DATABASE[@mrbt_type]
        TMMRBT::DATABASE[@mrbt_type][rand(TMMRBT::DATABASE[@mrbt_type].size)].clone
      end
      #--------------------------------------------------------------------------
      # ○ ランダムつぶやきの待機時間をセット
      #--------------------------------------------------------------------------
      def set_next_mrbt_count
        n = rand([TMMRBT::MAX_INTERVAL - TMMRBT::MIN_INTERVAL, 1].max)
        @mrbt_count = TMMRBT::MIN_INTERVAL + n
      end
    end
     
    #==============================================================================
    # ■ Game_Interpreter
    #==============================================================================
    class Game_Interpreter
      #--------------------------------------------------------------------------
      # ● 指定したIDのイベントにつぶやきを強制
      #--------------------------------------------------------------------------
      def mrbt(id, text)
        event = $game_map.interpreter.get_character(id)
        event.mrbt = text if event
      end
    end
     
    #==============================================================================
    # ■ Sprite_Character
    #==============================================================================
    class Sprite_Character
      #--------------------------------------------------------------------------
      # ● オブジェクト初期化
      #     viewport  : ビューポート
      #     character : キャラクター (Game_Character)
      #--------------------------------------------------------------------------
      alias tmmrbt_sprite_character_initialize initialize
      def initialize(viewport, character = nil)
        @bitmap_mrbt = Cache.system("mrbt_window")
        @mrbt_duration = 0
        tmmrbt_sprite_character_initialize(viewport, character)
      end
      #--------------------------------------------------------------------------
      # ● 解放
      #--------------------------------------------------------------------------
      alias tmmrbt_sprite_character_dispose dispose
      def dispose
        dispose_mrbt
        tmmrbt_sprite_character_dispose
      end
      #--------------------------------------------------------------------------
      # ○ フキダシメッセージの解放
      #--------------------------------------------------------------------------
      def dispose_mrbt
        if @mrbt_sprite
          @mrbt_sprite.bitmap.dispose if @mrbt_sprite.bitmap
          @mrbt_sprite.dispose
          @mrbt_sprite = nil
          @mrbt_duration = 0
        end
      end
      #--------------------------------------------------------------------------
      # ● その他の更新
      #--------------------------------------------------------------------------
      alias tmmrbt_sprite_character_update_other update_other
      def update_other
        tmmrbt_sprite_character_update_other
        update_mrbt
      end
      #--------------------------------------------------------------------------
      # ○ フキダシメッセージの更新
      #--------------------------------------------------------------------------
      def update_mrbt
        if @mrbt_duration > 0
          @mrbt_duration -= 1
          if @mrbt_duration == 0
            @character.mrbt = nil
          else
            @mrbt_sprite.x = x
            @mrbt_sprite.y = y - height
            @mrbt_sprite.opacity = @mrbt_duration * 24
          end
        end
      end
      #--------------------------------------------------------------------------
      # ● 新しいエフェクトの設定
      #--------------------------------------------------------------------------
      alias tmmrbt_sprite_character_setup_new_effect setup_new_effect
      def setup_new_effect
        tmmrbt_sprite_character_setup_new_effect
        if @mrbt != @character.mrbt
          @mrbt = @character.mrbt
          start_mrbt(@mrbt)
        end
      end
      #--------------------------------------------------------------------------
      # ○ 文字色取得
      #     n : 文字色番号 (0~31)
      #--------------------------------------------------------------------------
      def text_color(n)
        x = (n % 8) * 8
        y = 32 + (n / 8) * 8
        return @bitmap_mrbt.get_pixel(x, y)
      end
      #--------------------------------------------------------------------------
      # ○ 特殊文字の変換
      #--------------------------------------------------------------------------
      def convert_special_characters(text)
        text.gsub!(/\\/)               { "\e" }
        text.gsub!(/\e\e/)             { "\\" }
        text.gsub!(/\eV\[([0-9]+)\]/i) { $game_variables[$1.to_i] }
        text.gsub!(/\eV\[([0-9]+)\]/i) { $game_variables[$1.to_i] }
        text.gsub!(/\eN\[([0-9]+)\]/i) { actor_name($1.to_i) }
        text.gsub!(/\eP\[(\d+)\]/i)    { party_member_name($1.to_i) }
        text.gsub!(/\eG/i)             { Vocab::currency_unit }
        text.gsub!(/\eL/i)             { "\x00" }
        text.gsub!(/\eC\[([0-9]+)\]/i) { "\x01[#{$1}]" }
        text
      end
      #--------------------------------------------------------------------------
      # ○ アクター n 番の名前を取得
      #--------------------------------------------------------------------------
      def actor_name(n)
        actor = n >= 1 ? $game_actors[n] : nil
        actor ? actor.name : ""
      end
      #--------------------------------------------------------------------------
      # ○ パーティメンバー n 番の名前を取得
      #--------------------------------------------------------------------------
      def party_member_name(n)
        actor = n >= 1 ? $game_party.members[n - 1] : nil
        actor ? actor.name : ""
      end
      #--------------------------------------------------------------------------
      # ○ フキダシメッセージ表示の開始
      #--------------------------------------------------------------------------
      def start_mrbt(text)
        dispose_mrbt
        return unless text
        @mrbt_duration = TMMRBT::MESSAGE_DURATION
        text = convert_special_characters(text.clone)
        pos = {:x => 4, :y => 0, :width => 0, :line_height => TMMRBT::FONT_SIZE + 4}
        bitmap = Bitmap.new(160, 160)
        bitmap.font.size = TMMRBT::FONT_SIZE
        loop do
          c = text.slice!(/./m)         # 次の文字を取得
          case c
          when nil
            break                           # 描画すべき文字がなければ終了
          when "\x00"                       # 改行
            process_new_line(pos)
          when "\x01"                       # \C[n]  (文字色変更)
            text.sub!(/\[([0-9]+)\]/, "")
            bitmap.font.color = text_color($1.to_i)
          else
            bitmap.draw_text(pos[:x], pos[:y], 40, pos[:line_height], c)
            c_width = bitmap.text_size(c).width
            pos[:x] += c_width
            process_new_line(pos) if pos[:x] >= 140   # 右端にきていれば改行
          end
        end
        w = [pos[:x], pos[:width]].max + 4
        h = pos[:y] + (pos[:x] == 4 ? 0 : pos[:line_height])
        create_mrbt_sprite(w, h)            # フキダシウィンドウのスプライトを作成
        @mrbt_sprite.bitmap.blt(0, 0, bitmap, bitmap.rect)
        bitmap.dispose
        update_mrbt
      end
      #--------------------------------------------------------------------------
      # ○ 改行の処理
      #--------------------------------------------------------------------------
      def process_new_line(pos)
        pos[:width] = pos[:x] if pos[:width] < pos[:x]
        pos[:x] = 4
        pos[:y] += pos[:line_height]
      end
      #--------------------------------------------------------------------------
      # ○ フキダシウィンドウのスプライトを作成
      #--------------------------------------------------------------------------
      def create_mrbt_sprite(width, height)
        @mrbt_sprite = ::Sprite.new(nil)
        @mrbt_sprite.z = 90
        @mrbt_sprite.ox = width / 2
        @mrbt_sprite.oy = height + 4
        @mrbt_sprite.bitmap = Bitmap.new(width, height + 8)
        rect = Rect.new(0, 0, 8, 8)
        alpha = TMMRBT::BACK_OPACITY
        @mrbt_sprite.bitmap.blt(0, 0, @bitmap_mrbt, rect, alpha)
        rect.x += 8
        @mrbt_sprite.bitmap.blt(width - 8, 0, @bitmap_mrbt, rect, alpha)
        rect.y += 8
        @mrbt_sprite.bitmap.blt(width - 8, height - 8, @bitmap_mrbt, rect, alpha)
        rect.x -= 8
        @mrbt_sprite.bitmap.blt(0, height - 8, @bitmap_mrbt, rect, alpha)
        rect.set(16, 0, 8, 8)
        @mrbt_sprite.bitmap.blt(@mrbt_sprite.ox - 4, height, @bitmap_mrbt, rect, alpha)
        color = @bitmap_mrbt.get_pixel(8, 8)
        color.alpha = alpha
        @mrbt_sprite.bitmap.fill_rect(8, 0, width - 16, height, color)
        @mrbt_sprite.bitmap.fill_rect(0, 8, 8, height - 16, color)
        @mrbt_sprite.bitmap.fill_rect(width - 8, 8, 8, height - 16, color)
      end
    end[/pre]
回复

使用道具 举报

梦石
0
星屑
29896
在线时间
5733 小时
注册时间
2016-3-8
回帖
1653
发表于 2025-11-8 21:22:45 | 显示全部楼层
本帖最后由 alexncf125 于 2025-11-8 21:52 编辑

村人a好像就有一个
喔~记错了~不是村人a的~而是tomoaky的~叫村人のつぶやき才对~
https://rpg.blue/forum.php?mod=r ... amp;fromuid=2652223
回复

使用道具 举报

梦石
0
星屑
976
在线时间
121 小时
注册时间
2019-3-2
回帖
32
 楼主| 发表于 2025-11-8 23:43:41 | 显示全部楼层
alexncf125 发表于 2025-11-8 21:22
村人a好像就有一个
喔~记错了~不是村人a的~而是tomoaky的~叫村人のつぶやき才对~
https://rpg.blue/ ...


该脚本在以事件为主体使用时,在一个气泡显示完毕后会在第199行报错NoMethodError
undefinded method “x=” for nil:NilClass
以玩家角色为主体使用时,则没有这个问题。
回复

使用道具 举报

梦石
0
星屑
976
在线时间
121 小时
注册时间
2019-3-2
回帖
32
 楼主| 发表于 2025-11-9 00:22:23 | 显示全部楼层
本帖最后由 sansy 于 2025-11-9 00:50 编辑
alexncf125 发表于 2025-11-9 00:09
啊这......
那用这版吧......
    #======================================================== ...


请问这个脚本是没有自动按顺序播放的功能吗?我在事件脚本里写:
mrbt(0, "文本1")
mrbt(0, "文本2")
mrbt(0, "文本3")
他会直接显示“文本3”,而且我自行在中间设置60帧间隔以后,虽然会按顺序显示这三条文本,但是每条文本的持续时间却不固定,时长时短(如有时候“文本1”尚未消失就会被“文本2”替换掉,而有时却会在“文本1”自行消失一会儿后,“文本2”才出现)。
这对我的使用造成了很大的困扰,有没有解决方式呢?
同时“最大间隔”与“最小间隔”的设置到底影响了什么?我目前理解不了。
气泡消失时的渐变消失效果,也无法稳定有或稳定没有,观感非常差。
作为一个简易气泡对话而言,似乎有点太过难以使用了,至少需要能够按顺序,好好的播放下一条对话吧 。
回复

使用道具 举报

梦石
0
星屑
29896
在线时间
5733 小时
注册时间
2016-3-8
回帖
1653
发表于 2025-11-9 01:04:16 | 显示全部楼层
本帖最后由 alexncf125 于 2025-11-9 09:42 编辑
sansy 发表于 2025-11-9 00:22
请问这个脚本是没有自动按顺序播放的功能吗?我在事件脚本里写:
mrbt(0, "文本1")
mrbt(0, "文本2")


关于时长时短的情況, 把132行的return nil unless @mrbt_type && TMMRBT::DATABASE[@mrbt_type]
改成return @mrbt unless @mrbt_type && TMMRBT::DATABASE[@mrbt_type]就好了

至于“最大间隔”与“最小间隔”的设置, 那是做菜市场(61-63行)用的,
我想大概是用来随机出时间差, 来模拟出比较人性化的叫卖效果,
不然几个菜贩的每句话, 都隔着相同帧数的话, 会显得有些呆板?

睡觉去了~不说啦~自己研究去吧~
回复

使用道具 举报

梦石
0
星屑
976
在线时间
121 小时
注册时间
2019-3-2
回帖
32
 楼主| 发表于 2025-11-9 01:24:06 | 显示全部楼层
alexncf125 发表于 2025-11-9 01:04
关于时长时短的情況, 把132行的return nil unless @mrbt_type && TMMRBT::DATABASE[@mrbt_type]
改成retu ...

时长时短的问题已经得到解决,现在又出现了新的问题:
并行处理的事件中使用该脚本,会出现:
1.无法以0指代”本事件“,会错误的让文本气泡出现在另外一个事件上方(我的测试中,21号并行处理事件播放的气泡出现在了5号事件上)
2.尝试令该并行处理事件循环如上所述的:
mrbt(0, "文本1")
等待若干帧数
mrbt(0, "文本2")
等待若干帧数
mrbt(0, "文本3")
等待若干帧数
的时候,在第一条文本播放完毕后,无论等多久,都不会再播放文本。
回复

使用道具 举报

老鹰

梦石
40
星屑
37812
在线时间
7091 小时
注册时间
2012-5-26
回帖
3297

极短24评委极短23参与极短22参与极短21评委老司机慢点开短篇十吟唱者组别冠军开拓者剧作品鉴家

发表于 2025-11-9 09:22:12 | 显示全部楼层
我自己的对话框似乎符合,开启兼容模式,就不会覆盖其它对话框
不过可能功能太多了?
https://rpg.blue/thread-476586-1-1.html

点评

功能确实有一点太多,我个人总会觉得太多用不上的功能反而很容易和其他的脚本起冲突...... 虽然目前用不上,不过还是谢谢大佬了。  发表于 2025-11-9 17:48
回复

使用道具 举报

梦石
0
星屑
29896
在线时间
5733 小时
注册时间
2016-3-8
回帖
1653
发表于 2025-11-9 09:37:19 | 显示全部楼层
本帖最后由 alexncf125 于 2025-11-9 09:41 编辑

并行处理用 get_character(21).mrbt = "文本1" 啦~
(或者把152行的$game_map.interpreter.删掉
回复

使用道具 举报

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

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部