Check this code.. why is dx7 ddraw so slow...
Please refer to the code below:
compiled in Dev-C++..
even in 640x480, the ''sprite'' moves slowly across the screen, the mouse is instantaneous but the sprite, when i''m holding down the left arrow key, moves slow.
I even put the main code into a while(running=true) type of loop and used getasynckeystates to detect when you hit VK_ESCAPE or VK_LEFT.. moves smoother but still slow.
I know in win32 api, it would zip across the screen, even CDXLIB using MSVC v5.0, I had to add a delay.
i''m blitting the background (bypassing the clearscreen), to gain a little speed, is there something I am overlooking?
thanx in advance
it compiles to 17kb Feel free to use this code as I have begged/borrowed/stolen from the net, but if you make lotsa money using it in your next great 2D engine, I want a cut. haha
#include "stdafx.h"
#include
#include
#include
HINSTANCE g_hinstance;
HWND g_hwnd;
bool g_running;
bool g_active;
const char* g_appName = "My DirectDraw Program";
char szBitmap[ ] = "Greenstone.bmp";
char szBckgnd[ ] = "backgrnd.bmp";
int ef=32;
int f=0;
HBITMAP hbm;
HDC hdcImage= NULL;
HDC hdcSurf= NULL;
IDirectDraw7* dd;
IDirectDrawSurface7* primary;
IDirectDrawSurface7* backgrnd;
IDirectDrawSurface7* back;
IDirectDrawSurface7* lpA;
DDSURFACEDESC2 ddsd;
void update();
bool createWindow();
LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
bool initDirectDraw(int,int,int);
void clearScreen();
void flip();
void cleanUp();
void lock();
void unlock();
void setPixel(int, int, unsigned char);
void CopyBitmap(IDirectDrawSurface7*, HBITMAP, int, int, int, int);
int APIENTRY WinMain(HINSTANCE hinstance, HINSTANCE,
LPSTR cmdLine, int)
{
g_hinstance = hinstance;
RECT lpR;
RECT lpB;
int e=0;
POINT p;
if(!createWindow())
return 0;
SetFocus(g_hwnd);
ShowWindow(g_hwnd, SW_SHOWNORMAL);
UpdateWindow(g_hwnd);
if(!initDirectDraw(800,600,16))
return 0;
g_running = true;
backgrnd = DDLoadBitmap(dd, "backgrnd.bmp", 0, 0);
lpA = DDLoadBitmap(dd, "Greenstone.bmp", 0, 0);
DDSetColorKey(lpA, RGB(0, 0, 0));
lpB.left=0;
lpB.right=800;
lpB.top=0;
lpB.bottom=600;
lpR.left=0;
lpR.right=64;
lpR.top=0;
lpR.bottom=64;
back->BltFast(0, 0, backgrnd, &lpB, DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);
back->BltFast(0, 0, lpA, &lpR, DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);
while(true)
{
MSG msg;
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
return msg.wParam;
// Send messages to WindowProc
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else if(g_running && g_active)
// call variable updates here
// then update() to call screen updates, which flips screen at the end
while (g_running) {
// update();
// for (e=0; eBltFast(0, 0, backgrnd, &lpB, DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);
back->BltFast(ef, 0, lpA, &lpR, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT);
GetCursorPos(&p);
back->BltFast(p.x, p.y, lpA, &lpR, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT);
if (GetAsyncKeyState(VK_ESCAPE)) g_running = false;
if (GetAsyncKeyState(VK_RIGHT)) ef+=1;
flip();
}
}
// Prevent compiler warning even though we never get here
return -1;
}
bool createWindow()
{
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(wc));
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hIconSm = LoadIcon(0, IDI_WINLOGO);
wc.hInstance = g_hinstance;
wc.lpfnWndProc = wndProc;
wc.lpszClassName = g_appName;
wc.cbSize = sizeof(wc);
wc.style = CS_VREDRAW | CS_HREDRAW;
if(RegisterClassEx(&wc))
{
g_hwnd = CreateWindowEx(
WS_EX_TOPMOST,
g_appName,
g_appName,
WS_POPUP | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
0, 0, g_hinstance, 0
);
return g_hwnd != 0;
}
return false;
}
LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
{
switch(msg)
{
case WM_SETCURSOR:
SetCursor(NULL);
return 0;
case WM_KEYDOWN:
if (GetAsyncKeyState(VK_ESCAPE))
msg = WM_DESTROY;
case WM_DESTROY:
cleanUp();
PostQuitMessage(0);
return 0;
case WM_ACTIVATE:
g_active = (LOWORD(w) != WA_INACTIVE) && !((BOOL)HIWORD(w));
break;
}
return DefWindowProc(hwnd, msg, w, l);
}
bool initDirectDraw(int Sx, int Sy, int Sc)
{
HRESULT r = DirectDrawCreateEx(0, (void**)&dd, IID_IDirectDraw7, 0);
if(FAILED(r))
return false;
r = dd->SetCooperativeLevel(g_hwnd, DDSCL_EXCLUSIVE |
DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);
if(FAILED(r))
return false;
r = dd->SetDisplayMode(Sx, Sy, Sc, 0, 0);
if(FAILED(r))
{
dd->Release();
return false;
}
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps =
DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
r = dd->CreateSurface(&ddsd, &primary, 0);
if(FAILED(r))
{
dd->Release();
return false;
}
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
r = primary->GetAttachedSurface(&ddsd.ddsCaps, &back);
if(FAILED(r))
{
primary->Release();
dd->Release();
return false;
}
return true;
}
void clearScreen()
{
DDBLTFX clsBltFX;
ZeroMemory(&clsBltFX, sizeof(clsBltFX));
clsBltFX.dwSize = sizeof(clsBltFX);
back->Blt(0, 0, 0, DDBLT_COLORFILL | DDBLT_WAIT, &clsBltFX);
}
void flip()
{
// dd->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
primary->Flip(0, DDFLIP_WAIT);
}
void cleanUp()
{
if(dd)
{
dd->Release();
if(primary)
primary->Release();
}
}
unsigned char* videoMemory;
long pitch;
void lock()
{
DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof(ddsd);
back->Lock(0, &ddsd, DDLOCK_WAIT, 0);
videoMemory = (unsigned char*)ddsd.lpSurface;
pitch = ddsd.lPitch;
}
void unlock()
{
back->Unlock(0);
}
void setPixel(int x, int y, int c)
{
videoMemory[x + pitch * y] = c;
}
void update()
{
flip();
// clearScreen();
}
I don''t think there is any problem with speed here. The problem is that DDraw probably locks along your screen''s refresh rate, so you only get about 60 or 75 frames per second. And since you are moving the sprite a single pixel each frame, it will only move 60 or 75 pixels per second, which feels slow.
Either try to disable the "vertical retrace", or just speed up the movement of the sprite. I don''t think this is a performance problem, anyway.
Either try to disable the "vertical retrace", or just speed up the movement of the sprite. I don''t think this is a performance problem, anyway.
I find that 1pel/frame is a very slow velocity for sprites. Try like, 4 or 5pels/frame.
Paradigm Shift 2000
Edited by - Paradigm Shift 2000 on October 20, 2001 7:28:16 PM
Paradigm Shift 2000
Edited by - Paradigm Shift 2000 on October 20, 2001 7:28:16 PM
Thank you thank you! It does speed it up and yet it looks smooth, which confuses me..
with this command:
primary->Flip(0, DDFLIP_WAIT);
it looks very smooth and fast, I would think it would move in chunks..
however with this command:
dd->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
it moves in chunks (however many pels/framerate I set it for)...
why is that?
I fseek, therefore I fam.
with this command:
primary->Flip(0, DDFLIP_WAIT);
it looks very smooth and fast, I would think it would move in chunks..
however with this command:
dd->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
it moves in chunks (however many pels/framerate I set it for)...
why is that?
I fseek, therefore I fam.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement