Guest Post HD Cheese Game Jam Postmortem


Posted on November 10th, by Marvin Hawkins in Chicago Game. No Comments

Chicago Game Jam 2013 Post Mortem

(Grave Danger by HDCheese)

Grave DangerThe Team

Team HDCheese is:

  •  Mike Turano (programming
  • Brandon Sharas (art)

We had music assistance from the talented Marcus Bailey.

The Setup

We participated in the Chicago Game Jam 2013 at The Nerdery October 25 – 27. It is listed as a 48 hour

game jam, but was in reality more like 30-something hours. The theme was announced Friday night,

teams formed, and then everyone went home and came back out around 8 AM the next day to work

right through to the deadline the next morning. We came with our 2-man team already formed: a

programmer/artist team where I was doing the programming and Brandon was doing the art. I used

the excellent libGDX (a cross-platform Java framework somewhat similar to XNA in scope) to build

our game, with some small amount of my own code to handle game state management, some display

conveniences (animation management, aspect ratio correction for game world drawing, etc), and a few

math functions. I wasn’t doing it from scratch, per se, but I was definitely missing out on a lot of basics

that would have been provided for me by an engine like Unity, Gamemaker, GameSalad (who was a

sponsor, yay!), or even a more mature personal engine.

The theme was announced: “Death.”

The Design

It surprised us how broad the theme was, but it was going to allow us a lot of freedom in our design.

Immediately after the theme was announced Friday night we started spit-balling ideas. We pretty

quickly settled on one – we would make a local co-op game with a small level where the players were

grave robbers in service of a mad doctor who needed “parts” for… whatever evil things he does. The

players need to rob graves in order to fulfill a quota of “parts” in order to proceed to the next level.

There would be graves that needed to be “dug out,” which would take a certain amount of time, as

meanwhile the players were being hounded by enemies. Upon opening a grave, there would be a

chance that either helpful body parts would spawn for collection or a vicious enemy would spawn to

attack the player. Combat would be difficult, to discourage brawling and encourage running, hiding,

and teamwork distraction of enemies. We also wanted to somehow implement a betrayal mechanic

– all players and enemies would drop parts when they died, so if your teammate died – either by an

enemy’s hand or yours – you could then collect his parts and they would add to your total. Levels would

be small, and the map would be tile-based, but allow dynamic entities (players, monsters) to move in

between tiles and handle collision with axis aligned rectangle collision with other dynamic entities. The

maps would be randomly generated, but there would be no rooms and few objects that were barriers

to movement in order to keep the generation process simple. We also wanted there to be “items” that

players could only use one at a time, which would either make you better at fighting or better at digging,

in order to encourage sort of a player class mechanic. Body parts would have to be carried back to a

cart at the end of the level (taking up your item slot) in order to be counted towards your total.

We came up with a title right away – “Grave Danger.” We loved the design – this game was going to be

awesome, the scope was reasonable and it would be super fun!

There was a lot of emphasis on mile stones during the opening presentation at the game jam, and we

wisely took it to heart. We created some mile stones for our game, and as a broad estimate I basically

rated each milestone as “difficult” or “simple” in terms of required time investment. Here are our

milestones, roughly in order:

1. Collision and Movement (difficult)

2. Animated Sprites (simple)

3. Multiplayer (simple)

4. Automatic Level Generation (difficult)

5. Enemies (difficult)

6. Combat (difficult)

7. Items (difficult)

8. Win/Loss Conditions (simple)

As a basic estimate, I was assuming any “difficult” task to take 6 hours, and any “simple” task to take 2

hours. It looked like we had our work cut out for ourselves, as by the time we had settled on this list of

milestones, we had less time than the indicated total – not allowing any time for sleep between Friday

night and Sunday morning. I was banking on having over-estimated, though, so we went to sleep Friday

night confident of our ability to pull it off.

The Reality

We woke up early the next morning and arrived at the venue – The Nerdery in Chicago (http://

nerdery.com/) – who generously allowed us to use a portion of their well-equipped space that included

a projector, a common area with several tables, and several rooms with white boards that teams could

shut themselves in to work / take a nap in.

We arrived not long after the venue opened in order to claim a good spot at a table. We didn’t

oversleep and seemed to be one of the first few groups there. We picked up some McDonald’s

breakfast on the way over. So far, so good.

Brandon chose a very distinctive style for all the artwork that would be mostly 90 degree angles, with

occasional use of 45 (or so) degree angles. He mocked up some characters and we were both excited

about the art direction. He started pumping out characters and their associated animations. It would

be a top down game, so he would need to animate everything from 4 directions (my simple animation

system had only handled side view before, so in order to keep things simpler for me he was willing to

flip the animations himself and I could just treat them as separate assets). We didn’t see this huge

undertaking as too much of a problem for him, as we knew I would be the real bottleneck for time

anyway.

One of the sound guys there, Marcus Bailey, was offering to make music for teams besides his own.

Brandon talked to him about the game’s vibe to try to get the music straight. A little while later Marcus

came up with a creepy but catchy little tune for the game and our music was covered.

I began to work on collision and movement. As a test run in the week leading up the jam, I had coded a

simple tile-based map collision system with dynamic entities that had discrete movement from scratch

as practice. I could pull this off in about 5 hours over 2 practice sessions at home. I started on the

movement first. I was using integers to represent the velocity and map positions, but breaking out any

fractional portions into vectors and floats in order to allow acceleration and deceleration based on time

rather than simply setting the speed every frame. This was a mistake, as I was somehow getting this

wrong, even though in my practice session it had been working fine. The movement took too long.

Then I got into making the controllers work. Handling 2 axes of movement input in a top down game

with a controller was a bit weirder than I had anticipated, and I hadn’t actually practiced with the

controllers – my only experience using controllers in libGDX had involved a single axis of movement…

diagonal overhead movement and it’s interplay with the controller-sent input became a major disaster.

A few hours went by before I hacked in something less interesting but more predictable than the weird

behavior I was initially getting. I wasn’t handling diagonal movement properly at all, but if the player

stuck to the 4 cardinal directions only it worked. I was behind, and I hated the way my movement felt,

but I tried to move on.

Then it was on to collision. I thought I knew what I was doing here, also, but right off the bat I started

noticing some wonky behavior that I hadn’t seen during practice. Things weren’t being displaced out of

“barrier” map tiles correctly, my calculations seems to be weirdly off, it was impossible for the player

to pass between a 1 tile gap, and when I undersized his collision boundary too much my formula didn’t

work anymore. If I undersized the characters just a bit it could work better, but required an unfair

amount of precision from the player. My mental state really started to deteriorate. My movement

sucked and my collision sucked, and I was spending way too much time on it. We broke to eat at some

point, and the short walk and break to eat some fast food helped me realize one of the mistakes I

had been making – having to do with the fixed time step I had sloppily implemented. That realization

did help, but it didn’t fix the most glaring issues with my broken system. I had to toss in some magic

numbers before I finally got it to “mostly work. “

I was really depressed and angry at this point. My most basic systems were already bug riddled, and

they had taken way too long to get to a just-barely-working state. I was getting ready to move on to

something else, but then I took one more shot at the movement velocity– ripping out all the integers

and just changing them to floats, and hacking apart anything that got in the way. It worked to make the

movement a lot better than it was. Collision was still screwed up, and the controls still didn’t handle

diagonals properly, but the movement was much better than it had been.

Next, I put the character graphics and animation for the player in. Brandon had wisely created

placeholder graphics early on, but we were already so far along on time and he had already made so

many “final” assets that I just put in the final version of the player graphics. We noticed that the scale

was off – his great artwork was getting scaled down badly and suffered a bit for it. It was too late,

though, so he just kept the same scale as he kept working. “Just get it to work” became our mantra.

I moved on to combat next. I made a simple attack that would have the attacker create a hit box in the

direction he had most recently been moving in that could strike any entities (including players), and

introduce a “stun” to himself that would prevent him from accepting any commands again for a time.

Attacks would also “stun” an opposing entity hit by them. It worked about how I had expected and

there weren’t any surprises there fortunately.

At this point we had about 10 hours left for everything else. We re-examined our milestones and

decided to cut out the concept of items entirely, and remove the concept of win/loss and parts

“carrying” entirely – your “parts” would just become your score and you would try to get the highest

score you could.

I got “digging” working next by simply having the player attack the graves in order to chip away at their

“health” before transforming them to “open graves.” No surprises there.

I moved on to enemies next. I got a “night watchman” enemy occasionally spawning randomly in the

level. He had two states: wander and chase. I wasn’t going to get fancy with the AI, just have him do

really dumb chase where he looks for the closest player and then chooses to walk towards him along

the longest axis, or for wander he will randomly choose a direction. I made them attack whenever the

player was very close to them, and because I had already made the attack dependent on the walking

direction, and the enemies would always walk towards the player, the attack basically magically worked

for the enemies. When they bumped into map objects they would enter the wander state for a time.

Overall the enemies ended up behaving better than expected and were completed fairly quickly.

We threw out random generation entirely and I asked Brandon to draw out a level on graph paper we

had brought and I would just hard-code the map values using what he came up with.

There were probably about 4 hours left at this point. With enemies actually chasing the player now

(and viciously murdering him) as he tried to run around and dig up graves, it was starting to feel more

like a game. Brandon had been begun working on all the sound effects, finding objects to use and

using his voice to record sounds for attacks, hurt sounds, etc. I put in the “parts” next. When a grave

was opened, or an enemy died, or a player died, 10 parts would randomly spawn, some of which were

uncollectable “bones” that didn’t add to your parts total. It all worked.

We finally started playing multiplayer for the first time. I hacked in some camera zooming to attempt to

address players leaving the same screen area. It was far from perfect and consisted entirely of guessed

magic numbers, but it kind of worked. “Just make it work.”

We had about 2 hours left. We had never added the enemy that could spawn when you dig up a grave,

and I didn’t feel we had time to do it. We left out the skeleton enemy Brandon had already created all

the animations for because I didn’t think I could fit it in time. I finally put in sound effects that Brandon

had recorded, and the music Marcus had made. This was all straight forward. My simple sound library

was configured to accept multiple sound files as the definition of a single type of sound and randomly

select between them automatically, so I was able to use all the various sounds that Brandon recorded

to add a bit of variety to the sounds without any real time investment on my part. We did some last

minute tuning, I inserted Brandon’s title screen and loading screen images. It was stretching them. Oh

well, just make it work.

I did some minor tuning to movement values at the last minute, I think I screwed it up a bit as

movement ended up “slidier” than I had intended, but time was basically up. We also never really

built in a compelling reason to betray your teammate, as doing so would only cause the enemies to

concentrate on you instead. You could still collect their parts, though.

Despite everything, we had finished! It was a fully functional, if buggy, game! Multiplayer was actually

kind of fun, and the art and music really made it pop.

What Worked

The milestones were crucial. Being able to look at our milestones regularly and determine what was

truly necessary for a complete game that accomplished as many of our design goals as possible and

was still possible to create in the remaining time is the only thing that allowed us to finish despite my

programming disaster. Here’s how our milestones ended up shaking out:

1. Collision and Movement (difficult) <– broken but “works”

2. Animated Sprites (simple) <– inefficient asset creation but works

3. Multiplayer (simple) <– works, but no usability polish

4. Automatic Level Generation (difficult) <– cancelled due to time

5. Enemies (difficult) <– works

6. Combat (difficult) <– works

7. Items (difficult) <– cancelled due to time

8. Win/Loss Conditions (simple) <– cancelled in favor of simple “score only” setup

The scope was realistic. We did a good job of not going too far overboard with our scoping. Even

though the “items” idea turned out to be a bit much, we still had a complete game without it, so that

proves the concept was not fundamentally too large.

We had done 1 game jam prior to this (our first), and we were woefully ignorant of how to scope

appropriately, or how to plan our time. It was a miracle we got something working by the end of that

one, and it was only because of wide swaths of feature slashing that ended up creating a game utterly

different than what we had planned and envisioned.

What Didn’t Work

I didn’t stick to the milestone order as strictly as I should have. Mainly, I should have started putting

Brandon’s placeholder graphics in earlier so that he could have adjusted the size of the assets he was

creating to be more appropriate to the zoom level we were working with for the game. More generally,

this issue with the art pointed out that our workflow could use some additional tooling or at a minimum

just earlier and more in-depth coordination before all the parameters for generated art are settled

upon.

I was not truly accounting for the fact that code created under pressure is not as good as code created

at home with no time pressure. I am not a brilliant savant programmer. If I had just taken the simple

way out with movement earlier (not bothering to break out integers and just using floats for everything

instead) I could have saved a lot of time and frustration. As far as collision is concerned, I probably

should have just gone with pure axis aligned rectangle collisions with inefficient checking instead of

even using tiles. What I will more likely do for next time is to have created my own general purpose 2D

collision system that is gameplay agnostic that I will make part of my “kit,” intended for use with all 2D

games I make going forward.

The other option would be to learn a tool like GameMaker, GameSalad, etc, but I like to use game jams

as an opportunity to beef up my general purpose tools anyway, so for me that option is not a good one.

I would highly recommend using these tools for anyone interested, though!





Leave a Reply

Your email address will not be published. Required fields are marked *



From The Blog