The XAP development diary

Done:

[] adjust player’s max speed - now 32 pixels/frame
[
] adjust alien bullet speed - now 4 pixels/frame, and unvarying

hm yes, so they were the easiest things on ths list :slight_smile:

Failed:

[*] try to think of a better background. I tried that Magic Water algorithm with a texture behind, using a bit of displacement mapping and shading. Took an hour or two over it. Wherever the player went it disturbed the “water” and sent out these lovely ripples. I would have put ripples in for the gidrahs and such as well except … apart from not looking as good as I’d hoped, it was also pretty slow, and the texture of course rather limited the size of the playing area, which abruptly ended.

It has occurred to me that any background texture is going to have this “sudden ending” problem. Hm. I don’t really want the player whizzing off into nowhere but I don’t really want the border to be “hard” or “abrupt”. Fade it out at the edges perhaps? Sudden attack of immensely strong gravity should you stray too far? Both?

[*] Fix sound problems. No matter what I do I just can’t make my sounds play consistently. I may have to hassle Brian. He won’t know the answer, but I feel like hassling him anyway :wink:

Cas :slight_smile:

Rode 300 miles for 5 hours for a meeting that was cancelled five minutes after I set off. Bah. Typical I had to sell the car just as the temperature plummets to freezing. Praise be to BMW heated grips!

Cas :slight_smile:

Sound troubles have been fixed! Sort of. It turns out that it starts to go wrong when I change the listener position. So now everything’s at 0,0,0, and the sounds don’t go wrong. But it’s no longer stereo which is a shame. I’d like to get to the bottom of it, but moving on…

[] shield now works, although it looks classically crap. Who’s going to to me a nice one, eh?
[
] player starts in the middle of the battlezone
[] bubbles tend to beam in nearby blobs now
[
] altered Jelly and Gunner movement to be a little more wacky
[] tweaked the player max velocity back down to 16 pixels / frame, reduced deceleration. It’s pretty damned fast.
[
] speeded up the enemy bullets
[] altered the alien res-in effect, so there’s now these concentric circles that whoosh in around them. Needs the colours tweaking but it looks a lot better. I’ll get rid of the particles as well as it doesn’t seem to need them
[
] put in a level-start sound effect, a kind of electro-belch reminiscing of the days of Revenge of the Mutant Camels.
[*] player gets 2 seconds’ grace when a level starts before the gidrahs turn up

Yes, it looks like I’m still just dithering and doing easy things again doesn’t it?

Cas :slight_smile:

The Big Refactor, part #1.

I may have mentioned a lot of things were getting messy deep in the code. This is what I like to call a big load of object orientated wank and it usually happens halfway through designing something object orientated. There is usually only one cure, which is to stop and rewrite. Fortunately the refactoring tools in Eclipse are pretty handy, and save a lot of trouble. The instant impact analysis is also exceedingly useful, as everything that breaks after a change gets a sea of wiggly red lines all over it and lots of angry red crosses.

One of the first signs of object oriented wank is not remembering where something is. When there’s only a very few finite elements in a program, why move them all over the place when you can have them all in the same place? I was doing Player.getPlayer(), because it looked nice and OO to do so: but really, the player is part of the Game. So now it’s Game.getPlayer(). And nearly everything else is being moved up into the Game class as well.

The next sign of object oriented wank is seeing more than one indirection, such as Game.battleZone.spriteEngine. The sprite engine is now private, and the appropriate methods that I wanted are wrapped and moved up into battleZone.

A further sign of object oriented wank is using getXXX() and setXXX() all over the place when a dot will do. Usually I try and make my variables public final if there’s no setting required, and a dot can access them.

One last sign of object oriented wank is having to remember to set some instance variable that’s always the same. My sprite engine had this clever notion of being able to support multiple SpriteRenderers, one of which was a GLSpriteRenderer for drawing sprites using OpenGL. The Game had a static instance of GLSpriteRenderer it used for all its sprites, and whenever a got a new Sprite(), I’d have to remember to call sprite.setRenderer(Game.spriteRenderer). This is, of course, ludicrous. As if I’m ever going to use any other sprite renderer! So now all the sprites use the same renderer, and it’s no longer necessary to store it in each and every sprite because the SpriteEngine itself has it. And as if I’m going to use any other renderer for it! So now it’s just tucked away in an inner class and it all looks much neater.

But tonight, it’s off for a romantic dinner with my lovely wife Charlotte, who is more important than XAP. More on the Big Refactor tomorrow.

Cas :slight_smile:

The Big Refactor, part #2

Object-oriented wank has crept in and taken root like a malignant fungus. The Tumour of Doubt shadows my development. What’s happening is this: I’m not sure where something should be, so I’m dithering about where it should go instead of just bloody getting on and coding it.

Now ask yourself when was the last time this stopped you from doing something in BASIC? Sometimes I wonder if we take two steps forward, only to realise we left our trousers behind. Madness.

I’ve got this nifty resource system in XAP. I’ll describe it in detail in January but the gist of it is this: all the “things” in the game are resources, accessed by a single resource management class by a unique name. If you ask for a resource, it is returned to you ready-to-use. If, for example, you ask for a GL texture object, you get one that’s been loaded from disk, and uploaded to GL. This is called “creation”. However, before you ask for it, it’s in an “uncreated” state, and anything it might be referencing hasn’t been loaded yet. Similarly when you “destroy” a resource, it frees up things that it’s been hanging on to. This might sound like I’ve reinvented the garbage collection wheel but know this: GC knows nothing of native resources. It cannot be relied upon to free up a huge GL texture in a timely fashion because the resource itself will only be garbage collected when Java feels like it.

So all my gidrahs are resources, and the player, and the lasers, etc. As a resource, the gidrahs can create instances of the resource as a template - i.e. how many points it’s worth, the accuracy of its shooting, etc. The trouble is, I’m effectively using the resource as both a template and an actual game entity with sprites associated with it, and that’s just uncomfortable. Some of the code’s beginning to look ugly, separated in methods with a humungous ‘if’ statement depending on whether it’s a resource template or an instance. Daft.

So I think the gidrah instances themselves are going to become inner classes of their templates, which would be a much better way to do it.

Cas :slight_smile:

Did some - ok, hardly any - work on the LWJGL today just prior to the 0.4 release. It was a worthwhile bit of work, to do with: how we get display modes, based on some troubles that people had been having; the vagaries of Linux and all its strange ways of talking to a graphics card; and some whingey developers wanting a drag bar on the debug window. Tsk! You know who you are :slight_smile:

Layered on top of this new change, the Shaven Puppy Game Library now gets its own Display class, which does the rather more complicated but infinitely more useful task of actually choosing the best display mode given your specific requirements. Check it out as usual at http://sourceforge.net/projects/spgl in the CVS (com.shavenpuppy.jglib.Display.java).

It does display mode selection in three steps:

Firstly, you provide it a set of minimum and maxium criteria for every aspect of the display - width, height, frequency, colour bit depth, alpha bits, depth buffer bits, and stencil bits. This essentially gets all of the display modes that the system reports it can do and filters out the ones that don’t fit your criteria. (You can specify -1 for any minimum or maximum and it won’t be used to filter the list). At the moment, we just guess every possible combination of alpha, depth, and stencil bits for the most common video cards and insert them into the list of display modes too, although in future we might get a bit more intelligent and try some OS-specific extensions to figure out what’s not available.

Secondly, you then ask it to sort the filtered list in ascending or descendng order for any number of display mode parameters, which effectively gives you a list in order of preference.

Thirdly, it then goes through the sorted list starting at the top, and attempts to change to that screen mode. If it fails, it tries the next one. If it runs out of modes to try, that’s when it throws an Exception. If it gets a mode, it returns it, and that’s the mode you’re in. Presto! A neat bit of code, if I say so myself, made all the easier by a bit of reflection.

Cas :slight_smile:

Charlotte’s crazy Russian granny is coming over at 10am tomorrow to inspect our house for dust and fingerprints! This means I spent all day hoovering, wiping*, bleaching, scrubbing, etc. and generally having a miserable time.

Went shopping in Bridgwater, scourge of Somerset, this evening. Full of very pissed off middle aged husbands and wives standing in front of empty shelves yelling at each other - “This is what happens when we leave it to the last minute!” etc. Highly amusing. Bought some stuffing, wine, more wine, and a Christmas treat for the dogs.

Of course, very little got done to XAP today, and I suspect that there will be 3 days to follow of insurrection, drunkenness, feasting, and all things unrelated to programming. Happy Christmas!

Cas :slight_smile:

  • wiping should be in the Dictionary of Words That Make You Feel A Little Uncomfortable. Along with moist.

Happy new year etc.

The Big Refactor continues. If only I’d done it this way in the first place. It makes so much more sense. Imagine a class heirarchy that looks somewhat like this:



/**
 * The interface for things that have a position in the battlezone and
 * collide with other Entities
 */
public interface Entity {
}

/**
 * Describes the properties of an Entity
 */
public abstract class EntityFeature {

      /**
       * An actual instance of an Entity
       */
      protected abstract class EntityInstance implements Entity {
      }
}

/**
 * Gidrah is the base interface for all aliens
 */
public interface Gidrah extends Entity {
}

/**
 * Common Gidrah feature.
 */
public abstract class GidrahFeature extends EntityFeature {

      /**
       * Gidrah instances
       */
      protected abstract class GidrahInstance extends EntityInstance implements Gidrah {
      }
}

/**
 * A particular gidrah: the bubble
 */
public interface Bubble extends Gidrah {
}

/**
 * The Bubble feature
 */
public class BubbleFeature {
      protected class BubbleInstance extends GidrahInstance implements Bubble {
      }
}


You see what’s going on here? Now there’s interfaces to describe the general external properties of things, and there’s three lines of inheritance going on.

The advantage with using the inner classes is that the XXXInstance classes have access to all the data in the XXXFeature classes. The feature classes describe things like movement speed, firing accuracy, initial hit points etc. Obviously it would be tedious to copy all this information from the feature into the instances of the gidrah, or worse still, try and bully the features into actually being instances as well by using a boolean flag. Horrible.

So now my instances can see the data they need to, there’s no confusing and irrelevant code in the Features any more, and anything that needs to interface with the instances has to use the appropriate interface instead. Perfect!

It’s important to get all this looking super tidy now, because this January I have to work balls out for the Man doing some tedious BBC election server software. I won’t be able to work on XAP hardly at all - which means when I come back to it in a month, it’s got to be obvious how it all works.

And once again, XAP is running, although the explosions have been removed and a few other little bits and bobs are broken as a result of the refactor. But they’re now much easier to put in. There’s an EmitterFeature abstract class for describing things that can emit… ParticlesFeature instances! I hope to go all-out on beautiful particle effects.

More good news - Chaz might be able to do the graphics for XAP. Chaz is second-to-none and lightning fast. One day he’ll be famous. Probably, as is the case with artists usually, 200 years after he’s dead.

I’ll know more on the 3rd when he gets back from France.

Cas :slight_smile:

Haven’t phoned Chaz yet. Tsk. Guests round all weekend so not much work done.

I’ve developed a generic prioritized pooled resource class for the Shaven Puppy Game Library. Imagine you’ve got a pool of resources pre-constructed, and a bunch of things that need to allocate things from the pool. Very soon all the things will be allocated and there will be none left, and you have to rely on their good grace to return them to the pool. Furthermore, something more important might want something from the pool and there won’t be any left.

To solve these problems I’ve wrapped up the resource allocation in a class (com.shavenpuppy.jglib.util.PriorityPool), and the things which it can allocate implement the PriorityPooled interface.

When you request a pooled item you supply a priority and an “owner”. Allocation first gives you any unused pooled object. If there are no free ones, then it gives you the lowest-priority object out of the pool that is lower than the specified priority - effectively snatching the resource from whoever last “owned” it. Failing that, it finds the oldest resource of the same priority and snatches that one instead. And if everything currently allocated is of a higher priority it returns null, meaning you can’t have that resource.

Every frame, the pool is “ticked” which checks to see which resources are no longer in use, and returns them to the pool by clearing the ownership.

This means that if you want to call any methods on pooled resources over subsequent frames you must check that the resource is still owned, because it might have been snatched by someone more important.

I’m not particularly happy about using the class for large-scale pooled resources like particles yet, because it currently scales badly. In the case where there are free slots, allocation is free. But in the case where a pooled resource needs to be pre-empted from somone else, allocation time is linear with the size of the pool. I thought about using it for Particles to make sure the most important particles got allocated in preference to incidental particles whilst keeping a cap on the number of particles allocated, but imagine if I already had 2000 out of 2000 particles in the game and wanted to allocate another 500 high-priority particles for the player’s explosion - it would cost 500x2000=1000000 operations to complete just the allocation. What I need to do is sort the pooled resources when an allocation is first made and then simply count up from the bottom instead of searching through the whole list every allocation. When the list is reordered I simply mark it as needing sorting again. This effectively makes the initial allocation scale with the sorting algorithm speed (probably 5 log n if I use a radix sort) and makes subsequent allocation “free”. I’ll put that in later.

You might be asking when you want to use this rather complex mechanism to allocate stuff. Why not, for example, just use new() and wait for the GC to get rid of things? Here are your reasons:

  1. Use the pool when construction of your resource is expensive.
  2. Use the pool when resources are scarce but need to be allocated according to importance. Native resources are a good candidate.

The first use for this mechanism is the underlying algorithm for allocating sound effects in the game. There are only 8 sound effect slots in the pool so scalability isn’t an issue.

Cas :slight_smile:

Tweaked the sound effect for the gidrah res-in. Sounds much more menacing now. Also the gidrahs have a nastier, screechier bullet noise which makes you feel more worried. The player’s explosion is now more crumbly and less flanged - sounds good with the woofer turned up. And for extra atmosphere there’s a throbbing sub-bass heartbeat which is the background noise for the level. This is going to increase in pitch as it draws closer to the Gunner appearing. I hope this game will be aurally creepy.

The gidrah explosions and player explosions are back in, and look nice once more. I’d better put the player’s beam-in back in again. And tweak the gidrah beam-in. A longer delay between circles and faster res-in circles would be better.

Emitters are gone. Couldn’t really see the point in them, as Particles seem to contain all the information they need to know to just get on with things on their own.

Fixed a bug in the sprite library when I noticed all my sprites disappearing one by one… turns out I left their alpha at 0 when I reallocated them.

Brian showed me a pure Java Ogg Vorbis decoder today, which I will have an experiment with. I plan to ship the samples compressed as .oggs, and decompress them on first run into .jgwave files. Provided the strange electronic nature of the sounds isn’t lost in the process. Currently my sound files stand at 1 meg though, which is rather too much, as that’s my entire sound budget… still, if Vorbis fails me, I could try Flac, which is a lossless compression format, but which will only achieve about 50% compression. Mind you, I’ve still to downsample my waves from 44khz stereo to 22khz mono, and that’ll quarter their size straight off.

By the way, SimSynth 2.7 from Fruityloops is the dog’s bollocks and worth every single penny and the painful registration procedure. Even if I weren’t producing a game I could waste hours and hours just making wacky sounds in it for fun.

Cas :slight_smile:

Another sleepless night. Gave up coffee and tea as of this morning. It’s difficult. I gave up smoking without a second thought.

Did some code tidying but otherwise worked for The Man today.

Cas :slight_smile:

A surprisingly productive day considering I was avoiding doing any work for the Man. Coffee withdrawals are pretty bad. I can’t concentrate on anything much and have an overpowering urge to fall asleep at a moment’s notice.

The game now ends - which is nice - and starts up again from the title screen. After a few tweaks here and there, such as making sure all the gidrahs were removed for the next game, it’s worked just fine. Todo: “Game Over” and a high-score entry / display screen.

Jellies, blobs and bubbles are all behaving properly and interacting as they should. I notice the Gunner has dissappeared. I wonder where it’s got to.

Messed around with Ant for a few hours as well, trying to get it do do what I want from Eclipse, but it persistently refused to obey my instructions. In the bin with it for now. The new version of Eclipse has better Ant support but it’s got a fatal bug and won’t compile any of my code :slight_smile:

Got hold of Chaz, who says he’s up for doing sprites. Hurrah! I’ll be seeing him weekend after next. Sent him a demo but his shitbag Voodoo3 system failed to run. In fact it bluescreened which says a lot about the drivers considering at the point it bluescreened all it was trying to do was change display mode… hopefully that’ll be resolved in LWJGL at some point…

Put the player beam-in effect back in. It’s still rather dull; I’m hoping Chaz will think of something cool to put in as well.

Cas :slight_smile:

I’m really having some awful trouble with OpenAL. I found a bug in the code whereby it calculated the pitch of a buffer to be 0.0, and then proceeded to do a divide by zero with it, which in turn caused an endless loop in the OpenAL driver (and hence a lockup at 100% CPU which was tricky to get out of thanks to Windows XP’s awful multitasking capabilities). It took absolutely ages to pin down with loads of printfs - I don’t know how to debug .dlls when they’re loaded by Java - and then I recompiled the AL drivers and now I’ve got crackly sounds. Like they’re being badly overdriven. I wonder what’s up. The source is straight from the OpenAL CVS.

Fixed a bug whereby if the last blob was mutated the jellies didn’t arrive (which is the whole point…) Also added a suitably unpleasant sound effect and horrible strobe when the the jelly incursion begins.

I noticed a sprite glitch occurring; when new gidrahs are spawned they flash for one frame at 0,0. Hmm. I bet it’s one of those really annoying bugs that take ages to find and then have you bashing your head on the wall.

I’d like to alter the behaviour of jellies to make them a bit madder. Eventually, due to the fact that they home in on the player, they all end up in a huge wobbling cluster, which makes them a bit easy to zap. I think every now and again I’ll adjust their movement randomly.

Caffeine withdrawals now very, very serious. This is unlike anything I have experienced before. I see movement in my peripheral vision, and hear noises that aren’t there. Urge to sleep is stronger by the minute. I feel like killing everybody that comes near me. Good thing I’m writing a nice relaxing game of destruction then!

I suppose you might want to see some more screen shots… well, they can wait until Chaz beautifies the current sprites, I think. It’s very difficult to get an interesting screenshot in the game because everything happens so fast.

Cas :slight_smile:

Put the player beamin sound in. Once again experimented with positional audio in OpenAL and once again was greeted by sounds which inexplicably fail to occur. Must hassle Brian once more. So I put it back. It still sounds pretty awesome if I say so myself :slight_smile: Remember when you were small and walked around the arcades trying to get near the Defender machine? You couldn’t see it because of the crowd of geeks clustered around some hero or other but you could tell where it was because that’s where all the evil noises emanated from.

Put the Jelly incursion into a separate Feature so I can dick with it in XML. Also moved difficulty factors into XML now so the gidrahs can get harder as the levels increase. Some gidrahs won’t even be appearing on later levels.

Those mischevious Danes had me doing funny things with LWJGL and one of them was putting a drag bar on the debug window. Inexplicably this causes the application to hang if the window loses focus. Grr. If anybody’s got any ideas why it freezes (on a wglSwapBuffers() call) having lost focus, please get in touch.

So XAP is more or less playable now - I’ve actually found myself just having another go instead of actually looking for bugs. That’s quite a good sign. Let’s have a ToDo list to keep me focused!

[] Do the control panel with score, lives, bombs, and shield indicator
[
] Go to the next level when this one’s cleared
[] Put up the end-of-level bonus screen
[
] Smart bombs - nice and easy
[] Bonus indicators for rescuing Blobs from Bubbles
[
] Find out where the Gunner’s got to
[] Fix positional sound
[
] Tweak sound priorities
[] Adjust background parallax so it’s right
[
] Think about doing a radar
[] Do a high score display
[
] Do high score entry
[] Fix the title screen so it isn’t a big bag of shit
[
] Do title screen sequence to run through the gidrahs
[] Do help screens - just static instructions, no point in animation
[
] Resist coffee
[] Make Bubbles slightly more aggressive and chase Blobs a bit
[
] More sound effects for all sorts of little things
[] Consider adding gidrah’s velocity to bullets fired
[
] Shrink sound effects down to 11khz mono where necessary or Ogg
[] Start thinking about nicer game background again
[
] Consider possibility of a little pseudo-3D so I can do fancier particles
[] Become fabulously wealthy. Oh… bugger.
[
] Resist coffee

Cas :slight_smile:

Fixed an annoying bug in the PriorityPool which meant that lower priority sounds could pre-empt higher priority sounds. I’m going to put the sound priorities into the XML data files so I don’t have to hunt around in Java code for them. It’s easier to balance and assess the priorities of different sound effects too when they’re all in front of you in one place.

Downsampled everything to 11KHz mono today. Some of the sound effects actually sound better! Some of them are a tiny bit worse. I played the game through my stereo and it still sounded like the house was under attack by aliens so no worries there. The tool I used is Sound Gadget Pro - shareware costing only a tenner - from http://www.compsoc.man.ac.uk/~nigel/SGPro.html (I bet the URL changes because it looks like he’s at University). This is another tool worth every penny of the ten quid I haven’t yet paid him :wink: Rest assured it’s something I’ll definitely register when I can be arsed to.

Chaz is hopefully coming over to visit on Sunday. I think he’s starting at Rage in Bristol next week doing contract monkey work for them on some of their 3D models which don’t look right. They actually have the nerve to pay him £8 an hour for this. You can get £8 an hour cleaning windows. He’s one of the most genius talented artists I have ever met, and really ought to be earning about £40 an hour, which is what I’d pay him if I were hiring him :slight_smile: Instead I get him for free! Well, 20% of the royalties. That could be a fair old chunk though considering he’s only got about 1 months’ work to do on XAP.

Must do some work for The Man today as I’ve gotten seriously behind.

Cas :slight_smile:

Showed Brian a WIP demo of XAP last night, and he seemed to like it. We talked about the design a little and three main things came to light:

  1. The laser would be better if it fired and stopped where you actually targeted rather than a fixed length.

  2. Powerups. Brian really wants powerups in the game. I was umm-ing and ahh-ing over having powerups because they have a tendency to screw up balanced gameplay, but Charlotte chimed in as well and said she wanted powerups too. So Powerups there shall be.

  3. Big bosses. Brian wants end-of-level-gidrahs as well (and the moon on a stick). Once again Charlotte backed him up. Grudgingly it looks like I will be adding eolgs as well then.

The laser took all of 5 minutes to change. I also added an autofire; hold it down and it repeats every 10 ticks. You can still whack the mouse button over and over to get it to shoot faster but the real reason I put in the autofire is because I fear for my mouse’s longevity…

On powerups: I think that I will basically use the same powerups that were in XAP. In the original XAP, powerups beamed in randomly at the same time as an attack wave. This time however I think I will limit their availability somewhat; perhaps they will appear every 7,500 points or so. Extra lives and smartbombs also appeared as powerups instead of being automatically awarded when your score reached a certain threshold - currently every 10,000 points.

You can collect multiple powerups of the same type to stack them for even greater effect. When you die, you are stripped of one level of each powerup (to prevent ‘stranded-on-level-16-with-a-weedy-gun’ syndrome).

The powerups are:

[] Extra life
[
] Extra smartbomb
[] Extra blob
[
] Super shield - recharges itself slowly but discharges twice as fast. Collect more super shields for a faster recharge with corresponding faster discharge, up to level 3.
[] Rapid fire - every 8, 4, or 3 ticks instead of 10
[
] Super laser - does 2, 3, or 4 points of damage instead of 1
[] Spinning orbs - they rotate around your ship twatting aliens. Collect up to 3 of these
[
] Homing missiles - fire automatically when a blob is under attack. (Cheese and onion Union Jack tickler, aka Pack of 3 :slight_smile: )

The bosses (eolgs) will appear at the end of every 4th level. I plan to have 32 levels in the game, so I’ll have to have 8 eolgs. After level 32, I won’t describe the attack waves in XML any more, you’ll just get 8 waves of 8 random gidrahs per level thereafter and a random eolg every four levels, until you die.

I have to consider these factors when adding features to the game:

  1. How long does the feature take to develop, and hence how much money does it take to develop it?
  2. How much more of an incentive does the feature have to purchase the full version of the game?
  3. Does this work out in turns of return on investment?

In the case of powerups, it makes the game more satisfying when you get a few good ones as you really get a feeling of invincibility (illusiory, of course, as it still only takes one bullet with your name on it). The player benefits are clear, and it might result in, say, an increase of 0.1% to the number of people registering the game, and that might result in another £1,500 profit on a (guesswork) registration rate of 1% on 100,000 downloads over the years at £15 for the full game. As the powerups are likely to take only a week to implement that will probably pay off so I’m pretty happy to be doing it. Of course I won’t know until it’s too late, but I’ve got to start somewhere.

The case for the eolgs is harder to pursue. Eolgs take, typically, about 2-3 days to design, animate, and program or so, being complex as they are. Therefore we’re looking at approximately one month to do the eolgs. Now if having eolgs every four levels is a registration incentive - “ooh, I must get to see the next one” etc. - then it’s got to be a pretty powerful one. Remember, Space Invaders, Galaxians, Pac Man, Defender, Scramble - none of them had bosses, but people got hooked playing them just the same, because they got into the “Zone” and became one with the machine. Man. Then of course there’s the fact that half the people who register the game may never see past level 16 anyway because they get bored or because they’re just too crap at playing it, in which case that’s a load of time and effort wasted because most people will never see these gidrahs anyway.

If eolgs only give me another 0.5% conversion rate then that’s £1,500 for one months’ work, and that’s no bloody good. Not to mention they’ll add a megabyte to the size of the download (actually not so bad as it’s the size of the demo that usually puts people off buying games). On the other hand if the combination of eolgs and powerups makes the game twice as compelling as it was without them - say, a fantastic 2% conversion rate - then it’ll mean £15k for 5 weeks’ work and that looks like a reasonably safe bet.

All based of course on whether I publish the game or someone else such as Dexterity or Garagegames publish it, in which case we get a far, far smaller cut. Dexterity offer 35% (so we’d only make £5k on it) and Garagegames offer 65% (so we’d only make £10k on it). On the other hand, Dexterity and Garagegames will probably give us ten times the downloads we otherwise might have. I’ll be looking into this at the end of February when hopefully XAP will be at ready to start a wider (read: public) test phase.

What I’d like to do now is ask for your opinions on eolgs:

  • Do you consider them to be an important part of the game to break the flow up?
  • Or do you just like getting sweaty palms and blasting ever more ferocious swarms of little gidrahs?

Answers to cprince@shavenpuppy.com please!

Cas :slight_smile:

Today I did a little refactoring to get the game sequence correct. The game sequence goes roughly like this:

STOPPED -> PLAYING -> END_OF_LEVEL -> PLAYING -> GAME_OVER -> STOPPED

and it runs in a GamePanel. The Game class itself has only three states:

TITLESCREEN -> PLAYING -> (ENTER_HISCORE) -> TITLESCREEN

While it’s in PLAYING state the GamePanel gets to tick every frame and do whatever. In any other state, the GamePanel is not visible and hence doesn’t tick.

I use “state machines” quite a lot in XAP. It helps to ensure that things are running properly and progressing in the correct fashion. A state machine is something that does this:


private int state;

private void setState(int newState) {
      if (state == newState) {
            assert false : "Illegal state change";
      } else {
            switch (newState) {
                  case PLAYING:
                        switch (state) {
                              case STOPPED:
                                    // Start a new game
                                    state = newState;
                                    break;
                              case END_OF_LEVEL:
                                    // Begin next level
                                    state = newState;
                                    break;
                              default:
                                    assert false : "Illegal state change"
                        }
                        break;
                  case END_OF_LEVEL:
                        assert state == PLAYING : "Illegal state change";
                        state = newState;
                        // Do end-of-level gui
                        break;
                  case GAME_OVER:
                        assert state == PLAYING : "Illegal state change";
                        state = newState;
                        // Do game over GUI
                        break;
                  case STOPPED:
                        assert state == GAME_OVER : "Illegal state change";
                        state = newState;
                        setVisible(false);
                        break;
                  default:
                        assert false : "Illegal state change";
            }
      }
}

You can see it’s sprinkled with assertions about the way I think state should progress. I’ve used this method in Entities, Gidrahs, the Player, the Game, the GUI, etc. to make sure that everything is done in the correct order, and it’s trapped quite a few logic bugs so far.

There’s a nice way to do state machines in Java that involves modeling each state as a class with an operation to switch to another state defined in it; this is the proper OO way of doing things but it’s not really necessary for my little game as I have so few states to worry about.

Stuff done:

[] Game now progresses to the next level when the gidrahs are all dead
[
] End of level GUI now shows your bonus. Need to do a blob animation in it though to count them in one by one.
[*] Smartbombs are implemented. They’re quite psychedelic at the moment, being rainbow coloured. I rather like them like that.

Now I’m going to work on the smartbomb sound effect.

Cas :slight_smile:

A day off! Well isn’t that nice. Horseriding and Harry Potter 2. Better than the first one. Harry looks like Louis Theroux even more. And he’s a bit big for a 12 year old.

Cas :slight_smile:

XAP has gone pseudo 3D! Wait! Before you get excited it’s not 3D at all, it’s still 2D, except that I’ve changed the view frustum from a glOrtho to a glFrustum and currently I’m fiddling about trying to get the right range of values which leaves the original orthographic projection plane at z=0 intact.

Using the new projection I’m able to do 3D particle effects, which will be nice. The backgrounds have also got some proper depth now, and they look better for it. In fact, good enough to keep instead of replacing them with something else (which would have a very poor return on investment anyway).

Stuff done:

[] XAP has gone 3D ish, which fixes the background parallax perfectly.
[
] Found out where the Gunner’s got to - had an extra zero on a timer, so he just slept in is all.
[] Resisted coffee all last week! Hurrah!
[
] Make Bubbles slightly more aggressive and chase Blobs a bit: now they pick a Blob to molest and 30% of their moves will be towards it instead of wholly random. If there are no Blobs they start menacingly wobbling towards the player in an unconvincingly deadly display of terror.
[*] Shuink sound effects down to 11khz mono where necessary. Some of the sounds are actually better than before. Strange! Not tried Ogg yet.

Cas :slight_smile:

Much work for the Man today. Little XAPpage done:

[] Lasers now frizzle away a bit as they fade - the particles drift a few pixels like smoke. Sort of. I’m not sure if it’s an improvement or not so I’ll test it on my guinea pig, Brian.
[
] Bubbles were losing their Blobs and wandering off randomly. Now fixed.
[*] Gunner timing tweaked.

Because it’s such a short diary entry I thought I’d share with you a bit of code from my Game class: the Main Loop.


public static void main(String[] arguments) {

      try {

            init();

            int frames = 0;

            Timer timer = new Timer();
            timer.reset();
            timer.resume();

            boolean f6WasDown = false;

            while (!finished) {

                  AbsMouse.poll();

                  long then = Sys.getTime();

                  gl.clear(GL.COLOR_BUFFER_BIT);
                  Interface.mainLoop();
                  Interface.render();
                  Resources.manage();
                  gl.swapBuffers();
                  soundPlayer.play();

                  if (Keyboard.isKeyDown(Keyboard.KEY_F6)) {
                        if (!f6WasDown) {
                              f6WasDown = true;
                              screenshot();
                        }
                  } else
                        f6WasDown = false;

                  if (Sys.DEBUG && Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
                        System.exit(0);

                  if (!GL.WGL_EXT_swap_control) {
                        long now = Sys.getTime();
                        float elapsed = (float)(now - then) / (float)Sys.getTimerResolution();

                        while (elapsed < FRAME_TIME) {
                              // Wait a bit
                              try {
                                    Thread.sleep((long)((FRAME_TIME - elapsed) * 1000.0f));
                              } catch (InterruptedException e) {
                              }
                              now = Sys.getTime();
                              elapsed = (float)(now - then) / (float)Sys.getTimerResolution();

                        }
                  }

                  // Count the frames per second
                  frames++;
                  float time = timer.getTime();
                  if (time >= 1.0f) {
                        fps = (int) (frames / time);
                        timer.reset();
                        frames = 0;
                  }
            }

      } catch (Throwable t) {
            t.printStackTrace();
      } finally {
            cleanup();
      }

}

Thrilling eh? Unfortunately all the exciting stuff happens in the Interface class which is the entry point to my GUI library :slight_smile: The general gist of it is that the Interface works out what the mouse and keyboard are up to this frame, and manages all the little controls and windows and things that I have on the screen (one of which is a Panel running the game). Then, after all the thinking’s done, it all gets rendered in one go, and I swawp the buffers and play any sounds that are waiting to be played.

However if there’s any newless clewbies reading take note of two things going on in this loop:

  1. There’s a frames-per-second counter. A lot of people ask about this very simple piece of code - no idea why as it’s beyond trivial, but here it is, if you’re still stuck.

  2. If there’s no fixed vertical blanking rate from the monitor (from WGL_EXT_swap_control on Win32, no idea about Linux and OSX yet), there’s a thread-based sleep hack in there to keep things at the right rate. It’s not guaranteed to work (although it just happens to on my laptop) but it’s the best you can do without busy-waiting on the hires timer which is a nasty thing to have to do.

Cas :slight_smile: