Running with Code Like with scissors, only more dangerous

23May/120

Microspotting: A future product, or something more innocuous?

Posted by Rob Paveza

I was driving over at Building 86 today and saw this. It's either an ad for a product I haven't seen, a road sign, or an indication that I have a really obscure sense of humor.

Microsoft Median: A future product or a sign that I have a weird sense of humor?

20Aug/080

Software Development and LEGOs

Posted by Rob

I recently went to my cousin's birthday party (he turned 6), and since he's apparently become a huge Star Wars fan (read: played LEGO Star Wars and loves shooting off C-3PO's leg), my parents decided to get him a couple small Star Wars LEGO toys that were designed for that age group.  They're small - maybe 30 pieces or so - but they're still pretty neat, and I can't help but be amazed at how the pieces still come together to form the whole.  I was a LEGO and K'nex fanatic when I was younger, but I don't think I really played around with them since I was 14 or so - ever since I left Illinois.  So when I was asked to help my cousin put them together, my first reaction was, "Hey, I don't do that anymore."  But as I got started, I was drawn in - even on the little 30-piece landspeeder.

And so, I recently made one of the biggest entirely-vanity buys since I've moved into my new place:

The box

The "Ultimate Collector's Edition" Imperial Star Destroyer.  I couldn't bring myself to invest the full $500 in the Millenium Falcon, but I thought that the price wasn't too insane, a paltry 3104 pieces wasn't too daunting, and that I would have enough fun putting together the monstrous 37" set.  The instruction book is about the thickness of my high school year books, and I'm disappointed but not entirely surprised that they didn't include the hyperdrive units as part of the set.  I guess I'm on my own for making it actually fly.

I took the pieces out and set them on my dining room table, and as I analyze the rather daunting task ahead, I realized that, really, it's like my every day job.  And the first page of the book seemed to confirm it:

Page 1: The Phantom Frame

Everything is done in components.  We have a frame, then a wing, then another wing.  The bridge.  All of these go together with little regard for how the rest of the ship is built.  Just like we build software.  We try to solve a problem, but we try to make sure that our components can be used or adapted to solve another problem as well. 

So maybe all of my formative years building with those LEGO sets weren't for nought.  Maybe they were setting the stage for software development even then, tuning my problem-solving skills, making me think of things as tasks to be decomposed until the smallest task can be approached.  Who's to say?

Sadly, my software development experience doesn't have a way for me to estimate time to build this bad boy.  But at least my motivation's there!

On the dining room table

Update: Check out the building marathon!

Tagged as: , No Comments
27May/080

WCF for Fun and Profit

Posted by Rob

I've alluded in the past that I got my start in computers because of games; I also ended up getting started in programming because of games.  I happen to be a big fan of the WarCraft and StarCraft series produced by Blizzard Entertainment, and it was my association with (and desire to make a good website for!) a group of people on their gaming service called Battle.net that got me involved with programming, and that's where the "Fun" part of this comes from.  I'm not sure where "Profit" comes into play.

With the knowledge that StarCraft 2 is on the horizon, and the new announcement of Diablo 3, I've been working on a series of open-source projects collectively named after my cat Jinx (we had the name WAY before the movie), which includes a third-party utility library that manages client connections to Battle.net's chat service, a full-blown client, and some plugins for the client.  When I first got into the bot-making community I found a project called WebChannel and WebBot -- these projects allowed clients to broadcast their channel information via another service called BotNet, which then rendered the content over an ISAPI Extension.  At the time I only really knew the basics of C#, and I could not find a way to mimic the functionality (WebChannel streamed content over the wire by removing Content-Length from HTTP headers, and then never closing the client connections).  To my knowledge, there is not a way to get ASP.NET to not send the Content-Length header; I guess I've never pursued it after about three years ago.

When starting this project, I knew from the start that I wanted to recreate the functionality (particularly because WebChannel has been unavailable for a long time).  But I also knew that I wanted to do it without recreating a lot of functionality; in the past, submitting complex types to Web Services caused the complex types to be generated as proxies as part of the client assembly, and there was no support for inheritance/polymorphism.  I knew that all of my event arguments would derive from a single class, and so polymorphism seemed to be the way to go.  Plus, all complex types serialized to and from XML needed to have a default public constructor and public gettable/settable properties, which in my mind would severely break encapsulation.  The question was, how to go about pushing my client content to a web site.

It turns out that WCF Data Contracts were the answer to my problem.  By decorating all of my classes with [DataContract] and [DataMember] I was (mostly) able to easily serialize the classes over the wire, and the best part was that I only needed one method, and inheritance was observed!  I didn't even have to break encapsulation; consider the ChatMessageEventArgs class.  By applying [DataMember] to fields instead of properties, I didn't need to make my properties settable, which means that the objects should be (more or less) immutable to code consumers.  By sharing the common code between the web server and the client plugin, I was (mostly) able to avoid any kind of object recreation, and even more fun, the types were rendered to JavaScript automatically as part of ASP.NET AJAX.

The astute reader might have noticed a lot of qualifying "mostly" asides in that last paragraph.  I'll get to that.

The final result - well, not really final - was a very Meebo-esque client that shows a live display of the channel Diablo II USA-1 on the US-East Battle.net server.  (If it's not up I apologize).  (Also, I definitely take no credit for what is said in the channel; I'm just showing that it can be done).

Headaches

There have been some trials on this project.

  • Proxy generation ignored shared types -- this occurred once I started sending some certain complex types over the wire.  When I added the service reference and looked at the Object Browser in Visual Studio, I would see all of my BNSharp.dll-driven classes being recreated.  This was what I wanted to avoid!  It turned out to be that I was not decorating some enumerations with [EnumMember] - once I did this, proxy generation returned to normal.
  • I received an error that "more than one http binding cannot be configured" when attempting to view a WCF service.  Because I use a shared web host, and multiple hosts were configured on the same IP, I was getting an error when setting up WCF services on my host.  It turned out that this was corrected with a web.config setting in .NET 3.5 called <baseAddressPrefixFilters>.
  • I then received an error that my plugin was no longer authorized once I moved it into the shared hosting environment.  I eventually tracked this down to using wsHttpBinding (the more secure Web Services HTTP binding), and had to change to basicHttpBinding.
  • I then received an error that my application was sending content-type "application/soap+xml, charset='utf-8'", which was not the expected "text/xml, charset='utf-8'".  Ultimately this ended up being traced to not using basicHttpBinding on the client as well.  That one had to be the most frustrating; honestly, it's the same thing.

What needs to yet be done

I've noticed that the client tends to cache the content returned from the server.  I need to access the HttpResponse and set its cacheability.

Other than that, it's just the user interface that needs to be done.  We've got the basics, but it needs a channel list and the ability for users to type a password into the client to communicate with the host application and then interact with the channel.

Tagged as: , No Comments
22May/080

Breakout in Model-View-Presenter

Posted by Rob

I sat down tonight and in about three hours or so cranked out the first vestiges of something that kind of maybe resembles Breakout, only using graphics that are possibly worse than anything ever shown on Atari 2600 because well, I made them.

Thanks to Joel Neubeck for the video player, and thanks to digital blasphemy for the background (yes I know it's not a free image, I'll be sure to remove it before it goes anywhere).

I should also point out: I used some sounds from the Spacewar demo in XNA Game Studio 2.0.  Those sound AWESOME.

This app is built with a model in a separate assembly; the model portion of the project contains the mathematics, collision detection, and all the game objects on the screen.  We've got tiles, a ball, and a paddle.  I should also point out that there's a game board (that's the big black empty space on the screen).

The XNA game application, then, instantiates a GameBoard (that's the containing class that owns all of the rest of the objects) and then instantiates a GameBoardPresenter.  GameBoardPresenter is part of the game application itself, and it owns a copy of the GameBoard because it's intimately tied to its inner workings.

To keep things relatively efficient, the GameBoard class exposes all of its object lists as properties that return the lists.  This way, object references aren't duplicated (except for the references to the Lists), and we're not wasting unnecessary memory and copy operations.  (If you're not clear what I mean, here are the properties:)

   1: public Paddle Player
   2: {
   3:     get { return m_player; }
   4: }
   5:  
   6: public List<Ball> Balls
   7: {
   8:     get { return m_balls; }
   9: }
  10:  
  11: public List<Tile> Tiles
  12: {
  13:     get { return m_tiles; }
  14: }
  15:  
  16: public List<Projectile> Projectiles
  17: {
  18:     get { return m_projectiles; }
  19: }

Since the balls are the only pieces of the game that move, each call to Update() on the GameBoard instance iterates through each Ball object, moving it accordingly and handling any collisions.  When a collision is detected, it fires an event corresponding to the type of collision, which is consumed by the GameBoardPresenter.

One other advantage of separating out the presentation and the actual game logic is that I can scale the graphics size to anything I want; for instance, the video above was recorded and 960x720, but I was also able to run it at 1920x1200 without any apparent differences in visualization.  The internal game units actually default to a game board size of 4800x4800, and scaling is simply done within the GameBoardPresenter's Draw() method:

   1: public void Draw(SpriteBatch target)
   2: {
   3:     Texture2D currentTexture;
   4:     Vector2 scale = new Vector2(m_scale);
   5:     Vector2 offset = new Vector2(m_xOffset, 0);
   6:  
   7:     currentTexture = m_textures[BoardItemType.GameBoard];
   8:     target.Draw(currentTexture, offset,  null, Color.White, 0f, Vector2.Zero, scale, SpriteEffects.None, 1f);
   9:  
  10:     currentTexture = m_textures[BoardItemType.BasicTile];
  11:     foreach (Tile t in m_tiles)
  12:     {
  13:         target.Draw(currentTexture, t.Position * scale + offset, null, Color.White, 0f, Vector2.Zero, m_scale, SpriteEffects.None, 0f);
  14:     }
  15:  
  16:     currentTexture = m_textures[BoardItemType.Paddle];
  17:     target.Draw(currentTexture, m_paddle.Position * scale + offset, null, Color.White, 0f, Vector2.Zero, m_scale, SpriteEffects.None, 0f);
  18:  
  19:     currentTexture = m_textures[BoardItemType.Ball];
  20:     foreach (Ball b in m_balls)
  21:     {
  22:         target.Draw(currentTexture, b.Position * scale + offset, null, Color.White, 0f, Vector2.Zero, m_scale, SpriteEffects.None, 1f);
  23:     }
  24: }

The scale is calculated when the backbuffer is sized.

Source code for this isn't quite ready yet; there are some things that I want to refactor (for instance, I want the Model part to define input "actions" and that View/Presenter part to keymap inputs to actions). 

Tagged as: , , , No Comments
5Feb/080

Mass Effect: Promised the Galaxy, Delivered… a Star System

Posted by Rob

Oooh, shiny!Mass Effect, the latest installment of Bioware's epic RPGs, promised us the world, nay, the galaxy.  It spoke of a universe of incredible depth, a future world in which humanity has discovered the means by which to travel to distant stars, interact with aliens, and eek our our place in the galaxy.  It's got an incredibly compelling story, in which you are selected as humanity's first "Spectre," an agent of the galactic government empowered to do anything you see fit to preserve galactic stability.  The visual artwork is compelling; the game has a "graininess filter," to make it look like an old 80's sci fi movie, and the music fits right into that genre (it makes the game feel all nostalgic).  The use of HDR is gorgeous, and while at times it might feel a little overused, in general it is fantastic.

Graphics

Although graphical quality is excellent, there is one exception: load times.  Please, take five more seconds to load the textures and the bump maps.

Load Times - a mass immersion breaker

As you can see in the photo to the left (I apologize, they were taken from my digital camera pointed at my TV), the bump map and texture map on the ground didn't load immediately.  Take a few extra seconds and load the bump maps before I get into the game.  In my opinion, it's incredibly immersion breaking, and should have been unacceptable to Bioware.  Unless load time was one of the highest-priority requirements, which I can't imagine (and I'll say why in a second), it amazes me that it made it to production.

One of the COOL things about loading in this game, though, is the elevator load style.  Loading happens in a lot of areas by going into elevators - definitely one of the least immersion-breaking aspects of the game.  That was a fantastic move, and in fact while we're on the Citadel, you can pick up information on new missions and get a little more information about your squad members.  It was definitely one of the strongest parts of the game.

Gameplay

Where did it go?

This is without a doubt one of the best games I've ever played in terms of control.  It is incredibly easy to control the characters, the selection of dialogue is fantastic, and the menu interface is great (with the single exception of - surprise, surprise - inventory management).

One thing I'm curious about - the E3 2006 dialog depicted to the left - where did it go?  "A billion lives are hanging in the balance here.  I won't let some piss-ant bartender slow me down."  That seemed like such a great scene.  I'm disappointed that it's not in the game.

There is one downer - the vehicle is ridiculous in terms of control.  I'm on my third playthrough, and I haven't figure out how to control it steadily.  One thing I totally loved, though, was the running-over the Geth.  It was fun to run them into the lava on the planet, incidentally, shown in the image with the bad load times.

I also don't like the mission assignments.  Besides the main quests, it's annoying to hear from the Systems Alliance admiral whom you never meet, who just says "You're a Spectre, and you answer to the Council, but you're still a human."  Come on, give me a break.  Seth Green, give me a chance to say no - don't just say "Transmission comin' in - patchin' it through" every freaking time I look at the Galaxy Map.  PLEASE, SETH GREEN, LET ME DO MY OWN THING!

Music

The music is absolutely fantastic.  It's one of the best soundtracks I've ever heard; it's absolutely distinctive.  And it was inexpensive to buy on iTunes!  Other than that, I can't say much.

Finally - the Universe

I think this is possibly Mass Effect's greatest weakness, as well as the greatest strength.  While places like the Citadel are built up very well, the Citadel feels like about 60% of the universe's civilization.  That's pretty sad considering that they indicate a few million (maybe seven million) people live on the Citadel, and there have to be hundreds of billions, if not trillions, of people across the galaxy.  The planets you can visit outside of the main quest feel forced and random, not to mention barren.  It's supposed to be the galaxy - why do I hardly ever run into people who aren't trying to kill me?

But on the other hand, the way the other races are introduced and described is incredibly thorough.  It's exactly how I'd like to see a game introduce the races it has.  I can't sing the praises of the story or the universe (in this sense) enough.

Go buy it, if you haven't yet.  It's worth the cash.  Get it new - support BioWare.

Tagged as: , , No Comments