Графические средства языка

Предыдущая тема Следующая тема Перейти вниз

Графические средства языка

Сообщение  justar в Вс Окт 19, 2008 9:55 am

FreeBASIC, как и многие другие диалекты Бейсика, содержит многочисленные средства для построения графических изображений.

Инициализация графического окна
Для того, что бы начать рисовать, видеосистему компьютера следует подготовить: перевести в графический режим, задать умолчания, очистить экран. Для этого предназначен оператор SCREEN. Следует сразу оговориться – в многозадачных операционных системах вместо перехода в графический режим поверх консольного окна приложения откроется новое графическое окно – куда и будет осуществляться весь последующий вывод. Следует отметить, что хотя мы далее будем пользоваться термином «графическое окно», оно не является Windows-окном и непосредственно к нему не применимы приёмы из раздела «Платформа Win32» (о рисовании в Windows-окнах речь пойдёт в главе «Платформа Win32 - Графика»). В графическом режиме (окне) экран представляет собой матрицу точек (пикселей). Количество точек по горизонтали и вертикали характеризует разрешение экрана. Каждому графическому режиму (в зависимости от аппаратных возможностей вашей видеокарты их может быть различное количество) соответствует определённое разрешение. В каждый момент времени каждая точка может быть окрашена в определённый цвет, количество возможных цветов зависит от графического режима. Различают цвет фона – цвет, в который окрашено всё графическое окно (по умолчанию – чёрный) и цвет изображения – цвет, в который окрашена текущая точка. Следует помнить, что даже если точка не видна на экране, это лишь означает, что она окрашена в цвет фона.

Оператор SCREEN задаёт основные параметры графического окна: номер графического режима (режим 0 закрывает графическое окно или переводит видеосистему в консольный режим), глубина цветности (количество бит на пиксел – этот параметр работает только в расширенных режимах, начиная от 14-го), номер графической страницы (использование этого параметра позволяет отрисовывать изображение заранее, а в нужный момент, переключаясь на отрисованную страницу, мгновенно выводить изображение на экран), флаги (при использовании графической библиотеки GfxLib) и частота обновления экрана (параметр видеодрайвера).

В операционной системе Windows cоздаваемое оператором SCREEN графическое окно по умолчанию получает заголовок, одноимёный с именем исполняемого файла программы. Если надо задать окну определённый, отличный от имени программы, заголовок, это можно сделать с помощью оператора WindowsTitle “заголовок окна”.

Очистка окна производится оператором CLS. Этот оператор окрашивает все точки графического окна в выбранный цвет фона. Так как вновь созданное окно уже «чистое» (под этим термином здесь и далее будем понимать окно, все точки которого окрашены в цвет фона), при инициализации окна оператор CLS имеет смысл использовать только если фон окна должен быть отличен от чёрного (предварительно необходимо выбрать этот цвет оператором COLOR).

Приведём пример инициализации графического окна в системе Windows:
Код:

WindowsTitle “FreeBASIC example graphics window”
SCREEN 9
COLOR , 9
CLS
SLEEP
Эта короткая программа создаёт графическое окно голубого цвета с заголовком “FreeBASIC example graphics window”. Кроме уже знакомых операторов в ней встречается новый – оператор задания цветов по умолчанию COLOR. Перейдём же к разговору о том, как формировать цвета пpи рисовании.

Определение палитры и цветов
Как уже говорилось, для того, что бы задать графическому окну цвета по умолчанию, предназначен оператор

COLOR цвет_рисования, цвет_фона

Цвет рисования – это цвет, который будут использовать все операторы рисования, если цвет рисования в них не указан в явном виде. Цвет фона – цвет, которым закрашивается всё окно оператором CLS.

Встаёт вопрос: какому номеру соответсвует какой цвет? Это определяется таблицей, называемой палитра. Для видеорежимов 1-13, эмулирующих старые типы видеоадаптеров, компилятор FreeBASIC содержит стандартные палитры, однако при необходимости они могут быть переопределены. Для видеорежимов 14-21 палитры надо явным образом определять до применения операторо COLOR (расширенный синтаксис оператора COLOR, применяемый в FreeBASIC, позволяет определить цвет и в самом операторе COLOR – для этого вместо номера цвета в палитре применяется макрос RGB, создающий цвет; подробнее об этом макросе см. ниже).

Палитра представляет собой таблицу, каждая строка которой описывает один цвет и состоит из двух полей – индекс, представляющий собой номер цвета, применяемый в операторе COLOR и операторах рисования, и цвет – код, содержащий в себе три цветовые составляющие (красный, зелёный и синий цвета) и их «веса» (насыщенности). Веса могут изменяться в диапазоне 0-255. Например, цвет с нулевыми весами всех цветовых составляющих – чёрный, а если веса всех составляющих установить в 255 – получим белый цвет. Для работы с палитрой цветов предназначен оператор PALETTE, имеющий несколько вариантов синтаксиса.

PALETTE индекс, цвет присваивает заданному номеру указанный цвет.
PALETTE индекс, r, g, b позволяет явным образом задать веса составляющих
PALETTE GET индекс, r, g, b выполняет обратное предыдущему действие – помещает в переменные r, g и b веса соотвествующих цветов из цвета с указанным номером. Разумеется, имена переменных могут быть произвольными.
PALETTE GET USING имя_массива загружает всю палитру в заданный массив
Код:

SCREEN 15 
LOCATE  1,1: COLOR 15
PRINT  "Press any key to change my color!"
SLEEP
' Меняем цвет 15 с белого на ярко красный
PALETTE  15, &h00003F
SLEEP
Эта программа вначале выводит в графическое окно текст белым цветом, а потом меняет цвет текста на красный. Возникает вопрос: как определить код цвета? Для упрощения этой операции в компиляторе определён макрос RGB (red, green, blue):

#define RGB(r,g,b) ((CUInt(r) Shl 16) Or (CUInt(g) Shl Cool Or CUInt(b) Or
&hFF000000)


В качестве аргументов макроса выступают веса соотвествующих основных цветов – красного, зелёного и синего.

Иногда необходимо узнать текущий цвет определённого пикселя. Для этого предназначенна функция POINT (coord_x, coord_y). Функция возвращает номер цвета для режимов 1-13 или значение RGB для режимов 14-21.
Код:

SCREEN 13
LINE (10, 10) – (100, 100), 12
PRINT POINT (20, 20)
SLEEP
Программа рисует линию 12-м цветом и печатает «12» - номер цвета одной из точек этой линии.

justar

Сообщения : 135
Дата регистрации : 2008-05-12
Возраст : 43
Откуда : Кишинёв, Республика Молдоа

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Графические средства языка

Сообщение  justar в Вс Окт 19, 2008 9:56 am

Основные графические примитивы
Все изображения представляют собой набор графических примитивов. Самым простым примитивом является… точка (пиксел). Три других основных примитива – линия, прямоугольник и окружность являют собой упорядоченныы по определённому алгоритму набор точек. «Рисование» точки, по своей сути, являет собой изменение её цвета. Эту операцию в FB выполняет оператор PSET (x, y), цвет. Имеется так же модифицированный оператор PRESET (x, y), цвет.Разница в этих операторах проявляется только в том случае, если параметр «цвет» отсутствует – в этом случае PSET изображает точку цветом рисования, выбранным по умолчанию (см. оператор COLOR), а PRESET – цветом фона. Поэтому условно принято считать, что оператор PSET предназначен для установки точки, а PRESET – для «стирания». Продемонстрируем это примером:
Код:

DIM x AS INTEGER
DIM y AS INTEGER
SCREEN 13
COLOR 0, 9
CLS
REM Рисуем закрашенный чёрный квадрат
FOR x = 10 TO 100
  FOR y = 10 TO 100
      PSET (x, y)
  NEXT
NEXT
SLEEP
REM "Стираем" квадрат путём изображения его же цветом фона
FOR x = 10 TO 100
  FOR y = 10 TO 100
      PRESET (x, y)
  NEXT
NEXT
SLEEP
Выше мы уже столкнулись с ещё одним графическим примитивом – линией. Линию, конечно же, можно вычертить последовательным отображением составляющих её точек… но на то FreeBASIC и язык высокого уровня – что бы программисту не надо было опускаться до таких тонкостей: для вычерчивания линий и прямоугольников в нём есть специальный оператор, так и называемый – «линия»:

LINE (start_x, start_y) – (end_x, end_y), цвет, BF, фактура

В скобках указываются координаты начала и конца отрезка или координаты левого верхнего и правого нижнего углов прямоугольника – при использовании параметра «В». Параметр «F» имеет смысл только в комбинации с параметром «B» - он обеспечивает закрашивание прямоугольника цветом контура. Параметр «фактура» применяется в том случае, когда линия (закрашенный прямоугольник) должна быть не «гладкого» цвета, а с неким «орнаментом» - например, штриховая. Изучим это на примере:
Код:

SCREEN 13
CLS
LINE (0, 100) - (319, 100), 2,,&hAAAA
SLEEP
В результате получим зелёную штриховую линию. Секрет «таинственного» значения последнего параметра в том, что шестнадцатиричная константа АААА эквивалентна цепочке битов 1010 1010 1010 1010, которая задаёт чередование цветов пикселов зелёного (цвет рисования) и чёрного (цвет фона) цветов.

Координаты концов отрезка могут задаваться частично и относительно. Если первая кордината отсутствует, то отрезок будет проведён к указанной точке из точки, где окончилось предыдущее рисование. Например, оператор:

LINE – (100, 100)

Проведёт отрезок из последней точки к точке с координатами (100, 100).
Если перед скобками указать модификатор STEP, то координаты в скобках будут трактоваться как приращения. Например, оператор:

LINE (100, 100) – STEP (10, -20)

Начертит линию из точки с координатами (100, 100) длиной 10 точек по осит Х и -20 пикселов по оси Y – т.е. в точку с координатами (110, 80). А оператор:

LINE STEP (10, -20) – (150, 170)

отложит от последней нарисованной точки 10 точек по оси Х вправо и 20 точек по оси Y влево (из-за знака «-») и из полученной точки начертит отрезок в точку с координатами (150, 170).

Согласитесь, если в каждой графической программе все эти операции программировать с помощью операторов PSET и PRESET, то за деревьями можно и не увидеть леса ;-)

В завершении разговора об операторе LINE продемонстрируем его практическое использование на примере программы построения гистограммы:
Код:

DIM AS INTEGER st = 6, sp = 36, in = 5
DIM AS INTEGER lg, lo, mx, my
DIM AS INTEGER i, k
DIM AS INTEGER cnt = (sp-st)/in+1
DIM AS INTEGER ra (100), da (cnt)

SCREEN 13
REM Подготавливаем данные для построения гистограммы
FOR i = 1 TO 100
  READ ra (i)
NEXT
FOR i = 1 TO 100
  FOR k = st TO sp STEP in
      IF ra (i) < k THEN
        da ((k-1)/in) = da ((k-1)/in)+1
        k = sp
      END IF
  NEXT
NEXT
FOR i = 1 TO cnt
  IF lg < da (i) THEN lg = da (i)
NEXT
my = 150/lg : mx = 299/sp ‘ фактор масштабирования
REM Вычерчиваем оси координат
LINE (0, 150) - (319, 150), 2
LINE (25, 0) - (25, 150), 2
FOR i = 0 TO sp STEP in
  LINE (25+i*mx, 150) - STEP (0,  10), 2
  LINE (25, 150-my*i) - STEP (-10, 0), 2
NEXT
PRESET (25, 150)  ‘ устанавливаем первую точку гистограммы
REM Построение гистограммы
FOR i = 0 TO cnt-1
  LINE - STEP (0, my*(da(i)-da(i+1))), 2
  LINE - STEP (mx*in, 0), 2
NEXT
LINE - STEP (0, my*da(cnt)), 2
SLEEP  ‘ Любуемся результатами ;-)

REM Исходные данные
DATA 1,2,3,4,7,8,8,9,9,10,6,7,8,11,12,12,13,13,14
DATA 14,15,15,12,13,12,14,15,16,16,16,16,16,16,17,18,19,20,17,17
DATA 16,17,17,17,18,19,20,20,21,22,23,24,25,21,21,22,22,22,22,23
DATA 21,21,22,26,26,27,28,28,29,29,27,28,29,31,32,33,34,351,2
DATA 6,10,8,11,12,13,16,17,18,22,23,24,25,26,27,28,31,32,33,3
Гистограмма получилась неказистая, но важен принцип, марафет всегда можно навести ;-)

Последний из основных графических примитивов – окружность. Для вычерчивания окружностей (а так же дуг, и элипсов) предназначен оператор

CIRCLE (x, y), радиус, цвет, начало, конец, сплюснутость, F

Первый параметр оператора задаёт точку, в которой находится центр окружности. Как и в операторе LINE, координаты центра можно задавать в явном и относительном виде. В последнем случае перед скобками должен присутствовать модификатор STEP и значения из скобок откладываются по тем же правилам от координат последней нарисованной точки. Например, оператор:

СIRCLE (160, 100), 30, 2

нарисует окружность зелёного цвета радиусом в 30 точек с центром в точке (100, 100).
Параметры начало и конец применяются при рисовании дуг и обозначают начало и конец дуги (в радианах). Параметр сплюснутость предназначен для рисования элипсов и их дуг и определяет отношение высоты фигуры к её ширине. Последний параметр «F» аналогичен одноимённому в операторе LINE – если он присутсвует, то рисуется не окружность, а круг, закрашенный в цвет контура.

Продемонстрируем сказанное несколькими простыми программами.
Код:

SCREEN 13
FOR i AS INTEGER = 1 TO 125
  CIRCLE (160+100*COS (i/20), 90+80*SIN (i/20)), 45-i/3, 1
NEXT
SLEEP
Получился «рог изобилия» ;-)
А теперь немного модифицируем эту программу – сделаем цвет составляющих «рог» окружностей величиной переменной:
Код:

SCREEN 13
FOR i AS INTEGER = 1 TO 125
  CIRCLE (160+100*COS (i/20), 90+80*SIN (i/20)), 45-i/3, ((i/5) MOD 4)
NEXT
SLEEP
Правда красивее получилось?
Продолжим программить…
Код:

CONST PI = 3.14158
DIM i AS INTEGER
DIM AS SINGLE x, y, st
SCREEN 1
FOR i = 15 TO 2 STEP -1
  x = 80*COS (PI/i)
  y = 80*SIN (PI/i)
  CIRCLE (160, 10+y), x, 3,,,.3
NEXT
st = y
FOR i = 10 TO 65 STEP 5
  x = 20/(i/15)
  CIRCLE (160, st+i), x, 3,,,.3
NEXT
st = st + i
FOR i = 2 TO 10
  x = 2*EXP (i/3)
  CIRCLE (160, st+i), x, 3,,,.3
NEXT
SLEEP
Получилась изящная рюмка (наверное этот пример мне вчерашний «День вина» навеял – государственный праздник Молдовы, традиционно проводимый во вторые выходные октября Wink Данный пример демонстрирует рисование элипсов – обратите внимание на последний параметр операторов CIRCLE в нём. Так как два параметра в середине списка нам не нужны сейчас, они пропущены, но разделяющие их запятые обязательно должны быть.

Но пора уж и об этих оставшихся параметрах поговорить. Четвёртый и пятый параметры, как уже было выше сказано, задают начало и конец дуги окружности в радианах. Продемонстрируем использование этих параметров на примере программы, рисующей простую круговую диаграмму:
Код:

CONST PI = 3.14158
SCREEN 13
CIRCLE (110, 100), 80, 1, (-2*PI), (-PI/3)
CIRCLE (110, 100), 80, 2, (-PI/3), (-3*PI/4)
CIRCLE (110, 100), 80, 3, (-3*PI/4), (-2*PI)
LOCATE 10, 25: PRINT "Materials"
LOCATE  3, 10: PRINT "Advertising"
LOCATE 18, 25: PRINT "Manufacturing"
LOCATE 25, 6  : PRINT "WIDGET Cost Factors"
SLEEP
Теперь модифицируем эту программу что бы познакомиться с ещё одним базовым графическим оператором языка FreeBASIC:
Код:

CONST PI = 3.14158
SCREEN 13
CIRCLE (110, 100), 80, 1, (-2*PI), (-PI/3)
PAINT (117, 95), 1, 1
CIRCLE (110, 100), 80, 2, (-PI/3), (-3*PI/4)
PAINT (110, 85), 2, 2
CIRCLE (110, 100), 80, 3, (-3*PI/4), (-2*PI)
PAINT (110, 115), 3, 3
LOCATE 10, 25: PRINT "Materials"
LOCATE  3, 10: PRINT "Advertising"
LOCATE 18, 25: PRINT "Manufacturing"
LOCATE 25, 6 : PRINT "WIDGET Cost Factors"
SLEEP
Теперь сектора диаграммы у нас получились раскрашенными. За счёт чего же? Что нового мы добавили? Ага, после каждого оператора CIRCLE появился какой-то оператор PAINT... Что ж это за «краска» такая??? Не в нём ли заковыка? Да, именно в нём:

PAINT (x, y), цвет, цвет_контура

Оператор закрашивает замкнутый контур внутри которого расположена точка с указанными координатами (как и прежде, эти координаты могут быть и относительными – тогда перед скобками должен стоять модификатор STEP) цветом «цвет». Если вокруг точки существуют несколько контуров, то требуемый можно уточнить по его цвету в последнем необязательном параметре.

Давайте ещё больше улучшим наш построитель диаграмм – добавим в него возможность менять количество секторов и «раздвигать» сектора:
Код:

CONST PI = 3.14158
DIM a AS STRING
DIM i AS INTEGER 
DIM num AS INTEGER
DIM tot AS SINGLE = 0
DIM AS SINGLE dx, dy, px, py
REM Ввод даных
CLS
LOCATE 1, 20 : PRINT "Pie chart"
LOCATE 10, 15: PRINT "Enter # of pie slices of Q to quit";: INPUT a
IF a = "q" OR a = "Q" THEN END ELSE num = VAL (a)
IF num = 0 THEN END
DIM AS SINGLE da(num), ra(num), cu(num)
CLS
FOR i = 1 TO num
  LOCATE 5, 1 : PRINT "Enter data for seg#";i;"=>"
  LOCATE 5, 25: INPUT da(i)
NEXT
REM Обработка данных
REM Вычисление центральных углов
REM Сумма центральных углов
FOR i = 1 TO num
  tot = tot + da(i)
NEXT
REM Относительные значения
FOR i = 1 TO num
  ra(i) = da(i)/tot
  cu(i) = ra(i)
NEXT
REM Сумма относительных значений
FOR i = 1 TO num
  cu(i) = cu(i-1)+cu(i)
NEXT
cu(0) = 1
REM Построение диаграммы
CLS
SCREEN 13
FOR i = 0 TO num-1
  REM Отступ секторов от центра на 5 точек
  dx = 5*COS(2*PI*(cu(i)+.5*ra(i+1)))
  dy = 5*SIN(2*PI*(cu(i)+.5*ra(i+1)))
  CIRCLE (130+dx, 100-dy), 95, (1+i MOD 3), (-cu(i)*2*PI), (-cu(i+1)*2*PI)
  REM Вычисление начальных точек для закраски секторов
  px = 25*COS(2*PI*(cu(i)+.5*ra(i+1)))
  py = 25*SIN(2*PI*(cu(i)+.5*ra(i+1)))
  CIRCLE (130, 100), 5, 2 ' Выделяем центр диаграмы
  PAINT (130+px, 100-py), (1+i MOD 3), (1+i MOD 3)
NEXT
SLEEP
Уфф… Диаграмы – вещь хорошая и в работе полезная, но не увлёкся ли я? Пора перейти к рассмотрению последнего из базовых графических операторов. Это даже не просто оператор, а целый язык графического программирования Wink Заинтриговал? Уверен, что да. Ну так вперёд!

justar

Сообщения : 135
Дата регистрации : 2008-05-12
Возраст : 43
Откуда : Кишинёв, Республика Молдоа

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Графические средства языка

Сообщение  justar в Вс Окт 19, 2008 9:57 am

Язык графических построений
Оператор DRAW применяется для вычерчивания линейных изображений сложных форм. Он имеет следующий синтаксис:

DRAW “чертёжные команды”

Просто? Да. Но не зря пословица говорит, что краткость – сестра таланта. «Чертёжные команды» - это параметр, представляющий собой строку символов, заключённую в кавычки. Совокупность таких команд называется «язык графических построений», по скольку спомощью команд этого языка можно получить на экране любую фигуру, не прибегая к другим графическим средствам.

Язык графическх построений включает в себя 15 команд и их модификаторы. Они позволяют рисовать отрезки прямых, окрашивать их, вращать отнисительно заданых точек, изменять их длину, закрашивать замкнутые области. В качестве параметров команд могут выступать константы и целочисленные (INTEGER) переменные.

Синтаксис всех команд одинаков: ...YZnn... Здесь «Y» -необязательный модификатор (есть не у всех команд), «Z» - собственно символ команды, «nn» - числовой параметр, которых в некоторых командах может быть несколько – тогда они разделяются запятой.

Познакомимся теперь с командами языка графических построений и их модификаторами.

Универсальная команда перемещения точки Команда М x, y задаёт отрезок прямой, проведённый из текущей точки в точку с указанными в команде координатами. Если параметры команды указаны со знаками «+» или «-», то они интерпретируются компилятором как приращения. Если перед символом команды добавить модификатор «В», то курсор будет перемещён в заданную точку без рисования. Обычно с такой команды «ВМ x,y» начинаются все скрипты на языке графических построений – что бы явным образом задать начальную точку рисунка.

Специальные команды перемещения точки. Очень часто линию необходимо провести в определённом направлении, например, вертикально вверх или вниз, по горизонтали, вправо или влево. Подобные построения выполняются с помощью набора специальных команд:
Un – вверх на n точек
Dn – вниз на n точек
Rn – вправо на n точек
Ln – влево на n точек
En – вверх и вправо на n точек
Fn – вниз и вправо на n точек
Gn – вниз и влево на n точек
Hn – вверх и влево на n точек

Любой команде перемещения может предшествовать модификатор «В» - в этом случае курсор перемещается без рисования, или «N» - в этом случае после вычерчивания отрезка курсор возвращается (без рисования) в предыдущую позицию.

Проиллюстрируем применение команд перемещения точки:
Код:

SCREEN 13
DRAW “BM 60,60 NU10 NE10 NR10 NF10 ND10 NG10 NL10 NH10”
Команды выбора цвета. Раскрашивание изображений производится с помощью двух чертёжных команд.

Первая из них, Cn, задаёт цвет всех точек и отрезков, которые рисуются следующими за ней чертёжными командами. Значение параметра – такое же, как и «цвет» во всех предыдущих графических операторах.

Команда P p, b закрашивает цветом «р» часть экрана вокруг текущей позиции курсора, ограниченную замкнутым контуром цвета «b» - т.е. это полный эквивалент оператора PAINT.

Для иллюстрации вышесказанного нарисуем на экране цветной домик:
Код:

SCREEN 13
DRAW “C3 U20 E20 F20 D20 L39”
DRAW “BM 170,90 P 2,3”
Команды вращения. У пытливого читателя уже должен родиться вопрос уже должен родиться вопрос: «А как быть, если отрезок надо провести под углом, отличным от 45 и 90 градусов? Неужели придётся высчитывать координаты и пользоваться универсальной командой?» Нет. Не придётся. В языке графических построений есть две чертёжные команды, которые осуществляют вращение отрезков.

Команда An поворачивает следующие за ней отрезки на n*90 градусов (нулевому углу соответствует отрезок, отложенный по горизонтали вправо, углы отсчитываются от него против часовой стрелки).

Команда TАn позволяет повернуть следующие за ней отрезки на произвольный угол в пределах -360…+360 градусов. Если угол отрицательный, вращение осуществляется по часовой стрелке, если положительный – против.

Команда масштабирования. Команда Sn определяет масштаб, согласно которому уменьшаются или увеличиваются длины отрезков.

Команда выполнения строки. Последняя из чертёжных команд имеет следующий формат: Х указатель на строковую переменную.

PS: В процессе написания главы с неприятным удивлением выяснил, что в отличии от старых Бейсиков, в FB оператор DRAW не поддерживает переменные в качестве аргументов команд. IMHO, это здорово снижает его полезность. Впрочем, это с лихвой компенсируется развитостью других графических инструментов языка.

justar

Сообщения : 135
Дата регистрации : 2008-05-12
Возраст : 43
Откуда : Кишинёв, Республика Молдоа

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Графические средства языка

Сообщение  justar в Вс Окт 19, 2008 9:58 am

Экранные окна и преобразования координат
Иногда необходимо получить на экране несколько изображений так, что бы их можно было строить и преобразовывать независимо друг от друга. Для этого введено понятие «экраное окно» - это выделенная внутри координатного пространства экрана область, в которой производятся все графические построения. Таких областей может быть несколько, при чём каждая из них действует как отдельный, независимый от других, экран. В частности, если заданные координаты выходят за пределы окна, но находятся в пределах экрана, изображение всё равно появится за пределами окна. Для задания экранного окна предназначен оператор

VIEW SCREEN (start_x, start_y) – (end_x, end_y), цвет, цвет_границы

Необязательный модификатор SCREEN задаёт режим вывода изображения, в котором координаты точек отсчитываются от границ полного экрана. Однако, если координаты части изображения выйдут за пределы заданного окна, эта часть изображения видна на экране не будет – что бы её увидеть надо передвинуть окно. Если модификатор SCREEN отсутсвует, координаты точек отсчитываются от границ окна. Оператр VIEW без параметров удаляет все созданные экранные окна и делает активным окном весь графический экран.

Оператор

WINDOW SCREEN (start_x, start_y) – (end_x, end_y)

производит вычисления, связанные с определением координат изображений, выводимых графическими примитивами. Если требуется вычертить рисунок, размеры которого превосходят размеры текущего графического экрана или экранного окна, его размеры перед выводом на экран надо так промасштабировать, что бы рисунок целиком поместился в прямоугольник экрана (экранного окна). Благодаря оператору WINDOW необходимость в таких расчётах отпадает. Программисту достаточно лишь указать предельные размеры объекта, а все остальные преобразования выполнит компилятор сам.

Параметры в скобках задают граничные допустимые значения координат но осям X и Y. Эти значения могут быть как положительными, так и отрицательными. В любом случае началом координат считается точка (0, 0). Если оператор применяется без параметров, то устанавливается стандартная координатная система с началом координат в левом верхнем углу и с граничными значениями, заданными номером графического режима (см. оператор SCREEN).

Существуют два варианта нестандартной системы координат. Если модификатор SCREEN опущен, то работа ведётся в обычной декартовой системе. Если он задан, то используется перевёрнутая декартовая система – в которой ось ординат направлена не снизу вверх, а сверху вниз.

Ознакомимся с работой этих двух операторов на примере следующей программы:
Код:

CONST PI = 3.14158
DIM i AS INTEGER

SCREEN 13, 0
COLOR 0,0
CLS
WINDOW (-318, -198) - (318, 198)

VIEW (1, 1) - (159, 98),, 1
LINE (-318, 0) - (318, 0), 3,, &hAAAA
LINE (0, 198) - (0, -198), 3,, &hAAAA
FOR i = -300 TO 300 STEP 2
  IF i = 0 THEN i = 2
  PSET (i, 150 * COS ((i * PI) / 75)), 2
NEXT

VIEW (1, 101) - (159, 198),, 2
LINE (-318, 0) - (318, 0), 3,, &hAAAA
LINE (0, 198) - (0, -198), 3,, &hAAAA
FOR i = -300 TO 300 STEP 2
  PSET (i, EXP (-i / 300) * 50 * SIN ((i * PI) / 75)), 2
NEXT

VIEW (162, 101) - (318, 198),, 3
LINE (-318, 0) - (318, 0), 3,, &hAAAA
LINE (0, 198) - (0, -198), 3,, &hAAAA
FOR i = -300 TO 300 STEP 2
  PSET (i, 50 * TAN ((i * PI) / 75)), 2
NEXT

VIEW (162, 1) - (318, 98),, 2
LINE (-318, 0) - (318, 0), 3,, &hAAAA
LINE (0, 198) - (0, -198), 3,, &hAAAA
FOR i = -300 TO 300 STEP 2
  PSET (i, 150 * SIN ((i * PI) / 75)), 2
NEXT
SLEEP

Картинки начинают двигаться
Нередко программе необходимо не только вывести на экран статический рисунок, но и заставить двигаться по экрану изображения или их части. Помню, в восьмидесятые годы прошлого века, учась в школе познакомился с очень крутым (по тем временам) японским учебным компьютером Ямаха-MSX, для которой фирма Микрософт написала весьма интересный диалект Бейсика – MSX-BASIC. Интересен он был в частности тем, что в нём предоставлялись программисту развитые средства для создания движущихся изображений. В основу метода было положено понятие «спрайта» - так назывались собственно движущиеся изображения. Язык имел операторы для создания спрайтов, вывода их в определённых координатах и автоматически отслеживал их наложение – ситуации, когда в одних и тех же координатах оказывалось два и более спрайтов. Очень удобно было на том языке писать двухмерные игры… однако у него был серьёзный, по нынешним понятиям, недостаток – спрайты задавались битовой маской, а потому были монохромные. Наверно поэтому в FreeBASIC и не были включены спрайтовые операторы. Однако, само понятие запомним…

Несмотря на отсутсвие механизма спрайтов в явном виде, в стандартной графической библиотеке FreeBASIC имеется достаточно средств для построения движущихся изображений.

В основу спрайтового метода FB положен не битовый образ спрайта, а «буфер изображения» (Image Buffer) – выделенная область памяти, в которой содержится изображение выводимого объекта в относительных координатах. При этом само изображение полноценное – его размеры и цветность ограниченны только параметраме выбранного видеорежима. Само изображение (спрайт) может быть как созданным в программе с помощью графических операторов FB, так и нарисовано в каком-нибудь внешнем графическом редакторе (или даже отсканировано или сфотографировано) и загружено в программу с диска…

Но прежде чем создавать спрайт необходимо создать буфер для него – т.е. выделить область памяти, которая будет использоваться только для хранения образа этого спрайта. В главе, посвящёной указателям, вы уже сталкивались с функциями выделения памяти ALLOCATE () и CALLOCATE (), осуществляющими поиск свободного участка памяти заданного размера и возвращающего указатель на его начало. В принципе, можно пользоваться и ими, однако возникает сложность правильного вычисления необходимого размера буфера, который зависит не только от размера изображения, но и от выбранного графического режима. Для того, что бы облегчить жизнь программиста, в языке FB есть специализированная надстройка надо функцией ALLOCATE ():

image_buffer = ImageCreate (ширина, высота, цвет)

Эта функция по заданной ширине и высоте спрайта и текущему видеорежиму вычисляет необходимый размер памяти, вызывает ALLOCATE (), передавая ей этот размер и присваивает переменной (в нашем примере – image_buffer) значение указателя на выделенную область, возвращённое функцией ALLOCATE (), или 0 пр ошибке. Переменная image_buffer должна быть предварительно определена следующим образом:

DIM image_buffer AS ANY PTR

Разумется, имя переменной может быть любым – «image_buffer» я выбрал просто для наглядности. Это обычный указатель, поэтому если в программе много спрайтов, их образы можно объединить в массив, например, описание:

DIM sprites (1 ТО 100) AS ANY PTR

задаёт массив указателей на 100 спрайтов.
Необязательный параметр «цвет» задаёт цвет, которым будет заполнен весь буфер сразу после его создания.

Для заполнения буфера спрайта можно воспользоваться несколькими способами. Самый простой из них заимствован языком FB из QB. Вначале надо на экране (или на невыводимой видеостранице) нарисовать это изображение любыми графическими средствами, а затем скопировать охватывающий изображение прямоугольник в буфер спрайта. Это делается оператором

GET image_buffer, STEP (start_x, start_y) – STEP (end_x, end_y)

Оператор GET сохраняет начиная с адреса *image_buffer часть экрана, ограниченного прямоугольником с координатами левого верхнего и правого нижнего углов, заданных в скобках (смысл необязательных модификаторов STEP перед скобками такой же, как и у оператора LINE).

Второй способ, существующий исключительно в языке FB, основан на опущенном прежде свойстве всех графических операторов языка – если самым первым параметром любого графического примитива (PSET, PRESET, LINE, CIRCLE, PAIN и DRAW) указать имя переменной – указателя на буфер спрайта, то изображение, формируемое этим оператором, будет выводиться не на экран, а в указанную область памяти. Например:

CIRCLE image_buffer, (32, 32), 28, RGB(255, 0, 0),,, 1.0, F

Третий способ предназначен для загрузки изображения в буфер спрайта с диска:

result = BLOAD (file_name, immage_buffer, palette_buffer)

Эта функция (существенное отличие от других диалектов Бейсика – в них BLOAD это оператор и не возвращает в программу ни каких значений!) загружает с диска файл изображения в формате .bmp в заданный буфер спрайта (если указатель на буфер отсутсвует или равен 0, то файл загружается в видеопамять). Необязательный параметр palette_buffer задаёт место для размещения палитры изображения. Если он равен нулю, то загружаемая палитра сразу становится системной, используемой по умолчанию. Если он отсутсвует, то палитра изображения не загружается, а используется текущая системная.

После загрузки файла функция возвращает 0 если загрузка прошла успешно или код ошибки в противном случае:

1 – неверный вызов функции. Может означать следующее:
- image_buffer не указывает на существующую область памяти
- image_buffer равен 0, но графический режим экрана не задан
- file_name указывает на неподдерживаемый формат файла
- загруженая палитра не совместима с выбранным графическим режимом

2 – файл не найден (file_name указывает на несуществующий файл)

3 – ошибка ввода/вывода при загрузке файла.

После того, как спрайт создан, его можно вывести на экран. Для этого предназначен оператор

PUT (x, y), image_buffer, метод

Этот оператор выводит спрайт на экран, начиная от точки с заданными координатами.
Параметр «метод» может принимать следующие значения:
PSET – точки спрайта копируются на экран без каких-либо изменений
PRESET – точки спрайта копируются на экран в негативе
TRANS - точки спрайта копируются на экран с загруженной в буфер палитрой
AND - при помещении точки спрайта на экран, выполняется «логическое И» её цвета с цветом точки, которую она замещает
OR - аналогично AND, но выполняется «логическое ИЛИ»
XOR - аналогично AND, но выполняется «логическое исключающее ИЛИ»

Последний метод наиболее применим для движения спрайта – повторное применение его в тех же координатах восстанавливает предыдущее содержимое, на которое был наложен спрайт («стирает» спрайт):
Код:

DIM i AS INTEGER

SCREENRES 320, 200, 32

REM Создаём спрайт под именем «img»
DIM img AS ANY PTR = ImageCreate( 32, 32, 0)
CIRCLE  img, (16, 16), 15, RGB(255, 255, 0),,, 1, F
CIRCLE  img, (10, 10), 3,  RGB(0, 0, 0),,, 2, F
CIRCLE  img, (23, 10), 3,  RGB(0, 0, 0),,, 2, f
CIRCLE  img, (16, 18), 10, RGB(0, 0, 0), 3.14, 6.28

REM Двигаем спрайт по экрану
FOR i = 0 TO 100
  PUT (10+i, 10+i), img, XOR
  SLEEP 5
  PUT (10+i, 10+i), img, XOR
NEXT

REM Уничтожаем спрайт и освобождаем память
ImageDestroy img
Вот мы и закончили рассмотрение стандартной графической библиотеки FreeBASICа.
По мимо этих, простых, но достаточно скудных по современным меркам средств (хотя и позволяющих сделать очень и очень многое), компилятор FB поддерживает разнообразные внешние графические библиотеки (GDI, GFX, DirectX, OpenGL), но разговор о каждой из них достоин отдельной главы.

justar

Сообщения : 135
Дата регистрации : 2008-05-12
Возраст : 43
Откуда : Кишинёв, Республика Молдоа

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Графические средства языка

Сообщение  justar в Вс Окт 19, 2008 9:59 am

Ну вот, за две недели работы кое-что вырисовалось... Жду замечаний и дополнений.

justar

Сообщения : 135
Дата регистрации : 2008-05-12
Возраст : 43
Откуда : Кишинёв, Республика Молдоа

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Графические средства языка

Сообщение  tux в Вс Окт 19, 2008 6:25 pm

Отличная статья, представляю скока ты ето писал
мда, помница тоже в школе рисовал елочки да снеговиков, дома на листке лайнов в пол тетради напишу, а потом на компе пол дня набирал, тож какойто интерпретатор бейсика стоял, и недайбог ошибиться одной циферкой и линия вылезет не в том месте))
Кстать, можно еще упомянуть об интегрированных в компилятор функциях работы с OpenGL, тоже достаточно быстро с их помощю мона писать полноценные графические приложения, но это наверно ужо какнить в другой статье.
avatar
tux

Сообщения : 365
Дата регистрации : 2008-04-06
Возраст : 29
Откуда : Сибирь

Посмотреть профиль http://tux.nsk.ru/

Вернуться к началу Перейти вниз

Re: Графические средства языка

Сообщение  justar в Вс Окт 19, 2008 9:29 pm

tux пишет:Отличная статья
Cпасибо
представляю скока ты ето писал
Две с половиной недели Wink
Кстать, можно еще упомянуть об интегрированных в компилятор функциях работы с OpenGL, тоже достаточно быстро с их помощю мона писать полноценные графические приложения, но это наверно ужо какнить в другой статье.
Я о них в заключении упомянул. Но они не интегрированны в компилятор - это ж внешняя библиотека. И о ней действительно нужна отдельная статья. Я не готов её писать... Сам разве что о простой графике на Виндовс-окнах могу написать. А вот с DirectX и OpenGL не работал никогда - поэтому ни чего о них написать не смогу... Sad

justar

Сообщения : 135
Дата регистрации : 2008-05-12
Возраст : 43
Откуда : Кишинёв, Республика Молдоа

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Графические средства языка

Сообщение  tux в Пн Окт 20, 2008 9:09 am

Я о них в заключении упомянул. Но они не интегрированны в компилятор
Да я имею ввиду функции создания окана сразу под OpenGL и вывода отрисованного без использования Апи, а напрямую из компилятора, допустим так
Код:
#include once "GL/gl.bi"
const GFX_OPENGL=&h02
screenres 640, 480, 32, GFX_OPENGL
glBegin GL_LINES
glVertex2i 30, 30
glVertex2i 300, 300
glEnd
flip
sleep
вроде так, тока проверить не могу, под линухом OpenGL найти немогу))
Иначе же (или сДиректИксом) пришлось бы вручную через апишки создавать окно, и отрисовывать опять же серез апишки
avatar
tux

Сообщения : 365
Дата регистрации : 2008-04-06
Возраст : 29
Откуда : Сибирь

Посмотреть профиль http://tux.nsk.ru/

Вернуться к началу Перейти вниз

Re: Графические средства языка

Сообщение  justar в Пн Окт 20, 2008 2:12 pm

tux пишет: я имею ввиду функции создания окана сразу под OpenGL и вывода отрисованного без использования Апи, а напрямую из компилятора
Идея понятна. Но, увы, я про OpenGL не знаю совершенно ничего :'( Может ты сам напишешь главу про него?

justar

Сообщения : 135
Дата регистрации : 2008-05-12
Возраст : 43
Откуда : Кишинёв, Республика Молдоа

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Графические средства языка

Сообщение  Спонсируемый контент


Спонсируемый контент


Вернуться к началу Перейти вниз

Предыдущая тема Следующая тема Вернуться к началу


 
Права доступа к этому форуму:
Вы не можете отвечать на сообщения