This weekend I participated in Global Game Jam for the third time (after taking a hiatus in 2011 to go speak at conference overseas). This year, I was at the UVA site and took part in a 3 person team with my brother in law and an awesome UVA student. The result was an interesting two player competitive game called Eat Sheep (and Die).

This jam was way less stressful than any other jam I've participated in. We essentially had something fun to play by middle of day 2, and just polished things throughout the end of day 2 and day 3. As a result, this is probably the most complete jam game I've ever worked on. Very little went wrong. It was great.

So what when right?

  1. AngelXNA – Power of Angel combined with the power of XNA! This was the third time I've used Angel in a jam and every time it's improved. We were able to get levels in games quickly, spawn actors, and do all sorts of things quickly and easily. It actually worked really well. Again.
  2. Abandoning Design – The original point of the game was to have a cyclic back and forth of helping and hurting the other player. On your turn, you would have your goal, and a directive to help or hurt your opponent. On the next turn, you would be given a bonus based on how well or poorly your opponent did. At some point, we realized there was never any reason to help your opponent. It just wasn't worth it. So we abandoned the helping, turn based component, and went with real time versus. This makes it questionable whether we obeyed the theme, but whatever. The game was much better as a result.

What went wrong?

  1. AngelXNA? – So, the one thing I don't like about Angel and XNA is that it does have a huge barrier to entry for people playing the game after the Jam. I know I don't bother playing a GGJ game that requires a download unless it comes VERY highly recommended. I will, however, look at pretty much every HTML5 or Flash game. That said, Angel is awesome, so maybe I have to figure out a way to fix this. Native Client maybe?

That's it. Not too many lessons this time out because everything went so well. It's a weird feeling. Really looking forward to next year!

One of the tips I gave in my recent talk is to have a tool for GGJ. My tool of choice is AngelXNA, because it combines the power of XNA with the power of Angel. When I was demoing it to the other attendees, I realized I hadn't added a few demo screens that are really necessary.

To that end, I've added two demo screens showcasing two features that are in AngelXNA that aren't in Angel. The first is the Editor. While I had a problem with the Editor in the last GGJ, Fire Hose used it a lot for prototyping and I think we've worked out most of the kinks. It's not perfect, but it does make creating levels in Angel super easy. There are shortcuts for cloning, scaling, and rotating actors, which makes the level editing process super quick.

The second feature has several aspects, but comes down to the ability to use sprite sheets and the ability to create named, data driven animations. There are two parts to this. The first part is the Tiling system. By adding a .tileinfo file parallel to any given image file, it will automatically start rendering Actors that use that image as tiled. Here's an example .tileinfo:

IsAnim = true
FrameSize = Vector2(160, 200)
AnimDirection = TiledAnimDirection.Horizontal
StartFrame = Vector2(0, 0)
EndFrame = Vector2(0, 2)

It specifies that this file contains an animation, that each frame is 160x200, that the animation frames run left to right, starts at 0,0, and ends at 0,2. You can also use a non-anim and specify a specific tile to render.

Once you have these .tileinfos specified, you can specify animation files. Here's the example anim file:

BeginAnimation("Idle", TiledAnimRenderPath.Create())
    AnimDelay = 0.03
    File = "images/devo/devo_idle_strip"
    AnimType = AnimationType.Loop
EndAnimation()

BeginAnimation("Run", TiledAnimRenderPath.Create())
    AnimDelay = 0.03
    File = "images/devo/devo_run_strip"
    AnimType = AnimationType.Loop
EndAnimation()

BeginAnimation("Fall", TiledAnimRenderPath.Create())
    AnimDelay = 0.03
    File = "images/devo/devo_fall_strip"
    AnimType = AnimationType.OneShot
EndAnimation()

This allows you to call just Actor.PlayAnimation("Idle") or Actor.PlayAnimation("Run").

This is still a bit more complicated than I'd like, but does work really well. The only thing I'd like to improve is the specification of the render path. AngelXNA actually generally selects the correct render path automatically, but the data driving system, specifically the animation system, isn't detecting its render path. I can probably fix this, which I'll hopefully do after GGJ.

Update: Better late than never, my talk is now on my site.

Happy New Year!

For those that don't know, in May (or so) I moved from Boston to Charlottesville, VA. Thankfully, the awesome people at Fire Hose have allowed me to stay with them and work remotely, so I haven't moved companies. I have, however, moved communities.

Charlottesville isn't a huge center for game development, but I think if could be a great place for game companies in the future. There's a lot of talent to be had from the neighboring universities (UVA, JMU, GMU, Virginia Tech, and William and Mary are all fairly close) and it's just a great place to live. It's not a big city, but that's actually what I like about it.

To try to help this along, I've created the Charlottesville Game Developers meet-up group. We've had a few small meetings so far, with mostly me talking, but coming up over the next few months, we're going to have some great talks about starting companies, working with the city of Charlottesville, and maybe more! (By the way, if you'd like to come visit Charlottesville and give a talk, let me know and we'll work something out).

Tonight, I'm giving a talk on tips for game jams. Since UVA has been nice enough (at my urging) to host a Global Game Jam site this year, I'm making sure everyone comes in prepared. Most of the tips come from my previous post mortems of game jams, but there will be some new stuff in there. I'll try to be sure to post the slides tomorrow as well, so everyone can get the benefit.

Anyway, if you're in the Charlottesville area, come out to our meetings! I'm really looking forward to seeing what the Charlottesville community can produce over the next year.

Inspired by a Twitter discussion with Liam Devine about my previous blog post, I've decided to take a bit of time to talk about my opinion on Singletons. In my previous post, I used a lot of them, though generally, I'm not a huge fan. In fact, I've been known to dedicate non-trivial amounts of time in talks to the subject of why singletons suck. Singletons are just globals under another name, and they have almost all of the same drawbacks as globals, and don't provide too many benefits. Each singleton is a potential bottleneck, a potential threading nightmare, and almost always creates giant side effects throughout the code base every time they're used. In addition, if you're doing unit testing, use of singletons / globals requires significant set-up overhead, which can make tests more complicated.

So what gives? Why am I using them here?

Generally, there's nothing intrinsically wrong with a Singletons or globals. It's their overuse that becomes a problem. As mentioned above, each singleton needs to be managed carefully because it can become a potential bottleneck across your entire code. However, when you're working with something that does need to be global, a Singleton is sometimes a better option, since you can insist certain conditions be met before an instance can be returned.

A good example is a Fixed String Table. If you're unfamiliar with this, here's the idea: every string in your code is translated to a hashed number. In some cases, this translation is done manually, but for the sake of code readability and simplicity, I do the translation in code any time a FixedString object is created. In order to make sure that same string always returns the same hash, and to make sure we can translate the hash to a string, we put the string into a table. This table could be a static member of FixedString, but if you want to, say, tell the table where to allocate its memory from, or how much memory it's allowed to use, you need to initialize said table. Again, you could use a static method for this, but this is hiding what's actually happening. Furthermore, if your table class is any amount of complex, or has functions for accessing usage data, you're essentially going to be pushing that all into static methods of FixedString. It's a pain, when you are, in essence, creating a global interface anyway, since FixedString itself will probably be in global scope. At least by moving things into a singleton you potentially have the option of creating multiple tables in the future, should you so choose.

But what about all those Factory singletons from my initial post?

First, a point of clarification: in the previous post, I made it look like every factory was a singleton. I did this for simplicity, and I apologize. It actually isn't true. My factories aren't singletons. In reality, the code reads like this:

Application::Instance()->GetFactory()->RegisterComponent(…);

Application is one of the other few singletons I have in my engine. Now, I'll admit that this isn't much better than having the factories themselves be singletons, since they're retrievable from a singleton anyway. If you look at the code, it looks like my component code is now coupled to both the factory AND the application.

But in reality that's not true. My factories aren't coded or tested as singletons. If I wanted to create another factory I could, and all my unit tests will still work. And the components themselves aren't coupled to the factories or the application at all. The only thing that couples factories, the components, and the application is the auto-registration system, which serves as a bridge between all three systems. Each system is still usable stand alone.

This just leaves whether or not the Application as a singleton / manager is a good idea. The answer is, no. No it isn't. But since it is one of few, it sticks out like a sore thumb when you type it, and in code review. Every time you see or type Application::Instance() should be like warning lights going off in your brain that you're potentially doing something dangerous. BUT, since I'm mostly doing this during initialization, and at no other point, I'm okay with it.

So, as I'm sure many seasoned veterans of know, the initialization order of static variables is undefined by the C++ standard. While this generally isn't a problem, it can quickly become a problem if you're doing something like overriding the memory manager, as is the case in most games. Any structure that wants to call out to a custom allocator, must wait for the allocator to be initialized. One way around this is to have the allocator as a self-instantiating singleton, but what if you're doing something more complicated?

An example is a self-registration system. This is a fairly common occurrence: you have a factory class that takes care of instantiating other classes based on something data-driven. In my scenario, this is a component system, but it really could be anything. Each component needs to register itself with the factory class so the factory can proceed to instantiate them. You have two options here: one is to have a giant init method that looks something like this:

void InitFactory()
{
     Factory.RegisterComponent(ComponentA);
     Factory.RegisterComponent(ComponentB);
     Factory.RegisterComponent(ComponentC);
     Factory.RegisterComponent(ComponentD);
     Factory.RegisterComponent(ComponentE);
     // and so on...
}

The problem with this is that it requires you #include every component header, and remember to register every component manually. Not my idea of fun.

The second is to use an auto registration system. Basically, you create an auto-registration template class:

template <class Component>
class ComponentAutoRegister
{
public:
	ComponentAutoRegister();
};

template <class Component>
ComponentAutoRegister<Component>::ComponentAutoRegister()
{
     Factory::Instance()->RegisterComponent(...);
}

And then add that to any component class:

class MyComponent
{
    static ComponentAutoRegister<MyComponent> __AutoRegistration;
};

When the static auto-registration template class is constructed, it will automatically register your class with the factory.

The problem is this: If your factory class has any other dependencies, it will need to initialize those first. If this usually happens post-main, or as part of any other variable being statically initialized, you can't use this auto-registration system. Damn.

Here's my scenario: I have a table of fixed strings that needs to be initialized with a table page size and an allocator before it can be used. My component factory uses fixed strings as keys for each component. Instead of attempting to make a long chain of singletons which would only end up coupling all the systems together (something I wanted to avoid) I slightly edited my auto-registration system to auto-register a callback instead, which is then called post initialization:

template <class Component>
class ComponentAutoRegister
{
public:
	ComponentAutoRegister();

	static void PerformAutoRegister();
};

template <class Component>
void ComponentAutoRegister<Component>::PerformAutoRegister()
{
	Factory::Instance()->RegisterComponent(...);
}

template <class Component>
ComponentAutoRegister<Component>::ComponentAutoRegister()
{
	Application::AddPostInitHook(&PerformAutoRegister);
}

The callbacks are held in an opaque linked list, managed by a zero-overhead pool pulled out of system memory. It could actually be held in an array as well, but being able to free the memory once post-initialization is complete makes me happy.

And this could easily be extended to support multiple layers of auto-registered post-initialization, so long as the layers are kept free of dependencies. For now, I only need the one layer, so I'll keep it simple.

This may seem hacky, but it does work pretty well. What are your thoughts?

Crunch has been coming up in the news again, mostly because of the Team Bondai issues, and generally, I like to avoid talking about issues like this on my blog, but I figured I'd share some of my thoughts and see what people think. As a disclaimer, I have never gone through what anyone would call a "death march," which is what Team Bondai had to deal with. I've had to do crunch, but never on a huge magnitude, which I'll get to. I'm also going to take what some would say is a "controversial" stance on crunch. Here's the not controversial part: crunch is always bad, never required, and always avoidable, and a team should do everything it can to avoid it. But it's not always that simple.

Types of Crunch

The thing is, there are lots of types of crunch. And they're all different, and affect the team in different ways, and on different levels. In my mind, there are three major types:

  1. Self-imposed crunch: This is the crunch that some people in the game industry do on their own accord. They stay late every night because they want to. They want to get that one last thing in, they want to polish the hell out of whatever, or get that one last boss battle in. This is a personal choice, and there's really not much you can do about it. However, it should be clear to other team members that this type of behavior is not condoned or required. Don't reward them for this behavior. Otherwise you get into the second type of crunch.
  2. Team de-facto crunch: This is where the team "decides on its own" that it's going to crunch, when the culture necessitates it, or when management does nothing to stop it. When too many people start self-imposing crunch, other people at the team will start to look down on those that "aren't working as hard," and peer pressure will cause them to stay later, or work longer. This is particularly true in companies with lots of younger workers who are not only particularly vulnerable to this type or peer pressure (they really want to impress their superiors) and also believe that this is just the way the game industry is. If this bubbles up to management, there becomes this situation where long hours are expected, and people that don't do them are considered less valuable employees. Don't let this happen. As a manager, it is your job to make sure self-imposed crunch is seen as an anomaly, and to do your best to keep people from doing it.
  3. Mandatory Crunch: Just what it sounds like. Management, for some reason, requires longer hours. This is the most common form of crunch we hear about, and the worst. To producers / managers out there, just because you do the same hours does not make mandatory crunch okay. Actually, nothing really makes mandatory crunch okay. There are no excuses here. Mandatory crunch is always a failure somewhere down the pipe.

The first two types of crunch are cultural and occur at all studios, but can be mitigated once you recognize the warning signs.

In addition there are three levels of crunch:

  1. Mitigated crunch: The increase in hours is not huge, maybe 10 extra hours of work during the week, the length is known and can be planned for.
  2. Long crunch: The increase in hours is high. Working 60 to 80 hours during a week with no break. The length can still be known, but may be a long way off.
  3. Death march: The increase in hours is high, and there is no end in sight, or the end is repeatedly pushed back.

A Mandatory Death March is the worst type of crunch, and when we talk about "crunch" we're usually talking about mandatory long crunch or mandatory death march. There are no excuses for them, but we should take a look at the causes to figure out if they're avoidable.

Causes of Mandatory Crunch

Everyone looks at crunch as a failure of management. I agree, but there are a lot more factors to it than that. Here, in my mind are the general causes of crunch.

  1. Company Policy: The Epic model. There are no important deadlines coming up, there's nothing that's actually requiring crunch, but the company has decided to require everyone always work 60 to 80 hour weeks. Not okay. There is no excuse for this other than management being completely inept. It affects work quality and general quality of life. Don't do it.
  2. Bad Information: This is what happened to Team Bondai. They were constantly told (and believed) that the game was almost finished. In such cases, many team members, believing the end is in sight, will do self-imposed crunch, which eventually will lead to de-facto crunch. In addition, this is where a death march starts, and tends to never end.
  3. Bad Planning: This is the most common cause of crunch, and management gets rightly blamed for it all the time. But there are two types of bad planning:
    1. Bad Low Level Planning: Even the best management team can make a mistake, because they can only make decisions based on what they're told by the people below them. If what they're told is wrong, their planning will be wrong. So, if you're at the low level, don't fudge your numbers. Tell management the truth so they can make the right decisions.
    2. Bad High Level Planning: Even with all the right information, managers, especially bad managers, will plan incorrectly.
  4. Shifting Requirements: Even with good planning and good information, games are a highly creative and highly iterative product, and when something's not working or isn't fun, it has to be changed. Unlike other industries where you can work "to spec", the "spec" of a game is frequently fluid, which makes planning for the long term almost impossible. This, unlike the other causes, isn't anyone's fault, per-se, since a team can come to the mutual decision that something needs to be reworked, but it's something that frequently gets ignored while doing planning
  5. Deadline: When all is said and done, this is the real cause of crunch. When a deadline is involved any amount of error in planning or requirements hits a head when the deadline looms. Some studios are in a position where the deadline can be pushed, but not all, especially when dealing with a multi-game publisher that has to allocate resources at various times (QA, marketing, operations, etc) to make sure the game launches without a hitch, so they can move on to the next one. In these situations, moving the deadline is impossible.

The Myths: Crunch is a Given and Crunch is Always Avoidable

Both of the above statements are wrong. If the causes of crunch are listed above, avoiding crunch is as simple as avoiding those mistakes. Don't make crunch company policy, always give your employees all the information, plan well at all levels, have a solid design document, and don't have a hard deadline. Simple. But, if any of those slip, you have to make a hard decision: cut features, cut polish, or crunch.

If your company has a lot of experience or a lot of leeway, you can always avoid crunch. However, if you're a start-up working for a publisher, on a hard launch deadline, under contract, and you want to make the best game possible, chances are someone, and it's not necessarily management, is going to make a mistake, and that mistake is going to cause some amount of crunch.

Was it avoidable? Yes, probably at some point it was, and yes someone made a mistake somewhere. Crunch is always a failure somewhere down the line. But at some point in the project, it will become obvious that some amount of crunch will be needed. The next step is to mitigate it.

Mitigating Crunch

Crunch does not always mean Quality of Life or Quality of Work has to suffer, it's just that in most circumstances it does, because of the way it's implemented. I have gone through two sets of crunch, both mandatory, one long, one mitigated, and both sucked. But there are a few things that I found helped me, and I think would help others, get through any period of crunch

  1. Provide All the Information: Inform everyone how much more you expect them to work, what needs to be done, and where the deadline is. If ANY of this information changes, make sure the team knows. I have been in and heard about crunch situations where information about deadlines or cut features was withheld, and this only makes people angry
  2. Allow people to choose their extra hours: People are different and have different home lives. Some people work better in the morning, others at night, others over the weekend. Do not blanket ask everyone to stay late. Instead, let them choose when to work and they will choose times that will not only make them most productive, but will interfere with their lives the least.
  3. Allow people to work from home: Set up your infrastructure to let people work from home. Some people can be just as productive at home as they can be in the office, and this removes the stress of a long commute and improves QoL since they can be around for their loved ones.
  4. Allow people during longer periods of crunch to take some time off: This is huge for me, and I've never been anywhere that does this. If your crunch is going to last a long time, or looks like it will need to be lengthened, give people a day off. Say "Okay, everyone can take a day off free sometime in the next two weeks." Giving them a time frame allows them to plan for things like short trips, or time with their family. They'll come back rested, happier and more productive.
  5. Make sure they have and know the reward: In a start-up, the reward is in the stock, but in larger companies, make sure people know they will be compensated of extra hours, and then compensate them.

Hopefully this makes sense. I don't like crunch either, and it is avoidable for companies that have really experienced teams and a certain amount of give, but some companies do not and will not have the luxury to avoid crunch entirely. Obviously, great companies will always avoid crunch, usually because they've learned from their mistakes. But realize that a good company may crunch, but will always find a way to mitigate it when and if it happens, and will learn from their mistakes on their way to becoming a great company.

This weekend Boston Game Jams ran Cardboard Jam, a game jam where everyone made board or card games instead of making digital games. I have to say, I think I had way more fun at this game jam than at almost any other digital jam I've been a part of for a few reasons.

First, there's no tech choices or learning curve. At game digital game Jams, the first thing you have to do (once you have a game you want to create) is decide what technology you want to work in. This can be tough when you have multiple people who all come with different tech backgrounds and make them try to work together. Either you end up choosing teams based on tech that people know, or a few people end up working in tech they are unfamiliar with. This can make many digital game jams more about overcoming technical challenges, rather than overcoming design challenges in the game.

Second, other than the theme of the materials, there was no theme for this Jam. Though originally I thought this was a detriment, I am beginning to think that the lack of theme contributed to making this Jam awesome. In every game jam I've participated in, the themes have been aesthetic. They're themes like "immigration," "extinction," or "deception," and although they offer a good constraint on the Jam (and place everyone on equal footing for implementing an idea), they force most Jammers to think in terms of aesthetic first, mechanic last. This is why most Jammers can't "finish," because they're actually pushing for an aesthetic, rather than mechanical goal.

Last, jamming in board games meant that iteration cycles were really, really fast, which meant that you could focus on and tune the game and the mechanics quickly, which resulted in better games across the board. The game I worked on took about 10 minutes to play, and after initial discussion, we did nothing but play it, with short discussions in between. We probably play tested the game 50 times, each time with slightly tweaked rules to attempt to address problems we were seeing in the previous play through. Iteration times like this not only let you learn more about the game you're creating, but more about game design in general, since you see the results of you actions quickly. This speed of iteration and learning would have been impossible in a digital game jam, since implementing rule changes requires too many cycles. In digital game jams, if you get two to three full playtests in before time is up you're lucky, and that's including for teams that use prebuilt engines like Unity.

So in closing, if you get a chance to participate in a board game jam, you absolutely should. There's less stress, more learning, and way more collaboration. That, and you end up with an actually complete board game at the end, which is super awesome.

I was at Northeastern last night talking with programming students about getting into the game industry.  As with most students, they were very curious about what, specifically, they should learn in order to make it easier for them to get into the game industry, and where they should learn it.  I gave some standard advice (which I'll probably write up a blog post about at some point, maybe?) but I realized that one way to find really good places to learn is through the blogrolls and recommendations of talented developers.

And then I realized I haven't updated my blogroll, probably in a year at least.  So, I've updated it this morning, fixing links to places like t-machine, removing some long dead blogs, and making a few additions.  Some recent additions:

  • Games From Within: Noel is now an iPhone developer, but his development methodologies are really what I look at in his blog.  He updates fairly frequently and his articles are almost always good.
  • Bitsquid: I'm not sure really what Bitsquid is working on, but their programming posts are fantastic.
  • Insomniac R&D: Awesome posts from Insomniac devs
  • #AltDevBlogADay: There is so much awesome in this (basically aggregate) feed that I often I can't keep up with it.
  • Brett's Footnotes: Brett is a lead programmer at Bethesda Game Studios, but wasn't there when I was.  He's awesome and his posts are always interesting.

I will do my best to keep my blogroll up to date from now on, though I can't make any promises.

GDC is over, and my talk "From College To Industry: 20 Lessons Learned for Getting the Most out of Your Early Career" went fairly well I think.  The room was packed, which was no small feat considering how big it was, but I think that was mainly because those attending the Career Seminar had nowhere else to go during that time.  I could be wrong, though.  The title could have been that good.

Regardless, the slides for the talk are now posted and available for anyone.  I've been asked to give this talk a few more times, but I think I'm going to revise it a bit.  I really want to emphasize the two points about knowing business and making sure all the founders of a company are on the same page.  Of all the points in my talk, these two feel like the most important, but also the most belabored by other speakers, and also the most ignored.  They may be lessons that you have to learn the hard way, but want to do everything I can to really hammer those points home.  Hopefully I can accomplish that with revisions.

If you attended the talk, I'd love to hear your opinions and feedback.

I've posted my talk on getting the most out of data driven programming that I gave at Game Forum Germany a few weeks ago on my website. The talk recommends reflection as solution to a lot of the potential pitfalls of needing a single editable location for fields and properties and, interestingly, fellow Toolsmith Geoff Evans has an article in Game Developer this month about that same topic, and specifically how they solved it in Helium. So if you're thinking about using reflection to do automatic UI generation and serialization, definitely give that article a read.

I've been told that there will be video of the talk at some point, and I'll let you know when that's available.