• Subcribe to Our RSS Feed
Archive from February, 2011

Hexagon of Hexagons

Feb 13, 2011   //   by Josh   //   Games, Uncategorized  //  5 Comments

I’ve been thinking of a slightly new direction for HexDev, which led me to thinking it would be appropriate to generate a hexagonal canvas instead of a rectangular one for creating HexWorlds.  I also decided to document the process of where it is today and how to get there for fun and for others to learn from.

So first a little background.  Let’s start with generating a rectangular grid of hexagons as HexDev already does.  To do this, we need a little bit of math (or you can ignore the math and use magic numbers).  I chose to orient the hexagons with their left and right side being vertically aligned, points facing up and down.  If you choose to orient them a different way, the math may look a little different.

From http://mathworld.wolfram.com/Hexagon.html, we learn the following properties which are very useful for this kind of grid generation:

Given a regular hexagon with side length a:

The inradius: r = 0.5 * sqrt(3) * a
The circumradius: R = a.

The inradius r is important because it tells us how much horizontal distance we need to shift between each tile and how much horizontal space we need to shift every other row.
The circumradius R is useful because we can calculate how much vertical distance we need to shift for every row.  Fortunately for us, R = a, so that keeps the math easy. :)

The horizontal and vertical space between the center of each tile is then calculated by the following formulas:
horizontalSpace = 2.0 * inradius
verticalSpace = 1.5 * R = 1.5 * a

So, given these fomula, here’s the code to tile a Prefab in a rectangular grid in Unity3D:

public class HexGrid : MonoBehaviour
{
    public int Width = 10;
    public int Height = 10;
 
    public float HexSideLength = 1.0f;
    public GameObject HexTilePrefab = null;
 
    public void GenerateGrid()
    {
        float inradius = (float)(0.5 * Mathf.Sqrt(3) * HexSideLength);
	float spaceBetweenTilesHorizontal = 2.0f * inradius;
	float spaceBetweenTilesVertical = 1.5f * HexSideLength;
 
	if (HexTilePrefab != null)
        {
            for (int x = 0; x < Width; x++)
            {
                for (int y = 0; y < Height; y++)
                {
                    GameObject tile = (GameObject)Instantiate(HexTilePrefab, Vector3.zero, Quaternion.identity);
                    tile.transform.parent = gameObject.transform;
                    tile.transform.localPosition = new Vector3(x * spaceBetweenTilesHorizontal + (y & 1) * inradius, 0, y * spaceBetweenTilesVertical);
	        }
	    }
        }
 
        // Center the Grid
        gameObject.transform.Translate(new Vector3(-spaceBetweenTilesHorizontal * Width / 2.0f + inradius, 0, -spaceBetweenTilesVertical * Height / 2.0f - HexSideLength));
    }
}

Using this code will produce a visually “tight” grid of hexagons, if HexSideLength equals the visual length of the hexagon.  If you want some space in between your hexagons, you can set HexSideLength to a value > the actual side length of the hexagon, producing an even space around each hexagon.

Here we show HexSideLength = 1 and HexSideLength = 1.05 for a hexagon whose actual side length = 1.

So with a little background out of the way, we can now attempt to generate hexagonal grids.  Using HexDev’s Free Tile Builder, I generated the hexagonal grids that I want to automatically generate.  I started with 1×1 and worked up to 5×5 to determine the pattern and here’s what we end up with:

So what we have here are forests that represent the tiles that I actually want to generate and water to represent the empty spaces in the rectangular grid space.  My planned input is a single value a that represents the number of tiles per side.

To figure out how we are going to generate this grid, some observable stats are useful.  If we can find general equations for these values in terms of a, we’ve got enough information to render the grid, so let’s do that.

Here are some stats for every grid:

a rows midRowColumns midRowNumber
1 1 1 1
2 3 3 2
3 5 5 3
4 7 7 4
5 9 9 5

Let’s break down a = 5 to some even further stats:

row leadingSpaces tileCount abs(distanceFromMid)
1 2 5 4
2 2 6 3
3 1 7 2
4 1 8 1
5 0 9 0
6 1 8 1
7 1 7 2
8 2 6 3
9 2 5 4

So here are some equations that we can derive from these tables:

rowCount = 2a – 1
distanceFromMid[row] = abs(a – row)
tileCount[row] = rowCount – distanceFromMid[row]

The hardest one to derive I think is the leadingSpaces variable, because it changes depending on even/odd a values, but I’ve found this to be true:
For even values of a:  leadingSpaces[row] = Floor(distanceFromMid[row] / 2 )
For odd values of a: leadingSpaces[row] = Floor((distanceFromMid[row] + 1) / 2)

At the moment, I’m not going to share my code for this, because it’s getting late and it needs to be cleaned up… but if there is enough interest, I don’t have any qualms against posting it.  For now, I leave you with a screenshot of HexDev using a hexagonal canvas.  HexDev’s Free Tile Builder mode has been updated to also generate Hexagonal boards in 4, 5, and 8 length sizes.  Enjoy!

/Equip Gear

Feb 9, 2011   //   by Josh   //   Games  //  No Comments

Sometimes I think I have more fun playing with visuals than I do with implementing gameplay mechanics… thus the lack of gameplay in HexDev thus far.  But, our hero has donned some armor and a wooden sword! (in this screenshot anyway…)

Mental Design Sprint [Blindfolded]

Feb 6, 2011   //   by Josh   //   Uncategorized  //  No Comments

Game design can be stressful on your life!  Especially when you try to cram it in between the nooks and crannies of your daily activities.  It starts to consume me in some ways… when I’m sleeping I’m dreaming of hexagons.  Nearly every time I get a break, I’m thinking of player progression, tile design, adventure objectives, design mode, exploration, and how to please all of the Bartle Test cases.  Apologies go out to my wife and kids for that, because I probably look and act like a zombie when I get like this.

Suffice it to say: this “sprint” is not going well.  It’s more like a mental sprint for me than anything.  Or… I guess you could picture me sprinting across a corn field with a blindfold on (which means I’ll walk in a circle and never get where I want to go).  To put it quite frankly, I don’t have a solid direction for this game.

But then again, maybe I need to come to the realization that I don’t HAVE to have a solid direction.  Many great designers that I read about often find that through making and playing the game, they discover new and creative ways to play the game.  ”Find the fun”.  This is a difficult thing for me to accept, because I hate being “wasteful”.  I don’t want to implement something if I’m not sure about which direction it will go.  I don’t have an enormous amount of time to pour into this initiative because of my family and my job.   Not saying I want to invest more time, because I’m happy with where my time is allocated right now, I wish I could spend more time with my kids.  But more to the point, I feel that with my limited amount of time, I need to make it count.  In reality, my “making it count” ends up being a nearly complete waste, because I stare at my computer screen (running HexDev) and think.

One of my primary goals for HexDev is to avoid “hand-crafted” levels for a couple of reasons.  Lost Garden has a fantastic post about making the game Steambirds that points out many of the reasons I want to move in this direction.

  1. I don’t have time to invest in hand-crafted content.
  2. To keep things more interesting, I would rather develop new “mechanics” that players can experience than “churn” out new content.
  3. The 1/99 rule of the internet.  1% of users will invest heavily in your product for the other 99% to enjoy

I want community and sharing to be a fundamental aspect of the game, so I think it’s important for me to keep to the roots of the initial design in tact and keep going with a “tile building” style.  Or at least, leave it there as an avenue for people to generate the content.

That being said, here are some design sketches I’ve been doodling over the past few days with ideas for HexDev… I’m not sure if any of them will come to fruition or not, but it’s fun to see them anyway.

HexDev Sprint Day 3

Feb 5, 2011   //   by Josh   //   Uncategorized  //  No Comments

Day 3 was a wash… I stared at my screen for an hour, added a wooden sword for our hero to hold, but alas, he still cannot swing.

I’m mentally drained from the work week, maybe an update tomorrow evening.

Edit: Braindump included.

I need an over arching gameplay objective for the game and not having one is leaving me idle.  So you have this cool world which randomly generates and has all kinds of cool stuff in it!  Now what?

1 idea I have:  Every tile will support different “levels of difficulty”.  When the “Adventure” begins, the game will choose a spawn location and create an increasingly difficult map the further you move away from the spawn point.

For example:  A Swamp tile has 5 levels of difficulty:

  • Safe: The swamp is merely a marsh, not harmful and no enemies spawn
  • Light: The swamp is poisonous, but has small patches of islands so the user can safely cross (with some precision), and no enemies spawn.
  • Moderate: The swamp is poisonous, only 1 or 2 patches exist, so you may take more damage walking through.
  • Difficult: The swamp has no patches, and now spawns Muck Dwellers, which throw sludge at our hero.
  • Epic: The hardest level of difficulty, where a “boss” type mob appears.  This is your objective in adventure mode, to progress to a high enough level to defeat all Epic tiles.

I imagine that the difficulty here would come in discovering how to generate a nice progression curve at runtime.  But I guess as long as there is a path from 1 -> 5 through the map, it could be ok.  Different map sizes may be interesting to deal with. :)

HexDev Sprint Day 2

Feb 4, 2011   //   by Josh   //   Uncategorized  //  2 Comments

A mildly productive evening, like usual I didn’t get as far as I’d like, but I thought of a few design ideas.  Here’s what’s new:

  • Forest Tiles randomly spawn between 1 and 2 bats.
  • Prototype Health and EXP HUDs (they don’t actually function yet).

Unfortunately the bats have no AI other than flying in a circle and you can’t attack anything just yet.

Plan for Day 3:

  • Add a weapon for our hero: a wooden sword.
  • Be able to attack and slay bats.  Bats are level 1 and will drop 1 green block (exp).
  • Make Bats attack back with a whirlwind type ability that you can dodge.
  • If I have time: Implement a rudamentary health/experience system and make the  HUDs for XP and Health work.

HexDev Sprint Day 1

Feb 3, 2011   //   by Josh   //   Uncategorized  //  No Comments

Well, tonight was mostly relearning everything I had done before and fighting the Unity environment to load blend files properly… which I never got working. So, I’m resorting to exporting all models as FBX files manually, which will suffice.

I did however manage to get a small update. I tweaked some visuals and the camera controls and enabled different grid size selection. “Play” it on the HexDev link above or click this fine looking screenshot to have a look.

Plan for Day 2: Spawn some really stupid enemy units to slash apart. Maybe add a weapon (and a cape!) for our protagonist. I think if I get that far I’ll be in good shape.

Ready, set, sprint!

Feb 3, 2011   //   by Josh   //   Games  //  No Comments

I’m starting a 14 day, HexDev sprint tonight, in hopes of publishing something for Kongregate’s Unity3D contest.

So here’s my commitment to you (and to me):

  • For 14 days, instead of playing games, I’m going to work on HexDev.
  • Every night, I’ll publish updates at or around midnight before going to bed.
  • My followers are my playtesters!  All of ya!  So make sure you subscribe to my RSS Feed if you haven’t already and share it with your friends who are interested in indie game development.
  • Comment if you have something to say.  It’ll keep me motivated.  :)

I don’t have much to say about it right now, but I’ll post a brief update around midnight.

Bang!