[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