Tuesday, March 8, 2011

D&D BattleMap Using the UDK - The Grid

Building on our previous post, let's add the iconic D&D grid.  This is significantly easier using the Flash UI.  I'll summarize at the end what we had to do to get it to work using just the UDK.

Flash
In Flash, we simply created the grid using the drawing tools.  Vertical and horizontal lines, using a hairline stroke, spaced 20 units apart, covering the entire scene:


In the ActionScript of our Actions layer, we added a couple of functions that will be called by UnrealScript.  The first will show/hide the grid, the second will scale it.  We hide the grid initially to make positioning easier:
function GridToggle()
{
 GridInst._visible = !GridInst._visible;
}

function GridZoom(Param1:Number)
{
 GridInst._xscale = GridInst._xscale + Param1;
 GridInst._yscale = GridInst._xscale;
 GridInst._x = stage.width*.5 - GridInst._width*.5;
 GridInst._y = stage.height*.5 - GridInst._height*.5;
}

GridInst._visible = false;

From now on, whenever you make a change to the HUD you must:
  1. Publish the movie
  2. Open the UDK Editor and reimport the movie into your package using the Content Browser.
  3. Save the package
  4. Copy the package from the UDKGame\Content\Misc folder to the UDKGame\CookedPC folder.
Since we haven't actually referenced the package from the BM-Necropolis.udk map that we're testing with, the Unreal Frontend doesn't include it when it Cooks.  Believe me, I've lost a lot of time trying to figure out why my ActionScript functions weren't being called when I simply forgot step 4 above.

BattleMapGfxHud.uc
Add two wrapper functions for the ActionScript functions above:
function CallGridToggle()
{
 ActionScriptVoid("GridToggle");
}

function CallGridZoom( float Param1 )
{
 ActionScriptVoid("GridZoom");
}

BattleMapPlayerController.uc
All we need to do here is reference a new Input class that we're going to create to interpret keyboard/mouse commands.  Add this to the DefaultProperties section:
 InputClass=class'BattleMap.BattleMapPlayerInput'

BattleMapPlayerInput.uc
This is a new class that will call our wrapper functions based on input events.  I arbitrarily chose a delta of 5.0% when scaling the grid:
class BattleMapPlayerInput extends UTPlayerInput within BattleMapPlayerController;
var float GridZoomDelta;
exec function BMGridToggle()
{
 BattleMapHUD(myHUD).CrossHairMovie.CallGridToggle();
}

exec function BMGridZoomIn()
{
 BattleMapHUD(myHUD).CrossHairMovie.CallGridZoom(-GridZoomDelta);
}

exec function BMGridZoomOut()
{
 BattleMapHUD(myHUD).CrossHairMovie.CallGridZoom(GridZoomDelta);
}

DefaultProperties
{
 GridZoomDelta = 5.0f
}

I know.  We seem to have a lot of functions just calling each other.  Here's the flow:

Input Event > PlayerInput > GFxMoviePlayer > ActionScript

DefaultInput.ini
Lastly, we need to specify what keyboard/mouse events will trigger those actions.  In UDKGame\Config\DefaultInput.ini, scroll all the way down past "Editor Bindings".  Add a new section:
;-------------------
; BattleMap Bindings
;-------------------
.Bindings=(Name="BMGridToggle",Command="BMGridToggle")
.Bindings=(Name="BMGridZoomIn",Command="BMGridZoomIn")
.Bindings=(Name="BMGridZoomOut",Command="BMGridZoomOut")
-Bindings=(Name="G",Command="GBA_SwitchToBestWeapon")
-Bindings=(Name="MouseScrollUp",Command="GBA_PrevWeapon")
-Bindings=(Name="MouseScrollDown",Command="GBA_NextWeapon")
.Bindings=(Name="G",Command="BMGridToggle")
.Bindings=(Name="MouseScrollUp",Command="BMGridZoomOut")
.Bindings=(Name="MouseScrollDown",Command="BMGridZoomIn")

This is doing three things:
  • Maps Input Binding commands with UnrealScript (PlayerInput) functions (I just happened to have named them the same)
  • Unbinds previously specified inputs from their default commands
  • Binds those inputs to our new commands
Essentially, we use the "G" key to toggle the grid and the mouse wheel to scale the grid.

The result is:



For reference, to implement this just using the UDK and UnrealScript, we had to:
  • Paint a grid texture
  • Model a grid mesh (essentially, a 2D plane)
  • Create a BattleMapGridActor in UnrealScript which instantiated the grid mesh, applied the texture, and included several functions for moving ("scaling" by moving up and down, and positioning horizontally)
  • Include numerous functions in BattleMapPlayerInput for spawning, moving and snapping the grid
It was a huge amount of code, compared to the few changes above.  I wonder what else we can move from UnrealScript to Flash...

4 comments:

  1. Where does the flash file come in? How do you associate the swf file with our package? I have top-down working, but no mouse movement or character rotation.

    ReplyDelete
  2. The flash file is referenced in BattleMapGfxHud.uc. (See the previous post.) That shows how to connect the mouse's movements in ActionScript to UnrealScript.

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. What exactly is in your HUD? Is it just the BIG mouse pointer and the line from the Pointer and the Player? Or is it the Green Information system up in the top left of the Screen? Or both?

    ReplyDelete