Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (499)
Games in Android Showcase (118)
games submitted by our members
Games in WIP (567)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2
  ignore  |  Print  
  The XAP development diary  (Read 13381 times)
Thotep, noblemaster and 2 Guests are viewing this topic.
Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Posted 2002-12-05 13:30:13 »

This is a diary of my first commercial game development, for your amusement, enlightenment, and perusal.

I've mysteriously gained some kind of reputation on the 'net for Knowing Stuff but without ever having actually produced anything. So here goes: and indy game. Looking for a publisher! If you're interested, get hold of me: cprince@puppygames.net

Now, it has to be said there have been many aborted attempts before by myself to write a game. You want to know why 95% of the games being written don't get published? It's because they don't bloody get finished, that's why.

But there's other reasons. Massive overambition is the main one after failure to finish the thing, and is usually the cause of not finishing it in the first place. XAP is the final boil-down to the simplest game I want to make. I can't make a game much simpler than XAP. It's kinda retro, really, but there's quite a market for people who want retro-style games. Look at PomPom and Llamasoft.

If I can't finish XAP by February I'll... I'll... take a bit longer over it.

Before you ask, I suspect that it will be available for Win32 and Linux as a binary download, and possibly as a Java download too for those who already have JRE1.4 installed. It'll be temptingly cheap enough to be affordable and just expensive enough to assure you that it won't be a big bag of shite. And there will be a 4-level demo to get you introduced to a few of the basic aliens and maybe one big boss.

My usual offer goes out to the artists amongst you: if you take care of the art for me, there's 20% of the profits in it for you. If you can do sound, there's 10% in it for you. Just send me a portfolio...

And now, on with the diary.

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #1 - Posted 2002-12-05 13:31:04 »

Having ripped the menu and GUI code out of a project on hold whilst Niels gets some free time to himself, XAP is born. The game design was thought of many years ago, so it's a case of beautifying* it all and refining it somewhat.

For starters I'm going to code the very basic game, which is this: defend the blobs from the evil bubbles. When a bubble captures a blob it turns it into a Mad Jelly. When all the blobs die you are attacked by a swarm of Jellies. The bubbles are otherwise defenseless, so they have a backup alien, the Tringle, to help them. Tringles can shoot. If you spend too long on a level we will hurry you along by sending in a particularly vicious alien, the Gunner, which behaves like a Jelly on steroids, and isn't worth any points either. As Jellies are particularly nasty as it is, the Gunner is worth avoiding. Periodically a new attack wave appears, or as soon as the player has killed all the existing aliens. After several attack waves the level ends.

Your ship is controlled by the mouse and the ship's gun is targeted also by the mouse. The spacebar fires a smartbomb, and holding down the shift key activates a shield which discharges quickly. The shield can be used to kill enemies but it discharges even quicker, and the bigger the alien, the more it gets discharged. I think I'll relate the collision discharge to the number of hits the alien needs before it dies.

Points are scored for rescuing blobs and killing enemies. A bonus is awarded at the end of the level for every blob left alive. Every 8 levels you get all your blobs back. Every level your shield is recharged according to how many blobs you have left.

The overall feel of XAP is going to be extremely hectic, breathless gameplay. You get no respite; and this should get you into the Zone, where your subconcious starts to play the game and your peripheral vision goes black. I'm in two minds about powerups; on the one hand, they add a bit of fun and variation; on the other, they always, always, always, spoil the balance of gameplay. I think this time round I might leave them out.

* Any beautifying, of course, ain't gonna be done by me...

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #2 - Posted 2002-12-05 13:31:45 »

Today I put the player into the game, a stunningly disappointing purple circle. There's a blue rectangle at the top of the screen for a status display, and the game area is sort of dark red. Not because it's a nice colour; just because I wanted to make sure something got displayed.

After a multitude of false starts the player's ship finally accelerates towards the mouse when the left button is held down. It takes very little time to realise that it's going to accelerate clean out of the playing area, so I've put in a little bit of code to decelerate too.

I'm really going to need some help with the graphics Wink Currently I've drawn single-frame graphics for each thing in the game, and no more. Ideally they all need to be lovingly rendered by a 3d Studio MAX genius... but of course Niels is busy. C'mon, help me out...

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #3 - Posted 2002-12-05 13:33:05 »

Lasers today. I've got the laser defined in XML, along with various parameters like its thickness and speed and range etc. etc. etc. so I can fiddle with it at leisure. Right now it looks beautifully Defender-esque, which fits the game design to a tee, as XAP is very firmly a Defender-clone.

The laser proved awkward in the end. It's quite a complicated and expensive beast to produce - each laser is drawn with, say, 256 scaled sprites. This is a lot of sprites when you've got a whole bunch of lasers being drawn. If I just allowed 8 lasers that means I've used 2048 sprites just to draw them! That's going to get a bit taxing on the low-end systems, like a TNT, which is my target low-end system - and I haven't even thought about the aliens or the background or the particle effects yet...

Not only that, but the creation of a single laser involves creating about 8k of data and a large number of sprites. Fire that laser a hundred times and you've got nearly a megabyte of garbage to deal with and done no end of sprite addition and removal. I'd rather not let the whims of the garbage collector spoil the show, so the laser now incorporates a pool of instances, and they get recycled. Instantly there's no garbage! Hurray! And I also discovered that by only drawing every other pixel of the laser I get approximately the same visuals but with twice the performance. Double hurray!

Currently they fade out in random colours. I'm not sure I like this; I think they need to boil away down a set gradient of colour.

I showed my wife the laser. She's too young to remember much before 1984 Smiley And she takes one look at this lovely laser, which I spent 6 hours straight getting perfect, and says, "It looks shit. It's too blobby and messy." etc. There's no pleasing some people Wink I tweaked the XML a bit but it needs those colours fixing. At least the background is now black.

On another note: in the original XAP I was limited by the Amiga and AMOS to having a static playing area. Quite hectic but not very cool. In the new XAP I think I'm going to scroll the playing area around and have a radar map in the middle of the screen. I'll always have the player diagonallly opposite the mouse from the centre of the screen. I tried this out a couple of months ago in a quick test; it's quite confusing at first, but you get used to it quickly.

I think tomorrow I'll put the scrolling playing area in. I suppose that means I need a background, and I think a parallax background would look great and suitably retro. Being good and lazy with OpenGL I think that means I'll be drawing three huge transparent quads on top of each other to give me a bit of depth. I might even squeeze the original XAP background in there somewhere, but it depends on fast line drawing and I seem to recall some of the older GL cards had awful line drawing ability, inexplicably.

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #4 - Posted 2002-12-05 13:39:58 »

Today I have spent rather too much time - about 3 hours - tracking downa bug in the Server VM for 1.4.1_01. If only I'd known.

What was happening is that after whizzing around the screen testing the laser out for a while, the left mouse button would just mysteriously stop working. On closer inspection it turns out that it hadn't stopped working, but that the JVM compiler had suddenly made an optimisation that caused a local integer variable which contained the mouse buttons state to suddenly have a rather random negative value, which is of course impossible if you only OR bits 1, 2, and 4 together...

So, back to the client VM.

Spot the obvious optimisation for lasers: why am I scaling them when they might as well be the right size in the first place? Duh. That's saved a couple of thousand floating point operations...

Work on scrolling can begin now. This means I have to put the game panel into on of my GL scroll pane controls and turn off the scrollbars. All this does is translate and clip what's drawn; I don't envisage there being any advantage to figuring out if any sprites are outside the drawing area as GL will clip them more efficiently than I can.

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #5 - Posted 2002-12-05 13:58:00 »

Here's a screenie of a bit of the UI. It's all rendered in realtime and animates nicely. Could perhaps do with some texturing on it or something:



And here's that laser and pitiful player spaceship:




Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #6 - Posted 2002-12-05 16:35:56 »

Scrolling is now implemented, along with a rotating background. I turned off the clipping as things just vanished when they got to the edges of the scrolled component - most disturbing. But not as disturbing as the rotating background! There's this odd iris pattern I knocked up in Cosmigo's ProMotion. There's three of them, in random colours, transparently overlaid on eacher other and rotating in different speeds in different directions. Every now and again they change direction. What with you zooming around the screen and the mouse changing the scrolled view instantly it gets really quite disorientating. Hopefully I'll manage to make a few people sick!

The player can now zoom off into the distance and never return. I think I might have to put a limit on how far out of the game area you can roam. Or possibly I'll just have you attacked by Gunners.

That's enough of that for today. Tomorrow, I think we need to put the cute purple blobs in that you need to rescue.


Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #7 - Posted 2002-12-06 19:51:03 »

06/12/2002

Just before I went to bed last night I put in a colour fade sequence class, which smoothly interpolates between a sequence of colours. Very nice. The laser now boils away from white through yellow, orange, red, and finally evaporates into ultraviolet. It's also a bit longer and faster now. Perfect. I'll be using it to do some other special effects as well, including strobes. Whizz for stroboscopics! If you don't throw up from the rotation I'll make sure you have a fit instead. This will, of course, have an option to turn it off Smiley You can't be too careful these days.

This morning I went horseriding up in dense fog in the hills for two hours. I'm absolutely knackered and I've only really just got up!

I'm too lazy to put the purple blobs in so I'm going to have a bit of fun doing the background. First off is to make the layers of the rotating iris a bit parallax to give it more depth; then I'm going to have a stab at implementing a few layers of the original XAP "circuitry" background with them. Display lists is the way to go.

It's fun starting work at 3pm.

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #8 - Posted 2002-12-06 19:55:34 »

Oh dear. Well, I put the new parallax background in, in sort of transparent green circuitry, on three layers. I mean, it works and things... but it just looks shit. Ten years has been hard on an idea that was just a timesaving hack in the first place...

It has to go. I think I'll just replace the whole circuits and rotation thing with a couple of huge textures.

Here's a screenie for posterity:



Too bad you can't see it moving. Well never mind, it sucks anyway.

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #9 - Posted 2002-12-06 22:04:21 »

07/12/2002 1am

Put blobs and bubbles in the game. They aren't animated at all, so they look exceedingly crap, rather like the player's ship. However the background has undergone a re-evaluation, and is now a more colourful affair and actually looks quite nice in a retro abstract way.

The blobs sit around and occasionally jump about. The bubbles wander about in a diagonal fashion. Currently that's all they do, because the collision detection code isn't implemented yet (although it's in there, there's simply no action on a collision). Collision is going to be radius-based rather than bounding boxes for now, because it's easier.

Time for bed.

Cas Smiley

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #10 - Posted 2002-12-07 15:12:40 »

Collision detection has been implemented. This turned out to be a bit of a hassle as well. Originally I'd thought I could get away with just using a radius and doing collision detection that way. This generally works fine and providing the radii are small enough then you don't get too many false hits, and when a few pixels scrape then you can just consider it a lucky escape. "Chalkdust!" as McEnroe used to yell at the umpire at Wimbledon.

Unfortunately the laser is lozenge shaped and moves very quickly - 32 pixels per frame - which is likely to see it sailing straight through some gidrahs. (The aliens are called gidrahs. Look it up.) So now, laser collision is done separately. When the laser is due to animate, it finds out all the gidrahs in a fairly large radius to itself, i.e. the radius of the circle which encompasses its entire 32 pixel line move. This gives us a very small shortlist of likely collision candidates. The laser then steps two pixels at a time towards its target, checking for collisions with gidrahs as it goes. The first one it hits usually stops it. In the worst case scenario, there will be 50 gidrahs crammed into a 32 pixel wide circle right next to the laser and it will somehow manage to move 16 times and have to check each gidrah for collisions. This is so utterly improbable it's not worth worrying about. Two or three gidrahs is highly likely, and so is a collision with at least one of them, so I suspect that this means that a laser fired into a bunch of aliens incurs about 30 collision checks. Not going to break the bank I don't think...

So now the blobs disappear when they're shot, and so do the bubbles.

Tomorrow I won't get much time to do anything as we've got friends round for dinner. Braised beef in port and stout with pickled walnuts and thyme with potatoes dauphinoise and redcurrant red cabbage, followed by drunken pears with rosemary cream. Should be nice.

But just in case I can squeeze in the time, I think it's high time the aliens beamed in when they're spawned and exploded into many tiny bits when shot, don't you?

Technical Note

Collision is implemented as a closed system where all classes are known beforehand and extend from a base class, Entity, which has a radius and a position upon which to base its collision. When a collision occurs between two entities, both are informed simultanously of the collision:

1  
2  
3  
4  
if (entity.isTouching(this)) {
      entity.inCollisionWith(this);
      this.inCollisionWith(entity);
}


In Entity, there is an inCollisionWith() method which further breaks down the collision into specific known classes of collision and dispatches the correct method "in reverse". This is fine providing you never try to call the specialised inCollisionWithXXX() methods directly as the reversing will not happing and you'll get a one-sided collision where one party has no action performed upon it:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
abstract class Entity {

      abstract void inCollisionWith(Entity entity);
     
      // Default behaviour is to ignore the collision
     void inCollisionWithLaser(Laser laser) {}
      void inCollisionWithPlayer(Player player) {}
      void inCollisionWithBlob(Blob blob) {}
      void inCollisinoWithGidrah(Gidrah gidrah) {}

}

class Bubble extends Entity {
      void inCollisionWith(Entity entity) {
            entity.inCollisionWithBubble(this);
      }
      void inCollisionWithLaser(Laser laser) {
            // Oh no, we've been shot!
           kill();
      }
}

class Gidrah extends Entity {
      void inCollisionWith(Entity entity) {
            entity.inCollisionWithGidrah(this);
      }
      void inCollisionWithLaser(Laser laser) {
            // Oh no, we've been shot!
           kill();
      }
}

class Player extends Entity {
      void inCollisionWith(Entity entity) {
            entity.inCollisionWithPlayer(this);
      }
      void inCollisionWithGidrah(Gidrah gidrah) {
            // Oh no, we've hit an alien
           kill();
      }
}

class Laser extends Entity {
      void inCollisionWith(Entity entity) {
            entity.inCollisionWithLaser(this);
      }
      void inCollisionWithGidrah(Gidrah gidrah) {
            // Hit something, so stop the laser
           kill();
      }
      void inCollisionWithBlob(Gidrah gidrah) {
            // Hit something, so stop the laser
           kill();
      }
}


Cas :)

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #11 - Posted 2002-12-07 22:16:40 »

Now the bubbles explode in a satisfying shower of burning particles. Not bad for an hours' work under the influence of a bottle of wine.

Definitely retro.

(Food for fact freaks: each explosion consists of no less than 128 different particles whizzing off in different directions and different velocities, with a total duration of approximately one second)

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #12 - Posted 2002-12-08 23:13:16 »

At last, the evil Mad Jelly lives (although he doesn't shoot yet). In order to give me plenty of cannon fodder to playtest with the bubbles automatically spawn at random intervals giving me infinite gidrahs to zap. As a strange side effect of this, they appear on the title screen as well. I suppose that'll have to stop...

And another strange thing about the title screen is it sometimes hangs around in the background whilst you're playing the game. No idea why yet, but I'm sure it's trivial.

So, the bubbles now capture blobs, and after about 4 seconds they turn them into a nasty green jelly. When I first put the jellies in they just shot towards the player like a ... a... rabid jelly. It's difficult to describe what it looks like when a small swarm of green jellies hurtle towards you intent on death. Then they just sit there wobbling at you, because currently there's no code to kill the player Smiley

So the jellies got slowed down a bit and at least there's a small chance of shooting them before they get you.

I even remembered all the daft fringe cases like the blob gets shot by the player accidentally in a bungled rescue attempt, or the bubble gets zapped and the blob gets rescued etc.

Also, I put in an alien res-in effect, using a shrinking glow effect and a few particles whizzing together. Looks quite nice but might need more tweaking. This gives you about 1 second to avoid having an alien res in on top of you. Fortunately they still can't kill you of course.

Reduced explosions to 64 particles. Seems like enough. You should see what it looks like when you waste five bubbles in a row, it's like bonfire night.

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #13 - Posted 2002-12-11 16:48:53 »

At last, you can die! In a huge shower of particles, of course. All the effects, it has to be said, look pretty much the same, so they're going to have to be fiddled with. In particular I need some different particle sprites to the rather boring 'spotlight' glow, which isn't even animated.

With death comes reincarnation. You get a second or two pause after death, and then you rez in in a swirl of ... particles. (Guess what - I like particles Smiley ) This gives you a moment to position yourself somewhere where the aliens aren't. The view suddenly snaps into place once you materialize which is rather disconcerting so I think that's going to have to be a smoother affair, but I'll put that in later when I'm tuning it all.

Strange things happen when you run out of lives. The title screen reappears unexpectedly. All the particles remain frozen in space, but the gidrahs keep trundling around!

We also now have the mighty Tringle to defend the bubbles. The Tringle is also hopelessly drawn, as if by an idiot, such as me. It's red, triangular, and rather obviously not very mean. It wanders around in roughly the same pattern as the bubbles right now, and it doesn't even shoot yet so it's pretty useless.

With tringles we now have attack waves and multiple levels.

A new attack wave comes after a timeout (currently 30 seconds on the first level), or when there's only one gidrah left on the screen. (To keep track of how many gidrahs are on the screen, the Gidrah class gets a static int, and the constructor increments it, and the doFuneral() method decrements it).

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #14 - Posted 2002-12-11 16:50:16 »

Added a small new feature to particles to make them change in size over time by a fixed amount. Slightly prettier as a result, but still not as good as having some proper particle sprites to choose from.

XAP has gotten a little messy now with all the XML and features stuff. Here's how it works:

During development I run a XAP Resources Converter, which loads an XML file, which then maps tags to classes called Resources. Whenever a tag is encountered, I create a new instance of the class and stuff it in a Map with a name, along with its parsed attributes and other data.

Some of the instances are effectively singletons; the Player is a singleton. I declare a mapping to it, include it just once, and then maintain a single instance of the player as a static variable on the Player class itself.

Some of the instances are "templates": each of the gidrahs is a template. For example, I map the "<bubble> tag to xap.gidrahs.Bubble, and create a single instance of Bubble with the name "gidrah_bubble".

What I can now do is get this template Bubble instance like so:

1  
Bubble masterBubble = (Bubble) Resources.get("gidrah_bubble");


I can then use the template to spawn a copy of the Bubble - ie. create a new alien to plonk in the game:

1  
Entity.spawn(masterBubble);


There's a spawn() method on Entity (the superclass of Gidrah, which is in turn the superclass of Bubble) which calls all the relevant stuff to create me a new alien.

So what's all this Resources thing doing then?

Well, Resources is a way of stashing all the information about a thing that you want, without it actually having to really exist. Not only are there gidrahs and game levels etc. in there but I'm putting all my textures and (soon) sound effect in there too.

When I want a Resource, I look it up by its name. If the resource hasn't been created yet, then it goes off and does whatever clever stuff it needs to do to become created. In the case of a GLTexture, for example, I load in a binary image file and call the various GL commands to upload the texture into OpenGL.

I can then explicitly destroy() Resources when I don't want them any more, which will unload anything that's needed to be unloaded, but which leaves me with the raw uncreated Resource hanging around just in case I ask for it to be created again.

So back to the resource converter: its output is a nice serialized HashMap of resource names to serialized resource objects, all waiting to be created when needed. This lets me ship the game without needing all the XML APIs installed; the only classes dragged in are a few of the interfaces and supporting classes.

Now I'm going to wrestle with OpenAL and try to figure out how to make a suitably menacing laser zap.

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #15 - Posted 2002-12-11 20:56:40 »

Well I'll be dipped in dogshit! I wrote some ALBuffer and ALSource classes for the Shaven Puppy Game Library and wrote a .WAV -> .jgwave converter (my own special format which I understand Smiley ), and every Entity now gets an ALSource. I'm not sure if that's wise but anyway - the laser was the first to get a noise, and it's a proper laser noise! None of this quiet "pewww, pewww" pingy rubbish - this laser sounds like it's going to hurt!

Die alien scum!

However, I have had less success with the res-in noises, and most disappointing of all, the explosions Sad

Basically, they just aren't working and I don't know why yet...

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #16 - Posted 2002-12-15 15:34:24 »

Brian suggested to me that creating 500 OpenAL sound sources might have been the problem Smiley I was just treating them like OpenGL textures, i.e. a relatively unlimited resource, and I was expecting the OpenAL drivers to try and cope with whatever hardware it has to mix them. Wrong! Seems like I can only rely on about 8 of them actually being present. It's a bit annoying I don't seem to be getting an exception if I ask for sources and they can't be created. More investigation with Brian about that one.

What I've got now is a SoundPlayer class which maintains a little pool of 8 ALSources, each associated with a priority and the time it was last told to play a sound. When I want to play a new sound I search for the oldest lowest priority sound effect and stop it, and then play the new sound using it.

It's not quite perfect as some fairly low-priority but long lasting sound effects can get cut off a bit too soon. I think I should really calculate how long each sound is going to play for and mark them unused after that time, so I can always pick a source with no sound effect currently playing in it. So that's on the "to-do" list.

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #17 - Posted 2002-12-15 15:37:44 »

Not much time on the game today. Out riding horses for a couple of hours. Ouch! Tried to create a decent explosion sound effect for when the player gets fingered. Ended up with something that sounds rather like a crisp packet going pop Sad Igore, more work at the labs!

Oh, I remember what I did now: gidrahs can now shoot! Quite an amusing start to it as well. I got the probability that a gidrah will shoot a bit wrong and immediately on appearing the tringles set about blasting the player with a huge cloud of deadly plasma balls. (And due to another bug they flew at the player at hundreds of pixels per second - resulting, of course, in instant death).

So the tringles now shoot much more rarely. Jellies and Gunners shoot at regular intervals as they home in on the player. They seem to be moving faster than their bullets which is perhaps not quite right. Much bullet speed tuning is required.

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #18 - Posted 2002-12-15 15:41:12 »

There are lots of niggling things that are beginning to annoy me in XAP now which need to be fixed. There's a glitch with the sprites that sees them flicker quite a lot; this is something to do with NV_vertex_array_range. It needs fixing.

When you die with the mouse button held down you fire a laser upon reappearing. By a stroke of incredibly bad luck this always seems to point at one of the cute purple blobs. Splat!

And when you die the res-in sound effect starts too early (i.e before the actual res-in starts, in the "death delay"). And when you've finished appearing, there's a cluster of particles left hanging about for a bit.

When the game ends none of the particles vanish in your final explosion. And if you start a new game all the existing gidrahs are still there!

So it's time to make a big mongy list of Things To Do and work them through one by one before I continue. Someone once told me that you are vastly more likely to achieve goals when you actually write them down. This can backfire slightly of course - I've written down such chores as "tie shoelaces" and "eat lunch" before - but by and large it's a great technique for getting things done. I shall post the list up here when it's full of stuff and tick them off in the coming days.

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #19 - Posted 2002-12-16 23:02:51 »

- Alien bullets should be a single sprite: currently I'm (wastefully) drawing a blue halo under a central flickering white core, which looks nice but really should just be one sprite... and it would be nice if it left a little teeny trail of sparks too, and some smoke, like a sparkler.

- fix sound problems. Oh, how these are the bane of my life. Apart from being crap they don't play when they should, still. It all starts off OK, then after a while, one by one, they just sort of don't happen any more. Except for the laser, which seems to be the only one not affected. It's terribly difficult to figure out if it's OpenAL or me.

- when all the gidrahs die go to the next level. This involves the blob bonus screen where you get points for surviving blobs.

- try and think of a better background.

- put in shield code for player. Hold down left shift, on comes the shield.

- when all blobs die make swarm of jellies appear

- adjust alien bullet speeds to get them just right.

- adjust player's max speed to cope with the bullets and jellies.

- do better alien res-in effect. I have some ideas about concentric rainbow circles. Hippy ideas I suppose. I admit to being heavily Yakfluenced. But then, Yak's games were always the best ones. Oh, and Andy Braybrook's too. Them were the days etc.

- do better player res-in effect. It's really rather lame, just a bunch of dots spiralling in from space.

- maybe go to slight 3d perspective so I can have particles flying in the air a little bit. It'll look better when there's a more reasonably solid background and shadows under the sprites.

- draw some particle animations - the current "spotlight" effect is great as a
general purpose particle but really I need some nice animated hoops and sparkles as well.

- better alien death - make particles fly in direction of damage? That would be nice. When a laser bolt slams into the side of a gidrah the bits could fly off in the appropriate direction.

- put up Game Over sequence

- remove leftover crud when the game ends like particles etc

- find out why the level doesn't appear to reset when you start a new game: all the last gidrahs are still there and the gunner usually appears immediately.

- do some blob sound effects: a wee scream when they get shot; a suitable noise when they're captured by a bubble; a bonus noise when you rescue them from a bubble; a bonus noise when you rescue them from a bubble with style and panache; and the noise of a Mad Jelly appearing - I seem to recall sampling the maniacal cackle at the start of a song called Lucretia by Megadeth last time round which I think I might use again.

- put the mouse crosshairs in. Depending on what you're pointing at the mouse crosshair changes. For example it changes to a "don't shoot" crosshair if you wave it over a blob.

- blob farming. I can't remember now if this was in the original one, but I always thought that dragging the mouse over blobs should coax them to move where you want them.

- make the bubbles appear in the proximity of a randomly chosen blob.

- make a little bonus score appear if you rescue a blob

- smartbombs: tap ctrl key, eat nuclear death gidrahs!

- position player in the middle of the battlezone at the start of the level.

- smooth movement from the current scroll position to the desired scroll position to prevent nasty view snap when the player beams in.

Cas Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #20 - Posted 2002-12-16 23:06:15 »

Done:


  • adjust player's max speed - now 32 pixels/frame
  • adjust alien bullet speed - now 4 pixels/frame, and unvarying


[size=1]hm yes, so they were the easiest things on ths list Smiley[/size]

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 Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #21 - Posted 2002-12-19 22:23:36 »

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 Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #22 - Posted 2002-12-19 22:26:22 »

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 Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #23 - Posted 2002-12-20 15:05:58 »

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 Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #24 - Posted 2002-12-24 06:46:45 »

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 Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #25 - Posted 2002-12-24 06:48:27 »

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 Smiley

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 Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #26 - Posted 2002-12-24 06:49:27 »

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 Smiley


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


Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #27 - Posted 2003-01-02 21:08:00 »

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:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
/**
 * 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 Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #28 - Posted 2003-01-05 11:14:00 »

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 Smiley

Offline princec

JGO Kernel


Medals: 390
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #29 - Posted 2003-01-06 11:49:55 »

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 Smiley

Pages: [1] 2
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Pippogeek (39 views)
2014-09-24 16:13:29

Pippogeek (30 views)
2014-09-24 16:12:22

Pippogeek (19 views)
2014-09-24 16:12:06

Grunnt (45 views)
2014-09-23 14:38:19

radar3301 (27 views)
2014-09-21 23:33:17

BurntPizza (63 views)
2014-09-21 02:42:18

BurntPizza (33 views)
2014-09-21 01:30:30

moogie (41 views)
2014-09-21 00:26:15

UprightPath (50 views)
2014-09-20 20:14:06

BurntPizza (54 views)
2014-09-19 03:14:18
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!