Entity code reorganization.
This was SVN commit r278.
This commit is contained in:
parent
672c25084b
commit
0b8ff2d0da
35
source/simulation/Collision.cpp
Executable file
35
source/simulation/Collision.cpp
Executable 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
24
source/simulation/Collision.h
Executable 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
|
@ -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.
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -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
|
||||
|
134
source/simulation/EntityStateProcessing.cpp
Executable file
134
source/simulation/EntityStateProcessing.cpp
Executable 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 );
|
||||
}
|
Loading…
Reference in New Issue
Block a user