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.
394 lines
9.7 KiB
394 lines
9.7 KiB
2 months ago
|
//
|
||
|
// 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);
|
||
|
|
||
|
|
||
|
|
||
|
|