Monday, 24 February 2014

Finite State Machine for handling input.

This is maybe obvious but for whatever reason I struggled to work out how to handle a simple left click of the mouse.  The problem being that a single left click could mean many different things depending what state your in.  Take selecting a unit as an example, it could be interpreted as, 1) select this unit 2) deselect current and now select new unit 3) move to 4) attack.  etc.  Keeping track of the state you're in then is vital, and I'm using an enum which is perfect for this.

enum pickingState { nothing, unitPicked, cityPicked, moveTo}
pickingState curPickingState = pickingState.nothing;

The next step was breaking down the methods for moving between states.  To go from (nothing --> unitPicked) we'll need a Select() method.  And likewise, to get back to nothing selected (unitPicked --> nothing)we need a DeSelect() method.  For the raycasting itself, Unity provides excellent collision checking for that, mine looks something like this.

//picking code looks something like this
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;

//left click
if (Input.GetMouseButtonDown(0) && Managers.OverGUI == false)
{
  //did we hit something
  bool hitResult = Physics.Raycast(ray, out hit, 100f);


  switch (curPickingState)
    {
      case(pickingState.nothing):
        Debug.Log("nothing selected state");
        handleSelection(hitResult, hit);
        break;
      case(pickingState.unitPicked):
      case(pickingState.cityPicked):
        handleDeselection(hitResult, hit);
        break;
      case(pickingState.moveTo):
        Debug.Log("in moveto state");
        handleMoveTo(hitResult, hit);
        break;

   }
}

private void handleSelection(bool hitResult, RaycastHit hit)
{
//bring up gui elements here
}

private void handleDeselection(bool hitResult, RaycastHit hit)
{
//fade out gui elements here & call the picking code again
}

private void handleMoveTo(bool hitResult, RaycastHit hit)
{
//set target
}


Using a switch() statement with enums is a perfect match. as you can see, and neater than a big ol' pile of if() else() statements.  An element that may be a little confusing is calling handleDeselection() if we have a unit picked already.  This was a minor eureka moment for me, and when I worked out I neeeded to seperate out selection and deselection correctly.  So if the player has decided they wanted to select a different unit when one is already selected, you first need to correctly change back to the nothing selected state, then we simple call the picking code again and it will correctly interpret us back into the correct state.  It simple be the player clicked off map to deselect entirely, which would be hitReseult = false.

The last little piece is the Managers.OverGUI bool.  Unity handles interface input in the OnGUI() method for things like buttons etc.  You don't want to have clicks going through the GUI into the world and so for that we need to check each loop if the cursor is over a GUI element, and if so we don't want to handle any 3d world picking and instead let our GUI code handle it instead.  

I'm sure much of the above is second nature to some programmers but I really struggled getting all the bits and pieces working together correctly.

Monday, 17 February 2014

Little by little, turn by turn.

I developed the 'battle' system a little more.  I was getting mired in indecision but I eventually got a version that I think will work.  Better to get something up and running to get a sense of how it all fits together, and there still more pieces to do until I can get a better overall picture.  Tortured metaphors done, here's a screenshot.

xna protoype with number revealed

prototype in unity with icons

The battlefield will consist of a front line and a rear line.  So I was having trouble working out how support units would fit into the mix, like archers or catapults, and using a second line that gives bonuses to the front line helps works them in. The art is just programmer placeholder stuff for now.  It ties into another requirement I gave myself, which is to have the same art/representation on the battlefield screen and on the main map.  If you have a battle screen that is wildly different you have double the art work to do...and I'm probably going to struggle with one lot as art is not my forte.  I'm using a similar size and shape to Total War as I really like their implementation.  In researching I found the artist who did the great iconography for Rome Total War II.  If I got anything close to that I'd be very happy.

ui thoughts
I also went round in a circle on the UI.  I tried some little pixel art decorations but ultimately I think I prefer the simple red and black motif.  Altering the sprite font in Unity is maybe possible but not worth the hassle as far as I'm concerned.  There's certainly been a trend towards simpler/minimalistic interfaces in games, and I'm certainly a fan of that style.  I mostly just want the information to be clear and easy to read.