Game Development Community

dev|Pro Game Development Curriculum

Projectile Spread

by Derk Adams · 08/17/2006 (11:58 am) · 3 comments

Download Code File

Purpose:
I came to a point where I wanted to add variability to the weapon firing based on range. A simple server-side addition randomly selects the trajectory based on a cone from the player's eye.

Discussion:
This system projects a circle along the player's view to the maximum range of the weapon. It randomly selects an offset from center and a direction from center. This is then scaled to the eye vector and normalized for projectile use.

Comments:
There are many ways to determine the diameter of the circle, whether it be constant, as in my example, or based on the players speed or position.

I have shown it as an extension of the weapon object, but it can easily be made into a function that is called by all weapons.

Development Environment:
August 2006
Head 1.4
Win32
Single and Multi Player

Implementation:
ScriptFile: /server/scripts/crossbow.cs
function CrossbowImage::onFire(%this, %obj, %slot)
{
   %projectile = %this.projectile;

   // Decrement inventory ammo. The image's ammo state is update
   // automatically by the ammo inventory hooks.
   %obj.decInventory(%this.ammo,1);

   // Determine initial projectile velocity based on the 
   // gun's muzzle point and the object's current velocity
   %muzzleVector = %obj.getMuzzleVector(%slot);

//------- Projectile Spread -------
  // These two variables can come from the datablock, a player function, or both, or static values.
  %maxRange = 200; // game units
  %spread = 4; // radius of circle at max range in game units (this decreases as the target is closer)

  %randDist = getRandom(0,%spread*1000) / 1000; // random distance from center
  %randDir = getRandom(0,62831) / 1000; // random direction on circle
  %rvar = mSin(%randDir) * %randDist; // horizontal distance from center
  %uvar = mCos(%randDir) * %randDist; // vertical distance from center
  
  %muzzleTransform = %obj.getSlotTransform(%slot);
  %aa = getWords(%muzzleTransform, 3, 6);
  %tmat = VectorOrthoBasis(%aa);
  %rv = getWords(%tmat, 0, 2); // Right Vector
  %fv = getWords(%tmat, 3, 5); // Forward Vector
  %uv = getWords(%tmat, 6, 8); // Up Vector

  %roffset = VectorScale(%rv, %rvar); // scale horizontal vector by horizontal distance
  %uoffset = VectorScale(%uv, %uvar); // scale vertical vector by vertical distance

  // Combine for final vector
  %muzzleVector = VectorScale(%muzzleVector, %maxRange);
  %muzzleVector = VectorAdd(%muzzleVector, %roffset);
  %muzzleVector = VectorAdd(%muzzleVector, %uoffset);
  %muzzleVector = VectorNormalize(%muzzleVector);
//----- End Projectile Spread -----

   %objectVelocity = %obj.getVelocity();
   %muzzleVelocity = VectorAdd(
      VectorScale(%muzzleVector, %projectile.muzzleVelocity),
      VectorScale(%objectVelocity, %projectile.velInheritFactor));

   // 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;
}

#1
08/17/2006 (9:29 pm)
I have been looking for something like this. Thankyou!
#2
08/19/2006 (12:30 am)
very nice. Derk Adams, thank you.
#3
11/23/2008 (12:38 am)
5-Star Rating,
Extremely Easy Drag and Drop Code.
Thank You, Derk!