Chapter 2 – Getting the mouse into the fray

December 20th, 2009 Leave a comment Go to comments

To get mouse coordinates we will use an extended HUD class. What is a hud ? Its a HEADS UP DISPLAY. Usually its the class that will render health, ammo and other nice overlays in real time in the viewport.

Lets create a new file named MyHud. Now you should anticipate you will have to change its “extends Object” to something. Lets extend from GameHUD. First thing we will do is wire it to our game. Again, go to your IsometricGameInfo class and add the following to its default properties :

HUDType=class‘MyHud’


Now I will try let go the white gloves a bit so we can both get to a pleasant pace for this tutorial. If you start having troubles integrating the classes, try setting up PostBeginPlay function like we coded in the IsometricGamePlayerController. This should output something to the console if the class has a proper instance. Remember that the Log function is your eyes to the code. You can make it output any variables. I will add Log functions as we go so do not worry about the details, I will explain them as we go along. As a last thing, I may use the following syntax to describe functions : CLASS :: FUNCTION, this is my C++ background getting the better of me, but its quicker to say in which class and which function I am referring to.

  • Compile and run to see that no error is present.

 

Getting mouse coordinates

 

Add the following function to your MyHud class and take the time to read the comment :

 

 


/******************************************************************
 *
 * TUTORIAL FUNCTION
 *
 * This function will fetch mouse coordinates from the UI
 * Hierarchy in the UIController of the PlayerController
 *
 *
 ******************************************************************/
function vector2D GetMouseCoordinates()
{
	local Vector2D mousePos;
	local UIInteraction UIController;
	local GameUISceneClient GameSceneClient;

	UIController  = PlayerOwner.GetUIController();

	if ( UIController != None)
	{
		GameSceneClient = UIController.SceneClient;
		if ( GameSceneClient != None )
		{
			mousePos.X = GameSceneClient.MousePosition.X;
			mousePos.Y = GameSceneClient.MousePosition.Y;
		}
	}

	return mousePos;
}

Now if you do not catch what the comment means, do not worry about it, with this we get the mouse coordinates. If you really want to know more go to GameUISceneClient.uc.

Now the UDK theory about HUD calculation is that everything is supposed to be calculated in a function called PostRender. All the variables we need to calculate will be located in our player controller for our pawn to know where the mouse is located in 3d space. Unfortunately, with UDK, the only valid place to calculate this is inside the HUD. The reason is that we need a variable called Canvas that can turn mouse coordinates into 3d world coordinates inside the game. Copy the following PostRender function in your MyHud class :


/******************************************************************
 *
 * PostRender event
 *
 * Use postRender function to define and call all hud drawing
 * routine.
 *
 *
 ******************************************************************/
event PostRender()
{
	local IsometricCamera PlayerCam;
	local IsometricGamePlayerController IsoPlayerController;

	super.PostRender();

	//Get a type casted reference to our custom player controller.
	IsoPlayerController = IsometricGamePlayerController(PlayerOwner);

	//Get the mouse coordinates from the GameUISceneClient
	IsoPlayerController.PlayerMouse = GetMouseCoordinates();
	//Deproject the 2d mouse coordinate into 3d world. Store the MousePosWorldLocation and normal (direction).
	Canvas.DeProject(IsoPlayerController.PlayerMouse, IsoPlayerController.MousePosWorldLocation, IsoPlayerController.MousePosWorldNormal);

	//Get a type casted reference to our custom camera.
	PlayerCam = IsometricCamera(IsoPlayerController.PlayerCamera);

	//Calculate a trace from Player camera + 100 up(z) in direction of deprojected MousePosWorldNormal (the direction of the mouse).
	//-----------------
	//Set the ray direction as the mouseWorldnormal
	IsoPlayerController.RayDir = IsoPlayerController.MousePosWorldNormal;
	//Start the trace at the player camera (isometric) + 100 unit z and a little offset in front of the camera (direction *10)
	IsoPlayerController.StartTrace = (PlayerCam.ViewTarget.POV.Location + vect(0,0,100)) + IsoPlayerController.RayDir * 10;
	//End this ray at start + the direction multiplied by given distance (5000 unit is far enough generally)
	IsoPlayerController.EndTrace = IsoPlayerController.StartTrace + IsoPlayerController.RayDir * 5000;

	//Trace MouseHitWorldLocation each frame to world location (here you can get from the trace the actors that are hit by the trace, for the sake of this
	//simple tutorial, we do noting with the result, but if you would filter clicks only on terrain, or if the player clicks on an npc, you would want to inspect
	//the object hit in the StartFire function
	IsoPlayerController.TraceActor = Trace(IsoPlayerController.MouseHitWorldLocation, IsoPlayerController.MouseHitWorldNormal, IsoPlayerController.EndTrace, IsoPlayerController.StartTrace, true);

	//Calculate the pawn eye location for debug ray and for checking obstacles on click.
	IsoPlayerController.PawnEyeLocation = Pawn(PlayerOwner.ViewTarget).Location + Pawn(PlayerOwner.ViewTarget).EyeHeight * vect(0,0,1);

	//Your basic draw hud routine
	DrawHUD();
}

The magic of type casting

 

There is multiple ways of accessing variables inside our custom player controller. The way I prefer is to type-cast the variable only once and use it for the entire function. Depending on the way the compiler works this may be inneficient, but I do not possess enough knowledge about this particular topic to let the compiler do it for me.

 

First way of getting a variable from another class :

local MyClass MyVar;

 

MyVar = MyClass(OtherClass);

MyVar.Member += 1;

 

or

 

MyClass(OtherClass).Member += 1;

 

To make the tutorial easier to follow, I use the first approach.

 

 

 

Chapter 2 – Setting up for movement

 

 

 

Update me when site is updated
Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Slashdot
  • PDF
  • Twitter
  1. Lucas Cooper
    January 9th, 2010 at 19:16 | #1

    Im having trouble compiling this. The PlayerMouse Variable doesnt seem to exist

  2. Hotdot
    January 12th, 2010 at 20:16 | #2

    PlayerMouse must be declared in the PlayerController because its referenced with IsoPlayerController.PlayerMouse, sorry but you should compile when the tutorial says so, I did it that way so you will not end up with undeclared variables, just look into chapter 2 setting up for movement and it will be pretty obvious what to add :)

  3. vitiank
    March 19th, 2010 at 13:32 | #3

    i cant set up VS2008 to work properly so i use simple text editor for scripts and Frontend to compile. Plz tell me how can i declare PlayerMouse variable in my PlayerController for compile to succeed

  4. Hotdot
    March 20th, 2010 at 19:23 | #4

    vitiank you should follow the tutorial from chapter 0 and install vs2008 and install nfringe and if you just follow the explanations you should be able to compile correctly. Now if you are a hardcore programmer and cannot help but use notepad or such other software, you should make a sub folder like explained in chapter 0 for your projet and modify the proper ini files so that the frontend will be able to know where to look for your file.

  5. FozZ
    July 24th, 2010 at 15:11 | #5

    GameHUD.uc does not exist in the July 2010 release. I’ve tried using copying it from a November 09 install with no luck. Any suggestions? Thanks.

  6. Jake
    July 29th, 2010 at 09:36 | #6

    @FozZ
    Try using UDKHUD or UTHUD

  7. LeNain
    August 25th, 2010 at 15:47 | #7

    This really is some good quality tuto mate! I didn’t finish it yet, and encounter quite a lot of difficulties because of the new UDK releases (and the fact that I’m adapting your stuff to be directly as I want it ^^), but still very helpful.

    I’d like to point out 2 things that you should mention in a EDIT in my opinion:
    - first one is the commment ok Jake answering to FozZ => GameHUD.uc doesn’t exist anymore, replace it with UTHUD.uc.
    - a bit trickier: I’m using the latest classes they made (using July 2010 build), namely all the UT****.uc (e.g. UTPawn instead of Pawn). I guess that from now on, most of the users will do so, and there comes the problem which took me hours to solve: the new “GameInfo.uc” is “UTGame.uc”, and this one will never use your custom HUD class!!!
    => Fortunately, i can finally spread the solution in order to prevent people from falling into depression: from now on, UE3 can use either an Unreal Script HUD or a Flash one (called scaleform); this new scaleform HUD is the default one, which is why my custom Unreal Script HUD was not used. The trick is to add in your IsometricGameInfo.uc – default properties – the following statement:

    ———————–
    bUseClassicHUD=true
    ———————–

    This will make the engine use the Unreal Script HUD again!

  8. Roychr
    September 8th, 2010 at 11:38 | #8

    Thanks LeNain that is really good information to pass on !

  9. Sickin
    December 1st, 2010 at 21:28 | #9

    Though I would pass this information through here, as it will prolly help a few people like me. Creasso Posted on UDK forums a fix for this with the changes made starting in October beta when the basic game hud was removed. This is a fix for the Scaleform system that is now used. This will get you mouse coordinates for this section.

    You need to replace you GetMouseCoordnates() with this

    function vector2D GetMouseCoordinates()
    {
    local Vector2D mousePos;
    mousePos.X = YourRootMovieName.GetVariableNumber(“_root._xmouse”);

    Credit where credit is due http://forums.epicgames.com/showthread.php?p=27789000#post27789000
    mousePos.Y = YourRootMovieName.GetVariableNumber(“_root._ymouse”);
    return mousePos;
    }

    • Roychr
      December 1st, 2010 at 22:09 | #10

      Thanks Sickin, this is definitly needed, lots of people had problems with the hud when it was half removed by epic a few months back.

  10. Chillone
    December 3rd, 2010 at 18:49 | #11

    I used the code that Sickin provided and replaced the GetmouseCoordinates() function and replaced YourRootMovieName with GameSceneClient. Then i get the error messege :
    C:\UDK\UDK-2010-11\Development\Src\RtsTest\Classes\MyHud.uc(19) : Error, Bad or missing expression for token: GameSceneClient, in ‘=’
    What am I doing wrong?

    Thanks!

  11. admin
    December 3rd, 2010 at 18:54 | #12

    you probably have to at least follow a tutorial on how to get a simple GUI with ScaleForm working inside your code and then the snippet from Sickin will make more sense. In fact the compiler will generate this kind of error when “GameSceneClient” is not found as a declared ressource. The code for all intent and purpose will link the object to the ressource named “GameSceneClient” as a ScaleForm resource.

  12. December 13th, 2010 at 20:02 | #13

    For anyone following the tutorial right now like I am, the best way I found to get mouse coords out of ScaleForm is explained in this thread:
    http://utforums.epicgames.com/showthread.php?t=742353

    This is the method that worked for me, and it does a good job of explaining to how set up your custom HudMovie class that you will need to load your custom Flash .swf

  13. Syndrome9001
    January 10th, 2011 at 01:45 | #14

    As of the December 2010 release of UDK, the GameHud.uc is now named Hud.uc for purposes such as:

    class MyHud extends Hud;

  14. Kien
    February 16th, 2011 at 14:09 | #15

    I get the following error when I try to compile:

    C:\UDK\UDK-2011-01\Development\Src\UDNGame\Classes\UDNHUD.uc(50,0): error : Bad or missing expression in ‘=’

    Can anybody help me with this?

  15. roychr
    February 16th, 2011 at 14:26 | #16

    Kien this is a little vague, copy /paste the entire problematic line, this is a compile issue. It could be related to a bad copy/paste or garbage inserted in the code. There should be an error line mentionned by the compiler, check the specific line with VS, this problem is really common when you start programming.

  16. Kien
    February 16th, 2011 at 14:32 | #17

    class UDNHUD extends MobileHUD;

    DefaultProperties
    {
    }
    /*===================================================
    *
    * TUTORIAL FUNCTION
    *
    * This function will fetch mouse coordinates from the UI
    * Hierarchy in the UIController of the PlayerController
    *
    *
    ===================================================**/
    function vector2D GetMouseCoordinates()
    {
    local Vector2D mousePos;
    local UIInteraction UIController;
    local GameUISceneClient GameSceneClient;

    UIController = PlayerOwner.GetUIController();

    if ( UIController != None)
    {
    GameSceneClient = UIController.SceneClient;
    if ( GameSceneClient != None )
    {
    mousePos.X = GameSceneClient.MousePosition.X;
    mousePos.Y = GameSceneClient.MousePosition.Y;
    }
    }

    return mousePos;
    }

    /*=========================================================
    *
    * PostRender event
    *
    * Use postRender function to define and call all hud drawing
    * routine.
    *
    *
    ===========================================================*/
    event PostRender()
    {
    local UDNPlayerCamera PlayerCam;
    local UDNPlayerController IsoPlayerController;

    super.PostRender();

    //Get a type casted reference to our custom player controller.
    IsoPlayerController = IsometricGamePlayerController(PlayerOwner);

    //Get the mouse coordinates from the GameUISceneClient
    IsoPlayerController.PlayerMouse = GetMouseCoordinates();
    //Deproject the 2d mouse coordinate into 3d world. Store the MousePosWorldLocation and normal (direction).
    Canvas.DeProject(IsoPlayerController.PlayerMouse, IsoPlayerController.MousePosWorldLocation, IsoPlayerController.MousePosWorldNormal);

    //Get a type casted reference to our custom camera.
    PlayerCam = UDNPlayerCamera(IsoPlayerController.PlayerCamera);

    //Calculate a trace from Player camera + 100 up(z) in direction of deprojected MousePosWorldNormal (the direction of the mouse).
    //—————–
    //Set the ray direction as the mouseWorldnormal
    IsoPlayerController.RayDir = IsoPlayerController.MousePosWorldNormal;
    //Start the trace at the player camera (isometric) + 100 unit z and a little offset in front of the camera (direction *10)
    IsoPlayerController.StartTrace = (PlayerCam.ViewTarget.POV.Location + vect(0,0,100)) + IsoPlayerController.RayDir * 10;
    //End this ray at start + the direction multiplied by given distance (5000 unit is far enough generally)
    IsoPlayerController.EndTrace = IsoPlayerController.StartTrace + IsoPlayerController.RayDir * 5000;

    //Trace MouseHitWorldLocation each frame to world location (here you can get from the trace the actors that are hit by the trace, for the sake of this
    //simple tutorial, we do noting with the result, but if you would filter clicks only on terrain, or if the player clicks on an npc, you would want to inspect
    //the object hit in the StartFire function
    IsoPlayerController.TraceActor = Trace(IsoPlayerController.MouseHitWorldLocation, IsoPlayerController.MouseHitWorldNormal, IsoPlayerController.EndTrace, IsoPlayerController.StartTrace, true);

    //Calculate the pawn eye location for debug ray and for checking obstacles on click.
    IsoPlayerController.PawnEyeLocation = Pawn(PlayerOwner.ViewTarget).Location + Pawn(PlayerOwner.ViewTarget).EyeHeight * vect(0,0,1);

    //Your basic draw hud routine
    DrawHUD();
    }

    the error line is 50

  17. Kien
    February 16th, 2011 at 14:33 | #18

    Error line 50 is: super.PostRender(); @Kien

  18. roychr
    February 16th, 2011 at 14:41 | #19

    Okay I asked for the line not the entire source code which I wrote :) I do not have access to my UDK installation and VS 2008 on hand

  19. roychr
    February 16th, 2011 at 14:43 | #20

    Did you tried to get the source files at the end of the chapter, they can be valuable to make a diff between your source and mine.

  20. Game Master
    February 26th, 2011 at 17:36 | #21

    Im getting a null pointer:

    ScriptWarning: Accessed None ‘ViewTarget’
    myHUD Test2.TheWorld:PersistentLevel.myHUD_0
    Function Animus.myHUD:PostRender:044F

    Can you help me ?

  21. Game Master
    February 26th, 2011 at 17:50 | #22

    @Game Master

    The error is being throwed on this line:
    IsoPlayerController.PawnEyeLocation = Pawn(PlayerOwner.ViewTarget).Location + Pawn(PlayerOwner.ViewTarget).EyeHeight * vect(0,0,1);

    Also, when game starts i cant see the player model.

  22. Game Master
    February 26th, 2011 at 18:08 | #23

    @Game Master
    Got it to work with tour precious adivse: “EDIT FROM FEEDBACKS (Jan 02, 2010)” from PART 1 – Creating hte Isometric Camera.

    Do you have any clues why some people get this pawn problem ?

  23. roychr
    February 26th, 2011 at 18:31 | #24

    Game Master I recommend you check for how scaleform works, this is a little outdated.

  24. unikz
    March 15th, 2011 at 19:28 | #25

    Anyway, Epic Games has released an almost new documentation by the name of “Development Gems”. in the “Creating a mouse interface” they’ve told about getting mouse coordinate without using scaleform.

    Creating a mouse interface:
    http://udn.epicgames.com/Three/DevelopmentKitGemsCreatingAMouseInterface.html

    Development Gems:
    http://udn.epicgames.com/Three/DevelopmentKitGems.html

  1. June 10th, 2011 at 08:54 | #1
  2. November 18th, 2011 at 12:35 | #2
You must be logged in to post a comment.