TorqueX/PlatformerFrameworkShooter
From TDN
Contents |
Introduction
The platformer starter kit is great, but what if you wanted to add shooting to it? Now you can!
Please note that this is still a W.I.P.
Materials Needed
You will need the following to complete this tutorial:
- Visual C# Express
- XNA
- Torque X
- Platformer Starter Kit
- A new project started using the Platformer Demo
- A crosshair :

Adding Shooting
- 1. Once you have created a new Platformer Starter Kit project open up the project file in Torque X Builder.
- 2. Add a new sprite called ProjectileTemplate and make sure Template and Pool with components is checked.
- 3. Add a new object called "aimer" (without quotes)
- 4. Add the newly created object, "aimer", to the dragon that is by default already added into the scene.
- 5 Add a new object called "gun" and mount it to the "aimer"
- 6. Open up the project in Visual C# Express and open the "PlayerController.cs" file.
- 7. In the Private, protected, internal methods region add the following code after protected void _SetupInputMap()
protected void _Fire()
{
T2DSceneObject gun = TorqueObjectDatabase.Instance.FindObject<T2DSceneObject>("Gun");
T2DSceneObject player = TorqueObjectDatabase.Instance.FindObject<T2DSceneObject>("Player");
T2DSceneObject projectileObj = TorqueObjectDatabase.Instance.CloneObject<T2DSceneObject>("ProjectileTemplate");
T2DSceneObject aimer = TorqueObjectDatabase.Instance.FindObject<T2DSceneObject>("Aimer");
projectileObj.Position = gun.Position; // Set the "bullet" to "spawn" from where the gun is positiond
projectileObj.Rotation = aimer.Rotation; // Set the "bullet" to be facing the right way
projectileObj.Layer = gun.Layer + 1;
projectileObj.Physics.Velocity = T2DVectorUtil.VectorFromAngle(aimer.Rotation + 90) * 80; // Turns the rotation of the aimer into a vector to use as velocity
TorqueObjectDatabase.Instance.Register(projectileObj);// Registers the object
}
protected void _AimMove(Vector2 v)
{
T2DSceneObject aimer = TorqueObjectDatabase.Instance.FindObject<T2DSceneObject>("Aimer");
aimer.Rotation = T2DVectorUtil.AngleFromInput(v) - 90;
}
7. In the same file(Just abouve where you put the abouve functions) find protected void _setupInputMap() and change the function to look like:
protected void _setupInputMap()
{
MoveManager moveManager = new MoveManager();
ProcessList.Instance.SetMoveManager(this, moveManager);
InputMap inputMap = new InputMap();
inputMap.MoveManager = moveManager;
int gamePadNumber = Game.Instance.Players.Count - 1;
int gamepadId = InputManager.Instance.FindDevice("gamepad" + gamePadNumber);
inputMap.BindMove(gamepadId, (int)XGamePadDevice.GamePadObjects.LeftThumbX, MoveMapTypes.StickAnalogHorizontal, 0);
inputMap.BindMove(gamepadId, (int)XGamePadDevice.GamePadObjects.LeftThumbY, MoveMapTypes.StickAnalogVertical, 0);
inputMap.BindMove(gamepadId, (int)XGamePadDevice.GamePadObjects.RightThumbX, MoveMapTypes.StickAnalogHorizontal, 1);
inputMap.BindMove(gamepadId, (int)XGamePadDevice.GamePadObjects.RightThumbY, MoveMapTypes.StickAnalogVertical, 1);
inputMap.BindCommand(gamepadId, (int)XGamePadDevice.GamePadObjects.X, null, _Fire);
inputMap.BindMove(gamepadId, (int)XGamePadDevice.GamePadObjects.A, MoveMapTypes.Button, 0);
inputMap.BindMove(gamepadId, (int)XGamePadDevice.GamePadObjects.LeftTriggerButton, MoveMapTypes.Button, 0);
inputMap.BindMove(gamepadId, (int)XGamePadDevice.GamePadObjects.RightTriggerButton, MoveMapTypes.Button, 1);
inputMap.BindCommand(gamepadId, (int)XGamePadDevice.GamePadObjects.Back, null, Game.Instance.Exit);
int keyboardId = InputManager.Instance.FindDevice("keyboard0");
inputMap.BindMove(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.Space, MoveMapTypes.Button, 0);
inputMap.BindCommand(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.Enter, null, _Fire);
inputMap.BindMove(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.D, MoveMapTypes.StickDigitalRight, 0);
inputMap.BindMove(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.A, MoveMapTypes.StickDigitalLeft, 0);
inputMap.BindMove(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.W, MoveMapTypes.StickDigitalUp, 0);
inputMap.BindMove(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.S, MoveMapTypes.StickDigitalDown, 0);
inputMap.BindMove(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.Right, MoveMapTypes.StickDigitalRight, 1);
inputMap.BindMove(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.Left, MoveMapTypes.StickDigitalLeft, 1);
inputMap.BindMove(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.Up, MoveMapTypes.StickDigitalUp, 1);
inputMap.BindMove(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.Down, MoveMapTypes.StickDigitalDown, 1);
InputManager.Instance.PushInputMap(inputMap.CloneInputMap());
}
In Drillheadkillcomponent.cs find:
protected override void _onEnter(T2DSceneObject ourObject, T2DSceneObject theirObject, T2DCollisionInfo info)
Change the function to look like this:
protected override void _onEnter(T2DSceneObject ourObject, T2DSceneObject theirObject, T2DCollisionInfo info)
{
T2DSceneObject projectileObj = TorqueObjectDatabase.Instance.FindObject<T2DSceneObject>("ProjectileTemplate");
DragonActorComponent dragon = theirObject.Components.FindComponent<DragonActorComponent>();
if (theirObject.TestObjectType(PlatformerData.DamageTriggerObjecType))
{
_drillActor.TakeDamage(100.0f, projectileObj); //100 being the amount of damage the projectile does.
SceneObject.CollisionsEnabled = false;
}
// check for players
if (!theirObject.TestObjectType(PlatformerData.PlayerObjectType) || _drillActor == null)
return;
// get the dragon actor component that landed on us
// make sure it's valid
if (dragon == null || !_drillActor.Alive)
return;
// get the angle
float angle = MathHelper.ToDegrees((float)Math.Atan2(-info.Normal.X, info.Normal.Y)) - ourObject.Rotation;
angle = Math.Abs(angle) % 360;
float ourVelY = ourObject.Physics != null ? ourObject.Physics.VelocityY : 0.0f;
// check the angle against our angle threshold
if ((angle <= _maxHeadKillAngle || angle >= 360 - _maxHeadKillAngle) && theirObject.Physics.VelocityY >= ourVelY)
{
_drillActor.TakeDamage(_takeDamageOnLand, dragon.Actor);
dragon.Bounce(100);
SceneObject.CollisionsEnabled = false;
}
else if (angle > _maxHeadKillAngle && angle < 360 - _maxHeadKillAngle)
{
dragon.TakeDamage(_dealDamageOnBump, _drillActor.Actor);
}
}
In playercontroller.cs find :
public virtual void ProcessTick(Move move, float elapsed)
{
// check if move exists
if (move != null)
{
// set horizontal actor movement flags
if (move.Sticks[0].X < 0)
_moveLeft();
else if (move.Sticks[0].X > 0)
_moveRight();
else
_horizontalStop()
After this, add:
if(move.Sticks[1].X != 0 || move.Sticks[1].Y != 0)
_AimMove(new Vector2(move.Sticks[1].X, move.Sticks[1].Y));
Make sure you set the projectiletemplate object type to damagetriger else not alot will happen. Sorry if this seems a little rushed and if ive missed anything, im sat on the train with no direct access to the code. There is a missing check in the processtick to check when the trigger is pressed down to shoot so untill i get home to update it, X will do. Or you can use what code is written here, and in the starter pack to work out how to add firing to a trigger. By default the arrow's on the keyboard move the aimer or the right hand stick on the XBOX. Enter will fire and X on the XBOX.
Credits
--Dro Sarhadian Wrote part of the _Fire function.
--Henry Garle Wrote the aiming and directional shooting code. Henrygarle@gmail.com.



