Плохо! Плохо!:  0
Страница 1 из 2 12 ПоследняяПоследняя
Показано с 1 по 10 из 16

Тема: Window

  1. #1

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

    Вниманию скриптеров, предлагаю следующую реализацию класса Window (не Window_Base) и рекомендую к использованию в своих проектах:
    Спойлер Window:
    Код:
    #===============================================================================
    # Custom Window v1.2
    # Автор оригинала: poccil
    # Над скриптом измывались: Vitamant [Jabber: vitamant@jabber.ru]
    #===============================================================================
    class Window
      #-----------------------------------------------------------------------------
      # Свойства, доступные только для чтения
      #-----------------------------------------------------------------------------
      attr_reader :x # Координата X окна.
      attr_reader :y # Координата Y окна.
      attr_reader :z # Координата Z окна.
      attr_reader :width # Ширина окна.
      attr_reader :height # Высота окна.
      attr_reader :opacity # Непрозрачность окна (0-255).
      attr_reader :back_opacity # Непрозрачность фона окна (0-255).
      attr_reader :contents # Ссылка на рисунок (Bitmap), используемый как содержимое окна.
      attr_reader :ox # Координата X начальной точки содержимого окна.
      attr_reader :oy # Координата Y начальной точки содержимого окна.
      attr_reader :space_x # Смещение содержимого окна относительно рамки по оси X.
      attr_reader :space_y # Смещение содержимого окна относительно рамки по оси Y.
      attr_reader :contents_opacity # Непрозрачность содержимого окна (0-255).
      attr_reader :windowskin # Ссылка на рисунок (Bitmap), используемый как скин окна.
      attr_reader :stretch # Метод отображения фона. Если TRUE, растягивает графику фона.
      attr_reader :pause # Видимость графики паузы.
      attr_reader :cursor_rect # Контейнер рисунка курсора-указателя (Rect).
      attr_reader :viewport # Возвращает область просмотра (Viewport).
      attr_reader :active # Состояние мерцания указателя. Если TRUE, то курсор мерцает.
      attr_reader :visible # Видимость окна. Если TRUE, то окно видимо.
      attr_reader :openness
      attr_reader :skingrid
      #-----------------------------------------------------------------------------
      # Инициализация
      #-----------------------------------------------------------------------------
      def initialize
        @x = 0 # Координата X окна.
        @y = 0 # Координата Y окна.
        @z = 0 # Координата Z окна.
        @width = 0 # Ширина окна.
        @height = 0 # Высота окна.
        @opacity = 255 # Непрозрачность окна (0-255).
        @back_opacity = 255 # Непрозрачность фона окна (0-255).
        @ox = 0 # Координата X начальной точки содержимого окна.
        @oy = 0 # Координата Y начальной точки содержимого окна.
        @space_x = 0 # Смещение содержимого окна относительно рамки по оси X.
        @space_y = 0 # Смещение содержимого окна относительно рамки по оси Y.
        @contents_opacity = 255  # Непрозрачность содержимого окна (0-255).
        @stretch = true # Метод отображения фона. Если TRUE, растягивает графику фона.
        @pause = false # Видимость графики паузы.
        @cursor_rect = Window::CursorRect.new(self) # Контейнер рисунка курсора-указателя (Rect).
        @active = true # Состояние мерцания указателя. Если TRUE, то курсор мерцает.
        @visible = true # Видимость окна. Если TRUE, то окно видимо.
        @openness = 255
        
        @skingrid = Window::Skingrid.new
        @pauseframe = 0
        @pauseopacity = 255 # непрозрачность значка ожидания
        @cursorblink = 0 # см. def update
        @cursoropacity = 255 # непрозрачность курсора
        @disposed = false
            
        @sprites = {}
        @sidebitmaps = [nil, nil, nil, nil]
        @spritekeys = [
          "back",
          "corner0","side0","scroll0",
          "corner1","side1","scroll1",
          "corner2","side2","scroll2",
          "corner3","side3","scroll3",
          "cursor","contents","pause"
        ]
        for i in @spritekeys
          @sprites[i] = Sprite.new
        end
        
        private_refresh(true)
      end
      #-----------------------------------------------------------------------------
      # Освобождает окно. Если окно уже было освобождёно, возвращает false.
      #-----------------------------------------------------------------------------
      def dispose
        return false if @disposed
        @sprites.free
        @sidebitmaps.free
        @cursorbitmap.free
        @backbitmap.free
        @windowskin = nil
        @contents = nil
        @disposed = true
      end
      #-----------------------------------------------------------------------------
      # Возвращает TRUE, если окно было освобождёно.
      #-----------------------------------------------------------------------------
      def disposed?
        return @disposed
      end
      #-----------------------------------------------------------------------------
      # Задает новое значение координаты X окна.
      # value :integer - новое значение
      #-----------------------------------------------------------------------------
      def x=(value)
        @x = value
        private_refresh
      end
      #-----------------------------------------------------------------------------
      # Задает новое значение координаты Y окна.
      # value :integer - новое значение
      #-----------------------------------------------------------------------------
      def y=(value)
        @y = value
        private_refresh
      end
      #-----------------------------------------------------------------------------
      # Задает новое значение координаты Z окна.
      # value :integer - новое значение
      #-----------------------------------------------------------------------------
      def z=(value)
        @z = value
        private_refresh
      end
      #-----------------------------------------------------------------------------
      # Изменяет ширину окна.
      # value :integer - новое значение
      #-----------------------------------------------------------------------------
      def width=(value)
        @width = value
        private_refresh(true)
      end
      #-----------------------------------------------------------------------------
      # Изменяет высоту окна.
      # value :integer - новое значение
      #-----------------------------------------------------------------------------
      def height=(value)
        @height = value
        private_refresh(true)
      end
      #-----------------------------------------------------------------------------
      # Изменяет непрозрачность окна.
      # value :integer {0~255} - новое значение
      #-----------------------------------------------------------------------------
      def opacity=(value)
        @opacity = value.correct(0, 255)
        private_refresh
      end
      #-----------------------------------------------------------------------------
      # Изменяет непрозрачность фона окна.
      # value :integer {0~255} - новое значение
      #-----------------------------------------------------------------------------
      def back_opacity=(value)
        @back_opacity = value.correct(0, 255)
        private_refresh
      end
      #-----------------------------------------------------------------------------
      # Заменяет содержимое окна.
      # value :bitmap - новый рисунок
      #-----------------------------------------------------------------------------
      def contents=(value)
        @contents = value
        private_refresh
      end
      #-----------------------------------------------------------------------------
      # Задает новое значение координаты X содержимого окна.
      # value :integer - новое значение
      #-----------------------------------------------------------------------------
      def ox=(value)
        @ox = value
        private_refresh
      end
      #-----------------------------------------------------------------------------
      # Задает новое значение координаты Y содержимого окна.
      # value :integer - новое значение
      #-----------------------------------------------------------------------------
      def oy=(value)
        @oy = value
        private_refresh
      end
      #-----------------------------------------------------------------------------
      # Изменяет расстояние между границей окна и его содержимым по оси OX
      # value :integer - новое значение
      #-----------------------------------------------------------------------------
      def space_x=(value)
        @space_x = value
        private_refresh(true)
      end
      #-----------------------------------------------------------------------------
      # Изменяет расстояние между границей окна и его содержимым по оси OY
      # value :integer - новое значение
      #-----------------------------------------------------------------------------
      def space_y=(value)
        @space_y = value
        private_refresh(true)
      end
      #-----------------------------------------------------------------------------
      # Изменяет непрозрачность содержимого окна.
      # value :integer {0~255} - новое значение
      #-----------------------------------------------------------------------------
      def contents_opacity=(value)
        @contents_opacity = value.correct(0, 255)
        private_refresh
      end
      #-----------------------------------------------------------------------------
      # Заменяет шкурку окна.
      # value :bitmap - новый скин
      #-----------------------------------------------------------------------------
      def windowskin=(value)
        return false unless value.exists? || value.is_a?(Bitmap)
        # Расчитываем положение элементов оформления
        if value.width == 192 && value.height = 128 # RPG Maker XP
          @skingrid.back.set  (  0,   0, 128, 128)
          @skingrid.blind.set (  0,   0,   0,   0)
          @skingrid.border.set(128,   0,  64,  64)
          @skingrid.cursor.set(128,  64,  32,  32)
          @skingrid.pause.set (160,  64,  32,  32)
          @skingrid.colors.set(152,  24,  16,  16)
          @skingrid.color.set (  0,   0,   2,   2)
        elsif value.width == 128 && value.height == 128 # RPG Maker VX
          @skingrid.back.set  (  0,   0,  64,  64)
          @skingrid.blind.set (  0,  64,  64,  64)
          @skingrid.border.set( 64,   0,  64,  64)
          @skingrid.cursor.set( 64,  64,  32,  32)
          @skingrid.pause.set ( 96,  64,  32,  32)
          @skingrid.colors.set( 64,  96,  64,  32)
          @skingrid.color.set (  0,   0,   8,   8)
        else
          return false
        end
        b = @skingrid.border
        @skingrid.side_rects[0].set(b.x + 16, b.y, 32, 16)
        @skingrid.side_rects[1].set(b.x, b.y + 16, 16, 32)
        @skingrid.side_rects[2].set(b.x + 48, b.y + 16, 16, 32)
        @skingrid.side_rects[3].set(b.x + 16, b.y + 48, 32, 16)
        p = @skingrid.pause
        pw = @skingrid.pause_width  = p.width  / 2
        ph = @skingrid.pause_height = p.height / 2
        @skingrid.pause_rects = [
          p.x,      p.y,
          p.x + pw, p.y,
          p.x,      p.y + ph,
          p.x + pw, p.y + ph
        ]
        # Цепляем шкурку
        @windowskin = value
        for i in 0..3
          @sprites["corner#{i}"].bitmap = value
          @sprites["scroll#{i}"].bitmap = value
        end
        @sprites["pause"].bitmap = value
        # Задаем изображения углов и знаков прокрутки
        @sprites["corner0"].src_rect.set(b.x, b.y, 16, 16) # верхний-левый
        @sprites["corner1"].src_rect.set(b.x + 48, b.y, 16, 16) # верхний-правый
        @sprites["corner2"].src_rect.set(b.x, b.y + 48, 16, 16) # нижний-левый
        @sprites["corner3"].src_rect.set(b.x + 48, b.y + 48, 16, 16) # нижний- правый
        @sprites["scroll0"].src_rect.set(b.x + 24, b.y + 16, 16, 8) # верхний
        @sprites["scroll3"].src_rect.set(b.x + 24, b.y + 40, 16, 8) # нижний
        @sprites["scroll1"].src_rect.set(b.x + 16, b.y + 24, 8, 16) # левый
        @sprites["scroll2"].src_rect.set(b.x + 40, b.y + 24, 8, 16) # правый
        private_refresh(true)
      end
      #-----------------------------------------------------------------------------
      # Изменяет способ отображения фона.
      # value :boolean - если true, растягивает графику фона
      #-----------------------------------------------------------------------------
      def stretch=(value)
        @stretch = value
        private_refresh(true)
      end
      #-----------------------------------------------------------------------------
      # Включает или отключает отображение значка ожидания.
      # value :boolean - если true, отображает значок ожидания
      #-----------------------------------------------------------------------------
      def pause=(value)
        @pause = value
        @pauseopacity = 0 unless value
        private_refresh
      end
      #-----------------------------------------------------------------------------
      # Изменяет положение прямоугольника курсора.
      # value :rect - новый прямоугольник
      #-----------------------------------------------------------------------------
      def cursor_rect=(value)
        unless value.is_a?(Rect)
          @cursor_rect.clear
        else
          @cursor_rect.set(value.x, value.y, value.width, value.height)
        end
      end
      #-----------------------------------------------------------------------------
      # Задает новую область просмотра.
      # value :viewport - новая область просмотра
      #-----------------------------------------------------------------------------
      def viewport=(value)
        @viewport = value
        for i in @spritekeys
          #@sprites[i].dispose
          if @sprites[i].is_a?(Sprite)
            #@sprites[i] = Sprite.new(@viewport)
            @sprites[i].viewport = @viewport
          elsif @sprites[i].is_a?(Plane)
            #@sprites[i] = Plane.new(@viewport)
            @sprites[i].viewport = @viewport
          else
            @sprites[i].dispose
            @sprites[i] = nil
          end
        end
        private_refresh(true)
      end
      #-----------------------------------------------------------------------------
      # Включает или отключает мерцание курсора.
      # value :boolean - если true, курсор будет мерцать
      #-----------------------------------------------------------------------------
      def active=(value)
        @active = value
        private_refresh(true)
      end
      #-----------------------------------------------------------------------------
      # Включает или отключает видимость окна и всех его элементов.
      # value :boolean - если true, окно видимо
      #-----------------------------------------------------------------------------
      def visible=(value)
        @visible = value
        private_refresh
      end
      #-----------------------------------------------------------------------------
      # 
      #-----------------------------------------------------------------------------
      def openness=(value)
        @openness = value.correct(0, 255)
        private_refresh
      end
      #-----------------------------------------------------------------------------
      # Обновляет мерцание указателя и значок ожидания.
      #-----------------------------------------------------------------------------
      def update
        return if @disposed # Если окно было освобождено, ничего не делаем
        # Если окно активно - мерцаем курсором, меняя его непрозрачность
        if @active
          if @cursorblink == 0
            @cursoropacity -= 8
            @cursorblink = 1 if @cursoropacity <= 128
          else
            @cursoropacity += 8
            @cursorblink = 0 if @cursoropacity >= 255
          end
          unless @cursor_rect.empty?
            @sprites["cursor"].opacity = @cursoropacity * @contents_opacity / 255
          end
        # Если окно неактивно - делаем курсор полупрозрачным
        else
          unless @cursoropacity == 128
            @cursoropacity = 128
            @sprites["cursor"].opacity = @cursoropacity * @contents_opacity / 255
          end
        end
        # Если значок ожидания отображен, постепенно проявляем его
        if @pause
          @pauseframe = (Graphics.frame_count / 8) % 4
          @pauseopacity = [@pauseopacity + 64, 255].min
          @sprites["pause"].opacity = @pauseopacity
        end
        @sprites.each_value { |value| value.update }
      end
      #-----------------------------------------------------------------------------
      # Возвращает изображение заданного размера. Если существующее изображение
      # удовлетворяет требованиям и не было освобождено, возварщает его.
      # bitmap :bitmap - исходное изображение
      # width  :integer - требуемая ширина изображения
      # height :integer - требуемая высота изображения
      #-----------------------------------------------------------------------------
      def ensure_bitmap(bitmap, width, height)
        if !bitmap || bitmap.disposed? || bitmap.width < width || bitmap.height < height
          bitmap.dispose if bitmap
          bitmap = Bitmap.new([1, width].max, [1, height].max)
        end
        return bitmap
      end
      #-----------------------------------------------------------------------------
      # Заполняет указанную область рисунка "плитками", взятыми из другого рисунка
      # dst_bitmap :bitmap - рисунок, на который будет производиться копирование
      # dst_rect   :rect   - область, которая будет заполнена
      # src_bitmap :bitmap - рисунок, с которого будет производиться копирование
      # src_rect   :rect   - область, определяющая положение "плитки"
      #-----------------------------------------------------------------------------
      def tile_bitmap(dst_bitmap, dst_rect, src_bitmap, src_rect)
        return if !src_bitmap || src_bitmap.disposed?
        left = dst_rect.x
        top = dst_rect.y
        y = 0; loop do break unless y < dst_rect.height
          x = 0; loop do break unless x < dst_rect.width
            dst_bitmap.blt(x + left, y + top, src_bitmap, src_rect)
            x += src_rect.width
          end
          y += src_rect.height
        end
      end
      #-----------------------------------------------------------------------------
      # Перерисовывает окно и его содержимое
      # ???? :boolean - если true, ????
      #-----------------------------------------------------------------------------
      def private_refresh (changeBitmap = false)
        return if @disposed    
        # Цепляем содержимое
        @sprites["contents"].bitmap = @contents
        # Если есть шкурка - делаем окно видимым...
        if @windowskin.exists?
          for i in 0..3
            @sprites["corner#{i}"].opacity = @opacity
            @sprites["corner#{i}"].visible = @visible
            @sprites["side#{i}"].opacity = @opacity
            @sprites["side#{i}"].visible = @visible
            @sprites["scroll#{i}"].opacity = @opacity
            @sprites["scroll#{i}"].visible = @visible
          end
          @sprites["back"].opacity = @back_opacity * @opacity / 255
          @sprites["contents"].opacity = @contents_opacity
          @sprites["back"].visible = @visible
          @sprites["contents"].visible = @visible && @openness == 255
          @sprites["pause"].visible = @visible && @pause
          @sprites["cursor"].visible = @visible && @openness == 255
          hascontents = @contents.exists?
          @sprites["scroll0"].visible = @visible && hascontents && @oy > 0
          @sprites["scroll1"].visible = @visible && hascontents && @ox > 0
          @sprites["scroll2"].visible = @visible && hascontents && (@contents.width - @ox) > @width - @space_x * 2
          @sprites["scroll3"].visible = @visible && hascontents && (@contents.height - @oy) > @height - @space_y * 2
        # ...если шкурки нет - делаем окошко невидимым
        else
          for i in 0...4
            @sprites["corner#{i}"].visible = false
            @sprites["side#{i}"].visible = false
            @sprites["scroll#{i}"].visible = false
          end
          @sprites["contents"].visible = @visible && @openness == 255
          @sprites["contents"].opacity = @contents_opacity
          @sprites["back"].visible = false
          @sprites["pause"].visible = false
          @sprites["cursor"].visible = false
        end
        # Задаем высоту спрайтов
        @sprites.each_value { |sprite| sprite.z = @z }
        @sprites["cursor"].z = @z + 1
        @sprites["contents"].z = @z + 2
        @sprites["pause"].z = @z + 2
        # Задаем размеры содержимого окна
        if @width > @space_x * 2 && @height > @space_y * 2
          @sprites["contents"].src_rect.set(@ox, @oy, @width - @space_x * 2, @height - @space_y * 2)
        else
          @sprites["contents"].src_rect.set(0, 0, 0, 0)
        end
        # Обновляем анимацию паузы
        @sprites["pause"].src_rect.set(
          @skingrid.pause_rects[@pauseframe * 2],
          @skingrid.pause_rects[@pauseframe * 2 + 1],
          @skingrid.pause_width, @skingrid.pause_height
        )
        # Изменяем положение элементов окна на экране
        @sprites["pause"].x = @x + @width - 24
        @sprites["pause"].y = @y + @height - 24
        @sprites["contents"].x = @x + @space_x
        @sprites["contents"].y = @y + @space_y
        @sprites["corner0"].x = @x
        @sprites["corner0"].y = @y
        @sprites["corner1"].x = @x + @width - 16
        @sprites["corner1"].y = @y
        @sprites["corner2"].x = @x
        @sprites["corner2"].y = @y + @height - 16
        @sprites["corner3"].x = @x + @width - 16
        @sprites["corner3"].y = @y + @height - 16
        @sprites["side0"].x = @x + 16
        @sprites["side0"].y = @y
        @sprites["side1"].x = @x
        @sprites["side1"].y = @y + 16
        @sprites["side2"].x = @x + @width - 16
        @sprites["side2"].y = @y + 16
        @sprites["side3"].x = @x + 16
        @sprites["side3"].y = @y + @height - 16
        @sprites["scroll0"].x = @x + @width / 2 - 8
        @sprites["scroll0"].y = @y + 8
        @sprites["scroll1"].x = @x + 8
        @sprites["scroll1"].y = @y + @height / 2 - 8
        @sprites["scroll2"].x = @x + @width - 16
        @sprites["scroll2"].y = @y + @height / 2 - 8
        @sprites["scroll3"].x = @x + @width / 2 - 8
        @sprites["scroll3"].y = @y + @height - 16
        @sprites["back"].x = @x + 2
        @sprites["back"].y = @y + 2
        @sprites["cursor"].x = @x + @space_x + @cursor_rect.x
        @sprites["cursor"].y = @y + @space_y + @cursor_rect.y
        if changeBitmap && @windowskin.exists?
          width = @cursor_rect.width
          height = @cursor_rect.height
          # Если рамка курсора существует, перерисовывает курсор
          unless @cursor_rect.empty?
            cursor_x = @skingrid.cursor.x
            cursor_y = @skingrid.cursor.y    
            cursorrects=[
              # границы
              Rect.new(cursor_x + 2, cursor_y + 0, 28, 2),
              Rect.new(cursor_x + 0, cursor_y + 2, 2, 28),
              Rect.new(cursor_x + 30, cursor_y + 2, 2, 28),
              Rect.new(cursor_x + 2, cursor_y + 30, 28, 2),
              # углы
              Rect.new(cursor_x + 0, cursor_y + 0, 2, 2),
              Rect.new(cursor_x + 30, cursor_y + 0, 2, 2),
              Rect.new(cursor_x + 0, cursor_y + 30, 2, 2),
              Rect.new(cursor_x + 30, cursor_y + 30, 2, 2),
              # фон
              Rect.new(cursor_x + 2, cursor_y + 2, 28, 28)
            ]
            shift = 2 # Смещение элементов
            # Рисуем фон...
            @cursorbitmap = ensure_bitmap(@cursorbitmap, width, height)
            @cursorbitmap.clear
            @sprites["cursor"].bitmap = @cursorbitmap
            @sprites["cursor"].src_rect.set(0, 0, width, height)
            rect = Rect.new(shift, shift, width - shift * 2, height - shift * 2)
            @cursorbitmap.stretch_blt(rect, @windowskin, cursorrects[8])
            # Рисуем углы...
            @cursorbitmap.blt(0, 0, @windowskin, cursorrects[4])# верхний-левый
            @cursorbitmap.blt(width - shift, 0, @windowskin, cursorrects[5]) # верхний-правый
            @cursorbitmap.blt(0, height - shift, @windowskin, cursorrects[6]) # нижний-правый
            @cursorbitmap.blt(width - shift, height - shift, @windowskin, cursorrects[7]) # нижний-левый
            # Рисуем границы...
            #...верхнюю
            rect = Rect.new(shift, 0, width - shift * 2, shift)
            @cursorbitmap.stretch_blt(rect, @windowskin, cursorrects[0])
            #...левую
            rect = Rect.new(0, shift, shift, height - shift * 2)
            @cursorbitmap.stretch_blt(rect, @windowskin, cursorrects[1])
            #...правую
            rect = Rect.new(width - shift, shift, shift, height - shift * 2)
            @cursorbitmap.stretch_blt(rect, @windowskin, cursorrects[2])
            #...нижнюю
            rect = Rect.new(shift, height - shift, width - shift * 2, shift)
            @cursorbitmap.stretch_blt(rect, @windowskin, cursorrects[3])
          else # Если рамки курсора нет - делаем его невидимым
            @sprites["cursor"].visible = false
            @sprites["cursor"].src_rect.set(0, 0, 0, 0)
          end
          # Рисуем стороны окна
          for i in 0..3
            dwidth = (i == 0 || i == 3) ? @width - 32 : 16
            dheight = (i == 0 || i == 3) ? 16 : @height - 32
            @sidebitmaps[i] = ensure_bitmap(@sidebitmaps[i], dwidth, dheight)
            @sprites["side#{i}"].bitmap = @sidebitmaps[i]
            @sprites["side#{i}"].src_rect.set(0, 0, dwidth, dheight)
            @sidebitmaps[i].clear
            side_rects = @skingrid.side_rects
            if side_rects[i].exists?
              @sidebitmaps[i].stretch_blt(@sprites["side#{i}"].src_rect,
                                          @windowskin, side_rects[i])
            end
          end
          # Рисуем фон окна, если есть где рисовать
          backwidth = @width - 4
          backheight = @height - 4
          if backwidth > 0 && backheight > 0
            @backbitmap = ensure_bitmap(@backbitmap, backwidth, backheight)
            @sprites["back"].bitmap = @backbitmap
            @sprites["back"].src_rect.set(0, 0, backwidth, backheight)
            @backbitmap.clear
            if @stretch # Если true, то
              # ...растягиваем фон...
              @backbitmap.stretch_blt(@sprites["back"].src_rect, @windowskin, @skingrid.back)
            else
              # ...иначе, укладываем его "плитками"
              tile_bitmap(@backbitmap, @sprites["back"].src_rect, @windowskin, @skingrid.back)
            end
            unless @skingrid.blind.empty?
              # накладываем поверх фона текстуру, если она есть
              tile_bitmap(@backbitmap, @sprites["back"].src_rect, @windowskin, @skingrid.blind)
            end
          else
            # Если рисовать негде - делаем фон невидимым
            @sprites["back"].visible = false
            @sprites["back"].src_rect.set(0, 0, 0, 0)
          end
        end
        # Если окно открывается, "разворачиваем" его
        unless @openness == 255
          opn = @openness / 255.0
          for k in @spritekeys
            sprite = @sprites[k]
            ratio = (@height <= 0) ? 0 : (sprite.y - @y) * 1.0 / @height
            sprite.zoom_y = opn
            sprite.oy = 0
            sprite.y = (@y + (@height / 2.0) + (@height * ratio * opn) - (@height / 2 * opn)).floor
          end
        else
          # Иначе, приводим его к нормальному виду
          for k in @spritekeys
            sprite = @sprites[k]
            sprite.zoom_y = 1.0
          end
        end
        i = 0
        # Ensure Z order
        for k in @spritekeys
          sprite = @sprites[k]
          y = sprite.y
          sprite.y = i
          sprite.oy = (sprite.zoom_y <= 0) ? 0 : (i - y) / sprite.zoom_y
        end
      end
    end


    Спойлер Window::Skingrid:
    Код:
    class Window
      class Skingrid
        attr_accessor :back
        attr_accessor :blind
        attr_accessor :border
        attr_accessor :cursor
        attr_accessor :pause
        attr_accessor :colors
        attr_accessor :color
        attr_accessor :side_rects
        attr_accessor :pause_rects
        attr_accessor :pause_width
        attr_accessor :pause_height
        def initialize
          @back   = Rect.new(0, 0, 0, 0)
          @blind  = Rect.new(0, 0, 0, 0)
          @border = Rect.new(0, 0, 0, 0)
          @cursor = Rect.new(0, 0, 0, 0)
          @pause  = Rect.new(0, 0, 0, 0)
          @colors = Rect.new(0, 0, 0, 0)
          @color  = Rect.new(0, 0, 0, 0)
          @side_rects = [
            Rect.new(0, 0, 0, 0), Rect.new(0, 0, 0, 0),
            Rect.new(0, 0, 0, 0), Rect.new(0, 0, 0, 0)
          ]
          @pause_rects = [0, 0, 0, 0, 0, 0, 0, 0]
          @pause_width = 0
          @pause_height = 0
        end
      end
    end


    Спойлер Window::CursorRect:
    Код:
    #===============================================================================
    # Custom WindowCursorRect v1.1
    # Автор оригинала: poccil
    # Над скриптом измывались: Vitamant [Jabber: vitamant@jabber.ru]
    #===============================================================================
    class Window
      class CursorRect < Rect
        #-----------------------------------------------------------------------------
         attr_reader :x,:y,:width,:height
        #-----------------------------------------------------------------------------
        def initialize(window)
          @window = window
          @x = 0
          @y = 0
          @width = 0
          @height = 0
        end
        #-----------------------------------------------------------------------------
        def clear
          needupdate = (@x != 0 || @y != 0 || @width != 0 || @height != 0)
          if needupdate
            @x = 0
            @y = 0
            @width = 0
            @height = 0
            @window.private_refresh(true)
          end
        end
        #-----------------------------------------------------------------------------
        def set(x, y, width, height)
          needupdate = (@x != x || @y != y || @width != width || @height != height)
          if needupdate
            @x = x
            @y = y
            @width = width
            @height = height
            @window.private_refresh(true)
          end
        end
        #-----------------------------------------------------------------------------
        def height=(value)
          @height = value; @window.private_refresh(true)
        end
        #-----------------------------------------------------------------------------
        def width=(value)
          @width = value; @window.private_refresh(true)
        end
        #-----------------------------------------------------------------------------
        def x=(value)
          @x = value; @window.private_refresh(true)
        end
        #-----------------------------------------------------------------------------
        def y=(value)
          @y = value; @window.private_refresh(true)
        end
        #-----------------------------------------------------------------------------
      end
    end


    То что нужно для работы окошка:
    Спойлер Numeric:
    Код:
    #===============================================================================
    #
    #===============================================================================
    class Numeric
      #-----------------------------------------------------------------------------
      def correct (min, max = nil)
        if min && self < min
          result = min
        elsif max && self > max
          result = max
        else
          result = self
        end
        return result
      end
      #-----------------------------------------------------------------------------
    end


    Спойлер Object:
    Код:
    #===============================================================================
    #
    #===============================================================================
    class Object
      #-----------------------------------------------------------------------------
      def any_class?(*classes)
        classes = classes[0] if classes[0].is_a?(Array)
        result = false
        for c in classes
          result = true if is_a?(c)
        end
        return result
      end
      #-----------------------------------------------------------------------------
      def any_kind?(*classes)
        classes = classes[0] if classes[0].is_a?(Array)
        result = false
        for c in classes
          result = true if kind_of?(c)
        end
        return result
      end
      #-----------------------------------------------------------------------------
      def exists?
        return false if self.nil?
        return (methods.include?("disposed?") ? !disposed? : true)
      end
      #-----------------------------------------------------------------------------
      def disposable?
        return methods.include?("dispose")
      end
      #-----------------------------------------------------------------------------
      # Освобождает зарезервированную объектом память, если это возможно
      # В случае если объект - массив или хэш, будет освобождено все его содержимое
      #-----------------------------------------------------------------------------
      def free
        if is_a?(Array)
          each_with_index{ |item, index|
            item.free
            self[index] = nil
          }
          clear
        elsif is_a?(Hash)
          each{ |key, item|
            item.free
            key.free
            self[key] = nil
          }
          clear
        elsif is_a?(Sprite)
          self.bitmap.free
          dispose
        else
          dispose if disposable?
        end
      end
      #-----------------------------------------------------------------------------
    end


    Спойлер Rect:
    Код:
    #===============================================================================
    #
    #===============================================================================
    class Rect
      #-----------------------------------------------------------------------------
      def empty?
        return (width <= 0 || height <= 0)
      end
      #-----------------------------------------------------------------------------
      # Преобразует прямоугольник в одномерный массив
      # Возвращает :[i, i, i, i] - [x, y, ширина, высота]
      #-----------------------------------------------------------------------------
      def to_array
        return [self.x, self.y, self.width, self.height]
      end
      #-----------------------------------------------------------------------------
      def []=(index, value)
        case index
        when 0; self.x = value
        when 1; self.y = value
        when 2; self.width = value
        when 3; self.height = value
        end
      end
      #-----------------------------------------------------------------------------
      def [](index)
        to_array[index]
      end
      #-----------------------------------------------------------------------------
    end


    Кроме того, для VX измените метод в классе Window_Selectable:
    Спойлер Что менять...:
    Код:
    #--------------------------------------------------------------------------
      # * Create Window Contents
      #--------------------------------------------------------------------------
      def create_contents
        self.contents.dispose
        self.contents = Bitmap.new(width - 32, [height - 32, row_max * WLH].max)
    end
    на

    Код:
    #--------------------------------------------------------------------------
      # * Create Window Contents
      #--------------------------------------------------------------------------
      def create_contents
        self.contents.free
        self.contents = Bitmap.new(width - 32, [height - 32, row_max * WLH].max)
    end

    Возможно, для XP тоже самое - тестируйте.

    Что это и с чем его едят? Это базовый класс для всех окон, реализованный товарищем Poccil и приведенный мною в божеский вид.
    Что он вам дает? В первую очередь - власть над тонкими материями при создании сложных интерфейсов. Вам это не нужно? Тогда задумайтесь об еще одной возможности - устанавливать смещение содержимого окна относительно его границ! Да-да, те самые пресловутые 16 пикселей, которые порой так портят жизнь, не давай сделать маленькое аккуратное окошечко размерами 200х10, выдавая 200х42. Я уже реализовал это более удобным и гибким способом - окну достаточно задать свойства space_x и space_y - и вуаля. Смещение, может быть равно хоть 0 (хотя, с эстетической точки зрения, все же лучше оставлять 2 пикселя по x и 4 по y).
    А еще это окошко поддерживает скины и от VX и от XP

    Учтите, что по-умолчанию для всех окон смещение будет установлено в значение 0, 0. Вы можете либо изменить это в классе Window либо, что более желательно, в Window_Base, установив в блоке initialize значения self.space_x и self.space_y равными 16.

    Пользуясь случаем, напомню о старом моем проекте, который благополучно все позабыли.
    А именно полностью переписанные скрипты VX под XP, с некоторыми улучшениями, русскими комментариями, багами и недоделками, остановленной по причине моего ухода из мейкера посреди переделки интерфейсов под 1024x768. Если желающие найдутся, я бы рекомендовал добить его - ибо это даст огромное пространство для маневра (аж целых 479232 пикселей ). Ну, а если желания не будет - то там имеется Window_Base, переписанный под этот Window (впрочем, использовать можно и без него).
    http://narod.ru/disk/18501933001/Source.rar.html

    P.S. Тем же, кто все-таки решится использовать мой жуткий проектик, напомню, что он не совместим с чужими скриптами (подавляющим большинством), как от VX, так и от XP, ввиду чего все скрипты придется переписывать и долго править (но оно того стоит ).
    Последний раз редактировалось Arnon; 23.07.2011 в 08:50.

  2. #2
    Авторитет Аватар для Злодей
    Информация о пользователе
    Регистрация
    28.05.2010
    Адрес
    Краснодар
    Сообщений
    1,516
    Записей в дневнике
    7
    Репутация: 62 Добавить или отнять репутацию

    По умолчанию

    Вау! Спасибо. Ща попробую впитать этот скрипт...


    Спойлер 1:


  3. #3

    По умолчанию

    Не заработает.
    Я обновил пост - под вторым спойлером дополнение к скрипту Window. Надеюсь, больше ничего "из своего" я не использовал. Но, если будут ошибки при запуске - пишите (Ctrl+C в окне ошибки скопирует ее в буффер обмена). Разберемся где остались мои хвосты. Что-то выдам. Что-то кривое выкусим. (А так все лежит в архиве )

    P.S. И удостоверьтесь что работает и под XP и под VX. Должен.
    Последний раз редактировалось Equilibrium Keeper; 08.07.2011 в 21:42.

  4. #4
    Авторитет Аватар для Злодей
    Информация о пользователе
    Регистрация
    28.05.2010
    Адрес
    Краснодар
    Сообщений
    1,516
    Записей в дневнике
    7
    Репутация: 62 Добавить или отнять репутацию

    По умолчанию

    Ну я вроде инстальнул... но он не попёр.... как его устанавливать? С заменой стандартного виноу бэйз? или над мэйн?
    Я над мэйн VX поставил. Он дал ошибку связанную с курсором.


    Спойлер 1:


  5. #5

    По умолчанию

    НАД Window_Base
    Это не Window_Base, это - то что выше него.
    Что касается VX, ошибку в студию, как я писал - Ctrl+C в окне ошибки, Ctrl+V сюда.

  6. #6
    Авторитет Аватар для Злодей
    Информация о пользователе
    Регистрация
    28.05.2010
    Адрес
    Краснодар
    Сообщений
    1,516
    Записей в дневнике
    7
    Репутация: 62 Добавить или отнять репутацию

    По умолчанию

    ---------------------------
    New game
    ---------------------------
    Script ' ' line 50: NameError occurred.

    uninitialized constant Window::CursorRect
    ---------------------------
    ОК
    ---------------------------


    Спойлер 1:


  7. #7

    По умолчанию

    Все, ошибку нашел. Довыложил недостающие классы (не мои - авторские).

    ---
    И еще три своих. Кроме того, в классе Window_Selectable нужно изменить один метод:
    Код:
    #--------------------------------------------------------------------------
      # * Create Window Contents
      #--------------------------------------------------------------------------
      def create_contents
        self.contents.dispose
        self.contents = Bitmap.new(width - 32, [height - 32, row_max * WLH].max)
      end
    на

    Код:
    #--------------------------------------------------------------------------
      # * Create Window Contents
      #--------------------------------------------------------------------------
      def create_contents
        self.contents.free
        self.contents = Bitmap.new(width - 32, [height - 32, row_max * WLH].max)
      end
    Проверил на чистом VX - с этим работает.

    Но учти, что для всех окон по-умолчанию ox, oy будет установлен в 0. Чтобы не поплыл интерфейс - определи их как 16 в Window_Base и изменяй уже при необходимости для конкретного класса.

    С VX разобрались. Что с XP? Тестируйте.

    ---

    Исправил первый пост темы - теперь полностью работоспособно для VX. Проверяйте для XP.
    Последний раз редактировалось Equilibrium Keeper; 08.07.2011 в 22:20.

  8. #8
    Авторитет Аватар для Злодей
    Информация о пользователе
    Регистрация
    28.05.2010
    Адрес
    Краснодар
    Сообщений
    1,516
    Записей в дневнике
    7
    Репутация: 62 Добавить или отнять репутацию

    По умолчанию

    ими нужно реплейснуть текущие классы? или тоже вставить их перед ними?


    Спойлер 1:


  9. #9

    По умолчанию

    А у тебя нет этих классов (во всяком случае в чистом проекте). Если все же есть - ставь перед, после - где угодно, главное - над Main

    Так, например.

  10. #10
    Авторитет Аватар для Злодей
    Информация о пользователе
    Регистрация
    28.05.2010
    Адрес
    Краснодар
    Сообщений
    1,516
    Записей в дневнике
    7
    Репутация: 62 Добавить или отнять репутацию

    По умолчанию

    Сделал всё, как ты сказал!
    Титульник запустился... на нём немного сместились надписи... а при запуске игры дал ошибку:


    ---------------------------
    Project1
    ---------------------------
    Script 'Window_Base' line 44: NoMethodError occurred.

    undefined method `dispose' for nil:NilClass
    ---------------------------
    ОК
    ---------------------------


    ИМХО, может быть проще было бы выложить рабочую демку?


    Спойлер 1:


Страница 1 из 2 12 ПоследняяПоследняя

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

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

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

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

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

Ваши права

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