Archived

This topic is now archived and is closed to further replies.

Alec999

DirectDraw problem.. help

Recommended Posts

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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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


Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
For timing try something like this:

  
#define Interval 30
int 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.

Share this post


Link to post
Share on other sites
Hi,

10x for helping...

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

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


Alec999

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
Don''t use the offset by "1",just use more little number (for example 0.09)and use the Time reference to contral the speed and FPS.

goddess just one...

Share this post


Link to post
Share on other sites
Yes,I will say the "S" means speed of a ball.on the assumption that the ball moving just in its x direction and "X" is its position in x axis.I also assume "Delay" is the delay between Frames.
then the following formula is the method of smooth moving:

X=X+S*Delay

x''s units is pixel;
s''s units is pixel per millisecond;
Delay''s units is millisecond;

For example, I want the ball has a speed 20 pixels per second.Then the actual speed of the ball is:
S = 20/1000 = 0.02 (pixel per millisecond)

How to get the Delay?At the beginning os game loop Use the method GetTickCount() to get current tick count on millisecond---"t0".then before render next frame use this method again--"t1".
Delay = t1-t0
For example Delay = 1000 milliseconds
then X=X+0.02*1000

The offect of this frame is 20 pixels.

However there is a problem ,the frame rate.I will give you the method Sleep().I think you can work out it yourself.







goddess just one...

Share this post


Link to post
Share on other sites

  
float PosX; //Xpos of whatever you want to move.

float SpeedInPixPerSecond = 20.0; //20 pixels pr. second.



PosX += SpeedInPixPerSecond * ((float)TimeInMilliseconds/1000.0);



Same applies for y-axis.


Share this post


Link to post
Share on other sites