CShotManipulator: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
mNo edit summary
 
(Added code - link was busted)
Line 5: Line 5:
http://mathworld.wolfram.com/images/eps-gif/CircularDistribution_1000.gif
http://mathworld.wolfram.com/images/eps-gif/CircularDistribution_1000.gif


The source code is available [http://www.orst.edu/~holtt/shot_manipulator.h here]
The source code is as follows...
 
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef SHOT_MANIPULATOR_H
#define SHOT_MANIPULATOR_H
#ifdef _WIN32
#pragma once
#endif
 
#include "vector.h"
extern ConVar ai_shot_bias_min;
extern ConVar ai_shot_bias_max;
 
//---------------------------------------------------------
// Caches off a shot direction and allows you to perform
// various operations on it without having to recalculate
// vecRight and vecUp each time.
//---------------------------------------------------------
class CShotManipulator
{
public:
CShotManipulator( const Vector &vecForward )
{
SetShootDir( vecForward );
};
void SetShootDir( const Vector &vecForward )
{
m_vecShotDirection = vecForward;
VectorVectors( m_vecShotDirection, m_vecRight, m_vecUp );
}
const Vector &ApplySpread( const Vector &vecSpread, float bias = 1.0 );
const Vector &GetShotDirection() { return m_vecShotDirection; }
const Vector &GetResult() { return m_vecResult; }
const Vector &GetRightVector() { return m_vecRight; }
const Vector &GetUpVector() { return m_vecUp;}
private:
Vector m_vecShotDirection;
Vector m_vecRight;
Vector m_vecUp;
Vector m_vecResult;
};
//---------------------------------------------------------
// Take a vector (direction) and another vector (spread)
// and modify the direction to point somewhere within the
// spread. This used to live inside FireBullets.
//---------------------------------------------------------
inline const Vector &CShotManipulator::ApplySpread( const Vector &vecSpread, float bias )
{
// get circular gaussian spread
float x, y, z;
if ( bias > 1.0 )
bias = 1.0;
else if ( bias < 0.0 )
bias = 0.0;
float shotBiasMin = ai_shot_bias_min.GetFloat();
float shotBiasMax = ai_shot_bias_max.GetFloat();
// 1.0 gaussian, 0.0 is flat, -1.0 is inverse gaussian
float shotBias = ( ( shotBiasMax - shotBiasMin ) * bias ) + shotBiasMin;
float flatness = ( fabsf(shotBias) * 0.5 );
do
{
x = random->RandomFloat(-1,1) * flatness + random->RandomFloat(-1,1) * (1 - flatness);
y = random->RandomFloat(-1,1) * flatness + random->RandomFloat(-1,1) * (1 - flatness);
if ( shotBias < 0 )
{
x = ( x >= 0 ) ? 1.0 - x : -1.0 - x;
y = ( y >= 0 ) ? 1.0 - y : -1.0 - y;
}
z = x*x+y*y;
} while (z > 1);
m_vecResult = m_vecShotDirection + x * vecSpread.x * m_vecRight + y * vecSpread.y * m_vecUp;
return m_vecResult;
}
 
#endif // SHOT_MANIPULATOR_H


[[Category:Helpers]]
[[Category:Helpers]]

Revision as of 03:09, 20 January 2006

Created with the shoot direction in the constructor, this helper class can spread out shots with a given spread.

Pertaining to this, Tim Holt has created a modification to this shot distribution class so it's biased.

http://mathworld.wolfram.com/images/eps-gif/CircularDistribution_1000.gif

The source code is as follows...

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================//

#ifndef SHOT_MANIPULATOR_H
#define SHOT_MANIPULATOR_H
#ifdef _WIN32
#pragma once
#endif
 

#include "vector.h"


extern ConVar ai_shot_bias_min;
extern ConVar ai_shot_bias_max;
 

//---------------------------------------------------------
// Caches off a shot direction and allows you to perform
// various operations on it without having to recalculate
// vecRight and vecUp each time. 
//---------------------------------------------------------
class CShotManipulator
{
public:
	CShotManipulator( const Vector &vecForward )
	{
		SetShootDir( vecForward );
	}; 

	void SetShootDir( const Vector &vecForward )
	{
		m_vecShotDirection = vecForward;
		VectorVectors( m_vecShotDirection, m_vecRight, m_vecUp );
	}

	const Vector &ApplySpread( const Vector &vecSpread, float bias = 1.0 ); 

	const Vector &GetShotDirection()	{ return m_vecShotDirection; }
	const Vector &GetResult()			{ return m_vecResult; }
	const Vector &GetRightVector()		{ return m_vecRight; }
	const Vector &GetUpVector()			{ return m_vecUp;}

private:
	Vector m_vecShotDirection;
	Vector m_vecRight;
	Vector m_vecUp;
	Vector m_vecResult;
};

//---------------------------------------------------------
// Take a vector (direction) and another vector (spread) 
// and modify the direction to point somewhere within the 
// spread. This used to live inside FireBullets.
//---------------------------------------------------------
inline const Vector &CShotManipulator::ApplySpread( const Vector &vecSpread, float bias )
{
	// get circular gaussian spread
	float x, y, z;

	if ( bias > 1.0 )
		bias = 1.0;
	else if ( bias < 0.0 )
		bias = 0.0;

	float shotBiasMin = ai_shot_bias_min.GetFloat();
	float shotBiasMax = ai_shot_bias_max.GetFloat();

	// 1.0 gaussian, 0.0 is flat, -1.0 is inverse gaussian
	float shotBias = ( ( shotBiasMax - shotBiasMin ) * bias ) + shotBiasMin;

	float flatness = ( fabsf(shotBias) * 0.5 );

	do
	{
		x = random->RandomFloat(-1,1) * flatness + random->RandomFloat(-1,1) * (1 - flatness);
		y = random->RandomFloat(-1,1) * flatness + random->RandomFloat(-1,1) * (1 - flatness);
		if ( shotBias < 0 )
		{
			x = ( x >= 0 ) ? 1.0 - x : -1.0 - x;
			y = ( y >= 0 ) ? 1.0 - y : -1.0 - y;
		}
		z = x*x+y*y;
	} while (z > 1);

	m_vecResult = m_vecShotDirection + x * vecSpread.x * m_vecRight + y * vecSpread.y * m_vecUp;

	return m_vecResult;
}

 
#endif // SHOT_MANIPULATOR_H