Look over my code.

Started by
1 comment, last by n0p3x 23 years, 9 months ago
Hey, I'm just in the process of getting to grips with DirectX and I wrote the following attempt at a game the other day. It wasn't origionally going to be a game, I just got carried away adding things to it. So that should explain the wierdness of it. It all more-ales works but if you people don't mind reading over it and giving any pointers as you go along it would be much appreciated. If anyone wants the graphics or anything else let me know.. The main source code:
    
/*
TITLE: 		DirectX Game Shell
AUTHOR: 		David Stubbs
DATE: 		30/5/00
EMAIL: 		root@cod3r.cjb.net
WEB: 			http://cod3r.cjb.net

TEL: 			+44 7968 397782

TODO: Tidy code and libs
      Optimise where posible
      Comment more
      Add end screen
      Make all important stages logged to error log file
      Work out why sometimes near the end of prog blt gives error invalid params
      ...and the surface is lost before GAME_END
      Stop good guy flickering
      make sure too many bad guys arnt attempted to be created at end of game
*/
//---------------------------------------------------------------------------

//Library Files

#define WIN32_LEAN_AND_MEAN  										// just say no to MFC


#include <windows.h>   							  // include important windows stuff
#include <windowsx.h> 
#include <mmsystem.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>


#include <c:\mssdk\include\ddraw.h>   						//DirectDraw header file
#include <c:\mssdk\include\dinput.h>                 //DirectInput header file
//---------------------------------------------------------------------------

//Constants

#define WINDOW_CLASS_NAME "WINCLASS1"
//---------------------------------------------------------------------------

//Globals

HWND      				hMainWindow		= NULL; 		 // globally track main window

HINSTANCE 				hModule        = NULL; 			// globally track hinstance


LPDIRECTDRAW			lpdd 				= NULL;				// The DirectDraw Object

LPDIRECTDRAW4			lpdd4 			= NULL;				// DirectX 6 interafce 4

DDSURFACEDESC2 		ddsd;											//Surface description

LPDIRECTDRAWSURFACE4	lpddsprimary 	= NULL;			  //Primary surface pointer

LPDIRECTDRAWSURFACE4	lpddsback 		= NULL;
LPDIRECTDRAWSURFACE4	MySprite 		= NULL;
LPDIRECTDRAWSURFACE4	MySprite2 		= NULL;

LPDIRECTINPUT        lpdi      		= NULL;    					  // dinput object

LPDIRECTINPUTDEVICE  lpdikey   		= NULL;    					// dinput keyboard


UCHAR        			keyboard_state[256]; 	 // contains keyboard state table


int						LevelTimer		= 0;
int						FPS				= 0;
int						FrameCount		= 0;
int						Lives				= 3;
int						Level				= 1;
char						TextOutput[256]= "Sprite ";
char						Temp[10] 		= " ";
int						WindowClosed = 0;
//---------------------------------------------------------------------------

struct Sprite_Type
{
	int	x, y;
   int 	xv, yv;
	int	AnimState;
   LPDIRECTDRAWSURFACE4	Surface[8];
   int 	Frame;
} Sprite[30];

Sprite_Type				Unit;
int						Frame;
//---------------------------------------------------------------------------

const int SCREEN_WIDTH  = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_RES    = 16;
//---------------------------------------------------------------------------

#include "routines.cpp"
//---------------------------------------------------------------------------

//Function prototypes

LRESULT CALLBACK WindowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam);
int Game_Main(void);
//---------------------------------------------------------------------------

LRESULT CALLBACK WindowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
PAINTSTRUCT				ps;											// used in WM_PAINT

HDC						hdc;								// handle to a device context


switch(msg)
{

	case WM_CREATE:
   {
		SetTimer(hwnd, 1, 1000, NULL);
   }break;

   case WM_TIMER:
   {
   	FPS=FrameCount;
      FrameCount=0;
   }break;

	case WM_PAINT:
   {
   	hdc = BeginPaint(hwnd,&ps);								//Validate the window

      EndPaint(hwnd,&ps); 													//End painting

   }break;

	case WM_DESTROY:
   {
   	PostQuitMessage(0);  						//Send WM_QUIT, kills application
   }break;

	default:break;
};
                                             //Let windows deal with all other

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

}
//---------------------------------------------------------------------------

void	DoCharacter(void)
{
lpdikey->GetDeviceState(256, (LPVOID)keyboard_state); 	//Get keyboard state



if (keyboard_state[DIK_RIGHT])			 //If right arrow move x right 5 pixels

	Unit.x+=5;

else if (keyboard_state[DIK_LEFT])//else if keyboard left move x left 5 pixels

	Unit.x+=-5;

if (keyboard_state[DIK_UP])             					//If up move y -5 pixels

	Unit.y+=-5;

else if (keyboard_state[DIK_DOWN])
	Unit.y+=5;         								  //else if down move y +5 pixles


if (Unit.x<=1)
	Unit.x=1;    				 //If user at end of screen on left hold them there


else if (Unit.x>=SCREEN_WIDTH-50)
	Unit.x = SCREEN_WIDTH-50;						  		//Same for right hand side


if (Unit.y<=1)
	Unit.y=1;       													//And top of screeen


else if (Unit.y>=SCREEN_HEIGHT-50)
	Unit.y = SCREEN_HEIGHT-50;        									//Finally left


Unit.Frame++;     									//Move onto next animation frame


if (Unit.Frame >=9)
	Unit.Frame=1;  					//If at end of animation sequence start again


																			//Draw unit to screen

BlitSurface(Unit.Surface[Unit.Frame], lpddsback, 140, 100, 50, 30, Unit.x, Unit.y);
}
//---------------------------------------------------------------------------

void DoEnemy(void)
{
for (int i=0; i<Level+5; i++)										//For all the enemy sprites

{
	Sprite<i>.x+=Sprite[i].xv;				//Increment x + y positions by velocity

   Sprite[i].y+=Sprite[i].yv;

   if (Sprite[i].x <= 1)
   	Sprite[i].xv = 3;		//If sprite hits left wayy set velocity to positive


   if (Sprite[i].x>SCREEN_WIDTH-51) 			//Right wall then set moving left

   	Sprite[i].xv = -3;

   if (Sprite[i].y <=1 )    										//Top set moving down

   	Sprite[i].yv = 3;

   if (Sprite[i].y>SCREEN_HEIGHT-51)   				  	  //Bottom set movinf up

   	Sprite[i].yv = -3;

   if (Sprite[i].AnimState==0)	 	  //Check which animation frame and draw it

   {
   	BlitSurface(MySprite, lpddsback, 280, 140, 50, 50,Sprite[i].x, Sprite[i].y);
      Sprite[i].AnimState=1;
   }
   else if (Sprite[i].AnimState=1)
   {
   	BlitSurface(MySprite2, lpddsback, 280, 140, 50, 50,Sprite[i].x, Sprite[i].y);
      Sprite[i].AnimState=0;
   }

   													//Check for user and enemy collision

   if ((Unit.x >= Sprite[i].x) && (Unit.x <= Sprite[i].x+50))
   	if ((Unit.y >= Sprite[i].y) && (Unit.y <= Sprite[i].y+50))
      {
      	Lives--;											  		//If so decrement lives

         Unit.x=320;    								  //Move user to centre screen

         Unit.y=240;
         if (Lives<1)     								  //If no more lives then quit

         	{
         	PostMessage(hMainWindow,WM_CLOSE,0,0);
            WindowClosed = 1;
            }
      }
}
}
//---------------------------------------------------------------------------

int Game_Main(void)
{

DWORD StartTime=GetTickCount();       	   //Get tickcount at start of routine


LevelTimer++;
if (LevelTimer % 500 == 0)
	Level++;

if (WindowClosed)   										//Don't re-run code after exit

	return(0);

lpdikey->GetDeviceState(256, (LPVOID)keyboard_state); 	//Get keyboard state


if (keyboard_state[DIK_ESCAPE])			 //If right arrow move x right 5 pixels						  //Test for escapoe key, if so quit
{
   WindowClosed = 1;
   PostMessage(hMainWindow,WM_CLOSE,0,0);
   return(0);
}

FillScreen(lpddsback, RGB(0,0,0)); 								  //Clear back buffer


DoCharacter();															 //Sort out character

DoEnemy();                                                         //And enemy


																		  //Display screen stats

wsprintf(TextOutput, "Frames Per Second: %d Lives: %d Level: %d", FPS, Lives, Level);
Draw_Text_GDI(TextOutput,0, 0, RGB(0, 255, 0), lpddsback);

lpddsprimary->Flip(NULL, DDFLIP_WAIT);				//Flip primary and back buffer


FrameCount++;														//Another frame rendered


int difference=GetTickCount();						  //Get finish time of routine


										//If we arnt running at 30FPS slow down to 30FPS

if ((difference - StartTime) < 33)
  	Sleep (difference);

return(1);
}
//---------------------------------------------------------------------------

int Game_Init(void *parms = NULL, int num_parms = 0)
{
HFILE File;

DeleteFile("errors.log");   	 //Delete old log file and create empty new one

_lcreat("errors.log", 0);
_lclose(File);

ShowCursor(FALSE);   											//Hide the mouse cursor


LogProg("STARTING: GameInit", FALSE);

DirectDrawCreate(NULL, &lpdd, NULL);						    //Get DD4 Interface

lpdd->QueryInterface(IID_IDirectDraw4, (LPVOID *)&lpdd4);
lpdd->Release();

LogProg("          Setting coop level", FALSE);        //Set cooperation level

lpdd4->SetCooperativeLevel(hMainWindow, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_ALLOWREBOOT);

LogProg("          Setting display mode", FALSE); 		  		//Set display mode

lpdd4->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_RES, 0, 0);

DDRAW_INIT_STRUCT(ddsd);				  //clear surface description and set size


ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;      	//Enable valid fields


ddsd.dwBackBufferCount = 1; 									  //Enable 1 back buffer


ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;

LogProg("          Creating surface", FALSE);
lpdd4->CreateSurface(&ddsd, &lpddsprimary, NULL); //Create the primary surface


ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;//And get a handle to the back buffer

lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback);

LogProg("          Attaching clipper to primary buffer", FALSE);
RECT	RectList[1]={0,0,SCREEN_WIDTH,SCREEN_HEIGHT};
AttachClipper(lpddsprimary, 1, RectList);//Attach a clipper to the full screen


LogProg("          Attaching clipper to back buffer", FALSE);
AttachClipper(lpddsback, 1, RectList);//Attach a clipper to the full screen


LogProg("          Loading and drawing logo to primary surface", FALSE);
													 //Draw the startup image to the screen

BlitSurface(File2NewSurface("logo.bmp"), lpddsprimary, 640, 480, 640, 480,0,0);

LogProg("          Loading oponent sprites", FALSE);
											  //Load opponents images and output progress

MySprite=File2NewSurface("n0p3x.bmp");
Draw_Text_GDI("Loading Images.",0, 0, RGB(0, 255, 0), lpddsprimary);
MySprite2=File2NewSurface("n0p3x2.bmp");;
Draw_Text_GDI("Loading Images..",0, 0, RGB(0, 255, 0), lpddsprimary);

LogProg("          Loading users animation frames", FALSE);
  									    //Load all frames of animation for users unit

Unit.Surface[1]=File2NewSurface("unit1.bmp");
Draw_Text_GDI("Loading Images...",0, 0, RGB(0, 255, 0), lpddsprimary);
Unit.Surface[2]=File2NewSurface("unit2.bmp");
Draw_Text_GDI("Loading Images....",0, 0, RGB(0, 255, 0), lpddsprimary);
Unit.Surface[3]=File2NewSurface("unit3.bmp");
Draw_Text_GDI("Loading Images.....",0, 0, RGB(0, 255, 0), lpddsprimary);
Unit.Surface[4]=File2NewSurface("unit4.bmp");
Draw_Text_GDI("Loading Images......",0, 0, RGB(0, 255, 0), lpddsprimary);
Unit.Surface[5]=File2NewSurface("unit5.bmp");
Draw_Text_GDI("Loading Images.......",0, 0, RGB(0, 255, 0), lpddsprimary);
Unit.Surface[6]=File2NewSurface("unit6.bmp");
Draw_Text_GDI("Loading Images........",0, 0, RGB(0, 255, 0), lpddsprimary);
Unit.Surface[7]=File2NewSurface("unit7.bmp");
Draw_Text_GDI("Loading Images.........",0, 0, RGB(0, 255, 0), lpddsprimary);
Unit.Surface[8]=File2NewSurface("unit8.bmp");
Draw_Text_GDI("Loading Images..........done",0, 0, RGB(0, 255, 0), lpddsprimary);

Unit.Frame=1; 										//Set current annimation frame to 1


LogProg("          Initialising sprites start positions", FALSE);
												   	 //Initialise all opponents details

Draw_Text_GDI("Initialising sprites....",0, 12, RGB(0, 255, 0), lpddsprimary);
for (int i=0; i<21; i++)
{
	Sprite[i].x   =rand()%SCREEN_WIDTH;
   Sprite[i].y   =rand()%SCREEN_HEIGHT;
   Sprite[i].xv =3;
   Sprite[i].yv =3;
   Sprite[i].AnimState=0;
}

Unit.x=320; 									   		//Set users starting position

Unit.y=240;

Draw_Text_GDI("Initialising sprites.......done",0, 12, RGB(0, 255, 0), lpddsprimary);

Draw_Text_GDI("Initialising keyboard...",0, 24, RGB(0, 255, 0), lpddsprimary);

LogProg("          Creating DINPUT object", FALSE);
															//Create the direct input object

if (DirectInputCreate(hModule,DIRECTINPUT_VERSION,&lpdi,NULL)!=DI_OK)
   return(0);

LogProg("          Creating a keyboard device", FALSE);
																	//Create a keyboard device

if (lpdi->CreateDevice(GUID_SysKeyboard, &lpdikey, NULL)!=DI_OK)
   return(0);

LogProg("          Setting keyboard co-op level", FALSE);
																		//Set cooperation level

if (lpdikey->SetCooperativeLevel(hMainWindow,
                 DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)!=DI_OK)
    return(0);

LogProg("          Setting keyboard data format", FALSE);
if (lpdikey->SetDataFormat(&c_dfDIKeyboard)!=DI_OK)          //Set data format

   return(0);

LogProg("          Acquiring the keyboard", FALSE);
if (lpdikey->Acquire()!=DI_OK)          					  //Acquire the keyboard

   return(0);

Draw_Text_GDI("Initialising keyboard...done",0, 24, RGB(0, 255, 0), lpddsprimary);

LogProg("          Waiting for enter key before continuing", FALSE);
do 																 //Loop until enter pressed

{
	lpdikey->GetDeviceState(256, (LPVOID)keyboard_state);
}
while (!keyboard_state[DIK_RETURN]);

LogProg("ENDING:   GameInit", FALSE);

return(1);
}
//---------------------------------------------------------------------------

int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
LogProg("STARTING: Game_Shutdown", FALSE);

//Surface is lost by this point. Why?

//BlitSurface(File2NewSurface("end.bmp"), lpddsprimary, 640, 480, 640, 480,0,0);

LogProg("          Releasing keyboard", FALSE);
lpdikey->Unacquire();											 //Release the keyboard

lpdikey->Release();
lpdi->Release();

LogProg("          Releasing users sprite animation frames", FALSE);
for (int i=1; i<8; i++)							  //Kill all frames of users sprite

	if (Unit.Surface[i])
   {
		Unit.Surface[i]->Release();
   	Unit.Surface[i]=NULL;
   }

LogProg("          Releasing opponent sprite animation frames", FALSE);
if (MySprite)													   //Kill opponent sprites

{
	MySprite->Release();
   MySprite=NULL;
}
if (MySprite2)
{
	MySprite2->Release();
   MySprite=NULL;
}

LogProg("          Releasing back buffer", FALSE);
if (lpddsback)          										 //Kill the back buffer

{
	lpddsback->Release();
   lpddsback=NULL;
}

LogProg("          Releasing primary surface", FALSE);
if (lpddsprimary)     										  //...The primary surface

{
   lpddsprimary->Release();
   lpddsprimary=NULL;
}

LogProg("          Releasing DDraw object", FALSE);
if (lpdd4)    														//Finally the DD object

{
	lpdd4->Release();
	lpdd4 = NULL;
}

LogProg("ENDING:   Game_Shutdown", FALSE);

return(1);
}
//---------------------------------------------------------------------------

int WINAPI WinMain(	HINSTANCE hinstance,
					HINSTANCE hprevinstance,
					LPSTR lpcmdline,
					int ncmdshow)
{

WNDCLASSEX winclass; 						 //This will hold the class we create

HWND	     hwnd;	 											  //Generic window handle

MSG		  msg;		 												  //Generic message

HDC        hdc;      									   //Graphics device context

			  				   	  		  	//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.hCursor	    	= LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName	= NULL;
winclass.lpszClassName	= WINDOW_CLASS_NAME;
winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);

hModule = hinstance;          							//Save hinstance in global


if (!RegisterClassEx(&winclass)) 					  //Register the window class

	return(0);

// create the window

if (!(hwnd = CreateWindowEx(NULL,                  			 //Extended style

                            WINDOW_CLASS_NAME,     						 //Class

						          "DirectX Game Shell" , 						 //Title

						          WS_VISIBLE | WS_POPUP,
					 	          0,0,	  										 //Initial x,y
						          400,300,  						//Initial width, height
						          NULL,	  							  //Handle to parent

						          NULL,	  							    //Handle to menu

						          hinstance,			  //Instance of this application

						          NULL)))							 //Extra creation parms

	LogProg("ERROR:    WinMain, CreateWindow", TRUE);

hMainWindow = hwnd;											 //Save main window handle


Game_Init();														 //Initialize game here


while(TRUE)															//Enter main event loop

{
   						     //Test if there is a message in queue, if so get it
	if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
   {
      				    						   	        //Test if this is a quit

       if (msg.message == WM_QUIT)
           break;

	   TranslateMessage(&msg);                //Translate any accelerator keys


	   DispatchMessage(&msg);            //Send the message to the window proc

   }
    

   Game_Main();										//Main game processing goes here

       
}

Game_Shutdown();													   	//Close down game


ShowCursor(TRUE);										  //Give the user the cursor back

LogProg("*END*", FALSE);

return(msg.wParam);
}
//---------------------------------------------------------------------------

[/source]

The routines.cpp file: 

[source]
#define WIN32_LEAN_AND_MEAN  // just say no to MFC
//----------------------------------------------------------------------------

#define _RGB16BIT565(r,g,b) ((b%32) + ((g%64) << 5) + ((r%32) << 11))
#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
//----------------------------------------------------------------------------

typedef struct BITMAP_FILE_TAG
{
	BITMAPFILEHEADER	bitmapfileheader;
   BITMAPINFOHEADER	bitmapinfoheader;
   PALETTEENTRY		palette[256];
   UCHAR					*buffer;
}  BITMAP_FILE, *BITMAP_FILE_PTR;
//---------------------------------------------------------------------------

#define MAX_COLORS_PALETTE   256
#define INITGUID
//---------------------------------------------------------------------------

const int BITMAP_ID = 0x4D42;
//---------------------------------------------------------------------------

typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char  UCHAR;
typedef unsigned char  BYTE;
//----------------------------------------------------------------------------

//When sent a DirectX error code outputs actual errors name to error log file

void ErrorCode2Log(HRESULT errcd);
//Copies a bitmap to a surface at given xy coordinates

void Bmp2Surface(BITMAP_FILE_PTR Bitmap, LPDIRECTDRAWSURFACE4 &lpddsSurface, int x, int y);
//Logs given text to a error log file. Exits program if desired

void LogProg(char *ErrorMessage, bool Exit);
//Loads a bitmap file into memory

int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename);
//Unloads a nbitmap file from memory

int UnloadBitmapFile(BITMAP_FILE_PTR Bitmap);
//Attaches a clipper to desired surface

LPDIRECTDRAWCLIPPER AttachClipper(LPDIRECTDRAWSURFACE4 lpdds, int num_rects, LPRECT clip_list);
//Creates desired surface

LPDIRECTDRAWSURFACE4 CreateSurface(int width, int height, int mem_flags, int color_key=0);
//Creates a new surface for given bitmap and copies it there

LPDIRECTDRAWSURFACE4 File2NewSurface(BITMAP_FILE_PTR Bitmap);
//Copies one surface to the other using the hardware blitter. If dest>src image is stretched

void BlitSurface(LPDIRECTDRAWSURFACE4 &lpddsSource, LPDIRECTDRAWSURFACE4 &lpddsDest, int Swidth, int Sheight,int Dwidth, int Dheight, int x, int y);
//Draws desired text using GDI

void Draw_Text_GDI(char *text, int x,int y,COLORREF color, LPDIRECTDRAWSURFACE4 lpdds);
//Fills screen desired colour

void FillScreen(LPDIRECTDRAWSURFACE4 &lpddsSurf, COLORREF Colour);
//----------------------------------------------------------------------------

byte Get16bitFormat(LPDIRECTDRAWSURFACE4 lpDDSPrimary)
{
DDPIXELFORMAT 	ddpf;

memset(&ddpf,0,sizeof(DDPIXELFORMAT));
ddpf.dwSize=sizeof(DDPIXELFORMAT);

byte gfxmode=0;

if (lpDDSPrimary->GetPixelFormat(&ddpf)==DD_OK)
{
	if ((ddpf.dwGBitMask /32) == 31 )
   	gfxmode =1;
	if ((ddpf.dwGBitMask /32) == 63 )
   	gfxmode =2;
}
else
	gfxmode = 255;

return gfxmode;
}

//----------------------------------------------------------------------------

void FillScreen(LPDIRECTDRAWSURFACE4 &lpddsSurf, COLORREF Colour )
{
DDBLTFX ddbltfx; 												//The blitter fx structure


DDRAW_INIT_STRUCT(ddbltfx);     							//Initialise the structure

ddbltfx.dwFillColor = Colour;                        //Set the colour to blit


																	  //Blit colour to surface

if (FAILED(lpddsSurf->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx)))
	LogProg("ERROR:    FillScreen, Blitting colour to surface", FALSE);

}
//----------------------------------------------------------------------------

void Draw_Text_GDI(char *text, int x,int y,COLORREF color, LPDIRECTDRAWSURFACE4 lpdds)
{

HDC xdc; 																	 //The working dc


if (FAILED(lpdds->GetDC(&xdc)))							 //Get the dc from surface

	LogProg("ERROR:    Draw_Text_GDI, Getting surface DC", TRUE);

SetTextColor(xdc,color);							//Set the colors for the text up


						 //Set background mode to transparent so black isn't copied

SetBkMode(xdc, TRANSPARENT);

TextOut(xdc,x,y,text,strlen(text));									  //Draw the text


lpdds->ReleaseDC(xdc);													  //Release the DC


}
//----------------------------------------------------------------------------

void ErrorCode2Log(HRESULT errcd)
{
char	ErrorString[255];

strcpy(ErrorString, "ERROR:    ErrorCode2Log ANALYSIS: ");

if (errcd == DDERR_GENERIC)
	strcat(ErrorString, "DDERR_GENERIC");
if (errcd == DDERR_INVALIDCLIPLIST)
   strcat(ErrorString, "DDERR_INVALIDCLIPLIST");
if (errcd == DDERR_INVALIDOBJECT)
  	strcat(ErrorString, "DDERR_INVALIDOBJECT");
if (errcd == DDERR_INVALIDPARAMS)
	strcat(ErrorString, "DDERR_INVALIDPARAMS");
if (errcd == DDERR_INVALIDRECT)
	strcat(ErrorString, "DDERR_INVALIDRECT");
if (errcd == DDERR_NOALPHAHW)
	strcat(ErrorString, "DDERR_NOALPHAHW");
if (errcd == DDERR_NOBLTHW)
	strcat(ErrorString, "DDERR_NOBLTHW");
if (errcd == DDERR_NOCLIPLIST)
	strcat(ErrorString, "DDERR_NOCLIPLIST");
if (errcd == DDERR_NODDROPSHW)
	strcat(ErrorString, "DDERR_NODDROPSHW");
if (errcd == DDERR_NOMIRRORHW)
	strcat(ErrorString, "DDERR_NOMIRRORHW");
if (errcd == DDERR_NORASTEROPHW)
	strcat(ErrorString, "DDERR_NORASTEROPHW");
if (errcd == DDERR_NOROTATIONHW)
	strcat(ErrorString, "DDERR_NOROTATIONHW");
if (errcd == DDERR_NOSTRETCHHW)
	strcat(ErrorString, "DDERR_NOSTRETCHHW");
if (errcd == DDERR_NOZBUFFERHW)
	strcat(ErrorString, "DDERR_NOZBUFFERHW");
if (errcd == DDERR_SURFACEBUSY)
	strcat(ErrorString, "DDERR_SURFACEBUSY");
if (errcd == DDERR_SURFACELOST)
	strcat(ErrorString, "DDERR_SURFACELOST");
if (errcd == DDERR_UNSUPPORTED)
	strcat(ErrorString, "DDERR_UNSUPPORTED");
if (errcd == DDERR_WASSTILLDRAWING)
	strcat(ErrorString, "DDERR_WASSTILLDRAWING");

   LogProg(ErrorString, FALSE);
}
//----------------------------------------------------------------------------

void BlitSurface(LPDIRECTDRAWSURFACE4 &lpddsSource, LPDIRECTDRAWSURFACE4 &lpddsDest, int Swidth, int Sheight,int Dwidth, int Dheight, int x, int y)
{
RECT	SourceRect, DestRect;

DestRect.left   = x;   										//Set the destination rect

DestRect.top    = y;
DestRect.right  = x+Dwidth-1;
DestRect.bottom = y+Dheight-1;

SourceRect.left   = 0;                               	  //Set the source rect

SourceRect.top    = 0;
SourceRect.right  = Swidth-1;
SourceRect.bottom = Sheight-1;

HRESULT errcd = lpddsDest->Blt(&DestRect, lpddsSource, &SourceRect, (DDBLT_WAIT | DDBLT_KEYSRC), NULL);
if (FAILED(errcd))
{
	char	ErrorString[255];
	wsprintf(ErrorString, "ERROR:    BlitSurface, Blitting image of %d*%d, to %d*%d, Error Code: %d", Swidth, Sheight, Dwidth, Dheight, errcd);

	LogProg(ErrorString, FALSE);
   ErrorCode2Log(errcd);

}
}
//----------------------------------------------------------------------------

LPDIRECTDRAWSURFACE4 File2NewSurface(char *FileName)
{
LPDIRECTDRAWSURFACE4	NewSurface;
BITMAP_FILE Bitmap;

Load_Bitmap_File(&Bitmap, FileName);    				 //Load the desired bitmap


                                                    //Create a surface for it

NewSurface=CreateSurface(int(Bitmap.bitmapinfoheader.biWidth), int(Bitmap.bitmapinfoheader.biHeight), DDSCAPS_SYSTEMMEMORY);     //DDSCAPS_VIDEOMEMORY


Bmp2Surface(&Bitmap, NewSurface, 0, 0);			      //Copy image to surface


UnloadBitmapFile(&Bitmap); 								  //Unload unneeded bitmap


return (NewSurface);									//Return new surface with bitmap

}
//----------------------------------------------------------------------------

LPDIRECTDRAWCLIPPER AttachClipper(LPDIRECTDRAWSURFACE4 lpdds, int num_rects, LPRECT clip_list)
{

int 						index;                          				 //Looping var

LPDIRECTDRAWCLIPPER 	lpddclipper;   //Pointer to the newly created dd clipper

LPRGNDATA 				region_data;  //Pointer to the region data that contains

                                                   //The header and clip list


													//First create the direct draw clipper

if (FAILED(lpdd4->CreateClipper(0,&lpddclipper,NULL)))
	LogProg("ERROR:    AttachClipper, Creating DDraw clipper", TRUE);

// now create the clip list from the sent data


// first allocate memory for region data

region_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rects*sizeof(RECT));

// now copy the rects into region data

memcpy(region_data->Buffer, clip_list, sizeof(RECT)*num_rects);

// set up fields of header

region_data->rdh.dwSize          = sizeof(RGNDATAHEADER);
region_data->rdh.iType           = RDH_RECTANGLES;
region_data->rdh.nCount          = num_rects;
region_data->rdh.nRgnSize        = num_rects*sizeof(RECT);

region_data->rdh.rcBound.left    =  64000;
region_data->rdh.rcBound.top     =  64000;
region_data->rdh.rcBound.right   = -64000;
region_data->rdh.rcBound.bottom  = -64000;

// find bounds of all clipping regions

for (index=0; index<num_rects; index++)
    {
    // test if the next rectangle unioned with the current bound is larger

    if (clip_list[index].left < region_data->rdh.rcBound.left)
       region_data->rdh.rcBound.left = clip_list[index].left;

    if (clip_list[index].right > region_data->rdh.rcBound.right)
       region_data->rdh.rcBound.right = clip_list[index].right;

    if (clip_list[index].top < region_data->rdh.rcBound.top)
       region_data->rdh.rcBound.top = clip_list[index].top;

    if (clip_list[index].bottom > region_data->rdh.rcBound.bottom)
       region_data->rdh.rcBound.bottom = clip_list[index].bottom;

    } // end for index


// now we have computed the bounding rectangle region and set up the data

// now let's set the clipping list


if (FAILED(lpddclipper->SetClipList(region_data, 0)))
   {
   // release memory and return error

   free(region_data);
   return(NULL);
   } // end if


// now attach the clipper to the surface

if (FAILED(lpdds->SetClipper(lpddclipper)))
   {
   // release memory and return error

   free(region_data);
   return(NULL);
   } // end if


// all is well, so release memory and send back the pointer to the new clipper
free(region_data);
return(lpddclipper);

} // end DDraw_Attach_Clipper

//----------------------------------------------------------------------------

int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
{
// this function is used to flip bottom-up .BMP images


UCHAR *buffer; // used to perform the image processing

int index;     // looping index


// allocate the temporary buffer

if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))
   return(0);

// copy image to work area

memcpy(buffer,image,bytes_per_line*height);

// flip vertically

for (index=0; index < height; index++)
    memcpy(ℑ[((height-1) - index)*bytes_per_line],
           &buffer[index*bytes_per_line], bytes_per_line);

// release the memory

free(buffer);

// return success

return(1);

}
//----------------------------------------------------------------------------

void Bmp2Surface(BITMAP_FILE_PTR Bitmap, LPDIRECTDRAWSURFACE4 &lpddsSurface, int x, int y)
{

DDSURFACEDESC2 ddsd;		//Surface description


LogProg("STARTING: Bmp2Surface", FALSE);

DDRAW_INIT_STRUCT(ddsd);

lpddsSurface->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);

USHORT *PrimaryBuffer=(USHORT *)ddsd.lpSurface;
// process each line and copy it into the primary buffer

for (int index_y = 0; index_y < Bitmap->bitmapinfoheader.biHeight; index_y++)
    {
    for (int index_x = 0; index_x < Bitmap->bitmapinfoheader.biWidth; index_x++)
        {
        // get BGR values, note the scaling down of the channels, so that they
        // fit into the 5.6.5 format

        UCHAR blue  = (Bitmap->buffer[index_y*Bitmap->bitmapinfoheader.biWidth*3 + index_x*3 + 0]) >> 3,
              green = (Bitmap->buffer[index_y*Bitmap->bitmapinfoheader.biWidth*3 + index_x*3 + 1]) >> 3,
              red   = (Bitmap->buffer[index_y*Bitmap->bitmapinfoheader.biWidth*3 + index_x*3 + 2]) >> 3;

        // this builds a 16 bit color value in 5.6.5 format (green dominant mode)
        USHORT pixel = _RGB16BIT565(red,green,blue);

        // write the pixel

        PrimaryBuffer[index_x+x + (index_y*ddsd.lPitch >> 1)+y*SCREEN_WIDTH] = pixel;

        } // end for index_x


    } // end for index_y



LogProg("          Unlocking primary surface", FALSE);
lpddsSurface->Unlock(NULL);
}
//----------------------------------------------------------------------------

void LogProg(char *ErrorMessage, bool Exit)
{

HFILE FileHandle;

	FileHandle=_lopen("ERRORS.LOG", OF_WRITE);
   _llseek(FileHandle, 0, FILE_END);
   _lwrite(FileHandle, ErrorMessage, lstrlen(ErrorMessage));
   _lwrite(FileHandle, "\r\n", 2);

   _lclose(FileHandle);

if (Exit)
   exit(0);
}
//----------------------------------------------------------------------------

int UnloadBitmapFile(BITMAP_FILE_PTR Bitmap)
{
	LogProg("STARTING: UnloadBitmapFile", FALSE);
	if (Bitmap->buffer)
   {
   	free(Bitmap->buffer);
      Bitmap->buffer = NULL;
   }
   LogProg("ENDING:   UnloadBitmapFile", FALSE);
   return(1);
}
//----------------------------------------------------------------------------

LPDIRECTDRAWSURFACE4 CreateSurface(int width, int height, int mem_flags, int color_key)
{
// this function creates an offscreen plain surface


DDSURFACEDESC2 ddsd;         // working description

LPDIRECTDRAWSURFACE4 lpdds;  // temporary surface

    
// set to access caps, width, and height
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize  = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;

// set dimensions of the new bitmap surface

ddsd.dwWidth  =  width;
ddsd.dwHeight =  height;

// set surface to offscreen plain

ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | mem_flags;

// create the surface

if (FAILED(lpdd4->CreateSurface(&ddsd,&lpdds,NULL)))
   return(NULL);

// test if user wants a color key

if (color_key >= 0)
   {
   // set color key to color 0

   DDCOLORKEY color_key; // used to set color key

   color_key.dwColorSpaceLowValue  = 0;
   color_key.dwColorSpaceHighValue = 0;

   // now set the color key for source blitting

   lpdds->SetColorKey(DDCKEY_SRCBLT, &color_key);
   } // end if


// return surface

return(lpdds);
} // end DDraw_Create_Surface

//----------------------------------------------------------------------------

int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
{
// this function opens a bitmap file and loads the data into bitmap


int file_handle,  // the file handle

    index;        // looping index


UCHAR   *temp_buffer = NULL; // used to convert 24 bit images to 16 bit

OFSTRUCT file_data;          // the file data information


// open the file if it exists

if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
   return(0);

// now load the bitmap file header

_lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));

// test if this is a bitmap file

if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
   {
   // close the file

   _lclose(file_handle);

   // return error

   return(0);
   } // end if


// now we know this is a bitmap, so read in all the sections

// first the bitmap infoheader


// now load the bitmap file header

_lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));

// now load the color palette if there is one

if (bitmap->bitmapinfoheader.biBitCount == 8)
   {
   _lread(file_handle, &bitmap->palette,MAX_COLORS_PALETTE*sizeof(PALETTEENTRY));

   // now set all the flags in the palette correctly and fix the reversed 

   // BGR RGBQUAD data format

   for (index=0; index < MAX_COLORS_PALETTE; index++)
       {
       // reverse the red and green fields

       int temp_color                = bitmap->palette[index].peRed;
       bitmap->palette[index].peRed  = bitmap->palette[index].peBlue;
       bitmap->palette[index].peBlue = temp_color;
       
       // always set the flags word to this

       bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
       } // end for index


    } // end if


// finally the image data itself

_llseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);

// now read in the image, if the image is 8 or 16 bit then simply read it
// but if its 24 bit then read it into a temporary area and then convert

// it to a 16 bit image


if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16 || 
    bitmap->bitmapinfoheader.biBitCount==24)
   {
   // delete the last image if there was one

  // if (bitmap->buffer)
     //  free(bitmap->buffer);

   // allocate the memory for the image

   if (!(bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
      {
      // close the file

      _lclose(file_handle);

      // return error

      return(0);
      } // end if


   // now read it in

   _lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);

   } // end if

else
   {
   // serious problem

   return(0);

   } // end else

// close the file

_lclose(file_handle);

// flip the bitmap

Flip_Bitmap(bitmap->buffer, 
            bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8), 
            bitmap->bitmapinfoheader.biHeight);

// return success

return(1);

} // end Load_Bitmap_File

//----------------------------------------------------------------------------


    
The errors.log file

STARTING: GameInit
          Setting coop level
          Setting display mode
          Creating surface
          Attaching clipper to primary buffer
          Attaching clipper to back buffer
          Loading and drawing logo to primary surface
STARTING: Bmp2Surface
          Unlocking primary surface
STARTING: UnloadBitmapFile
ENDING:   UnloadBitmapFile
          Loading oponent sprites
STARTING: Bmp2Surface
          Unlocking primary surface
STARTING: UnloadBitmapFile
ENDING:   UnloadBitmapFile
STARTING: Bmp2Surface
          Unlocking primary surface
STARTING: UnloadBitmapFile
ENDING:   UnloadBitmapFile
          Loading users animation frames
STARTING: Bmp2Surface
          Unlocking primary surface
STARTING: UnloadBitmapFile
ENDING:   UnloadBitmapFile
STARTING: Bmp2Surface
          Unlocking primary surface
STARTING: UnloadBitmapFile
ENDING:   UnloadBitmapFile
STARTING: Bmp2Surface
          Unlocking primary surface
STARTING: UnloadBitmapFile
ENDING:   UnloadBitmapFile
STARTING: Bmp2Surface
          Unlocking primary surface
STARTING: UnloadBitmapFile
ENDING:   UnloadBitmapFile
STARTING: Bmp2Surface
          Unlocking primary surface
STARTING: UnloadBitmapFile
ENDING:   UnloadBitmapFile
STARTING: Bmp2Surface
          Unlocking primary surface
STARTING: UnloadBitmapFile
ENDING:   UnloadBitmapFile
STARTING: Bmp2Surface
          Unlocking primary surface
STARTING: UnloadBitmapFile
ENDING:   UnloadBitmapFile
STARTING: Bmp2Surface
          Unlocking primary surface
STARTING: UnloadBitmapFile
ENDING:   UnloadBitmapFile
          Initialising sprites start positions
          Creating DINPUT object
          Creating a keyboard device
          Setting keyboard co-op level
          Setting keyboard data format
          Acquiring the keyboard
          Waiting for enter key before continuing
ENDING:   GameInit
ERROR:    BlitSurface, Blitting image of 140*100, to 50*30, Error Code: -2147024809
ERROR:    ErrorCode2Log ANALYSIS: DDERR_INVALIDPARAMS
ERROR:    BlitSurface, Blitting image of 140*100, to 50*30, Error Code: -2147024809
ERROR:    ErrorCode2Log ANALYSIS: DDERR_INVALIDPARAMS
STARTING: Game_Shutdown
          Releasing keyboard
          Releasing users sprite animation frames
          Releasing opponent sprite animation frames
          Releasing back buffer
          Releasing primary surface
          Releasing DDraw object
ENDING:   Game_Shutdown
*END*

 
Thanks.. Dave Edited by - n0p3x on 7/23/00 7:52:10 AM
Regards,Dave
Advertisement
And how do you guys do the niceboxes around youre code in posts. I''ll go and see if it''s in the FAQ now.
Regards,Dave
It''s not a good idea to post this much code on the forum, no one is going to read it.

- WitchLord

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement