src.left=unionx;

 src.top=uniony;

 src.right=unionx+unionw;

 src.bottom=uniony+unionh;

 r=cursor_union->BltFast(0, 0, primsurf, &src, DDBLTFAST_WAIT);

 if (r!=DD_OK) {

  TRACE('Blt 1 failed ');

  CheckResult(r);

 }

 //------ Блиттинг 2: стирание старого курсора

 // во вспомогательном буфере ---------

 r=cursor_union->BltFast(oldcurx-unionx, oldcury-uniony, cursor_under, 0, DDBLTFAST_WAIT);

 if (r!=DD_OK) {

  TRACE('Blt 2 failed ');

  CheckResult(r);

 }

 //------ Блиттинг 3: сохранение области под новым курсором -----

 src.left=curx-unionx;

 src.top=cury-uniony;

 src.right=src.left+cursor_width;

 src.bottom=src.top+cursor_height;

 r=cursor_under->BltFast(0, 0, cursor_union, &src, DDBLTFAST_WAIT);

 if (r!=DD_OK) {

  TRACE('Blt 3 failed ');

  CheckResult(r);

 }

 //------ Блиттинг 4: рисование нового курсора

 // во вспомогательном буфере ---------

 r=cursor_union->BltFast(curx-unionx, cury-uniony, cursor, 0, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT);

 if (r!=DD_OK) {

  TRACE('Blt 4 failed ');

  CheckResult(r);

 }

 //------- Блиттинг 5: копирование вспомогательного буфера

 // на первичную поверхность --------

 src.left=0;

 src.top=0;

 src.right=unionw;

 src.bottom=unionh;

 r=primsurf->BltFast(unionx, uniony, cursor_union, &src, DDBLTFAST_WAIT);

 if (r!=DD_OK) {

  TRACE('Blt 5 failed ');

  CheckResult(r);

 }

 return TRUE;

}

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

Завершение приложения 

Осталось лишь поговорить о том, как завершается работа приложения. Эта тема неоднократно рассматривалась, и ее можно было бы пропустить, но для программы Cursor она важна из-за наличия дополнительного потока. Мы должны не только послать потоку ввода сигнал о завершении, но и проследить за тем, чтобы поток завершился до уничтожения объекта устройства мыши и поверхностей DirectDraw. В противном случае он может попытаться обратиться к мыши или обновить первичную поверхность после того, как соответствующие объекты перестанут существовать. Функция OnDestroy() выглядит так:

void CursorWin::OnDestroy() {

 critsection.Lock();

 DirectDrawWin::OnDestroy();

 if (mouse) {

  TRACE('mouse->Unacquire() ');

  mouse->Unacquire();

  TRACE('sending mouse quit message... ');

  mouse_event[quit_event_index]->SetEvent();

  Sleep(100);

  // дать потоку мыши возможность ответить

  TRACE('Releasing mouse pointer... ');

  mouse->Release(), mouse=0;

  delete mouse_event[mouse_event_index];

  delete mouse_event[quit_event_index];

 }

 if (keyboard) keyboard->Release(), keyboard=0;

 if (dinput) dinput->Release(), dinput=0;

 critsection.Unlock();

}

Когда MFC вызывает функцию OnDestroy(), основной поток заведомо не обновляет экран, потому что он занят выполнением этой функции. Тем не менее мы не знаем, не обновляется ли экран потоком ввода. Чтобы поток ввода закончил последнее обновление, мы блокируем критическую секцию.

Далее мы уступаем мышь. Устройство перестает генерировать новые события, которые заставили бы поток ввода попытаться снова обновить экран. Затем функция CEvent::SetEvent() посылает потоку ввода сигнал о завершении.

Нам осталось лишь освободить объекты DirectInput. Но перед тем, как это делать, мы вызываем функцию Sleep(), чтобы ненадолго приостановить основной поток. Поток ввода получает возможность обработать событие и завершиться. Наконец, мы освобождаем критическую секцию, и функция завершается — на этом работа приложения заканчивается.

Заключение 

Вывод курсора в DirectDraw — одна из тех досадных проблем, которые часто возникают перед разработчиками. Однако частичное обновление экрана и многопоточность пригодятся вам и в других ситуациях.

Глава 8. Воспроизведение видеороликов

Видеоролики встречаются в компьютерных играх уже несколько лет, но обычно лишь в простейших заставках или переходах между уровнями. Впрочем, иногда они образуют все содержание самой игры. Например, в игре Phantasmagoria фирмы Sierra On-Line видеотехнология применяется для наложения роликов с живыми актерами на интерьеры, сгенерированные компьютером. В результате возникает на удивление правдоподобный синтез реального и компьютерного окружения. В этом случае видео обеспечивает уровень реализма, которого было бы невозможно добиться с синтезированными актерами.

В этой главе мы узнаем, как считать AVI-файл и вывести его на поверхности DirectDraw. Хотя материал не ориентирован ни на какие конкретные цели, кроме простого воспроизведения видеороликов, он станет хорошей отправной точкой для самостоятельной работы с видео в DirectDraw. Изложенный материал воплощен в программе AviPlay, предназначенной для воспроизведения AVI-файлов.

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату