Development

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

Advertisements
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

Dungeon Ho!: Unity – Dev Blog #3

Welcome back, Unity fans!  Today, I’m going to show you how to use the Tilemap objects created last time… as well as the basic object/entity hierarchy that’ll finally get a player into the maze.

The cornerstone of all Unity objects is the GameObject, and we’re going to utilize this beast for all of our mobs (old-school speak for Mobile Objects), items, and of course, the player.  We need a base class script that we can attach to a GameObject so that Unity knows it’s one of our Entities… so, enter the Entity class;

DHU 5

The Entity is a MonoBehavior, because there’s some functionality in that class that we’ll need down the road… primarily the gameObject member variable.  At the very least, we need to be able to modify its position in the game world!  And speaking of that game world, let’s backtrack a bit since I did promise to show you how to generate a very simple test map to run around in.

DHU 6

As you can see, our TestDungeonGenerator inherits from our DungeonGenerator ScriptableObject, and I’ve added a CreateAssetMenu tag at the top of the file so that I can automatically create a new Asset of that type.  We’ll need to create one as a prefab so we can assign it to the DungeonGenerator variable from Dungeon.cs, swapping out the (currently) empty original DungeonGenerator.

This TestDungeonGenerator overrides the generateDungeon method of that class to create a simple 10×10 dungeon full of empty tiles, denoted by the tile constant TILE_EMPTY.  We then set all of the tiles on the border of the map to TILE_WALL, and set two of the empty tiles to our up and down stairs, respectively.  We also throw a single solid wall into the center of the dungeon to test collision and pathfinding, once we’ve got them in.

Now that we have somewhere for our player to go adventuring, let’s continue inspecting the object hierarchy.  We’ve got an Entity, which forms the basic building block of all of our in-game objects.  Item objects will inherit from Entity, once we are ready to equip our Mobs, and (you guessed it) the Mob class will inherit from Entity.  Currently, the only member variables Entities have are weight and flags, but we’ll be adding to that later on.  Note that the Entity class defines a Start() method, which Unity calls when the object is first created/activated (and, for our purposes, is basically the same thing).  The Start() method sets the name of the entity so that we can quickly identify it in the Unity scene tree.  All subclasses will override this method, as you’ll soon see.

Naturally, the Player class inherits from Mob, so here’s our inheritance tree;

Entity > Mob > Player

Next, it’s time to port over the master ObjectSpawner class from the original Dungeon Ho! codebase.  This factory class, as its name suggests, is responsible for spawning every kind of object the game could possibly need.  Right now, we need it to spawn us a player.  Eventually, we’ll need it to spawn a player from a specific set of characteristics, like character class and gender, but for now all of that will be set to temporary defaults.

DHU 7

The spawnPlayer method creates a new, blank GameObject and attaches a Player component to it, representing our Player.cs script (which, currently, merely sets the gameObject’s name to “Player” – similar to how the Entity class does).  It then attaches a SpriteRenderer, and loads one of our existing sprite assets from the Resources folder to serve as its sprite.  Note that the sortingOrder is set to DungeonMap.RENDER_LAYER_ENT; this is a convenience constant I defined to put all of the spawned sprites in front of the TileMaps that make up the dungeon.  Once all of that is done, the method returns the newly-created gameObject.  Let’s see where this is all tied together… in our Dungeon class.

DHU 8

The Dungeon keeps a reference to the player (we’ll need it later), and it grabs a reference to the newly-spawned player’s Player component (we can always access the gameObject directly through it).  Although, I may want to simply return the Player component from the ObjectSpawner, now that I think of it.  It’ll save me from having to manually do that every time I spawn anything.  Let’s put that on the ol’ TODO list.  Anyway, once we’ve got the player we set his position (I added a setPosition() method to the Entity class that changes the gameObject’s world position by passing it a new Vector3.  We’ll take a quick look at that next time when we cover movement), and parented the player’s gameObject to the Dungeon itself, so it appears under the Dungeon in the scene tree.  Hmm, may want to wrap that in a method as well.  To the TODO list it goes!

Eventually, this spawn code is going to be moved out of the Dungeon.start() method, but it’s okay for now.  Let’s see our results!

DHU 9

Not too shabby!  Tune in next time when I take our intrepid adventurer out for walkies, creating the object command queue processor and handling collision with the TileMap.

-Steve

Categories: Development, Dungeon Ho!, Unity | 2 Comments

Dungeon Ho!: Unity – Dev Blog #2

Welcome back, coding fiends!  Today we’re going to look at the core app design for Dungeon Ho!: Unity, from both a project and code perspective.

As I mentioned previously, I decided to go with a single-Scene approach.  Each game menu, screen, and dialog would be organized in a hierarchy of Unity Canvas objects, which will keep me from having to worry about data persistence or nested scene management.  As this will be a single-developer project, encapsulation and decoupling is not going to be my biggest concern.

So, let’s look at the basic scene tree;

DHU 1

As you can see, within the scene I have a GameObject called Game.  This, as the name suggests, is the object that contains the entire game; the map, the monsters, the players, all of that good stuff.  It will also eventually contain things like AudioListeners, high score tables, and so on – but, we’ll burn those bridges when we come to them.  For now, the Game contains our Dungeon, which consists of a Map that has three layers, represented by Unity Tilemap objects; Floor, Walls, and Details.  These layers are separate for both stacking/rendering and collision purposes, which we will set up later.  Floor and Walls are self-explanatory, but what about Details?  The Details layer will represent “props” that decorate the dungeon, like torch brackets, furniture, and cracks in the floor.  By keeping those tiles on their own layer, we can generate a wide variety of scenery without having to make a tile for every possible combination.  The Camera will eventually be attached to our player object, but for now we can let it float free.

Next up is our overall project structure for asset management.  I’ve created some preliminary folders, as shown in the Project view;

DHU 2

As you may already know, the Tile objects are created from sprite sheets sliced from singular images.  Currently, I’m using placeholder art imported from the original Dungeon Ho! assets, but these will eventually be replaced.  The tile assets themselves are kept under the Resources directory so that they can be dynamically loaded at runtime.  I should probably look into making them AssetBundles instead.  We’ll throw that on the ol’ TODO list.

With the initial set of GameObjects created and a basic project folder structure in place, let’s start coding.

There is, of course, a Game.cs script – but as our Game currently does bupkis, it’s simply an empty MonoBehavior.  We’ll fill it in as the game progresses.  The most important thing to do right now is to create our Dungeon/Map classes so that we have something to run around in.  The Dungeon GameObject has a Dungeon.cs script attached to it, which currently (we’ll change this eventually) generates a new dungeon map when the game starts.

DHU 3

Note that we do a GameObject.Find() call to locate the Map GameObject within the class and grab a reference to its DungeonMap component (…which I haven’t discussed yet; it’s the DungeonMap.cs script).  We do this so we can access the script attached to it and manipulate the Tilemap, which we’ll see in a moment.

The DungeonGenerator member variable deserves special mention.  Initially, I had the DungeonGenerator class not inherit from anything (IE, it wasn’t a MonoBehavior or ScriptableObject) that just had a single static method called generateDungeon().  I switched it to a ScriptableObject and made it public so that I could swap out the DungeonGenerator object from within the editor.  This is so that I could dynamically assign different DungeonGenerators to the object, which would generate different kinds of dungeons.  It’s currently using a class called TestDungeonGenerator, which generates a single, simple 10×10 room with a center wall and both entry and exit tiles.  When the actual DungeonGenerator is ready, and I’m done using this small room for testing, I’ll simply swap in the other one.  ScriptableObjects; you gotta love ’em.  I’ll go over that process a bit more next time.

Here’s the DungeonMap.cs;

DHU 4

Pretty straightforward so far.  I’ve defined constants to represent the layers, as well as the different tile types.  There’s an array of Tiles (for our loaded Tile resources) as well as TileMaps (for our Tilemap layers).  We do some Find() calls to locate our in-scene Tilemaps; again, we could easily just have assigned them from the editor, but this is pretty much the same thing (whoops! Took the screenshot before I changed the DETAILS layer to find the “Details” object!  Rest assured this was fixed in the code).  We also define a method to load a particular tileset, which grabs all Tile assets in the provided folder, and a setTile() method that sets a particular tile on a particular layer to a particular index.  We simply pass in the TILE_ constant and the code indexes it into the Tile[] array and finds the proper Tile object to use.  Easy!

Tune in next time, and I’ll show you how I generated the test dungeon… and, if we’re lucky, I’ll also have had time to get a player wandering around in there.

-Steve

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

Dungeon Ho!: Unity – Dev Blog #1

Hello, nerds!  Today we’re kicking off the first in a series of Development posts about porting my first Android title, Dungeon Ho!, to Unity.

Dungeon Ho! was a Roguelike written for Android API level 10 and released in the summer of 2013.  It did… respectably for a first solo attempt in a niche with basically zero marketing, but ultimately a bunch of design decisions that I’d made during development came back to bite me in the ass to the point where the planned ongoing addition of new content and features never came to be.

Here’s a screenshot of the game running in either Android Studio, Eclipse, or on my test device.  I forget.

5631_10151355638768124_168043149_n

I’ve had a plan to do a sequel ever since I realized there were a number of ways I could have made the game better, both feature-wise and code-wise.  After all, it was my first Android title and I’d learned so much since (mostly by leveraging the fact that I’d published an app to actually get a string of jobs as a professional Android developer, but I digress.  Even so, Lesson #1: publish something!  It looks great on your resume!)… but one snag came in the form of Unity, which I’d learned during a stint of downtime between jobs.  Unity offered so much stuff in it that I could leverage to make great games, but the tilemap support was still in development and, at the time, didn’t seem that great.  I revisited it recently, though, and that cinched it; rather than re-use my custom Roguelike engine (…which needed refactoring anyway), I would merely port the game to Unity.

Why. though?  After all, refactoring aside, I already had an engine, right?

Well, yes.  But here’s the thing; Roguelikes have a big audience, especially on Steam.  If I could make a stellar sequel, and I did it in Unity, I could leverage the cross-platform building capabilities of Unity to spread it far and wide.  I mean, I did already have one or two people ask me if there was an iOS version, so there you go.

***

Ok, now what?  Well, the first thing I had to do in terms of tech (I already know my feature list) was to analyze the Android build and see where I went wrong, and what exactly needed to be re-done as opposed to just ported to C# from Java.

Here’s my initial list;

  1. UI – When I first moved to Android, I didn’t feel like it would be productive to spend a huge amount of time absorbing all of the new platform’s features.  After all, by this time I had a large amount of J2ME experience and felt that I would be able to leverage my hard-won optimization skills to keep the game small and light.  So, all I learned how to do initially was start a thread that would paint to a canvas, scale it to the size of the device’s display, and that would be enough.  My main concern was that I had no hard data on whether mixing blitted bitmaps with Android’s XML/Layout-based UI would cause performance issues that I wouldn’t start seeing until riiiiight before release, because I was already developing on the Android emulator (I didn’t have a device yet) and figured I’d play it safe.  In the long run?  I wasted a ton of time rolling my own UI components when I could have totally just used Android’s dialogs, buttons, lists, text boxes, and other handy widgets.  For the Unity port, I will definitely be leveraging Unity’s UI canvases.
  2. More robust Command system – To keep the amount of Java classes in the app fairly small, I chose to do a number of things with switch statements rather than polymorphism.  This was fine when the switch statements only had a few branches, but the game essentially takes a different switch branch for every possible command in the game.  This… got ugly.  The Unity version will definitely provide child classes for the TurnCommand class, cutting down on the game loop complexity immensely.
  3. No class-based conditionals – “if (variable instanceof Class)”?  Blargh!  The fact that I kept checking the types of my objects told me that I’d blundered my inheritance chain somewhere.
  4. Better object spawning – For some reason, I chose to do the most basic of object initialization within the SpawnFactory classes, but setting other aspects of the items and mobs was done wherever said item/mob was spawned, leading to me copy-pasting various spawning boilerplate all over the place, so that when a bad spawn initialization occurred I would have to hunt down which spawn chunk-o-code was responsible.  Making the spawn factory more robust, to allow specific kinds of object spawning as well as randomly-generated, is definitely going to be a must.
  5. String formatting, not concatenation – Ugh.  With the amount of text in a Roguelike, you’d think I’d have been smart enough to use formatted strings, but no; I concatenated everything.  The amount of time I spent tweaking my string cleanup routines to remove rogue spaces and such was… a lot more than it needed to be.

That’d do for a start.  My next step was to decide on the overall application architecture within Unity.  After a lot of pondering over things like persistent objects and scene loading, I eventually decided to just keep it simple and use a single Unity scene with a number of switchable canvases for the menus and information screens, both in and out of the game.

And, that’s basically where I am now.  Tune in next time where I’ll go over the initial Unity coding, and how the various game objects (as well as GameObjects) are arranged.

-Steve

 

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

Blog at WordPress.com.