Showing posts with label Game Jam. Show all posts
Showing posts with label Game Jam. Show all posts

Saturday, July 2, 2011

Game Jam Tips

I've done a few game jams. At Google, I've done a few at work, and been asked for tips on running them internally and externally. Thanks Seth Ladd for nudging me to post. So, why not jot some thoughts down here:

Prepare, and make sure participants are prepared. You want to spend the jam making awesome, not doing the boring stuff:

  • Publicize frameworks in advance and encourage attendees to come with 'hello world' games already under their belt so they can hit the ground running. Possibly include a super simple template of our own that isn't a 'framework', but just a tiny simple example.
  • Publicize easy / free tools for e.g. audio & 2D drawing. (e.g. Audacity & Paint.Net)
  • Publicize source control and encourage teams to already know how to use it, set it up in advance, and have made a trivial pull, edit, push cycle.
  • Publicize game hosting tech (appengine, nodeJS) and point to relevant examples (Well, for web games)

Hold something back until the Jam - usually the theme. Generate a surprise theme that balances creative license and enough constraint to remove the 'blank page' effect.

Decide to allow pre-formed teams or not. Most Jams I've been in discouraged pre-formed teams or game concepts. Instead, we brainstormed them up, pitched them to the wide crowd, and formed small teams to work on the top ideas. Pros and cons either way, but I've enjoyed the mixer style.

Small teams tend to work out much better than large. E.g. 2 or 3 coders. Communication is a killer on a tight schedule.

Have an art plan. Either set expectations that people should work with minimal art (e.g. procedural, 'retro' lo-fi-pixel-junk, or freely available stock), have artists and a plan for how to get art out quick, or pre made art. Some contests have run in two phases of 'prepare art' and then 'make games using only prepared art'.

Encourage rapid prototyping development practices! Games should be functional half way through!!! They'll need the second half for polish. People always always always blow this and mis-estimate. Encourage frequent re-prioritization of what people are working on. One good technique is have a team list out the top few tasks, rank `em, and have people work on those and only those. Don't work on anything unless it's an agreed top priority.

Eat, sleep, don't try to mash it all out. Taking short breaks through the day let's you get Meta, re-evaluate progress and priorities, and plan. Sleep helps you make the remaining time more effective.

Don't make it a contest, but if you do, run several wildly different categories. E.g. most original, best use of new tech, most hilarious. Don't just have "the best".

Plan for games to have more work done after the Jam, and how they will be publicized. Can teams update links, images, YT videos, etc?

Capture the presentations at the end, e.g. video recording. Snapshot the code and art too. (Good reminder, Mike Mahemoff)

Have fun. If it's not fun... do something fun. ;)

Monday, October 18, 2010

LootGrab: HTML5 Game from Triangle Game Jam 2010


Spoilers in the Video! Consider Playing LootGrab first. (As of Sept 2010, Chrome was definitely the best option since Firefox and IE struggled, you can give your smart phone a try too).

2010 Triangle Game Jam game: LootGrab Video on youtube, or LootGrab Video on vimeo.

This year brought changes from the Game Jams of past:
First, I moved from the Research Triangle and now work at Google, and Adrienne came too (we've worked together on 5 of the game jam projects now). So, we got some fresh blood at Google to join us and ran a game jam in parallel with the 2010 Triangle Game Jam.

Second, instead of using C# we used HTML5 this year:

Third, you can Play LootGrab with a click of a button - ridiculously easy compared to all previous Jams where I didn't even bother giving you the gazillion prerequisites required.

Theme and Game Ideas
The theme this year was, "Placing Blocks". Here is my game concept, which didn't make the cut::


(someone pointed out it would be great from the side too, with ballistic arcs.)

We voted up ideas, and Adrienne's one out: LootGrab is about placing down blocks in a dungeon to influence the hero, instead of controlling the hero directly. The greedy guy runs for the closest loot, food, or exit ... without care for monsters or traps.

We figured we'd need a map editor, the runtime, and perhaps a level sharing system online via AppEngine. I was particularly attached to an idea of allowing user contributed game object definitions. Allow a user to upload an image and a snippit of javascript that defines it's behavior. How cool would a mod-able game jam game be? :) That was stretching a bit far though.

HTML5

HTML5 is a grab bag of new functionality in browsers. Some of it is pretty cool (peer to peer networking, local storage, video and audio tags). We focused on two simple components, canvas 2d to draw and audio for sound effects.

In my day job I'm working to accelerate canvas with GPUs, as are others at Microsoft, Mozilla, and Apple. It's fairly fast even in software, and LootGrab runs fine without GPU acceleration. In fact, it runs on phones pretty well, such as my Nexus One Android phone. That's pretty cool, all we did to support mobile was to make sure we handled low frame rates without changing gameplay. To do that we used fixed time step gameplay logic (tick based), and just run as many ticks as needed to cover the amount of time elapsed.

Our use of canvas is basically clearing it, drawing a pile of sprites (via sub-rectangles of larger images), and also a line to show where the player is moving. Actually, we have a few layers of canvas stacked on top of each other. Theoretically we could have saved performance by not redrawing non animating tiles - just compositing them underneath.

Adrienne took on audio for sound effects, and did run into a bit of trouble. The sound effects were very short, and had to be padded out to longer audio lengths to trigger properly. Also, multiple instances needed to be created in case the sound was played more than once.

Javascript

Several of us hadn't done anything substantial in Javascript before. Certainly not an object oriented game entity system that can factory from user created levels. Some complicated flurry of activity by Glen, Ian, Nat, and Gregg made that happen. The result could be cleaner, but worked well. We have JSON data blobs, e.g. for the tile definitions.

Things I loved:
Need to add extra data to your level components of game object definitons? Perhaps only to particular items? No problem! Just start typing. At runtime it is trivial to just check if the data is there and use it if so.

Writing some code and wish you could hang more data off an object? Just set that value! Check to see if it's === "undefined" later and you can pick up  your special data easily. Object definitions don't have to worry about implementation details of other systems, and those other systems don't need extra book keeping kept in parallel. e.g.:

  try {
    ctx.drawImage(this.img, ...);
  } catch(e) {
    if(this.error_printed === undefined) {
      tdl.log("problem with image " + this.entDefID);
      this.error_printed = true;
  };


Development tools: Logging. Resource load timeline. Immediate mode editor: Hit a breakpoint, and just execute some code at the Javascript console.

Fast iteration time, though C# was great for that too.

Instant continuous "build"! Glen installed an Auto Reload Chrome extension and put the game up on a projector. Check in some code and see the game running it in 20 seconds. ;) Helps to have a game that can play its self.

Libraires such as TDL, and JQuery: some helper code for Javascript. It's not so important what you use, but you definitely want to not worry about the minutia.

Not so great?
I didn't use an IDE that had code analysis, and that's a very convenient feature of MSVC. Though, Ian had good things to say about WebStorm.

Also "classes" in javascript are syntactically very sad, and inheritance to my novice eyes looks messy. And variable "scoping" is dicey.

Debugging is functional and GUI, which is better than what most programmers use around my on linux. But it falls short of a modern debugger such as MSVC with C++ or C#.

Also, deciphering a web page via HTML, script, HTML embedded in script, CSS files, and dynamic changes to styles? ... yikes.

Things for Next Time


Would be nice to have some basics already written:
- Factory that will created entities from JSON data packs
- Cleaner audio solution
- Sprite system for canvas

Smaller teams. We had six on this project, and that's a bit much for a game jam game. Several were first time jammers, and several Javascript newbies, so it did really help to share know-how. But we wasted a lot of time getting started, coming to consensus on implementation choices, and stepping on each other's code.

The End

And now I leave you with some screen shots:


And a thanks to whoever oryx is, who created the sprites we used:

Tuesday, October 20, 2009

Pixelated Martini Roller - Game Jam Video

I've posted about Pixelated Martini Roller before, including a cell phone video recording of an IGDA presentation and a description of the collision. But dear blog readers you've never been able to see a high quality video. Here it is:



Best watched in High Definition / full screen, with vimeo or youtube.

If you don't recall, it's one of the Triangle Game Jam games I've worked on, this one from 2008.

Three.5 of us made the game in 2 days, based on the madlibs jam theme that randomly made the title "Pixelated Martini Roller".

You're an olive. You like martinis. You roll around and get to umbrellas for checkpoints. Sitting in a martini glass gets you a bit tipsy. You've got more energy and can jump higher. But watch out, stay too long and you get sloppy. You'll stagger around, and your jumps won't land you where you want to go.

As you get tipsy the screen gets pixelated, and the music sounds like it's had too much to drink too.

The world was created with an in-game level editor. The objects are just a few images that represent the visual and collision texels.

We've noted how fun it is to implement hacky collision over and over again in a weekend, but I liked coming up with and working on the pixel based collision we did for this one. I also enjoyed writing the post FX pixels and rushing out the level design in the last hour. ;)

Thanks for Michael Noland and Adrienne Walker for working together on this game with me, and Brad for the title screen.

Wednesday, July 15, 2009

Diving - Triangle Game Jam 3 - Music Game



Video links (Recommended viewing in H.D.): youtube, vimeo.

The 3rd Triangle Game Jam was last weekend! Hot off the presses, the game I worked on: Diving. (The other games have not yet been posted on that website yet -- we're all busy catching up after speding the whole weekend making games)

The theme was Music Game, similar to how music and video can be used to make a music video experience. The theme was inspired by Reset.

In Diving, the gameplay is subtle. The game is primarily delivering an experience well tuned to the music. I'm pleased that our design captured the mood of the music, synchronized to the lyrics, and also the piano notes.

The actual gameplay mechanics allow you to steer left and right as you chase the ring down into the depths. While that's a bit simple, the concept of the woman at the railing, jumping after the ring, and swimming down after it ever deeper, is the real point. The game is designed to never let you actually catch the ring, it's always just out of reach and lands on the ground always at the end of the song. As the song closes and the woman just about reaches the ring, there's a fade to black.

The song and concept seed were Adrienne Walker's, and I contributed significantly to the final design we presented.

Contributers:
Brett Brown (Title Art) (Electronic Arts)
Derek Ehrman (Programming) (Atomic Games)
Vincent Scheib (Gameplay Art/Programming) (Emergnt Game Technologies)
Adrienne Walker (Programming) (Emergnt Game Technologies)

The song was Feathers by Man Man.

Monday, February 23, 2009

The Escapist Show coveres the Triangle Global Game Jam

The Triangle site of the global game jam was covered by The Escapist Show:



After the "48 hours later" montage, all games shown were developed by our game jam group.

Monday, February 2, 2009

Global Game Jam: Robot Love

The Global Game Jam weekend is over, and I'm excited to say I got to help out on Robot Love:

High Resolution Version available on youtube website.

The theme was, "As Long as We Have Each Other we'll never run out of Problems..."

Gameplay: A 2 player co-op game with a simple gimmick, you need to stand next to the other player to reload! Two robots are escaping their factory, chased by mobs of other zombie robots.

Credits:
  • Demond Rogers (Epic) did an awesome job at the character animations.
  • Jason Connell (Red Storm) built the 2.5D environment.
  • Adrienne Walker (Emergent) was ninja lead programmer.
  • Harrison Moore did sound and UI.
  • Will McGuire coded and placed enemies and props in the level.
  • Mike Daly (Emergent) chipped in on level file format and robot AI.
  • Vincent Scheib (Emergent) helped with collision, a bit of gameplay, and gamestate/screens.
Download it!

Saturday, January 31, 2009

Global Game Jam: Kicking off the Triangle

The first global game jam has been kicked off! Although I can't participate all weekend, I did help get things started at the local triangle game jam. You can check in on them with this ustream:



Icarus studios is being an excellent host, setting us up in their motion capture room and having wired up a LAN for us. We've got just under 20 participants, with 4 games in development (brainstorm names: Breeder, Tethered, Robot Swarm, Buttons and Mindy).

Monday, May 19, 2008

Pixelated Martini Roller - Collision - Triangle Game Jam 2008

More Pixelated Martini Roller game stuff (other posts)... I just pulled everything off my camera and noticed this video showing the collision system in progress:

Collision system in progress
(a final video can be found here)

I figured I'd briefly write up what we decided to do for the collision / physics. Nolan had already put together some simple gameplay motion. We used Aristotelian physics: objects are at rest unless something actively disturbs them. AKA apply velocity only, not acceleration. Well, some velocity is recycled frame to frame... but, that not what I really was going to talk about. That would be collision:

We wanted:
  • easy to make art
  • simple to code collision
  • fairly decent performance, even with lots of objects, but lets just get the thing working quickly
  • robustness even when many objects are overlapping
We really only considered
  • making piece wise linear shapes, aka polygons, to represent shapes
  • making images to represent where shapes were solid
We ended up with colliding against images because it greatly simplified art workflow (just paint a version of the sprite with what you wanted to be solid), would allow for pretty complicated shapes, and I figured the code may be easier.

Nolan and I pair programmed it at the end of the day Saturday, good thing too, we were both getting tired. Here's what we did:
  • The olive is a circle in gameplay.
  • Initialize a 1D buffer representing the closest any surface is to the center of the circle for a given arc. We ended up cranking this up to an arc being 1 degree. Init value is float_max. Call this buffer buckets.
  • For all sprites:
  • transform the circle to sprite local space
  • check if you're overlapping the sprite at all
  • for the overlapping area, scan through all texels:
  • if the texel is solid, transform it to polar coordinates, and set the bucket value if this new point is closer to circle center.
  • ...
  • Then, check through all the buckets, did we find some collision and some not collision?
  • If not, quit, can't do anything useful.
  • If so, scan through the buckets looking for the largest open area. This will be the widest open space around our circle, and the way out.
  • (btw, need to loop around the circle, regardless of the buffer's boundary, so everything uses modulo math)
  • Find the center of the largest open space, and consider that the normal to the surface.
  • ...
  • Now, get out of whatever objects we may have gotten into:
  • for every bucket, transform out of polar coordinates, and then compute the distance from that point to the penetrating side of the circle, in the direction of the normal. The max value tells us how far to move out along the normal to no longer be in collision.
  • ...
  • If we have any velocity along the normal, remove it (we we don't move into the object).
  • Take a portion of that velocity and apply it tangentially, to keep up some momentum.
  • ....
  • And, if we hit the surface hard enough, make some noise.
Overall I think the system worked out pretty well. It was very easy to make art. The gameplay felt pretty good. It was fairly quick to code. It was pretty robust, even when nasty shapes.

Downsides: The olive was overly sticky to some surfaces, you can crawl around objects sometimes a bit before falling off. That was related to us basically turning gravity way down if you're already sitting on a surface. Without doing that you couldn't roll around as freely as we liked.

Note: Noland replied to this post --- check out the comments

Code from the above, if you're into that:
static bool debugGeom = false;
static int numBuckets = 360 / 1;
static float[] buckets = new float[numBuckets];

public static void DetectCollision(DynamicObject dObj)
{
for (int i = 0; i < airborne =" true;" sobj =" bObj" collisiondata ="=" localcenter =" dObj.position" localradius =" dObj.radius" y =" (int)(localCenter.Y">= sObj.TexCollision.Height)
continue;
for (int x = (int)(localCenter.X - localRadius); x <>= sObj.TexCollision.Width)
continue;

Vector2 sampleVec = new Vector2(x, y) - localCenter;
if (sampleVec.LengthSquared() > localRadius * localRadius)
continue;

float angle = (float)Math.Atan2(sampleVec.Y, sampleVec.X);
int bucket = ((int)(angle * numBuckets / (2 * Math.PI)) + numBuckets) % numBuckets;

Color c = sObj.collisionData[x + y * sObj.TexCollision.Width];
if (c.A == 0)
continue;

buckets[bucket] = Math.Min(buckets[bucket], sampleVec.Length()) / localRadius;
}
}

}

// Find the longest bucket chain
int first;
bool found = false;
for (first = 0; first < found =" true;" chainmiddle =" 0;" maxlength =" 0;" thislen =" 0;" i =" 0;" b =" (first"> maxLength)
{
maxLength = thisLen;
chainMiddle = (b - thisLen / 2 + numBuckets) % numBuckets;
}
thisLen = 0;
}
else
{
thisLen++;
}
}

// find the distance we need to move to get the circle not penetrating

float rot = (float)(chainMiddle * 2 * Math.PI / numBuckets);
Vector2 collisionNormal = new Vector2((float)Math.Cos(rot), (float)Math.Sin(rot));

// Fix up penetration position
// walk through all buckets, project point back into local dObj space
// Find longest distance along normal to sphere edge
// translate the sphere that distance along the normal
// NOTE: given that we only store one value in bucket[], it's possible there
// is a slightly more distance value that has a higher penetration depth.
// Oh well.
//
// Also, this isn't quite right for the martini glass. It works *well enough*.
float penetrationDistance = 0;
for (int i = 0; i < bucketrot =" (float)(i" point =" new" pointdotnormal =" Vector2.Dot(point," basedotnormal =" Vector2.Dot(-collisionNormal," distpointtospherebase =" pointDotNormal" collisiontangent =" new" pointdottangent =" Vector2.Dot(point," angletopenetrationpoint =" (float)Math.Acos((float)Math.Abs(pointDotTangent));" distspherebasetosphere =" (float)Math.Sin((float)angleToPenetrationPoint);" distpointtosphere =" distPointToSphereBase" penetrationdistance =" Math.Max(distPointToSphere," positionadjust =" collisionNormal" adjustlen =" positionAdjust.Length();"> 0) ? 1 : -1) * adjustLen / dObj.radius;

if (debugGeom)
{
Level.DebugRecord s;
s.center = dObj.position;
s.v = collisionNormal * 30;
s.c = Color.Blue;
s.scale = 2;
Game.level.DebugVectors.Add(s);
}

float objVelocityOriginalMagnitude = dObj.velocity.Length();

float ColisionNormalDotVelocity = Vector2.Dot(collisionNormal, dObj.velocity);
float dotNormalized = ColisionNormalDotVelocity / objVelocityOriginalMagnitude;
if (ColisionNormalDotVelocity > 0)
return;

dObj.airborne = false;
dObj.lastGround = 0;

Vector2 penetratingVelocity = collisionNormal * ColisionNormalDotVelocity;

// Remove penetratingVelocity velocity from object
dObj.velocity -= penetratingVelocity;

// Transfer velocity that was penetratingVelocity into tangential
float objVelocityTruncated = dObj.velocity.Length();
if (objVelocityTruncated > 0.01)
{
float amountToTransfer = (1 - (-dotNormalized)); // transfer only if not directly into collision
float objVelocityResulting = MathHelper.Lerp(objVelocityTruncated, objVelocityOriginalMagnitude, amountToTransfer);
dObj.velocity *= objVelocityResulting / objVelocityTruncated;
}

// Should we make a noise?
const float minHitVelocityForSound = 1f; //TODO make this better? tune it in XACT or something?
if (Math.Abs(ColisionNormalDotVelocity) > minHitVelocityForSound)
Game.sound.soundsToPlayThisFrame.Add("hit");
}

Sunday, May 11, 2008

Triangle Game Jam, It's Over!


Nicer videos and reports will come later I'm sure [EDIT: Here is high quality video], but for now here's a handheld video of the Pixelated Martini Roller when we ran out of time:


You're an olive. You like martinis. You roll around and get to umbrellas for checkpoints. Sitting in a martini glass gets you a bit tipsy. You've got more energy and can jump higher. But watch out, stay too long and you get sloppy. You'll stagger around, and your jumps won't land you where you want to go.
As you get tipsy the screen gets pixelated (hard to see in this video), and the music sounds like it's had too much to drink too (hard to hear in this video).
Thanks for everyone at the Jam for a good time. Thanks for Michael Noland and Adrienne Walker for working together on this game with me, and Brad for the title screen.
(music by STU, 8bitpeople.com, MyMelody, Creative Commons attribution license)

Saturday, May 10, 2008

Triangle Game Jam part way results

The theme is game madlibs. We've picked several ridiculous game titles to implement, and several teams are well under way. I'm working on Pixelated Martini Roller:



But, you've also got to check out the progress on Musical Dragon Twirler:


Getting sleepy now....

Friday, May 9, 2008

Pre Triangle Game Jam, May 2008

The Triangle Game Jam 2008 starts tomorrow! It'll be quite exciting. This is the second Triangle Game Jam, we did one last summer as well. There, Mike Daly and I made Shape Slasher:


Mike had the idea to cut up shapes and try to score the result based on how nice of a triangle it was. We decided that the size of the triangle shouldn't matter, just how close it was to an equilateral triangle. Mike wrote some scoring code for triangle shapes, and I wrote a definition of n-gons and code to cut them. We decided to always have convex shapes.

Things turned out well, Mike made some procedural level generation code with different shape size, irregularity complexity, and speeds. I dressed up the graphics a bit, worked on the code for cutting and movement, etc.

We added special bonus rounds as well, so gamplay alternates between levels with moving random pieces, and bonus rounds with shapes that start off still. Your job is to quickly decide how to cut and collect as many triangles as possible in a limited amount of time.

The game turned out to be pretty fun, and we had a good difficulty curve over the duration of several levels. The final stage is quite challenging, and the last bonus stage is a rare treat. ;)

Since the first game jam, spending a lot of energy getting used to XNA and C#, we've gotten faster and continued to use XNA.