Показано с 1 по 10 из 28

Тема: EKLib

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

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

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

    EKLib v.2.1b

    Предисловие:
    Вот, наконец, я и закончил вылавливать всех жуков в своем творении и с гордостью, а так же потаенным страхом в душе, могу представить на ваш суд свою библиотеку. В версии 2.0 она претерпела весьма значительные изменения и абсолютно не совместима с предыдущими версиями. Так что если вы пользовались более ранней версией библиотеки - придется много чего менять. Надеюсь, в будущем, с обновлением будет попроще... Смотрите, тестите, оценивайте, пользуйтесь, критикуйте... Только ногами не бейте... или, хотя бы, не по голове... Пожелания и советы - пишите все. Вот...

    Список изменений:
    • Новый метод: mirror(Bitmap) - возвращает отраженное изображение
    • Новый метод: resize(Bitmap) - возвращает изображение с измененным размером
    • Измене метод: hyphen_draw_text(Bitmap) - рисует строку text в контейнере рисунка, перенося не помещающиеся слова


    Методы:
    • calculate_line[Math] - возвращает массив координат точек, лежащих на отрезке AB.
    • calculate_circle[Math] - возвращает массив координат точек, лежащих на окружности
    • calculate_arc[Math] - возвращает массив координат точек, лежащих на дуге окружности
    • push_image_fragments(Array) - записывает в массив фрагменты изображения
    • to_string(Numeric) - преобразует число в строку с заданным количеством знаков
    • mirror(Bitmap) - возвращает отраженное изображение
    • resize(Bitmap) - возвращает изображение с измененным размером
    • draw_rout(Bitmap) - рисует точки заданной величины в координатах, взятых из массива
    • draw_rectangle(Bitmap) - рисует прямоугольник
    • hyphen_draw_text(Bitmap) - рисует строку text в контейнере рисунка, перенося не помещающиеся слова
    • change(Font) - изменяет все параметры шрифта изображения, если они не указаны, возвращает их к значению по умолчанию

    Примечание: Подробное описание методов, их параметров, а так же инструкции по применению вы можете найти в теле скрипта.

    В следующих версиях планирую:
    • Добавить возможность менять расположение текста, написанного методом hyphenDrawText.
    • Добавить перенос слишком длинных слов, написанных методом hyphenDrawText.


    Скрипт:
    Код:
    #==============================================================================
    # EK Lib v2.1b
    #------------------------------------------------------------------------------
    # Created by: Equilibrium Keeper [equilibriumkeeper@inbox.com]
    # Created on: 05.01.2009 22:02:54
    # Отдельное спасибо: insider, Snaiper, Рольф, Dr. Nick To, Steck
    #          А так же: rpgmaker.sk6.ru, rpg-maker.info, gdsa.rpgmaker.ru,
    #                    otvety.google.ru
    # За основу метода draw_rout был взят метод draw_line неизвестного автора
    #==============================================================================
    # Описание: Библиотека содержит несколько наиболее часто используемых мной
    #           методов. При желании вы можете воспользоваться ими, но делайте
    #           это на свой страх и риск.
    #------------------------------------------------------------------------------
    # Установка: В редакторе скриптов создайте чистую страницу над "Main" и
    #            скопируйте туда данный скрипт.
    #------------------------------------------------------------------------------
    # Примечание: В описании скриптов используются следующие сокращения:
    # [](array) - массив; i(integer) - целое число; f(float) - дробное число
    # b(boolean) - true/false; s(string) - строка
    # В круглых () скобках указаны рекомедуемые значения параметров
    # В фигурных {} скобках указаны допустимые значения параметров
    #==============================================================================
    class Test
      def initialize
        # Класс для тестирования методов и отлова ошибок.
        # Вызывается через команду "Script..." события: Test.new
      end
    end
    #==============================================================================
    module Math
      #----------------------------------------------------------------------------
      # Метод возвращает массив координат точек, лежащих на отрезке AB
      # Возвращает   :[[i, i],..,[i, i]]
      # start_coords :[i, i] - координаты x, y начала отрезка
      # end_coords   :[i, i] - координаты x, y конца отрезка
      #----------------------------------------------------------------------------
      def self.calculate_line(start_coords, end_coords)
        distance = (start_coords[0] - end_coords[0]).abs + (start_coords[1] - end_coords[1]).abs
        array = []
        for i in 1..distance
          x = (start_coords[0] + 1.0 * (end_coords[0] - start_coords[0]) * i / distance).to_i
          y = (start_coords[1] + 1.0 * (end_coords[1] - start_coords[1]) * i / distance).to_i
          array.push([x, y])
        end
        return array
      end
      #----------------------------------------------------------------------------
      # Метод возвращает массив координат точек, лежащих на окружности
      # Возвращает :[[i, i],..,[i, i]]
      # center     :[i, i]  - координаты x, y центра окружности
      # radius     :[i, i]  - координаты x, y точки лежащей на окружности
      # -radius    :integer - радиус окружности
      # accuracy   :integer {1~5) - точность вычислений; nil - автоматически
      #   чем больше значение accuracy, тем дольше расчеты
      #----------------------------------------------------------------------------
      def self.calculate_circle (center, radius, accuracy = nil)
        if radius.is_a?(Array)
          catet_x = (radius[0] - center[0]).abs
          catet_y = (radius[1] - center[1]).abs
          radius = hypot(catet_x, catet_y)
        end
        if accuracy == nil then accuracy = 1 + radius/100 end
        angle = 0
        array = []
        while angle > -360 * accuracy && angle < 360 * accuracy
          x = center[0] + radius * cos(PI * angle.to_f / (180 * accuracy))
          y = center[1] + radius * sin(PI * angle.to_f / (180 * accuracy))
          angle += 1
          unless array.include?([x.round, y.round])
            array.push([x.round, y.round])
          end
        end
        return array
      end
      #----------------------------------------------------------------------------
      # Метод возвращает массив координат точек, лежащих на дуге окружности
      # Возвращает   :[[i, i],..,[i, i]]
      # center       :[i, i] - координаты x, y центра окружности
      # start_coords :[i, i] - координаты x, y начала дуги
      # end_coords   :[i, i] - координаты x, y конца дуги
      #   обе точки должны лежать на одной окружности, иначе метод вернет false
      # -end_coords  :float (-359.0~+359.0) - угол,
      #   на который конец дуги отстоит от ее начала
      # accuracy     :integer {1~5) - точность вычислений; nil - автоматически
      #   чем больше значение accuracy, тем дольше расчеты
      #----------------------------------------------------------------------------
      def self.calculate_arc (center, start_coords, end_coords, clockwise = true, accuracy = nil)
        catet_x = (start_coords[0] - center[0]).abs
        catet_y = (start_coords[1] - center[1]).abs
        radius = hypot(catet_x, catet_y)
        if end_coords.is_a?(Array)
          catet_x2 = (end_coords[0] - center[0]).abs
          catet_y2 = (end_coords[1] - center[1]).abs
          radius2 = hypot(catet_x2, catet_y2)
          return false if radius != radius2
        end
        circle = calculate_circle(center, radius, accuracy)
        index = circle.index([start_coords[0], start_coords[1]])
        unless end_coords.is_a?(Array)
          if end_coords < 0
            end_coords = -end_coords
            clockwise = !clockwise
          end
          while end_coords > 360.0
            end_coords -= 360.0
          end
          rate = circle.size.to_f / 360.0
          end_index = (end_coords * rate).round
          if clockwise
            end_index += index
            if end_index > circle.size - 1 then end_index -= circle.size end
          else
            end_index = index - end_index
            if end_index < 0 then end_index += circle.size end
          end
        end
        array = []
        loop do
          array.push(circle[index])
          if end_coords.is_a?(Array)
            break if circle[index] == [end_coords[0], end_coords[1]]
          else
            break if index == end_index
    
          end
          if clockwise
            if index + 1 == circle.size then index = 0 else index += 1 end        
          else
            if index == 0 then index = circle.size - 1 else index -= 1 end
          end
        end
        return array
      end
      #----------------------------------------------------------------------------
    end
    #==============================================================================
    class Array
      #----------------------------------------------------------------------------
      # Метод записывает в массив фрагменты изображения
      # filename : string  - имя файла, относительно папки проекта
      # index_t  : integer / [integer] [0~...) - порядковый номер(а) фрагмента(ов)
      # - index_t[0] == true - будут возвращены все фрагменты с index[1] по index[2]
      # - index_t[0] == false - будет возвращено index[2] фрагментов начиная с index[1]
      # width    : integer [1 ~ bitmap.width]  - ширина каждого фрагмента
      # height   : integer [1 ~ bitmap.height] - высота каждого фрагмента
      # Примечание: Счет ведется слева направо, сверху вниз.
      #----------------------------------------------------------------------------
      def push_image_fragments (filename, index_t, width, height)
        index = []
        if index_t.is_a?(Integer)
          return false if index_t < 0
          index.push(index_t)
          @interval = index
        elsif index_t.is_a?(Array)
          index = index_t
          return false if index[1] < 0
          if index[0] == true
            return false if index[2] < index[1]
            @interval = index[1]..index[2]
          elsif index[0] == false
            return false if index[2] < 1
            @interval = index[1]...index[1] + index[2]
          end
        else
          return false
        end
        for index_t in @interval
          bitmap = Bitmap.new (filename)
          bitmap_result = Bitmap.new (width, height)
          n = bitmap.width / width
          x = index_t % n * width
          y = index_t / n * height
          rect = Rect.new(x, y, width, height)
          bitmap_result.blt(0, 0, bitmap, rect)
          self.push(bitmap_result)
        end    
      end
      #----------------------------------------------------------------------------
    end
    #==============================================================================
    class Numeric
      #----------------------------------------------------------------------------
      # Метод преобразует число в строку с заданным количеством знаков
      # digits         : integer - количество знаков в возвращаемой строке
      # filling_symbol : string  - символ, заполняющий не достающие знаки
      #----------------------------------------------------------------------------
      def to_string(digits = 3, filling_symbol = "0")
        counter = self.to_s
        for i in self.to_s.size...digits
          counter = filling_symbol + counter
          i += 1
        end
        return counter
      end
      #----------------------------------------------------------------------------
    end
    #==============================================================================
    class Bitmap
      #----------------------------------------------------------------------------
      # Метод возвращает отраженное изображение
      # horizontal :boolean - изображение будет отражено по горизонтали
      # vertical   :boolean - изображение будет отражено по вертикали
      #----------------------------------------------------------------------------
      def mirror(horizontal = true, vertical = false)
        source = self
        if horizontal
          bitmap = Bitmap.new(source.width, source.height)
          for i in 0...source.width
            bitmap.blt(i, 0, source, Rect.new(source.width - 1 - i, 0, 1, source.height))
          end
          source = bitmap
        end
        if vertical
          bitmap = Bitmap.new(source.width, source.height)
          for i in 0...source.height
            bitmap.blt(0, i, source, Rect.new(0, source.height - 1 - i, source.width, 1))
          end
          source = bitmap
        end
        return source
      end
      #----------------------------------------------------------------------------
      # Метод возвращает изображение с измененным размером
      # width         :integer {1~+x) - итоговая ширина изображения
      # height        :integer {1~+x) - итоговая высота изображения
      # background    :color          - цвет фона
      # interpolation :boolean {false} (НЕ РАБОТАЕТ) - будет ли исходное изображение растянуто или сжато
      #----------------------------------------------------------------------------
      def resize(width, height, interpolation = false, background = nil)
        unless interpolation
          bitmap = Bitmap.new(width, height)
          bitmap.fill_rect(0, 0, width, height, background) if background
          bitmap.blt(0, 0, self, Rect.new(0, 0, self.width, self.height))
          return bitmap
        end    
      end
      #----------------------------------------------------------------------------
      # Метод рисует точки заданной величины в координатах, взятых из массива
      # points      :[[i, i],..,[i, i]] - двумерный массив координат x, y точек
      # start_color :color   - цвет, которым будет изображена первая точка
      # width       :integer {1~5) - размер точек
      # end_color   :color - цвет, которым будет изображена последняя точка
      #  если начальный цвет и конечный совподают, то все точки будут нарисованы
      #  начальным цветом, в противном случае будет осуществлен плавный переход цвета
      #----------------------------------------------------------------------------
      def draw_rout (points, start_color, width = 1, end_color = start_color)
        if end_color == start_color
          for i in 0...points.size
            if width == 1
              self.set_pixel(points[i][0], points[i][1], start_color)
            else
              self.fill_rect(points[i][0], points[i][1], width, width, start_color)
            end
          end
        else
          for i in 0...points.size
            # Graphics.update # Следить за линией
            r = start_color.red   * (points.size-1-i)/(points.size-1) + end_color.red   * i/(points.size-1)
            g = start_color.green * (points.size-1-i)/(points.size-1) + end_color.green * i/(points.size-1)
            b = start_color.blue  * (points.size-1-i)/(points.size-1) + end_color.blue  * i/(points.size-1)
            a = start_color.alpha * (points.size-1-i)/(points.size-1) + end_color.alpha * i/(points.size-1)
            if width == 1
              self.set_pixel(points[i][0], points[i][1], Color.new(r, g, b, a))
            else
              self.fill_rect(points[i][0], points[i][1], width, width, Color.new(r, g, b, a)) 
            end
          end
        end
      end
      #----------------------------------------------------------------------------
      # Метод рисует прямоугольник
      # rect    : rect - прямоугольник
      # -rect   : [i, i, i, i] - массив с координатами x, y, ширина, высота
      # color   : color  - цвет прямоугольника
      # gauge   : integer - толщина линии, не имеет значения при заливке
      # filling : boolean - флаг заливки
      #----------------------------------------------------------------------------
      def draw_rectangle (rect, color, gauge = 2, filling = false)
        if rect.is_a?(Rect)
          x = rect.x
          y = rect.y
          width = rect.width
          height = rect.height
        else
          x = rect[0]
          y = rect[1]
          width = rect[2]
          height = rect[3]
        end
        if filling
          fill_rect(x, y, width, height, color)
        else
          fill_rect(x, y, width, gauge, color)
          fill_rect(x, y, gauge, height, color)
          fill_rect(x, y + height - gauge, width, gauge, color)
          fill_rect(x + width - gauge, y, gauge, height, color)
        end
      end
      #----------------------------------------------------------------------------
      # Метод рисует строку text в контейнере рисунка, перенося не помещающиеся слова
      # text     : string  - строка (длина не важна), которую требуется записать
      # width    : integer - максимальная длина строк
      # x        : integer - координата x начала первой строки
      # y        : integer - координата y начала первой строки
      # height   : integer - высота строки
      # calc     : boolean - если true, то рисование производиться не будет
      #   при некорректном значении, будет высчитана автоматически
      #----------------------------------------------------------------------------
      def hyphen_draw_text (text, width, x = 20, y = 20, height = -1, calc = false)
        n = 0
        index = 0
        strings = []
        if height < (font.size.to_f / 1.2).to_f then height = text_size("1рВысотаHeight0").height end
        if text == "" then strings.push("") end
        while n < text.size
          length = text.size
          while text_size(text[n, length]).width > width
            length /= (text_size(text[n, length]).width.to_f / width.to_f).to_f
          end
          strings[index] = text[n, length]
          if (n + length) < text.size
            while (strings[index][length - 1, 1] != " " && strings[index][length - 1, 1] != "")
              length -= 1
              strings[index] = strings[index][0, length]
            end
            n += length - 1
          else
            n += length
          end
          index += 1
        end    
        for i in 0...strings.size
          if strings[i] == "" && i == strings.size - 1
            break
          elsif strings[i] == "" then i += 1 end
          if strings[i][0, 1] == " " then strings[i] = strings[i][1, strings[i].size] end
          unless calc then draw_text(x, y + height * i, width, height, strings[i]) end
        end
        return [strings, y + height * i, height]
      end
      #----------------------------------------------------------------------------
    end
    #==============================================================================
    class Font
      #----------------------------------------------------------------------------
      # Метод изменяет все параметры шрифта изображения, если они не указаны,
      # возвращает их к значению по умолчанию
      # size   : integer - размер шрифта
      # bold   : boolean - флаг утолщенности
      # italic : boolean - флаг курсива
      # color  : color   - цвет шрифта
      # name   : string / [string] - имя шрифта или массив имен
      #----------------------------------------------------------------------------
      def change (size = 24 , bold = false, italic = false,
                      color = Color.new(255,255,255,255),
                      name = ["Arial", "Courier New", "Times New Roman"])
        self.size = size
        self.bold = bold
        self.italic = italic
        self.color = color
        self.name = name
      end
      #----------------------------------------------------------------------------
    end
    #==============================================================================
    Последний раз редактировалось Equilibrium Keeper; 05.01.2009 в 23:38.

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

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

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

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

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

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

Ваши права

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