Original Post
I'm about to go postal here. This has been a problem for about 2 weeks now. It's such a simple thing. You can hardly make a 2D game without doing it. Why is it so hard for me? ARRGH!
Anyway, I followed this tutorial exactly. In fact, I copied and pasted the code right into my project. Everything compiles fine. The only change I had to make to the code was to cast the return value of LoadImage to an (HBITMAP). But that's it. It compiles fine.
I use the code to load the bitmap into an offscreen surface and then I blit it to the screen buffer, and then flip the page. But instead of it doing what its supposed to do, when it runs I simply get a blank screen (along with all the junk that was on the back buffer.
Has anyone had a similar problem with those functions? Is there something wrong with the code you see there? I'll supply the code for my program as well:
[edited by - utwo on May 19, 2003 11:08:23 PM]
// INCLUDES ////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <windowsx.h>
#include <initguid.h>
#include <ddraw.h>
#include "resource.h"
// DEFINES /////////////////////////////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN
#define INITGUID
// CONSTANTS & GLOBALS /////////////////////////////////////////////////////////
HWND hwnd;
LPDIRECTDRAW lpdd = NULL;
LPDIRECTDRAW7 lpdd7 = NULL;
LPDIRECTDRAWSURFACE7 lpddsprimary = NULL;
LPDIRECTDRAWSURFACE7 lpddssecondary = NULL;
LPDIRECTDRAWSURFACE7 lpddstitle = NULL;
LPDIRECTDRAWSURFACE7 lpddsmenu = NULL;
LPDIRECTDRAWSURFACE7 lpddsgame = NULL;
// MACROS //////////////////////////////////////////////////////////////////////
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
// PROTOTYPES //////////////////////////////////////////////////////////////////
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);
int Game_Init();
int Game_Shutdown();
int Game_Main();
// These functions will load a bitmap from a resource into a new offscreen surface.
void CreateBitmapSurface(LPDIRECTDRAWSURFACE7 lpSurface, char *fname, int xs, int ys);
void DrawHBitmap(IDirectDrawSurface7 *lpSurface, HBITMAP hBitmap, int x, int y, int width, int height);
void CreateSurface(LPDIRECTDRAWSURFACE7 *lpSource, int xs, int ys);
////////////////////////////////////////////////////////////////////////////////
// END OF HEADER //
////////////////////////////////////////////////////////////////////////////////
// //
// ŽŽ ŽŽ //
// ŽŽ ŽŽ //
// ŽŽŽŽŽŽŽŽŽŽŽŽŽŽ //
// ŽŽŽŽ ŽŽŽŽŽŽ ŽŽŽŽ //
// ŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽ //
// ŽŽ ŽŽŽŽŽŽŽŽŽŽŽŽŽŽ ŽŽ //
// ŽŽ ŽŽ ŽŽ ŽŽ //
// ŽŽŽŽ ŽŽŽŽ //
// //
////////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
// Structures for window class and messages
MSG msg;
WNDCLASSEX wndclass;
// Define window class.
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC | CS_DBLCLKS;
wndclass.lpfnWndProc = WinProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = "winclass1";
wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
// Resgister class, create and show window.
if(!RegisterClassEx(&wndclass))
{
MessageBox(NULL, "Class registration failed.", "Error", MB_OK);
}
if(!(hwnd = CreateWindowEx(0, "winclass1", "Super Metris", WS_POPUP, 50, 50, 640, 480, NULL, NULL, hInstance, NULL)))
{
MessageBox(NULL, "Window creation failed.", "Error", MB_OK);
}
ShowWindow(hwnd, nShowCmd);
// Initialize program, enter game loop, and shut down game
Game_Init();
while(1)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT) { break; } // end if
TranslateMessage(&msg);
DispatchMessage(&msg);
} // end if
Game_Main();
} // end while
Game_Shutdown();
return 0;
} // end WINMAIN
// Callback Procedure
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_CLOSE : {
Game_Shutdown();
PostQuitMessage(0);
}
}
return (DefWindowProc(hwnd,msg,wparam,lparam));
}
int Game_Init()
{
// Create the DirectDraw object
if(FAILED(DirectDrawCreate(NULL, &lpdd, NULL)))
{
MessageBox(NULL, "Failed to create DirectDraw object.", "Error", MB_OK);
}
// Use DirectDraw object to create DirectDraw7 object
if(FAILED(lpdd->QueryInterface(IID_IDirectDraw7, (LPVOID *)&lpdd7)))
{
MessageBox(NULL, "Failed to create DirectDraw 7 object.", "Error", MB_OK);
}
// Release DirectDraw object
lpdd->Release();
lpdd = NULL;
// Set Cooperative Level
if(FAILED(lpdd7->SetCooperativeLevel(hwnd, DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_ALLOWMODEX)))
{
MessageBox(NULL, "Failed to set cooperation level.", "Error", MB_OK);
}
// Set Display Mode
if(FAILED(lpdd7->SetDisplayMode(800,600,32,0,0)))
{
MessageBox(NULL, "Failed to set display mode.", "Error", MB_OK);
}
// Create Primary Surface
DDSURFACEDESC2 ddsd; // surface description
ZeroMemory(&ddsd, sizeof(ddsd)); // clear DDSD's memory
ddsd.dwSize = sizeof(ddsd); // Size of DDSD
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; // Which flags we're specifying
ddsd.dwBackBufferCount = 1;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX |
DDSCAPS_FLIP; // Make PRIMARY, COMPLEX, FLIPABLE surface
if(FAILED(lpdd7->CreateSurface(&ddsd, &lpddsprimary, NULL)))
{
MessageBox(NULL, "Failed to create primary surface.", "Error", MB_OK);
}
// Get secondary surface and assign to lpddssecondary.
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
if(FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddssecondary)))
{
MessageBox(NULL, "Failed to create secondary surface.", "Error", MB_OK);
}
CreateBitmapSurface(lpddstitle, "C:/0progproj/DirectX/utwo.bmp", 300, 300);
RECT source;
RECT dest;
source.left = 0;
source.top = 0;
source.right = 300;
source.bottom = 300;
dest.left = 0;
dest.top = 300;
dest.right = 300;
dest.bottom = 300;
lpddssecondary->Blt(&dest, lpddstitle, &source, DDBLT_WAIT, NULL);
lpddsprimary->Flip(NULL, DDFLIP_WAIT);
}
int Game_Shutdown()
{
if(lpdd7)
{
lpdd7->Release();
lpdd7 = NULL;
}
if(lpddsprimary)
{
lpddsprimary->Release();
lpddsprimary = NULL;
}
if(lpddssecondary)
{
lpddssecondary->Release();
lpddssecondary = NULL;
}
if(lpddstitle)
{
lpddstitle->Release();
lpddstitle = NULL;
}
if(lpddsmenu)
{
lpddsmenu->Release();
lpddsmenu = NULL;
}
if(lpddsgame)
{
lpddsgame->Release();
lpddsgame = NULL;
}
return 1;
}
int Game_Main()
{
if(KEYDOWN(VK_UP))
{
Game_Shutdown();
PostQuitMessage(0);
}
}
void CreateSurface(LPDIRECTDRAWSURFACE7 *lpSource, int xs, int ys)
{
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = xs;
ddsd.dwHeight = ys;
lpdd7->CreateSurface(&ddsd, lpSource, NULL);
}
void DrawHBitmap(IDirectDrawSurface7 *lpSurface, HBITMAP hBitmap, int x, int y, int width, int height)
{
HDC hdcImage;
HDC hdc;
BITMAP bm;
if (lpSurface == NULL || hBitmap == NULL) return;
lpSurface->Restore();
hdcImage = CreateCompatibleDC(NULL);
SelectObject(hdcImage, hBitmap);
GetObject(hBitmap, sizeof(bm), &bm);
width = width == 0 ? bm.bmWidth : width;
height = height == 0 ? bm.bmHeight : height;
lpSurface->GetDC(&hdc);
BitBlt(hdc, x, y, width, height, hdcImage, 0, 0, SRCCOPY);
lpSurface->ReleaseDC(hdc);
DeleteDC(hdcImage);
}
void CreateBitmapSurface(LPDIRECTDRAWSURFACE7 lpSurface, char *fname, int xs, int ys)
{
HBITMAP hBitmap;
CreateSurface(&lpSurface, xs, ys);
hBitmap = (HBITMAP)LoadImage(NULL, fname, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
DrawHBitmap(lpSurface, hBitmap, 0, 0, xs, ys);
DeleteObject(hBitmap);
}