G
gxcooo
Unregistered / Unconfirmed
GUEST, unregistred user!
刚考完《操作系统》,开始写我的第二个directx程序:256色下的淡入和淡出
先谈谈256色吧:
有些朋友一看到256色就以为是过时的东西,游戏中256色怎么够用呢?
其实256色模式可以描述为:调色板模式下24bit模式.在该模式下,每个像素都可以赋予0-255的
一个值,这些值作为参数,起到所谓的调色板输入项数组的作用,现在,数组中每个输入相对颜色中的每一个红、蓝、绿
强度都包含一个8bits值,结果使得用每8bits表示一个像素的颜色可以达到24bits深度,即16777216种颜色,但一屏只能显示其中的256种颜色。
所以只要你不断改变调色板就可以改变这256种颜色。
再谈谈画面的淡出:
屏幕上的每一个象数的颜色都存放在一个大小为256的数组中,数组中的每一项包括3*8bits.也就是说屏幕显示内存中存放的
不是这个点的真实颜色而是一个索引。我们只要改变这个索引所指向的颜色(保存在调色板中)就可以改变这点的颜色。
当我们要进行100步淡出时,我们每一步把调色板中的那256减去1%,这样就实现了淡出效果。
淡入时情况打假可想而知了吧。
例程:http://go.163.com/progame/mytest.html (网易没法做直接链接,所以大家必须访问这个页面,新加了一些好东西[])
源代码:
///////////////////////////////////////////////////////////////////////////////
// mytest_api.dpr
///////////////////////////////////////////////////////////////////////////////
// This is my test program;
///////////////////////////////////////////////////////////////////////////////
program mytest_api;
//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------
uses
Windows, Messages, DirectDraw, SysUtils, DDUtil;
{$R *.res}
const
//---------------------------------------------------------------------------
// Local definitions
//---------------------------------------------------------------------------
NAME: PChar = 'DDExample2';
TITLE: PChar = 'Direct Draw Example 2';
szBitmap: PChar = 'Background.BMP';
Step: Integer = 100; //Fade In Step Count
var
//---------------------------------------------------------------------------
// Global data
//---------------------------------------------------------------------------
g_pDD: IDirectDraw7; // DirectDraw object
g_pDDSPrimary: IDirectDrawSurface7; // DirectDraw primary surface
g_pDDPal: IDIRECTDRAWPALETTE; // The primary surface palette
ddsd: TDDSurfaceDesc2;
AnimPalette, OrgPalette: array[0..255] of PALETTEENTRY;//调色板条目
g_bActive: Boolean = False; // Is application active?
//-----------------------------------------------------------------------------
// Name: ReleaseAllObjects
// Desc: Finished with all objects we use; release them
//-----------------------------------------------------------------------------
procedure ReleaseAllObjects;
begin
if Assigned(g_pDD) then
begin
if Assigned(g_pDDSPrimary) then
begin
g_pDDSPrimary := nil;
end;
if Assigned(g_pDDPal) then
begin
g_pDDPal := nil;
end;
g_pDD := nil;
end;
end;
//-----------------------------------------------------------------------------
// Name: InitFail
// Desc: This function is called if an initialization function fails
//-----------------------------------------------------------------------------
function InitFail(h_Wnd: HWND; hRet: HRESULT; Text: string): HRESULT;
begin
ReleaseAllObjects;
MessageBox(h_Wnd, PChar(Text + ': ' + DDErrorString(hRet)), TITLE, MB_OK);
DestroyWindow(h_Wnd);
Result := hRet;
end;
//-----------------------------------------------------------------------------
// Name: FadeOut
// Desc: FadeOut
//-----------------------------------------------------------------------------
procedure FadeOut;
var
i, j: integer;
begin
for i := 0 to Step do
begin
for j := 0 to 255 do
begin
AnimPalette[j].peRed := OrgPalette[j].peRed - Trunc((OrgPalette[j].peRed * i) / Step);
AnimPalette[j].peGreen := OrgPalette[j].peGreen - Trunc((OrgPalette[j].peGreen * i) / Step);
AnimPalette[j].peBlue := OrgPalette[j].peBlue - Trunc((OrgPalette[j].peBlue * i) / Step);
AnimPalette[j].peFlags := PC_RESERVED;
end;
g_pDDPal.SetEntries(0, 0, 256, @AnimPalette);
Sleep(30);
end;
end;
//-----------------------------------------------------------------------------
// Name: FadeIn
// Desc: FadeIn
//-----------------------------------------------------------------------------
procedure FadeIn;
var
i, j: integer;
begin
for i := 0 to Step do
begin
for j := 0 to 255 do
begin
AnimPalette[j].peRed := Trunc((OrgPalette[j].peRed * i) / Step);
AnimPalette[j].peGreen := Trunc((OrgPalette[j].peGreen * i) / Step);
AnimPalette[j].peBlue := Trunc((OrgPalette[j].peBlue * i) / Step);
AnimPalette[j].peFlags := PC_RESERVED;
end;
g_pDDPal.SetEntries(0, 0, 256, @AnimPalette);
Sleep(30);
end;
end;
//-----------------------------------------------------------------------------
// Name: InitSurface
// Desc: Load a Bitmap into PrimarySurface.
//-----------------------------------------------------------------------------
function InitSurface: Boolean;
var
hbm: HBITMAP;
begin
Result := false;
hbm := LoadImage(0, szBitmap, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE or LR_CREATEDIBSECTION);
if hbm = 0 then
Exit;
DDCopyBitmap(g_pDDSPrimary, hbm, 0, 0, 640, 480);
Result := true;
end;
//-----------------------------------------------------------------------------
// Name: WindowProc
// Desc: The Main Window Procedure
//-----------------------------------------------------------------------------
function WindowProc(h_Wnd: HWND; aMSG: Cardinal; wParam: Cardinal; lParam: Integer): Integer; stdcall;
begin
case aMSG of
// Pause if minimized
WM_ACTIVATE:
begin
if HIWORD(wParam) = 0 then
g_bActive := True
else
g_bActive := False;
Result := 0;
Exit;
end;
// Clean up and close the app
WM_DESTROY:
begin
ReleaseAllObjects;
PostQuitMessage(0);
Result := 0;
Exit;
end;
// Handle any non-accelerated key commands
WM_KEYDOWN:
begin
case wParam of
VK_ESCAPE:
begin
FadeOut;
PostMessage(h_Wnd, WM_CLOSE, 0, 0);
Result := 0;
Exit;
end;
VK_F11: FadeIn;
Vk_F12: begin
FadeOut;
FadeIn;
end;
end;
end;
// Turn off the cursor since this is a full-screen app
WM_SETCURSOR:
begin
SetCursor(0);
Result := 1;
Exit;
end;
end;
Result := DefWindowProc(h_Wnd, aMSG, wParam, lParam);
end;
//-----------------------------------------------------------------------------
// Name: InitApp
// Desc: Do work required for every instance of the application:
// Create the window, initialize data
//-----------------------------------------------------------------------------
function InitApp(hInst: THANDLE; nCmdShow: Integer): HRESULT;
var
h_Wnd: HWND;
wc: WNDCLASS;
hRet: HRESULT;
pDDTemp: IDirectDraw;
begin
// Set up and register window class
wc.style := CS_HREDRAW or CS_VREDRAW;
wc.lpfnWndProc := @WindowProc;
wc.cbClsExtra := 0;
wc.cbWndExtra := 0;
wc.hInstance := hInst;
wc.hIcon := LoadIcon(hInst, 'MAINICON');
wc.hCursor := LoadCursor(0, IDC_ARROW);
wc.hbrBackground := GetStockObject(BLACK_BRUSH);
wc.lpszMenuName := NAME;
wc.lpszClassName := NAME;
RegisterClass(wc);
// Create a window
h_Wnd := CreateWindowEx(WS_EX_TOPMOST,
NAME,
TITLE,
WS_POPUP,
0,
0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
0,
0,
hInst,
nil);
if h_Wnd = 0 then
begin
Result := 0;
Exit;
end;
ShowWindow(h_Wnd, nCmdShow);
UpdateWindow(h_Wnd);
SetFocus(h_Wnd);
///////////////////////////////////////////////////////////////////////////
// Create the main DirectDraw object
///////////////////////////////////////////////////////////////////////////
hRet := DirectDrawCreate(nil, pDDTemp, nil);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'DirectDrawCreate FAILED');
Exit;
end;
hRet := pDDTemp.QueryInterface(IDirectDraw7, g_pDD);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'QueryInterface FAILED');
Exit;
end;
pDDTemp := nil;
// Get exclusive mode
hRet := g_pDD.SetCooperativeLevel(h_Wnd, DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'SetCooperativeLevel FAILED');
Exit;
end;
// Set the video mode to 640X480x8
hRet := g_pDD.SetDisplayMode(640, 480, 8, 0, 0);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'SetDisplayMode FAILED');
Exit;
end;
// Create the primary surface
FillChar(ddsd, SizeOf(ddsd), 0);
ddsd.dwSize := SizeOf(ddsd);
ddsd.dwFlags := DDSD_CAPS;
ddsd.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE;
hRet := g_pDD.CreateSurface(ddsd, g_pDDSPrimary, nil);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'CreateSurface FAILED');
Exit;
end;
// Create and set the palette
g_pDDPal := DDLoadPalette(g_pDD, szBitmap);
if g_pDDPal = nil then
begin
Result := InitFail(h_Wnd, hRet, 'DDLoadPalette FAILED');
Exit;
end;
hRet := g_pDDSPrimary.SetPalette(g_pDDPal);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'SetPalette FAILED');
Exit;
end;
//取得调色板条目
g_pDDpal.GetEntries(0, 0, 256, @OrgPalette);
if not InitSurface then
Exit;
Result := DD_OK;
end;
//-----------------------------------------------------------------------------
// Name: WinMain
// Desc: Initialization, message loop
//-----------------------------------------------------------------------------
type
Screen = array of Word;
var
aMSG: MSG;
begin
if InitApp(GetModuleHandle(nil), SW_SHOW) <> DD_OK then
begin
Exit;
end;
while True do
begin
if PeekMessage(aMsg, 0, 0, 0, PM_NOREMOVE) then
begin
if not GetMessage(aMsg, 0, 0, 0) then
Exit;
TranslateMessage(aMsg);
DispatchMessage(aMsg);
end
else if g_bActive then
begin
if g_pDDSPrimary.IsLost = DD_OK then
begin
if g_pDDSPrimary._Restore <> DD_OK then exit;
InitSurface;
end;
end
else
begin
// Make sure we go to sleep if we have nothing else to do
WaitMessage;
end;
end;
end.
先谈谈256色吧:
有些朋友一看到256色就以为是过时的东西,游戏中256色怎么够用呢?
其实256色模式可以描述为:调色板模式下24bit模式.在该模式下,每个像素都可以赋予0-255的
一个值,这些值作为参数,起到所谓的调色板输入项数组的作用,现在,数组中每个输入相对颜色中的每一个红、蓝、绿
强度都包含一个8bits值,结果使得用每8bits表示一个像素的颜色可以达到24bits深度,即16777216种颜色,但一屏只能显示其中的256种颜色。
所以只要你不断改变调色板就可以改变这256种颜色。
再谈谈画面的淡出:
屏幕上的每一个象数的颜色都存放在一个大小为256的数组中,数组中的每一项包括3*8bits.也就是说屏幕显示内存中存放的
不是这个点的真实颜色而是一个索引。我们只要改变这个索引所指向的颜色(保存在调色板中)就可以改变这点的颜色。
当我们要进行100步淡出时,我们每一步把调色板中的那256减去1%,这样就实现了淡出效果。
淡入时情况打假可想而知了吧。
例程:http://go.163.com/progame/mytest.html (网易没法做直接链接,所以大家必须访问这个页面,新加了一些好东西[])
源代码:
///////////////////////////////////////////////////////////////////////////////
// mytest_api.dpr
///////////////////////////////////////////////////////////////////////////////
// This is my test program;
///////////////////////////////////////////////////////////////////////////////
program mytest_api;
//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------
uses
Windows, Messages, DirectDraw, SysUtils, DDUtil;
{$R *.res}
const
//---------------------------------------------------------------------------
// Local definitions
//---------------------------------------------------------------------------
NAME: PChar = 'DDExample2';
TITLE: PChar = 'Direct Draw Example 2';
szBitmap: PChar = 'Background.BMP';
Step: Integer = 100; //Fade In Step Count
var
//---------------------------------------------------------------------------
// Global data
//---------------------------------------------------------------------------
g_pDD: IDirectDraw7; // DirectDraw object
g_pDDSPrimary: IDirectDrawSurface7; // DirectDraw primary surface
g_pDDPal: IDIRECTDRAWPALETTE; // The primary surface palette
ddsd: TDDSurfaceDesc2;
AnimPalette, OrgPalette: array[0..255] of PALETTEENTRY;//调色板条目
g_bActive: Boolean = False; // Is application active?
//-----------------------------------------------------------------------------
// Name: ReleaseAllObjects
// Desc: Finished with all objects we use; release them
//-----------------------------------------------------------------------------
procedure ReleaseAllObjects;
begin
if Assigned(g_pDD) then
begin
if Assigned(g_pDDSPrimary) then
begin
g_pDDSPrimary := nil;
end;
if Assigned(g_pDDPal) then
begin
g_pDDPal := nil;
end;
g_pDD := nil;
end;
end;
//-----------------------------------------------------------------------------
// Name: InitFail
// Desc: This function is called if an initialization function fails
//-----------------------------------------------------------------------------
function InitFail(h_Wnd: HWND; hRet: HRESULT; Text: string): HRESULT;
begin
ReleaseAllObjects;
MessageBox(h_Wnd, PChar(Text + ': ' + DDErrorString(hRet)), TITLE, MB_OK);
DestroyWindow(h_Wnd);
Result := hRet;
end;
//-----------------------------------------------------------------------------
// Name: FadeOut
// Desc: FadeOut
//-----------------------------------------------------------------------------
procedure FadeOut;
var
i, j: integer;
begin
for i := 0 to Step do
begin
for j := 0 to 255 do
begin
AnimPalette[j].peRed := OrgPalette[j].peRed - Trunc((OrgPalette[j].peRed * i) / Step);
AnimPalette[j].peGreen := OrgPalette[j].peGreen - Trunc((OrgPalette[j].peGreen * i) / Step);
AnimPalette[j].peBlue := OrgPalette[j].peBlue - Trunc((OrgPalette[j].peBlue * i) / Step);
AnimPalette[j].peFlags := PC_RESERVED;
end;
g_pDDPal.SetEntries(0, 0, 256, @AnimPalette);
Sleep(30);
end;
end;
//-----------------------------------------------------------------------------
// Name: FadeIn
// Desc: FadeIn
//-----------------------------------------------------------------------------
procedure FadeIn;
var
i, j: integer;
begin
for i := 0 to Step do
begin
for j := 0 to 255 do
begin
AnimPalette[j].peRed := Trunc((OrgPalette[j].peRed * i) / Step);
AnimPalette[j].peGreen := Trunc((OrgPalette[j].peGreen * i) / Step);
AnimPalette[j].peBlue := Trunc((OrgPalette[j].peBlue * i) / Step);
AnimPalette[j].peFlags := PC_RESERVED;
end;
g_pDDPal.SetEntries(0, 0, 256, @AnimPalette);
Sleep(30);
end;
end;
//-----------------------------------------------------------------------------
// Name: InitSurface
// Desc: Load a Bitmap into PrimarySurface.
//-----------------------------------------------------------------------------
function InitSurface: Boolean;
var
hbm: HBITMAP;
begin
Result := false;
hbm := LoadImage(0, szBitmap, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE or LR_CREATEDIBSECTION);
if hbm = 0 then
Exit;
DDCopyBitmap(g_pDDSPrimary, hbm, 0, 0, 640, 480);
Result := true;
end;
//-----------------------------------------------------------------------------
// Name: WindowProc
// Desc: The Main Window Procedure
//-----------------------------------------------------------------------------
function WindowProc(h_Wnd: HWND; aMSG: Cardinal; wParam: Cardinal; lParam: Integer): Integer; stdcall;
begin
case aMSG of
// Pause if minimized
WM_ACTIVATE:
begin
if HIWORD(wParam) = 0 then
g_bActive := True
else
g_bActive := False;
Result := 0;
Exit;
end;
// Clean up and close the app
WM_DESTROY:
begin
ReleaseAllObjects;
PostQuitMessage(0);
Result := 0;
Exit;
end;
// Handle any non-accelerated key commands
WM_KEYDOWN:
begin
case wParam of
VK_ESCAPE:
begin
FadeOut;
PostMessage(h_Wnd, WM_CLOSE, 0, 0);
Result := 0;
Exit;
end;
VK_F11: FadeIn;
Vk_F12: begin
FadeOut;
FadeIn;
end;
end;
end;
// Turn off the cursor since this is a full-screen app
WM_SETCURSOR:
begin
SetCursor(0);
Result := 1;
Exit;
end;
end;
Result := DefWindowProc(h_Wnd, aMSG, wParam, lParam);
end;
//-----------------------------------------------------------------------------
// Name: InitApp
// Desc: Do work required for every instance of the application:
// Create the window, initialize data
//-----------------------------------------------------------------------------
function InitApp(hInst: THANDLE; nCmdShow: Integer): HRESULT;
var
h_Wnd: HWND;
wc: WNDCLASS;
hRet: HRESULT;
pDDTemp: IDirectDraw;
begin
// Set up and register window class
wc.style := CS_HREDRAW or CS_VREDRAW;
wc.lpfnWndProc := @WindowProc;
wc.cbClsExtra := 0;
wc.cbWndExtra := 0;
wc.hInstance := hInst;
wc.hIcon := LoadIcon(hInst, 'MAINICON');
wc.hCursor := LoadCursor(0, IDC_ARROW);
wc.hbrBackground := GetStockObject(BLACK_BRUSH);
wc.lpszMenuName := NAME;
wc.lpszClassName := NAME;
RegisterClass(wc);
// Create a window
h_Wnd := CreateWindowEx(WS_EX_TOPMOST,
NAME,
TITLE,
WS_POPUP,
0,
0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
0,
0,
hInst,
nil);
if h_Wnd = 0 then
begin
Result := 0;
Exit;
end;
ShowWindow(h_Wnd, nCmdShow);
UpdateWindow(h_Wnd);
SetFocus(h_Wnd);
///////////////////////////////////////////////////////////////////////////
// Create the main DirectDraw object
///////////////////////////////////////////////////////////////////////////
hRet := DirectDrawCreate(nil, pDDTemp, nil);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'DirectDrawCreate FAILED');
Exit;
end;
hRet := pDDTemp.QueryInterface(IDirectDraw7, g_pDD);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'QueryInterface FAILED');
Exit;
end;
pDDTemp := nil;
// Get exclusive mode
hRet := g_pDD.SetCooperativeLevel(h_Wnd, DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'SetCooperativeLevel FAILED');
Exit;
end;
// Set the video mode to 640X480x8
hRet := g_pDD.SetDisplayMode(640, 480, 8, 0, 0);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'SetDisplayMode FAILED');
Exit;
end;
// Create the primary surface
FillChar(ddsd, SizeOf(ddsd), 0);
ddsd.dwSize := SizeOf(ddsd);
ddsd.dwFlags := DDSD_CAPS;
ddsd.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE;
hRet := g_pDD.CreateSurface(ddsd, g_pDDSPrimary, nil);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'CreateSurface FAILED');
Exit;
end;
// Create and set the palette
g_pDDPal := DDLoadPalette(g_pDD, szBitmap);
if g_pDDPal = nil then
begin
Result := InitFail(h_Wnd, hRet, 'DDLoadPalette FAILED');
Exit;
end;
hRet := g_pDDSPrimary.SetPalette(g_pDDPal);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'SetPalette FAILED');
Exit;
end;
//取得调色板条目
g_pDDpal.GetEntries(0, 0, 256, @OrgPalette);
if not InitSurface then
Exit;
Result := DD_OK;
end;
//-----------------------------------------------------------------------------
// Name: WinMain
// Desc: Initialization, message loop
//-----------------------------------------------------------------------------
type
Screen = array of Word;
var
aMSG: MSG;
begin
if InitApp(GetModuleHandle(nil), SW_SHOW) <> DD_OK then
begin
Exit;
end;
while True do
begin
if PeekMessage(aMsg, 0, 0, 0, PM_NOREMOVE) then
begin
if not GetMessage(aMsg, 0, 0, 0) then
Exit;
TranslateMessage(aMsg);
DispatchMessage(aMsg);
end
else if g_bActive then
begin
if g_pDDSPrimary.IsLost = DD_OK then
begin
if g_pDDSPrimary._Restore <> DD_OK then exit;
InitSurface;
end;
end
else
begin
// Make sure we go to sleep if we have nothing else to do
WaitMessage;
end;
end;
end.