1
0
forked from 0ad/0ad

Entity code reorganization.

This was SVN commit r278.
This commit is contained in:
MarkT 2004-05-28 02:57:50 +00:00
parent 672c25084b
commit 0b8ff2d0da
8 changed files with 719 additions and 164 deletions

35
source/simulation/Collision.cpp Executable file
View File

@ -0,0 +1,35 @@
#include "Collision.h"
#include "EntityManager.h"
HEntity getCollisionObject( CEntity* entity )
{
assert( entity->m_bounds );
std::vector<HEntity>* entities = g_EntityManager.getActive();
std::vector<HEntity>::iterator it;
for( it = entities->begin(); it != entities->end(); it++ )
{
assert( (*it)->m_bounds );
if( (*it)->m_bounds == entity->m_bounds ) continue;
if( entity->m_bounds->intersects( (*it)->m_bounds ) )
{
HEntity collisionObject = *it;
delete( entities );
return( collisionObject );
}
}
delete( entities );
return( HEntity() );
}
HEntity getCollisionObject( CEntity* entity, float x, float y )
{
float _x = entity->m_bounds->m_pos.x;
float _y = entity->m_bounds->m_pos.y;
entity->m_bounds->setPosition( x, y );
HEntity _e = getCollisionObject( entity );
entity->m_bounds->setPosition( _x, _y );
return( _e );
}

24
source/simulation/Collision.h Executable file
View File

@ -0,0 +1,24 @@
// Collision.h
//
// Last modified: 28 May 04, Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
//
// Collision detection functions
//
// Usage: Fairly trivial; getCollisionObject( CEntity* entity ) will return the first entity colliding with the given entity.
// The version with (x, y) parameters is just a helper; it temporarily moves the entity's collision bounds to the given
// position before transferring to the other function.
// Notes: getCollisionObject will only return the /first/ entity it finds in collision. This /may/ need a rethink when
// multiple-entity (pileup) collisions become possible, I don't know.
//
// Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
#ifndef COLLISION_INCLUDED
#define COLLISION_INCLUDED
#include "BoundingObjects.h"
#include "Entity.h"
HEntity getCollisionObject( CEntity* entity );
HEntity getCollisionObject( CEntity* entity, float x, float y );
#endif

View File

@ -8,6 +8,8 @@
#include "Model.h"
#include "Terrain.h"
#include "Collision.h"
CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
{
// Set our parent unit and build us an actor.
@ -133,131 +135,14 @@ void CEntity::update( float timestep )
{
case CEntityOrder::ORDER_GOTO_NOPATHING:
case CEntityOrder::ORDER_GOTO_COLLISION:
{
CVector2D delta;
delta.x = (float)current->m_data[0].location.x - m_position.X;
delta.y = (float)current->m_data[0].location.y - m_position.Z;
m_ahead = delta.normalize();
if( m_bounds->m_type == CBoundingObject::BOUND_OABB )
((CBoundingBox*)m_bounds)->setOrientation( m_ahead );
float len = delta.length();
float scale = timestep * m_speed;
if( scale > len )
scale = len;
delta = m_ahead * scale;
m_position.X += delta.x;
m_position.Z += delta.y;
m_bounds->setPosition( m_position.X, m_position.Z );
HEntity collide = getCollisionObject();
if( collide )
{
// Hit something. Take a step back.
m_position.X -= delta.x;
m_position.Z -= delta.y;
m_bounds->setPosition( m_position.X, m_position.Z );
// Are we still hitting it?
if( collide->m_bounds->intersects( m_bounds ) )
{
// Oh dear. Most likely explanation is that this unit was created
// within the bounding area of another entity.
// Try a little boost of speed, to help resolve the situation more quickly.
m_position.X += delta.x * 2.0f;
m_position.Z += delta.y * 2.0f;
m_bounds->setPosition( m_position.X, m_position.Z );
return;
}
if( collide->m_bounds->m_type == CBoundingObject::BOUND_OABB )
{
// And it's square.
// TODO: Implement this case properly.
// HACK: See if this thing we've hit is likely to be our destination. If so, just skip to our next waypoint.
// Otherwise, turn right (as with circle collisions)
if( len < collide->m_bounds->m_radius * 2.0f )
{
m_orderQueue.pop_front();
return;
}
else
{
CEntityOrder avoidance;
avoidance.m_type = CEntityOrder::ORDER_GOTO_COLLISION;
CVector2D right;
right.x = m_ahead.y; right.y = -m_ahead.x;
CVector2D avoidancePosition = collide->m_bounds->m_pos + right * ( collide->m_bounds->m_radius * 2.5f );
avoidance.m_data[0].location = avoidancePosition;
if( current->m_type == CEntityOrder::ORDER_GOTO_COLLISION )
m_orderQueue.pop_front();
m_orderQueue.push_front( avoidance );
return;
}
}
else
{
// A circle.
// TODO: Implement this properly.
// Try turning right.
CEntityOrder avoidance;
avoidance.m_type = CEntityOrder::ORDER_GOTO_COLLISION;
CVector2D right;
right.x = m_ahead.y; right.y = -m_ahead.x;
CVector2D avoidancePosition = collide->m_bounds->m_pos + right * ( collide->m_bounds->m_radius * 2.5f );
avoidance.m_data[0].location = avoidancePosition;
if( current->m_type == CEntityOrder::ORDER_GOTO_COLLISION )
m_orderQueue.pop_front();
m_orderQueue.push_front( avoidance );
return;
}
}
snapToGround();
updateActorTransforms();
if( len < 0.1f )
m_orderQueue.pop_front();
return;
break;
}
if( processGotoNoPathing( current, timestep ) ) break;
return;
case CEntityOrder::ORDER_GOTO:
{
CEntityOrder pathfind_solution;
pathfind_solution.m_type = CEntityOrder::ORDER_GOTO_NOPATHING;
pathfind_solution.m_data[0] = current->m_data[0];
m_orderQueue.pop_front();
m_orderQueue.push_front( pathfind_solution );
if( m_actor->m_Model->GetAnimation() != m_actor->m_Object->m_WalkAnim )
{
m_actor->m_Model->SetAnimation( m_actor->m_Object->m_WalkAnim );
m_actor->m_Model->Update( ( rand() * 1000.0f ) / 1000.0f );
}
break;
}
if( processGoto( current, timestep ) ) break;
return;
case CEntityOrder::ORDER_PATROL:
{
CEntityOrder this_segment;
CEntityOrder repeat_patrol;
this_segment.m_type = CEntityOrder::ORDER_GOTO;
this_segment.m_data[0] = current->m_data[0];
repeat_patrol.m_type = CEntityOrder::ORDER_PATROL;
repeat_patrol.m_data[0] = current->m_data[0];
m_orderQueue.pop_front();
m_orderQueue.push_front( this_segment );
m_orderQueue.push_back( repeat_patrol );
break;
}
if( processPatrol( current, timestep ) ) break;
return;
default:
assert( 0 && "Invalid entity order" );
}
@ -306,42 +191,10 @@ void CEntity::render()
// We can loose this later on, I just need a way to see collision boxes temporarily
glColor3f( 1.0f, 1.0f, 1.0f );
if( getCollisionObject() ) glColor3f( 0.5f, 0.5f, 1.0f );
if( getCollisionObject( this ) ) glColor3f( 0.5f, 0.5f, 1.0f );
m_bounds->render( m_position.Y + 0.25f );
}
HEntity CEntity::getCollisionObject()
{
if( !m_bounds ) return( HEntity() );
std::vector<HEntity>* entities = g_EntityManager.getActive();
std::vector<HEntity>::iterator it;
for( it = entities->begin(); it != entities->end(); it++ )
{
if( *it == me ) continue;
if( (*it)->m_bounds )
if( m_bounds->intersects( (*it)->m_bounds ) )
{
HEntity collisionObject = *it;
delete( entities );
return( collisionObject );
}
}
delete( entities );
return( HEntity() );
}
HEntity CEntity::getCollisionObject( float x, float y )
{
float _x = m_bounds->m_pos.x;
float _y = m_bounds->m_pos.y;
m_bounds->setPosition( x, y );
HEntity _e = getCollisionObject();
m_bounds->setPosition( _x, _y );
return( _e );
}
void PASAPScenario()
{
// Got rid of all the hardcoding that was here.

View File

@ -64,6 +64,11 @@ public:
private:
CEntity( CBaseEntity* base, CVector3D position, float orientation );
bool processGotoNoPathing( CEntityOrder* current, float timestep );
bool processGoto( CEntityOrder* current, float timestep );
bool processPatrol( CEntityOrder* current, float timestep );
public:
// Handle-to-self.
@ -75,8 +80,6 @@ public:
float getExactGroundLevel( float x, float y );
void snapToGround();
void pushOrder( CEntityOrder& order );
HEntity getCollisionObject();
HEntity getCollisionObject( float x, float y );
};
#endif

View File

@ -11,6 +11,9 @@
// Perform updates on all world entities by g_EntityManager.updateAll( timestep )
// Dispatch an identical message to all world entities by g_EntityManager.dispatchAll( message_pointer )
// Get an STL vector container of all entities with a certain property with g_EntityManager.matches( predicate )
// or just get all entities with g_EntityManager.getActive().
//
// Those last two functions - caller has responsibility for deleting the collection when you're done with it.
#ifndef ENTITY_MANAGER_INCLUDED
#define ENTITY_MANAGER_INCLUDED

View File

@ -6,6 +6,462 @@ CGenericProperty::CGenericProperty()
m_integer = 0;
}
CGenericProperty::~CGenericProperty()
{
releaseData();
}
void CGenericProperty::releaseData()
{
switch( m_type & ~PROP_TYPELOCKED )
{
case PROP_STRING:
delete( m_string ); break;
case PROP_VECTOR:
delete( m_vector ); break;
default:
break;
}
}
CGenericProperty::operator i32()
{
return( toInteger() );
}
CGenericProperty::operator float()
{
return( toFloat() );
}
CGenericProperty::operator CStr()
{
return( toString() );
}
CGenericProperty::operator CVector3D()
{
return( toVector() );
}
CGenericProperty::operator void *()
{
return( toVoid() );
}
CGenericProperty& CGenericProperty::operator=( int32 value )
{
if( m_type & PROP_TYPELOCKED )
{
fromInteger( value );
}
else
{
releaseData();
m_type = PROP_INTEGER;
m_integer = value;
}
return( *this );
}
CGenericProperty& CGenericProperty::operator=( float value )
{
if( m_type & PROP_TYPELOCKED )
{
fromFloat( value );
}
else
{
releaseData();
m_type = PROP_FLOAT;
m_float = value;
}
return( *this );
}
CGenericProperty& CGenericProperty::operator=( CStr& value )
{
if( m_type & PROP_TYPELOCKED )
{
fromString( value );
}
else
{
releaseData();
m_type = PROP_STRING;
m_string = new CStr( value );
}
return( *this );
}
CGenericProperty& CGenericProperty::operator=( CVector3D& value )
{
if( m_type & PROP_TYPELOCKED )
{
fromVector( value );
}
else
{
releaseData();
m_type = PROP_VECTOR;
m_vector = new CVector3D( value );
}
return( *this );
}
CGenericProperty& CGenericProperty::operator =( void* value )
{
if( m_type & PROP_TYPELOCKED )
{
fromVoid( value );
}
else
{
releaseData();
m_type = PROP_PTR;
m_ptr = value;
}
return( *this );
}
void CGenericProperty::associate( i32* value )
{
i32 current = toInteger();
releaseData();
m_type = (EPropTypes)( PROP_INTEGER | PROP_INTRINSIC | PROP_TYPELOCKED );
m_integerptr = value;
*m_integerptr = current;
}
void CGenericProperty::associate( float* value )
{
float current = toFloat();
releaseData();
m_type = (EPropTypes)( PROP_FLOAT | PROP_INTRINSIC | PROP_TYPELOCKED );
m_floatptr = value;
*m_floatptr = current;
}
void CGenericProperty::associate( CStr* value )
{
CStr current = toString();
releaseData();
m_type = (EPropTypes)( PROP_STRING | PROP_VECTOR | PROP_TYPELOCKED );
m_string = value;
*m_string = current;
}
void CGenericProperty::associate( CVector3D* value )
{
CVector3D current = toVector();
releaseData();
m_type = (EPropTypes)( PROP_VECTOR | PROP_INTRINSIC | PROP_TYPELOCKED );
m_vector = value;
*value = current;
}
void CGenericProperty::typelock( EPropTypes type )
{
if( m_type & PROP_INTRINSIC ) return;
switch( type )
{
case PROP_INTEGER:
{
i32 current = toInteger();
releaseData();
m_integer = current;
}
break;
case PROP_FLOAT:
{
float current = toFloat();
releaseData();
m_float = current;
}
break;
case PROP_STRING:
{
CStr* current = new CStr( toString() );
releaseData();
m_string = current;
}
break;
case PROP_VECTOR:
{
CVector3D* current = new CVector3D( toVector() );
releaseData();
m_vector = current;
}
break;
case PROP_PTR:
{
void* current = toVoid();
releaseData();
m_ptr = current;
}
break;
default:
return;
}
m_type = (EPropTypes)( type | PROP_TYPELOCKED );
}
void CGenericProperty::typeloose()
{
if( m_type & PROP_INTRINSIC ) return;
m_type = (EPropTypes)( m_type & ~PROP_TYPELOCKED );
}
i32& CGenericProperty::asInteger()
{
assert( ( m_type & PROP_STRIPFLAGS ) == PROP_INTEGER );
if( m_type & PROP_INTRINSIC )
return( *m_integerptr );
return( m_integer );
}
float& CGenericProperty::asFloat()
{
assert( ( m_type & PROP_STRIPFLAGS ) == PROP_FLOAT );
if( m_type & PROP_INTRINSIC )
return( *m_floatptr );
return( m_float );
}
CStr& CGenericProperty::asString()
{
assert( ( m_type & PROP_STRIPFLAGS ) == PROP_STRING );
return( *m_string );
}
CVector3D& CGenericProperty::asVector()
{
assert( ( m_type & PROP_STRIPFLAGS ) == PROP_VECTOR );
return( *m_vector );
}
i32 CGenericProperty::toInteger()
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
return( asInteger() );
case PROP_FLOAT:
return( (i32)asFloat() );
case PROP_STRING:
case PROP_STRING_INTRINSIC:
return( (i32)( asString().ToInt() ) );
case PROP_VECTOR:
case PROP_VECTOR_INTRINSIC:
case PROP_PTR:
return( 0 );
default:
assert( 0 && "Invalid property type" );
}
return( 0 );
}
float CGenericProperty::toFloat()
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
return( (float)asInteger() );
case PROP_FLOAT:
return( asFloat() );
case PROP_STRING:
case PROP_STRING_INTRINSIC:
return( asString().ToFloat() );
case PROP_VECTOR:
case PROP_VECTOR_INTRINSIC:
case PROP_PTR:
return( 0.0f );
default:
assert( 0 && "Invalid property type" );
}
return( 0.0f );
}
CStr CGenericProperty::toString()
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
return( CStr( asInteger() ) );
case PROP_FLOAT:
return( CStr( asFloat() ) );
case PROP_STRING:
return( CStr( asString() ) );
case PROP_VECTOR:
{
char buffer[256];
snprintf( buffer, 250, "{ %f, %f, %f }", asVector().X, asVector().Y, asVector().Z );
return( CStr( buffer ) );
}
case PROP_PTR:
return( CStr() );
default:
assert( 0 && "Invalid property type" );
}
return( CStr() );
}
CVector3D CGenericProperty::toVector()
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_VECTOR:
return( CVector3D( asVector() ) );
case PROP_INTEGER:
case PROP_FLOAT:
case PROP_STRING:
case PROP_PTR:
return( CVector3D() );
default:
assert( 0 && "Invalid property type" );
}
return( CVector3D() );
}
void* CGenericProperty::toVoid()
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_PTR:
return( m_ptr );
case PROP_INTEGER:
case PROP_INTEGER_INTRINSIC:
case PROP_FLOAT:
case PROP_FLOAT_INTRINSIC:
case PROP_STRING:
case PROP_STRING_INTRINSIC:
case PROP_VECTOR:
case PROP_VECTOR_INTRINSIC:
return( NULL );
default:
assert( 0 && "Invalid property type" );
}
return( NULL );
}
void CGenericProperty::fromInteger( i32 value )
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
asInteger() = value; return;
case PROP_FLOAT:
asFloat() = (float)value; return;
case PROP_STRING:
asString() = value; return;
case PROP_VECTOR:
asVector() = CVector3D(); return;
case PROP_PTR:
m_ptr = NULL; return;
default:
assert( 0 && "Invalid property type" );
}
}
void CGenericProperty::fromFloat( float value )
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
asInteger() = (i32)value; return;
case PROP_FLOAT:
asFloat() = value; return;
case PROP_STRING:
asString() = value; return;
case PROP_VECTOR:
asVector() = CVector3D(); return;
case PROP_PTR:
m_ptr = NULL; return;
default:
assert( 0 && "Invalid property type" );
}
}
void CGenericProperty::fromString( CStr& value )
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
asInteger() = value.ToInt(); return;
case PROP_FLOAT:
asFloat() = value.ToFloat(); return;
case PROP_STRING:
asString() = value; return;
case PROP_VECTOR:
asVector() = CVector3D(); return;
case PROP_PTR:
m_ptr = NULL; return;
default:
assert( 0 && "Invalid property type" );
}
}
void CGenericProperty::fromVector( CVector3D& value )
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
asInteger() = 0; return;
case PROP_FLOAT:
asFloat() = 0.0f; return;
case PROP_STRING:
{
char buffer[256];
snprintf( buffer, 250, "{ %f, %f, %f }", value.X, value.Y, value.Z );
asString() = CStr( buffer );
}
return;
case PROP_VECTOR:
asVector() = CVector3D( value ); return;
case PROP_PTR:
m_ptr = NULL; return;
default:
assert( 0 && "Invalid property type" );
}
}
void CGenericProperty::fromVoid( void* value )
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
asInteger() = 0; return;
case PROP_FLOAT:
asFloat() = 0.0f; return;
case PROP_STRING:
asString() = CStr(); return;
case PROP_VECTOR:
asVector() = CVector3D(); return;
case PROP_PTR:
m_ptr = value; return;
default:
assert( 0 && "Invalid property type" );
}
}
/*
Here lies the old version of CGenericProperty. Will remove it when I know the new one works.
CGenericProperty::CGenericProperty()
{
m_type = PROP_INTEGER;
m_integer = 0;
}
CGenericProperty::CGenericProperty( i32 value )
{
m_type = PROP_INTEGER;
@ -73,7 +529,7 @@ CGenericProperty::~CGenericProperty()
}
}
CGenericProperty::operator CStr()
CGenericProperty::operator CStr&()
{
char working[64];
switch( m_type )
@ -158,3 +614,4 @@ CGenericProperty::operator void*()
return( NULL );
}
}
*/

View File

@ -7,9 +7,6 @@
// Usage: Nothing yet.
// These properties will be accessed via functions in CEntity/CBaseEntity
//
// Inefficiency warning.
// Will move frequently accessed properties (position, name, etc.) to native C++ primitives.
// Just playing around with this idea, will probably keep it for at least some of the more exotic and/or user-defined properties.
// TODO: Fix the silent failures of the conversion functions: need to work out what to do in these cases.
@ -39,6 +36,8 @@ public:
enum EPropTypes
{
PROP_INTRINSIC = 256,
PROP_TYPELOCKED = 512,
PROP_STRIPFLAGS = 255,
PROP_INTEGER = 0,
PROP_FLOAT,
PROP_STRING,
@ -49,8 +48,8 @@ public:
PROP_STRING_INTRINSIC = PROP_STRING | PROP_INTRINSIC,
PROP_VECTOR_INTRINSIC = PROP_VECTOR | PROP_INTRINSIC
};
private:
EPropTypes m_type;
private:
union
{
i32 m_integer;
@ -63,6 +62,10 @@ private:
};
public:
CGenericProperty(); // Create an integer property containing 0.
~CGenericProperty();
void releaseData();
/*
CGenericProperty( i32 value ); // Create an integer property with a given value.
CGenericProperty( i32* value ); // Create an integer property that points to the given variable.
CGenericProperty( float value ); // Create a floating-point property with a given value.
@ -72,12 +75,55 @@ public:
CGenericProperty( CVector3D& value ); // Create a vector object property that's initialized to a copy of the given vector.
CGenericProperty( CVector3D* value ); // Create a vector object property that points to the given variable.
CGenericProperty( void* value ); // Create a general property that points to the given value.
~CGenericProperty();
*/
// Associator functions: Links the property with the specified engine variable.
void associate( i32* value );
void associate( float* value );
void associate( CStr* value );
void associate( CVector3D* value );
// Getter functions: Attempts to convert the property to the given type.
operator i32(); // Convert to an integer if possible (integer, float, some strings), otherwise returns 0.
operator float(); // Convert to a float if possible (integer, float, some strings), otherwise returns 0.0f.
operator CStr(); // Convert to a string if possible (all except generic pointer), otherwise returns CStr().
operator CVector3D(); // If this property is a vector, returns that vector, otherwise returns CVector3D().
operator void*(); // If this property is a generic pointer, returns that pointer, otherwise returns NULL.
// Setter functions: If this is a typelocked property, attempts to convert the given data
// into the appropriate type, otherwise setting the associated value to 0, 0.0f, CStr() or CVector3D().
// If this property is typeloose, converts this property into one of the same type
// as the given value, then stores that value in this property.
CGenericProperty& operator=( i32 value );
CGenericProperty& operator=( float value );
CGenericProperty& operator=( CStr& value );
CGenericProperty& operator=( CVector3D& value );
CGenericProperty& operator=( void* value ); // Be careful with this one. A lot of things will cast to void*.
// Typelock functions. Use these when you want to make sure the property has the given type.
void typelock( EPropTypes type );
void typeloose();
private:
// resolve-as functions. References the data, whereever it is.
i32& asInteger();
float& asFloat();
CStr& asString();
CVector3D& asVector();
// to functions. Convert whatever this is now to the chosen type.
i32 toInteger();
float toFloat();
CStr toString();
CVector3D toVector();
void* toVoid();
// from functions. Convert the given value to whatever type this is now.
void fromInteger( i32 value );
void fromFloat( float value );
void fromString( CStr& value );
void fromVector( CVector3D& value );
void fromVoid( void* value );
};
#endif

View File

@ -0,0 +1,134 @@
// Entity state-machine processing code.
#include "Entity.h"
#include "Model.h"
#include "Collision.h"
bool CEntity::processGotoNoPathing( CEntityOrder* current, float timestep )
{
CVector2D delta;
delta.x = (float)current->m_data[0].location.x - m_position.X;
delta.y = (float)current->m_data[0].location.y - m_position.Z;
m_ahead = delta.normalize();
if( m_bounds->m_type == CBoundingObject::BOUND_OABB )
((CBoundingBox*)m_bounds)->setOrientation( m_ahead );
float len = delta.length();
float scale = timestep * m_speed;
if( scale > len )
scale = len;
delta = m_ahead * scale;
m_position.X += delta.x;
m_position.Z += delta.y;
m_bounds->setPosition( m_position.X, m_position.Z );
HEntity collide = getCollisionObject( this );
if( collide )
{
// Hit something. Take a step back.
m_position.X -= delta.x;
m_position.Z -= delta.y;
m_bounds->setPosition( m_position.X, m_position.Z );
// Are we still hitting it?
if( collide->m_bounds->intersects( m_bounds ) )
{
// Oh dear. Most likely explanation is that this unit was created
// within the bounding area of another entity.
// Try a little boost of speed, to help resolve the situation more quickly.
m_position.X += delta.x * 2.0f;
m_position.Z += delta.y * 2.0f;
m_bounds->setPosition( m_position.X, m_position.Z );
return( false );
}
if( collide->m_bounds->m_type == CBoundingObject::BOUND_OABB )
{
// And it's square.
// TODO: Implement this case properly.
// HACK: See if this thing we've hit is likely to be our destination. If so, just skip to our next waypoint.
// Otherwise, turn right (as with circle collisions)
if( len < collide->m_bounds->m_radius * 2.0f )
{
m_orderQueue.pop_front();
return( false );
}
else
{
CEntityOrder avoidance;
avoidance.m_type = CEntityOrder::ORDER_GOTO_COLLISION;
CVector2D right;
right.x = m_ahead.y; right.y = -m_ahead.x;
CVector2D avoidancePosition = collide->m_bounds->m_pos + right * ( collide->m_bounds->m_radius * 2.5f );
avoidance.m_data[0].location = avoidancePosition;
if( current->m_type == CEntityOrder::ORDER_GOTO_COLLISION )
m_orderQueue.pop_front();
m_orderQueue.push_front( avoidance );
return( false );
}
}
else
{
// A circle.
// TODO: Implement this properly.
// Try turning right.
CEntityOrder avoidance;
avoidance.m_type = CEntityOrder::ORDER_GOTO_COLLISION;
CVector2D right;
right.x = m_ahead.y; right.y = -m_ahead.x;
CVector2D avoidancePosition = collide->m_bounds->m_pos + right * ( collide->m_bounds->m_radius * 2.5f );
avoidance.m_data[0].location = avoidancePosition;
if( current->m_type == CEntityOrder::ORDER_GOTO_COLLISION )
m_orderQueue.pop_front();
m_orderQueue.push_front( avoidance );
return( false );
}
}
snapToGround();
updateActorTransforms();
if( len < 0.1f )
m_orderQueue.pop_front();
return( false );
}
bool CEntity::processGoto( CEntityOrder* current, float timestep )
{
CEntityOrder pathfind_solution;
pathfind_solution.m_type = CEntityOrder::ORDER_GOTO_NOPATHING;
pathfind_solution.m_data[0] = current->m_data[0];
m_orderQueue.pop_front();
m_orderQueue.push_front( pathfind_solution );
if( m_actor->m_Model->GetAnimation() != m_actor->m_Object->m_WalkAnim )
{
m_actor->m_Model->SetAnimation( m_actor->m_Object->m_WalkAnim );
m_actor->m_Model->Update( ( rand() * 1000.0f ) / 1000.0f );
}
return( true );
}
bool CEntity::processPatrol( CEntityOrder* current, float timestep )
{
CEntityOrder this_segment;
CEntityOrder repeat_patrol;
this_segment.m_type = CEntityOrder::ORDER_GOTO;
this_segment.m_data[0] = current->m_data[0];
repeat_patrol.m_type = CEntityOrder::ORDER_PATROL;
repeat_patrol.m_data[0] = current->m_data[0];
m_orderQueue.pop_front();
m_orderQueue.push_front( this_segment );
m_orderQueue.push_back( repeat_patrol );
return( true );
}