Archived

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

brianhj

Another newbie question :)

Recommended Posts

brianhj    122
Hey it''s me... what do you expect? I was well on my way to making Quake 4 when I ran into a little problem. I found that article my Andre Lamothe about how to set up DirectX in VC++. And much to my delight, the article was aimed at game development! (what''s the name of this web site again?) Anywho, I was reading the article with renewed hope when I ran smack dab into a wall. DirecX 5. DIRECTX 5. Ouch. I load the source code anyway thinking hell, maybe I''ll get lucky and it will work with DirectX 7. Well, it didn''t. I''ve tried editing the code based on SDK samples, but to no avail. I''m a newbie, mind you, and if anyone here still remembers what it was like to be a newbie in Windows (Walls? Who said that?!) Programming and that someone is willing to help me translate this code into DirectX 7 / VC++ 6 then... well, then help me. I''d just like to get it working like he says it will in the article. Moving blob and all. Here''s the code: http://www.gamedev.net/reference/articles/article589.asp Thank you so much, Brian

Share this post


Link to post
Share on other sites
Nytegard    839
The code that was on the page works with DirectX 7. Tested it and it works. What I think you might be believing is wrong is not with DX7, rather the compiler used. It uses several conventions that were popular in VC++5, but have changed in VC++6.

Just remember to include winmm.lib and ddraw.lib in your project.

Project->Settings->Object/library modules.
Only two lines of code you need to change are lines 239 and lines 282.



winclass.hbrBackground = GetStockObject(BLACK_BRUSH);
becomes
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

EndPaint(hdc,&ps);
becomes
EndPaint(hwnd,&ps);

This should be the working source:

    
// LISTING 1.0 - DIRECT X 5.0 GAME CONSOLE ////////////////////////////////////


// INCLUDES ///////////////////////////////////////////////////////////////////


#define WIN32_LEAN_AND_MEAN // make sure certain headers are included correctly


#include <windows.h> // include the standard windows stuff
#include <windowsx.h> // include the 32 bit stuff
#include <mmsystem.h> // include the multi media stuff
// note you need winmm.lib also

#include <ddraw.h> // include direct draw components


#include <stdlib.h> // include all the good stuff
#include <stdio.h>
#include <math.h>
#include <float.h>


// DEFINES ////////////////////////////////////////////////////////////////////


#define WINDOW_CLASS_NAME "WINDOW_CLASS" // this is the name of the window class


// defines for screen parameters


#define SCREEN_WIDTH 640 // the width of the viewing surface
#define SCREEN_HEIGHT 480 // the height of the viewing surface
#define SCREEN_BPP 8 // the bits per pixel
#define MAX_COLORS 256 // the maximum number of colors


// TYPES //////////////////////////////////////////////////////////////////////


typedef unsigned char UCHAR;

// MACROS /////////////////////////////////////////////////////////////////////


// these query the keyboard in real-time


#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

// PROTOTYPES /////////////////////////////////////////////////////////////////


int DD_Init(HWND hwnd);
int DD_Shutdown(void);
int Set_Pal_Entry(int index, int red, int green, int blue);

void Game_Init(void);
void Game_Main(void);
void Game_Shutdown(void);

// DIRECTDRAW GLOBALS ////////////////////////////////////////////////////////


LPDIRECTDRAW lpdd = NULL; // dd object

LPDIRECTDRAWSURFACE lpddsprimary = NULL; // dd primary surface

LPDIRECTDRAWPALETTE lpddpal = NULL; // a pointer to the created dd palette

PALETTEENTRY color_palette[256]; // holds the shadow palette entries

DDSURFACEDESC ddsd; // a direct draw surface description struct

DDSCAPS ddscaps; // a direct draw surface capabilities struct

HRESULT ddrval; // result back from dd calls

HWND main_window_handle = NULL; // used to store the window handle

UCHAR *video_buffer = NULL; // pointer to video ram



// GAME GLOBALS GO HERE /////////////////////////////////////////////////////


// DIRECT X FUNCTIONS /////////////////////////////////////////////////////////


int DD_Init(HWND hwnd)
{
// this function is responsible for initializing direct draw, it creates a
// primary surface


int index; // looping index


// now that the windows portion is complete, start up direct draw
if (DirectDrawCreate(NULL,&lpdd,NULL)!=DD_OK)
{
// shutdown any other dd objects and kill window

DD_Shutdown();
return(0);
} // end if


// now set the coop level to exclusive and set for full screen and mode x

if (lpdd->SetCooperativeLevel(hwnd, DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE |
DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX)!=DD_OK)
{
// shutdown any other dd objects and kill window

DD_Shutdown();
return(0);
} // end if


// now set the display mode

if (lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP)!=DD_OK)
{
// shutdown any other dd objects and kill window

DD_Shutdown();
return(0);
} // end if


// Create the primary surface

ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

if
(lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)!=DD_OK)
{
// shutdown any other dd objects and kill window

DD_Shutdown();
return(0);
} // end if


// create the palette and attach it to the primary surface


// clear all the palette entries to RGB 0,0,0
memset(color_palette,0,256*sizeof(PALETTEENTRY));

// set all of the flags to the correct value

for (index=0; index<256; index++)
{
// create the GRAY/RED/GREEN/BLUE palette, 64 shades of each
if ((index / 64)==0)
{
color_palette[index].peRed = index*4;
color_palette[index].peGreen = index*4;
color_palette[index].peBlue = index*4;
} // end if

else
if ((index / 64)==1)
color_palette[index].peRed = (index%64)*4;
else
if ((index / 64)==2)
color_palette[index].peGreen = (index%64)*4;
else
if ((index / 64)==3)
color_palette[index].peBlue = (index%64)*4;

// set the no collapse flag

color_palette[index].peFlags = PC_NOCOLLAPSE;

} // end for index


// now create the palette object, note that it is a member of the dd object itself
if (lpdd->CreatePalette((DDPCAPS_8BIT | DDPCAPS_INITIALIZE),color_palette,&lpddpal,NULL)!=DD_OK)
{
// shutdown any other dd objects and kill window

DD_Shutdown();
return(0);
} // end if


// now attach the palette to the primary surface

lpddsprimary->SetPalette(lpddpal);

// return success if we got this far

return(1);

} // end DD_Init


///////////////////////////////////////////////////////////////////////////////


int DD_Shutdown(void)
{
// this function tests for dd components that have been created and releases

// them back to the operating system


// test if the dd object exists

if (lpdd)
{
// test if there is a primary surface

if(lpddsprimary)
{
// release the memory and set pointer to NULL

lpddsprimary->Release();
lpddsprimary = NULL;
} // end if


// now release the dd object itself

lpdd->Release();
lpdd = NULL;

// return success

return(1);

} // end if

else
return(0);

} // end DD_Shutdown


//////////////////////////////////////////////////////////////////////////////


int Set_Pal_Entry(int index, int red, int green, int blue)
{
// this function sets a palette entry with the sent color


PALETTEENTRY color; // used to build up color


// set RGB value in structure

color.peRed = (BYTE)red;
color.peGreen = (BYTE)green;
color.peBlue = (BYTE)blue;
color.peFlags = PC_NOCOLLAPSE;

// set the color palette entry

lpddpal->SetEntries(0,index,1,&color);

// make copy in shadow palette

memcpy(&color_palette[index],
&color,
sizeof(PALETTEENTRY));

// return success

return(1);

} // end Set_Pal_Entry


// WINDOWS CALLBACK FUNCTION //////////////////////////////////////////////////


LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
// this is the main message handler of the system


HDC hdc; // handle to graphics context

PAINTSTRUCT ps; // used to hold the paint info


// what is the message?


switch(msg)
{
case WM_CREATE:
{
// do windows inits here

return(0);
} break;

case WM_PAINT:
{
// this message occurs when your window needs repainting

hdc = BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);

return(0);
} break;

case WM_DESTROY:
{
// this message is sent when your window is destroyed

PostQuitMessage(0);
return(0);
} break;

default:break;

} // end switch


// let windows process any messages that we didn't take care of

return (DefWindowProc(hwnd, msg, wparam, lparam));

} // end WinProc


// WINMAIN ////////////////////////////////////////////////////////////////////


int WINAPI WinMain( HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow)
{
WNDCLASSEX winclass; // this holds the windows class info

HWND hwnd; // this holds the handle of our new window

MSG msg; // this holds a generic message


// first fill in the window class stucture


winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;

// register the window class

if (!RegisterClassEx(&winclass))
return(0);

// create the window

if (!(hwnd = CreateWindowEx(WS_EX_TOPMOST,
WINDOW_CLASS_NAME, // class

"You can't See This!", // title

WS_VISIBLE | WS_POPUP,
0,0, // x,y
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL, // parent

NULL, // menu

hinstance, // instance

NULL))) // creation parms

return(0);

// hide the mouse cursor

ShowCursor(0);

// save the window handle

main_window_handle = hwnd;

// initialize direct draw

if (!DD_Init(hwnd))
{
DestroyWindow(hwnd);
return(0);
} // end if


// initialize game

Game_Init();

// enter main event loop

while(1)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
// test if this is a quit

if (msg.message == WM_QUIT)
break;

// translate any accelerator keys

TranslateMessage(&msg);

// send the message to the window proc

DispatchMessage(&msg);
} // end if

else
{
// do asynchronous processing here


// acquire pointer to video ram, note it is always linear
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
lpddsprimary->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR,NULL);
video_buffer = (UCHAR *)ddsd.lpSurface;

// call main logic module

Game_Main();

// release pointer to video ram

lpddsprimary->Unlock(ddsd.lpSurface);

} // end else


} // end while


// shut down direct draw

DD_Shutdown();

// shutdown game

Game_Shutdown();

// return to Windows

return(msg.wParam);

} // end WinMain


// HERE ARE OUR GAME CONSOLE FUNCTIONS ///////////////////////////////////////////////////////


void Game_Init(void)
{
// do any initialization here

} // end Game_Init


/////////////////////////////////////////////////////////////////////////////////////////////


void Game_Shutdown(void)
{
// cleanup and release all resources here

} // end Game_Shutdown


/////////////////////////////////////////////////////////////////////////////////////////////


void Game_Main(void)
{
// process your game logic and draw next frame

// this function must exit each frame and return back to windows

// also this function is responsible for controlling the frame rate

// therefore, if you want the game to run at 30fps, then the function should
// take 1/30th of a second before returning


static int px = SCREEN_WIDTH/2, // position of player

py = SCREEN_HEIGHT/2,
color = 0; // color of blob 0..3, gray, red, green, blue

// on entry video_buffer is valid


// get input, note how keyboard is accessed with constants "VK_"
// these are defined in "winuser.h" are basically the scan codes

// for letters just use capital ASCII codes


if (KEY_DOWN(VK_ESCAPE))
PostMessage(main_window_handle,WM_CLOSE,0,0); // this is how you exit you game


// which way is player moving

if (KEY_DOWN(VK_RIGHT))
if (++px>SCREEN_WIDTH-8) px=8;

if (KEY_DOWN(VK_LEFT))
if (--px<8) px=SCREEN_WIDTH-8;

if (KEY_DOWN(VK_UP))
if (--py<8) py=SCREEN_HEIGHT-8;

if (KEY_DOWN(VK_DOWN))
if (++py>SCREEN_HEIGHT-8) py=8;

// adjust color, notice
if (KEY_DOWN('C'))
{
if (++color>=4)
color=0;
Sleep(100);
} // end if


// draw graphics

for (int pixels=0; pixels<32; pixels++)
video_buffer[(px-4+rand()%8)+(py-4+rand()%8)*SCREEN_WIDTH] = (color*64)+rand()%64;

// sync time (optional)

// use sleep to slow system down to 70ish fps

Sleep(14); // note that Sleep is extremly inaccurate, IRL you would use something more robust

// return and let windows have some time


} // end Game_Main


Hope this helps.

Edited by - Nytegard on July 21, 2000 12:36:52 AM

Share this post


Link to post
Share on other sites
brianhj    122
ARRRGGG! Why does it always happen to me?!

lIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/H1.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

Share this post


Link to post
Share on other sites
Syzygy    122
The unresolved external "_main" indicates that your VC project isn''t a windows app. The "WinMain" in the code from Nytegard indicates that the source IS for a windows app. Try creating a new project and choosing "Win32 Application" as the type.

Share this post


Link to post
Share on other sites
Kayan    122
No you can''t just make a c++ source file. You have to tell to Visual C++ that is a win32 application. You seems to have some hard time with that. Do you know how to configure VC properly in order to work with the DirectX libraries and all that stuff?

If you don''t I could give you a crash course on the subject, just page me on ICQ or send an e-mail.

Share this post


Link to post
Share on other sites