Homework #2

Custom Game with HUD


Description

For this assignment, you will be required to create a new type of Heads-Up Display (HUD) which can be used for Death Match-like games.

The HUD that you see when playing a game is conditional on the type of game that you are playing.  Thus the HUD that you see when playing Death Match is very different from the HUD you see when playing Capture-the-flag.  In order to create a new HUD, one actually has to create a new type of game.  However, if one subclasses from xDeathMatch directly and does not override of the game functionality, then that new game type will be identical to Death Match and be able to use the same Death Match maps (as specified by the "DM-" file prefix on map files).

Imagine a new type of Death Match game in which, your HUD keeps track of the player that has done the most damage to you and helps you locate and kill that player.  This is the premise behind a new type of game called the Grudge Match.  You have a grudge with the player that has hurt you the most.  The Grudge Match is exactly the same as the Death Match, except it will keep a little bit of extra information to help you figure out with whom you have the biggest grudge.  The largest modification to this new game type will be in the HUD which will track the player you have a grudge against.

You will create a new type of HUD, GrudgeHud that is derived from HudBDeathMatch -- the type of HUD that Death Match uses.  Your HUD class should move the health indicator and the ammo count indicator to different positions on the screen.  You may arrange other screen elements as well.  Try to think of arrangements that actually facilitate game play or different ways of representing the game data (for example, displaying  health as a "fuel gage").  Additionally, your HUD should track the player that has done the most damage to you.  To do this, you need to mark the enemy's position on the screen.  For example, you could draw a circle around the enemy player or render a second cross-hair over the enemy.  Your HUD should track your enemy even if she is not currently visible -- this will help you track that player down.

In order to utilize your new HUD, you will create a new game type class, called GrudgeMatch, which subclasses from xDeathMatch.  This is just to enable the new HUD; the only modification you need to make here is that your game should reference your new HUD class.  In order to keep track of how much damage an enemy player has done to you, you must also modify the xPlayer (the type of PlayerController used in Death Matches) class.  You will create a subclass of xPlayer called GrudgePlayer .

You are encouraged to make as radical a departure from the conventional HUD as you can.  Additionally, you are encouraged to think about features for the HUD that will make game play more effective or enjoyable.  For example, it might be a good idea to print out the name of the player with whom the grudge is held.


All about HUDs in UT2004

The HUD class, and its subsequent subclasses, are very complicated.  Not only are they responsible for drawing the heads-up information to the screen, they must quickly do this every tick of the game.  The HUD is an object that runs only on the client machine (and not the server).  Therefore, if you write new functions, it is a good idea to make them simulated.

Rendering the HUD esentially amounts to drawing a picture on an invisible canvas over the screen.  On one side is the user's eyes.  On the other side is the virtual world geometry.  Anything drawn on that canvas, of course, will obscure what is happening in the game.  The HUD has a single Canvas object on which "widgets", "sprites", "tiles", and text are drawn.  The Canvas has a built-in "pen" which, instead of drawing lines, draws objects such as those mentioned above.  For example the following piece of code will draw the words "faster!" to the screen.

simulated function DrawHudPassC (Canvas C)
{
   super.DrawHudPassC(C);

   C.DrawColor = WhiteColor;
   C.SetPos(100, 100);
   C.DrawText("faster!", true);
}

Notice, we had to set the canvas's pen's color and set the pen's position before trying to draw any text.  Nowhere in the DrawText() call is there any mention of color or position.  The canvas has a few member variables that could be useful:

The canvas has one function that you will find very useful: WorldToScreen().  This function takes a Vector of an object in the world and projects that point onto the screen (in two dimensions).  The return value of this function is a Vector in which the X and Y represent locations on the HUD instead of locations in the world.  The Z value of the return vector is not used.

The HUD is actually rendered to the screen in a series of passes, labeled A through D.  Each pass has a corresponding function that gets called automatically when the HUD must be redrawn:

I don't know what all of that means, but I think you should only override passes A and C.  Look to the superclasses for guidance -- see what kinds of things they draw in each pass, if anything at all.

Additionally, the function UpdateHUD() should be overridden to contain code that changes any HUD variables, such as keeping score.  By clumping all variable calculations and updates into one function and the pure drawing code to other functions, the computationaly overhead of actual drawing can be minimized.

Much of what is drawn in the HudBDeathMatch class is specified as member variables and set in the default properties.  Therefore, any of this is readily modifiable.  For example, there are different crosshairs that can be used, which are stored in an array, Crosshair.  Each cross hair is of type SpriteWidget (which is something defined in the low-level game engine -- you will not find a class definition in the UnrealScript library).  In the default parameters, you will find a description of each crosshair and its parameters:

Crosshairs(0)=(WidgetTexture=Texture'Crosshairs.HUD.Crosshair_Cross1',RenderStyle=STY_Alpha,TextureCoords=(X2=64,Y2=64),TextureScale=0.750000,DrawPivot=DP_MiddleMiddle,PosX=0.500000,PosY=0.500000,Scale=1.000000,Tints[0]=(B=255,G=255,R=255,A=255),Tints[1]=(B=255,G=255,R=255,A=255))

This line of code initializes the array member by defining an object.  Each comma-delimited parameter corresponds to a member variable inside the SpriteWidget object.  Here is a run-down of some of the parameters:

You can get lots of good technical information about how to draw and arrange sprites at http://udn.epicgames.com/pub/Technical/HeadsUpDisplayTutorial/ .


Creating a new game type

Creating a new game type is slightly more complicated than just subclassing from xDeathMatch or any other child of GameInfo. Of course, the first step is to write a class that derives from GameInfo.

Once this is done, you must tell UT2004 that that new game type exists.  This is done through initialization files, specifically the .int file.  Every package can have an .int file and what is inside can be used to set class parameters or to tell the UT2003 game engine that there is something special that needs to be done.  In the case of creating a game type, the initialization file tells UT2004 that there is a new type of game and that it should make it an available option in its menus.

This is what your initialization file, Hw2.int , should look like:

[Public]
Object=(Class=Class,MetaClass=Engine.GameInfo,Name=Hw2.GrudgeMatch,Description="DM|Grudge Match|xinterface.Tab_IADeathMAtch|xinterface.MapListDeathMatch|false")

This parameter is telling the UT2004 engine that there is an object that is a type of GameInfo and what package to find it in.  The description tells the engine to use list the "DM" maps (those mape with the "DM" prefix in their names) in conjunction to this game type and that the game type should be listed in the menu options as "Grudge Match".

If you look in xGame.int, you will find the code that initializes the other game types.

When the package is compiled, this info will be used to create a .ucl file. There must be a .ucl file for UT2004 to provide the gametype option in the game menu. Note that things don't quite work right in the STEAM version of UT2004. Specifically, the .ucl is not created quite right. You must manually modify the .ucl file to change the description parameter to be other than "Death Match" or your game will not show up properly in the game menu.


Classes that you should be aware of

GameInfo

The base class of all game types.

HUDType
A string specifying what type of HUD human users will have when they play a given type of game.  You will have to change this default parameter when you create your own game type.
ControllerClassName
A string specifying what type of Controller human players should use when they join the game.  You will have to change this default parameter when you create your own game type.

Hud

The abstract base class for all HUDs.

PlayerOwner
A reference to the PlayerController representing the human user viewing the HUD.
PawnOwner
A reference to the Pawn representing the human user viewing the HUD.
PawnOwnerPRI
A reference to the PlayerReplicationInfo object representing the user.  The PlayerReplicationInfo object holds a lot of information about the player, such as the player's name, score, etc.  It would be useful to check this class out.

HudBase

This is an abstract base class but much more detailed than Hud.  It would be very good to look through this class and see how and where and when certain things are done.

DrawHudPassA (), DrawHudPassB (), DrawHudPassC (), DrawHudPassD (), UpdateHud ()
See above.
SpriteWidget, NumericWidget
Structs that are central to drawing on the HUD.
DrawSpriteWidget (), DrawNumericWidget ()
Important drawing functions.  Unfortunately, they are native (meaning they are written in underlying C code), so you can't see their implementation.

HudBDeathMatch

Type of HUD used specifically by the death match game type.  This is the class you will derive your own HUD class from.  It is reccommended that you spend time familiarizing yourself with all the member variables and member functions of this class.

Controller

The base class of all players, both human and bot.

NotifyTakeHit(...)
This function is called by the Controller's body (a Pawn object) every time the player takes damage.  The parameters that are passes in specify the Pawn that did the shooting and how much damage was done.

PlayerController

The type of Controller that represents a human player.  Only PlayerControllers have HUDs.

myHUD
A reference to the HUD that the human user controlling this player sees.


Files that you will need

In order to complete your project you will need the following files:


Setting up your homework project

You must create a new package in the UT2004 class library.  All the new classes you write should be part of this package.  The name of your package should be "Hw2".

  1. Create a new directory, UT2004\Hw2\Classes.  All your class files should go in this directory.
  2. Open WOTGreal and select "ut2004" -> "Refresh Package/Class Tree" menu option.
  3. Edit UT2004\System\UT2004.ini and add "EditPackages= Hw2" to the appropriate section of the file.
  4. Don't forget to create Hw2.int sothat your new game type will be recognized!

Testing your project

To test your project, run UT2004 and select the "Grudge Match" from the Instant Action menu.  You should be able to choose any Death Match map.  Once the game starts, you will be able to look at the HUD to determine if information is displaying correctly.  Make sure that you get shot by more than one enemy player so that you know whether your HUD is tracking the correct enemy.


What you must turn in

To get credit for your work, you must submit a single UMod file.

The UMod file should contain GrudgeMatch.uc, GrudgeHud .uc, GrudgePlayer.uc, any other UnrealScript classes that you have written, Hw2.int, and Hw2.u .  Your UnrealScript files should unpack automatically into UT2004\Hw2 directory.  Your .u and .int files should unpack into UT2004\System directory.

You should also write a readme.txt which describes exactly what static elements you changed on the HUD and what new dynamic functionalities your HUD has and what I need to do to see it in action (what circumstances do I need to create when I am running your game.  Do I need to shoot somebody or get shot or look at something for a specified amount of time?). The readme.txt should be in your UT2004/Hw2 directory (not UT2004/Hw2/Classes).  Make sure that this file is included in your UMod.