DirectDraw problem.. help

Started by
12 comments, last by Alec999 22 years, 2 months ago
Hi, I have a problem in DirectDraw windowd mode for 1 year now I am doing sth. like bouncing ball in windowed mode using Vc++ and DirectDraw7 ... but the ball is not smooth all the time (it jumps for more moves than it should be).. can you pleas give me some source code for windowed mode or tell me what i must do to load a bitmap ball form a file and move it smooth. pleas help me .. my head hurts i can"t figure this out Alec999
The only easy day was yesterday.
Advertisement
Its sounds like either you are''nt getting enough FPS, or more likely your movement code has an error.

Try posting the code you are using to move the ball.

,Jay
here is the hole code ... healp me pleas
*****************************************
#define WIN32_MEAN_AND_LEAN

#include <windows.h>
#include <ddraw.h>
#include "ddutil.h"
#include "resource.h"


#pragma warning (disable:4244)


#define HITROST 280

HWND hWnd;
HINSTANCE hInst;
HMENU hMenu;



HDC hdc;

static char g_szClassName[] = "MyWindowClass";

const int W_WIDTH = 640;
const int W_HEIGHT = 480;

RECT rcBack, rcWnd;


LPDIRECTDRAW7 pDD;
LPDIRECTDRAWSURFACE7 pPrimary, pBackBuffer, pSmile, pBrisi;
LPDIRECTDRAWCLIPPER pClipper;
DDSURFACEDESC2 ddSurface;
DDSCAPS2 ddCaps;




int smileX, smileY;
int deltaV;


int BarvnaGlobina;

POINT p1, p2;

bool gamerun;

BOOL MoveLeft = 0;
BOOL MoveRight = 0;
BOOL MoveUp = 0;
BOOL MoveDown = 0;

void CheckSurfaces()
{
// Check the primary surface
if (pPrimary)
{
if (pPrimary->IsLost() == DDERR_SURFACELOST)
pPrimary->Restore();
}
// Check the back buffer
if (pBackBuffer)
{
if (pBackBuffer->IsLost() == DDERR_SURFACELOST)
pBackBuffer->Restore();
}
}


void PreveriGlobino(void){

ddSurface.dwSize = sizeof(DDSURFACEDESC2);
pDD->GetDisplayMode( &ddSurface );

if( ddSurface.ddpfPixelFormat.dwRGBBitCount == 8 ){
MessageBox(NULL, "You must set your graphic to 16,24 or 32 bit color!", "Note", MB_OK | MB_SYSTEMMODAL);
PostQuitMessage(0);
}

if( ddSurface.ddpfPixelFormat.dwRGBBitCount == 16 ){
BarvnaGlobina=16;
}

if( ddSurface.ddpfPixelFormat.dwRGBBitCount == 24 ){
BarvnaGlobina=32;
}

if( ddSurface.ddpfPixelFormat.dwRGBBitCount == 32 ){
BarvnaGlobina=32;
}


}


void BrisiVse(void){
DDBLTFX brisi;

UCHAR r, g, b;
UINT barva;
/*
if(BarvnaGlobina==8){
r = 214 >> 3;
g = 211 >> 2;
b = 206 >> 3;
barva = r | g | b;

memset(&brisi, 0, sizeof(DDBLTFX));
brisi.dwSize = sizeof(DDBLTFX);
brisi.dwFillColor = barva;
}
*/

if(BarvnaGlobina==16){
r = 214 >> 3;
g = 211 >> 2;
b = 206 >> 3;
barva = (r << 11) | (g << 5) | b;

memset(&brisi, 0, sizeof(DDBLTFX));
brisi.dwSize = sizeof(DDBLTFX);
brisi.dwFillColor = barva;
}


if(BarvnaGlobina==32){
memset(&brisi, 0, sizeof(DDBLTFX));
brisi.dwSize = sizeof(DDBLTFX);
brisi.dwFillColor = RGB(206,211,214);
}



pBackBuffer->Blt(NULL, pBrisi, NULL, DDBLT_COLORFILL, &brisi);

}


void RisiSmile(void){

RECT rcSmile, rcDest;

SetRect(&rcDest, 0, 0, 0, 0);
rcDest.left += smileX;
rcDest.top += smileY;
rcDest.right = rcDest.left + 30;
rcDest.bottom = rcDest.top + 30;


SetRect(&rcSmile, 0, 0, 30, 30);




pBackBuffer->Blt(&rcDest, pSmile, &rcSmile, DDBLT_WAIT | DDBLT_KEYSRC, NULL);
// pBackBuffer->BltFast( smileX, smileY, pSmile, &rcSmile, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY);



}

void UpdateSmile(double time)
{

deltaV = time*HITROST;



if(MoveLeft)
smileX -= deltaV;


if(MoveRight)
smileX+=deltaV;


if(MoveUp)
smileY-=deltaV;


if(MoveDown)
smileY+=deltaV;




if(smileX<0)
smileX = 0;


if(smileX>W_WIDTH-10-30)
smileX = W_WIDTH-10-30;


if(smileY<0)
smileY = 0;


if(smileY>W_HEIGHT-30-48-20)
smileY = W_HEIGHT-30-48-20;



}



//-----------------------------------------------------------------------------//
int CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam){

switch(Message){

case WM_COMMAND:

switch(wParam){

static char Buffer[100];



//--------------------------------------------//
case ID_FILE_EXIT:
PostMessage(hWnd, WM_CLOSE, 0, 0);
break;

}//-- konec WM_Command switcha

return 0;
//-----------------------------------------------------------//
//----------------- Keys ------------------------------------//
case WM_KEYDOWN:
switch(wParam){

case VK_F12:
PostMessage(hWnd, WM_COMMAND, ID_FILE_EXIT, 0);
break;

/************Movements For Smile************/
case VK_LEFT:
MoveLeft = true;
break;

case VK_RIGHT:
MoveRight = true;
break;

case VK_UP:
MoveUp = true;
break;

case VK_DOWN:
MoveDown = true;
break;

}

return 0;
//--------------------- KEY UP -------------------------------------//
case WM_KEYUP:
switch(wParam){

case VK_LEFT:
MoveLeft = false;
break;

case VK_RIGHT:
MoveRight = false;
break;

case VK_UP:
MoveUp = false;
break;

case VK_DOWN:
MoveDown = false;
break;

}

return 0;

//-----------------------------------------------------------------//
case WM_CREATE:
{


//
HRESULT hr;


DirectDrawCreateEx(NULL, (void**)&pDD, IID_IDirectDraw7, NULL);


hr = pDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);
if(hr != DD_OK)
MessageBox(NULL, NULL, NULL, NULL);


//----------- Primary -----------------//
pPrimary = NULL;

memset(&ddSurface, 0, sizeof(ddSurface));
ddSurface.dwSize = sizeof( ddSurface );
ddSurface.dwFlags = DDSD_CAPS;
ddSurface.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

hr = pDD->CreateSurface(&ddSurface, &pPrimary, NULL);
if(hr != DD_OK)
MessageBox(NULL, NULL, NULL, NULL);


//----------- Clipper ------------------//
// Create the clipper using the DirectDraw object
hr = pDD->CreateClipper(0, &pClipper, 0);
if(hr != DD_OK)
MessageBox(NULL, NULL, NULL, NULL);

// Assign your window''s HWND to the clipper
hr = pClipper->SetHWnd(0, hWnd);
if(hr != DD_OK)
MessageBox(NULL, NULL, NULL, NULL);

// Attach the clipper to the primary surface
hr = pPrimary->SetClipper(pClipper);
if(hr != DD_OK)
MessageBox(NULL, NULL, NULL, NULL);

//----------- Secondary -----------------//
pBackBuffer = NULL;

memset(&ddSurface, 0, sizeof(ddSurface));
ddSurface.dwSize = sizeof( ddSurface );
ddSurface.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddSurface.dwWidth = W_WIDTH; // whatever you want
ddSurface.dwHeight = W_HEIGHT; // whatever you want
ddSurface.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;



hr = pDD->CreateSurface(&ddSurface, &pBackBuffer, NULL);
if(hr != DD_OK)
MessageBox(NULL, NULL, NULL, NULL);





PreveriGlobino(); //-- preveri globino baru na racunalniku


//------//
pSmile = DDLoadBitmap(pDD, "balls.bmp", 128, 128);
DDSetColorKey(pSmile, RGB(255, 255, 255));
//------//






}break;

//-----------------------------------------------------------------//
case WM_PAINT:
PAINTSTRUCT ps;
BeginPaint(hWnd,&ps);


if( NULL == pPrimary )
return E_FAIL;



GetClientRect(hWnd, &rcWnd);
p1.x = rcWnd.left;
p1.y = rcWnd.top;
p2.x = rcWnd.right;
p2.y = rcWnd.bottom;
ClientToScreen(hWnd, &p1);
ClientToScreen(hWnd, &p2);
SetRect(&rcWnd, p1.x, p1.y, p2.x, p2.y);



// return pPrimary->Blt(&rcWnd, pBackBuffer, &rcBack, DDBLT_WAIT, NULL);



EndPaint(hWnd,&ps);
break;
//----------------------------------------------------------------//

case WM_CLOSE:
DestroyWindow(hWnd);
return 0;
//----------------------------------------------------------------//
case WM_DESTROY:
PostQuitMessage(0);
break;
//----------------------------------------------------------------//
case WM_QUIT:

if(pDD){

pDD->Release();
pDD = NULL;

if(pSmile){
pSmile->Release();
pSmile = NULL;
}

if(pBrisi){
pBrisi->Release();
pBrisi = NULL;
}
if(pBackBuffer){
pBackBuffer->Release();
pBackBuffer = NULL;
}


if(pPrimary){
pPrimary->Release();
pPrimary = NULL;
}

}


break;
//-------------------------------------------------------//
default:
return DefWindowProc(hWnd, Message, wParam, lParam);

}


return false;

}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hInstPrev, LPSTR lpCmdLine, int nCmdShow){

hInst = hInstance;


WNDCLASSEX window;
MSG Msg;

window.cbSize = sizeof(WNDCLASSEX);
window.style = CS_HREDRAW|CS_VREDRAW;
window.cbClsExtra = 0;
window.cbWndExtra = 0;
window.lpfnWndProc = (WNDPROC)WndProc;
window.hInstance = hInst;
window.hbrBackground = CreateSolidBrush(RGB(214,211,206));
window.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IKONE));
window.hIconSm = LoadIcon(NULL, NULL);
window.hCursor = LoadCursor(NULL, IDC_CROSS);
window.lpszMenuName = (LPCSTR)MyMenu;
window.lpszClassName = g_szClassName;

RegisterClassEx(&window);



hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"BALLS - beta DX7 build 15022002",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, W_WIDTH, W_HEIGHT,
NULL, NULL, hInst, NULL);



ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);

hMenu = GetMenu(hWnd);


// gamerun = true;
GetClientRect(hWnd, &rcBack);



LONGLONG frekvenca, counter, counter2;
double na_sekundo;


QueryPerformanceFrequency((LARGE_INTEGER*)&frekvenca);

na_sekundo = 1.0f / frekvenca;

QueryPerformanceCounter((LARGE_INTEGER*)&counter);

while(TRUE){

if(PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE)){


// if(!GetMessage(&Msg, NULL, 0, 0)){
// gamerun = false;
// break;
// }

// retrieve a message
GetMessage(&Msg, NULL, NULL, NULL);

if( Msg.message == WM_QUIT )
break; // only way out of the for( MAIN ) loop


// dispatch the message to our WndProc


TranslateMessage(&Msg);
DispatchMessage(&Msg);


}
else
{



/* if(gamerun)
{
*/


QueryPerformanceCounter((LARGE_INTEGER*)&counter2);
counter2 = counter2 - counter;
QueryPerformanceCounter((LARGE_INTEGER*)&counter);
//counter = counter2;



CheckSurfaces();
BrisiVse();
UpdateSmile(counter2*na_sekundo);
RisiSmile();





pDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL);
pClipper->SetHWnd(NULL, hWnd);
pPrimary->Blt(&rcWnd, pBackBuffer, &rcBack, DDBLT_WAIT, NULL);




// }


}

}


return Msg.wParam;


}


*******************************************
Alec999


The only easy day was yesterday.
Try incrementing/decrementing ''smile'' (ball?) rather than adding or subtracting time*HITROST.

replace this:

  if(MoveLeft)smileX -= deltaV;if(MoveRight)smileX+=deltaV;if(MoveUp)smileY-=deltaV;if(MoveDown)smileY+=deltaV;  


with this:

  if(MoveLeft)smileX --;if(MoveRight)smileX++;if(MoveUp)smileY--;if(MoveDown)smileY++;  


If you were using this to time the ball this is the wrong way to go about it, try looking at some of the tutorials on this site.

,Jay
I am using that to make it run on all computers with the same speed. And I tried "if(MoveLeft)smileX --;if(MoveRight)smileX++;if(MoveUp)smileY--;if(MoveDown)smileY++; " before and it doesn"t help me ....


I am very sad ... becouse I can"t belive it is sooo hard to make
smoot bouncing ball or small pic. moveing ...


I am even willing to pay like 10$ to the person that
makes smooth and fast bouncing ball under DirectDraw windowed mode


Alec999
The only easy day was yesterday.
For timing try something like this:

  #define Interval 30int StartTime = 0;void UpdateSmile(){  if(StartTime+Interval>=TimeGetTime()){      // DoUpdate           if(MoveLeft)smileX --;      if(MoveRight)smileX++;      if(MoveUp)smileY--;      if(MoveDown)smileY++;        if(smileX<0) smileX = 0;      if(smileX>W_WIDTH-10-30)smileX = W_WIDTH-10-30;      if(smileY<0)smileY = 0;      if(smileY>W_HEIGHT-30-48-20)smileY = W_HEIGHT-30-48-20;      StartTime=TimeGetTime();      }}  



Thats a better way of handling timing, if you still get large movments across the screen its because somewhere else in your code somethings using a lot of proccessor time.

One such instance might because you are refilling your background surface each instance. take

  pBackBuffer->Blt(NULL, pBrisi, NULL, DDBLT_COLORFILL, &brisi);  


this out of BrisiVse and place it in

  CheckSurfaces(); // BrisiVse();UpdateSmile();pBackBuffer->Blt(NULL, pBrisi, NULL, DDBLT_COLORFILL, &brisi);RisiSmile();  


you will still have to call BrisiVse, but only at the start of the program and inside CheckSurfaces. If your using a colour fill there is a particular call for it within directdraw that might speed things up even more.

To play with the speed alter ''Interval'' up or down.

,Jay

PS: Look at the FAQ for source code tags.
Hi,

10x for helping...

i get TimeGetTime(); : undeclared identifier .. error

do I have to include some .h to get TimeGetTime() ?


Alec999
The only easy day was yesterday.
ok I solved that one .... i had to include mmsystem.h and winmm.lib

The only easy day was yesterday.
well the ball is still not smooth

what F.A.Q. should I look


I think I am not getting enough speed .. i don"t know what is holding it back. Its not the cleaning of the screen becouse if i have no cleaning than it still isnt smooth
The only easy day was yesterday.
Coukld it be HDD ... my light on HDD blinks like once every second ... and the moving of the ball is simila ... when HDD
blinks it stops a little (but i can say that 100%)

i tried upping the priorty but it doesnt help

The only easy day was yesterday.

This topic is closed to new replies.

Advertisement