Ini adalah tutorial pendek yang fokus pada pemrograman grafis 2D
dalam lingkungan Direct3D. Lebih spesifik lagi, tutorial ini tentang
animasi 2D dengan interface ID3DXSprite, sebuah pembungkus
fungsionalitas menampilkan sprite 2D dalam grafis 3D.
Mengapa artikel ini tentang 2D?
Karena saya penggemar game-game side scroller seperti Sega Sonic atau Mario Bros.
Mengapa menggunakan Direct3D?
Sejak versi 8, M$ telah menyatakan bahwa DirectDraw sudah deprecated
dan tidak lagi dikembangkan dan M$ akan fokus mengembangkan DirectX
Graphics yakni API baru hasil penggabungan DirectDraw dan Direct3D
(Direct X versi 7 kebawah) untuk urusan grafik. So suatu saat di masa
datang, mungkin DirectDraw sudah tidak di-support.
Pada tutorial kali ini semua kode menggunakan DirectX 8 (karena
sistem saya masih pake DirectX 8 , anda harus menginstall DirectX 8
untuk bisa menjalankan contoh program yang ada disini. Pada tutorial,
saya akan menggunakan istilah Direct3D untuk mengacu pada DirectX
Graphics.
Mungkinkah membuat aplikasi 3D dengan Delphi?
Tentu! Oleh karena itu, download dulu unit konversi header DirectX dari SourceForge (DirectX 9) atau di sini (DirectX 8.1). Source code bisa didownload disini. Cukup introduksinya. Ayo mulai..
Dasar-Dasar Direct3D
Inisialisasi Direct3D
Fungsi Direct3DCreate8() tersedia untuk proses inisialisasi
mendapatkan instance ke interface IDirect3D8 yang dideklarasi di unit
DirectXGraphics.pas. Contoh
var
d3d8:IDirect3D8;
begin
d3d8:=Direct3DCreate8(D3D_SDK_VERSION);
...
Bila sukses d3d8 akan berisi pointer ke interface IDirect3D8 yang
selanjutnya dapat kita pergunakan untuk mendapatkan instance
IDirect3DDevice8 yang merupakan interface yang merwakili kartu grafis
yang ada pada system. Idirect3D8 juga kita pergunakan untuk keperluan
pengecekan kapabilitas kartu grafis.
Inisialisasi Device
Selama eksekusi aplikasi, kita akan sering menggunakan device untuk
proses inisialisasi mode grafis, transformasi, menciptakan tekstur,
menampilkan hasil render ke screen dan lain-lain. Device
direpresentasikan oleh interface IDirect3DDevice8. Untuk mendapatkan pointer interface ini kita menggunakan fungsi CreateDevice() milik IDirect3D8
function CreateDevice(const Adapter : Cardinal;
const DeviceType : TD3DDevType;
hFocusWindow : HWND;
BehaviorFlags : LongWord;
var pPresentationParameters:
TD3DPresent_Parameters;
out ppReturnedDeviceInterface :
IDirect3DDevice8) : HResult; stdcall;
Adapter adalah nilai ordinal vga card. Untuk mengacu pada VGA card utama kita set parapeter ini dengan D3DADAPTER_DEFAULT.
- DeviceType :tipe device isi dengan D3DDEVTYPE_HAL untuk menggunakan HAL.
- hFocusWindow:Handle yang akan menjadi target.
- BehaviorFlags adalah parameter yang menentukan sifat
device. Isi dengan D3DCREATE_HARDWARE_VERTEX_PROCESSING untuk
menggunakan VGA card yang mendukung 3D acceleration atau
D3DCREATE_SOFTWARE_VERTEX_PROCESSING bila tidak memiliki 3D
accelerator. D3DCREATE_HARDWARE_VERTEX_PROCESSING dan
D3DCREATE_SOFTWARE)VERTEX_PROCESSING bersifat mutual ekslusif, yakni
kita hanya bisa menggunakan salah satu tapi tidak keduad-duanya.
- pPresentationParameters berisi informasi seperti resolusi
mode grafis, kedalaman warna, jumlah backbuffer dan sebagainya. Untuk
saat ini, field yang penting adalah:
- BackBufferWidth dan BackBufferHeight kita
pergunakan untuk mengatur resolusi layar contoh 800x600, 1024x768 dan
lain-lain. Jika resolusi tidak didukung, CreteDevice akan gagal. Tips:
sebaiknya gunakan resolusi mode grafis yang standar yang banyak
didukung oleh vga card seperti 800x600 atau 1024x768.
-
Windowed kita pergunakan untuk mengatur apakah aplikasi
berjalan secara fullscreen atau dalam window. Jika diisi false
aplikasi berjalan pada mode fullscreen. Pada mode fullscreen, aplikasi
kita dapat menggunakan page flipping atau blitting untuk proses double
buffering. Sedangkan pada mode windowed, double buffering hanya
menggunakan blitting.
Catatan: Page flipping maupun blitting adalah teknik
double buffering yang umum dipakai. Double buffering dikembangkan
untuk meminimalkan terjadinya flicker yakni dengan memanfaatkan dua buah
buffer (atau triple buffering bila tiga) yakni buffer utama biasa
disebut front buffer atau primary buffer, buffer ini adalah buffer yang
terlihat dan sebuah buffer tambahan yang tidak terlihat (back
buffer). Proses penggambaran dilakukan di back buffer. Setelah
penggambaran selesai, back buffer ditransfer ke front buffer.
Page flipping adalah proses mengubah front buffer menjadi back buffer
dan sebaliknya dengan mengubah alamat start scanning kartu grafis.
Blitting adalah singkatan dari Block Binary transfer mengkopi isi back
buffer ke front buffer. Secara teoritis page flipping lebih cepat dari
blitting, karena proses menampilkan isi back buffer sehingga dapat
dilihat tidak melibatkan pengkopian data.
- BackBufferFormat kita pergunakan untuk menentukn kedalaman
warna yang kita inginkan. Contoh untuk menjalankan aplikasipada
kedalaman warna 32 Bit, kita menggunakan D3DFMT_A8R8G8B8 dimana tiap
pixel terdiri atas komponen Alpha(A) =8 bit, Red (R)= 8 bit, Green(G)=
8 bit dan Blue(B)=8 bit. Alpa menentukan tingkat transparansi pixel
tersbut jika dicampur dengan warna lain. Untuk mode 16 bit kita bisa
menggunakan D3DFMT_R5G6B5 dengan R=5 bit G=6 bit dan B=5 bit tanpa
komponen alpha. Untuk mode 24 bit konstanta yang bisa kita pakai
adalah D3DFMT_R8G8B8 tanpa alpha
- SwapEffect menentukan bagaimana proses pertukaran back
buffer dan front buffer. Jika disi D3DSWAPEFFECT_DISCARD, maka setelah
swap back buffer dan front buffer, isi back buffer menjadi berubah
sehingga kita tidak bisa mengasumsikan bahwa back buffer isinya akan
sama dengan sebelum swap. Dengan menggunakan D3DSWAPEFFECT_DISCARD kita
memberitahukan kepada DirectX untuk memilih mekanisme swap yang paling
optimal untuk buffer kita. Jika kita isi dengan D3DSWAPEFFECT_FLIP kita
meberithaukan DirectX untuk menggunakan page Flipping. dan
D3DSWAPEFFECT_COPY serta D3DSWAPEFFECT_VSYNC_COPY untuk blitting.
VSYNC melakukan blitting dengan melakukan sinkronisasi vertical trace
guna meminimalkan efek tear-off.
- hDeviceWindow handle window yang akan menjadi target proses render. Jika 0 hFocusWindow yang akan digunakan.
ppReturnedDeviceInterface interface yang akan menerima pointer IDirect3DDevice8
jika CreateDevice() gagal ppReturnedDeviceInterface sama dengan nil. Contoh:
if accel3DSupported then
behaviour:=D3DCREATE_HARDWARE_VERTEX_PROCESSING
else
behaviour:=D3DCREATE_SOFTWARE_VERTEX_PROCESSING;
ZeroMemory(presentParam,sizeof(TD3DPresent_Parameters));
presentParam.hFocusWindow:=Form1.Handle;
presentParam.BackBufferCount:=1;
presentParam.BackBufferWidth:=800;
presentParam.BackBufferHeight:=600;
presentParam.SwapEffect:=D3DSWAPEFFECT_DISCARD;
presentparam.BackBufferFormat:=D3DFMT_A8R8G8B8;
d3d8.CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
behaviour,
presentParam,
d3d8Dev);
Mengecek Apakah 3D accelerator tersedia.
Agar kita bisa memanfaatkan kemampuan kartu grafis dengan optimal,
kita perlu memastikan bahwa kartu grafis kita mendukung 3D
acceleration. UNtuk mengecek kapabilitaskartu grafis tersedia metode IDirect3D8.GetDeviceCaps().
function GetDeviceCaps(const Adapter : Cardinal;
const DeviceType : TD3DDevType;
out pCaps : TD3DCaps8) : HResult; stdcall;
Adapter : nilai ordinal kartu grafis. Seperti biasa bisa disisi
D3DADAPTER_DEFAULT untuk mengacu pada primary adapter. DeviceType.: tipe
device D3DDEVTYPE_HAL atau D3DDEVTYPE_REF pCaps :struktur yang akan
diisi info kapabilitas kartu grafis
Untuk mengecek apakah 3D accelerator tersedia kita perlu mengecek
variable pCaps.DevCaps apakah mengandung nilai
D3DDEVCAPS_HWTRANSFORMANDLIGHT. Contoh:
d3d8.GetDeviceCaps(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, aCaps);
accel3DSupported:=(aCaps.DevCaps
AND
D3DDEVCAPS_HWTRANSFORMANDLIGHT
= D3DDEVCAPS_HWTRANSFORMANDLIGHT);
Membersihkan Isi Back Buffer
Untuk membersihkan buffer, baik itu buffer untuk proses render, depth buffer atau stencil buffer kita menggunakan IDirect3DDevice8.Clear().
function Clear(const Count : LongWord;
pRects : PD3DRect;
const Flags : LongWord;
const Color : TD3DColor;
const Z : Single;
const Stencil : LongWord) : HResult; stdcall;
Count berisi jumlah rectangle yang ada pada pRects. Jika pRects=nil
maka Count harus diset 0 pRects berisi rectangle-rectangle yang akan
diclear jika diisi nil, maka seluruh buffer akan di clear. Flags
mengindikasikan buffer yang akan diclear. D3DCLEAR_STENCIL menyebabkan
stencil buffer diclear dengan nilai yang terkandung pada parameter
Stencil. D3DCLEAR_ZBUFFER mengclear depth buffer dengan nilai yang ada
pada parameter Z dan D3DCLEAR_TARGET mengclear render target dengan
warna yang tersimpan di Color.
Untuk tutorial ini depth buffer dan stencil buffer belum relevan
untuk dibahas. Untuk membersihkan (lebih tepatnya mengisi) seluruh
buffer render dengan sebuah warna merah (ARGB=$FFFF0000) contohnya
adalah sebagai berikut:
d3dDev.Clear(0,nil, D3DCLEAR_TARGET, $FFFF0000,0,0);
Memulai dan Mengakhiri Proses Menggambar Object 3D
Sebelum menggambar obyek 3D, kita wajib memanggil BeginScene() dan mengakhirinya dengan EndScene(), dimana diantara dua pemanggilan fungsi diatas adalah kode-kode untuk menyusun obyek 3D.
d3ddev.BeginScene;
//gambar obyek-obyek disini
d3ddev.EndScene;
Pasangan BeginScene/EndScene harus dipanggil walaupun kita tidak menggambar obyek apa-apa.
Menampilkan Isi Back Buffer Ke Front Buffer
Agar semua yang kita gambar dapat terlihat dilayar, kita harus menampilkannya dengan fungsi Present().
function Present(pSourceRect, pDestRect : PRect;
const hDestWindowOverride : HWND;
pDirtyRegion : PRgnData) : HResult; stdcall;
- pSourceRect rectangle yang akan dikopi. Jika diisi nil maka
seluruh buffer akan dikopi. Harus diisi nil bila device dicreate
dengan swap effect D3DSWAPEFFECT_COPY atau D3DSWAPEFFECT_VSYNC_COPY.
- pDestRect rectangle tujuan. Sama dengan pSourceRect.
- hDestWindowOverride handle window yang akan dijadikan target render. Jika 0 TD3Dpresent_Parameters.hDeviceWindow yang akan digunakan.
- pDirtyRegion belum digunakan dan harus diisi nil.
Contoh:
d3ddev.Present(nil,nil,nil,0,nil);
Tekstur
Tekstur adalah istilah untuk gambar yang ditempelkan pada poligon,
guna meningkatkan tingkat realistis obyek 3D. Di Direct3D 8 tekstur
direpresentasikan oleh interface IDirect3DTexture8
Menciptakan Tekstur dari File Gambar
DirectX memiliki kumpulan utility yang bernama D3DX, salah satu fungsi pada D3DX ini adalah D3DXCreateTextureFromFile() dan D3DXCreateTextureFromFileEx() keduanya
dideklarasi di d3dx8.pas. Fungsi yang terakhir adalah perluasan
fungsi yang pertama dan yang akan kita pergunakan untuk menciptakan
tektur.
Sprite
Sprite adalah istilah dalam game programming yang mengacu pada gambar
karakter-karakter pada sebuah game. Ciri utama sprite adalah
mengandung informasi transparansi dimana warna-warna yang dianggap
transparan (color key) tidak akan ditampilkan. Kursor mouse adalah
contoh sprite.
ID3DXSprite
D3DX menyediakan interface untuk mempermudah mainpulasi sprite menggunakan ID3DXSprite.
Menciptakan Sprite
Fungsi D3DXCreateSprite() kita pergunakan untuk mendapatkan pointer instance ID3DXSprite.
function D3DXCreateSprite(const pDevice : IDirect3DDevice8;
out ppSprite : ID3DXSprite) : HResult; stdcall;
Contoh:
D3DXCreateSprite(d3dDev,aSprite);
Memulai dan Mengahiri proses Menggambar Sprite
Untuk memulai proses menggambar sprite, kita harus memanggil ID3DXSprite.Begin dan ID3DXSprite.End.
Perhatikan bahwa karena Begin dan End adalah kata tercadang, maka
pada header konversi, fungsi ini di rename menjadi _Begin dan _End
aSprite._Begin;
//lakukan sesuatu dengan sprite
aSprite._End;
Implementasi Aplikasi Animasi
Cukup sekian dulu introduksi Direct3D, mari kita buat implementasi
framework untuk aplikasi 2D. Kita akan membuat aplikasi dimana kita
akan dapat menggerakkan karakter Guile (Street Fighter), mengontrol
Guile untuk menampilkan aksi memukul dan menendang.
TEngine
Kita akan membuat wrapper class untuk proses inisialisasi Direct3D dan rendering. Fitur yang dimiliki kelas ini adalah:
- Memiliki metode untuk proses inisialisasi device yang diimplementasi dalam procedure InitDevice;
- Memiliki metode untuk membersihkan buffer melalui procedure Clear
- Memiliki metode untuk menampilkan proses rendering.
- Memiliki metode untuk menggambar semua obyek 3D yang diimplementasi
oleh procedure abstrak Draw. Kelas turunan harus mengimplementasikan
metode ini.
T3DCollection
Adalah kelas basis untuk kumpulan item-item pada engine 3D ini. Kelas
ini memiliki sebuah property bertipe Tengine dan diturunkan dari
TCollection
Texture wrapper class
Kelas enkapsulasi manajemen tekstur terdiri atas dua
TtextureCollection dan Ttexture. Ttexture menghandle inisialisasi
IDirect3DTexture8 dan loading file gambar. TtextureCollection menghandle
manajemen Ttexture. TtextureCollection diturunkan dari T3Dcollection.
Ttextur sendiri diturunkan dari TcollectionItem
unit u_3D_engine;
interface
uses classes,windows,sysutils,directxGraphics;
type
E3DError=class(Exception);
TEngineParam=record
Handle:HWND;
Fullscreen:boolean;
ResolutionWidth:integer;
ResolutionHeight:integer;
TotalBackBuffer:integer;
ColorDepth:integer;
InitDeviceOnCreate:boolean;
end;
TEngine=class(TObject)
private
FDirect3DObj:IDirect3D8;
FDirect3DDevice:IDirect3DDevice8;
function CreateD3D:IDirect3D8;
function CreateDevice(const d3d:IDirect3D8):IDirect3DDevice8;
function HwVertexProcSupported:boolean;
protected
FEngineParam:TEngineParam;
FPresentParam:TD3DPresent_Parameters;
procedure BeginDraw;
procedure Draw;virtual;abstract;
procedure EndDraw;
public
constructor Create(Param:TEngineParam);virtual;
destructor Destroy;override;
procedure InitDevice;
procedure Clear(const ClearCol:TD3DColor);
procedure Render;
published
property Direct3DObj:IDirect3D8 read FDirect3DObj;
property Direct3DDevice:IDirect3DDevice8 read FDirect3DDevice;
end;
T3DCollection=class(TCollection)
private
FEngine: TEngine;
procedure SetEngine(const Value: TEngine);
published
property Engine:TEngine read FEngine write SetEngine;
end;
T3DObject=class(TCollectionItem)
private
protected
FVertexBuff:IDirect3DVertexBuffer8;
FIndexBuff:IDirect3DIndexBuffer8;
public
procedure Init;virtual;abstract;
procedure Draw;virtual;abstract;
end;
TTexture=class(TCollectionItem)
private
FTextureObj: IDirect3DTexture8;
FColorKey: TD3DColor;
procedure SetColorKey(const Value: TD3DColor);
public
destructor Destroy;override;
procedure LoadFromFile(const filename:string);
published
property TextureObj:IDirect3DTexture8 read FTextureObj;
property ColorKey:TD3DColor read FColorKey write SetColorKey;
end;
TTextureCollection=class(T3DCollection)
end;
implementation
uses d3dx8;
{ TEngine }
procedure TEngine.BeginDraw;
begin
if FDirect3DDevice<>nil then
FDirect3DDevice.BeginScene;
end;
procedure TEngine.Clear(const ClearCol:TD3DColor);
begin
if FDirect3DDevice<>nil then
FDirect3DDevice.Clear(0,nil,D3DCLEAR_TARGET,ClearCol,0,0);
end;
constructor TEngine.Create(Param: TEngineParam);
begin
FEngineParam:=Param;
FDirect3DObj:=CreateD3D;
if FEngineParam.InitDeviceOnCreate then
InitDevice;
end;
function TEngine.CreateD3D: IDirect3D8;
begin
result:=Direct3DCreate8(D3D_SDK_VERSION);
end;
function TEngine.CreateDevice(const d3d: IDirect3D8): IDirect3DDevice8;
var hr:HResult;
vertexProcessing:cardinal;
begin
if d3dnil then
begin
ZeroMemory(@FPresentParam,sizeof(TD3DPresent_Parameters));
FPresentParam.Windowed:=not FEngineParam.Fullscreen;
FPresentParam.BackBufferWidth:=FEngineParam.ResolutionWidth;
FPresentParam.BackBufferHeight:=FEngineParam.ResolutionHeight;
FPresentParam.BackBufferCount:=FEngineParam.TotalBackBuffer;
FPresentParam.BackBufferFormat:=FEngineParam.ColorDepth;
FPresentParam.SwapEffect:=D3DSWAPEFFECT_DISCARD;
//3D hardware acceleration tersedia?
if HwVertexProcSupported then
vertexProcessing:=D3DCREATE_HARDWARE_VERTEXPROCESSING
else
vertexProcessing:=D3DCREATE_SOFTWARE_VERTEXPROCESSING;
hr:=d3d.CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
FEngineParam.Handle,
vertexProcessing,
FPresentParam,
result);
if result=nil then
raise E3DError.Create(D3DXErrorString(hr));
end else
result:=nil;
end;
destructor TEngine.Destroy;
begin
FDirect3DDevice:=nil;
FDirect3DObj:=nil;
inherited;
end;
procedure TEngine.EndDraw;
begin
if FDirect3DDevice<>nil then
FDirect3DDevice.EndScene;
end;
function TEngine.HwVertexProcSupported: boolean;
var caps:TD3DCaps8;
begin
FDirect3DObj.GetDeviceCaps(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,caps);
result:=((caps.DevCaps and D3DDEVCAPS_HWTRANSFORMANDLIGHT)0);
end;
procedure TEngine.InitDevice;
begin
FDirect3DDevice:=CreateDevice(FDirect3DObj);
end;
procedure TEngine.Render;
begin
BeginDraw;
try
Draw;
if FDirect3DDevice<>nil then
FDirect3DDevice.Present(nil,nil,0,nil);
finally
EndDraw;
end;
end;
{ T3DCollection }
procedure T3DCollection.SetEngine(const Value: TEngine);
begin
FEngine := Value;
end;
{ TTexture }
destructor TTexture.Destroy;
begin
FTextureObj:=nil;
inherited;
end;
procedure TTexture.LoadFromFile(const filename: string);
var atexcollection:TTextureCollection;
hr:HResult;
begin
if Collection is TTextureCollection then
begin
aTexCollection:=Collection as TTextureCollection;
if (aTexCollection.Engine.Direct3DDevice<>nil) and
fileExists(filename) then
begin
hr:=D3DXCreateTextureFromFileEx(aTexCollection.Engine.Direct3DDevice,
PChar(filename),
D3DX_DEFAULT,
D3DX_DEFAULT,
D3DX_DEFAULT,
0,
D3DFMT_UNKNOWN,
D3DPOOL_MANAGED,
D3DX_FILTER_NONE,
D3DX_FILTER_NONE,
FColorKey,
nil,nil,
FTextureObj);
if FTextureObj=nil then
raise E3DError.Create(D3DXErrorString(hr));
end;
end;
end;
procedure TTexture.SetColorKey(const Value: TD3DColor);
begin
FColorKey := Value;
end;
end.
Implementasi 2D Engine
OK, selanjutnya kita buat implementasi untuk menangani sprite. Proses
manajemen sebuah sprite akan dienkapsulasi dalam kelas TSprite
sedangkan TSprite diatur dalam TspriteCollection. Sama seperti
unit u2DSpr;
interface
uses classes,directxgraphics,d3dx8,u_3D_engine;
type
TSpriteCollection=class(T3DCollection)
private
FSprite:ID3DXSprite;
procedure Init;
public
destructor Destroy;override;
procedure BeginDraw;
procedure EndDraw;
published
property SpriteObj:ID3DXSprite read FSprite;
end;
TSprite=class(T3DObject)
private
FSprite:ID3DXSprite;
FTexture: TTexture;
FRotation: single;
FColor: TD3DColor;
FScaling: TD3DXVector2;
FRotationCenter: TD3DXVector2;
FTranslation: TD3DXVector2;
FAlpha: byte;
procedure SetTexture(const Value: TTexture);
procedure SetColor(const Value: TD3DColor);
procedure SetRotation(const Value: single);
procedure SetRotationCenter(const Value: TD3DXVector2);
procedure SetScaling(const Value: TD3DXVector2);
procedure SetTranslation(const Value: TD3DXVector2);
procedure SetAlpha(const Value: byte);
public
constructor Create(ACollection: TCollection);override;
destructor Destroy;override;
procedure Init;override;
procedure Draw;override;
procedure DrawEx(const translVect,
scaleVect,
rotCenter:PD3DXVector2;
const rot:single;
const Acolor:TD3DColor;
const alphaValue:byte);
published
property Texture:TTexture read FTexture write SetTexture;
property Translation:TD3DXVector2 read FTranslation write SetTranslation;
property X:single read FTranslation.x write FTranslation.x;
property Y:single read FTranslation.y write FTranslation.y;
property RotationCenter:TD3DXVector2 read FRotationCenter write SetRotationCenter;
property Scaling:TD3DXVector2 read FScaling write SetScaling;
property Rotation:single read FRotation write SetRotation;
property Color:TD3DColor read FColor write SetColor;
property Alpha:byte read FAlpha write SetAlpha;
end;
implementation
{ TSprite }
constructor TSprite.Create(ACollection: TCollection);
var asprCollect:TSpriteCollection;
begin
inherited;
FSprite:=nil;
if ACollection is TSpriteCollection then
begin
asprCollect:=ACollection as TSpriteCollection;
if asprCollect.SpriteObj=nil then
asprCollect.Init;
FSprite:=asprCollect.SpriteObj;
end;
FTranslation.x:=0;
FTranslation.Y:=0;
FRotationCenter.x:=0;
FRotationCenter.y:=0;
FRotation:=0;
FScaling.x:=1;
FScaling.y:=1;
FColor:=$FFFFFFFF;
end;
destructor TSprite.Destroy;
begin
FSprite:=nil;
inherited;
end;
procedure TSprite.Draw;
begin
DrawEx(@FTranslation,
@FScaling,
@FRotationCenter,
FRotation,
FColor,
FAlpha);
end;
procedure TSprite.DrawEx(const translVect, scaleVect,
rotCenter: PD3DXVector2; const rot: single;
const AColor:TD3DColor;const AlphaValue:byte);
begin
if (FSprite<>nil) and
(FTexture<>nil) and
(FTexture.TextureObj<>nil) then
begin
FSprite.Draw(FTexture.TextureObj,nil,
scaleVect,
rotCenter,rot,
translVect,
(AlphaValue shl 24) or AColor);
end;
end;
procedure TSprite.Init;
begin
end;
procedure TSprite.SetAlpha(const Value: byte);
begin
FAlpha := Value;
end;
procedure TSprite.SetColor(const Value: TD3DColor);
begin
FColor := Value;
end;
procedure TSprite.SetRotation(const Value: single);
begin
FRotation := Value;
end;
procedure TSprite.SetRotationCenter(const Value: TD3DXVector2);
begin
FRotationCenter := Value;
end;
procedure TSprite.SetScaling(const Value: TD3DXVector2);
begin
FScaling := Value;
end;
procedure TSprite.SetTexture(const Value: TTexture);
begin
FTexture := Value;
end;
procedure TSprite.SetTranslation(const Value: TD3DXVector2);
begin
FTranslation := Value;
end;
{ TSpriteCollection }
procedure TSpriteCollection.BeginDraw;
begin
if FSprite<>nil then
FSprite._Begin;
end;
destructor TSpriteCollection.Destroy;
begin
FSprite:=nil;
inherited;
end;
procedure TSpriteCollection.EndDraw;
begin
if FSprite<>nil then
FSprite._End;
end;
procedure TSpriteCollection.Init;
begin
if (Engine<>nil) and (Engine.Direct3DDevice<>nil) then
D3DXCreateSprite(Engine.Direct3DDevice,FSprite)
else
FSprite:=nil;
end;
|
Tidak ada komentar:
Posting Komentar