DirectX for C++ Builder
Там же смотреть DOWNLOADS
Главная страница
Инструкции
-=-
|
-=-
Image1.Transparent := True; |
Image1.Picture.Bitmap.TransparentMode:= tmFixed; |
Image1.Picture.Bitmap.Width := Image1.ClientWidth; |
Image1.Picture.Bitmap.Height := Image1.ClientHeight; |
Image1.Picture.Bitmap.PixelFormat := pf32bit; |
Image1.Picture.Bitmap.Transparent := True; |
Image1.Picture.Bitmap.TransparentColor := clWhite; |
Form1.DoubleBuffered := True; |
OpenGL Tutorials http://nehe.gamedev.net/
C++ Builder DirectX
http://www.clootie.ru/cbuilder/index.html
Bitmap Functions
http://msdn.microsoft.com/en-us/library/dd183385%28v=VS.85%29.aspx
ROPCODES:
http://msdn.microsoft.com/en-us/library/aa928169.aspx
DWORD MAKEROP4( DWORD fore, DWORD back );
http://forums.randi.org/archive/index.php/t-57654.html
Example using TransparentBlt. I paint the background black, and use white as my transparent color:
case WM_PAINT: {
hdc = BeginPaint(hWnd, &ps);
HBITMAP foo = LoadBitmap (hInst, MAKEINTRESOURCE (IDB_BITMAP1));
HDC memDC = CreateCompatibleDC (hdc);
int save = SaveDC (memDC);
int savedc = SaveDC (hdc);
SelectObject (hdc, GetStockObject (BLACK_BRUSH));
Rectangle (hdc, 0, 0, 500, 500);
SelectObject (memDC, foo);
// BitBlt (hdc, 100, 120, 48, 48, memDC, 0, 0, SRCCOPY);
TransparentBlt (hdc, 100, 120, 48, 48, memDC, 0, 0, 48, 48, RGB (255, 255, 255));
RestoreDC (memDC, save);
RestoreDC (hdc, savedc);
EndPaint(hWnd, &ps);
DeleteObject (foo);
}
break;
Спрайты:
http://reinerstileset.4players.de/vehiclesE.html
http://www.animationfactory.com/en/
ссылки - http://plg.lrn.ru/index.php?sub=links&sort=2
http://www.panelmonkey.org/category.php?id=2
Способы анимации спрайтов (очень полезная ссылка):
http://delphiforfun.org/programs/Delphi_Techniques/animation.htm
Прога:
http://gmakers.ru/index.php?board=51.0
http://www.compdoc.ru/prog/builder/builder/7.shtml
http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Graphics_TCopyMode.html
http://docwiki.embarcadero.com/CodeExamples/en/BrushCopy_%28C%2B%2B%29
TheImage->Canvas->CopyMode = cmSrcInvert;
TheImage->Canvas->Draw(0, 0, OverlayImage.get());
TheImage->Canvas->CopyMode = cmSrcCopy;
if (ShowText == true) PaintAsText(TheImage.get(), PaintTRect);
Canvas->CopyMode = cmSrcCopy;
Canvas->Draw(0, 0, TheImage.get());
http://delphiworld.narod.ru/base/sprites_work.html
======================================================================
Description
==================================![]() | |||||||
| |||||||
Проект Delphi World © Выпуск 2002 - 2004 Автор проекта: ___Nikolay |
======================================================================
Description
TCopyMode values describe how to combine the colors of a source bitmap and a destination bitmap.
The Windows unit defines the following constants for TCopyMode values:
Value | Meaning |
Fills the destination rectangle on the canvas with black. | |
Inverts the image on the canvas and ignores the source. | |
Combines the image on the canvas and the source bitmap by using the Boolean AND operator. | |
Combines the inverted source bitmap with the image on the canvas by using the Boolean OR operator. | |
Copies the inverted source bitmap to the canvas. | |
Combines the image on the canvas and the source bitmap by using the Boolean OR operator, and inverts the result. | |
Copies the source pattern to the canvas. | |
Combines the source pattern with the image on the canvas using the Boolean XOR operator | |
Combines the inverted source bitmap with the source pattern by using the Boolean OR operator. Combines the result of this operation with the image on the canvas by using the Boolean OR operator. | |
Combines the image on the canvas and source bitmap by using the Boolean AND operator. | |
Copies the source bitmap to the canvas. | |
Inverts the image on the canvas and combines the result with the source bitmap by using the Boolean AND operator. | |
Combines the image on the canvas and the source bitmap by using the Boolean XOR operator. | |
Combines the image on the canvas and the source bitmap by using the Boolean OR operator. | |
Fills the destination rectangle on the canvas with white. |
Программный модуль
К файлу модуля Unit1.h (Листинг 7.5) добавлено описание структуры FigureType, включающей позицию (X,Y) , смещение (DX,DY) фигуры и номер объекта спрайта (SD); а в секции public класса формы объявлены четыре переменные размеров изображений, две фигуры Fig [2] и соответствующие им две пары спрайтов Sprite [4]. Класс SpriteClass и его методы определены в файлах Sprite.h и Sprite.cpp, соответственно.
ttifndef UnitlH
#define UnitlH
#include
#include
#include
typedef struct { int X, Y, DX, DY, SD; } FigureType;
class TFormI : public TForm (
_published: // IDE-managed Components TPaintBox *PaintBox;
TImage *DrawBox;
TImage *Background;
TImage *Figures;
TTimer *Timerl;
TPanel * Panel 1;
TSpeedButton *SpeedButtonl;
TSpeedButton *SpeedButton2;
TSpeedButton *SpeedButton3;
TSpinEdit *SpinEditl;
TOpenDialog *OpenDialog;
void _fastcall TimerlTimer(TObject * Sender);
void _fastcall SpinEditlKeyUp(TObject *Sender, WORD &Key, TShiftState Shift);
void _fastcall SpinEditlKeyDown(TObject * Sender,
WORD &Key, TShiftState Shifts-void_fastcall SpeedButtonlClick(TObject *Sender) ;
void_fastcall SpeedButton2Click(TObject * Sender);
void_fastcall SpeedButton3Click(TObject * Sender);
private: // User declarations public: // User declarations _fastcall TFormI(TComponent* Owner);
int W, H, w, h;
FigureType Fig[2];
SpriteClass Sprite[4];
};
extern TFormI *Forml;
#endif
Листинг 7.5. Содержание файла Unii1.h.
Файл модуля Unit1.cpp (Листинг 7.6) содержит 5 обработчиков событий от нажатия кнопок управления и обработчик события таймера.
//-_---------_____________-___-_-----__-____________________-
^include
#pragma hdrstop
#include "Unitl.h"
#pragma link "sampreg"
#pragma resource "*.dfm" TFormI *Forml;
//----------------——--——--—------———------—-----------
_fastcall TFormI::TFormI(TComponent* Owner) : TForm(Owner) ( // Конструктор формы устанавливает размеры по умолчанию W = Н = 400; w = h =61;
} //----------------------------------------------------------
void_fastcall TFormI::SpeedButtonlClick(TObject *Sender) { if (OpenDialog->Execute())
{ // Открыть файл изображения фона
Background->Picture->LoadFromFile(OpenDialog->FileName) ;
W = Background->Picture->Width;
H = Background->Picture->Height;
}
} //----—----------——-------—-——---—-—-—-------------
void_fastcall TFormI::SpeedButton2Click(TObject *Sender) { if (OpenDialog->Execute())
{ // Открыть файл изображения фигур
Figures->Picture->LoadFromFile(OpenDialog->FileName);
w = (Figures->Picture->Width)/6;
h = Figures->Picture->Height;
//______---------------------------------------------------
void_fastcall TFormI::SpeedButton3Click(TObject *Sender)
{ // Инициализировать поля структуры обеих фигур Fig[0].X = W/4; Fig[l].X = 3*W/4;
Fig[0].Y = H/4; Fig[l].Y = 3*H/4;
Fig[0].DX = 1; Fig[l].DX = -1;
Fig[0].DY = 1; Fig[l].DY = -1;
Fig[0].SD = 0; Fig[l].SD = 0;
// Подготовить экземпляры спрайта
Sprite[0].SetSprite(Figures->Canvas, 0,0, 4*w,0, w,h);
Sprite[1].SetSprite(Figures->Canvas, 2*w,0, 4*w,0, w,h);
Sprite[2].SetSprite(Figures->Canvas, w,0, 5*w,0, w,h);
Sprite[3].SetSprite(Figures->Canvas, 3*w,0, 5*w,0, w,h) ;
Timerl->Enabled = true;
}
void _fastcall TFormI::SpinEditlKeyUp(TObject *Sender,
WORD &Key, TShiftState Shift) { Timerl->Interval++; } void _fastcall TFormI::SpinEditlKeyDown(TObject *Sender,
WORD &Key, TShiftState Shift) { Timerl->Interval--; } //-.____-_-_-_-_.....____.__________________________________
int Shift = 0; // переменная прокрутки фона void _fastcall TFormI::TimerlTimer(TObject *Sender) ( // Сместить фигуры в пределах периметра
Fig[0].X += Fig[0].DX; Fig[0].Y += Fig[0].DY;
if (Fig[0].X > (W/2-w)) Fig[0].DX = -1;
if (Fig[0].X < 20) Fig[0].DX = 1;
if (Fig[0].Y > (H-2*h)) Fig[0].DY = -1;
if (Fig[0].Y < 20) Fig[0].DY = 1 ;
Fig[l].X += Fig[l].DX; Fig[l].Y += Pig[l].DY;
if (Fig[l].X > (W-w)) Fig[l].DX = -1;
if (Fig[l].X < (W/2+w)) Fig[l].DX = 1;
if (Fig[l].Y > (H-h)) Fig[l].DY = -1;
if (Fig[l].Y < 30) Fig[l].DY = 1 ;
// Оживить фигуры, переключая экземпляр спрайта
Fig[0].SD = (Fig[0].SD == 0) ? 2 : 0;
Fig[l].SD = (Fig[l].SD == 1) ? 3 : 1 ;
// Нарисовать фон и сдвинуть его влево
if (Shift == 0)
{ DrawBox->Canvas->CopyMode = cmSrcCopy;
DrawBox->Canvas->CopyRect(Rect(О, О, W, H),
Background->Canvas, Rect(0, 0, W, H));
}
else
{ DrawBox->Canvas->CopyMod^s = cmSrcCopy;
DrawBox->Canvas->CopyRect(Rect(0, 0, W-Shift, H),
Background->Canvas, Rect(Shift, 0, W, H) ) ;
DrawBox->Canvas->CopyRect(Rect(W-Shift, 0, W, H),
Background->Canvas, Rect(0, 0, Shift, H)) ;
}
Shift += 2;
if (Shift >= W) Shift -= W;
// Нарисовать фигуры на канве внеэкранного битового образа
Sprite[Fig[0].SD].Draw(DrawBox->Canvas,Fig[0].X, Fig[0].Y) ;
Sprite[Fig[l].SD].Draw(DrawBox->Canvas,Fig[1].X, Fig[l].Y) ;
// Скопировать изображение на экран
PaintBox->Canvas->CopyMode = cmSrcCopy;
PaintBox->Canvas->CopyRect(Rect(0, 0, W, H),
DrawBox->Canvas, Rect(0, 0, W, H)) ;
}
Листинг 7 6 Содержание файла Unit1 cpp.
Быстрые кнопки компонент TSpeedButton служат для управления программой. Первая кнопка открывает и загружает объект Background класса TImage из файла с изображением фона (размером w на H). Вторая кнопка открывает и загружает объект Figures класса TImage из файла с изображениями фигур (размером w на h каждая).
Третья кнопка устанавливает фигуры в начальные позиции и подготавливает объекты спрайта посредством обращении к методу SetSprite., а затем запускает таймер.
Нажатие кнопок компоненты редактирования TSpinEdit вызывает увеличение или уменьшение на единицу значения интервала таймера (по умолчанию устанавливается значение 40, соответствующее кадровой частоте 1/25 сек).
Ядром приложения является обработчик события OnTimer объекта Timerl. Первый блок кода реакции на прерывание от таймера отвечает за перемещение фигур, изменяя направление движения всякий раз, когда они "утыкаются" в фиксированные границы отведенного периметра. Рис. 7.3 изображает структуру канвы объектов DrawBox и PaintBox.

Рис. 7.3. Структура канвы для рисования движущихся фигур.
Следующий блок реализует прокрутку фона справа-налево, делая анимацию более реальной (можете называть этот процесс" виртуальной реальностью, если хотите). Фигуры могут сходиться и расходиться, но общее впечатление их движения слева-направо сохраняется. Для начала надо скопировать изображение фона целиком в буфер внеэкранного изображения, а затем организовать циклический сдвиг влево данных буфера на величину, установленную переменной Shift. Заключительный блок рисует, при помощи метода Draw, фигуры на канве невидимого объекта DrawBox, а затем копирует изображение канвы на экран, в видимый объект PaintBox.
7.5.3 Спрайты
Экземпляры класса SpriteClass (Листинг 7.7) обеспечивают анимацию одной маскируемой фигуры. Банк данных спрайта содержит канву невидимой компоненты TImage с битовыми образами фаз. Естественно, что все изображения банка данных спрайта должны быть одинакового размера. Изображения фаз анимации должны иметь черный фон, маска контура - белый.
class SpriteClass
private:
TCanvas *SpriteCanvas;
int ImageLeft, ImageTop;
int MaskLeft, MaskTop;
int Width, Height;
public:
void SetSprite(TCanvas *aSpriteCanvas,
int aImageLeft, int aImageTop, int aMaskLeft, int aMaskTop, int aWidth, int aHeight);
void Draw( TCanvas *aDrawCanvas, int aLeft, int aTop) ;
);
Листинг 7.7. Объявление класса спрайта в файле Spite, h.
В классе спрайта определены только два метода установки и рисования спрайта (Листинг 7.8). При вызове метода SetSprite аргументы aImageLeft и aImageTop определяют позицию спрайта на канве aSpriteCanvas, аргументы aMaskLeft и MaskTop - позицию маски, аргументы aWidth и aHeight - размеры спрайта. При вызове метода Draw аргумент aDrawCanvas задает канву рисования, а аргументы aLeft и aTop - позицию спрайта на этой канве.
void SpriteClass::SetSprite(TCanvas *aSpriteCanvas,
int aImageLeft, int aImageTop, int aMaskLeft, int aMaskTop, int aWidth, int aHeight) { SpriteCanvas = aSpriteCanvas;
ImageLeft = aImageLeft;
ImageTop = aImageTop;
MaskLeft = aMaskLeft;
MaskTop = aMaskTop;
Width = aWidth;
Height = aHeight;
}
void SpriteClass::Draw(TCanvas *aDrawCanvas,
int aLeft, int aTop) { aDrawCanvas->CopyMode = cmSrcAnd;
aDrawCanvas->CopyRect(Rect(aLeft, aTop,
aLeft+Width, aTop+Height), SpriteCanvas, Rect(MaskLeft, MaskTop, MaskLeft+Width, MaskTop+Height)) ;
aDrawCanvas->CopyMode = cmSrcPaint;
aDrawCanvas->CopyRect(Rect(aLeft, aTop,
aLeft+Width, aTop+Height), SpriteCanvas,
Rect(ImageLeft, ImageTop, ImageLeft+Width.ImageTop+Height));
}Листинг 7.8. Определение методов класса спрайта в файле Sprite.cpp.
Довольно трудно составить впечатление от работы приложения анимации по снимку одного кадра - тем более в черно-белом исполнении (Рис. 7.4). Книга не является подходящим носителем для распространения компьютерных мультфильмов. Если проблема вас заинтересовала, нет другого способа изучать ее дальше, как придумать и подготовить картинки и разработать собственное приложение, используя приведенные листинги в качестве прототипа.

Рис. 7.4. Снимок с экрана работающего приложения MOVEIT.
Сами фигуры представляют собой массив типа структуры, а не экземпляр какого-то класса. Однако не надо быть гениальным программистом, чтобы ввести логику работы с фигурами в соответствующий класс FigureClass, который будет инкапсулировать, в частности, свойство периметра и метод перемещения. Однако не стоит наследовать SpriteClass от класса фигур. Дело в том, что экземпляры этих классов имеют разную природу: спрайты - это графические объекты, а фигуры - логические конструкции. Если бы вам потребовалось произвести анимацию более, чем двух одинаковых фигур, все они по-прежнему будут разделять единственный класс спрайта, используя поле структуры Fig [ I ] . SD для связи I-фигуры с нужным экземпляром спрайта.
Взгляните на изображения фаз анимации самолета или вертолета. На второй фазе каждой фигуры пропеллер просто отсутствует. Постоянно переключая фазы, можно создать иллюзию вращения пропеллера. Зная, что программа не моделирует фактическое вращение, спросите, тем не менее, у наблюдающего за работой приложения: "В какую сторону вращается пропеллер?" - и любой уверенный ответ убедит вас в том, что время на программирование примера было потрачено не зря. Можно придумать какой-нибудь другой впечатляющий эффект, например, стреляющего пулемета. Расширяя банк данных спрайта дополнительными фазами фигур и соответствующими масками, можно добиваться различных эффектов
Комментариев нет:
Отправить комментарий