Uncategorized

HamQuest Hiatus Halting? Island Interloper Interruption Initiating?

The topic of this post reminds me of the 60’s Batman narrator.

HamQuest and I have a rocky relationship.

Periodically, I look back at the code base, and see a number of areas in which I can improve things.

I get inspired to do so.

After a while, the things that I want to do to make the game more configurable or better organized or generally more engineered pile up into a insurmountable list of issues to resolve.

Inspiration wanes.

Eventually I abandon working on it for a while, and move on to other things.

I imagine the curve plotted by my desire to work on HamQuest (or really, any long range project) might look something like a graph of cos(x).

Since there are endless cycles of this, the graph is really cos(x+k*2*pi), where 0<=x<=2*pi. And k is the number of cycles that have taken place already.

So, I appear to be heading for x=2*pi, which means the cycle will reset, and I will do some work on HamQuest.

Which is actually a good thing, because my “x” value for Island Interloper is rapidly reaching “pi”, or the minima in interest level.

Is it possible to have a few projects that hit peaks and valleys in interest level in such a fashion that I simply need to switch between them?

—-

So, why a decrease in interest in Island Interloper?

A couple of things.

1) There is a reason that HamQuest is not written in JavaScript(I tried… believe me!).  What does this have to do with Island Interloper? The problem with writing something in a scripting language is that it isn’t compiled.  This is also its strength, as long as it remains at a small enough scale.  Island Interloper has achieved a scale where it has become difficult to deal with.

2) I also don’t really want to invest the time needed to learn one of the many debuggers available for JavaScript.  Generally speaking, my “debugging” of JavaScript involves the heavy use of “alert”, and the FireFox error console, and that’s about it.

3) If the end goal of Island Interloper is to operate online in a multi-player scenario, a JavaScript single player game isn’t going to cut it except for prototyping how the game should be laid out.

4) I think that the “correct” client to use is SilverLight, with a swappable back end that can either be used to store data to isolated storage or through the web, and this layer would be abstracted so that I could use the iso storage one during development, and the web one in deployment.  Plus, C# has a real debugger.

Uncategorized

Object Oriented Code Is Not Smaller In Size

I have a new version of Island Interloper up.  Dunno if it is an upgrade or downgrade from the last time I uploaded it.

It has still not reached feature parity with the previous attempt, but one can buy and sell commodities at different islands.

Really there are only three minor features to add back before parity is achieved.

One is the ability to “take note” of prices at various islands.

Two is the save and load feature, which really isn’t much of a feature at all, as it just dumps a string to a textarea.

Third is the feature that actually consumes resources as the sailing voyage goes on.  It is a key feature that adds the element of anxiety over limited resources.  It gets you asking if you have enough food to make it to the next island. It is very “Oregon Trail”-esque.

(Maybe I should add the ability to fish….)

Anyway…

If you want evidence that OO code is larger than equivalent non-OO code (and the previous version was not completely non-OO, it was part-OO), you need look no farther than the code for Island Interloper.

Previous version (not counting third party code used unmodified as libraries): 37.0 K

Current version(again not counting third party, and haven’t achieved feature parity yet): 46.1 K

No, it isn’t a huge difference, but it is over 20% bigger at this point.

Of course, my software size is measured in K, not M or G.  In JavaScript, code size is the same as software size.

Why more code?

Because the code is better organized.

Huh?

Imagine this:

Your game has a number of different things to deal with that make up the game state.  In Island Interloper, these things to deal with are primarily the avatar and the islands, at least at the moment.

In the old code, the avatar was part of the game object, and was accessed using some code like:

game.avatar

One of the properties was called “heading”, which stored an angle in which the avatar’s ship was going.

It was stored in:

game.avatar.heading

As you can see, this is not entirely OO, but not entirely not either.  There is no encapsulation.  It is simply a raw global variable for all to see.

In the new code, there is still a game object passed just about everywhere, and within it there is an avatar object, but now the avatar is an object of a class called AvatarObject.

And while “heading” is still a variable within the AvatarObject, there are also two accessor functions: getHeading and setHeading.

And of course, the avatar property of the game is accessed through a function called getAvatar, so to get the heading of the avatar, we go from:

game.avatar.heading

to

game.getAvatar().getHeading()

Which is already longer, and so that is where the extra size comes from.

—-

There is a company called InnoGames.  They are German. If you have been on Facebook, they had a massive advertising campaign for their game Grepolis.

I tried out Grepolis, and their other strategy game Tribal Wars.

I didn’t much care for either of them.

However.

I also tried out their OTHER other game, The West.

It turns out to be an ideal fusion of “Errand Boy”, “Sporadic Play”, “Base Building”, and so on that I’ve found.

Takes about 5 minutes twice a day to play.  I queue up about 6 hours worth of activities for my character to do, and it calmly ticks down the timer for the character to do them.

Unlike many of the other strategic browser based MMOs I’ve played (lots of Storm8 games), the games purpose is not (as yet) easily thwarted by something like investing in passive income sources. Instead, there seems to be a pretty progressive series of errand boy missions, plus adding in contributing to building the town one belongs to.

And it accepts mailinator.com email addresses.

Uncategorized

Better Living Through JavaScript Closures, An Example

function ConfigObject(){
	var vowels = ["a","e","i","o","u"];
	var consonants = ["b","d","f","g","h","k","l","m","n","p","r","s","t","v","w","z"];
	var minimumNameLength = 3;
	var maximumNameLength = 10;
	var islandCount = 1000;
	var minimumIslandX = 0;
	var minimumIslandY = 0;
	var maximumIslandX = 1000;
	var maximumIslandY = 1000;
	var minimumIslandDistance = 10;
	var maximumDockingDistance = 2;
	var currencyCommodity = "gold";
	var unknownIslandName = "an unknown island";

	this.getVowelCount = function(){return vowels.length;};
	this.getVowel=function(index){return vowels[index];};
	this.getConsonantCount = function(){return consonants.length;};
	this.getConsonant = function(index){return consonants[index];};
	this.getMinimumNameLength = function(){return minimumNameLength;};
	this.getMaximumNameLength = function(){return maximumNameLength;};
	this.getIslandCount = function(){return islandCount;};
	this.getMinimumIslandX = function(){return minimumIslandX;};
	this.getMinimumIslandY = function(){return minimumIslandY;};
	this.getMaximumIslandX = function(){return maximumIslandX;};
	this.getMaximumIslandY = function(){return maximumIslandY;};
	this.getCenterIslandX = function(){return this.getMaximumIslandX()/2+this.getMinimumIslandX()/2;};
	this.getCenterIslandY = function(){return this.getMaximumIslandY()/2+this.getMinimumIslandY()/2;};
	this.getMinimumIslandDistance = function(){return minimumIslandDistance;};
	this.getCurrencyCommodity = function(){return currencyCommodity;};
	this.getUnknownIslandName = function(){return unknownIslandName;};
}
ConfigObject.prototype = new Unserializable();

The above is a good example of what I was talking about in my last post.  Previous to my work today, all of the items that are now preceded by “var” were preceded by “this.”, which means if I were careless, I would be able to clobber the values if I used them as raw properties.  Now I can’t, as the only way to access them is to use the various getter functions.

I’ve also found other areas where I don’t want to expose certain variables to serialization, like the following:

function AvatarCommodityObject(theCommodity){
	var commodity = theCommodity;
	this.units = Game.Commodities.getCommodity(commodity).rollInventory();

	this.getCommodity = function(){
		return commodity;
	}
	this.getUnits = function(){
		return this.units;
	};
	this.setUnits = function(units){
		this.units = units;
	};
	this.buyUnits = function(unitCount){
		this.setUnits(this.getUnits()+unitCount);
	};
	this.sellUnits = function(unitCount){
		this.setUnits(this.getUnits()-unitCount);
	};
}
AvatarCommodityObject.prototype = new Serializable();

Here I have put commodity as a var within the function, and the getter of getCommodity will retrieve it. I cannot be set after construction.  The variable this.units will still get serialized as usual.  Functions never get serialized, and so are a non-problem.

My one remaining issue is the call to Game.Commodities.getCommodity().  I should not have to rely upon a global Game object, nor its subobject Commodities.  Indeed, the Commodities object should be passed in to this constructor.  This I’ll be refactoring shortly.

I feel as though I’ve “leveled up” my JavaScript.

Uncategorized

Better Living Through JavaScript Closures

My original design for the javascript version of Island Interloper, I had a rather simplistic serialization scheme.

All of the data for the game was in a global object called “game”.

This was all just data, so that it could be made into a JSON string and then stored elsewhere, and similarly come from a JSON string and parsed into the original object.

This works pretty well, but there were some issues with it.

  1. I had some functions within the game data. Function objects are not JSON-able, and would be lost when saving, and missing when loading.
  2. I wound up with a lot of rather unwieldy expressions, like game.islands[game.avatar.island].name and so on. After first wrapping this up into functions to make it slightly easier, I attempted wrapping them into proxy objects, which made it even uglier, so I decided to do a different design.
  3. Not all parts of the game object need to be serialized. The commodity list doesn’t change ever, similarly the list of ships and crew members.  Do not serialize what you don’t need to.

So, after this minor setback, I’m well on the way to having a better design.

Except that I think that some of the functions used within the objects that now comprise the Game object should make better use of closures.

For example, the createRandomName function is only needed by Game.Islands to generate a list of random names.

Also, currently everything relies upon the global Game object to get data from other aspects of the game, like utility functions and actions.  I think that closures would be another better way to get the data.  Time will tell.

Uncategorized

JavaScript refactoring threshhold

I have determined the number of lines at which I suddenly develop a need to split a .js file into multiple files.

It is anywhere between 300 and 400.

I grow my JavaScript organically. I start out with a main.js, and add bits and pieces as I go along. The global vars and utility functions I put near the top, and the main function I put at the end.

Eventually I section it off by comment lines filled with /////////////////////////.

Then, somewhere around 350 lines, I split it out into whatever logical groups strike my fancy.

Uncategorized

A Story of Safari, Form, and OnSubmit

I learned something today.

I learned that, on Safari(iPod or mac… didn’t try PC), if one is using an <input type=”submit”/> in order to make the Enter key work when typing into a textbox (as I was doing in Hammurabi), the wrapping <form> tag will actually submit the contents of the form to the same URL that you are already at.  Firefox doesn’t do this.

In order to handle this correctly, you have to put an onsubmit handler that returns false on the form tag, or you will be feeding 2000 grain to your people, and suddenly you will have reset the game entirely.

Also, in the course of doing HTW and Hammurabi, I have determined a really nice way to structure the javascript for doing it.

Generally speaking, I use a single <div> that is the (for lack of a better term) “render target”.  Each time I update the content, I basically just replace the innerHTML property of the <div>.  This works rather well.  The game state will be held in some global javascript variable. The various event handlers of the <button> or <input> tags call other functions that further manipulate the state of the game.

This is all great, except that I determined that I needed to be able to start the content in one function, and be able to pass it to another function.  So, I came up with the following template for all of my text based game javascript functions:

function template(content){
    if(content==null) content="";
    //add content here
    document.getElementById("content").innerHTML = content;
}

This way, since all parameters of all javascript functions are optional, I can call something with no parameters and have the default value of null, which starts the content off as a blank string.

This way, I can have one function start off the content of another function with some sort of snide comment, or I can add some action resolution verbage to the status panel.