Графика (Работа с видестраницами и видеопамятью)

ScreenSet

Функция позволяет устанавливать рабочую и видимую страницу. Вы можете отображать на экране что-то одно, а в это время что-то рисовать на второй странице, потом нарисованную скопировать на экран, а на первой опять что-то отрисовывать. Получится эффект двойной буферизации, которая стала так популярна в графике. Двойная буферизация в значительной степени уменьшает мерцание.

Синтаксис:

ScreenSet [ work_page ] [, visible_page ]

  • work_page - рабочая страница
  • visible_page - видимая страница

Страницы имеют отсчет от 0. Если использовать функцию без параметров, то рисуется и отображается все на нулевой странице, что для анимации малоприемлемо. Если использовать только какой-то один  параметр, то втором параметре предполагается 0 страница.
Примеры с двойной буферизацией я покажу в обзоре следующей функции, а здесь просто пример из справки работы функции ScreenSet. Этот пример очень хорошо показывает ее работу:

'' 320x200x8, with 3 pages
Screen 13,,3

'' image for page #1
Screenset 1, 0
Cls
Circle( 160, 100 ), 90, 1 ,,,, f
Circle( 160, 100 ), 90, 15
Print "Press 2 to copy page #2 to visible page"
Print "Press escape to exit"

'' image for page #2
Screenset 2, 0
Cls
Line( 50, 50 )-( 270, 150 ), 2, bf
Line( 50, 50 )-( 270, 150 ), 15, b
Print "Press 1 to copy page #1 to visible page"
Print "Press escape to exit"

'' page #0 is the visible page
Screenset 0, 0
Cls
Print "Press 1 to copy page #1 to visible page"
Print "Press 2 to copy page #2 to visible page"
Print "Press escape to exit"

Dim k As String

Do
    k = Inkey
    Select Case k
        Case Chr(27)
            Exit Do
        Case "1"
            Screenset 0, 1
        Case "2"
            Screenset 0, 2
    End Select
    Sleep 25
Loop


В примере используются три видеостраницы, далее последовательно отрисовываются. Самая последняя страница устанавливается видимой по умолчанию. Далее в цикле при нажатии на клавиши 1 или 2 , устанавливается видимой 1 или 2 страница. Конечно правильно в условном операторе вместо ScreenSet использовать Pcopy , и в справке так и сделано, но чисто для понимания я решил изменить код. В принципе для этой задачи большой производительности не нужно.

 

ScreenCopy = PCopy = Flip

Эти три функции абсолютно одинакового можно использовать как для GFX , так и для OpenGL. Просто привычнее, что в OpenGL используют Flip. Данные функции копируют содержимое одной видеостраницы в другую. Кстати эта операция выполняется значительно быстрее, чем переключение страниц в прошлом примере. ScreenSet нужен лишь для переключения страниц под нужную операцию, а всю рутину выполняет PCopy.

Синтаксис:

Flip [ frompage ] [, topage ]

  • frompage - копируемая страница
  • topage - страница куда копировать

Если функция вызывается без параметров, то она берет установленные правила функцией ScreenSet. Если указывается какой-то один параметр, то во втором параметре предполагается нулевая страница. Для того, чтобы реально понять разницу, между выводом графики с двойной буферизацией и простым выводом , который был использован в прошлой статье "Координаты графических областей" , я взял один небольшой пример из справки и записал его двумя способами.

Вот такой подход рисования я думаю никого не устроит:

Screen 13
Color ,15
Dim x As Integer
x = -40

Do
    Cls
    Paint(20,20),2
    Line (x, 80)-(x + 39, 119), 4, BF
    x = x + 1
    If (x > 319) Then x = -40
    Sleep(10)
Loop While Inkey = ""

А вот этот же пример только с двойной буферизацией:

Screen 13,,2
Color ,15
Dim x As Integer
x = -40
Screenset 1
Do
    Cls
    Paint(20,20),2
    Line (x, 80)-(x + 39, 119), 4, BF
    x = x + 1
    If (x > 319) Then x = -40
    Sleep(10)
    Pcopy
Loop While Inkey = ""


Надеюсь разницу заметили.

 

ScreenLock и ScreenUnLock

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

ScreenLock - для запирания экрана
ScreenUnLock - для отпирания экрана

Принцип:

  • Запираем экран
  • Рисуем
  • Отпираем экран

Разработчики FreeBasic настоятельно советуют во время запирания экрана, не производить никаких лишних действий помимо рисования, то есть все подсчеты нужно вынести за рамки блока: ScreenLock  -  ScreenUnLock . И уж тем более не рекомендуется делать заведомые паузы.

У функции ScreenUnLock есть два параметра, но что-то я не смог получить никакого эффекта от их использования. Скорее всего разработчики их просто отключили...  По сути где не встречал, обе функции используются без параметров.

Пример:

Screen 13
Color ,15
Dim x As Integer
x = -40
Do
     Screenlock
    Cls
    Paint(20,20),2
    Line (x, 80)-(x + 39, 119), 4, BF
    Screenunlock
    x = x + 1
    If (x > 319) Then x = -40
    Sleep(10)
Loop While Inkey = ""

 

ScreenPtr

Данная функция позволяет получать доступ для чтения и записи видеобуфера страницы. Этодает возможность получить доступ к каждому пикселю видеобуфера. 

Пример из справки (вырезал все лишнее) :

Dim As Integer w, h, pitch
Screenres 256, 256, 32
Screeninfo w,h,,,pitch
Dim buffer As Any Ptr = Screenptr()

For y As Integer = 0 To h - 1
    Dim As Uinteger Ptr pixel = buffer
    For x As Integer = 0 To w - 1
        *pixel = Rgb(x, 6, y)
        pixel += 1
    Next x
    buffer += pitch
Next y
Sleep


В примере получаем указатель на страницу видеобуфера. Внешний цикл проходит по всем строкам страницы. Внутренний по всем пикселям каждой строки. В каждый пиксель пишется определенное цветовое значение с помощью макроса RGB.

Этой статьей я завершаю главу про графику. Всего доброго!

содержание | назад | вперед