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

📄 hawk.c

📁 著名物理引擎Hawk的源代码
💻 C
字号:
/* hawk.c, HAWK game engine
*
* Copyright 1997-1998 by Phil Frisbie, Jr.
* for Hawk Software
*
*/

#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <stdarg.h>
#include "hawk.h"
#include "internal.h"
#include "particle.h"
#include "graphics.h"
#include "dll.h"
#include "hardware.h"
#include "input.h"

unsigned char Keys[256];

/* Globals */

ENGINE		Engine;
LEVEL		Level;
GAMELEVEL	GLevel;
MOUSE		Mouse;
JOY			Joy; 
JOYSTICKINFO	Joyinfo;
GAMEDLL_EXPORT	*GAMEDLL;

#ifdef DEBUG_LOG

#ifdef WIN32
#define open	_open
#define close	_close
#define lseek	_lseek
#define read	_read
#define write	_write
#define stat	_stat
#define O_CREAT		_O_CREAT
#define O_RDWR		_O_RDWR
#define O_TRUNC		_O_TRUNC
#define S_IREAD		_S_IREAD
#define S_IWRITE	_S_IWRITE
#endif

/* use like printf() */
void logf(char *str, ...)
{
	char	    buffer[1024];
	va_list	    args;
	int			f;
	static BOOL	init = TRUE;
	
	va_start(args, str);
	vsprintf(buffer, str, args);
	va_end(args);
	
	if(init)
	{
		f = open("hawk.log", O_CREAT|O_RDWR|_O_TRUNC, S_IREAD | S_IWRITE);
		if(f<0)
		{
			close(f);
			return;
		}
		init = FALSE;
	}
	else
	{
		f = open("hawk.log", O_CREAT|O_RDWR, S_IREAD | S_IWRITE);
		if(f<0)
		{
			close(f);
			return;
		}
	}
	
	lseek(f, 0L, SEEK_END);
	write(f, buffer, (int)strlen(buffer));
	close(f);
}
#else
void logf(char *str, ...)
{
	return;
}
#endif

static GAMEDLL_EXPORT *(*GameInitDLL)(GAMEDLL_IMPORT *imp);

BOOL initGameDLL(void)
{
	void	*handle;
	GAMEDLL_IMPORT	gamei;
	
	handle = dllLoad("game.dll");
	if(!handle)
		return FALSE;
	/* this is not legal ANSI C */
	(*GameInitDLL) = dllGetFunction(handle, "GameInitDLL");
	if(!GameInitDLL)
		return FALSE;
	
	gamei.Level = &GLevel;
	gamei.Screenprintf = NULL;
	gamei.PlaySoundi = playSoundi;
	gamei.PlaySound3Di = playSound3Di;
	gamei.PlaySound = playSound;
	gamei.StopSoundi = sndStop;
	gamei.ClipRay = bspClipRay;
	gamei.Pointcontents = bspPointcontents;
	gamei.InPVS = bspInPVS;
	gamei.InPHS = bspInPHS;
	gamei.TraceRay = bspTraceRay;
	gamei.TraceBBox = bspTraceBBox;
	gamei.TraceSphere = bspTraceSphere;
	gamei.ObjectAdd = objAdd;
	gamei.ObjectDelete = objDelete;
	gamei.SoundLoad = soundLoad;
	gamei.ModelLoad = modelLoad;
	gamei.AnimationAdd = animAdd;
	gamei.AnimationDelete = animDelete;
	gamei.AnimationSetDefault = animSetDefault;
	gamei.AnimationSetNext = animSetNext;
	gamei.AnimationSetLoop = animSetLoop;
	gamei.AnimationGetCurrentFrame = animGetCurrentFrame;
	gamei.AnimationGetNextFrame = animGetNextFrame;
	gamei.AnimationSetCurrentFrame = animSetCurrentFrame;
	gamei.Splash = partMakeSplash;
	gamei.Trail = partMakeTrail;
	gamei.TempMalloc = TempMalloc;
	gamei.TempFree = TempFree;
	gamei.TagMalloc = TagMalloc;
	gamei.FreeTags = FreeTags;
	GAMEDLL = GameInitDLL(&gamei);
	return TRUE;
}

/*
* Do the 'ESC' menu
*/

void doMenu(void)
{
	
}

/*
* Do the 'pause' thing
*/
void doPause(void)
{
	renBlendScreen(0, 0, 0, 128);
	renDrawMessage(16, Engine.w / 2 - 30, Engine.h / 2, "Paused");
}

void SetViews( void )
{
	if(!GLevel.view[0])
		GLevel.view[0] = TagMalloc(sizeof(VIEW), TAG_GAME);
	
	GLevel.view[0]->width = Engine.w;
	GLevel.view[0]->height = Engine.h;
	GLevel.view[0]->scrX = 0;
	GLevel.view[0]->scrY = 0;
	GLevel.view[0]->angle = 90.0;
	GLevel.view[0]->object = &GLevel.objects[0];
	GLevel.view[0]->hangle = (float)0;
	GLevel.view[0]->type = 0;
	GLevel.view[0]->scaling = 1.0;
	GLevel.nview = 1;
	
	if(!GLevel.view[1])
		GLevel.view[1] = TagMalloc(sizeof(VIEW), TAG_GAME);
	
	GLevel.view[1]->width = Engine.h / 4;
	GLevel.view[1]->height = Engine.h / 4;
	GLevel.view[1]->scrX = 10;
	GLevel.view[1]->scrY = Engine.h - 10 - Engine.h / 4;
	GLevel.view[1]->angle = 120.0;
	GLevel.view[1]->object = &GLevel.objects[0];
	GLevel.view[1]->hangle = (float)180;
	GLevel.view[1]->type = V_REAR;
	GLevel.view[1]->scaling = 1.0;
}

void reshape(int w, int h)
{
	Engine.w = w;
	Engine.h = h;
	if(Engine.running)
		SetViews();
}


void getinput( void )
{
	static int	toggleT = FALSE, toggleL = FALSE,
		toggleC = FALSE, toggleV = FALSE,
		toggleM = FALSE, toggleSpace = FALSE,
		toggleS = FALSE, toggleB = FALSE,
		toggleF1 = FALSE, toggleF2 = FALSE,
		toggleP = FALSE;
	
	OBJECT		*player = GLevel.view[0]->object;
	
	/* clear the player event */
	player->event = 0;
	
	getKeys(Keys);
	getMouse(&Mouse);
	getJoy(&Joy);
	
	if(Keys[HK_ESCAPE])
		Done = TRUE;
	
	if(Keys['P'])
	{
		if (!toggleP)
		{
			Engine.paused = !Engine.paused;
			toggleP = TRUE;
		}
	}
	else
		toggleP = FALSE;
	
	if(Keys['T'])
	{
		if (!toggleT)
		{
			Engine.texture = !Engine.texture;
			toggleT = TRUE;
		}
	}
	else
		toggleT = FALSE;
	
	if(Keys['L'])
	{
		if (!toggleL)
		{
			Engine.light = !Engine.light;
			toggleL = TRUE;
		}
	}
	else
		toggleL = FALSE;
	
	if(Keys['C'])
		player->event |= EV_CROUCH;
	
	if(Keys['V'])
	{
		if (!toggleV)
		{
			GLevel.nview = (GLevel.nview == 1) ? 2 : 1;
			toggleV = TRUE;
		}
	}
	else
		toggleV = FALSE;
	
	if(Keys['M'])
	{
		if (!toggleM)
		{
			Engine.mouse = !Engine.mouse;
			toggleM = TRUE;
		}
	}
	else
		toggleM = FALSE;
	
	if(Keys[' '] || Joy.button1)
		player->event |= EV_SHOOT;
	
	if(Keys['S'])
	{
		if (!toggleS)
		{
			Engine.sight = !Engine.sight;
			toggleS = TRUE;
		}
	}
	else
		toggleS = FALSE;
	
	if(Keys['B'])
	{
		if (!toggleB)
		{
			GLevel.view[0]->type ^= V_EXTERNAL;
			toggleB = TRUE;
		}
	}
	else
		toggleB = FALSE;
	
	if(Keys[HK_F1])
	{
		if (!toggleF1)
		{
			graphCaptureScreen();
			toggleF1 = TRUE;
		}
	}
	else
		toggleF1 = FALSE;
	
	if(Keys[HK_F2])
	{
		if (!toggleF2)
		{
			if(player->type&O_WALLCOL)
				player->type = O_PLAYER;
			else
				player->type = O_PLAYER|O_WALLCOL|O_OBJCOL;
			toggleF2 = TRUE;
		}
	}
	else
		toggleF2 = FALSE;
	
	if(Keys[HK_SHIFT] || Joy.button2)
		player->event |= EV_FAST;
	
	if(Keys[HK_LEFT] || Joy.joyleft)
	{
		if (Keys[HK_ALT])
			player->event |= EV_LEFT;
		else
			player->event |= EV_TURNLEFT;
	}
	
	if(Keys[HK_RIGHT] || Joy.joyright)
	{
		if (Keys[HK_ALT])
			player->event |= EV_RIGHT;
		else
			player->event |= EV_TURNRIGHT;
	}
	
	if(Keys[HK_UP] || Joy.joyforward)
		player->event |= EV_FORWARD;
	
	if(Keys[HK_DOWN] || Joy.joyback)
		player->event |= EV_BACKWARD;
	
	if(Keys['1'])
		player->event |= EV_UP;
	
	if(Keys['2'])
		player->event |= EV_DOWN;
	
	/*	if(Keys[VK_END]) */
	/*		player->fVertSpeed = JUMP_ACCEL; */
	
	if(Keys[HK_PGUP] || Joy.hatback)
		player->event |= EV_LOOKUP;
	
	if(Keys[HK_PGDOWN] || Joy.hatforward)
		player->event |= EV_LOOKDOWN;
}

void HAWK_Start(void)
{
	Engine.starting = TRUE;
	Engine.running = TRUE;
	Engine.fps = 0;
	Engine.gamestart = 0;
	getElapsedTime();
}

void HAWK_Stop(void)
{
	Engine.stopping = TRUE;
}

void HAWK_Update(void)
{
	static int	frames = 0;
	static int	animframes = 0;
	static int	update = 0;
	static int	lastframes = 0;/* animation frames */
	static BOOL	waspaused = FALSE;
	
	if(!Engine.running)
		return;
	
	if(!Engine.gamestart)/* first time through */
	{
		Engine.gamestart = readTimer();
		Engine.gameframes = 1;
		GAMEDLL->GameUpdate(Engine.curframes, Engine.gameframes);
	}
	
	if(Engine.paused)
	{
		getinput();
		Engine.animframes = 0;
		waspaused = TRUE;
		HAWK_Render();
		doPause();
	}
	else
	{
		if(waspaused)/* recover from pause */
		{
			Engine.curframes = 1;
			Engine.animframes = (int)(lastframes + Engine.curframes)/(int)(GAME_TICKS/ANIMATE_TICKS);
			lastframes = (lastframes + Engine.curframes)%(int)(GAME_TICKS/ANIMATE_TICKS);
			Engine.gameframes = readTimer() - Engine.gamestart;
			waspaused = FALSE;
		}
		else
		{
			Engine.curframes = readTimer() - Engine.gamestart - Engine.gameframes;
			Engine.animframes = (int)(lastframes + Engine.curframes)/(int)(GAME_TICKS/ANIMATE_TICKS);
			lastframes = (lastframes + Engine.curframes)%(int)(GAME_TICKS/ANIMATE_TICKS);
			Engine.gameframes += Engine.curframes;
		}
		
		if(++frames == GAME_TICKS)
		{
			static int	last = 0;
			
			Engine.fps = frames /(float)(Engine.gameframes - last) * GAME_TICKS;
			last = Engine.gameframes;
			frames = 0;
		}
		
		if(Engine.curframes)
		{
			getinput();
			/* update realtime effects */
			partUpdate();
			engUpdate();
			sndUpdate();
			
			/* update game.dll */
			GAMEDLL->GameUpdate(Engine.curframes, Engine.gameframes);
			
			/* lighting must be updated AFTER game.dll */
			lightUpdate();
		}
		
		HAWK_Render();
	}
}

void HAWK_Init(int w, int h, int mode, int colorbits, int zbuffer)
{
	struct tm	*tp;
	time_t		aclock;
	
	time(&aclock);
	tp = localtime(&aclock);
	logf("================================================\n");
	logf("hawk.dll log file for HAWK demo\n\n");
	logf("Run time:\t%s\n", asctime(tp));
	logf("================================================\n\n");
	
	systemInfo();
	
	logf("Initializing memory\n");
	if(!initMemory())
	{
		logf("ERROR initializing memory\n");
		exit(1);
	}
	
	Engine.version = HAWK_VERSION;
	Engine.texture = TRUE;
	Engine.mouse = FALSE;
	Engine.sight = TRUE;
	Engine.w = w;
	Engine.h = h;
	Engine.colorbits = colorbits;
	Engine.zbufferbits = zbuffer;
	Engine.mode = mode;
	Engine.running = FALSE;
	Engine.paused = FALSE;
	reshape(w, h);
	
	if(!createWindow(w, h))
	{
		fatalError("Cannot create window %d by %d\n", w, h);
	}
	
	graphInit();
	renTextPrint("HAWK DLL version %2.2f\n", Engine.version);
	renTextPrint("\n");
	renTextPrint("For demo use only\n");
	renTextPrint("\n");
	
	renTextPrint("Initializing file system\n");
	initPAKfile();
	
	renTextPrint("Initializing timer\n");
	initTimer(GAME_TICKS);
	
	
	renTextPrint("Identifying CPU\n");
	cpuID();
	renTextPrint("  CPU vendor: %s\n", Cpu.vendor);
	if(Cpu.type == 5)
	{
		renTextPrint("  Found Pentium class processor!\n");
	}
	else if(Cpu.type == 6)
	{
		renTextPrint("  Found Pentium II class processor!!\n");
	}
	if(Cpu.hasMMX)
	{
		renTextPrint("  Found MMX extensions!!!\n");
	}
	if(Cpu.has3DNow)
	{
		renTextPrint("  Found 3DNow! extensions!!!\n");
	}
	renTextPrint("  CPU speed about %d MHz\n", Cpu.speed);
	
	renTextPrint("GL_VENDOR = %s\n", Engine.GLvendor);
	renTextPrint("GL_RENDERER = %s\n", Engine.GLrenderer);
	renTextPrint("GL_EXT_point_parameters %s\n", Engine.pointEXT ? "found":"not found");
	renTextPrint("GL_ARB_multitexture %s\n", Engine.multitexEXT ? "found":"not found");
	
	renTextPrint("Initializing sound\n");
	if(!initSound())
	{
		renTextPrint("  ERROR! Could not initialize sound\n");
		Mpause(2000);
		exit(1);
	}
	
	renTextPrint("Initializing game.dll\n");
	if(!initGameDLL())
	{
		renTextPrint("  ERROR! Could not load game.dll\n");
		Mpause(2000);
		exit(1);
	}
	if(GAMEDLL->G_dllversion != Engine.version)
	{
		renTextPrint("  ERROR! Wrong game.dll version, needed %2.2f, found %2.2f\n",
			Engine.version, GAMEDLL->G_dllversion);
		Mpause(2000);
		exit(1);
	}
	renTextPrint("  game.dll version:  %4.2f\n", GAMEDLL->G_dllversion);
	renTextPrint("  game.dll vendor: %s\n", GAMEDLL->G_dllvendor);
	renTextPrint("  game.dll name: %s\n", GAMEDLL->G_dllname);
	
	renTextPrint("Initializing input\n");
	initInput();
	if(Joyinfo.numjoy > 0)
	{
		renTextPrint("  Found a %d button %s\n", Joyinfo.numbuttons, Joyinfo.name);
		if(Joyinfo.hat)
			renTextPrint("  Joystick has a hat switch\n");
	}
	else
		renTextPrint("  No joystick found\n");
	
	SetViews();

	srand((unsigned)time(NULL));
}

void HAWK_SetTexScale(int s)
{
	Engine.texturescale = s;
}

void HAWK_SetGamma(float g)
{
	Engine.gamma = g;
}

⌨️ 快捷键说明

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