VR
Virtual Reality On-line   Журнал
Новости   |     Журнал    |    Хаkер    |     Магазин   |   Проекты
[   Вход    ]
[Kарта сайтa]

[ Download  ]
[  Конкурс  ]
[ Анекдоты  ]
[  Ссылки   ]
[  Реклама  ]
[ Почтальон ]
[ О проекте ]






TopList
Геймер
Рисование картинок
:

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

Хватит болтовни, давай приступим к программированию. Посмотри на рисунок 1. Сегодня ты получишь вот такую прогу.

Рис.1 Пример работы проги

Для облегчения проги я использовал библиотеку DDUtils1 . Её ты можешь взять (если ещё не сделал этого) в разделе "Полезности".

С чего всё началось? А началось всё с того, что я объявил ещё одну поверхность. Теперь у меня в программе три поверхности: две переключающиеся и одна для хранения BMP файла.

После этого, в конце процедуры StartDX я вызываю процедурку GetPicture.

procedure TForm1.GetPicture;
begin
FSecondSurface := DDLoadBitmap(FDirectDraw, '1.bmp', FRect.Left, FRect.Top);
 if(FSecondSurface = nil) then
  begin
   InitFail();
   Exit;
  end;
end;

DDLoadBitmap загружает картинку в поверхность FSecondSurface. Похожая процедура есть в DDUtils1, но я решил переписать её внеся небольшие изменения. Давай посмотрим, что в ней происходит:

function  DDLoadBitmap(DirectDraw      : IDirectDraw2;
 const BitmapName: string;var  Width, Height: integer):IDirectDrawSurface;
var
  Bitmap     : HBitmap;
  BM         : Windows.TBitmap;
  SurfaceDesc: TDDSurfaceDesc;
Begin
 // Пытаемся загрузить картинку
 Bitmap:= LoadImage(0, PChar(BitmapName), IMAGE_BITMAP, Width, Height,
                           LR_LOADFROMFILE or LR_CREATEDIBSECTION);
// Проверяем, получилось ли это?
 if Bitmap = 0 then
  Raise Exception.CreateFmt('Unable to load bitmap %s', [ BitmapName ]);

//Вытаскиваем из картинки растровые данные
 GetObject(Bitmap, SizeOf(BM), @BM);

//Подготавливаем временную поверхность
 FillChar(SurfaceDesc, SizeOf(SurfaceDesc), 0);
 with SurfaceDesc do
  begin
   dwSize:= SizeOf(SurfaceDesc);
   dwFlags:= DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH;
   ddsCaps.dwCaps:= DDSCAPS_OFFSCREENPLAIN;
   dwWidth:= BM.bmWidth;
   dwHeight:= BM.bmHeight;
  end;
// Создаём поверхность
 if DirectDraw.CreateSurface(SurfaceDesc, Result, NIL) <> DD_OK then
  Raise Exception.Create('CreateSurface failed');
//Копируем картинку на поверхность с помощью процедуры из DDUtils1
 DDCopyBitmap(Result, Bitmap, 0, 0, 0, 0);
 Width:=BM.bmWidth;
 Height:=BM.bmHeight;
 if Bitmap <> 0 then DeleteObject(Bitmap);
end;

Здесь ничего сложного нет, ты можешь сам разобраться. Если тебе лень разбираться, то просто используй эту функцию. В качестве параметров Width и Height возвращается ширина и высота загруженной картинки. Вот и всё. Картинка загружена, переходим к рисованию.

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

function BltFast(
dwX, dwY: DWORD; // Левая и верхняя позиция на результирующей поверхности.
lpDDSrcSurface: IDirectDrawSurface;// Исходная поверхность из  неё будет копироваться.
const lpSrcRect: TRect; // Область исходной поверхности, которую надо скопировать
dwTrans: DWORD): HResult; stdcall; 

Эта функция относится к объекту поверхности, поэтому вызывать её надо как ResultSurfase.BltFast(…). Копирование происходит на поверхность ResultSurfase.

dwTrans - это флаги, которые определяют параметры копирования.

  • DDBLTFAST_DESTCOLORKEY - Прозрачное копирование. В качестве прозрачного цвета используется colorkey результирующей поверхности.
  • DDBLTFAST_NOCOLORKEY - Копирование без прозрачности.
  • DDBLTFAST_SRCCOLORKEY - Прозрачное копирование. В качестве прозрачного цвета используется colorkey источника.
  • DDBLTFAST_WAIT - Если поверхность занята, то функция не генерирует ошибку, а ждёт освобождения поверхности и потом рисует.

Ещё одна интересная функция в программе - InitFail, которая вызывается, если не удалось загрузить картинку:

procedure TForm1.InitFail;
begin
 if FDirectDraw <> nil then
  begin
   FDirectDraw.FlipToGDISurface;
   MessageBox(Handle, 'DirectDraw Init FAILED', '', MB_OK );
   Close();
  end;
end;

Всё в этой функции тебе знакомо, я просто хотел обратить твоё внимание на то, что функция MessageBox вызывается после FDirectDraw.FlipToGDISurface. Зачем это? Я уже говорил в прошлых статьях, что FDirectDraw.FlipToGDISurface передает управление выводом на экран GDI, и после этого я вывожу сообщение. Если не передать управление на GDI, то сообщение не будет видно, потому что DirectDraw не может отобразить функцию MessageBox.

Вот и всё. Сегодня ты научился рисовать растровые данные на поверхности. Это уже половина необходимой информации по DirectDraw для создания игр.

Удачи тебе, до встречи в следующем номере.

 Исходники примера забирай здесь


Design by FMk group ©
Copyright©: Horrific aka Флёнов Михаил ©