TorqueX/PlatformerFrameworkShooter

From TDN

This page is a Work In Progress.


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 : Image:Xhair.png

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.