Saturday, January 31, 2009

Interview with a boutique MMO creator

Indie Game Developers Podcast interviews Aaron Murray, creator of the indie MMO Domain Of Heroes.

I don't usually link everything under the sun, or even much of anything really, but I found this interview quite interesting, as unlike just about every other interview of a developer I've read, it's actually quite meaty.

Some interesting talk about balancing, scaling, the economics of it, the whole bit.

Thursday, January 29, 2009

'Real' games starting to move into the Flash space.

This doesn't surprise me, since it's what I am doing and believe, but big money is starting to migrate into Flash games.

I'm not talking about in the portal space, where sites like Kongregate have been grabbing up the traffic with their stable of games, but actual "real", non-disposable games are starting to be made.

Flash is more than stable and capable enough to make a very good platform for just about any (non-3d) game you'd care to make. You can even make a pretty decent MMO client with it, and have a whopping 98% penetration and decent performance.

The story that brought this to my attention is here, where some company raised 8 million dollars for a Flash football game. Now, that's American football, not real football.

But damn, 8 million. Where can I find a bizdev guy that can do that?

Wednesday, January 28, 2009

Creating a (small) MMO is a worthy challenge!

Ya know, it's kind of a cliche in the industry that every noob wants to create his own MMO.

Now, I've been programming games for over 20 years now, and I'm very good at what I do, but I'll tell ya - this is challenging.

Even the very small scope I have set out for this first game can be daunting - for instance, today I am tackling visibility.

In this game, the players can only see things that are within sight range of their units/territory. Pretty standard war game stuff. However, it gets less standard when you're talking about an MMO. With a standard single player, or even non-server based multiplayer war game, you can store the visibility state locally and it's all good.

With an MMO you not only have to handle visibility for all of the arbitrary number of parties that could be involved, you also have to do it asynchronously - so in my case, if a player moves one of his Squads into another players sight area, I have to:

  • Remove the squads old visibility record from anyone who could see him before
  • Check to see who can see him at his new position
  • Send a message to anyone who can't see him anymore so that the client can remove the piece and show the Squad moving off out of sight range.
  • Send a message to the players who CAN see him so the client can add the piece and show it moving in from the fog.
  • Check to see what the Squad can see at its new position and then relay that back to the player that moved the squad in a message as well as adding those new records to the db.
Then, add in that the fact that the player doesn't have perfect information about the things he sees unless they are his or an allies, and then add in that the player shares visibility info with his "Family.."

Now add in scalability -you have to make sure your server cluster is going to be able to handle this for potentially hundreds or thousands of concurrent players. In my case, that might mean firing the visibility check off to a JMS queue that then is consumed by one of the servers in the cluster that has some time, which then fires off a message to the client when it's done.

It's interesting. I'm loving it.

Saturday, January 24, 2009

The joys of a quiet(er) PC

I'm sure every non-laptop PC user has experienced this - your PC getting louder and louder.

I actually bought my last PC with it being silent in mind. I didn't quite achieve that, since I didn't go that extra mile and buy the water cooling setup I had in mind. Although, with my P180, the drives properly mounted and the quiet power supply, it was quite good.

That said, it's been somewhat over a year now, and my awesome P180 started to fail me - not one, not two, but ALL FOUR of the Antec Tri-cool fans started making noise.. So, I finally replaced them today and am back to my normal somewhat quiet hum. Bliss.

Is it just me, or is everyone else getting sick of everything being so noisy all the time?

Monday, January 19, 2009

A note about Hibernate and the Generation Gap pattern

Now, the Hibernate gurus out there already know how to do this and not have it bite them in the ass, but here it is for those of you like me who got their ORM start on stuff like Propel, which just Does It For You(tm).

The Generation Gap Pattern, or GG from now on, is quite simple - you have your ORM objects like Business or Client or what have you generated as "_Business", or as "Business" but in a seperate namespace. Then, your actual class is Business extends _Business. This makes it easy to put object specific helper methods and properties into the Business class and not have it get wiped every time you re-generate the classes (using hbm2java in this case). Fine, it's very useful.

Now, Hibernate lets you do this, but it's not obvious how, and the very little mentioned about it is forum posts that are almost 5 years old. They still work, but they're quite sparse. There's also a couple of nasty gotchas. So, here's a base example (from my current game Capo):

<class name="Capo" table="capo" catalog="gangster">
<meta attribute="generated-class" inherit="false">com.tamedtornado.data.base._Capo</meta>

<meta attribute="extends" inherit="false">com.tamedtornado.data.Entity</meta>

<id name="id" type="java.lang.Integer">
<column name="capo_id">
<generator class="identity">
</id>




Ok, now the XML formatting is awful, I know, but you should see what you need to do. I've bolded the important line.. That gets you a base class named _Capo in .base, and one important bit to note is the inherit="false" attribute. Very important - if you don't include that, weird things will happen. The first set in your file will be written out as your base class when you run the code generator. Ugh. Took me a while to figure that one out.

The line under that is also useful - you can specify a base class for this Hibernate object to inherit from, so _Capo extends Entity in this case. In my case, Entity holds the HashCode, Equals, ID, etc code to make things work consistently.

I hope that helps someone.

Friday, January 9, 2009

Scripting missions in Java/Jython

The game I am working on has "missions" or "ops" or "capers" that involve the player choosing a bunch of his Crew for specific roles, such as say a Driver, a Lookout, a Thief, with specific skills. They then pull off the caper using their skills.

Since this is going to be a major portion of the content in the game, I wanted to have this be pretty accessible to the designers, so I thought up a simplified node-based system where a simple tree is walked and skill checks are made, etc..

Wow, what a waste of time that was.

It turns out that it's quite hard to simulate something like a mission script, even a simplified one, like that in this game. So I gave up and am now doing it the way I wanted to do it in the beginning - with scripts. Specifically, Jython/Python.

Now, this is slicker than it has any right to be. Basically you add the Jython.jar to your project, and if you want to use the JDK6 scripting support, you add the JSR-223 "engine" that is basically a glue layer between the Jython API and the JDK6 standardized scripting. Going to that engine page is a little disconcerting, as the engines there are from August and are all listed as "draft" - I'm sure there's more up to date stuff somewhere, but I haven't found it yet.

Anyway, if you use the JDK6 stuff instead of the Jython API directly, you get essentially transparent support for just about any scripting language you can think of. Jython is nice though, not only because it's Python and Python Est Good, but because it compiles the Python to JVM byte code, meaning it should be pretty fast.

That said, I got the scripts executing pretty quickly and ran into my next hurdle: How to debug mission scripts. Ugly.

Since right now op scripts are only running on a processor bean in the backend, and then generating results, etc, it's essentially very difficult to debug/create the scripts that way. I had to hack up a little Spring-based test app that loads the OpData I specify and then create a bunch of fake crew to meet the mission parameters, generate the Operation and then run the op script (first loading it from the "work" location rather than the database, where they will live when they are done.)

That works ok. Of course there are still rough spots, but I'm really just spoiled now - for instance, my basic OpExecution helper class in Python is derived from a Java base class, and since I don't have something set up right, the code completion can't complete for methods in the Java base class. Oh poor me. :)

Anyway, this is how I've wanted to do this kind of system in a game for a long time, and with how slick Java made it there's no way I'm going back!

Thursday, January 8, 2009

Another thing not to do

When creating your own data-bound components, don't set the value of the text field (for a data bound textfield) in the commitProperties() method, as proper as that might seem.

I just spent an hour debugging a problem where for (still unknown) reasons, my data bound control would display the text of the previous bound object, not the one that was currently bound - even though I traced all through the code and every bit of it had the right text in the text property.

Flex.

Flex 3s biggest failing - Silent Failure

Now, I've been doing a lot of programming in Flex lately.. Way too much, 80 hour weeks, and I'm getting pretty familiar with it.

The one thing that really kills me is it's major weakness, which stands out in sharp contrast to Java, which AS3 obviously aped in some ways. I've been doing my server backend in Java with Spring, Hibernate and BlazeDS, which is a winning (although a bit complex) setup.

The biggest weaknesses of Flex 3 are Silent Failure and Lack of Feedback.

When something fails in Java, if you've got your logging setup correctly, you generally see why, and exactly where. In Flex, most of the time it doesn't tell you.

A couple of examples from just today:

  1. I have a CRUD tool for my games backend data, and after performing some surgery on one of my data structures, I had broken a section of it and had to make some changes. No problem, I make the changes and... It now refuses to save any of the objects. The save is basically a remoteObject call where I send the new objects in a hash structure to the server. The Flex code gets all the way to the remote object call and then in there somewhere, just silently fails. Even in debug, no trace, no nothing - the server just never gets the request. I found it of course, after some hair pulling, but Flex was no help whatsoever.
  2. Passing some objects back from the server, some of them were untyped. I've run into this before, and of course it doesn't tell you WHY they are untyped, so I checked the usual suspects - yes, it has a RemoteClass metadata tag, yes the namespace and class names are correct, yes, yes, yes.
It was a semicolon. For instance:

[RemoteClass(alias="com...snip..DTO")]; <-- That
public class SkillCheckDTO

That semicolon, put there as I was programming this morning half awake, will cause Flex to just not type that object properly with no error.

Programming in Flex (and to some extent Java with some of the OSS stuff I am using) is a little TOO much like the bad old days of programming on the Amiga, where my software tools generally had no documentation and the documentation they did have was wrong, so I had to figure it out by trial and error.

And don't even get me started on the controls and databinding.

Compiling - no feedback whatsoever. I want to see WHY my compile is taking so long (although it's much better now). Where's the verbose compiler output?

If there's one thing they need to fix for 4, this is it. Overload me with optional information. I want to see everything you're doing, so that when it invariably breaks, I know why.

Monday, January 5, 2009

The evils of combined Flex/Java projects in Eclipse

Just wanted to give a little warning, as I just found out the hard way. :)

When I first started this project, the easiest way to get it going was to make a WTP combined project, that's where Eclipse has the Java backend source and the Flex client source in the same project and it handles deployment and such for you. That worked great, to a point.

Recently, I noticed the builds getting slower and slower. I did lots of experimentation to try to get the speeds back up, but nothing was having much impact. Even moving my embedded images to another project library/SWC didn't really affect anything that much.

Then, I noticed another fun thing - once your server and your Flex client code get to a certain size, they each take a little while to compile (Flex MUCH more so than Java, sadly).. So I'd do something like this:

  1. Adjust Java server code slightly
  2. Run client
  3. Client would require a workspace rebuild, in my case taking up to a couple minutes. (SLOW!)
  4. Then it would finally launch, when all it needed to do was re-deploy the changed Java.
Another horrible thing was when I'd adjust something in my "testdata.sql" file (my world data so that when I blow out the db I can repopulate the world without having to run any code, this happens automagically in my ant scripts for generating the DDL schema from the Hibernate objects) - when I would change even one character there, that counted as a workspace change, and you got it, everything had to rebuild. Ugh.

There was also the wonderful side effect that when you hit "launch" to launch the client, it would rebuild the workspace most of the time, then deploy it, and then launch it, but it wouldn't give the app server enough time to get it deployed and so the initial page load would fail (since the SWF wasn't fully there yet). Sometimes it would fail with really interesting error messages. What this boiled down to was pressing the refresh button the second the browser came to the front, since I knew it wasn't going to work otherwise. If I was forgetful and hit "debug" instead of just launch, this also meant launching the debug session again, since refreshing the browser breaks the debug connection. Pain.

So, I finally bit the bullet and seperated the projects. While I was at it I restructured my SVN repo to be more sane, since I expect this code base to be around for a long time.

I'll tell you the truth, it was kind of painful separating them. A couple months ago my Java know-how would have been insufficient. It's all stupid little stuff, but it is until you figure out how to fix it.

The thing that might be a problem for you that took me a bit to figure out - the Flex client and the Java server both need access to Flex's services-config.xml in WEB-INF, but you don't want to put the client in the same directory structure as the server, since when Eclipse deploys the server there it likes to wipe that directory out.

What I did was use Vista's symbolic link feature (Unix and OSX both have this, but it's fairly new in Windows. XP has something equivalent, but I can't remember if it's this easy). This just let me link from the Java deploy directory (the Java project owns the flex config files, oddly) to the Flex deploy directory.

Then, after adjusting the server settings for the Flex project, it should all work.

When all was said and done, the two projects are now separated and living in their own Eclipse workspaces and being used with seperate Eclipse installs (I also had FlexBuilder/Eclipse 3.4 reliability issues, but that's another story) - and now BOTH sides are down to few second compile times. It's amazing.

In short, WTP combined Flex/Java projects - BAD.