Game Development Community

OnFire Projectile Vector Adjustment

by James Laker (BurNinG) · in Torque Game Engine · 05/07/2008 (1:52 am) · 9 replies

For 3rd person titles the camera will rarely hit the object under the cursor.

One way of getting around this is to adjust the muzzlevector of the gun firing. This shouldn't be noticably visible in an action game.

So here's what I'm trying to do with the onFire method:
1) Do a rayscan from the CameraVector and see if we find anything worth shooting.
2) Adjust the projectile firing Vector to shoot in the direction where the target/object was found.

Here's
// Get the vector. Since Solar Battles is more a 3rd Person shooter, we use the Camera Vector
   %muzzleVector = %obj.getMuzzleVector(%slot);
      
	// Determin initial projectile velocity based on the
	// gun's muzzle point and the object's current velocity
	%muzzleVector = %obj.getMuzzleVector(%slot);
	%objectVelocity = %obj.getVelocity();
	%muzzleVelocity = VectorAdd(	VectorScale(%muzzleVector, %projectile.muzzleVelocity),
     							 	VectorScale(%objectVelocity, %projectile.velInheritFactor));

   //Do a rayscan to see if we need to adjust our muzzle for better accuracy
   if (!isObject(%obj.client.camera))
   {
      %eyeVector = %obj.getEyeVector();
      %eyePoint = %obj.getEyePoint();
   }
   else
   {
      %eyeVector = %obj.client.camera.getEyeVector();
      %eyePoint = %obj.client.camera.getEyePoint();
   }

   // scale eye vector to the range the player is able to fire
   %eyeScaled = VectorScale(%eyeVector, 10000);

   // targetpoint = eye point + length of selectable range
   %targetPoint = VectorAdd(%eyePoint, %eyeScaled);
   
   // Everything mask
   %mask = $TypeMasks::StaticObjectType|$TypeMasks::StaticShapeObjectType|$TypeMasks::InteriorObjectType|$TypeMasks::ShapeBaseObjectType;
   
   %scanTarg = ContainerRayCast (%eyePoint, %targetPoint, %mask, %obj);
   
   if (%scanTarg) {
    %targetPoint = getWords(%scanTarg,1,3);
   }
   
   //Make sure we fire in the correct direction
    %muzzleVelocity = VectorAdd(%targetPoint, %muzzleVelocity);

	// Create the projectile object
	%p = new (%this.projectileType)() {
		dataBlock        = %projectile;
		initialVelocity  = %muzzleVelocity;
		initialPosition  = %obj.getMuzzlePoint(%slot);
		sourceObject     = %obj;
		sourceSlot       = %slot;
		client           = %obj.client;
	};
	MissionCleanup.add(%p);
	return %p;

So this is what I currently have, but I'm doing something wrong. It's not firing in the correct direction. So I'm not doing point 2 correctly I guess. Can someone please help.

Thank you

#1
05/07/2008 (6:50 am)
The Raycast returns an ID, not a position.
Use %scanTarg.GetPosition().
#2
05/07/2008 (7:04 am)
Of course... doh... Will test it. Does my other calculations look right though?
#3
05/07/2008 (7:12 am)
For some reason it never finds anything in my RayCast. I'm trying to do a Rayscan from the Camera's eyepoint... So this should be the middle of the screen or am I wrong?
#4
05/07/2008 (7:35 am)
//where in game.cs:
// %player = new Player(PLAYER_OBJECT) {
// dataBlock = LightMaleHumanArmor;
// client = %this;
// };



%start = PLAYER_OBJECT.getEyePoint();
%end = VectorAdd(%start,VectorScale(PLAYER_OBJECT.getEyeVector(),10000));

%found = containerRayCast(%start,%end,%mask, PLAYER_OBJECT);
#5
05/07/2008 (7:50 am)
The problem is that I need to do a RayCast from the Player's Camera in the direction the Camera is looking, not the Player Object/model. This should allow me to adjust the InitialVelocity to fire in the direction where the Camera is looking. The reason I'm doing the RayCast is to see if there is anything where the crosshair is and adjust the Velocity depending on the distance of the object under the crosshair.

If you have tried shooting at and hitting something in 3rd person view, it becomes obvious that the way it is now is not usefull for 3rd person games.

EDIT: Just tested it again... using the Obj I have to aim above the target to actually hit it. This is why I need to use the Camera.
#6
05/07/2008 (9:28 am)
Are you trying to do some kind of Third person camera like GOW (where the player fires at the same direction as the camera )? If I understand what you are trying to do, I don't think you need to ray cast at all.

What you need to do

1. set your camera at your desire offset behind the player sample ( Point3F offset ( 0.5 , -1.5 , 2 ) ) //offset is compared to the player position
2. set your camera to look at a certain offset sample ( Point3F lookat ( 0.5 , 0 , 2 ) ) //offset is compared to the player position
3. rotate the camera using the player's head rotation

thats the ideal of it. You could only do this within the engine , can't think of anyway to do it from script.

Aun.
#7
05/07/2008 (10:11 am)
James, the code is good.
My start point is the EYE position (as you can see), the end point is the EYE's direction.
I understood quite well the problem.
#8
05/08/2008 (1:06 am)
@Aun - Not nessesarily GOW... I'm talking ANY 3rd person shooter. A player sitting at his desk looking at the screen wants to shoot where the Camera is Aiming using his/her crosshair. At the moment in Torque you shoot straight from the Gun's Muzzlepoint, and that does not work in a 3rd person camera.

To see the problem I'm describing, you'll need to change the Crosshair to actually see the crosshair in 3rd person cam - Search the forums how to do this. Then open up the Stronghold demo, go to the 3rd person cam. Put your Crosshair on any Target. Now Fire... You'll notice that the projectile doesn't hit exactly where you were aiming. I guess this is probably why the crosshair is removed when not in Firstperson mode.

So to fix this we just need to slighty adjust the direction (vector). This is unnoticable, but you'll actually be able to hit the target - If they're standing still. To hit them while they are moving I will have to add in the Velocity and Direction.

@Picasso - Thank you.

The problem is that %obj.client.camera.getEyePoint(); returns the Eye Node of the DTS its connected to. So what I had to create new Console functions (in ShapeBase.cpp) to return the Cam Node in the (dts) Shape:
ConsoleMethod( ShapeBase, getCamVector, const char*, 2, 2, "")
{
   MatrixF mat;
	F32 pos;
	object->getCameraTransform(&pos,&mat);
   VectorF v2;
   mat.getColumn(1,&v2);
   char* buff = Con::getReturnBuffer(100);
   dSprintf(buff, 100,"%g %g %g",v2.x,v2.y,v2.z);
   return buff;
}

ConsoleMethod( ShapeBase, getCamPoint, const char*, 2, 2, "")
{
   MatrixF mat;
	F32 pos;
   object->getCameraTransform(&pos,&mat);
   Point3F ep;
   mat.getColumn(3,&ep);
   char* buff = Con::getReturnBuffer(100);
   dSprintf(buff, 100,"%g %g %g",ep.x,ep.y,ep.z);
   return buff;
}

Will post my results after some thorough play testing.
#9
05/14/2008 (4:15 pm)
James, have you any results? Additionally, would you please post your working onFire script?

I already added your new code and tried to set this up and failed miserably.

Thanks.