Wednesday, October 10, 2012

October 2012 challenge, Day 10

I only had a few hours to program over the weekend but I managed to get saving and continuing to work - which took much longer than I expected. If you're looking for advice on how to save objects to the SharedObject with Flash or haxe and nme, I ended up relying on the Memento Pattern.

Here's the relevant part of the Fruit class:

public function toMemento():Dynamic
{
 return {
  x:x,
  y:y,
  vx:velocity.x,
  vy:velocity.y,
  maxSpeed: maxSpeed,
  maxAge: maxAge,
  type: type,
  plantType: plantType,
  age: age,
 };
}

public static function fromMemento(o:Dynamic):Fruit
{
 var c = new Fruit(o.x, o.y, o.type);
 c.velocity.x = o.vx;
 c.velocity.y = o.vy;
 c.maxSpeed = o.maxSpeed;
 c.maxAge = o.maxAge;
 c.age = o.age;
 c.plantType = o.plantType;
 return c;
}

One place where this was tricky was with the creatures' needs. Each creature has a list of needs that implement the Need interface. Since I don't know the real class at design time, it has to be handled differently. When creating the memento for needs, the class name is included and when converting the memento to the real object, a separate class takes the memento, looks at the need field, and has a switch statement that tells the appropriate class to create an instance from the memento. Here's the relevant part of the NeedToEatFruit class:

public function toMemento():Dynamic
{
 return {
  need: "NeedToEatFruit",
  target: target == null ? null : target.toMemento(),
 }
}

public static function fromMemento(o:Dynamic):Need
{
 var n = new NeedToEatFruit();
 n.target = o.target == null ? null : Fruit.fromMemento(o.target);
 return n;
}

Apart from that, I made some simple placeholder graphics for the plants and got the basic plant lifecycle to work. There's twelve species of plants. Some float to the surface, some are buoyant enough to float around, and others are planted in place. The simple ones are just a sprite but the more complex ones grow separate leaves. They can reproduce by budding, spores, seeds, or fruit. When a fruit-eating animal eats a fruit, it will wait 5 seconds or so then drop a seed of that plant. And that's why the Creature class has a pooCountdown field.
Next up is animal graphics, lifecycle, and more needs as well as changing the world structure. It's currently Perlin noise but when targeting the mac, it runs out of memory trying to make it. Really odd.

Friday, October 5, 2012

October 2012 challenge, Day 5

If you look at it a certain way, then I'm almost done. If you look at it the real way, then all that's left is the stuff I'm not good at.

After some late night work, pre-work work, and lunchtime work, I've got the core ideas working so now it's mostly a matter of adding content (graphics, sound, music, more game objects, etc) and fine tuning it. I'm sure there will be a round of performance optimizations, a round of cross-platform hacks, a round of feedback from beta testers, a round of panicked hacking, and a round of October 30th surprises. But not today. Today is good.

I don't want to give away too much of what the game is about (October is only 17% done after all) but here's the AI for other creatures:

package;

class CreatureController
{
 public function new()
 {

 }

 public function update(creature:Creature):Void
 {
  var lowestScore = 1.0;
  var lowestNeed = creature.needs[0];

  for (i in 0 ... creature.needs.length)
  {
   if (creature.needScores[i] > lowestScore)
    continue;

   lowestScore = creature.needScores[i];
   lowestNeed = creature.needs[i];
  }

  lowestNeed.update(creature);
 }
}

And here's a screenshot:

It's hard to see but there's two different background colors. The large squares are plants, the medium squares are animals, and the tiny squares are fruits. The green bar is your happiness. Later the squares will be things that look like what they are.

Thursday, October 4, 2012

October Ludum Dare challenge accepted

"Make a game — Take it to Market — Earn $1"

I'm in. I just got haxe setup on my computer and I'm ready to start working on an idea I've had for some time.

Things I still need to do:

  1. Make the game.
  2. Make it not suck.
  3. Make it look good.
  4. Make it sound good.
  5. Make an attractive website for it.
  6. Make sure it works on iPhone, iPad, and Android.
  7. Submit to the Apple App Store.
  8. Submit to the Android Market.
  9. Submit to some flash game site.
That's only nine things. I can do nine things in one month.

Thursday, August 30, 2012

Objectives that don't suck

It seems that most résumés have a generic objective copied from one of many "how to write a résumé" articles. You know the kind; "To utilize and expand my skills in blah blah blah". I think that's lame. Why start your résumé with some vague cookie-cutter bullshit that you copy-and-paste then forget about? My objective is "To work on a project that users want to use and maintainers want to maintain.". It's nothing fancy but it's honest and to the point and I actually believe it. I'm glad when something I create is useful to others and they want to use it. I'm glad when someone, usually myself or a coworker, is able to extend or change it to do something else.

But not everyone wants those things. Recent experiences with clients who are more concerned with making sure the software looks like it works rather than actually works reminded me that working software is the primary measure of progress. Because of that, I updated my objective to say "To create working software that users want to use and maintainers want to maintain." Even more true and even more to the point. And that's something I care about.

What's your resume objective? Do you actually believe it and try to live up to it?

Friday, August 24, 2012

Easier object setup in ActionScript

I recently thought of something that will make it easier when I'm creating instances with different values in ActionScript and thought I'd share it. It's sort of a mix of default parameter values and optional parameters and it makes it much more convenient to setup instances of things that are slightly different.

Let's suppose I have a Weapon class with some basic stats:

class Weapon
{
 public var name:String;
 public var attack:int    = 10;
 public var defense:int   = 10;
 public var speed:Number  = 1.0;
 public var heavy:Boolean = false;
 public var tags:Array    = ["weapon"];
 
 /* skipping constructor and a "describe" function that prints the values */
}

And assume I have some other code that creates a bunch of instances. They're mostly the same but ideally I could just specify what's different than the default. Something like this:

var weapons:Array = [
 new Weapon("stick"),
 new Weapon("sword", { attack: +2, defense: +2 } ),
 new Weapon("club",  { speed: -0.25, heavy: true } ),
 new Weapon("knife", { attack: -2, tags: ["sharp"] } )
];

for each (var weapon:Weapon in weapons)
 trace(weapon.describe());

It would be really cool if I could get something like this as the output:

stick = { attack=10, defense=10, speed=1, heavy=false, tags=weapon}
sword = { attack=12, defense=12, speed=1, heavy=false, tags=weapon}
club = { attack=10, defense=10, speed=0.75, heavy=true, tags=weapon}
knife = { attack=8, defense=10, speed=1, heavy=false, tags=weapon,sharp}

Well, wish no more because it's possible. Here's the function that makes it happen. It takes two things and expands the first by the second. It could be improved to handle other types, but this is enough to get started with.

public function expand(receiver:Object, expansions:Object):Object
{
 if (receiver == null || expansions == null)
  return receiver;
  
 for (var property:String in expansions)
 {
  if (receiver[property] == null)
   continue;
  
  var value:Object = expansions[property];
  
  if (value is Number || value is int)
  {
   receiver[property] += value;
  }
  else if (value is Array)
  {
   for each (var element:Object in value)
    receiver[property].push(element);
  }
  else
  {
   receiver[property] = value;
  }
 }
 
 return receiver;
}

Just use it in the constructor or some section external to the object like a Factory.

public function Weapon(name:String, values:Object = null)
{
 this.name = name;
 Util.expand(this, values);
}

I'm sure I'm not the first to do something like this but I think it's a more convenient way to create things. If I ever find myself working on a 7 day long project and need a quick way to add content, this could be useful....

Sunday, July 29, 2012

Notes for the next Game Jam I go to

I'm rarely a fan of posts that are in list form (e.g. "Top 10 tips for writing top 10 lists") but I seem to be in "list making mode" right now so expect some lists in this post.



I recently went to a local Game Jam. What's a game jam? I'd describe it as an event where people meet and come together to attempt to prototype an innovative game idea, fiting a common theme, and then share their results, no matter how embarrassingly incomplete, with others. All within a few hours.

Here's what I wanted to get out of it, from most important to least important:
  1. Meet cool people. I program at home and with coworkers all the time; this is a chance to meet others.
  2. Work together. I can work by myself any day.
  3. Fit a theme. I can follow my own ideas any day.
  4. Prototype a mechanic or idea. Because doing something boring is boring.
  5. See something cool. It can be really inspiring to see something created in such a short time.
  6. Show something cool. I need to share what I come up with more often.
  7. Make a game. Another thing I can do on my own time.
  8. Network/connect. If it happens, it happens; if not, I'm fine without it.

I'm sure everyone has their own criteria and there's probably someone with the exact opposite list writing a blog post right now about how they went to a game jam and ran into someone who spent all his time socializing and coding and didn't even bring business cards to hand out.

I certainly met some cool people, saw some really neat games, and even got a few business cards from other local developers and artists. The other things? Well... maybe next time. I was looking at the team I was on and the other teams and it seems like there's three things you need to do to accomplish the things on my list:
  • Pick an acceptable team
  • Pick an acceptable idea
  • Contribute

Notice I said "acceptable" team and idea. Not even "great", not even "good", just acceptable. You only have a few hours and everyone there will be quite impressed if your game is a slight variation of "avoid the red squares and collide with the green squares."

If those three things can make a gam jam experience good, then I suppose the opposite would probably lead to a less fun time:
  • Actively break up the team
  • Push or accept an idea that totaly misses the point of a game jam
  • Contribute nothing but your dumb idea

Yup, those were the three things I ran into. I suppose I should have stepped up and tried to keep the team together, make sure we we're doing something worth doing, and make sure everyone had something to do. So, if you're the proactive type of person, the three things you really need to do to prevent someone from sabotaging your efforts to accomplish the things on my list are:
  • Pick (and maintain) an acceptable team
  • Pick (and maintain) an acceptable idea
  • Contribute (and help others)

Here's another list of random observations:
  • UnityScript sucks. Not thoroughly statically typed, not thoroughly dynamically typed. If you have to explicitly cast every time you get something from an array then your language has the worst of both worlds. And that's the easy way. I had to sum an array of floats and since floats are primitive, I couldn't cast them. I looked online for about 15 minutes and in the end, I had to convert the object to a string then parse it as a float.
  • Pick a team you can quickly get started with. When you only have 6 hours you don't want to spend the first 2.5 hours downloading and setting up Unity and Dropbox.
  • Teams that stick to the spirit of game jam do better than people sitting near each other half-working toward a dumb idea.
  • Dropbox sharing made integration easy but also more painful: you constantly get updates in the background but when someone is stuck on a compiler error or obvious bug, everyone knows within thirty seconds. Ultimately, instant feedback, and help from others, was a better way of maintaining progress on such a short iteration.
  • Control-z is good enough version control if you're only programming for one session.
  • Unity may be better for weeklong or monthlong jams, but not good at all for 6 hour jams. The best games used Flixel.
  • Working in teams would be better without all the other people. I really hate to say it but I've never been a fan of teamwork and it rarely works out. Sometimes it does, but the end results are mostly beyond my influence and usually disappointing. It always reminds me of high school group projects.
  • Whatever you create is going to be buggy and incomplete and almost certainly not even fun. That's ok. Everyone there is in the same situation and we're all there to have a good time. There was definitely an air of cooperation and support. It was fun and strangely adventurous to see what so many small groups of people could come up with under such constraints.


I still plan on going to the next game jam in my area - I'm just going to do it differently.

Monday, June 18, 2012

Continuous Deployment: Doing the mundane several times a day

I'm a huge fan of Continuous Integration, as well as Continuous Delivery, and I think it should be used to it's full advantage - especially in enterprise or other non-trivial projects. Even if you can't do the impossible 50 times a day, you can reap the benefits with fairly low effort. Here's how I managed to do the mundane several times a day.



I recently got a new job and one of the things I did on my very first day was set up a Continuous Integration server. Most of them support similar features but I chose Jenkins because it seems like the most popular open source choice. Jenkins was a breeze to work with. Just download it, install it, start it from the command line, and point your web browser at it. You can add new projects, configure it, download new plugins, and even install it as a Windows service right from the web page. Easy-peasy.

The first thing I did was automate the build process for the project I inherited. Just a batch file that told MsBuild to rebuild the entire solution.

After that I set up a very basic integration job for the project I inherited. Initially the Jenkins job just compiled the project but after a couple days I added a file with two solution-wide msbuild targets: one for the developers that calls code inspection tools and prints the results to the console and one for the integration server that does the same code inspection then dumps the results to an xml file. Once you download the Violations plugin and configure your Jenkins job, it will show a nice chart of how many code inspection warnings you have over time. Let me tell you this right now: it's nice to have a physical measurement of how your changes affect the quality of the codebase. Real nice. For our first code inspection tool I chose the standard in the .NET world: FxCop. FxCop can't tell if the overall architecture or design is good or bad but it has an extensive library of rules regarding more minor (although still important) things like following the naming conventions, disposing IDisposable instances, avoiding unnecessary casts, and many other "in the small" best practices. There are a couple I disagree with (like making a method static if it doesn't affect any instance fields) but it's easy enough to disable those rules. FxCop won't make a bad product great, but if you set aside time to fix a few warnings each day, it can nudge you toward cleaner code.

After a couple weeks I was able to start writing some unit tests and add those to the integration build. The NUnit plugin for Jenkins will take the results and make a few nice charts that show your current test runs as well as test runs over time. Again, charting progress over time really gives these things more meaning.


The second thing I did with Jenkins involves the deployment process. We don't deploy directly to production but we do have a nightly deployment process for the project I'm working on. We make a setup.msi file, zip it, send it to the client, and send an email of the changes. It takes several minutes to do by hand and it's easy to forget to update the product version, forget what changes are being deployed, or not notice what time it is and have to do it all when you realize it's time to go home. That's why the deployment (even if it's just deploying for testing) should be automated and that's where the real fun comes in. It took a few days to get it worked out but the entire process can now be done by an MsBuild target and here's what it does:
  1. Update the msi settings. A custom inline task reads a file, increments the ProductVersion, sets a new Guid for the ProductCode, then saves over the original vdproj file and updates source control. I later found out that many other people have had to do similar things.
  2. Build the solution. Do a full clean then rebuild the msi and all it's dependancies with devenv since msbuild doesn't like the vdproj project type.
  3. Zip the resulting setup files with today's date in the filename using the MsBuild Community Tasks.
  4. Copy the file to a shared folder.
  5. Update PivotalTracker. We've been trying out PivotalTracker and it's working so well for us that I can't recommend it enough. Not only is it incredibly easy to use and not only does it provide just enough project management to get the job done without getting in the way, but it's dead-simple to integrate with external tools. We have another custom inline task to use PivotalTracker's awesome web api to change every story with a status of FINISHED to DELIVERED. The response from PivotalTracker is a list of the stories that were delivered. Anyone looking at our project page in PivotalTracker will soon see what has been delivered and is ready for review.
  6. Parse the results. Using another Community Task, get the names of all the stories that were just delivered. As usual, someone on StackOverflow ran into the same problem I did and got a great answer.
  7. Send out a notification. Email me a link to the newly shared file with a list of the names of the stories that were delivered. I then tweak the email and resend it to the people involved in reviewing the changes.
And finally, the whole thing is an automated Jenkins job that runs at 5:00pm every day.


It's not perfect and there's a lot more that could be done (like more unit tests, other code inspection tools, and making our build tasks shared across multiple projects) but even while getting familiar with a new codebase and researching the various parts to this process, I managed to improve the project codebase and process while still providing value to the customer. And that, in my experience, is the real double win of relying on a Continuous Integration server:
  • Quick feedback that, when diligently followed, provides value to the company by making the codebase better and better every day.
  • Powerful tools that, when properly used, automate technical chores so we can spend more time providing value to the customer.