⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tomslib.h

📁 游戏编程精华02-含有几十个游戏编程例子
💻 H
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) Tom Forsyth, 2001. 
 * All rights reserved worldwide.
 *
 * This software is provided "as is" without express or implied
 * warranties. You may freely copy and compile this source into
 * applications you distribute provided that the copyright text
 * below is included in the resulting source code, for example:
 * "Portions Copyright (C) Tom Forsyth, 2001"
 */
// Some standard useful classes, templates, etc.


#ifndef TOMSLIB_INCLUDED
#define TOMSLIB_INCLUDED


#include <assert.h>
#include <math.h>
#include <memory.h>
#include <malloc.h>
#include <stdio.h>
#include <stdarg.h>
#include <windows.h>
#include <mmsystem.h>


#ifdef DEBUG

//#define ASSERT(exp) { assert(exp); __assume(exp); }
#define ASSERT(exp) { if (!(exp)){_asm { int 3 };} }

inline TRACE ( char *fmt, ... )
{
	va_list vlist;

	char pchTemp[1000];

	va_start ( vlist, fmt );
	vsprintf ( pchTemp, fmt, vlist );
	OutputDebugString ( pchTemp );
	va_end ( vlist );
}

#else //#ifdef DEBUG

#define ASSERT sizeof
#define TRACE sizeof

#endif //#else //#ifdef DEBUG



static void DumpFunction ( char *pchFormat, ... )
{
	va_list va_ptr;
	char pchTemp[256];

	va_start ( va_ptr, pchFormat );

	vsprintf ( pchTemp, pchFormat, va_ptr );
	OutputDebugString ( pchTemp );

	va_end ( va_ptr );
}

#if 1
#define DUMP(args) DumpFunction args
#else
#define DUMP(args) sizeof args
#endif


// Couldn't do it with classes and templates,
// have to do it the old fashioned way.

// Defines a link
#define DlinkDefine(classname,linkname)\
	classname *linkname##pNextItem;\
	classname *linkname##pPrevItem


// Defines the class methods for the link.
#define DlinkMethods(classname,linkname)																		\
	void linkname##Init ( void ) { linkname##pNextItem = NULL; linkname##pPrevItem = NULL; }					\
																												\
	/* Find the next in the list. */																			\
	classname *linkname##Next ( void )																			\
	{																											\
		ASSERT ( ( linkname##pPrevItem == NULL ) || ( linkname##pPrevItem->linkname##pNextItem == this ) );		\
		ASSERT ( ( linkname##pNextItem == NULL ) || ( linkname##pNextItem->linkname##pPrevItem == this ) );		\
		return linkname##pNextItem;																				\
	}																											\
																												\
	/* Find the previous in the list. */																		\
	classname *linkname##Prev ( void )																			\
	{																											\
		ASSERT ( ( linkname##pPrevItem == NULL ) || ( linkname##pPrevItem->linkname##pNextItem == this ) );		\
		ASSERT ( ( linkname##pNextItem == NULL ) || ( linkname##pNextItem->linkname##pPrevItem == this ) );		\
		return linkname##pPrevItem;																				\
	}																											\
																												\
	/* Remove this item from the list. */																		\
	/* Returns the next item. */																				\
	classname *linkname##Del ( void )																			\
	{																											\
		classname *pNext = linkname##pNextItem;																	\
		classname *pPrev = linkname##pPrevItem;																	\
		ASSERT ( ( pPrev == NULL ) || ( pPrev->linkname##pNextItem == this ) );									\
		ASSERT ( ( pNext == NULL ) || ( pNext->linkname##pPrevItem == this ) );									\
		if ( pPrev != NULL )																					\
		{																										\
			pPrev->linkname##pNextItem = pNext;																	\
		}																										\
		if ( pNext != NULL )																					\
		{																										\
			pNext->linkname##pPrevItem = pPrev;																	\
		}																										\
		linkname##pNextItem = NULL;																				\
		linkname##pPrevItem = NULL;																				\
		return pNext;																							\
	}																											\
																												\
	/* Remove this item from the list. */																		\
	/* Assumes that this is the first item in the list for speed (asserted). */									\
	/* Returns the next item. */																				\
	classname *linkname##DelScan ( void )																		\
	{																											\
		ASSERT ( linkname##pPrevItem == NULL );																	\
		classname *pNext = linkname##pNextItem;																	\
		ASSERT ( ( pNext == NULL ) || ( pNext->linkname##pPrevItem == this ) );									\
		if ( pNext != NULL )																					\
		{																										\
			pNext->linkname##pPrevItem = NULL;																	\
		}																										\
		linkname##pNextItem = NULL;																				\
		linkname##pPrevItem = NULL;																				\
		return pNext;																							\
	}																											\
																												\
	/* Deletes the item, given a pointer to the first item in the list. */										\
	/* Modifies the point as necessary. */																		\
	/* Returns the next item. */																				\
	/* Use like   pThing->DelFromFirst ( &pFirst ); */															\
	classname *linkname##DelFromFirst ( classname **ppFirst )													\
	{																											\
		ASSERT ( ppFirst != NULL );																				\
		ASSERT ( *ppFirst != NULL );																			\
		if ( *ppFirst == this )																					\
		{																										\
			ASSERT ( linkname##pPrevItem == NULL );																\
			/* First in the list. */																			\
			*ppFirst = linkname##Del();																			\
			return *ppFirst;																					\
		}																										\
		else																									\
		{																										\
			/* DLink lists already know their previous item. */													\
			return ( linkname##Del() );																			\
		}																										\
	}																											\
																												\
	/* Add the item after the given item. */																	\
	/* Return the new next item. */																				\
	classname *linkname##AddAfter ( classname *pPrev )															\
	{																											\
		ASSERT ( linkname##pNextItem == NULL );																	\
		ASSERT ( linkname##pPrevItem == NULL );																	\
		ASSERT ( pPrev != NULL );																				\
		linkname##pNextItem = pPrev->linkname##pNextItem;														\
		linkname##pPrevItem = pPrev;																			\
		if ( linkname##pNextItem != NULL )																		\
		{																										\
			linkname##pNextItem->linkname##pPrevItem = this;													\
		}																										\
		pPrev->linkname##pNextItem = this;																		\
		return ( linkname##pNextItem );																			\
	}																											\
																												\
	/* Add the item after the given item. */																	\
	/* Assumes this is the last item in the list for speed (asserted) */										\
	void linkname##AddAfterEnd ( classname *pPrev )																\
	{																											\
		ASSERT ( linkname##pNextItem == NULL );																	\
		ASSERT ( linkname##pPrevItem == NULL );																	\
		ASSERT ( pPrev != NULL );																				\
		ASSERT ( pPrev->linkname##pNextItem == NULL );															\
		linkname##pNextItem = NULL;																				\
		linkname##pPrevItem = pPrev;																			\
		pPrev->linkname##pNextItem = this;																		\
	}																											\
																												\
	/* Add before given item. */																				\
	/* Returns the new previous item. */																		\
	classname *linkname##AddBefore ( classname *pNext )															\
	{																											\
		ASSERT ( linkname##pNextItem == NULL );																	\
		ASSERT ( linkname##pPrevItem == NULL );																	\
		ASSERT ( pNext != NULL );																				\
		linkname##pNextItem = pNext;																			\
		linkname##pPrevItem = pNext->linkname##pPrevItem;														\
		if ( linkname##pPrevItem != NULL )																		\
		{																										\
			linkname##pPrevItem->linkname##pNextItem = this;													\
		}																										\
		pNext->linkname##pPrevItem = this;																		\
		return ( linkname##pPrevItem );																			\
	}																											\
																												\
	/* Add the item before the given item. */																	\
	/* Assumes this is the first item in the list for speed (asserted) */										\
	void linkname##AddBeforeStart ( classname *pNext )															\
	{																											\
		ASSERT ( linkname##pNextItem == NULL );																	\
		ASSERT ( linkname##pPrevItem == NULL );																	\
		ASSERT ( pNext != NULL );																				\
		ASSERT ( pNext->linkname##pPrevItem == NULL );															\
		linkname##pPrevItem = NULL;																				\
		linkname##pNextItem = pNext;																			\
		pNext->linkname##pPrevItem = this;																		\
	}																											\
																												\
	/* Find the last item in the list. */																		\
	classname *linkname##FindLast ( void )																		\
	{																											\
		classname *pCurr = this;																				\
		ASSERT ( pCurr != NULL );																				\
		while ( pCurr->linkname##pNextItem != NULL )															\
		{																										\
			ASSERT ( ( pCurr->linkname##pPrevItem == NULL ) || ( pCurr->linkname##pPrevItem->linkname##pNextItem == pCurr ) );	\
			ASSERT ( ( pCurr->linkname##pNextItem == NULL ) || ( pCurr->linkname##pNextItem->linkname##pPrevItem == pCurr ) );	\
			pCurr = pCurr->linkname##pNextItem;																	\
		}																										\
		return pCurr;																							\
	}																											\
																												\
	/* Find the first item in the list. */																		\
	classname *linkname##FindFirst ( void )																		\
	{																											\
		classname *pCurr = this;																				\
		ASSERT ( pCurr != NULL );																				\
		while ( pCurr->linkname##pPrevItem != NULL )															\
		{																										\
			ASSERT ( ( pCurr->linkname##pPrevItem == NULL ) || ( pCurr->linkname##pPrevItem->linkname##pNextItem == pCurr ) );	\
			ASSERT ( ( pCurr->linkname##pNextItem == NULL ) || ( pCurr->linkname##pNextItem->linkname##pPrevItem == pCurr ) );	\
			pCurr = pCurr->linkname##pPrevItem;																	\
		}																										\
		return pCurr;																							\
	}																											\
																												\
	/* Consistency check - checks the current list is sound. */													\
	void linkname##ConsistencyCheck ( void )																	\
	{																											\
		classname *pCurr = this;																						\
		/* Scan backwards. */																					\
		ASSERT ( pCurr != NULL );																				\
		while ( pCurr->linkname##pPrevItem != NULL )															\
		{																										\
			ASSERT ( ( pCurr->linkname##pPrevItem == NULL ) || ( pCurr->linkname##pPrevItem->linkname##pNextItem == pCurr ) );				\
			ASSERT ( ( pCurr->linkname##pNextItem == NULL ) || ( pCurr->linkname##pNextItem->linkname##pPrevItem == pCurr ) );				\
			pCurr = pCurr->linkname##pPrevItem;																	\
		}																										\
		ASSERT ( ( pCurr->linkname##pPrevItem == NULL ) || ( pCurr->linkname##pPrevItem->linkname##pNextItem == pCurr ) );					\
		ASSERT ( ( pCurr->linkname##pNextItem == NULL ) || ( pCurr->linkname##pNextItem->linkname##pPrevItem == pCurr ) );					\
																												\
		/* Scan forwards. */																					\
		pCurr = this;																							\
		ASSERT ( pCurr != NULL );																				\
		while ( pCurr->linkname##pNextItem != NULL )															\
		{																										\
			ASSERT ( ( pCurr->linkname##pPrevItem == NULL ) || ( pCurr->linkname##pPrevItem->linkname##pNextItem == pCurr ) );				\
			ASSERT ( ( pCurr->linkname##pNextItem == NULL ) || ( pCurr->linkname##pNextItem->linkname##pPrevItem == pCurr ) );				\
			pCurr = pCurr->linkname##pNextItem;																	\
		}																										\
		ASSERT ( ( pCurr->linkname##pPrevItem == NULL ) || ( pCurr->linkname##pPrevItem->linkname##pNextItem == pCurr ) );					\
		ASSERT ( ( pCurr->linkname##pNextItem == NULL ) || ( pCurr->linkname##pNextItem->linkname##pPrevItem == pCurr ) );					\
	}																											\
																												\
	/* Adds the item to the end of this list */																	\
	void linkname##AddToEnd ( classname *pItem )																\
	{																											\
		ASSERT ( pItem != NULL );																				\
		linkname##AddAfterEnd ( pItem->linkname##FindLast() );													\
	}																											\
																												\
	/* Adds the item the the start of this list */																\
	void linkname##AddToStart ( classname *pItem )																\
	{																											\
		ASSERT ( pItem != NULL );																				\
		linkname##AddBeforeStart ( pItem->linkname##FindFirst() );												\
	}																											\
																												\
	/* Check that all the pointer are NULL, ready to be deleted */												\
	bool linkname##CheckNull ( void )																			\
	{																											\
		return ( ( linkname##pNextItem == NULL ) && ( linkname##pPrevItem == NULL ) );							\
	}																											\
																												\
	/* Calls delete() on all the objects in this list and deletes it */											\
	void linkname##DelWholeList ( void )																		\
	{																											\
		classname *pCur = linkname##FindFirst();																\
		while ( pCur != NULL )																					\
		{																										\
			classname *pNext = pCur->linkname##DelScan();														\
			delete ( pCur );																					\
			pCur = pNext;																						\
		}																										\
	}																											\







static int CountBitsIn ( unsigned int dwInput )
{
	int iCount = 0;
	unsigned int dwTemp = dwInput;
	while ( dwTemp != 0 )
	{
		dwTemp = ( dwTemp & ( dwTemp - 1 ) );
		iCount++;
	}
	return ( iCount );
}


// Swap things.
template <class S> void Swap ( S &a, S &b )
{
	S temp = a;
	a = b;
	b = temp;
}


// Count number of items in a static array, e.g. strings, etc.
// So for: DWORD dwArray[20], NumItemsIn ( dwArray ) = 20
template <class T> int NumItemsIn ( T &thing )
{
	return ( sizeof(thing) / sizeof (*thing) );
}


// Safe version of strncpy - always puts a trailing 0 on the end.
template <class C> C *SafeStrncpy ( C *dest, const C *src, size_t number )
{
	strncpy ( dest, src, number );
	dest[number-1] = 0;
	return ( dest );
}



// A moderately good "close enough" thing.
inline bool CloseEnough ( float f1, float f2, float epsilon = 0.0001f )
{
	if ( fabsf ( f1 ) > fabsf ( f2 ) )
	{
		return ( fabsf ( f1 - f2 ) <= fabsf ( epsilon * f1 ) + epsilon );
	}
	else
	{
		return ( fabsf ( f1 - f2 ) <= fabsf ( epsilon * f2 ) + epsilon );
	}
}




// "Values" to pass to templates.
// Thanks to Jan for this perversion!
class Yes
{
public:
	enum { bVal = TRUE };
};

class No
{
public:
	enum { bVal = FALSE };
};




// Slow - checks the heap every time.
#define CHECK_HEAP 0

// A binary heap. Actually stores pointers to type THING, not the THINGs themselves.
template <class THING, class SORT> class BinaryHeap
{

private:
	struct Blob
	{
		THING				*pThing;
		SORT				Sort;
	};

	Blob					*pBlobArray;
	int						iCurrentSize;
	int						iAllocatedSize;

	int						iCurrentPos;

#ifdef DEBUG
	// A flag that says using FindNext, RemoveNext and RemoveCurrent are OK to call.
	bool					bFindNextValid;
#endif


public:

	BinaryHeap ( void )
	{
		pBlobArray = NULL;
		iCurrentSize = 0;
		iAllocatedSize = 0;
#ifdef DEBUG
		bFindNextValid = FALSE;
#endif
		iCurrentPos = 0;
	}

	~BinaryHeap ( void )
	{
		if ( pBlobArray != NULL )
		{
			delete[] pBlobArray;
			pBlobArray = NULL;
		}
		iCurrentSize = 0;
		iAllocatedSize = 0;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -