You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

393 lines
9.7 KiB

//
// Copyright (c) 2010-2011 Matthew Jack and Doug Binks
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
#include "IGameObject.h"
#include "IObjectUtils.h"
#include "IBehaviorTreeManager.h"
#include "IBehaviorTree.h"
#include "IBehavior.h"
#include "IBlackboardManager.h"
#include "IGameManager.h"
#include "GlobalParameters.h"
#include "BB_Individual_Common.h"
#include "../../Common/Math.inl"
#include "../../RuntimeObjectSystem/ObjectInterfacePerModule.h"
#include "../../Systems/SystemTable.h"
#include "../../Systems/IEntitySystem.h"
#include "../../Systems/IAssetSystem.h"
#include "../../Systems/ILogSystem.h"
#include "../../RuntimeObjectSystem/ISimpleSerializer.h"
#include "../../Renderer/IAURenderable.h"
#include <assert.h>
#include <vector>
#include <stdio.h>
const AUVec3f ZERO(0,0,0);
class GameObject: public IGameObject
{
public:
GameObject()
: m_gameObjectType(EGO_COUNT)
, m_pBehaviorTree(0)
, m_pBehavior(0)
, m_pGameManager(0)
, m_pBlackboardManager(0)
, m_pGlobalParameters(0)
, m_pGameObjectParams(0)
, m_pRenMesh(0)
, m_rotationAxis(ZERO) // Demo
, m_collisionRadius(0.0f)
, m_scaleModulationTime(0.0f)
, m_bIsSelected(false)
{
}
virtual ~GameObject()
{
if (m_pRenMesh)
{
PerModuleInterface::g_pSystemTable->pAssetSystem->DestroyRenderableMesh(m_pRenMesh);
}
if( m_pEntity )
{
m_pEntity->SetRenderable(NULL);
m_pEntity->SetUpdateable(NULL);
}
if (!IsRuntimeDelete())
{
delete m_pBehavior;
}
}
// IEntityObject
virtual void Serialize(ISimpleSerializer *pSerializer)
{
IEntityObject::Serialize(pSerializer);
SERIALIZE(m_gameObjectType);
SERIALIZE(m_gameTeam);
SERIALIZE(m_color);
SERIALIZE(m_rotationAxis); // Demo
SERIALIZE(m_collisionRadius);
SERIALIZE(m_scaleModulationTime);
SERIALIZE(m_bIsSelected);
SERIALIZEIOBJPTR(m_pBehaviorTree);
SERIALIZEIOBJPTR(m_pBehavior);
}
virtual void Init( bool isFirstInit )
{
// Do nothing here on first init, because we need to use the more complicated version below
// to properly init the object
if (!isFirstInit)
{
DoInit(isFirstInit);
}
}
virtual void Init( EGameObject type, const AUVec3f& spawnPosition )
{
assert (type < EGO_COUNT);
if (type < EGO_COUNT)
{
// Initial load, set up some values for the first time
m_gameObjectType = type;
m_pEntity->SetPosition(spawnPosition);
// Now do regular init stuff
DoInit(true);
}
}
// ~IEntityObject
// IAUUpdateable
virtual void Update( float deltaTime )
{
AU_ASSERT(m_pBehaviorTree);
m_pBehaviorTree->Execute(this);
AU_ASSERT(m_pBehavior);
IBehavior* pBehavior = m_pBehavior; // Demo [Tutorial02] >>> NULL;//
pBehavior->Update(deltaTime);
UpdateScale();
m_scaleModulationTime += deltaTime;
//m_pRenMesh->SetColor( AUColor(1,1,1) ); // Demo // [Tutorial01]
SetRotation((float)M_PI_4 * 0.5f * deltaTime); // Demo
}
// ~IAUUpdateable
// IGameObject
virtual EGameObject GetGameObjectType() const
{
return m_gameObjectType;
}
virtual EGameTeam GetGameTeam() const
{
return m_gameTeam;
}
virtual const AUColor& GetColor() const
{
return m_color;
}
virtual IBehaviorTree* GetBehaviorTree()
{
return m_pBehaviorTree;
}
virtual IBehavior* GetBehavior()
{
return m_pBehavior;
}
virtual IAUEntity* GetEntity()
{
return m_pEntity;
}
virtual const IAUEntity* GetEntity() const
{
return m_pEntity;
}
virtual void SetModel( const char* file )
{
std::string path = "/Models/"; //directories relative to asset dir
path += file;
m_pRenMesh = PerModuleInterface::g_pSystemTable->pAssetSystem->CreateRenderableMeshFromFile( path.c_str() );
m_pEntity->SetRenderable( m_pRenMesh );
}
virtual void SetColor( const AUColor& color )
{
m_color = color;
if (m_pRenMesh)
{
m_pRenMesh->SetColor( m_color );
}
}
virtual void SetColor( float r, float g, float b, float a )
{
SetColor( AUColor(r, g, b, a) );
}
virtual void SetBehavior( ConstructorId constructor )
{
if (!m_pBehavior || m_pBehavior->GetObjectId().m_ConstructorId != constructor )
{
IBehavior* pBehavior = 0;
IObjectUtils::CreateObject( &pBehavior, constructor );
// Only destroy and replace existing behavior if we successfully created new one
if (pBehavior)
{
if (m_pBehavior)
{
m_pBehavior->EndBehavior();
delete m_pBehavior;
}
m_pBehavior = pBehavior;
m_pBehavior->SetGameObject(this);
m_pBehavior->StartBehavior();
}
}
}
virtual void OnSelect()
{
SetColor( m_pGameObjectParams->color_highlight );
m_bIsSelected = true;
}
virtual void OnDeselect()
{
SetColor( m_pGameObjectParams->color_normal );
m_bIsSelected = false;
}
virtual void OnPositionRequest( const AUVec3f& position )
{
BB_Individual_Common* pBB = (BB_Individual_Common*)m_pBlackboardManager->GetBlackboardIndividualCommon( this );
pBB->target_position = position;
}
virtual void OnCollision( IGameObject* pCollider )
{
if (m_pBehavior)
{
m_pBehavior->OnCollision( pCollider );
}
}
virtual float GetCollisionRadius() const
{
return m_collisionRadius;
}
virtual float GetMaxSpeed() const
{
return m_pGameObjectParams->max_speed;
}
virtual float GetHealth() const
{
BB_Individual_Common* pBB = (BB_Individual_Common*)m_pBlackboardManager->GetBlackboardIndividualCommon( this );
return pBB->current_health;
}
virtual float GetThreatRating() const
{
BB_Individual_Common* pBB = (BB_Individual_Common*)m_pBlackboardManager->GetBlackboardIndividualCommon( this );
return pBB->current_health * m_pGameObjectParams->attack_damage * ( 1.0f / m_pGameObjectParams->attack_speed );
}
virtual void GetDebugInfo( char* outputBuffer, size_t bufferLen )
{
BB_Individual_Common* pBB = (BB_Individual_Common*)m_pBlackboardManager->GetBlackboardIndividualCommon( this );
const AUVec3f& pos = pBB->current_position;
const AUVec3f& vel = pBB->current_velocity;
_snprintf_s( outputBuffer, bufferLen, _TRUNCATE,
"ID: %d\n"
"Name: %s\n"
"Position: (%0.2f, %0.2f, %0.2f)\n"
"Velocity: (%0.2f, %0.2f, %0.2f)\n"
"Health: %0.0f\n"
"Behavior: %s\n",
m_pEntity->GetId(), m_pEntity->GetName(), pos.x, pos.y, pos.z,
vel.x, vel.y, vel.z, pBB->current_health,
m_pBehavior ? m_pBehavior->GetTypeName() : "none"
);
}
// ~IGameObject
private:
void DoInit(bool bFirstTime)
{
m_pGameManager = (IGameManager*)IObjectUtils::GetUniqueInterface( "GameManager", IID_IGAMEMANAGER );
m_pBlackboardManager= (IBlackboardManager*)IObjectUtils::GetUniqueInterface( "BlackboardManager", IID_IBLACKBOARDMANAGER );
m_pGlobalParameters = m_pGameManager->GetGlobalParameters();
m_pGameObjectParams = &(m_pGlobalParameters->go[m_gameObjectType]);
m_gameTeam = m_pGameObjectParams->team;
SetModel( m_pGameObjectParams->model.c_str() );
m_collisionRadius = m_pGameObjectParams->collision_radius;
if (bFirstTime)
{
SetColor( m_bIsSelected ? m_pGameObjectParams->color_highlight : m_pGameObjectParams->color_normal);
m_scaleModulationTime = (float)(rand()*2*M_PI/RAND_MAX);
}
else
{
SetColor( m_color ); // Set render mesh to serialised color
}
if (!m_pBehaviorTree)
{
IBehaviorTreeManager* pBTManager = (IBehaviorTreeManager*)IObjectUtils::GetUniqueInterface( "BehaviorTreeManager", IID_IBEHAVIORTREEMANAGER );
m_pBehaviorTree = pBTManager->GetTree( m_pGameObjectParams->behavior_tree.c_str() );
AU_ASSERT(m_pBehaviorTree);
}
//* Demo
if (m_rotationAxis.IsZero())
{
m_rotationAxis = AUVec3f((float)rand()/RAND_MAX - 0.5f, (float)rand()/RAND_MAX - 0.5f, (float)rand()/RAND_MAX - 0.5f);
m_rotationAxis.Normalise();
SetRotation((float)(rand()*2*M_PI/RAND_MAX - M_PI));
}
//*/
m_pEntity->SetUpdateable( this );
}
//* Demo
void SetRotation(float fRotation)
{
AUOrientation3D orientation = m_pEntity->GetOrientation();
orientation.Rotate(m_rotationAxis, fRotation);
m_pEntity->SetOrientation(orientation);
}
//*/
void UpdateScale()
{
BB_Individual_Common* pBB = (BB_Individual_Common*)m_pBlackboardManager->GetBlackboardIndividualCommon( this );
const float sizeDiff = m_pGameObjectParams->max_size - m_pGameObjectParams->min_size;
const float healthProportion = pBB->current_health / m_pGameObjectParams->initial_health;
const float modulation = 1.0f + sin(m_scaleModulationTime) * 0.3f;
const float scale = m_pGameObjectParams->min_size + sizeDiff * healthProportion;// * modulation; // Demo
m_pEntity->SetScale( m_pGameObjectParams->base_size_modifier * scale );
m_collisionRadius = scale * m_pGameObjectParams->collision_radius;
}
// Private Members
EGameObject m_gameObjectType;
EGameTeam m_gameTeam;
IBehaviorTree* m_pBehaviorTree;
IBehavior* m_pBehavior;
IGameManager* m_pGameManager;
IBlackboardManager* m_pBlackboardManager;
GlobalParameters* m_pGlobalParameters;
GameObjectParams* m_pGameObjectParams;
IAURenderableMesh* m_pRenMesh;
AUColor m_color;
AUVec3f m_rotationAxis; // Demo
float m_collisionRadius;
float m_scaleModulationTime;
bool m_bIsSelected;
};
REGISTERCLASS(GameObject);