[Orxonox-commit 5397] r10060 - in code/branches/turretFS14: data/levels src/modules/objects src/modules/objects/controllers src/orxonox/worldentities
muemart at orxonox.net
muemart at orxonox.net
Thu May 15 17:10:55 CEST 2014
Author: muemart
Date: 2014-05-15 17:10:55 +0200 (Thu, 15 May 2014)
New Revision: 10060
Modified:
code/branches/turretFS14/data/levels/turretTest.oxw
code/branches/turretFS14/src/modules/objects/Turret.cc
code/branches/turretFS14/src/modules/objects/Turret.h
code/branches/turretFS14/src/modules/objects/controllers/TeamTargetProxy.cc
code/branches/turretFS14/src/modules/objects/controllers/TeamTargetProxy.h
code/branches/turretFS14/src/modules/objects/controllers/TurretController.cc
code/branches/turretFS14/src/modules/objects/controllers/TurretController.h
code/branches/turretFS14/src/orxonox/worldentities/WorldEntity.cc
Log:
Fix team acquisition, edit test level and start to try to make a raytest
Modified: code/branches/turretFS14/data/levels/turretTest.oxw
===================================================================
--- code/branches/turretFS14/data/levels/turretTest.oxw 2014-05-15 15:09:35 UTC (rev 10059)
+++ code/branches/turretFS14/data/levels/turretTest.oxw 2014-05-15 15:10:55 UTC (rev 10060)
@@ -2,7 +2,7 @@
<LevelInfo
name = "turret Test"
- description = "A level with a turret in it."
+ description = "A level to test turrets with."
tags = "test"
screenshot = "emptylevel.png"
/>
@@ -15,7 +15,6 @@
<?lua
include("templates/spaceshipAssff.oxt")
- include("templates/spaceshipTransporter.oxt")
include("templates/standardTurret.oxt")
?>
@@ -32,34 +31,57 @@
<Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
<SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
-<SpaceShip>
+<SpaceShip position = "0,0,800" collisionType="dynamic" team=10>
+ <controller>
+ <TeamTargetProxy team=10/>
+ </controller>
<attached>
- <Turret position="10,2,0" pitch="90" yaw="0" roll="0" scale3D="0.2,0.2,0.2">
- <templates>
- <Template link=standardturret />
- </templates>
- </Turret>
- <Turret position="-10,2,0" pitch="90" yaw="0" roll="0" scale3D="0.2,0.2,0.2">
- <templates>
- <Template link=standardturret />
- </templates>
- </Turret>
- <Turret position="0,2,0" pitch="90" yaw="0" roll="0" scale3D="0.2,0.2,0.2">
- <templates>
- <Template link=standardturret />
- </templates>
- </Turret>
+ <Model position="0,0,0" mesh="plane.mesh" scale3D="20,20,20" pitch=-90/>
+
+ <?lua for i = 1, 10, 1 do ?>
+ <Turret position="<?lua print(150-i*30) ?>,<?lua print(150-i*30) ?>,0" pitch="0" yaw="0" roll="0">
+ <templates>
+ <Template link=standardturret />
+ </templates>
+ </Turret>
+ <?lua end ?>
+
</attached>
- <templates>
- <Template link=spaceshipassff />
- </templates>
-<!-- <controller>
- <AIController />
- </controller> -->
+ <collisionShapes>
+ <BoxCollisionShape radius="10" position="0,0,0" halfExtents="200, 200, 0"/>
+ </collisionShapes>
</SpaceShip>
+<Turret collisionType="dynamic" pitch=90 position="30,0,0">
+ <attached>
+ <Model position="0,0,0" mesh="turretSocketFront.mesh" scale3D="10,10,10" pitch=-90/>
+ <Model position="0,0,0" mesh="turretSocketIn.mesh" scale3D="10,10,10" pitch=-90/>
+ <Model position="0,0,0" mesh="turretSocketTop.mesh" scale3D="10,10,10" pitch=-90/>
+ <Model position="0,0,0" mesh="turretSocketLeft.mesh" scale3D="10,10,10" pitch=-90/>
+ <Model position="0,0,0" mesh="turretSocketRight.mesh" scale3D="10,10,10" pitch=-90/>
+ <Turret position="0,0,-10" collisionType="dynamic" pitch=20 angularDamping=0.999999 mass=100 maxPitch=45 maxYaw=45 maxAttackRadius=2000 minAttackRadius=30>
+ <attached>
+ <Model position="0,0,0" pitch="-90" roll="0" mesh="turretHead.mesh" scale3D="10,10,10"/>
+ </attached>
+ <collisionShapes>
+ <SphereCollisionShape radius="10" position = "0,0,0"/>
+ </collisionShapes>
+ <controller>
+ <TurretController/>
+ </controller>
+ <?lua
+ include("includes/weaponSettingsTurret.oxi")
+ ?>
+ </Turret>
+ </attached>
+ <controller>
+ <TeamTargetProxy team=10/>
+ </controller>
+ </Turret>
+
+
</Scene>
</Level>
Modified: code/branches/turretFS14/src/modules/objects/Turret.cc
===================================================================
--- code/branches/turretFS14/src/modules/objects/Turret.cc 2014-05-15 15:09:35 UTC (rev 10059)
+++ code/branches/turretFS14/src/modules/objects/Turret.cc 2014-05-15 15:10:55 UTC (rev 10060)
@@ -29,7 +29,10 @@
#include "Turret.h"
#include "core/CoreIncludes.h"
#include "core/XMLPort.h"
+#include "Scene.h"
+#include <OgreSceneQuery.h>
+
namespace orxonox
{
RegisterClass(Turret);
@@ -72,22 +75,25 @@
/**
@brief
- Checks, if a (world)position is inside the turret's range.
+ Checks, if a WorldEntity is inside the turret's range.
This function is safe to use on turrets that are attached, rotated, etc.
- The turret's range is determined with the maxPitch, maxYaw, and the two attackRadius'.
+ The turret's range is determined with the maxPitch, maxYaw, and the two attackRadius.
- @param position
- The position to check
+ @param target
+ The WorldEntity to check
+
+ @return
+ The squared distance to the position. -1, if it's ouside of range
*/
- bool Turret::isInRange(const Vector3 &position)
+ float Turret::isInRange(const WorldEntity* target ) const
{
//Check distance
- Vector3 distance = position - this->getWorldPosition();
+ Vector3 distance = target->getWorldPosition() - this->getWorldPosition();
float distanceVal = distance.squaredLength();
if(distanceVal > (this->maxAttackRadius_ * this->maxAttackRadius_) || distanceVal < (this->minAttackRadius_ * this->minAttackRadius_))
{
- return false;
+ return -1.f;
}
//Check pitch
@@ -99,7 +105,7 @@
Ogre::Real angle = startDirProjected.angleBetween(dirProjected).valueDegrees();
if(angle > this->maxPitch_)
{
- return false;
+ return -1.f;
}
//Check yaw
@@ -110,9 +116,15 @@
angle = startDirProjected.angleBetween(dirProjected).valueDegrees();
if(angle > this->maxYaw_)
{
- return false;
+ return -1.f;
}
- return true;
+
+ Ogre::SceneManager* scenemanager = this->getScene()->getSceneManager();
+ Ogre::Ray ray = Ogre::Ray(this->getWorldPosition(), distance);
+ Ogre::DefaultRaySceneQuery rayscenequery = Ogre::DefaultRaySceneQuery(scenemanager);
+ rayscenequery.setRay(ray);
+
+ return distanceVal;
}
/**
@@ -214,12 +226,15 @@
The turret's actions are done here.
Every tick, the turret gets rotated if it should, and the local axes get updated with the parent's rotation.
+
+ @param dt
+ Duration of the tick
*/
void Turret::tick(float dt)
{
SUPER(Turret, tick, dt);
-
+ //Stuff isn't properly initialized in the c'tor, so we have to do it like this
if(!this->once_)
{
//Account for rotations done in xml
@@ -255,6 +270,8 @@
if(this->rotation_ != Quaternion::IDENTITY)
{
//Don't make the rotation instantaneous. Use an arbitrary interpolation, not that great...
+ //TODO: make the rotation better (constant velocity etc.). At the moment, the turret rotates
+ // slower the closer it is to the destination
Quaternion drot = Quaternion::nlerp(dt*this->rotationThrust_/20.f, Quaternion::IDENTITY, this->rotation_);
this->rotate(drot, WorldEntity::World);
this->rotation_ = Quaternion::IDENTITY;
Modified: code/branches/turretFS14/src/modules/objects/Turret.h
===================================================================
--- code/branches/turretFS14/src/modules/objects/Turret.h 2014-05-15 15:09:35 UTC (rev 10059)
+++ code/branches/turretFS14/src/modules/objects/Turret.h 2014-05-15 15:10:55 UTC (rev 10060)
@@ -45,6 +45,11 @@
a turret to a spaceship or a spacestation which is more or less completely autonomous in
it's behaviour.
+ This class also contains a custom local coordinate system, which gets initially rotated through xml, and
+ afterwards is updated with the parent's rotation (if there is one). This allows for almost trivialal calculation
+ of pitch, yaw and roll through coordinate transformation. (TODO: Ogre should do something like this already, investigate...)
+
+
@note
The rotation isn't limited "physically". You have to call isInRange to find out if the turret is allowed to shoot at a target.
*/
@@ -57,7 +62,7 @@
virtual void rotatePitch(const Vector2& value);
virtual void rotateYaw(const Vector2& value);
virtual void rotateRoll(const Vector2& value);
- virtual bool isInRange(const Vector3 &position);
+ virtual float isInRange(const WorldEntity* target) const;
virtual void aimAtPosition(const Vector3 &position);
virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
Modified: code/branches/turretFS14/src/modules/objects/controllers/TeamTargetProxy.cc
===================================================================
--- code/branches/turretFS14/src/modules/objects/controllers/TeamTargetProxy.cc 2014-05-15 15:09:35 UTC (rev 10059)
+++ code/branches/turretFS14/src/modules/objects/controllers/TeamTargetProxy.cc 2014-05-15 15:10:55 UTC (rev 10060)
@@ -27,54 +27,73 @@
*/
#include "TeamTargetProxy.h"
+#include "worldentities/ControllableEntity.h"
#include "worldentities/pawns/Pawn.h"
- namespace orxonox
- {
- RegisterClass(TeamTargetProxy);
+namespace orxonox
+{
+ RegisterClass(TeamTargetProxy);
- TeamTargetProxy::TeamTargetProxy(Context* context) : FormationController(context)
+ /**
+ @brief
+ Sets default values for all variables.
+
+ @param context
+ The context
+ */
+ TeamTargetProxy::TeamTargetProxy(Context* context) : FormationController(context)
{
RegisterObject(TeamTargetProxy);
this->once_ = false;
}
+ /**
+ @brief
+ Destructor. Nothing to see here.
+ */
TeamTargetProxy::~TeamTargetProxy()
{
}
+ /**
+ @brief
+ Copies the team and the target from the parent.
+
+ That's all there is.
+ */
void TeamTargetProxy::tick(float dt)
{
if (!this->isActive() || !this->getControllableEntity())
return;
ControllableEntity* parent = orxonox_cast<ControllableEntity*> (this->getControllableEntity()->getParent());
-
+ if(this->getTeam() != -1 && !this->once_ && parent)
+ {
+ orxout(internal_warning) << "TeamTargetProxy: Team already set, may result in undesired behaviour. Will get overridden by the parent's team." << endl;
+ }
+ if(!this->once_)
+ this->once_ = true;
+
+ //Teams aren't set immediately, after creation, so we have to check every tick...
if(parent)
{
-
- if(!this->once_)
+ Controller* parentcontroller = parent->getController();
+ if(parentcontroller)
{
- //Set the same team
- if(parent)
- {
- Controller* parentcontroller = parent->getController();
- if(parentcontroller)
- {
- this->setTeam(parentcontroller->getTeam());
- }
- else
- {
- this->setTeam(parent->getTeam());
- }
- this->getControllableEntity()->setTeam(parent->getTeam());
- }
- this->once_ = true;
+ this->setTeam(parentcontroller->getTeam());
}
+ else
+ {
+ this->setTeam(parent->getTeam());
+ }
+ this->getControllableEntity()->setTeam(parent->getTeam());
+ }
+ if(parent)
+ {
Pawn* parenttarget = orxonox_cast<Pawn*>(parent->getTarget());
if(parenttarget)
{
@@ -82,6 +101,5 @@
this->getControllableEntity()->setTarget(parenttarget);
}
}
-
}
- }
\ No newline at end of file
+}
\ No newline at end of file
Modified: code/branches/turretFS14/src/modules/objects/controllers/TeamTargetProxy.h
===================================================================
--- code/branches/turretFS14/src/modules/objects/controllers/TeamTargetProxy.h 2014-05-15 15:09:35 UTC (rev 10059)
+++ code/branches/turretFS14/src/modules/objects/controllers/TeamTargetProxy.h 2014-05-15 15:10:55 UTC (rev 10060)
@@ -34,6 +34,16 @@
namespace orxonox
{
+ /**
+ @brief
+ A controller, that just copies the team and the target of a parent for itself and it's controllable entity.
+
+ Useful for following (and similar) situations: (-> means attached to)
+ turret (rotates) -> some kind of turret base (looks nice) -> spaceship (flies around)
+ The turret has a controller that wants to copy the spaceship's target and team. In this case it doesn't work though,
+ because the turret isn't directly attached to the spaceship. Here's where this controller comes in. Drawback: the base
+ has to be controllable and ticks every second (performance?)
+ */
class _OrxonoxExport TeamTargetProxy : public FormationController, public Tickable
{
public:
@@ -43,7 +53,7 @@
virtual void tick(float dt);
private:
- bool once_;
+ bool once_; //!< Flag for executing code in the tick function only once.
};
}
Modified: code/branches/turretFS14/src/modules/objects/controllers/TurretController.cc
===================================================================
--- code/branches/turretFS14/src/modules/objects/controllers/TurretController.cc 2014-05-15 15:09:35 UTC (rev 10059)
+++ code/branches/turretFS14/src/modules/objects/controllers/TurretController.cc 2014-05-15 15:10:55 UTC (rev 10060)
@@ -34,6 +34,13 @@
{
RegisterClass(TurretController);
+ /**
+ @brief
+ Sets default values for all variables.
+
+ @param context
+ The context
+ */
TurretController::TurretController(Context* context) : ArtificialController(context)
{
RegisterObject(TurretController);
@@ -42,15 +49,31 @@
}
+ /**
+ @brief
+ Destructor. Nothing to see here.
+ */
TurretController::~TurretController()
{
}
+ /**
+ @brief
+ Searches a valid target for the turret to aim at.
+
+ Loops through all pawns and tests, if it is in range. Scores every pawn and chooses the best one (the one with the lowest score).
+ If the turret has a parent, try to aim at the same target the parent has, if there is one.
+
+ @see targetScore
+ The function that scores the pawns.
+ */
void TurretController::searchTarget()
{
Turret* turret = orxonox_cast<Turret*>(this->getControllableEntity());
- if(target_ && turret->isInRange(target_->getWorldPosition()))
+
+ //The controller might find a target before teams are set, so we need to check again here.
+ if(this->target_ && turret->isInRange(target_) != -1.f && !FormationController::sameTeam(turret, this->target_, this->getGametype()))
{
return;
}
@@ -65,7 +88,7 @@
if(parent)
{
Pawn* parenttarget = orxonox_cast<Pawn*>(parent->getTarget());
- if(parenttarget && turret->isInRange(parenttarget->getWorldPosition()))
+ if(parenttarget && turret->isInRange(parenttarget))
{
this->setTarget(parenttarget);
turret->setTarget(parenttarget);
@@ -73,61 +96,99 @@
}
}
- for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it != ObjectList<Pawn>::end(); ++it)
+ float maxScore = 0;
+ float tempScore;
+ Pawn* maxScorePawn = 0;
+
+ for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it != ObjectList<Pawn>::end(); ++it)
{
Pawn* entity = orxonox_cast<Pawn*>(*it);
- if (this->FormationController::sameTeam(this->getControllableEntity(), entity, this->getGametype()))
+ if (!entity || FormationController::sameTeam(this->getControllableEntity(), entity, this->getGametype()))
continue;
-
- if(turret->isInRange(entity->getWorldPosition()))
+ tempScore = turret->isInRange(entity);
+ if(tempScore != -1.f)
{
- this->setTarget(entity);
- turret->setTarget(entity);
- break;
+ if(tempScore > maxScore)
+ {
+ maxScore = tempScore;
+ maxScorePawn = entity;
+ }
}
- }
+ }
+ this->setTarget(maxScorePawn);
+ turret->setTarget(maxScorePawn);
}
+ /**
+ @brief
+ Tests, if the turret is looking at the target, with a specified tolerance
+
+ This uses the world position as opposed to the local position in the old version.
+
+ @param angle
+ The tolerance, in radians
+ */
bool TurretController::isLookingAtTargetNew(float angle) const
{
return (getAngle(this->getControllableEntity()->getWorldPosition(), this->getControllableEntity()->getWorldOrientation() * WorldEntity::FRONT, this->target_->getWorldPosition()) < angle);
}
+ /**
+ @brief
+ Scores a pawn as a target, based on distance and health.
+
+ The more health and distance a pawn has, the higher the score. This means lower equals better target.
+
+ @param pawn
+ The pawn to score
+
+ @param distance
+ The distance. Can be squared or normed, doesn't matter as long as all are treated the same.
+ */
+ float TurretController::targetScore(Pawn* pawn, float distance) const
+ {
+ return pawn->getHealth()/pawn->getMaxHealth() + distance;
+ }
+
+ /**
+ @brief
+ Does all the controlling of the turret.
+
+ If the turret has a parent, copies the team from there, if it's not already set.
+ Other actions are: Search a target. If a target has been found, aim and shoot at it.
+ */
void TurretController::tick(float dt)
{
if (!this->isActive() || !this->getControllableEntity())
return;
- if(!this->once_)
- {
- if(this->getTeam() != -1)
- {
- orxout(internal_warning) << "Turret: Team already set, may result in undesired behaviour" << endl;
- }
- else
- {
- //Make sure the turret is in the same team as the parent
- ControllableEntity* parent = orxonox_cast<ControllableEntity*> (this->getControllableEntity()->getParent());
- if(parent)
- {
- Controller* parentcontroller = parent->getController();
- if(parentcontroller)
- {
- this->setTeam(parentcontroller->getTeam());
- }
- else
- {
- this->setTeam(parent->getTeam());
- }
- this->getControllableEntity()->setTeam(parent->getTeam());
- }
- }
- this->once_ = true;
+ ControllableEntity* parent = orxonox_cast<ControllableEntity*> (this->getControllableEntity()->getParent());
+ if(this->getTeam() != -1 && !this->once_ && parent)
+ {
+ orxout(internal_warning) << "TurretController: Team already set, may result in undesired behaviour. Will get overridden by the parent's team." << endl;
}
+ if(!this->once_)
+ this->once_ = true;
+
+ //Teams aren't set immediately, after creation, so we have to check every tick...
+ if(parent)
+ {
+ Controller* parentcontroller = parent->getController();
+ if(parentcontroller)
+ {
+ this->setTeam(parentcontroller->getTeam());
+ }
+ else
+ {
+ this->setTeam(parent->getTeam());
+ }
+ this->getControllableEntity()->setTeam(parent->getTeam());
+ }
+
this->searchTarget();
- if(target_)
+ if(this->target_)
{
Turret* turret = orxonox_cast<Turret*> (this->getControllableEntity());
this->aimAtTarget();
Modified: code/branches/turretFS14/src/modules/objects/controllers/TurretController.h
===================================================================
--- code/branches/turretFS14/src/modules/objects/controllers/TurretController.h 2014-05-15 15:09:35 UTC (rev 10059)
+++ code/branches/turretFS14/src/modules/objects/controllers/TurretController.h 2014-05-15 15:10:55 UTC (rev 10060)
@@ -56,8 +56,9 @@
void searchTarget();
bool isLookingAtTargetNew(float angle) const;
+ float targetScore(Pawn* pawn, float distance) const;
- bool once_;
+ bool once_; //!< Flag for executing code in the tick function only once.
};
}
Modified: code/branches/turretFS14/src/orxonox/worldentities/WorldEntity.cc
===================================================================
--- code/branches/turretFS14/src/orxonox/worldentities/WorldEntity.cc 2014-05-15 15:09:35 UTC (rev 10059)
+++ code/branches/turretFS14/src/orxonox/worldentities/WorldEntity.cc 2014-05-15 15:10:55 UTC (rev 10060)
@@ -413,7 +413,7 @@
}
else if (this->isDynamic())
{
- //hacky hack, really shouldn't do that
+ //***HACKY HACK (to allow turrets to be attached)***
//orxout(internal_warning) << "Cannot attach a dynamic object to a WorldEntity." << endl;
//return false;
}
More information about the Orxonox-commit
mailing list