actorphysicsproperty.cc
Go to the documentation of this file.00001
00002
00003
00004
00005 #include "properties/actorphysicsproperty.h"
00006 #include "foundation/factory.h"
00007 #include "attr/attributes.h"
00008 #include "physics/server.h"
00009 #include "physics/level.h"
00010 #include "managers/timemanager.h"
00011 #include "mathlib/polar.h"
00012 #include "graphics/server.h"
00013 #include "graphics/cameraentity.h"
00014 #include "managers/entitymanager.h"
00015 #include "navigation/server.h"
00016 #include "msg/movesetvelocity.h"
00017
00018 namespace Properties
00019 {
00020 ImplementRtti(Properties::ActorPhysicsProperty, Properties::AbstractPhysicsProperty);
00021 ImplementFactory(Properties::ActorPhysicsProperty);
00022
00023 using namespace Game;
00024 using namespace Message;
00025 using namespace Managers;
00026
00027
00030 ActorPhysicsProperty::ActorPhysicsProperty() :
00031 followTargetDist(4.0f),
00032 curGotoSegment(0),
00033 gotoTimeStamp(0.0),
00034 headingGain(-4.0f),
00035 positionGain(-25.0f)
00036 {
00037
00038 }
00039
00040
00043 ActorPhysicsProperty::~ActorPhysicsProperty()
00044 {
00045
00046 }
00047
00048
00051 void
00052 ActorPhysicsProperty::SetupDefaultAttributes()
00053 {
00054 AbstractPhysicsProperty::SetupDefaultAttributes();
00055 this->GetEntity()->SetVector3(Attr::VelocityVector, vector3(0.0f, 0.0f, 0.0f));
00056 this->GetEntity()->SetFloat(Attr::RelVelocity, 1.0f);
00057 this->GetEntity()->SetFloat(Attr::MaxVelocity, 2.5f);
00058 this->GetEntity()->SetBool(Attr::Following, false);
00059 this->GetEntity()->SetBool(Attr::Moving, false);
00060 }
00061
00062
00066 void
00067 ActorPhysicsProperty::EnablePhysics()
00068 {
00069 n_assert(!this->IsEnabled());
00070
00071
00072 this->charPhysicsEntity = Physics::CharEntity::Create();
00073 this->charPhysicsEntity->SetUserData(this->GetEntity()->GetUniqueId());
00074 if (this->GetEntity()->HasAttr(Attr::Physics))
00075 {
00076 this->charPhysicsEntity->SetCompositeName(this->GetEntity()->GetString(Attr::Physics));
00077 }
00078 this->charPhysicsEntity->SetTransform(this->GetEntity()->GetMatrix44(Attr::Transform));
00079
00080
00081 Physics::Level* physicsLevel = Physics::Server::Instance()->GetLevel();
00082 n_assert(physicsLevel);
00083 physicsLevel->AttachEntity(this->charPhysicsEntity);
00084
00085
00086 this->Stop();
00087
00088
00089 nTime time = TimeManager::Instance()->GetTime();
00090 const matrix44& entityMatrix = this->GetEntity()->GetMatrix44(Attr::Transform);
00091 this->smoothedPosition.Reset(time, 0.0001f, this->positionGain, entityMatrix.pos_component());
00092
00093 polar2 headingAngle(entityMatrix.z_component());
00094 this->smoothedHeading.Reset(time, 0.0001f, this->headingGain, headingAngle.rho);
00095
00096
00097 AbstractPhysicsProperty::EnablePhysics();
00098 }
00099
00100
00103 void
00104 ActorPhysicsProperty::DisablePhysics()
00105 {
00106 n_assert(this->IsEnabled());
00107
00108
00109 this->Stop();
00110
00111
00112 Physics::Level* physicsLevel = Physics::Server::Instance()->GetLevel();
00113 n_assert(physicsLevel);
00114 physicsLevel->RemoveEntity(this->charPhysicsEntity);
00115
00116
00117 this->charPhysicsEntity = 0;
00118
00119
00120 AbstractPhysicsProperty::DisablePhysics();
00121 }
00122
00123
00126 bool
00127 ActorPhysicsProperty::Accepts(Message::Msg* msg)
00128 {
00129 return msg->CheckId(MoveDirection::Id) ||
00130 msg->CheckId(MoveFollow::Id) ||
00131 msg->CheckId(MoveGoto::Id) ||
00132 msg->CheckId(MoveStop::Id) ||
00133 msg->CheckId(SetTransform::Id) ||
00134 msg->CheckId(MoveTurn::Id) ||
00135 msg->CheckId(MoveSetVelocity::Id) ||
00136 msg->CheckId(MoveRotate::Id) ||
00137 AbstractPhysicsProperty::Accepts(msg);
00138 }
00139
00140
00143 void
00144 ActorPhysicsProperty::HandleMessage(Message::Msg* msg)
00145 {
00146 if (!this->IsEnabled())
00147 {
00148
00149 AbstractPhysicsProperty::HandleMessage(msg);
00150 }
00151 else if (msg->CheckId(MoveDirection::Id))
00152 {
00153 this->HandleMoveDirection((MoveDirection*) msg);
00154 }
00155 else if (msg->CheckId(MoveFollow::Id))
00156 {
00157 this->HandleMoveFollow((MoveFollow*) msg);
00158 }
00159 else if (msg->CheckId(MoveGoto::Id))
00160 {
00161 this->HandleMoveGoto((MoveGoto*) msg);
00162 }
00163 else if (msg->CheckId(MoveStop::Id))
00164 {
00165 this->Stop();
00166 }
00167 else if (msg->CheckId(SetTransform::Id))
00168 {
00169 this->HandleSetTransform((SetTransform*) msg);
00170 }
00171 else if (msg->CheckId(MoveTurn::Id))
00172 {
00173 this->HandleMoveTurn((MoveTurn*) msg);
00174 }
00175 else if (msg->CheckId(MoveRotate::Id))
00176 {
00177 this->HandleMoveRotate((MoveRotate*) msg);
00178 }
00179 else if (msg->CheckId(MoveSetVelocity::Id))
00180 {
00181 this->GetEntity()->SetFloat(Attr::RelVelocity, ((MoveSetVelocity*)msg)->GetRelVelocity());
00182 }
00183 else
00184 {
00185 AbstractPhysicsProperty::HandleMessage(msg);
00186 }
00187 }
00188
00189
00195 void
00196 ActorPhysicsProperty::OnMoveBefore()
00197 {
00198 this->HandlePendingMessages();
00199 if (this->IsEnabled())
00200 {
00201 if (this->IsGotoActive())
00202 {
00203 this->ContinueGoto();
00204 }
00205 if (this->GetEntity()->GetBool(Attr::Following))
00206 {
00207 this->ContinueFollow();
00208 }
00209 }
00210 }
00211
00212
00217 void
00218 ActorPhysicsProperty::OnMoveAfter()
00219 {
00220 if (this->IsEnabled())
00221 {
00222
00223 matrix44 physicsEntityTransform = this->charPhysicsEntity->GetTransform();
00224 vector3 physicsEntityVelocity = this->charPhysicsEntity->GetVelocity();
00225
00226
00227 polar2 headingAngles(-physicsEntityTransform.z_component());
00228 this->smoothedPosition.SetGoal(physicsEntityTransform.pos_component());
00229 this->smoothedHeading.SetGoal(headingAngles.rho);
00230
00231
00232 nTime time = TimeManager::Instance()->GetTime();
00233 this->smoothedPosition.Update(time);
00234 this->smoothedHeading.Update(time);
00235
00236
00237 matrix44 entityMatrix;
00238 entityMatrix.rotate_y(this->smoothedHeading.GetState());
00239 entityMatrix.translate(this->smoothedPosition.GetState());
00240
00241
00242 Ptr<Message::UpdateTransform> msg = Message::UpdateTransform::Create();
00243 msg->SetMatrix(entityMatrix);
00244 this->GetEntity()->SendSync(msg);
00245 this->GetEntity()->SetVector3(Attr::VelocityVector, physicsEntityVelocity);
00246 }
00247 }
00248
00249
00255 void
00256 ActorPhysicsProperty::SendStop()
00257 {
00258 Ptr<MoveStop> msg = MoveStop::Create();
00259 this->GetEntity()->SendSync(msg);
00260 }
00261
00262
00268 void
00269 ActorPhysicsProperty::Stop()
00270 {
00271 this->charPhysicsEntity->SetDesiredVelocity(vector3(0.0f, 0.0f, 0.0f));
00272 this->gotoPath = 0;
00273 this->GetEntity()->SetBool(Attr::Moving, false);
00274 this->GetEntity()->SetVector3(Attr::VelocityVector, vector3(0.0f, 0.0f, 0.0f));
00275 }
00276
00277
00281 void
00282 ActorPhysicsProperty::HandleMoveDirection(MoveDirection* msg)
00283 {
00284 n_assert(msg);
00285
00286 vector3 dir = msg->GetDirection();
00287
00288
00289 if (msg->GetCameraRelative())
00290 {
00291 Graphics::CameraEntity* camera = Graphics::Server::Instance()->GetCamera();
00292 n_assert(camera);
00293 matrix44 camTransform = camera->GetTransform();
00294 camTransform.pos_component().set(0.0f, 0.0f, 0.0f);
00295 dir = camTransform * dir;
00296 }
00297 dir.y = 0.0f;
00298 dir.norm();
00299
00300 vector3 desiredVelocity = dir * this->GetEntity()->GetFloat(Attr::RelVelocity) * this->GetEntity()->GetFloat(Attr::MaxVelocity);
00301 this->charPhysicsEntity->SetDesiredVelocity(desiredVelocity);
00302 this->charPhysicsEntity->SetDesiredLookat(dir);
00303 this->GetEntity()->SetBool(Attr::Moving, true);
00304 }
00305
00306
00310 void
00311 ActorPhysicsProperty::HandleMoveTurn(MoveTurn* msg)
00312 {
00313 n_assert(msg);
00314
00315 this->SendStop();
00316
00317 vector3 dir = msg->GetDirection();
00318 if (msg->GetCameraRelative())
00319 {
00320 Graphics::CameraEntity* camera = Graphics::Server::Instance()->GetCamera();
00321 n_assert(camera);
00322 matrix44 camTransform = camera->GetTransform();
00323 camTransform.pos_component().set(0.0f, 0.0f, 0.0f);
00324 dir = camTransform * dir;
00325 }
00326 dir.y = 0.0f;
00327 dir.norm();
00328 this->charPhysicsEntity->SetDesiredLookat(dir);
00329 }
00330
00331
00335 void
00336 ActorPhysicsProperty::HandleMoveRotate(MoveRotate* msg)
00337 {
00338 n_assert(msg);
00339
00340 float angle = msg->GetAngle();
00341 vector3 direction = this->charPhysicsEntity->GetDesiredLookat();
00342 direction.rotate(vector3(0.f, 1.f, 0.f), angle);
00343 this->charPhysicsEntity->SetDesiredLookat(direction);
00344 }
00345
00346
00350 void
00351 ActorPhysicsProperty::HandleMoveGoto(MoveGoto* msg)
00352 {
00353 n_assert(msg);
00354
00355
00356 const vector3& from = this->GetEntity()->GetMatrix44(Attr::Transform).pos_component();
00357 const vector3& to = msg->GetPosition();
00358 this->gotoPath = Navigation::Server::Instance()->MakePath(from, to);
00359 this->curGotoSegment = 0;
00360
00361 this->gotoTimeStamp = TimeManager::Instance()->GetTime();
00362 this->GetEntity()->SetBool(Attr::Moving, true);
00363 }
00364
00365
00369 void
00370 ActorPhysicsProperty::HandleSetTransform(SetTransform* msg)
00371 {
00372 n_assert(msg);
00373 this->charPhysicsEntity->SetTransform(msg->GetMatrix());
00374 }
00375
00376
00380 void
00381 ActorPhysicsProperty::HandleMoveFollow(MoveFollow* msg)
00382 {
00383 n_assert(msg);
00384 this->GetEntity()->SetInt(Attr::TargetEntityId, msg->GetTargetEntityId());
00385 Entity* targetEntity = EntityManager::Instance()->FindEntityById(this->GetEntity()->GetInt(Attr::TargetEntityId));
00386 if (targetEntity)
00387 {
00388 this->followTargetDist = msg->GetDistance();
00389 this->GetEntity()->SetBool(Attr::Following, true);
00390 }
00391 }
00392
00393
00397 void
00398 ActorPhysicsProperty::ContinueGoto()
00399 {
00400 n_assert(this->gotoPath.isvalid());
00401
00402 const vector3 curPos = this->GetEntity()->GetMatrix44(Attr::Transform).pos_component();
00403 vector3 targetVec = this->gotoPath->GetPoints()[this->curGotoSegment] - curPos;
00404 targetVec.y = 0.0f;
00405 float dist = targetVec.len();
00406
00407
00408 if (dist < (this->charPhysicsEntity->GetRadius() * 1.1f))
00409 {
00410
00411 if (this->curGotoSegment == this->gotoPath->CountSegments())
00412 {
00413 this->SendStop();
00414 }
00415 else
00416 {
00417
00418 this->curGotoSegment++;
00419 }
00420 }
00421 else
00422 {
00423
00424 Ptr<MoveDirection> msg = MoveDirection::Create();
00425 msg->SetDirection(targetVec);
00426 this->GetEntity()->SendSync(msg);
00427 }
00428 }
00429
00430
00434 void
00435 ActorPhysicsProperty::ContinueFollow()
00436 {
00437 n_assert(this->GetEntity()->GetBool(Attr::Following));
00438
00439 Game::Entity* targetEntity = EntityManager::Instance()->FindEntityById(this->GetEntity()->GetInt(Attr::TargetEntityId));
00440 if (0 == targetEntity)
00441 {
00442
00443 this->SendStop();
00444 return;
00445 }
00446
00447
00448 const vector3 targetPos = targetEntity->GetMatrix44(Attr::Transform).pos_component();
00449 const vector3 curPos = this->GetEntity()->GetMatrix44(Attr::Transform).pos_component();
00450 vector3 targetVec = targetPos - curPos;
00451 targetVec.y = 0.0f;
00452 float targetDist = targetVec.len();
00453
00454
00455 if (targetDist < this->followTargetDist)
00456 {
00457
00458 this->SendStop();
00459 this->charPhysicsEntity->SetDesiredLookat(targetVec);
00460 }
00461
00462
00463 if ((this->gotoTimeStamp + 1.0) < TimeManager::Instance()->GetTime())
00464 {
00465
00466 Ptr<MoveGoto> moveGoto = MoveGoto::Create();
00467 moveGoto->SetPosition(targetPos);
00468 this->HandleMoveGoto(moveGoto);
00469 }
00470 }
00471
00472
00475 Physics::Entity*
00476 ActorPhysicsProperty::GetPhysicsEntity() const
00477 {
00478 return this->charPhysicsEntity;
00479 }
00480
00481 };