|
RUBY 代码
[code]#==============================================================================
# ■ Undertale 风格敌人对话气泡
#==============================================================================
#作者:ruigi
#==============================================================================
# ■ 使用说明
#==============================================================================
# 【1】在敌人备注中写入对话标签
# 格式:
# 如:
# 可写入多行,每次随机抽取一句。
#
# 【2】手动换行(仅支持事件脚本)
# 使用 标签,例如:
# 自动换行已启用,超宽文字会自动折行。
#
# 【3】事件脚本指令(在战斗事件的[脚本]中使用)
# set_enemy_dialogue(索引, "台词") # 为敌人设置自定义对话(下次行动时显示)
# force_enemy_dialogue(索引) # 立即强制显示该敌人的对话气泡
# clear_enemy_dialogue(索引) # 清除自定义对话,恢复从备注随机读取
# dismiss_enemy_dialogue # 立即关闭当前显示的气泡
#
# 【4】可调参数(见模块 Enemy_Dialogue)
# ENABLED : 总开关(false 完全关闭功能)
# TEXT_TYPEWRITER : 打字机效果开关
# TYPE_SPEED : 打字速度(每 N 帧显示一个字)
# EXTRA_PAUSE : 打字完成后额外停留帧数
# DELAY_ACTION : 是否等气泡消失后再发动攻击
# SIMULTANEOUS_BUBBLES : 是否所有敌人同时显示气泡
# SIMULTANEOUS_BUBBLES_WAIT : 全体气泡是否等待结束后才继续行动
# REPEAT_DIALOGUE : 是否每回合都可能说话
# Z 键(确认键)可跳过当前正在显示的对话(打字或停留)。
#
# 【5】资源文件
# 请在 Graphics/System/ 下放置气泡图片,文件名见 DIALOGUE_BUBBLE_IMAGE。
#==============================================================================
module Enemy_Dialogue
ENABLED = true
DIALOGUE_BUBBLE_IMAGE = "Enemy_Dialogue_Bubble"
DURATION_IN_FRAMES = 200
X_OFFSET = -30
Y_OFFSET = -290
Z_VALUE = 100
TEXT_COLOR = Color.new(255, 255, 255, 255)
TEXT_SIZE = 20
TEXT_BOLD = true
TEXT_SHADOW_COLOR = Color.new(0, 0, 0, 160)
TEXT_TYPEWRITER = true
TYPE_SPEED = 2
EXTRA_PAUSE = 40
AUTO_WRAP = true
MANUAL_BREAK_TAG = //i
TEXT_PADDING_LEFT = 12
TEXT_PADDING_RIGHT = 12
LINE_SPACING = 24
BUBBLE_ZOOM_X = 1.0
BUBBLE_ZOOM_Y = 1.0
SHOW_IN_LOG = false
REPEAT_DIALOGUE = true
DELAY_ACTION = true
SIMULTANEOUS_BUBBLES = true
SIMULTANEOUS_BUBBLES_WAIT = true
end
#==============================================================================
# ■ RPG::Enemy
#==============================================================================
classRPG::Enemy < RPG::BaseItem
def dialogue_lines
@dialogue_lines ||= load_dialogue_lines
end
def random_dialogue
lines = dialogue_lines
lines.empty? ? nil : lines[rand(lines.size)]
end
private
def load_dialogue_lines
lines = []
note.scan(//i)do |match|
lines.push(match[0].strip)unless match[0].strip.empty?
end
lines
end
end
#==============================================================================
# ■ Game_Enemy
#==============================================================================
class Game_Enemy < Game_Battler
attr_accessor :custom_dialogue_text
attr_accessor :dialogue_displayed
attr_accessor :just_spoke_in_group
alias enemy_dialogue_initialize initialize
def initialize(index, enemy_id)
enemy_dialogue_initialize(index, enemy_id)
@custom_dialogue_text = nil
@dialogue_displayed = false
@just_spoke_in_group = false
end
def active_dialogue_text
return@custom_dialogue_textif@custom_dialogue_text
enemy.random_dialogue
end
def has_dialogue?
returntrueif@custom_dialogue_text
enemy.dialogue_lines.any?
end
def custom_dialogue_active?
!@custom_dialogue_text.nil?
end
end
#==============================================================================
# ■ Window_Enemy_Dialogue_Bubble
#==============================================================================
class Window_Enemy_Dialogue_Bubble < Window_Base
attr_reader :enemy, :text
attr_reader :typing_finished
def initialize(enemy, raw_text)
@enemy = enemy
@raw_text = raw_text
@processed_text = @raw_text.gsub(Enemy_Dialogue::MANUAL_BREAK_TAG, "\n")
@char_index = 0
@type_timer = 0
@typing_finished = false
super(0, 0, 210, 80)
self.opacity = 0
self.back_opacity = 0
self.contents_opacity = 255
self.z = Enemy_Dialogue::Z_VALUE
create_contents
max_width = max_text_width
@total_lines = calculate_lines(@processed_text, max_width)
line_height = Enemy_Dialogue::LINE_SPACING
w = [210, [280, max_width + 40].min].max
h = [80, @total_lines.size * line_height + 32].max
self.width = w
self.height = h
create_contents
create_bubble_sprite
update_display_text
set_position
end
# 自动换行计算
def full_text_width
bmp = Bitmap.new(1, 1)
bmp.font.size = Enemy_Dialogue::TEXT_SIZE
bmp.font.bold = Enemy_Dialogue::TEXT_BOLD
w = bmp.text_size(@processed_text).width
bmp.dispose
w
end
def max_text_width
self.width - 32 - Enemy_Dialogue::TEXT_PADDING_LEFT - Enemy_Dialogue::TEXT_PADDING_RIGHT
end
def create_bubble_sprite
@bubble_sprite = Sprite.new
@bubble_sprite.bitmap = Cache.system(Enemy_Dialogue::DIALOGUE_BUBBLE_IMAGE)
@bubble_sprite.z = self.z - 100
@bubble_sprite.zoom_x = Enemy_Dialogue::BUBBLE_ZOOM_X
@bubble_sprite.zoom_y = Enemy_Dialogue::BUBBLE_ZOOM_Y
end
def create_contents
self.contents.disposeifself.contents
self.contents = Bitmap.new(width - 32, height - 32)
self.contents.clear
end
def calculate_lines(text, max_width)
lines = []
paragraphs = text.split("\n")
bmp = self.contents
bmp.font.size = Enemy_Dialogue::TEXT_SIZE
bmp.font.bold = Enemy_Dialogue::TEXT_BOLD
paragraphs.eachdo |para|
if para.empty?
lines max_width
lines |