Archived

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

DirectX application crashes, need help plz...

This topic is 5151 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I''m working on my first DirectX application, but I''m having some trouble: firstly the application is the combination of two other programs: -the first is a DirectX-tutorial that creates me a simple DirectX window. -the second is a part of Andre Lamothe''s particle-demo from his ''tricks of the game programming gurus''. => result = (or should be...) a small DirectX window in which I can start particle explosions simply by clicking in it (thus, not using that little tank...or the rest of the engine,...I need just the particles) I think the problem lies in the Draw_Pixel(), DDraw_Unlock_Back_Surface() and DDraw_Lock_Back_Surface() funtions. ...But I just can''t get it figured out Can anybody help me with this? thx here''s the code: /////////////////////////////////////////////////////////// //DDraw_Class.h file 1/3 /////////////////////////////////////////////////////////// #ifndef DDRAW_CLASS_H #define DDRAW_CLASS_H #include <windows.h> #include <ddraw.h> /////////////////// ///////////////// #include <iostream.h> // include important C/C++ stuff #include <conio.h> #include <stdlib.h> #include <malloc.h> #include <memory.h> #include <string.h> #include <stdarg.h> #include <stdio.h> #include <math.h> #include <io.h> #include <fcntl.h> // The dimensions of our window #define WIN_WIDTH 640 #define WIN_HEIGHT 480 // The width and height of our bitmap #define BMP_WID 400 #define BMP_HGT 200 //--------------------------------------------------------------- //Particle system //--------------------------------------------------------------- #define PARTICLE_STATE_DEAD 0 #define PARTICLE_STATE_ALIVE 1 #define PARTICLE_TYPE_FLICKER 0 #define PARTICLE_TYPE_FADE 1 #define PARTICLE_COLOR_RED 0 #define PARTICLE_COLOR_GREEN 1 #define PARTICLE_COLOR_BLUE 2 #define PARTICLE_COLOR_WHITE 3 #define MAX_PARTICLES 128 #define COLOR_RED_START 32 #define COLOR_RED_END 47 #define COLOR_GREEN_START 96 #define COLOR_GREEN_END 111 #define COLOR_BLUE_START 144 #define COLOR_BLUE_END 159 #define COLOR_WHITE_START 16 #define COLOR_WHITE_END 31 #define RAND_RANGE(x,y) ( (x) + ( rand() % ((y)-(x)+1) ) ); const double PI = 3.1415926535; void Init_Reset_Particles(void); void Start_Particle(int,int,int,float,float,float,float); void Process_Particles(void); void Draw_Particles(void); void Start_Particle_Ring(int ,int ,int ,int ,int ,int ,int ,int ); //--------------------------------------------------------------- //--------------------------------------------------------------- //detect mouse button void MouseButtonDown(int x, int y, BOOL bLeft); extern float cos_look[360]; extern float sin_look[360]; extern int back_lpitch; extern UCHAR *back_buffer; //extern LPDIRECTDRAWSURFACE4 lpddsback;//4 extern DDSURFACEDESC ddsd;//2 #define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); } void Build_Sin_Cos_Tables(void); UCHAR *DDraw_Lock_Back_Surface(void); int DDraw_Unlock_Back_Surface(void); inline int Draw_Pixel(int x, int y,int color,UCHAR *video_buffer, int lpitch); int Draw_Pixel(int x, int y,int color,UCHAR *video_buffer, int lpitch); // This is going to be our Direct Draw object -- It will set up Direct Draw so we // can blit to a window application class DD_OBJ { public: // The Constructor -- Just set everything to NULL for starters DD_OBJ():lpDD(NULL),primarySurface(NULL),backSurface(NULL), clipper(NULL) { /* do nothing */ } bool Init(HWND hwnd); // This basically invokes the Direct Draw required setup code bool InitClipper(HWND hwnd); // This inits the clipper object bool InitSurfaces(); // This inits the primary and back surfaces // This will "fill" our backSurface with the bitmap we pass in bool LoadBackSurface(HINSTANCE hinstance, char *bmp_name); bool Draw(HWND hwnd); // Draw the backSurface to the primarySurface (the screen) // The Deconstructor ~DD_OBJ(); private: LPDIRECTDRAW2 lpDD; // This is an our "main" DirectDraw object // It "comes from" the IDirectDraw2 interface USE4!! LPDIRECTDRAWSURFACE primarySurface; // This is our primary surface (our front buffer) LPDIRECTDRAWSURFACE backSurface; // This is our back surface (our back buffer) LPDIRECTDRAWCLIPPER clipper; // This is our clipper object -- It will clip "Direct Draw" // to our window HDC hdc; // A handle to our device context void Free(); // This private function will free up all memory associated with // the DD_OBJ }; #endif /////////////////////////////////////////////////////////// //DDraw_Class.cpp file 2/3 /////////////////////////////////////////////////////////// #include "DDraw_Class.h" #include <math.h> //----------------------------------------------------------------- //Particle structure //----------------------------------------------------------------- typedef struct PARTICLE_TYP { int state; int type; float x,y; float xv,yv; int curr_color; int start_color; int end_color; int counter; int max_count; } PARTICLE, *PARTICLE_PTR; float particle_wind = 0; float particle_gravity = 0; PARTICLE particles[MAX_PARTICLES]; float cos_look[360]; float sin_look[360]; int back_lpitch = 0; UCHAR *back_buffer = NULL; //LPDIRECTDRAWSURFACE4 lpddsback = NULL; DDSURFACEDESC ddsd;//2 LPDIRECTDRAWSURFACE backSurface = NULL; //----------------------------------------------------------------- //----------------------------------------------------------------- // Set up our DirectDraw interface AND save off a compatible HDC AND load our clipper bool DD_OBJ::Init(HWND hwnd) { HRESULT result; // For the return codes from DirectDraw function/method calls LPDIRECTDRAW temp_lpdd = NULL; // This is a temp LPDIRECTDRAW object -- DirectDrawCreate() // requires we pass in one of these, but once we have this // "interface" we''re going to query it for a IDirectDraw2 interface // By Parameter: /* NULL -- This is a GUID (Globaly Unique ID) that represents which "display driver" we want to use -- By passing in NULL we''re selecting the active "driver" */ // temp_lpdd -- Address of our Direct Draw Structure for initializing // NULL -- Must be NULL (is there for future expansion) result = DirectDrawCreate(NULL,&temp_lpdd,NULL); // Error Check if(result != DD_OK) return false; /* For DirectDraw function/method calls, if they are successful the return value is DD_OK */ // What we doing here is "creating" an IDirectDraw2 Interface (if possible) result = temp_lpdd->QueryInterface(IID_IDirectDraw2,(void**)&lpDD); temp_lpdd->Release(); // It''s served it''s purpose, it''s time to let it go // Error Check if(result != DD_OK) return false; /** Now we want to store a compatible HDC **/ // First we''ll get the window''s HDC HDC win_hdc = GetDC(hwnd); // Error Check if(!win_hdc) return false; // Create the compatible HDC hdc = CreateCompatibleDC(win_hdc); // Free the win_hdc -- It''s served it''s purpose ReleaseDC(hwnd,win_hdc); // Error Check if(hdc == NULL) return false; /** Now we''ll use our new acquired IDirectDraw2 interface to finish initializing **/ // Here we''re "setting the cooperative level" which really just answers the question, // "What is going to be the behavior of this app?" // hwnd -- The handle of the application // DDSCL_NORMAL -- This app will function like a normal Window app result = lpDD->SetCooperativeLevel(hwnd,DDSCL_NORMAL); // Error Check if(result != DD_OK) return false; // Finally we load our clipper (return it''s success or failure) return InitClipper(hwnd); } // This creates a clipper object for us bool DD_OBJ::InitClipper(HWND hwnd) { HRESULT result; // This is for checking the return calls from Direct Draw method calls // This is the function that will create our clipper -- By parameter: // 0 -- This must currently be set to zero // &clipper -- This is the address of a LPDIRECTDRAWCLIPPER object (our clipper object) // It will be filled with our newly created clipper // NULL -- Again this parameter must be NULL (it''s there for expanding the API at a later time) result = DirectDrawCreateClipper(0,&clipper,NULL); // Error Check if(result != DD_OK) return false; // Okay now we''ll set the handle of our clipper to our window hwnd, by parameter: // 0 -- Yet another "future compatibility parameter" this must be zero // hwnd -- The HWND of the window to use as the "clipper window" result = clipper->SetHWnd(0,hwnd); if(result != DD_OK) return false; return true; // Everything went well } // This will init our primary and back surfaces bool DD_OBJ::InitSurfaces() { HRESULT result; // For the return codes from DirectDraw function/method calls // Our Direct Draw surface descriptor -- It will define our surfaces attributes DDSURFACEDESC surfaceDesc = {0}; // Set the stuff we care about for the primary surface surfaceDesc.dwSize = sizeof(DDSURFACEDESC); // Has to be set // Okay this says that the ddsCaps member will be valid (ie filled in) in our // DDSURFACEDESC surfaceDesc.dwFlags = DDSD_CAPS; // Here we setting the ddsCaps -- The flags mean this: // DDSCAPS_VIDEOMEMORY -- This surface will be created in video memory // DDSCAPS_PRIMARYSURFACE -- This surface that will be displayed to the monitor surfaceDesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_PRIMARYSURFACE; // Try and create the surface, by parameter: // &surfaceDesc -- Address of the surface descriptor // &primarySurface -- Address of the where to create the surface // NULL -- This has to be NULL result = lpDD->CreateSurface(&surfaceDesc,&primarySurface,NULL); // Error Check if(result != DD_OK) return false; /* Okay now we''ll change around the DDSURFACEDESC for our "back buffer" */ // The ddsCaps, dwHeight, and dwWidth will be valid member in our DDSURFACEDESC surfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; // Fill in the width and height for our surface surfaceDesc.dwHeight = WIN_HEIGHT; surfaceDesc.dwWidth = WIN_WIDTH; // We make a slight change to our dwCaps // DDSCAPS_VIDEOMEMORY -- This surface will be created in video memory // DDSCAPS_OFFSCREENPLAIN -- Means this surface will be a "rectangular area" in memory // that is commonly used for holding bitmaps/sprites surfaceDesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN; // Now we''ll create our back surface // &surfaceDesc -- Address of the surface descriptor // &backSurface -- Address of the where to create the surface // NULL -- This has to be NULL result = lpDD->CreateSurface(&surfaceDesc,&backSurface,NULL); // Error Check if(result != DD_OK) return false; // Now we need to set our clipper -- Clippers are usually set to surfaces which are // being used as overlays or blitted to the primary surface BUT since our primary // surface needs to be restricted to the size of our window, we''ll set the primary // surface''s clipper result = primarySurface->SetClipper(clipper); // Error Check if(result != DD_OK) return false; // Now we''ll get the backSurface''s HDC HDC bSurfDC = NULL; // To be filled with the backSurface''s HDC // Get the HDC result = backSurface->GetDC(&bSurfDC); // Error Check if(result != DD_OK) return false; // Create a rect defining the backSurface RECT rect = {0,0,WIN_WIDTH,WIN_HEIGHT}; // Remember we set it''s width and height // Fill the backSurface with black // FillRect(bSurfDC,&rect,(HBRUSH)GetStockObject(BLACK_BRUSH)); // Unlock the backSurface (if you don''t do this BAD THINGS HAPPEN result = backSurface->ReleaseDC(bSurfDC); // Error Check if(result != DD_OK) return false; return true; // Surfaces created successfully } // This will load the backSurface with our bitmap // (In a more elaborate application, you could have a surface for each bitmap, draw these // bitmap surfaces to the backSurface, for the current frame, then blit the backSurface // to the primary surface) bool DD_OBJ::LoadBackSurface(HINSTANCE hinstance, char *bmp_name) { // If we didn''t get a "good" file name, return false if(!bmp_name) return false; // Load the bitmap HBITMAP hbitmap = (HBITMAP)LoadImage(hinstance,bmp_name,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); // Error Check if(hbitmap == NULL) return false; // Select the object into our compatible HDC HBITMAP old_bitmap = (HBITMAP)SelectObject(hdc,hbitmap); // Error Check if(old_bitmap == NULL) { DeleteObject(hbitmap); return false; } HDC surfaceDC = NULL; // We''re going to fill this with the HDC of our backSurface // Fill surfaceDC with the backSurface''s HDC HRESULT result = backSurface->GetDC(&surfaceDC); // Error Check if(result != DD_OK) { // Free memory SelectObject(hdc,old_bitmap); DeleteObject(hbitmap); return false; } // Fill the backSurface with the bitmap BitBlt(surfaceDC,120,140,BMP_WID,BMP_HGT,hdc,0,0,SRCCOPY); // **Note the (120,140) comes from the fact our window is (640,480) our bitmap (400,200) // So to center it on the screen, the upper left corner needs to be (120,140) // Effectively "unlock" the backSurface (it''s okay to use again) backSurface->ReleaseDC(surfaceDC); // Free memory SelectObject(hdc,old_bitmap); DeleteObject(hbitmap); return true; } // end of DD_OBJ::LoadBackSurface(HINSTANCE hinstance, char *bmp_name) // This draws the backSurface to the primarySurface bool DD_OBJ::Draw(HWND hwnd) { RECT rect; // This will hold the rect of our window GetWindowRect(hwnd,&rect); // This fills rect with the RECT of our window in // in screen coordinates (ie relative to the screen) DDBLTFX ddbltfx = {0}; // This is the final parameter to be passed to the Blt method // There''s tons of flags and what-not that can be set to // modify your blit any number of ways -- All we''re going to set // is a "No tear flag" that should avoid "tearing" (this can occur // when the screen refresh rate is out of sync with // the application''s frame rate, a blit will actually appear tore) ddbltfx.dwSize = sizeof(DDBLTFX); // This has to be initialized ddbltfx.dwDDFX = DDBLTFX_NOTEARING; // This should avoid tearing // Okay the Blt() method could return this "error code" // which means "the Blt can''t be made cause the hardware is busy" // So when we Blt (blit) we''re going to pass in a flag DDBLT_WAIT that will // keep attempting to Blt until it''s successful or another error has occurred HRESULT result = DDERR_WASSTILLDRAWING; // While we still haven''t flipped while(result == DDERR_WASSTILLDRAWING) // The Blt method by parameter // &rect -- Address of a RECT that specifies the rectangular region to blit to // backSurface -- LPDIRECTDRAWSURFACE that is the source of the blit // NULL -- Address of RECT that specifies the source blit area, if it''s NULL // (like our case) the entire rectangular region of the source surface // will be used // DDBLT_WAIT -- Keeps trying to Blt until successful OR an error has occurred // (other than DDERR_WASSTILLDRAWING) // &ddbltfx -- Address of the DDBLTFX structure we filled in result = primarySurface->Blt(&rect,backSurface,NULL,DDBLT_WAIT,&ddbltfx); /* Remember the above line of code is in the while loop (kinda doesn''t look that way with all the comments above it) */ // Error Check if(result != DD_OK) return false; return true; } // Free all memory associated with DD_OBJ void DD_OBJ::Free() { // If a backSurface has been allocated if(backSurface) { backSurface->Release(); backSurface = NULL; } // If a primarySurface has been allocated if(primarySurface) { primarySurface->Release(); primarySurface = NULL; } // If a clipper has been allocated if(clipper) { clipper->Release(); clipper = NULL; } // If an IDirectDraw2 interface has been instantiated if(lpDD) { lpDD->Release(); lpDD = NULL; } // If the hdc has been filled if(hdc) { DeleteDC(hdc); hdc = NULL; } } // end of DD_OBJ::Free() //get all particles ready for use void Init_Reset_Particles(void) { for(int index=0; index= particles[index].max_count) particles[index].state = PARTICLE_STATE_DEAD; } //}//deze??? else { if(++particles[index].counter >= particles[index].max_count) { particles[index].counter = 0; if(particles[index].curr_color > particles[index].end_color) particles[index].state = PARTICLE_STATE_DEAD; } }//end else //particle off window? if(particles[index].x > WIN_WIDTH || particles[index].x < 0 || particles[index].y > WIN_HEIGHT || particles[index].y < 0) particles[index].state = PARTICLE_STATE_DEAD; }//end if }//end for } void Draw_Particles(void) { DDraw_Lock_Back_Surface(); for(int index=0; index= WIN_WIDTH || x < 0 || y >= WIN_HEIGHT || y < 0) continue; //drawPixel // Draw_Pixel(x,y,particles[index].curr_color, back_buffer, back_lpitch); } } DDraw_Unlock_Back_Surface(); } void Start_Particle_Ring(int type,int color,int count,int x,int y,int vx,int yv,int num_particles) { float vel = 2 + rand()%4; while(--num_particles >= 0) { int ang = rand() % 360; Start_Particle(type, color, count, x, y, vx + cos_look[ang] * vel, yv + sin_look[ang] * vel); } } inline int Draw_Pixel(int x, int y,int color, UCHAR *video_buffer, int lpitch) { // this function plots a single pixel at x,y with color video_buffer[x + y*lpitch] = color; // return success return(1); } // end Draw_Pixel void Build_Sin_Cos_Tables(void) { // create sin/cos lookup table // generate the tables for (int ang = 0; ang < 360; ang++) { // convert ang to radians float theta = (float)ang*PI/(float)180; // insert next entry into table cos_look[ang] = cos(theta); sin_look[ang] = sin(theta); } // end for ang } // end Build_Sin_Cos_Tables UCHAR *DDraw_Lock_Back_Surface(void) { // this function locks the secondary back surface and returns a pointer to it // and updates the global variables secondary buffer, and back_lpitch // is this surface already locked if (back_buffer) { // return to current lock return(back_buffer); } // end if // lock the primary surface DDRAW_INIT_STRUCT(ddsd); backSurface->Lock(NULL,&ddsd,DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,NULL); //lpddsback // set globals back_buffer = (UCHAR *)ddsd.lpSurface; back_lpitch = ddsd.lPitch; // return pointer to surface return(back_buffer); } int DDraw_Unlock_Back_Surface(void) { // this unlocks the secondary // is this surface valid if (!back_buffer) return(0); // unlock the secondary surface backSurface->Unlock(NULL); //lpddsback // reset the secondary surface back_buffer = NULL; back_lpitch = 0; // return success return(1); } // The deconstructor -- When a DD_OBJ is "destroyed" be sure all the memory is freed DD_OBJ::~DD_OBJ() { Free(); } /////////////////////////////////////////////////////////// //win_main.cpp file 3/3 /////////////////////////////////////////////////////////// // Done by TheTutor -- 9/19/01 /* **WARNING** If you''ve updated to DirectX8.0 (or higher), there''s a chance you CAN''T compile this tutorial What we''re going to do here is set up a "windowed" direct draw application. Then we''re going to blit a pretty picture to our "windowed" direct draw app. This isn''t anything that''s going to win ya a programming contest, but it should increase your knowledge about Direct Draw and windowed (ie NOT full screen) apps. */ #include "DDraw_Class.h" // Load our libraries for doing Direct Draw stuff #pragma comment(lib,"ddraw.lib") #pragma comment(lib,"dxguid.lib") #define class_name "DirectDraw_InAWindow" // Global DD_OBJ dd_obj; // Standard callback function LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprev, PSTR cmdline, int ishow) { HWND hwnd; MSG msg; WNDCLASSEX wndclassex = {0}; // Fill the fields we care about wndclassex.cbSize = sizeof(WNDCLASSEX); wndclassex.style = CS_HREDRAW | CS_VREDRAW; wndclassex.lpfnWndProc = WinProc; wndclassex.hInstance = hinstance; wndclassex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wndclassex.lpszClassName = class_name; RegisterClassEx(&wndclassex); // Register the WNDCLASSEX hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, // Window should have a "sunken edge border" class_name, "Particle System", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WIN_WIDTH, // Window''s width WIN_HEIGHT, // Window''s height NULL, NULL, hinstance, NULL); // Error check if(!hwnd) { UnregisterClass(class_name,hinstance); return EXIT_FAILURE; // Something really bad happened! } // Init our DD_OBJ if(dd_obj.Init(hwnd) == false) { MessageBox(hwnd,"Couldn''t init DD_OBJ!","Error",MB_OK | MB_ICONERROR); UnregisterClass(class_name,hinstance); return EXIT_FAILURE; // Something really bad happened! } // Init our DD_OBJ''s surfaces if(dd_obj.InitSurfaces() == false) { MessageBox(hwnd,"Couldn''t init DD_OBJ''s surfaces!","Error",MB_OK | MB_ICONERROR); UnregisterClass(class_name,hinstance); return EXIT_FAILURE; // Something really bad happened! } Build_Sin_Cos_Tables(); Init_Reset_Particles(); // Start_Particle(PARTICLE_TYPE_FADE,PARTICLE_COLOR_GREEN,90,10,20,0,-5); // Process_Particles(); // Draw_Particles(); // Show and update the window ShowWindow(hwnd, ishow); UpdateWindow(hwnd); while(1) { // Get message(s) if there is one if(PeekMessage(&msg,hwnd,0,0,PM_REMOVE)) { if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else { // Do all the hardcore computational stuff here %) } } // Free Memory UnregisterClass(class_name,hinstance); // Frees memory with WNDCLASSEX return msg.wParam; } // The WinProc LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { // Depending on the message -- we''ll do different stuff switch(message) { // If they drag the window, redraw our pretty picture case WM_MOVE: dd_obj.Draw(hwnd); return 0; // ESC will quit program case WM_KEYDOWN: if((int)wparam == VK_ESCAPE) PostQuitMessage(0); return 0; // case WM_SETCURSOR: // Turn off window cursor. // SetCursor( 0 ); // ShowCursor( TRUE ); // return TRUE; // Prevent Windows from setting cursor to window class cursor. case WM_LBUTTONDOWN: MouseButtonDown(LOWORD(lparam), HIWORD(lparam), TRUE); return 0; case WM_DESTROY: case WM_CLOSE: PostQuitMessage(0); return 0; } // end of switch(message) return DefWindowProc(hwnd, message, wparam, lparam); } void MouseButtonDown(int x, int y, BOOL bLeft) { // MessageBox(NULL,"Left MB Pressed","Info",MB_OK | MB_ICONINFORMATION); // Build_Sin_Cos_Tables(); // Init_Reset_Particles(); // Start_Particle(PARTICLE_TYPE_FADE,PARTICLE_COLOR_GREEN,90,10,20,0,-5); // Start_Particle_Ring(PARTICLE_TYPE_FADE, PARTICLE_COLOR_RED+rand()%4, RAND_RANGE(2,5), x, y, 0, 0,RAND_RANGE(75,100)); Start_Particle_Ring(PARTICLE_TYPE_FADE, PARTICLE_COLOR_RED+rand()%4, RAND_RANGE(2,5), missiles[index].x, missiles[index].y, 0, 0,RAND_RANGE(75,100)); Process_Particles(); // Draw_Particles(); }

Share this post


Link to post
Share on other sites