Advanced Message Window v1.0
Предисловие:
Данный скрипт, расширяющий доступные методы вывода сообщения в RPG Maker XP, как и все, что вышло из под моей клавиатуры, является сырым и некачественным, изобилующим глюками и недоработками. Однако, оные звери достаточно успешно прячутся от моего взора, а потому обо всех найденных экземплярах следует немедленно сообщать - буду истреблять.
Описание:
Данный скрипт представляет собой новый класс для вывода текстовых сообщений. Умеет показывать лица любых размеров, как из файла, так и из набора лиц, а так же выводить имя говорящего. Кроме того самостоятельно переносит не помещающиеся строки и оборудован прокруткой содержимого окна, так что в теории вы можете запихнуть в него текста на 65535 пикселей по высоте. Теоретически, потому что используется мой кривенький метод переноса из библиотеки EKLib, который все еще не научился быстро работать с большими объемами текста. Поэтому строго рекомендуется не выводить с помощью данного скрипта сообщения, длина которых превышает пять стандартных - будут заметные задержки. Ну, а если вы попытаетесь впихнуть сюда Войну и Мир, то игра благополучно закроется через десять секунд простоя. Кроме того, даже если в последствии скрипты будут модернизированы и задержки не будет, все же не рекомендуется собирать через чур длинные сообщения - это плохо скажется на динамичности игры.
Теперь о грустном. Пока не реализована система замен и управления текстом (вернее, замены на каком то этапе, вдруг, перестали работать). А так же еще часть мелких, нужных в хозяйстве деталей. Все это обязательно появится, как только появится свободное время.
Особенности:
В следствии довольно сложных настроек данного скрипта, которых в будущем станет еще больше, пришлось написать отдельную программу, генерирующую код для вставки в Script... события. Программа не требует установки и проста в управлении. Умеет запоминать настройки, в неограниченном количестве, так что в целом использовать ее должно быть удобно. Любые предложения, как по скрипту, так и по проге будут рассмотрены и, возможно, реализованы (для особо внимательных: да, скриншоты от разных версий, но снимать заново было лень ^^).
В следующих версиях планирую:
- Исправить замену.
- Доработать окно вывода имени.
- Прикрутить методы управления текстом.
Требования:
- Наличие EKLib v2.1
- Наличие EKLib Addon - Window Double v1.0
Работоспособность с более поздними версиями не гарантируется.
Установка:
В редакторе скриптов:
- Создайте чистую страницу над "Main" и скопируйте туда данный скрипт.
- В классе Scene_Map, в начале метода main вставить строку:
Код:
$advance_message_window = Window_Dialogue_Advance.new
В конце метода:
Код:
$advance_message_window.dispose
Пример:
Код:
#----------------------------------------------------------------------------
def main
@spriteset = Spriteset_Map.new
#-----
$advance_message_window = Window_Dialogue_Advance.new
#-----
@message_window = Window_Message.new
Graphics.transition
loop do
Graphics.update
Input.update
update
if $scene != self
break
end
end
Graphics.freeze
@spriteset.dispose
#-----
$advance_message_window.dispose
#-----
@message_window.dispose
if $scene.is_a?(Scene_Title)
Graphics.transition
Graphics.freeze
end
end
#----------------------------------------------------------------------------
- В методе update, после цикла (loop):
Код:
$advance_message_window.update if $advance_message_window.visible
Пример:
Код:
#----------------------------------------------------------------------------
def update
loop do
$game_map.update
$game_system.map_interpreter.update
$game_player.update
$game_system.update
$game_screen.update
unless $game_temp.player_transferring
break
end
transfer_player
if $game_temp.transition_processing
break
end
end
@spriteset.update
#-----
$advance_message_window.update if $advance_message_window.visible
#-----
@message_window.update
if $game_temp.gameover
$scene = Scene_Gameover.new
return
end
if $game_temp.to_title
$scene = Scene_Title.new
return
end
if $game_temp.transition_processing
$game_temp.transition_processing = false
if $game_temp.transition_name == ""
Graphics.transition(20)
else
Graphics.transition(40, "Graphics/Transitions/" +
$game_temp.transition_name)
end
end
if $game_temp.message_window_showing
return
end
if $game_player.encounter_count == 0 and $game_map.encounter_list != []
unless $game_system.map_interpreter.running? or
$game_system.encounter_disabled
n = rand($game_map.encounter_list.size)
troop_id = $game_map.encounter_list[n]
if $data_troops[troop_id] != nil
$game_temp.battle_calling = true
$game_temp.battle_troop_id = troop_id
$game_temp.battle_can_escape = true
$game_temp.battle_can_lose = false
$game_temp.battle_proc = nil
end
end
end
if Input.trigger?(Input::B)
unless $game_system.map_interpreter.running? or
$game_system.menu_disabled
$game_temp.menu_calling = true
$game_temp.menu_beep = true
end
end
if $DEBUG and Input.press?(Input::F9)
$game_temp.debug_calling = true
end
unless $game_player.moving?
if $game_temp.battle_calling
call_battle
elsif $game_temp.shop_calling
call_shop
elsif $game_temp.name_calling
call_name
elsif $game_temp.menu_calling
call_menu
elsif $game_temp.save_calling
call_save
elsif $game_temp.debug_calling
call_debug
end
end
end
#----------------------------------------------------------------------------
Настройка окна сообщений:
В Script... события вставить следующий код (генерируется с помощью "Dialogue Builder.exe"):
Код:
$advance_message_window.set(ширина_окна, высота_окна, отступ_от_края, горизонтальное_положение, вертикальное_положение, высота_строк, непрозрачность_фона, массив_параметров_шрифта, имя_говорящего_или_индекс_персонажа, лицо_говорящего_или_индекс_в_пакете_лиц)
(строго не рекомендуется вбивать руками)
Вывод окна сообщений:
В Script... события вставить следующий код (генерируется с помощью "Dialogue Builder.exe"):
Код:
$advance_message_window.open (массив_абзацев)
(так же не рекомендуется вбивать руками)
Внимание: В случае, если данное сообщение, идет в событии последним, что бы его закрытие не спровоцировало повторное обращение к событию, обязательно добавьте после вызова скрипта что-нибудь еще. К примеру, ожидание в течении одного кадра (wait 1).
Связанные ссылки:
Dialogue Bilder v1.3:
Демоверсия:
EKLib v2.1
EKLib(Addons) - Double Window v.1.0
Скрипт:
Код:
class Window_Dialogue_Advance < Window_Base
#----------------------------------------------------------------------------
attr_accessor :text
#----------------------------------------------------------------------------
def initialize
super(20, 460 - 20, 600, 20)
self.z = 9998
self.back_opacity = 200
@align = 1
@v_align = 2
@width = 600
@height = 240
@string_height = 2
@font = Font.new
@font.change (24, false, true, Color.new(255, 255, 255), ["Times New Roman", "Arial"])
@name = ""
@face = nil
@number = nil
@choice = nil
@speaker_name = Window_Double.new(0, 0, 300, 32, 8, 4)
@speaker_face = Sprite.new
@speaker_name.visible = false
@speaker_face.visible = false
self.visible = false
self.active = false
end
#----------------------------------------------------------------------------
def dispose
@speaker_name.dispose
@speaker_face.dispose
super
end
#----------------------------------------------------------------------------
def set (width = 600, height = 240, space = 20, align = 1, v_align = 2,
s_height = 20, back_opacity = 200,
font = [24, false, true, Color.new(255, 255, 255), ["Times New Roman", "Arial"]],
name = "", face = nil, number = nil, choice = nil)
self.width = width # Ширина окна
self.back_opacity = back_opacity # Непрозрачность
@align = align # Горизонтальное положение окна
@v_align = v_align # Вертикальное положение окна
@height = height # Высота окна
@string_height = s_height # Высота строк
@font = Font.new # Шрифт
@font.change (font[0], font[1], font[2], font[3], font[4])
@number = number # Ввод номера
@choice = choice # Выбор
case @align # Горизонтальное положение окна
when 0 # Слева
self.x = space
when 1 # Посередине
self.x = 320 - self.width / 2
when 2 # Справа
self.x = 640 - self.width - space
end
case @v_align # Вертикальное положение окна
when 0 # Сверху
self.y = space
when 1 # Посередине
self.y = 240 - @height / 2
when 2 # Снизу
self.y = 480 - @height - space
end
if name.is_a?(Integer) # Имя по неомеру
@name = $game_actors[name].name
elsif name.is_a?(String)
@name = name # Имя по строке
end
if face.is_a?(Integer) # Лицо из пакета лиц по номеру
temp = []
temp.push_image_fragments ("Graphics/Faces/faces.png", face, 100, 100)
@face = temp[0]
elsif face.is_a?(String) # Лицо по названию файла
@face = face != "" ? Bitmap.new("Graphics/Faces/" + face) : ""
end
end
#----------------------------------------------------------------------------
def open (text, hyphen = true)
self.pause = true
@text = text
replace
$game_temp.message_window_showing = true
if hyphen
new_y = self.y
new_text = []
temp = Bitmap.new(@width - 32, 460 - 32)
temp.font = @font
for string in @text
hyphen_calc = temp.hyphen_draw_text (string, @width - 32, 0, 0, -1, true)
new_y += hyphen_calc[1]
for i in 0...hyphen_calc[0].size
new_text.push(hyphen_calc[0][i])
end
end
if @string_height < @font.size / 2 then @string_height = hyphen_calc[2] end
@text = new_text
end
clear
draw_text
self.visible = true
while self.height < @height
self.height += 10
Graphics.update
end
if @name
@speaker_name.contents.clear
@speaker_name.contents.font = @font
@speaker_name.width = @speaker_name.contents.text_size(@name).width + @speaker_name.x_space * 2
@speaker_name.height = @speaker_name.contents.text_size(@name).height + @speaker_name.y_space * 2
@speaker_name.x = @align != 2 ? self.x : self.x + self.width - @speaker_name.width
@speaker_name.y = @v_align != 0 ? self.y - @speaker_name.height : self.y + self.height
@speaker_name.back_opacity = self.back_opacity
@speaker_name.contents.draw_text(0, 0, @speaker_name.contents.width, @speaker_name.contents.height, @name)
@speaker_name.update
@speaker_name.visible = true
end
if @face
@speaker_face.bitmap = @face
@speaker_face.x = @align != 2 ? self.x : self.x + self.width - @speaker_face.bitmap.width
@speaker_face.mirror = @align != 2 ? false : true
@speaker_face.y = @v_align != 0 ? self.y - @speaker_face.bitmap.height : self.y + self.height
@speaker_face.y -= @speaker_name.height if @speaker_name.visible && @v_align != 0
@speaker_face.y += @speaker_name.height if @speaker_name.visible && @v_align == 0
@speaker_face.visible = true
end
self.active = true
update
end
#----------------------------------------------------------------------------
def close
@speaker_name.visible = false
@speaker_face.visible = false
self.active = false
self.pause = false
y = self.y
while self.height > 32
self.height -= 10
self.y += 10
Graphics.update
end
self.visible = false
self.y = y
self.ox = 0
self.oy = 0
$game_temp.message_window_showing = false
end
#----------------------------------------------------------------------------
def replace
for string in @text
string.gsub!(/\\[Nn]\[([0-9]+)\]/) do
$game_actors[$1.to_i] != nil ? $game_actors[$1.to_i].name : ""
end
string.gsub!(/\\[Vv]\[([0-9]+)\]/) { $game_variables[$1.to_i] }
string.gsub!(/\\[Ee]\[([0-9]+)\]/) do
$data_enemies[$1.to_i] != nil ? $data_enemies[$1.to_i].name : ""
end
string.gsub!(/\\[Qq]\[([0-9]+)\]/) do
$data_classes[$data_actors[$1.to_i].class_id] != nil ?
$data_classes[$data_actors[$1.to_i].class_id].name : ""
end
string.gsub!(/\\[Uu]/) do
$game_map.name != nil ? $game_map.name : ""
end
end
end
#----------------------------------------------------------------------------
def clear
@text.delete("\260")
@text.delete("\n")
end
#----------------------------------------------------------------------------
def draw_text
self.contents = Bitmap.new(self.width - 32, @string_height * @text.size)
self.contents.font = @font
for i in 0...@text.size
if @string_height < (@font.size.to_f / 1.2).to_f
@string_height = self.contents.text_size(@text[i]).height
end
self.contents.draw_text (0, 0 + @string_height * i, 600, @string_height, @text[i])
end
end
#----------------------------------------------------------------------------
def update
return unless $game_temp.message_window_showing
loop do
Graphics.update
Input.update
super
if Input.trigger?(Input::C)
close
break
elsif Input.repeat?(Input::DOWN)
if self.oy < (@string_height * @text.size - self.height / 1.2)
self.oy += @string_height
end
elsif Input.repeat?(Input::UP)
if self.oy > 0
self.oy -= @string_height
end
end
end
end
#----------------------------------------------------------------------------
end
P.S.Прикрепленная "демоверсия", с которой были сняты скриншоты, являлась местом разработки скрипта, притензии по ней не принимаются(к примеру, невозможность войти в меню[исправлено]). Кстати, она является тем самым примером "как не надо делать", и показывает - что будет, если впихнуть слишком длинное сообщение.
P.P.S. Со следующей версией скрипт переоформлю в своем традиционном стиле, с подробными комментариями, etc.
P.P.P.S. Идеи, пожелания, багрепорты приветствуются.
Социальные закладки