Top Down Shooter (Isometric Camera, WASD Controls, Aiming at Mouse Cursor)

Goal:

We want to create a new Game Type similar to “Alien Swarm“.
The camera view will be isometric.
The player character can be controlled with WASD according to the camera view.
The player has a moving cross hair which sets player’s viewing direction as well as the firing direction.

This tutorial is completely done in Unreal Script.

Special thanks go to:

Roychr – his isometric camera tutorial
X9 Productions – their isometric camera tutorial
Zaiteria – his isometric camera and controls tutorial
ZomBPir8Ninja – Scaleform Approach with startDrag()

 

Screenshot

Alien Swarm Tutorial

HEADS UP:

For more information on which tools to use, how to set up a new game, etc. please check out the UDK Forums as well as the UDN. The folks over there are really helpful and know a thing or two.

This is an advanced tutorial and I will assume that there is a basic understanding of Unreal Script, Pawns, Game Info, Player Controller, setting up the folder structure, etc.
However you should be able to copy-paste the code into your script files and everything should be fine.

I use DM-Deck as default map.

Issues:

  • Currently the Weapon Mesh is not displayed correctly.
  • Feign Death breaks the system.

Game info

There is not so much going on here but assigning the default Pawn class, the Player Controller and HUD.
The player also gets a Link Gun. Yeah!

TestGameInfo.uc

  1. class TestGameInfo extends GameInfo;
  2. //Create inventory
  3. var array< class <Inventory> > DefaultInventory;
  4. //Add default items to inventory of PlayerPawn
  5. function AddDefaultInventory( pawn PlayerPawn )
  6. {
  7.     if(PlayerPawn.IsHumanControlled() )
  8.     {
  9.         PlayerPawn.CreateInventory(class’UTWeap_LinkGun’,false);
  10.     }
  11. }
  12. defaultproperties
  13. {
  14.         bDelayedStart=false
  15.         HUDType=class’MouseInterfaceHUD’
  16.         PlayerControllerClass=class’TestPlayerController’
  17.         DefaultPawnClass=class’TestPawn’
  18. }

Pawn

The Pawn has the camera functions built into it so we don’t need a separate camera class.

TestPawn.uc

  1. class TestPawn extends UTPawn
  2.         config(Game)
  3.         notplaceable;
  4. //Camera Variables
  5. var float CamOffsetDistance; //distance to offset the camera from the player
  6. var int IsoCamAngle; //pitch angle of the camera
  7. //Makes the player mesh visable
  8. simulated event BecomeViewTarget( PlayerController PC )
  9. {
  10.    local UTPlayerController UTPC;
  11.    Super.BecomeViewTarget(PC);
  12.    if (LocalPlayer(PC.Player) != None)
  13.    {
  14.       UTPC = TestPlayerController(PC);
  15.       if (UTPC != None)
  16.       {
  17.          //set player controller to behind view and make mesh visible
  18.          UTPC.SetBehindView(true);
  19.          SetMeshVisibility(true);
  20.          UTPC.bNoCrosshair = true;
  21.       }
  22.    }
  23. }
  24. // Uses the weapon height (if any), otherwise eye height, to define the start location of the projectile. Essentially, it causes the pawn to look straight ahead if you were in 1st person view.
  25. simulated function vector GetAimStartLocation()
  26. {
  27.         local Vector pawnAimLocation;
  28.         if (Weapon != none)
  29.         {
  30.                 pawnAimLocation = Location + vect(0,0,1) * (Weapon.GetPhysicalFireStartLoc().Z – Location.Z); // just use upvector
  31.                 return pawnAimLocation;
  32.         }
  33.         else
  34.         {
  35.                 return GetPawnViewLocation(); // eye fallback
  36.         }
  37. }
  38. //Gives us our camera view.
  39. simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out floatout_FOV )
  40. {
  41.    out_CamLoc = Location;
  42.    out_CamLoc.X -= Cos(IsoCamAngle * UnrRotToRad) * CamOffsetDistance;
  43.    out_CamLoc.Z += Sin(IsoCamAngle * UnrRotToRad) * CamOffsetDistance;
  44.    out_CamRot.Pitch = -1 * IsoCamAngle;
  45.    out_CamRot.Yaw = 0;
  46.    out_CamRot.Roll = 0;
  47.    return true;
  48. }
  49. //Returns Aim Rotation
  50. simulated singular event Rotator GetBaseAimRotation()
  51. {
  52.    local rotator POVRot, tempRot;
  53.    tempRot = Rotation;
  54.    tempRot.Pitch = 0;
  55.    SetRotation(tempRot);
  56.    POVRot = Rotation;
  57.    POVRot.Pitch = 0;
  58.    return POVRot;
  59. }
  60. defaultproperties
  61. {
  62.         Begin Object Class=SkeletalMeshComponent Name=InitialSkeletalMesh
  63.                 CastShadow=true
  64.                 bCastDynamicShadow=true
  65.                 bOwnerNoSee=false
  66.                 LightEnvironment=MyLightEnvironment;
  67.         BlockRigidBody=true;
  68.         CollideActors=true;
  69.         BlockZeroExtent=true;
  70.                 PhysicsAsset=PhysicsAsset’CH_AnimCorrupt.Mesh.SK_C H_Corrupt_Male_Physics’
  71.                 AnimSets(0)=AnimSet’CH_AnimHuman.Anims.K_AnimHuman _AimOffset’
  72.                 AnimSets(1)=AnimSet’CH_AnimHuman.Anims.K_AnimHuman _BaseMale’
  73.                 AnimTreeTemplate=AnimTree’CH_AnimHuman_Tree.AT_CH_ Human’
  74.                 SkeletalMesh=SkeletalMesh’CH_LIAM_Cathode.Mesh.SK_ CH_LIAM_Cathode’
  75.         End Object
  76.         Mesh=InitialSkeletalMesh;
  77.         Components.Add(InitialSkeletalMesh);
  78.    IsoCamAngle=8000 //6420 = 35.264 degrees Change this number for the camera angle
  79.    CamOffsetDistance=512 //change this number for camera distance.
  80.    GroundSpeed=256
  81. }

Player Controller

The Player Controller handles all the functions regarding mouse input, the pawn facing the mouse and the WASD movement.

TestPlayerController.uc

  1. class TestPlayerController extends UTPlayerController;
  2. // Mouse event enum
  3. enum EMouseEvent
  4. {
  5.   LeftMouseButton,
  6.   RightMouseButton,
  7.   MiddleMouseButton,
  8.   ScrollWheelUp,
  9.   ScrollWheelDown,
  10. };
  11. var vector PlaneHitPos;
  12. var bool bRooted;
  13. var float PreviousSpeed;
  14. // Handle mouse inputs.
  15. function HandleMouseInput(EMouseEvent MouseEvent, EInputEvent InputEvent)
  16. {
  17.   local MouseInterfaceHUD MouseInterfaceHUD;
  18.   // Type cast to get our HUD
  19.   MouseInterfaceHUD = MouseInterfaceHUD(myHUD);
  20.   if (MouseInterfaceHUD != None)
  21.   {
  22.     // Detect what kind of input this is
  23.     if (InputEvent == IE_Pressed)
  24.     {
  25.       // Handle pressed event
  26.       switch (MouseEvent)
  27.       {
  28.         case LeftMouseButton:
  29.      MouseInterfaceHUD.PendingLeftPressed = true;
  30.      break;
  31.    case RightMouseButton:
  32.      MouseInterfaceHUD.PendingRightPressed = true;
  33.      break;
  34.    case MiddleMouseButton:
  35.      MouseInterfaceHUD.PendingMiddlePressed = true;
  36.      break;
  37.    case ScrollWheelUp:
  38.      MouseInterfaceHUD.PendingScrollUp = true;
  39.      break;
  40.    case ScrollWheelDown:
  41.      MouseInterfaceHUD.PendingScrollDown = true;
  42.      break;
  43.    default:
  44.      break;
  45.       }
  46.     }
  47.     else if (InputEvent == IE_Released)
  48.     {
  49.       // Handle released event
  50.       switch (MouseEvent)
  51.       {
  52.         case LeftMouseButton:
  53.      MouseInterfaceHUD.PendingLeftReleased = true;
  54.      break;
  55.    case RightMouseButton:
  56.      MouseInterfaceHUD.PendingRightReleased = true;
  57.      break;
  58.    case MiddleMouseButton:
  59.      MouseInterfaceHUD.PendingMiddleReleased = true;
  60.      break;
  61.    default:
  62.      break;
  63.       }
  64.     }
  65.   }
  66. }
  67. // Hook used for the left and right mouse button when pressed
  68. exec function StartFire(optional byte FireModeNum)
  69. {
  70.   HandleMouseInput((FireModeNum == 0) ? LeftMouseButton : RightMouseButton, IE_Pressed);
  71.   Super.StartFire(FireModeNum);
  72. }
  73. // Hook used for the left and right mouse button when released
  74. exec function StopFire(optional byte FireModeNum)
  75. {
  76.   HandleMouseInput((FireModeNum == 0) ? LeftMouseButton : RightMouseButton, IE_Released);
  77.   Super.StopFire(FireModeNum);
  78. }
  79. // Called when the middle mouse button is pressed
  80. exec function MiddleMousePressed()
  81. {
  82.   HandleMouseInput(MiddleMouseButton, IE_Pressed);
  83. }
  84. // Called when the middle mouse button is released
  85. exec function MiddleMouseReleased()
  86. {
  87.   HandleMouseInput(MiddleMouseButton, IE_Released);
  88. }
  89. // Called when the middle mouse wheel is scrolled up
  90. exec function MiddleMouseScrollUp()
  91. {
  92.   HandleMouseInput(ScrollWheelUp, IE_Pressed);
  93. }
  94. // Called when the middle mouse wheel is scrolled down
  95. exec function MiddleMouseScrollDown()
  96. {
  97.   HandleMouseInput(ScrollWheelDown, IE_Pressed);
  98. }
  99. // Override this state because StartFire isn’t called globally when in this function
  100. auto state PlayerWaiting
  101. {
  102.   exec function StartFire(optional byte FireModeNum)
  103.   {
  104.     Global.StartFire(FireModeNum);
  105.   }
  106. }
  107. //This is where the magic happens! This updates the pawn’s rotation to face the mouse cursor!
  108. function UpdateRotation(float DeltaTime){
  109.    local Rotator   targetRotation;
  110.    local Vector    aimStartPos;
  111.    local float     hitLength;
  112.    local MouseInterfaceHUD   playerHud;
  113.    local TestPawn  TestPawn;
  114.    if (self.Pawn != None)
  115.    {
  116.       TestPawn = TestPawn(self.Pawn);
  117.         if (TestPawn != none)
  118.          {
  119.              aimStartPos = TestPawn.GetAimStartLocation();
  120.          }
  121.          else
  122.         {
  123.              aimStartPos = self.Pawn.GetPawnViewLocation();
  124.          }
  125.          playerHud = MouseInterfaceHUD(myHUD);
  126.          // calc the player/world plane > deproj mouse ray intersection
  127.          hitLength = -((vect(0,0,1) dot (playerHud.CachedMouseWorldOrigin – aimStartPos)) / (vect(0,0,1) dot playerHud.CachedMouseWorldDirection));
  128.          PlaneHitPos = (playerHud.CachedMouseWorldOrigin + playerHud.CachedMouseWorldDirection * hitLength);
  129.          targetRotation = pawn.GetBaseAimRotation();
  130.          targetRotation.Yaw = rotator(PlaneHitPos – aimStartPos).Yaw; // only update yaw
  131.          Pawn.FaceRotation(targetRotation, DeltaTime);
  132.          }
  133.          else
  134.          {
  135.          super.UpdateRotation(DeltaTime);
  136.          }
  137. }
  138. //The adjustments to this state cause WASD to function correctly.
  139. state PlayerWalking
  140. {
  141. ignores SeePlayer, HearNoise, Bump;
  142.    function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
  143.    {
  144.       if( Pawn == None )
  145.       {
  146.          return;
  147.       }
  148.       if (Role == ROLE_Authority)
  149.       {
  150.          // Update ViewPitch for remote clients
  151.          Pawn.SetRemoteViewPitch( Rotation.Pitch );
  152.       }
  153.       //Forces WASD to work properly!
  154.       Pawn.Acceleration.X = 1 * PlayerInput.aBaseY * DeltaTime * 100 * PlayerInput.MoveForwardSpeed;;
  155.       Pawn.Acceleration.Y = 1 * PlayerInput.aStrafe * DeltaTime * 100 * PlayerInput.MoveForwardSpeed;
  156.       Pawn.Acceleration.Z = 0;
  157.       CheckJumpOrDuck();
  158.    }
  159. }
  160. defaultproperties
  161. {
  162.   // Set the input class to the mouse interface player input
  163.   InputClass=class’MouseInterfacePlayerInput’
  164. }

Mouseinterface

This is taken from the Mouse Interface Gem from the UDN.
They can probably explain it better and in more detail than me :)

MouseInterfaceGfx.uc

  1. class MouseInterfaceGFx extends GFxMoviePlayer;
  2. var MouseInterfaceHUD MouseInterfaceHUD;
  3. function Init(optional LocalPlayer LocalPlayer)
  4. {
  5.         // Initialize the ScaleForm movie
  6.         Super.Init(LocalPlayer);
  7.         Start();
  8.     Advance(0);
  9. }
  10. event UpdateMousePosition(float X, float Y)
  11. {
  12.         local MouseInterfacePlayerInput MouseInterfacePlayerInput;
  13.         if (MouseInterfaceHUD != None && MouseInterfaceHUD.PlayerOwner != None)
  14.         {
  15.                 MouseInterfacePlayerInput = MouseInterfacePlayerInput(MouseInterfaceHUD.PlayerOwner.PlayerInput);
  16.                 if (MouseInterfacePlayerInput != None)
  17.                 {
  18.                         MouseInterfacePlayerInput.SetMousePosition(X, Y);
  19.                 }
  20.         }
  21. }
  22. defaultproperties
  23. {
  24.     bDisplayWithHudOff=false
  25.     TimingMode=TM_Game
  26.     bPauseGameWhileActive=false
  27. }

HUD

MouseInterfaceHUD.uc

  1. class MouseInterfaceHUD extends HUD;
  2. // The texture which represents the cursor on the screen
  3. var Texture2D CursorTexture;
  4. // The color of the cursor
  5. var const Color CursorColor;
  6. // Pending left mouse button pressed event
  7. var bool PendingLeftPressed;
  8. // Pending left mouse button released event
  9. var bool PendingLeftReleased;
  10. // Pending right mouse button pressed event
  11. var bool PendingRightPressed;
  12. // Pending right mouse button released event
  13. var bool PendingRightReleased;
  14. // Pending middle mouse button pressed event
  15. var bool PendingMiddlePressed;
  16. // Pending middle mouse button released event
  17. var bool PendingMiddleReleased;
  18. // Pending mouse wheel scroll up event
  19. var bool PendingScrollUp;
  20. // Pending mouse wheel scroll down event
  21. var bool PendingScrollDown;
  22. // Cached mouse world origin
  23. var Vector CachedMouseWorldOrigin;
  24. // Cached mouse world direction
  25. var Vector CachedMouseWorldDirection;
  26. // Last mouse interaction interface
  27. var MouseInterfaceInteractionInterface LastMouseInteractionInterface;
  28. // Use ScaleForm?
  29. var bool UsingScaleForm;
  30. // Scaleform mouse movie
  31. var MouseInterfaceGFx MouseInterfaceGFx;
  32. simulated event PostBeginPlay()
  33. {
  34.   Super.PostBeginPlay();
  35.   // If we are using ScaleForm, then create the ScaleForm movie
  36.   if (UsingScaleForm)
  37.   {
  38.     MouseInterfaceGFx = new () class’MouseInterfaceGFx’;
  39.     if (MouseInterfaceGFx != None)
  40.     {
  41.       MouseInterfaceGFx.MouseInterfaceHUD = Self;
  42.       MouseInterfaceGFx.SetTimingMode(TM_Game);
  43.       MouseInterfaceGFx.Init(class’Engine’.static.GetEngine().GamePlayers[MouseInterfaceGFx.LocalPlayerOwnerIndex]);
  44.     }
  45.   }
  46. }
  47. simulated event Destroyed()
  48. {
  49.   Super.Destroyed();
  50.   // If the ScaleForm movie exists, then destroy it
  51.   if (MouseInterfaceGFx != None)
  52.   {
  53.     MouseInterfaceGFx.Close(true);
  54.     MouseInterfaceGFx = None;
  55.   }
  56. }
  57. function PreCalcValues()
  58. {
  59.   Super.PreCalcValues();
  60.   // If the ScaleForm movie exists, then reset it’s viewport, scale mode and alignment to match the
  61.   // screen resolution
  62.   if (MouseInterfaceGFx != None)
  63.   {
  64.     MouseInterfaceGFx.SetViewport(0, 0, SizeX, SizeY);
  65.     MouseInterfaceGFx.SetViewScaleMode(SM_NoScale);
  66.     MouseInterfaceGFx.SetAlignment(Align_TopLeft);
  67.   }
  68. }
  69. /*simulated function SwitchCursorTexture(Texture2D Cursor)
  70. {
  71. local MouseInterfacePlayerInput MouseInterfacePlayerInput;
  72.  // Ensure that we aren’t using ScaleForm and that we have a valid cursor
  73.   if (!UsingScaleForm && CursorTexture != None)
  74.   {
  75.     // Ensure that we have a valid PlayerOwner
  76.     if (PlayerOwner != None)
  77.     {
  78.       // If we’re not using scale form and we have a valid cursor texture, render it
  79.       if (MouseInterfacePlayerInput != None)
  80.       {
  81.         Canvas.DrawTile(Cursor, CursorTexture.SizeX, CursorTexture.SizeY, 0.f, 0.f, CursorTexture.SizeX, CursorTexture.SizeY,, true);
  82.       }
  83.     }
  84.   }
  85. }       */
  86. event PostRender()
  87. {
  88.   local MouseInterfacePlayerInput MouseInterfacePlayerInput;
  89.   local MouseInterfaceInteractionInterface MouseInteractionInterface;
  90.   local Vector HitLocation, HitNormal;
  91.   Super.PostRender();
  92.   // Ensure that we aren’t using ScaleForm and that we have a valid cursor
  93.   if (!UsingScaleForm && CursorTexture != None)
  94.   {
  95.     // Ensure that we have a valid PlayerOwner
  96.     if (PlayerOwner != None)
  97.     {
  98.       // Cast to get the MouseInterfacePlayerInput
  99.       MouseInterfacePlayerInput = MouseInterfacePlayerInput(PlayerOwner.PlayerInput)  ;
  100.       // If we’re not using scale form and we have a valid cursor texture, render it
  101.       if (MouseInterfacePlayerInput != None)
  102.       {
  103.         // Set the canvas position to the mouse position
  104.         Canvas.SetPos(MouseInterfacePlayerInput.MousePosition.X, MouseInterfacePlayerInput.MousePosition.Y);
  105.         // Set the cursor color
  106.         Canvas.DrawColor = CursorColor;
  107.         // Draw the texture on the screen
  108.         Canvas.DrawTile(CursorTexture, CursorTexture.SizeX, CursorTexture.SizeY, 0.f, 0.f, CursorTexture.SizeX, CursorTexture.SizeY,, true);
  109.       }
  110.     }
  111.   }
  112.   // Get the current mouse interaction interface
  113.   MouseInteractionInterface = GetMouseActor(HitLocation, HitNormal);
  114.   // Handle mouse over and mouse out
  115.   // Did we previously had a mouse interaction interface?
  116.   if (LastMouseInteractionInterface != None)
  117.   {
  118.     // If the last mouse interaction interface differs to the current mouse interaction
  119.     if (LastMouseInteractionInterface != MouseInteractionInterface)
  120.     {
  121.       // Call the mouse out function
  122.       LastMouseInteractionInterface.MouseOut(CachedMouseWorldOrigin, CachedMouseWorldDirection);
  123.       // Assign the new mouse interaction interface
  124.       LastMouseInteractionInterface = MouseInteractionInterface;
  125.       // If the last mouse interaction interface is not none
  126.       if (LastMouseInteractionInterface != None)
  127.       {
  128.         // Call the mouse over function
  129.         LastMouseInteractionInterface.MouseOver(CachedMouseWorldOrigin, CachedMouseWorldDirection); // Call mouse over
  130.       }
  131.     }
  132.   }
  133.   else if (MouseInteractionInterface != None)
  134.   {
  135.     // Assign the new mouse interaction interface
  136.     LastMouseInteractionInterface = MouseInteractionInterface;
  137.     // Call the mouse over function
  138.     LastMouseInteractionInterface.MouseOver(CachedMouseWorldOrigin, CachedMouseWorldDirection);
  139.   }
  140.   if (LastMouseInteractionInterface != None)
  141.   {
  142.     // Handle left mouse button
  143.     if (PendingLeftPressed)
  144.     {
  145.       if (PendingLeftReleased)
  146.       {
  147.         // This is a left click, so discard
  148.         PendingLeftPressed = false;
  149.         PendingLeftReleased = false;
  150.       }
  151.       else
  152.       {
  153.         // Left is pressed
  154.         PendingLeftPressed = false;
  155.         LastMouseInteractionInterface.MouseLeftPressed(CachedMouseWorldOrigin, CachedMouseWorldDirection, HitLocation, HitNormal);
  156.       }
  157.     }
  158.     else if (PendingLeftReleased)
  159.     {
  160.       // Left is released
  161.       PendingLeftReleased = false;
  162.       LastMouseInteractionInterface.MouseLeftReleased(CachedMouseWorldOrigin, CachedMouseWorldDirection);
  163.     }
  164.     // Handle right mouse button
  165.     if (PendingRightPressed)
  166.     {
  167.       if (PendingRightReleased)
  168.       {
  169.         // This is a right click, so discard
  170.         PendingRightPressed = false;
  171.         PendingRightReleased = false;
  172.       }
  173.       else
  174.       {
  175.         // Right is pressed
  176.         PendingRightPressed = false;
  177.         LastMouseInteractionInterface.MouseRightPressed(CachedMouseWorldOrigin, CachedMouseWorldDirection, HitLocation, HitNormal);
  178.       }
  179.     }
  180.     else if (PendingRightReleased)
  181.     {
  182.       // Right is released
  183.       PendingRightReleased = false;
  184.       LastMouseInteractionInterface.MouseRightReleased(CachedMouseWorldOrigin, CachedMouseWorldDirection);
  185.     }
  186.     // Handle middle mouse button
  187.     if (PendingMiddlePressed)
  188.     {
  189.       if (PendingMiddleReleased)
  190.       {
  191.         // This is a middle click, so discard
  192.         PendingMiddlePressed = false;
  193.         PendingMiddleReleased = false;
  194.       }
  195.       else
  196.       {
  197.         // Middle is pressed
  198.         PendingMiddlePressed = false;
  199.         LastMouseInteractionInterface.MouseMiddlePressed(CachedMouseWorldOrigin, CachedMouseWorldDirection, HitLocation, HitNormal);
  200.       }
  201.     }
  202.     else if (PendingMiddleReleased)
  203.     {
  204.       PendingMiddleReleased = false;
  205.       LastMouseInteractionInterface.MouseMiddleReleased(CachedMouseWorldOrigin, CachedMouseWorldDirection);
  206.     }
  207.     // Handle middle mouse button scroll up
  208.     if (PendingScrollUp)
  209.     {
  210.       PendingScrollUp = false;
  211.       LastMouseInteractionInterface.MouseScrollUp(CachedMouseWorldOrigin, CachedMouseWorldDirection);
  212.     }
  213.     // Handle middle mouse button scroll down
  214.     if (PendingScrollDown)
  215.     {
  216.       PendingScrollDown = false;
  217.       LastMouseInteractionInterface.MouseScrollDown(CachedMouseWorldOrigin, CachedMouseWorldDirection);
  218.     }
  219.   }
  220. }
  221. function MouseInterfaceInteractionInterface GetMouseActor(optional out Vector HitLocation, optional out VectorHitNormal)
  222. {
  223.   local MouseInterfaceInteractionInterface MouseInteractionInterface;
  224.   local MouseInterfacePlayerInput MouseInterfacePlayerInput;
  225.   local Vector2D MousePosition;
  226.   local Actor HitActor;
  227.   // Ensure that we have a valid canvas and player owner
  228.   if (Canvas == None || PlayerOwner == None)
  229.   {
  230.     return None;
  231.   }
  232.   // Type cast to get the new player input
  233.   MouseInterfacePlayerInput = MouseInterfacePlayerInput(PlayerOwner.PlayerInput)  ;
  234.   // Ensure that the player input is valid
  235.   if (MouseInterfacePlayerInput == None)
  236.   {
  237.     return None;
  238.   }
  239.   // We stored the mouse position as an IntPoint, but it’s needed as a Vector2D
  240.   MousePosition.X = MouseInterfacePlayerInput.MousePosition.X;
  241.   MousePosition.Y = MouseInterfacePlayerInput.MousePosition.Y;
  242.   // Deproject the mouse position and store it in the cached vectors
  243.   Canvas.DeProject(MousePosition, CachedMouseWorldOrigin, CachedMouseWorldDirection);
  244.   // Perform a trace actor interator. An interator is used so that we get the top most mouse interaction
  245.   // interface. This covers cases when other traceable objects (such as static meshes) are above mouse
  246.   // interaction interfaces.
  247.   ForEach TraceActors(class’Actor’, HitActor, HitLocation, HitNormal, CachedMouseWorldOrigin +CachedMouseWorldDirection * 65536.f, CachedMouseWorldOrigin,,, TRACEFLAG_Bullet)
  248.   {
  249.     // Type cast to see if the HitActor implements that mouse interaction interface
  250.     MouseInteractionInterface = MouseInterfaceInteractionInterface(HitActor);
  251.     if (MouseInteractionInterface != None)
  252.     {
  253.       return MouseInteractionInterface;
  254.     }
  255.   }
  256.   return None;
  257. }
  258. function Vector GetMouseWorldLocation()
  259. {
  260.   local MouseInterfacePlayerInput MouseInterfacePlayerInput;
  261.   local Vector2D MousePosition;
  262.   local Vector MouseWorldOrigin, MouseWorldDirection, HitLocation, HitNormal;
  263.   // Ensure that we have a valid canvas and player owner
  264.   if (Canvas == None || PlayerOwner == None)
  265.   {
  266.     return Vect(0, 0, 0);
  267.   }
  268.   // Type cast to get the new player input
  269.   MouseInterfacePlayerInput = MouseInterfacePlayerInput(PlayerOwner.PlayerInput)  ;
  270.   // Ensure that the player input is valid
  271.   if (MouseInterfacePlayerInput == None)
  272.   {
  273.     return Vect(0, 0, 0);
  274.   }
  275.   // We stored the mouse position as an IntPoint, but it’s needed as a Vector2D
  276.   MousePosition.X = MouseInterfacePlayerInput.MousePosition.X;
  277.   MousePosition.Y = MouseInterfacePlayerInput.MousePosition.Y;
  278.   // Deproject the mouse position and store it in the cached vectors
  279.   Canvas.DeProject(MousePosition, MouseWorldOrigin, MouseWorldDirection);
  280.   // Perform a trace to get the actual mouse world location.
  281.   Trace(HitLocation, HitNormal, MouseWorldOrigin + MouseWorldDirection * 65536.f, MouseWorldOrigin , true,,, TRACEFLAG_Bullet);
  282.   return HitLocation;
  283. }
  284. defaultproperties
  285. {
  286.   // Set to false if you wish to use Unreal’s player input to retrieve the mouse coordinates
  287.   UsingScaleForm=false
  288.   CursorColor=(R=255,G=255,B=255,A=255)
  289.   CursorTexture=Texture2D’EngineResources.Cursors.Arrow’
  290. }

MouseINteraction

MouseInterfaceInteractionInterface.uc

  1. interface MouseInterfaceInteractionInterface;
  2. // Called when the left mouse button is pressed
  3. function MouseLeftPressed(Vector MouseWorldOrigin, Vector MouseWorldDirection, Vector HitLocation, VectorHitNormal);
  4. // Called when the left mouse button is released
  5. function MouseLeftReleased(Vector MouseWorldOrigin, Vector MouseWorldDirection);
  6. // Called when the right mouse button is pressed
  7. function MouseRightPressed(Vector MouseWorldOrigin, Vector MouseWorldDirection, Vector HitLocation, VectorHitNormal);
  8. // Called when the right mouse button is released
  9. function MouseRightReleased(Vector MouseWorldOrigin, Vector MouseWorldDirection);
  10. // Called when the middle mouse button is pressed
  11. function MouseMiddlePressed(Vector MouseWorldOrigin, Vector MouseWorldDirection, Vector HitLocation, VectorHitNormal);
  12. // Called when the middle mouse button is released
  13. function MouseMiddleReleased(Vector MouseWorldOrigin, Vector MouseWorldDirection);
  14. // Called when the middle mouse button is scrolled up
  15. function MouseScrollUp(Vector MouseWorldOrigin, Vector MouseWorldDirection);
  16. // Called when the middle mouse button is scrolled down
  17. function MouseScrollDown(Vector MouseWorldOrigin, Vector MouseWorldDirection);
  18. // Called when the mouse is moved over the actor
  19. function MouseOver(Vector MouseWorldOrigin, Vector MouseWorldDirection);
  20. // Called when the mouse is moved out from the actor (when it was previously over it)
  21. function MouseOut(Vector MouseWorldOrigin, Vector MouseWorldDirection);
  22. // Returns the hit location of the mouse trace
  23. function Vector GetHitLocation();
  24. // Returns the hit normal of the mouse trace
  25. function Vector GetHitNormal();
  26. // Returns the mouse world origin calculated by the deprojection within the canvas
  27. function Vector GetMouseWorldOrigin();
  28. // Returns the mouse world direction calculated by the deprojection within the canvas
  29. function Vector GetMouseWorldDirection();

Player Input

MouseInterfacePlayerInput.uc

  1. class MouseInterfacePlayerInput extends PlayerInput;
  2. var PrivateWrite IntPoint MousePosition;
  3. event PlayerInput(float DeltaTime)
  4. {
  5.         local MouseInterfaceHUD MouseInterfaceHUD;
  6.         // Handle mouse movement
  7.         // Check that we have the appropriate HUD class
  8.         MouseInterfaceHUD = MouseInterfaceHUD(MyHUD);
  9.         if (MouseInterfaceHUD != None)
  10.         {
  11.                 if (!MouseInterfaceHUD.UsingScaleForm)
  12.                 {
  13.                         // If we are not using ScaleForm, then read the mouse input directly
  14.                         // Add the aMouseX to the mouse position and clamp it within the viewport width
  15.                         MousePosition.X = Clamp(MousePosition.X + aMouseX, 0, MouseInterfaceHUD.SizeX);
  16.                         // Add the aMouseY to the mouse position and clamp it within the viewport height
  17.                         MousePosition.Y = Clamp(MousePosition.Y – aMouseY, 0, MouseInterfaceHUD.SizeY);
  18.                 }
  19.         }
  20.         Super.PlayerInput(DeltaTime);
  21. }
  22. function SetMousePosition(int X, int Y)
  23. {
  24.         if (MyHUD != None)
  25.         {
  26.                 MousePosition.X = Clamp(X, 0, MyHUD.SizeX);
  27.                 MousePosition.Y = Clamp(Y, 0, MyHUD.SizeY);
  28.         }
  29. }
  30. defaultproperties
  31. {
  32. }

Compile, debug and there you go!

I have tried to extend from UTGame instead of GameInfo to save some work on the HUD. The only successful approach was to utilize Scaleform and use the startDrag() function within Action Script.
The mouse cursor got laggy and I have not gone deeper down that path.

Let me know if you do and have fun with the new Top Down shooter!

Sorry for the mess with the pasted code into WordPress.
Copy and Paste should still be fine.

Advertisements

2 thoughts on “Top Down Shooter (Isometric Camera, WASD Controls, Aiming at Mouse Cursor)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s