Development

Dungeon Ho!: Unity – Art Blog #1

‘sup.  We’re breaking from our usual content format to give you a sneak peek at the game’s graphics overhaul, which is currently in progress.  The first step is to expand the game’s tileset to allow for a more richly detailed map.  You can see the bulk of the work being done here in the new Tomb/Dungeon environment tiles.

Tombs Tileset

-Steve

Categories: Artwork, Development, Dungeon Ho! | Leave a comment

Dungeon Ho!: Unity – Dev Blog #12

Welcome back, Item Picker-Uppers!  Today we’re finally going to look at the PickUpItemsDialog and how to leverage all of the things we’ve done so far in order to get items from the map into the player’s inventory, and back again.  But first, we need to know how to trigger this sort of thing from a keypress.

Do you remember the DungeonMaster class?  That’s the one that handles player keypresses.  I’ve done a lot of things to this class since we’ve seen it last, but the thing we’re most interested in is the collectInput() method:

// Primary keyboard driver - Queries Input object and puts commands in queue.
    public void collectInput()
    { 
        UIScreen topmostScreen;

        if (uiManager == null)
            uiManager = dungeon.getGame().getUIManager();

        topmostScreen = uiManager.getTopmostUiComponent();

        // Hotkeys
        if (Input.GetKeyDown(KeyCode.P))
            addCommand(new PassCommand(dungeon.getPlayer()));

        // Hotkeys for particular screens ////////////////////////////////////////
        if (topmostScreen != null)
        {
            // We don't want the user to be able to operate stuff "under"
            // any currently-displaying UI components.  IE, they shouldn't
            // be able to move with the character screen up.
            topmostScreen.handleHotkey();

            if (Input.GetKeyDown(KeyCode.Escape))
                topmostScreen.hide();

            return;
        }

        // Screen activation /////////////////////////////////////////////////////
        if (Input.GetKeyDown(KeyCode.I))
            uiManager.showUI(UIManager.INVENTORY_SCREEN);

        if (Input.GetKeyDown(KeyCode.C))
            uiManager.showUI(UIManager.CHARACTER_SHEET);

        if (Input.GetKeyDown(KeyCode.G))
            uiManager.showUI(UIManager.PICK_UP_ITEMS);

        if (Input.GetKeyDown(KeyCode.Q))
            uiManager.showUI(UIManager.QUEST_LOG);

        // Directionals //////////////////////////////////////////////////////////
        if (Input.GetKeyDown(KeyCode.LeftArrow))
            addCommand(new MoveCommand(dungeon.getPlayer(), MoveCommand.WEST));

        if (Input.GetKeyDown(KeyCode.RightArrow))
            addCommand(new MoveCommand(dungeon.getPlayer(), MoveCommand.EAST));

        if (Input.GetKeyDown(KeyCode.UpArrow))
            addCommand(new MoveCommand(dungeon.getPlayer(), MoveCommand.NORTH));

        if (Input.GetKeyDown(KeyCode.DownArrow))
            addCommand(new MoveCommand(dungeon.getPlayer(), MoveCommand.SOUTH));

        // TODO: Read abstract game actions
        // TODO: Read mouse/clicks
    }

Fun stuff!  The first part of the method assigns a reference to the pre-existing UIManager so that we have something to work with, assuming we haven’t already done so, and the next bit determines the topmost UI Canvas so that we can feed it keypresses.  Basically, if there’s a screen already active, it should get all the keys and then exit the method.  If there isn’t a UI Canvas visible, then we can assume a keypress will be one of the player commands… such as picking up an item (…see what I did there?).

As you can see, we’ll trigger the PickUpItemsDialog with the ‘G’ key on the keyboard – and eventually the mouse, when we get that far.  But that’s a post for another time.

If you recall from last time, we can simply call the showUI() method of the UIManager to activate the relevant canvas.  In this case, it’s the UIManager.PICK_UP_ITEMS canvas.

Speaking of which, let’s take a look at it;

DHU 31

I’ll leave it as an exercise to you, the reader, to recreate this dialog in the Unity editor.  It’s basically just three buttons and a ScrollView.  Each element of the ScrollView is a Prefab denoting an entry in the list, which is currently just a Text label.  We’ll look at slot prefabs in more detail once we take a deep dive into the inventory screen.

public class PickUpItemsDialog : UIScreen
{
     public GameObject dungeon;
     public GameObject contents;
     public GameObject slotPrefab;
}

At its base, the PickUpItemsDialog is a UIScreen, the abstract class we looked at last time.  It has public slots for the dungeon, its own contents (the GameObject representing the ScrollView’s content object), and its object Prefab, which – as previously explained – is simply a Label.  The beauty of using a Prefab here is that we can design a new slot object, perhaps with icons or something, and swap it out with no extra effort on our end apart from maybe having to change a line or two of code to not reference the Label if we decided to delete it.  Simply drag and drop the relevant game objects into these slots in the Editor and away we go.

Next up is the overridden method, prepare():

public override void prepare()
{
     Vector2Int playerPos;

     base.prepare();

     playerPos = player.getPosition();

     populateList(dungeon.GetComponent<Dungeon>().getAllEntitiesOnTile(playerPos.x, playerPos.y));
}

We’ll need the player’s position, so we grab it after we call the base prepare() method (so that we have a player to grab it from, among other things).  Then we populate the list of items based on the objects we get from the dungeon object.  (Since the dungeon is a GameObject, we get a reference to its Dungeon component first, since that’s where all of the data is.)

private void populateList(List<Entity> entsOnTile)
{
     clearcontents();

     if (entsOnTile != null)
     {
          foreach (Entity entity in entsOnTile)
          {
               if (entity != player)
                    createEntitySlot(entity).transform.SetParent(contents.transform);
          }
     }
}

private void clearcontents()
{
     foreach (Transform text in contents.transform)
     {
          GameObject.Destroy(text.gameObject);
     }
}

populateList() populates the contents object with slot prefabs based on the items passed into the method.  First it removes all of the existing items from the list, then creates a new Slot prefab for each item and attaches it by parenting it to the contents object.  The slot prefab is created in the createEntitySlot() method, which spawns a new instance of the Slot prefab and sets its text to the name property of the passed-in item.

private GameObject createEntitySlot(Entity item)
{
     GameObject slot = Instantiate(slotPrefab);

     PickupSlot slotComponent = slot.GetComponent<PickupSlot>();

     slot.name = slot.name.Replace("(Clone)", "");

     slotComponent.pickupDialog = this;

     slotComponent.setItem(item);

     slot.GetComponentInChildren<Text>().text = item.name;

     return slot;
}

Each SlotComponent (…which we’ll look at next) contains a reference to the dialog, as well as the Item object it’s attached to.  We need both of these objects so that it can manipulate the dialog and tell the PickUpCommand which item it should run on when the user clicks the relevant button.

Speaking of the PickupSlot Prefab object, it has the following script attached;

public class PickupSlot : MonoBehaviour
{
     private Color unselectedColor = Color.black;
     private Color selectedColor = Color.green;

     private Entity item;

     private bool selected;

     public PickUpItemsDialog pickupDialog;

     public void setItem(Entity i)
     {
          item = i;
     }

     public Entity getItem()
     {
          return item;
     }

     public void toggleSelected()
     {
          selected = !selected;

          if (selected)
               gameObject.GetComponentInChildren<Text>().color = selectedColor;
          else
               gameObject.GetComponentInChildren<Text>().color = unselectedColor;
     }

     public bool isSelected()
     {
          return selected;
     }
}

The most interesting method is the toggleSelected() method, which changes the color of the Prefab based on whether or not it’s selected.  When the user clicks on an item in the Pickup dialog, we want to highlight it/de-highlight it so that it’s included (or not) in the items that are to be picked up.  Therefore, each slot has a boolean that determines if it’s been selected or not.

So, how does all of that work?  Well, it requires an Event Trigger.  We define one and then attach it to the PickupSlot prefab, like so;

public class PickUpItemEventTriggerHandler : EventTrigger
{
     public override void OnPointerClick(PointerEventData data)
     {
          PickupSlot slot = gameObject.GetComponent<PickupSlot>();

          slot.pickupDialog.onItemSelected(slot);
     }
}

The OnPointerClick() method is automagically called when the Prefab is clicked, passing in the Event data of the PointerEvent that was generated by said click.  The event was generated by the gameObject the script is attached to, so we simply grab the PickupSlot script component of that gameObject, then call its attached pickupDialog’s onItemSelected() method, passing in that slot component.  We do this because the dialog may have to do some bookkeeping relevant to itself when the slot is selected, and we don’t want to tangle that code up in here.  Keeps everything neat.

The onItemSelected() method looks like this;

public void onItemSelected(PickupSlot slot)
{
     slot.toggleSelected();
}

And finally, we use the Unity Editor to call either pickUpSelectedItems() or pickUpAllItems() on the PickUpItemsDialog when the relevant button has been clicked.  pickUpAllItems() simply loops through all of the slots attached to the ScrollView and generates a PickUpItemCommand for each one, so we won’t bother to look at it.  We’ll look at pickUpSelectedItems() instead.

public void pickUpSelectedItems()
{
     DungeonMaster dm = dungeon.GetComponent<Dungeon>().getDungeonMaster();

     PickupSlot slot;

     foreach (Transform child in contents.transform)
     {
          slot = child.gameObject.GetComponent<PickupSlot>();

          if (slot.isSelected())
               dm.addCommand(new PickUpItemCommand(player, slot.getItem()));
     }

     hide();
}

As you can see, the foreach loop checks all of the contents’ object’s children to see if their PickupSlot component is selected.  If it is, a new PickUpItemCommand – which we saw way back when we looked at Command objects – is generated with the player as the source and the Item entity linked to the slot as the target.  The DungeonMaster object then processes all of these commands.

Could we have simply added the selected items to a separate list and then looped through that list and picked up all the items?  Sure, we could have.  Whether or not that’s a better solution is left as an exercise to the reader.  Finally, though, we call hide() on the pickupDialog, which hides it from view until we’re ready to pick up more items.

There’s one final note, here; I’ve implemented a maximum length on the player’s command queue, so if there are more items in the tile than slots in the queue, the player will only be able to pick up as many as there are free slots.  So for example, if the queue’s maximum length is 10 and there’s 20 objects in the tile, the player will only be able to pick up 10 items with one click, no matter how many they select in the dialog.

Well, that certainly was a big one! (obligatory “That’s what she said” joke here.) Hope it was worth the wait!  We’ll be using a similar model for other UI dialogs, especially the Inventory screen.  Tune in next time when we do just that, which will give us the ability to drop items back into the dungeon.

– Steve

Categories: Development, Dungeon Ho!, Unity | Leave a comment

Dungeon Ho!: Unity – Dev Blog #11

Welcome back, my long-lost readers!  It’s been way too long.  You’re looking well.  I wish I could say I’ve been hard at work on the ‘Ho!, but that would be a lie.  You know how it is.  Things happen.

Anyway… I’m here now, and that’s all that matters.  When last we met, I promised y’all that we would take a look at the UIManager and its various related classes, which is a convenience that I whipped up in order to manage all of the various menu screens and dialogs needed to make the game work.

But first, let’s talk design.  The UIManager class is basically a collection of methods that tracks, keeps reference to, and handles various functionality – such as hiding and showing – screens and dialogs from within the game.  These various UI components are, as you may well know, Unity Canvas objects with a script attached, appropriately named UIScreen.

Before we carry on with that, I noticed something that’s been happening ever since I started using text blocks to format my code examples.  Specifically, that the left and right angle brackets (< and >) in my code are getting “swallowed” by the HTML parser, and I can’t be assed to go in and correct every single instance of it.  If it affects anything important, like if-then logic, I’ll deal with it.  Otherwise, the bulk of the cases are List object declarations; so if you see something like List myList, assume I’m really trying to say List<Class> myList and roll with it.  You’re smart, you should be able to figure out what the relevant class is supposed to be.  Got it?  Good.  Let’s continue.

In Dungeon Ho! parlance, a UIScreen is basically a Unity Canvas with some additional functionality attached via a script, like so;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIScreen : MonoBehaviour {

    protected Player player;

    // Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}

    // Override this method to prepare the screen for viewing.
    public virtual void prepare()
    {
        if (player == null)
            player = GameObject.Find("Dungeon").GetComponent().getPlayer();
    }

    public void show()
    {
        // Yes, this doesn't make sense - but if the prepare(); method
        // alters the contents of the UI, its positions/dimensions/etc. 
        // won't get re-calculated if it's not active.
        gameObject.SetActive(true);

        prepare();
    }

    public void hide()
    {
        gameObject.SetActive(false);
    }

    public void toggle()
    {
        if (gameObject.activeSelf)
            hide();
        else
            show();
    }

    public bool isShowing()
    {
        return gameObject.activeSelf;
    }

    public virtual bool handleHotkey()
    {
        return false;
    }
}

The most interesting bits of the code are in the prepare() method.  This method is called before the UIScreen is about to be shown, and is where each subclass initializes its UI components with the relevant data, as we’ll see in a future post.  It also makes sure that there’s a reference to the game’s Player object, by explicitly caching a reference to one if it can find it.  (ProTip:  If it can’t find it, you broke the game somehow.  There will always be a player object for it to find.)

Why do we do this, rather than simply go into the Unity UI and drag our Player into the relevant slot?  Because it’s one line of code that does the same thing for every UI component and I can’t be bothered to do it the other way.  Maybe if I had a UI guy wiring up these dialogs for me, I’d care.  Rule #1 of solo projects, it’s okay to cut corners and not always follow “best practice” – which is usually only “best” because engineers love to follow the herd.  Mini-rant over.

Also note that the show() method puts what we just described into practice, by calling the prepare() method after setting the gameObject (IE, the UI component this script is attached to) active.  Why don’t we call prepare() first?  Because one of the first “features” I discovered when (logically) implementing it that way is that Canvases don’t update their UI components when they’re not active, so trying to set the data of, say, a ScrollContainer in the Canvas will simply fail.  (Hey, that’s in the code comments – whaddaya know.  Rule #2 of solo programming, always document this stuff when you find it… especially when you’re old and your memory is going, like I am – and mine is.)

OK, enough about UIScreen.  We’ll see how to actually make one in a future blog post.  Let’s look at UIManager next.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIManager
{
    public const int INVENTORY_SCREEN   = 0;
    public const int CHARACTER_SHEET    = 1;
    public const int PICK_UP_ITEMS      = 2;
    public const int QUEST_LOG          = 3;

    private List uiComponents;

    public UIManager(GameObject ui)
    {
        uiComponents = new List();

        foreach (Transform canvas in ui.transform)
        {
            uiComponents.Add(canvas.gameObject.GetComponent());
        }

        Debug.Log("UIManager found " + uiComponents.Count + " UI components.");
    }

    public void showUI(int id)
    {
        uiComponents[id].show();
    }

    public void hideAll()
    {
        foreach (UIScreen screen in uiComponents)
        {
            screen.hide();
        }
    }

    public void hideUI(int id)
    {
        uiComponents[id].hide();
    }

    public void toggleUI(int id)
    {
        uiComponents[id].toggle();
    }

    public bool isShowing(int id)
    {
        return uiComponents[id].isShowing();
    }

    public UIScreen getUiComponent(int id)
    {
        return uiComponents[id];
    }

    public UIScreen getTopmostUiComponent()
    {
        UIScreen top = null;

        foreach (UIScreen screen in uiComponents)
        {
            if (screen.isShowing())
                top = screen;
        }

        return top;
    }
}

First thing you’ll notice is a bit of laziness; I loop through the passed-in GameObject (…which is the top-level scene node that I have parented all of my UI canvases to) and grab references to them, putting them into a local List, which is indexed by constants.  (I could also have made those constants Strings and used a Dictionary.  Either-or.)

Now, whenever I want to reference a particular UI component, I just use its index constant.  Like so;

uiManager.hide(UIManager.QUEST_LOG);

…and speaking of, the main Game object instantiates an instance of UIManager in its own Unity-supplied start() method;

uiManager = new UIManager(GameObject.Find("UI").gameObject);

Note that I pass in the GameObject named “UI”, as previously described.

Pretty straightforward, eh?  Tune in next time when we look at the Inventory Screen, how it’s derived from UIScreen, and how it’s wired up to the Player’s inventory.  Once that’s out of the way, we’ll intercept some mouse clicks and be able to pick up and drop items… finally!

– Steve

Categories: Development, Dungeon Ho!, Unity | Leave a comment

Dungeon Ho!: Unity – Dev Blog #10

Welcome back, Item Hoarders! Today we’re going to finish looking at the basics of picking up an item, as well as the structure of the Inventory object. Once we know how these classes interact, we can start piecing together the PickUpItems dialog. And that’s where the fun begins.

But first, as promised, here’s the actual code for getting all items on a particular tile in the dungeon.  It’s really, really complicated.

public List getItemsOnTile(int x, int y)
{
   List itemsOnTile = null;

   Vector2Int position;

   foreach (Item item in items)
   {
       position = item.getPosition();

       if (position.x == x && position.y == y)
       {
           if (itemsOnTile == null)
               itemsOnTile = new List();

           itemsOnTile.Add(item);
       }
   }

   return itemsOnTile;
}

Okay, I lied. It’s not. Remember that the dungeon contains a List of all of the Items in it.  All we do is loop through that list and add any item in the correct tile (denoted by its position property) to the list of items on that tile that we’re building, then we return that list.

That’s not all, though; remember that we also want to get any corpses on the tile, because although those aren’t items – merely mobs with the CORPSE flag set – we need to be able to pick them up, too.  So we actually use a slightly different method, getAllEntitiesOnTile();

public List getAllEntitiesOnTile(int x, int y)
{
    List entitiesOnTile = null;

    Vector2Int position;

    foreach (Entity entity in entities)
    {
        position = entity.getPosition();

        if (position.x == x && position.y == y)
        {
            if (entitiesOnTile == null)
                entitiesOnTile = new List();

            entitiesOnTile.Add(entity);
        }
    }

    return entitiesOnTile;
}

As an aside, I also have a few other methods along these lines, including getMobOnTile()getSolidEntityOnTile(), and probably a few others.  You never know when they’ll come in handy!

OK, so now that we can query the tile for its contents (and, in theory, send a PickUpItemCommand for one of them), what actually happens when the command is processed?  Here’s the command itself.

public class PickUpItemCommand : MobCommand
{
    private string successMessage = "{0} picked up the {1}.";
    private string failureMessage = "{0} was unable to pick up the {1}.";

    public PickUpItemCommand(Entity src, Entity targ)  : base(src, targ)
    {
    }

    public override void execute(Dungeon dungeon)
    {
        Mob srcMob = source as Mob;

        string result;

        if (srcMob.pickUpItem(target))
        {
            target.detachFromDungeon(dungeon);

            result = string.Format(successMessage, source.name, target.name);
        }
        else
            result = string.Format(failureMessage, source.name, target.name);

        Debug.Log(string.Format("{0} {1}", ToString(), target.ToString()));

        Messenger.report(result);
    }

    protected override void determineTurnOrder()
    {
        Mob srcMob = source as Mob;

        turnOrder = srcMob.getBaseInitiative() - 5;
    }
}

Ignore determineTurnOrder() for now, as we haven’t discussed combat yet.  (I told you I was much further along than the blog would indicate!)  We’re mainly interested in the execute() method, here – which, if you recall, is called by the Dungeon object every time a turn is advanced.

The first thing the method does is tell the source of the command (that is, the entity that initiated it) to attempt to pick up the target of the command, which is the item itself.  The mob’s pickUpItem() method – which we’ll look at next – returns either true or false depending on whether the mob could actually pick up the item or not.  This, obviously, can fail if the mob is already carrying too much (or for any other reason we decide to implement).  If the method returns true (success), we detach the object from the dungeon (which is a fancy way of saying we remove it from the dungeon’s item and entity lists, since it’s now a part of the mob’s inventory instead), and assign the success string to the variable that the Messenger console is going to output once the command fully resolves.  If the mob’s pickup method returns false instead, we output the command’s failure message.  You can ignore the Debug.Log() statement.  That’s purely for debugging purposes; I currently have every command output all of its data to the Unity console so I can keep an eye on what it’s actually doing when it executes.

So far, so good?  The next step is to look at what happens when the Mob attempts to pick up the item in question.  Let’s move on over to the Mob class and check out the pickUpItem() method.

public bool pickUpItem(Entity item)
{
    if (canPickUpItem(item))
    {
        inventory.getContents().Add(item);

        item.setParent(gameObject);

        item.setOwner(this);

        item.enable(false);

        return true;
    }
    else
        return false;
}

First thing we do is check to see if the mob can actually pick up the item.  If they can, we add the item to the mob’s inventory.  Next, we set the item’s parent to that of the Mob’s gameObject.  Remember that the gameObject property of any Unity script component is the Unity gameObject that the script is attached to.  Changing the item’s parent to the Mob’s gameObject, therefore, moves the item directly under the Mob in the Unity scene tree.  This gives us a quick and dirty way of eyeballing what a mob is carrying within the Unity editor.  We also set the item’s owner (a property unique to our own Entity class) to the Mob.  This allows us to know which Mob owns the item without having to reference the gameObject and then query the Mob component.  It’ll also come in handy when we write our save/load routines, since gameObjects aren’t directly serializable and our own Entity data will be.  (As you can imagine, this was how object references were handled in the original Java code, which didn’t have a convenient scene graph for us to play with.  It’ll come in handy here as well, which is why I’m keeping it.)

Finally, we disable the item so that Unity doesn’t render it.  The enable() method is literally just a wrapper around a call to gameObject.setActive(), which looks cleaner.

Before we move on, here’s the setParent() method, so you can see how the Unity parenting is done.

public void setParent(GameObject obj)
{
    gameObject.transform.parent = obj.transform;
}

Next, let’s look at the mob’s canPickUp() method.  It contains the logic that determines if the mob can actually pick up the item.

public bool canPickUpItem(Entity item)
{
    return inventory.getTotalWeight() + item.getWeight() <= getMaxCarryWeight();
}

All we do here is check to see if the current weight of the mob’s inventory, plus the weight of the item, would exceed the mob’s maximum carry weight.  If it does, we don’t allow the mob to pick up the item (by returning false).  If it doesn’t, we return true instead.  We could easily extend this method with additional logic if we needed to.

Finally, let’s look at a select portion of the Inventory class; specifically, the bits that allow us to have an inventory!  Every mob has an instance of this class.

public class Inventory
{
    private List<Entity> items;

    public Inventory()
    {
        items = new List();
    }

    public float getTotalWeight()
    {
        float totalWeight = 0;

        foreach (Entity entity in items)
        {
            totalWeight += entity.getWeight();
        }

        return totalWeight;
    }

    public List getContents()
    {
        return items;
    }
}

The inventory consists of a List of Entity objects – not Items, because remember, the player can pick up Mob corpses as well, which are derived from Mob, not Item – as well as some handy methods to query the contents of the inventory as well as tally up the weight of everything in it.  As you can imagine, this class will get more complicated once we start equipping items… but for now, this is all we need in order to let the mob carry stuff.

Whew, that was a lot!  Tune in next time when I take a brief detour into the DropItemCommand, showing you how to do this process in reverse, and then we finally start to explore the UI system and how to wrap all of this process into a handy dialog component.

-Steve

Categories: Development, Dungeon Ho!, Unity | Leave a comment

Dungeon Ho!: Unity – Dev Blog #9

Welcome back, flag flippers! Rather than leave you all hanging, I decided to follow up yesterday’s dev blog with a short detour into the wonderful world of boolean operators. This is how the Entity flags are stored, so it’s a pretty useful topic for the aspiring Roguelike programmer. I first learned how to do this by browsing the Quake II source code nearly twenty(!) years ago, but obviously the technique goes back way farther than that.

As I’m sure you already know, numbers are stored in variables as binary values, which means that they’re converted from base 10 (1, 2, 3, 4, etc…) to base 2 – so, ultimately, they’re represented as strings of 0’s and 1’s.  Boolean operations let us act on these variables at the bit level (IE, on the 0’s and 1’s themselves).  We can use this trick to store a bunch of values in one single integer (or double, if you need more) that we’d normally need a stack of boolean variables to represent.

The trick is, each bit’s position in the integer is equivalent to the number 2 raised to a particular exponential value.  For example, 20 is 1. 23 is 8.  When you convert those resulting numbers to their binary representations… they just so happen to place a single 1 into the integer at the exact position of the exponent (starting with zero, of course; computers are funny that way).

For example, as I just said, 20 is 1.  1 in binary is, obviously, 1 – which means that if we were to represent the other 31 bits in the integer (assuming a 32-bit integer) with zeroes, we’d have:

00000000000000000000000000000001

23 is 8.  8 in binary is 1000.  So, once again, padding that out with zeroes we have;

00000000000000000000000000001000

Get the picture?  If we look at each ‘1’ in our integer as a separate flag, we can store 32 different flags in a single number!

…and that’s what we do.  Here’s the EntityFlags.cs file.

public class EntityFlags
{
    public static int EQUIPPABLE                 = (int)Mathf.Pow(2, 0);
    public static int CURSED                     = (int)Mathf.Pow(2, 1);
    public static int CORPSE                     = (int)Mathf.Pow(2, 2);
    public static int UNDEAD                     = (int)Mathf.Pow(2, 3);
    public static int NO_DROP                    = (int)Mathf.Pow(2, 4);
    public static int EQUIPPED                   = (int)Mathf.Pow(2, 5);
    public static int TWO_HANDED                 = (int)Mathf.Pow(2, 6);
    public static int CONSUMABLE                 = (int)Mathf.Pow(2, 7);
    public static int REQUIRES_AMMO_ARROWS       = (int)Mathf.Pow(2, 8);
    public static int REQUIRES_AMMO_BOLTS        = (int)Mathf.Pow(2, 9);
    public static int STACKABLE                  = (int)Mathf.Pow(2, 10);
}

Note that I could have done the math myself and simply defined the values as their actual base 10 equivalents (eg. set the value of CURSED to 2), but why bother?  That’s why we have computers.  They don’t make mistakes.

So, how do we set the flags?  Well, remember your boolean functions.  If you OR a 0 with a 1, you get 1.  So if we take a flag variable (such as the flags member of our Entity class) and simply OR it with one of the flag constants, if the flag bit isn’t already flipped, it will be.  For example;

Say our entity.flags variable is currently set to some binary value;

00110001110000000000000000011000

…and we want to set the CORPSE flag (22, or 4 – which is 100 in binary).  If we OR the two variables together (the relevant bits have been bolded)…

00110001110000000000000000011000 - (original number)

00000000000000000000000000000100 - (flag value)

00110001110000000000000000011100 - (result)

See what happened?  The 0’s in the flag’s value didn’t affect the already-set 1’s in the original variable because 0 OR’d with 1 is already 1.  And since the original value had 0 in the relevant position, ORing it with the 1 from the flag flipped the bit to 1.

Sorry to belabor that point but sometimes it takes a while for people to wrap their heads around it.  I know it sure did for me back in the day.

Anyway, now that we can do that, unsetting a flag is just as easy.  We just use an “exclusive OR” instead of the “inclusive OR” that we used to set it.  The exclusive OR only outputs 1 if both bits are different, so if we OR the flag with the variable and that bit is already set, then both elements of the OR are 1, so the resulting bit gets flipped back to 0.

And finally, we can see if a flag is set by ANDing the flag with the variable, since AND only produces a 1 if both bits are the same.  So ANDing the flag will produce a 1 in the flag’s bit position if the flag is set (since both the flag and the bit already at the flag’s position are both 1) and 0’s everywhere else because the 0’s in the flag ANDed with the existing bits in the variable will “clear” all of the other bits; 0 AND 0 are still 0, while 0 AND 1 are also 0.  That means that if the flag had been set, the result of the AND will be a non-zero value (since we’re left with the single flipped bit) and a 0 if it hadn’t (since all the bits have been ANDed to 0).

Clear as mud?  Fortunately, the code to handle these three operations is dead simple to implement. Here are the relevant functions from the Entity class. Naturally, the variable that stores the set flags is called flags.

public void setFlag(int flag)
{
    flags |= flag;
}

public void clearFlag(int flag)
{
    flags ^= flag;
}

public bool hasFlagSet(int flag)
{
    return ((flags & flag) != 0);
}

 

That’s all for today.  Tune in next time for a quick dive into the dungeon’s entity-querying methods and a brief intro to the UI system, which will be necessary to understand the dialog we’re going to build in order to (finally!) pick up items.

-Steve

Categories: Development, Dungeon Ho!, Unity | Leave a comment

Dungeon Ho!: Unity – Dev Blog #8

Welcome back, ex-parrots!  I’m not dead, nor am I pining for the fjords.  I do, however, have both good news, and bad news.  The good news is that I’ve done a lot of work on the ‘Ho! since we spoke last, but the bad news is that I’m now extremely behind on blog updates.  Oh well, at least I won’t be starving for material!

Let’s pick back up where we left off, and continue to talk about Items.

***

The beauty of Items is that they don’t really have to do much, due to the Effects system (…which we’ll definitely be discussing in depth in future blogs.  It’s a big’n!) – but for now, simply know that the Effects attached to an item determine what it can do.  But before we get to that, we have to know how they’re defined, placed in the world, and interacted with once the player is looming over one.  Today we’re going to talk about how they’re defined.

The good news is that Item definitions are very similar to Monster definitions, in that we serialize a set of JSON data into an ItemDefinition object and then use that definition to initialize the Item itself through the ObjectSpawner.  Let’s look at some (temporary!) items that I’ve defined in order to implement/test this process.

Here’s the current items.json file.

{
	"items":
	[
		{
			"name": "Small rock",
			"weight": 1,
			"durability": 10,
			"flags": "equippable"
		},
		{
			"name": "Tree Branch",
			"weight": 3,
			"durability": 5,
			"flags": "equippable|twoHanded"
		}
	],

	"weapons":
	[
		{
			"name": "Creepy Pointed Stick", 
			"weight": 1, 
			"durability": 2,
			"effects":
			[
				{
					"effect": "mod_attack",
					"amount": 1,
					"target": "owner"
				},
				{
					"effect": "damage",
					"type": "phys",
					"amount": 1
				},
				{
					"effect": "damage",
					"type": "dark",
					"amount": 2
				}
			]
		}
	],

	"armor":
	[
		{
			"name": "Sandwich Board",
			"weight": 5,
			"durability": 10,
			"effects":
			[
				{
					"effect": "mod_defense",
					"amount": 1,
					"target": "owner",
					"duration": "permanent"
				}
			]
		}
	]
}

First thing you’ll notice is that I’ve broken up the definitions into three categories, much like how I did the monster types.  They’re itemsarmor, and weapons.  For now, you can ignore the effects data… but as an exercise, try to think about what that data might do once we get there!  Skim past the Small Rock item and take a look at the Tree Branch.

{
	"name": "Tree Branch",
	"weight": 3,
	"durability": 5,
	"flags": "equippable|twoHanded"
}

The name and weight parameters are the same as they are for Entities, as we saw last time.  Durability maps to the item’s health/hit points, dictating how much damage it can take.  We’ll care about that when it comes time to implement item damage and repair, but it never hurts to plan ahead!

Anyway. next up is the clever bit; the flags.  As I mentioned before, all entities have an integer defined called (…wait for it) flags, that we can manipulate to stack data values together by way of boolean/logical operations.  I’ve defined a bunch of string constants that map to these flags, and the Item’s definition parsing code splits that string and then sets the correct flags.  Here’s how it’s done.

The flags variable is passed into the following function as a single string, which is called from the Item’s init() method:

private void processFlags(string flagString)
{
   if (flagString == null)
       return;

   string[] splitFlags = flagString.Split('|');

   foreach (string flag in splitFlags)
   {
       if (flag.Equals("equippable"))
           setFlag(EntityFlags.EQUIPPABLE);

       if (flag.Equals("consumable"))
           setFlag(EntityFlags.CONSUMABLE);

       if (flag.Equals("twoHanded"))
           setFlag(EntityFlags.TWO_HANDED);

       if (flag.Equals("stackable"))
           setFlag(EntityFlags.STACKABLE);

       if (flag.Equals("requires_arrows"))
           setFlag(EntityFlags.REQUIRES_AMMO_ARROWS);

       if (flag.Equals("requires_bolts"))
           setFlag(EntityFlags.REQUIRES_AMMO_BOLTS);

       if (flag.Equals("cursed"))
           setFlag(EntityFlags.CURSED);

       if (flag.Equals("nodrop"))
           setFlag(EntityFlags.NO_DROP);
   }
}

The string is split, using the ‘|‘ character as a delimiter, leaving us with a list of string tokens.  Then we simply loop through all of them and set the equivalent flags.  Could we have mapped the tokens to the strings using a Dictionary?  Yes, yes we could have.  Maybe I’ll put that on the ol’ TODO list and save myself the trouble of having to update these methods across Entity types.  Refactoring!  Truly the hero of the people.

Anyway, note some of the flags and try to figure out what, exactly they indicate.  It shouldn’t be too hard… which brings me to a very important point; your code should be self-documenting.  Don’t listen to those clowns who scoff at such things and tell you it’s a myth.  It’s not, and you should strive for it every time you sit down to write.  Use clean logic, plain and verbose variable names, and above all, document your process both with code comments and meaningful function names.  You’ll thank yourself for it later.

Moving on, here’s the ItemDefinition.  If you understood the MonsterDefinition, it shouldn’t surprise you at all.

[System.Serializable]
public class ItemDefinitions {

    [System.Serializable]
    public class ItemDefinition
    {
        public string name;
        public int weight;
        public int durability;

        public string flags;

        public EffectDefinition[] effects;
    }

    public ItemDefinition[] items;
    public ItemDefinition[] weapons;
    public ItemDefinition[] armor;

    public static ItemDefinitions initDefinitionsFromJSON(string json)
    {
        return JsonUtility.FromJson(json);
    }
}

See? Same format, same logic.  I won’t show you the spawnItem(), spawnWeapon(), and spawnArmor() methods of the ObjectSpawner class because they’re literally the same as the spawnMonster() method we’ve already seen.  We’ll revisit them later when they need to be added to because of the eventual expansion of the Item class.

***

Okay, so now we can spawn an item.  What do we do with it?  Well, we place it into the world same as we did the player and monster.  Here’s the relevant lines from the Dungeon class;

Item rock = ObjectSpawner.spawnItem();

rock.setPosition(2, 5);

addItem(rock);

Look familiar?  Keeping the handling of different kinds of entities as similar as possible is going to help us immensely down the road.  The addItem() method adds the rock we just spawned to the dungeon’s items and entities List objects, respectively, as well as parents it to the dungeon’s gameObject so that it appears in-game.

So, we’ve got a rock, and we can put it in the game world.  How do we get it into the player’s inventory so that they can, y’know, use it?

The easy, hacky way to do it is to simply bind a key to the “Pick Up” command in the DungeonMaster, same as we did for player movement and passing a turn.  Here’s the relevant lines from the DungeonMaster object’s collectInput() method.

if (Input.GetKeyDown(KeyCode.G))
{
     Vector2Int pos = player.getPosition();

     addCommand(new PickUpItemCommand(player, dungeon.getItemsOnTile(pos.x, pos.y)[0]));
}

 

As you can see, we check if the ‘G’ key is pressed, then query the player’s position and pass it to the dungeon’s getItemsOnTile() method, which, you guessed it, returns the item(s) on the player’s tile.  Since we only spawned one, we can assume the method only returns one, so we pass the first (and only) item in the list into the PickUpItemCommand’s constructor.

Now, if you’re paying attention you should see some flaws in this implementation.  Namely, what if the getItemsOnTile() method is called when the player is on a tile with no items?  And how do we query for those items, anyway?

Those are both good questions.  I’m going to answer them in a future blog, because – as you may very well have guessed – this is simply a temporary implementation meant to illustrate how to construct the PickUpItemCommand object.  Don’t press ‘G’ over an empty tile and you’ll be fine.

Tune in next time when I actually show you the getItemOnTile() implementation, as well as the real way to pick up all items – and monster corpses – on a tile, using a proper UI dialog.  It’ll pave the way for a full-blown Inventory screen, the likes of which we saw in a previous blog’s screenshot. Did you prefer the text-only code blocks to MonoDevelop screenshots? It’s certainly easier to work with on my end. Don’t know why I didn’t think of it sooner.

-Steve

Categories: Development, Dungeon Ho!, Unity | Leave a comment

Dungeon Ho!: Unity – Dev Blog #7

Welcome back, screenshot voyeurs!  A lot of work has been done on the ‘Ho! since I last checked in; multiple screens, UI goodness, and major chunks of functionality have been added… so let’s see some screenage!

DHU 27

This is Dungeon Ho!: Unity as it currently looks.  Note the fancy new message console, which updates as commands are processed and automagically scrolls along with the messages.  It’s groovy.  We’ll look at how it was implemented in a future blog post.  Also, check this;

DHU 28

Mmm, programmer art!  Takes me back to the good ol’ days.  Anyway, you’re looking at the inventory screen, and there are three major components of this bad boy.  There’s the scrolling list of items on the left, then the information panel on the right, and of course the (cut off) context menu on the right-right.  Both the item list and the context menu are fully interactive, and clicking on them will do interesting things like update the aforementioned information panel and execute the listed commands (although at the moment it’s only possible to equip, unequip, and drop the selected items).

That’s pretty hefty, I hear you cry.  How did you do that?  That’s why I come here, to read how you do things!  Well, settle down there, Beavis; before we tackle any of that we need to talk about Items.  How they’re defined, how they exist in the world, and how to interact with them.  Once we get all of that nonsense out of the way, and are actually capable of picking up an item and placing it in our inventory (…and implement the inventory), we can start digging into the fancy-shmancy UI magic.  Sound good?  Are you psyched?  Next to the combat process and effects system, this is pretty much the core of the entire game here, so let’s make sure we do it all real thorough-like.

First, what is an item?  Well, in DHo! terms an Item is anything that is not a Mob, but is an Entity.  Items inherit from the Entity class, and here is the first deviation from the original code design that we’re going to address; the issue of corpses.

Mobs leave behind corpses when they die.  Is a corpse an Item, or simply a Mob with no health left?  In the original game, Mobs spawned an actual corpse Item that contained a FLAG_CORPSE identifier when killed, and the actual Mob was removed from the Dungeon’s mob list.  (Don’t worry, we’ll go over object flags in a later post.)  This was fine, but it wasn’t optimal.  What would I do if I wanted to add Raise/Animate Dead spells?  I eventually decided for the rewrite to simply flag a dead mob as a corpse and handle the occasional deviation in logic in the relevant inventory subroutines.

But enough about that.  We’ll go over it when we talk about combat.  Here’s the Item class definition.

DHU 29

As you can see, there’s not much to it… but the Entity class has definitely expanded since we saw it last, so we’ll look at it next.  An Item defines a slot variable that defaults to Inventory.SLOT_WEAPON_HAND, a constant that you can probably guess the purpose of without too much trouble… but if not, don’t worry; we’ll come back to it when we discuss the Inventory.

Items are actually GameObjects, so that they can be inserted into the world the same as the Player and Mobs.  They exist on their own sprite render layer which is one step up from the TileMap, but one step down from the Mob/Entity layer.  This allows Mob sprites to be rendered on top of any items in their current space.  The Dungeon object has a List of Items in it (as well as a List for Mobs as well as a master List of both combined).  Whenever we spawn either a Mob or Item into the level (including the Player), we invoke a method on the Dungeon that adds the object to the relevant list, as well as parenting its GameObject to the Dungeon’s.

So, what magic have we wrought upon the Entity class? Here you go;

DHU 30

The Entity item contains a number of interesting member variables, as well as getters and setters for all of them.  Unfortunately, here’s where I’ve deviated from Unity/C# best practices and did not use the built-in C# getter/setter syntax.  I did this because, well, I’m lazy and forgot about it until after I’d already defined all of the member variables, and didn’t feel like going back and duplicating them all and add underscores to the originals.  The original Java codebase used standard getters and setters, so I basically just ported that because it’s what I’m more comfortable with.  What can I say, I’m old.  You kids and your new-fangled technology.

Anyway let’s talk about these variables.  Most of what I’m about to say is basically regurgitating the code comments, so feel free to skip it if those made sense.

type – Every Entity has a type.  For example, remember when we defined TYPE_HUMAN in order to spawn a Human Mob in the ObjectSpawner?  That value gets stored here.  That way, if we need a quick-and-dirty way to tell if an Item is a sword, or a Mob is a Kobold, we can look at this index.  It’ll also come in handy when we eventually start writing these values out to a save file of some kind, so that we can use a generic table for every Item but call the relevant spawner method, of which there will be many.

id – A unique integer that identifies the Entity.  Useful for “tagging” stuff, again, in the save file so that we know which items/effects belong to which mobs when storing inventories, for example.

flags – a single integer that can store a whole mess of information by way of boolean operations.  We’ll look at Entity flags and how they work in a future blog.

weight – how much the Entity weighs, in pounds.  (I’m American, what can I say?)

hp, maxHp, mana, maxMana – the current and maximum values of the relevant statistics.  Yes, Items can have mana and health; it’s so we can allow things like wands to have “charges” or a set number of uses, and to model item damage and repair.

value – how much gold the player can get for selling the item to a vendor.  Will also be used to calculate the player’s final haul (IE, score) if they survive the dungeon and complete the quest.

baseDamageType – a constant defining one of the eleven damage types in the game.  Mainly used to determine the type of damage a Mob does with an unarmed attack; a human would deal TYPE_PHYSICAL damage while a ghost would deal TYPE_SPIRITUAL.  Most weapons would have an attached DamageEffect and not use this value, but since it defaults to TYPE_PHYSICAL it can provide a quick-and-dirty way to use a generic, non-weapon item as a weapon.  If that makes sense.

solid – if this boolean is set to true, then the Entity obstructs other Entities trying to move into its space.  Primary used for Mobs, but also leaves open the option for things like conjurable Walls and such.

Inventory – this is the Entity’s inventory (duh).  The reason it’s defined at the Entity level and not at the Mob level is because certain Items (such as containers – chests, bags, etc.) can have inventories.

Effects – any effects attached to the Entity.  Effects are a huge, core component of the game and will be dealt with in a later blog.

Whew.  That’s enough for today, I think.  Tune in next time when I’ll show you how to spawn an item, then pick it up (via the PickUpCommand).  Once it’s in our inventory, that’s where the real fun begins.

– Steve

Categories: Development, Dungeon Ho!, Unity | Leave a comment

Dungeon Ho!: Unity – Dev Blog #6

Hello again, Blogstalkers!  Sorry for the lengthy delay between updates, but between the holidays and the numerous false starts on this particular topic, it took longer than I expected to actually settle on a simple, Unity-esque solution to the topic.  And once I found one, I just kept focusing on the fun stuff; coding!

Anyhoo, as promised, today we’re going to look at defining Mob characteristics in a data file.  Data-driven development, and all of the perks therein, should be obvious to anyone with half a clue – but if not, the primary reason I did it was to cut down on a lot of duplicate code in the various monster types.  For example, let’s say you have a Kobold.  When you spawn one, the object’s name needs to be set to “Kobold”, his height and weight need to be set, and his starting gear needs to be generated.  Now, you can do this via inheritance in the monster’s constructor – and the original Java Android version of Dungeon Ho! did this – but it involved a lot of copying and pasting, and flipping between files to make sure I didn’t leave anything out.  Wasn’t a big deal when I only had a few monster types.  Much more of a deal when I had twenty.  Much better to just pass a data file into the base Monster constructor and have it pull all the data from there.  And, what better format to use for this than JSON?  It’s human-readable, extensible, and most importantly, natively supported by Unity!  Can’t beat that with a stick.

So first, let’s take a quick look at the current monsters.json file.  This is, as you may have guessed, the JSON file that stores each monster’s default data.  The beauty of it is that we can simply add new key-value pairs as we think of them, and it won’t break the existing loader; everything the C# code doesn’t recognize is simply ignored.

dhu 19

As you can see, each monster definition is labeled with an object name (in this example, “human”) and assigned a bunch of data.  Since Unity handles text files directly, I simply dropped the .json file into a Data directory under my Assets folder in Unity, then dragged the file onto my Game object to create a reference to it.  If you recall from our previous entry, the Game object is, well, a GameObject that manages the state of the entire game via the attached Game.cs script.  So, by adding this line to the variable definition in that file…

public TextAsset monsterDefinitionsJSON;

We now have the ability to drag and drop a text file on there.  So, we do.

dhu 20

Once that reference has been assigned, we need to parse the JSON.  Merely assigning the asset causes Unity to automagically load the text file as a TextAsset, and we can then grab the text therein as a string.  This’ll be necessary to let the JsonUtility class do its thing, since it needs a JSON-formatted string to pull the data from.

So, let’s talk about the object we’re using to store all of these monster definitions.  It’s called, oddly enough, MonsterDefinitions.

dhu 21

Classes that can be parsed from JSON need to be tagged with [System.Serializable] – and note that we have a nested inner class to handle both the monster definition itself and the male/female pairings.  The actual definition itself is mapped to the “human” local variable, which must match the monster’s object name from the JSON data.

Why didn’t we simply make an array of MonsterDefinitions, and then define it as an array of objects within the JSON?  Because then the order of the definitions would matter, and I wanted to move away from hard-coding stuff like that.  This way if I later decide to copy-paste a bunch of definitions and make a mistake somehow, I only screw up the ones I copy-pasted rather than all of them.  Plus, and although this is a one-man project, let’s say a second person was tasked with inputting that data.  You told them/wrote it down somewhere that the monster order matters, and it gets misplaced.  Now you have an out of order data file.  Yippee.  Another drawback is having to possibly keep track of the number of monsters for the array allocation.  And the fact that I’ve read rumblings that Unity’s JSON deserialization for arrays can be iffy and require a wrapper class anyway.  Not worth the hassle.

Anyway.  Moving on.

In the Game class, we take the passed-in reference to our JSON datafile and call the static method of the MonsterDefinitions class initDefinitionsFromJSON to parse the data and give us a MonsterDefinitions object, like so;

monsterDefinitions = MonsterDefinitions.initDefinitionsFromJSON(monsterDefinitionsJSON.text);

 

We can then use this object to retrieve the data from the ObjectSpawner, as the monster definitions variable is both public and static, alleviating the need for any obnoxious getters or reference passing.  It’s totally okay since we’re only ever going to have one of these objects.  And, although I don’t know if it’ll help, I null out the TextAsset reference afterward so the garbage collector can reclaim it, since we don’t need it anymore after that.

So how does the object spawner, use this data?  Glad you asked.

dhu 24

The ObjectSpawner class uses similar logic for monsters that it did for the Player.  Note that the basic GameObject creation has been abstracted into a separate generateEntity method.  We do some basic housekeeping by setting a (temporary!) sprite to the SpriteRenderer so we can see it in game, as well as set the monster’s solid variable (we’ll cover that another time when we deep-dive further into the Monster and Item classes), but the most interesting thing is the assignMonsterComponent method.  It takes a MonsterType enum, which is defined as an integer, and based on that, passes a particular MonsterDefinition from the Game’s MonsterDefinitions class into the Monster’s init method.  That method is as follows;

dhu 25

Note the one-to-one mapping of variable names in the MonsterDefinition to the JSON data.  Easy!  We can grab the data fields as variable names and assign them to our own variables.  Also note the slick data processing that checks whether or not we should format the Monster’s name with “A” or “An” depending on whether or not it starts with a vowel.  Does this cause issues when localizing to other languages, you ask?  Damn right it does!  But I made the decision early on that such a text-heavy game would be basically impossible for me to localize anyway without a lot of work for very little gain.  So if you were hoping to play Dungeon Ho!: Unity in German or Swahili, you’re out of luck.

Anyway, that’s all for today.  Tune in next time when we lay the groundwork for items, including the Item class itself, extending the ObjectSpawner to handle them, and maybe even the Inventory system complete with picking stuff up that’s just lying around the dungeon.  (Told you I’ve been busy!)

– Steve

Categories: Development, Dungeon Ho!, Unity | Leave a comment

Dungeon Ho!: Unity – Dev Blog #5

Welcome back, Dungeon Masters!  Today, we’re finally going to look at the Dungeon Master object (…natch) and its role in processing the game’s command queue.

As I explained last time, the DungeonMaster object maintains a queue of all the commands collected from the player.

DHU 15

Pretty straightforward.  The DungeonMaster maintains a List object of MobCommands, which we saw the structure of last time.  There’s an addCommand() method, which adds a new command to the end of the queue.  We keep a constant to make sure the queue doesn’t get too large (which normally won’t happen, but if the game’s running slow and the user starts monkeybashing the UI, commands might get backed up in the queue).

Next up is the processCommandQueue() method.  This method simply checks to see if the queue is empty.  If it isn’t, it calls the dungeon’s advanceTime() method – which, as the name suggests, advances the time passed in the dungeon by one turn – and passes it the first command in the queue as the player’s input for that turn.  It then removes the command.  Simple enough, right?

Where the actual magic happens is in the Dungeon class.  It didn’t do much the last time we looked at it, so let’s revisit it now.

DHU 16

We’ve moved the map generation and player-spawning code out of the Start() method and into its own init() method, which will become relevant next time when we start doing some more sophisticated setup code in the Game object.  Stay tuned for that!  Moving on, you’ll notice we now have a DungeonMaster object and a turnQueue, which is a list of all of the commands collected from both the player and the monsters’ AI for the turn.

Since the Dungeon is a Unity Monobehavior, it has an Update() method which gets called repeatedly as the game runs.  This is our update loop.  Every pass through the loop, the dungeon tells the dungeonMaster to collect input from the player (…which we’ll see shortly).  Any input collected that frame is converted into a MobCommand and added to the DungeonMaster’s commandQueue.  And, after the input has been collected, that command queue is processed, as we just saw.

Now, you may be wondering why, if we’re only collecting input once a frame, why we don’t just pass that input directly to the dungeon.  Why the extra queue?  Well, the answer is because eventually we want to be able to collect input from the game’s UI, as the result of button presses and event handlers.  Those happen outside of this loop, so we need a way to collect all of the command input in one place and handle it in the order it was generated.

So, how do we do that?  Here’s the DungeonMaster’s collectInput() method, which is textbook Unity keyEvents.

DHU 17

See how we’re instantiating new commands of the types that we defined last time?  The MoveCommands take a reference to the player as their source (I added a getter to the dungeon to access its player object), as well as a constant denoting the direction, and the PassCommand merely takes the player (also as the source; remember, the source object is the one that initiated the command) and nothing else.

Okay, once we have commands to process, what do we do with them?  I’m glad you asked.  Remember, the dungeon calls advanceTime() to advance the game one turn.  Here’s that method.

DHU 18

Not exactly rocket science, is it?  Every turn, the dungeon clears its turnQueue, then adds the passed-in player’s command object to it.  (Eventually, it will loop through all the other Mobs and ask them for their commands, but we haven’t gotten that far yet!)  We then sort the queue, using the CompareTo() method we defined to sort on the turnOrder of the Command.  We pass in a lambda function calling that method with two MobCommands (denoted by the parameters mc1 and mc2) as our sort comparator (check the C# documentation for more on that – it’s kinda tricky).

Once the queue has been sorted, all of the commands will now be in turn order – so, we merely loop through each command in the queue and process it by calling the process() method we looked at in the previous blog.  Finally, we loop through all of the entities in the map (mobs, the player, items, and so forth) and call their postCommandUpdate() methods.  This method is currently empty, but will eventually do things that update the Entity’s state, like check if its health dropped below zero as the result of any attacks carried out in the queue so that it can mark it as dead.

…and that’s it!  This simple queue processor runs the entire game, and is stupidly flexible.  We simply define new commands for any new action we want a mob to be able to take, and as long as they inherit from MobCommand and define their own process() method, the turnQueue will handle them.

Tune in next time when I’ll show you how I finally decided to represent Entity spawning, including the use of JSON-based default data to avoid hard-coding values.  Things are starting to get interesting!

-Steve

Categories: Development, Dungeon Ho!, Unity | Leave a comment

Dungeon Ho!: Unity – Dev Blog #4

Welcome back, Roguelikers!  Today we’re going to be looking at the basic structure of the Command classes… which, collectively, are the heart of the entire game.

As many Roguelikes before it, Dungeon Ho! is turn-based.  Whenever the player inputs a command, the game puts that command into a queue, then queries all of the other Mobs to see what they want to do.  Each Mob also selects a Command (…even if it’s just doing nothing), then adds those to the queue as well.  The game then sorts all of the commands into an “initiative order” to represent the fact that some Commands should take priority (IE, “go faster”) than others.  For example, moving is faster than casting a spell (usually!), so if a Mob submitted a MoveCommand and another Mob submitted a CastSpellCommand, the first Mob would act before the second.  Since Mobs attack one another by moving into another Mob’s space, this means the first Mob may very well kill the second Mob before it gets to act!  Once all of the commands have been sorted, the game then runs down the list and processes each command in order, carrying out whatever tasks need to be done in order to fully execute the command.  This may involve updating the mob’s position in the world, running an attack routine, picking up an item and adding it to the mob’s inventory, or a host of other things.

For now, though, let’s look at the basic structure of a command.  It’s represented by the MobCommand class, and each different type of command will get its own class that inherits from MobCommand.  For example, moving is a MoveCommand.  We’ll get to that in a moment.

DHU 10

Don’t worry about the ToString() method being cut off on the bottom.  You’re not missing much.  All it does is replace the standard ToString() method with one that outputs a formatted string including the Command’s turnOrder, name, and data.

Anyway, let’s look at this class.  Note the two member variables of type Entity; we defined our Entity class in a previous blog entry, and it’s the building block of all… well, entities in our game.  A MobCommand needs to know its source (the entity that initiated the command) and its target (the entity the command is invoked upon).  For example, if one Mob was attacking another, we’d create a MobCommand with a source equal to the attacker, and the target equal to the victim.

We provide two constructors for our command class; note that one takes a parameter of type object, which gets assigned to a member variable called data.  Don’t confuse an object (little ‘o’) with an Object (big ‘O’)!  The lower-case object type is the base object class that everything in the C# language inherits from… that includes basic datatypes like integers!  The Object class is the base Unity object class, and the two of them are not equivalent.  We want our data variable to theoretically hold anything we can stuff in there, so it needs to be the most base of objects the language allows.  We could easily just have a single constructor that can take null for the data value, but this is more intuitive when you see it in action, IMO.  The variables are assigned in the init() method, to keep from duplicating code across constructors.

The process() method is the heart of a MobCommand.  This is the method that the game will call in order for the command to do whatever it needs to do.  We give it a reference to our Dungeon, because although most commands will simply act on the source and target, some of them will most likely need to gather additional data from the dungeon… like when a Mob tries to move.  (We’ll look at the MoveCommand shortly, so hang on!).

The compareTo() method allows us to compare two MobCommands and evaluate whether one is “higher” than another based on their turnOrder.  This method, as you will see later on, gets called in the Dungeon’s update loop when there is a turn to process.  It simply calls the built-in C# method CompareTo(), which is implemented in all basic datatypes… including ints, which is what our turnOrder is defined as.

The getTurnOrder() method should require no explanation.  Since turnOrder is private, it’s just a getter that allows other objects to access the variable.  We might not even need it, as turnOrder is basically calculated once and then forgotten about.

…and it’s calculated in determineTurnOrder(), which is a virtual method that can either default to the base initiative as calculated by the source entity (currently, it’s merely the maximum value an ability score can be, which is 100.  We’ll talk more about ability scores and how they determine initiative in a future blog.), or get overridden by a child class that provides its own way to calculate the turnOrder.  For example, we may want MoveCommands to use the mob’s current Agility score plus some kind of action modifier.

***

So, how do we make new commands?  Glad you asked.  Let’s do it.  Here’s the PassCommand, which is the command a mob would invoke when they didn’t want to do anything at all.

DHU 11

Fascinating, right?  The most interesting thing about the PassCommand class is that it inherits from MobCommand and invokes that base class’ constructor, passing it the values it is given by the code (defaulting the data parameter to null, as the PassCommand never provides data.  Hm, could probably invoke the other constructor instead, then… better fix that!).  We have to do this because otherwise Unity would complain that there is no “default” constructor, which is a constructor that takes no parameters… and it’s right!

We also override the process() method, because eventually the PassComand is going to put a message into the game’s log when a Mob passes its turn.  For now, though, we can just fart out a message to the log so that we know our queue has processed the command.

Now, let’s look at one with more beef to it; the MoveCommand.

DHU 12

The MoveCommand currently defines four constants to indicate the compass directions.  Note the TODO tag that implies that we’ll be expanding this in the future to handle diagonal movement.  (It’ll be fascinating, I assure you.)  Anyway, again the command provides its own constructor, and this one uses the data parameter because the game needs to pass one of those compass directions in so the command knows which way the source plans to go.  (Once again, I note that there’s an unused parameter – targ – so I modified the constructor definition after this screenshot was taken to remove it and simply pass null to the parent class.)

When the game processes a MoveCommand, it looks to see which direction is stored in the data, then constructs a Vector3 representing the modification to the source Mob’s position.  It queries said position (making a copy of it in the process, as the getter for that property provides a copy of the value, not the actual property itself), modifies that copy, and then checks if the Mob can move into the new space.  If they can, then the command updates the source Mob’s position with the new value… not using the setLocation() method that I defined for precisely that purpose!  Argh!  Y’know, it’s a good thing I’m doing these blogs.  They’re helping me catch a lot of mistakes that I’m overlooking while coding.

Anyway, we’ll fix that later.  You’re probably wondering what magic the canMoveTo() method is doing to check if the Mob’s path is clear.  Wonder no longer.

DHU 13

Remember how I said a command might need access to the Dungeon?  I’ve added a getter method to access the DungeonMap object, and passed that to the canMoveTo method, which calls the map’s getTile() method to return the Tile object on the WALLS layer at that position.  If there is no tile there, then the space is clear and we can move there.  Easy!  That’s the whole reason we have a WALLS layer in the first place – all collidable/solid tiles that block a Mob’s movement exist on that layer, and that layer alone.  You’re not shrooming if you don’t remember my defining a getTile() method, though; I added it as part of implementing collision.

DHU 14

Well, that’s enough code for today!  Tune in next time and I’ll explain how the game polls the turn queue and processes command input.  We’ll have our adventurer trekking about in no time, I promise.

-Steve

Categories: Development, Dungeon Ho!, Unity | Leave a comment

Create a free website or blog at WordPress.com.