Показано с 1 по 7 из 7

Тема: Advanced Message Window

Древовидный режим

Предыдущее сообщение Предыдущее сообщение   Следующее сообщение Следующее сообщение
  1. #1

    По умолчанию Advanced Message Window

    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. Идеи, пожелания, багрепорты приветствуются.
    Последний раз редактировалось aisuuw; 09.04.2011 в 07:25.

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Метки этой темы

Социальные закладки

Социальные закладки

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •  
Advanced Message Window