Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ИГС / IGS_2014-2015 / Lab_02 / labor_02pm.doc
Скачиваний:
9
Добавлен:
17.04.2018
Размер:
699.9 Кб
Скачать

Графические вставки из bmp-файлов в win программах в режиме работы с оперативной памятью.

Возьмем за основу программу mov05.cpp. В этой программе уберем движение стрелки, уберем фон в виде зеленого эллипса, добавим фон в виде зеленого поля и голубого неба изbmp-файла. Новую программу поместим в файлmov08.cpp. Работа программыmov08.cppбудет во многом похожа на работу программыmov07.cpp. Но будут свои особенности, на которые обратим внимание.

В программе mov05.cppзадержка в движении графических объектов осуществляется с помощью системного таймера. В функцииMove_OnTimer(),которая обрабатывает сообщения от таймера, работа построена следующим образом.

Создается контекст памяти, совместимый с контекстом экрана.

Растровое изображение, в виде битовой караты, загружается из ресурса в память.

Битовая карта связывается с контекстом памяти.

Выполняется рисование графических объектов в памяти на битовой карте. По сути дела рисование происходит на фоне, взятом из bmp-файла.

После этого изображение из контекста памяти копируется в контекст экрана с помощью функции BitBlt().

Затем все повторяется как в программе mov05.cpp. Ниже приводится измененный код функцииMove_OnTimer().

//функция обрабатывает сообщение WM_TIMER

void Move_OnTimer(HWND hwnd)

{

//получаем идентификатор контекста экрана

HDC hdcWin = GetDC(hwnd);

//создаем контекст памяти hdcMem, совместимый с контекстом экрана hdc

HDC hdcMem = CreateCompatibleDC(hdcWin);

//загружаем в память bitmap-ресурс из модуля exe-файла

//hInstApp - идентификатор экзепляра приложения

//"BitmapShip" - идентификатор bitmap-ресурса (в файле ресурсов)

//hBitmap - идентификатор загруженного bitmap-ресурса

HBITMAP hBitmap = LoadBitmap(hInstApp, "BitmapField");

//выбираем bitmap-объект hBitmap в контекст памяти hdcMem

HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMem, hBitmap);

tP += dtP;

dtP *= 0.99115;

xP2 = TrajP(tP).x;

yP2 = TrajP(tP).y;

fiP2 =atan2l(yP2-yP1,xP2-xP1);

//рисуем фигуру в точке (x2, y2)

TracP(hdcMem, tP, dtP);

Plain(hdcMem,PtP,7,xP1,yP1,xP2,yP2,fiP1,fiP2,kxP,kyP);

xP1 = xP2; yP1 = yP2; fiP1 = fiP2;

//копируем изображение из контекста памяти hdcMem в контекст экрана hdc

BitBlt(hdcWin, nLeft,mTop, nRight-nLeft, mBottom-mTop, hdcMem, 0, 0, SRCCOPY);

DeleteObject(hBitmap); //убираем растровое изображение из памяти

SelectObject(hdcMem, hBitmapOld); //востанавливаем контекст памяти

DeleteDC(hdcMem); //убираем контекст памяти

ReleaseDC(hwnd,hdcWin); //освобождаем контекст экрана

}

Компилируем, запускаем программу mov08.exe, и результат работы этой программы будет таким же, как и на Рис.35. Правда качество изображения будет несравненно выше. Кроме того, скорость работыWINпрограммы значительно выше, чем уDOSпрограммы.

Рис. 37.

Результат работы программы mov08.cpp.

Перемещение по экрану графических вставок из bmp-файлов в dos программах.

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

Возьмем за основу программу mov08DOS.cpp. Новую программу назовемmov09DOS. Изображение изbmp-файла разбиваем на небольшие блоки и помещаем в оперативную память. Это можно сделать с помощью конструктора классаScreenMemory. Приведем соответствующую строчку кода.

//копируем изображение в оперативную память по блокам 10x10

ScreenMemory ScMem(10,10,0,0,640,350);

Здесь размер элементарного блока выбран 1010 пикселей. Внизу на условной схеме элементарные блоки памяти это маленькие квадратики. Заметим, что схема расположения блоков в оперативной памяти соответствует расположению изображения на экране.

Теперь берем блок памяти, составленный из нескольких элементарных блоков. На схеме этот блок слева обведен жирной линией. Затем этот блок изображения, надо вывести в какое то место на экране. Новое положение блока изображения показано на схеме в виде прямоугольника, сдвинутого на вектор. Заметим, что новое положение блока не обязано точно ложиться на сетку элементарных блоков.

Для осуществления указанной операции добавим в класс ScreenMemoryеще одну член-функцию (метод класса).

//выводим блок изображение на экран

void ViewScreenLock(int i0, int j0, int nx, int ny, int x, int y);

Здесь i0, j0 – координаты левого верхнего угла, выделенного блока на сетке элементарных блоков. Для случая показанного на схеме эти координаты равныi0=0, j0=1. Далее параметрыnx, ny– это размеры блока по горизонтали и вертикали на сетке элементарных блоков. Для случая показанного на схеме эти размеры равны nx=2, ny=3. Наконец, параметрыx, y– это координаты левого верхнего угла, выделенного блока в новом положении, на растровой сетке. Для случая показанного на схеме эти координаты равныx=52, y=32пикселей.

Ниже приводится код этой функции.

//функция выводит блок изображения из памяти на экран

void ScreenMemory::ViewScreenLock(int i0, int j0,

int nx, int ny, int x, int y)

{

int dx = x - xp[i0], dy = y - yp[j0];

for(int j=j0; j<j0+ny; j++)

for( int i=i0; i<i0+nx; i++)

putimage(dx+xp[i], dy+yp[j], saucer[i][j], COPY_PUT);

}

Для примера будем моделировать движение вагона поезда. Пассажир будет находиться перед открытым окном вагона, за которым проплывают поля.

Поэтому нужно выделить блок растрового изображения размером с окно. Этот блок надо выбирать из разных участков картины и помещать все время в то место экрана, где будет находиться окно. Ниже показан фрагмент кода моделирующего движение растрового изображения за окном.

//копируем блок изображения размером hx,hy из памяти на экран

ScMem.ViewScreenLock(ix,10,hx,hy,xn1,yn1);

ix++;

if(ix+hx>ScMem.xBlk-1)

ix = 0;

Здесь индекс ixбежит по сетке изображения в памяти от левой границы изображения до правой границы изображения. Когда блок изображения добегает до правой границы растрового изображения, то этот блок прыжком переносится к левой границе изображения. Этому соответствует условиеix = 0.

Добавим в программу статический объект – окно вагона. Для этого введем функциюWindowWagon()которая рисует это окно и некоторые детали вагона.

Добавим также динамический объект – занавеску на окне вагона. Занавеска колыхается при движении вагона. Аффинные преобразования над занавеской не совершаются. Просто углы занавески меняют свое положение по определенным законам с течением времени. Движение занавески описывается функциейCurtain().

Ниже приводится код этой функции.

//рисует занавеску по вершинам Pt

void Curtain( Point *Pt, int N, double t)

{

Pt[2].x = PtC0[2].x + 0.5*sin(3*t);

Pt[3].y = PtC0[3].y + 0.7*cos(2.5*t);

Pt[4].x = PtC0[4].x - 0.3*sin(t);

Pt[4].y = PtC0[4].y + 0.3*sin(t);

int Poly[12];

for(int i=0; i<2*N; i++)

if((i % 2) == 0)

Poly[i] = xn(Pt[i/2].x);

else

Poly[i] = ym(Pt[i/2].y);

setlinestyle(SOLID_LINE,0,1);

setcolor(14);

setfillstyle(1, 15);

fillpoly(N,Poly);

moveto(xn(Pt[0].x),ym(Pt[0].y));

lineto(xn(Pt[3].x),ym(Pt[3].y));

}

Компилируем, запускаем программу mov09DOS.exe, и результат работы этой программы показан на Рис.38.

Рис. 38.

Результат работы программы mov09DOS.cpp.

Соседние файлы в папке Lab_02