Game Development Community

dev|Pro Game Development Curriculum

Basic Weapon Sway

by Bryce · 04/05/2010 (1:57 pm) · 22 comments

This resource will implement weapon sway in your project. An alternative to a motionless weapon image floating on your screen, weapon sway adds a bit more life to it. When the player turns, the weapon will move a bit in that direction, and when the player stops turning, the weapon creeps back to its original position. It adds a bit more of a natural feel if you ask me.


Issues:

1)Since the $mvPitch and $mvYaw values are updated too inconsistently to produce smooth sway, I have a function that gets these values once every 10th of a second. This most likely won't work networked.
2)Sometimes flickers. I only have this issue with Torque 3D. I'll look into it. EDIT: See comment #11 for the fix
3)Overall, this is an extremely hacky implementation of sway, just an FYI.

Implementation:

Open up T3D/player.h

In struct PlayerData: public ShapeBaseData {, under F32 minImpactSpeed;, add

// weapon sway
   F32 weaponSwayAmtX;
   F32 weaponSwayAmtZ;
   F32 weaponSwayResetX;
   F32 weaponSwayResetZ;

In class Player: public ShapeBase, under S32 mJumpDelay;, add

F32 mSwayX;
   F32 mSwayZ;
   F32 Yaw;
   F32 Pitch;

Open up T3D/player.cpp

In PlayerData::PlayerData(), under minImpactSpeed = 25.0f;, add

weaponSwayAmtX = 0.0005;
   weaponSwayAmtZ = 0.0005;
   weaponSwayResetX = 0.0005;
   weaponSwayResetZ = 0.0005;

In PlayerData::initPersistFields(), under addField("minImpactSpeed", TypeF32, Offset(minImpactSpeed, PlayerData));, add

addField("weaponSwayAmtX", TypeF32, Offset(weaponSwayAmtX, PlayerData));
	   addField("weaponSwayAmtZ", TypeF32, Offset(weaponSwayAmtZ, PlayerData));
	   addField("weaponSwayResetX", TypeF32, Offset(weaponSwayResetX, PlayerData));
	   addField("weaponSwayResetZ", TypeF32, Offset(weaponSwayResetZ, PlayerData));

Find stream->write(minImpactSpeed);, and under it, add

stream->write(weaponSwayAmtX);
   stream->write(weaponSwayAmtZ);
   stream->write(weaponSwayResetX);
   stream->write(weaponSwayResetZ);

Find stream->read(&minImpactSpeed);. Under it, add

stream->read(&weaponSwayAmtX);
   stream->read(&weaponSwayAmtZ);
   stream->read(&weaponSwayResetX);
   stream->read(&weaponSwayResetZ);

Find mReversePending = 0;, and under it, stick in

mSwayX = 0;
   mSwayZ = 0;

In Player::processTick(const Move* move), find updatePos();. Under it, add

// weapon sway
		  F32 amtX;
		  F32 amtZ;
		  F32 resetX;
		  F32 resetZ;
		  F32 limitX;
		  F32 limitZ;
		  amtX = mDataBlock->weaponSwayAmtX;
		  amtZ = mDataBlock->weaponSwayAmtZ;
		  resetX = mDataBlock->weaponSwayResetX;
		  resetZ = mDataBlock->weaponSwayResetZ;
		  limitX = 0.02 * 0.2;
		  limitZ = 0.02 * 0.2;
		  if (Yaw > 0 && Yaw != 0 && mSwayX < limitX)
			  mSwayX += amtX;
		  if (Yaw < 0 && Yaw != 0 && mSwayX > -limitX)
			  mSwayX -= amtX;
		  // Yaw sway
		  if (Yaw == 0)
		  {
			  if (mSwayX < 0)
				  mSwayX += resetX;
			  if (mSwayX > 0)
				  mSwayX -= resetX;
		  }
		  // Now do pitch sway
		  if (Pitch > 0 && Pitch != 0 && mSwayZ < limitZ)
			  mSwayZ += amtZ;
		  if (Pitch < 0 && Pitch != 0 && mSwayZ > -limitZ)
			  mSwayZ -= amtZ;
		  if (Pitch == 0)
		  {
			  if (mSwayZ < 0)
				  mSwayZ += resetZ;
			  if (mSwayZ > 0)
				  mSwayZ -= resetZ;
		  }

In Player::RenderMountedImage, under world.mul(nmat,offsetMat);, add

GameConnection* con = getControllingClient();
		  Yaw = Con::getFloatVariable("$swayYaw");
		  Pitch = Con::getFloatVariable("$swayPitch");
		  if (con->isAIControlled())
		  {
			  mSwayX = 0;
			  mSwayZ = 0;
		  }
	  	 Point3F swayDisplace;
		 swayDisplace.x = mSwayX;
                 swayDisplace.y = 0.0f;
		 swayDisplace.z = mSwayZ;

In this same block, locate world.setPosition( world.getPosition() + displace);, and change it to

world.setPosition( world.getPosition() + displace + swayDisplace);

That's it for engine changes. Compile, good luck. You should get a lot of warnings about “truncation from 'double' to 'F32'” with Visual C++. I'm not exactly sure what causes it, I don't do a lot of T3D engine coding. Anyone care to shine some light on this?

Anyway. Scripts. Open game/scripts/client/default.bind.cs, and locate
function panDown( %val )
{
   $mvPitchUpSpeed = %val ? $Pref::Input::KeyboardTurnSpeed : 0;
}

Underneath it, add
function getTurnValues()
{
	$gettingTurnValues = true;
	$swayYaw = $mvYaw;
	$swayPitch = $mvPitch;
	schedule(100,0,getTurnValues);
}

Now, find
function getMouseAdjustAmount(%val)
{	    
   // based on a default camera FOV of 90'
   return(%val * ($cameraFov / 90) * 0.01) * $pref::Input::LinkMouseSensitivity;
}

Change it to
function getMouseAdjustAmount(%val)
{
	if (!$gettingTurnValues)
	  getTurnValues();
	    
   // based on a default camera FOV of 90'
   return(%val * ($cameraFov / 90) * 0.01) * $pref::Input::LinkMouseSensitivity;
}

Now, open up art/datablocks/player.cs, go to the DefaultPlayerData datablock, and add in
// Weapon sway
   weaponSwayAmtX = 0.0012;
   weaponSwayAmtZ = 0.0012;
   weaponSwayResetX = 0.0010;
   weaponSwayResetZ = 0.0010;

Do this for your other player datablocks if you have them.

Go into your game, and give it a try! Good luck, and happy Torque'ing!
Page«First 1 2 Next»
#21
08/07/2010 (3:16 am)
Alright, thank you, I will try this as soon as I get the chance.
#22
12/27/2011 (11:33 am)
Fun fact: This actually does work networked. How 'bout them apples!
Page«First 1 2 Next»