Monday, 14 December 2009

Update

Like most bloggers, I sometimes take time off from blogging.

I have had a number of interruptions, including a trip to Barcelona, work on Mythaxis and (guiltily) replaying Myst III - magnificent scenery.


I haven't been totally idle, though. Since I last blogged, I have refined the Junk and modified a spiral staircase algorithm to give me swooping stairways. I'll post some examples real soon now. And Christmas hols are coming up. I should get some more design done then.

Friday, 11 September 2009

Reporting completion on the Junk

It's been a slowish business, but I'm now reasonably happy with the junk. After all, it's only a platform for transport and a piece of furniture to view from afar.

As a sprite, it'll be viewable at various sizes and seen from left or right, but not animated.

I'll do a separate animation of the waterline splashing along, so it appears to be moving, and calculate speeds / sizes for various manifestations of it.

Monday, 17 August 2009

Yet More Junk

The latest version of the junk and its dinghy (which shares the junk's hull shape) sans ropes, but ropes will appear soon, thanks to Chris Bartlett's Rope macros and "after-sales support".

Benjamin Roux has also volunteered to help with the project.

Tuesday, 28 July 2009

More Junk

Got the masts and sails in the junk. Had some difficulty with the decks, because patches are not 'real' shapes and differences, intersections etc don't work the way you'd expect. Solving it by fitting a deckhouse and then painstakingly filling in the areas left with boxes and polygons, which will lead to a more authentic final appearance. The picture here is hull, deckhouse, mast and sails.

Wednesday, 22 July 2009

Junk


Put together the hull for a Chinese Junk, using 3 bicubic patches (actually 2, because the port and starboard hull sections are mirror images of each other.) The view is of the transom (rear end) of the boat. I took the measurements for the hull profile from a design on the internet.

Next, the decks and masts.

Saturday, 13 June 2009

A Few Extra Plot and Image Points

I envisage a sea cave that the boat can sail into, but only when the portcullis across its entrance has been raised. So the player is at a land entrance to the cave, and can raise the gate from there, but the dock in the cave is only reachable by the boat sailing in.

Also, I started to devise a new spiral staircase function where the steps were not connected at the centre. I realised yesterday I could use an existing spiral stair function, and cut the centre out of it by differencing with a cylinder. I'd still have to add vertical struts on the edges for realism - a staircase can't just hang in the air - but the main job will be done.

Fan animation. I observed how a fan opens. The rearmost blade of the fan stays still, and only the top blade is showing. The top blade flips out, pulling the next and the next and so on.

I suspect the best way to create the images for this in povray would be in reverse. Start with the open fan as an array of blades, coat the array with the image, then for subsequent frames, pull the top blade back over the one underneath it, then pull them both back over the third, and so on, until the fan is closed. I'm not entirely sure this is possible, though.

Friday, 12 June 2009

A Bit of a Brain Dump


I haven't posted very much lately, partly because I was getting out the next issue of Mythaxis, but I have been thinking about it a lot. I have decided to start the game on a boat - a Chinese Junk. The boat can transport the player to various locations around the island as necessary, and I would use a chart table below decks to direct the boat to the destination.

The boat will also contain a number of useful items - including a fan to transport the player back to the junk, or summon it.

I already have a boat in povray. I just have to elaborate it a bit.

In thinking about this, I realised we must have a rocking effect for the scenery when on deck. I considered using an array of g2d rotated images for this, but I think it'll be easier just to pre-rotate the images in Paint Shop Pro and load them as sprites. I can arrange that they not be the whole size of the applet window by placing static sprites of portholes, sails, deckhouses etc to frame the background which will be a lower priority sprite.

I was briefly worried about fan management, because there are several fan functions, which I solved by having a hot spot on the open fan, and by having a special room for open fans.
  • pick up (closed) fan - double click when fan not carried
  • drop (closed) fan - double click when fan carried
  • open fan - single click when in inventory 'room' only and fan is closed
  • close fan - single click (not on fan hot spot) when in inventory 'room' only and fan is open
  • use fan - click on hot spot on open fan
Sounds complex, I know, but I think it'll be natural. I may remove the restriction on opening the fan only in the inventory. Fan animation is going to be fun!

I have come to the conclusion that I have to fill out the game in povray before I do any more gameplay. I just keep realising that the game isn't rich enough without a good deal more articles in it. The game's going to be small enough without looking impoverished. So the next big push is scenery.

I still haven't bitten the bullet of music in mp3, but I'm not too worried about that.

Friday, 22 May 2009

Break in Transmission

A whole month since I've had time to concentrate on The Game, but watch this space...

Wednesday, 22 April 2009

Version 1.1 now available

A zipped version with all the fixes to date is now available.

The original (lame) example now runs on 1.1 code.

Both of these can be accessed via:

http://amazonsystems.phpzilla.net/

Thursday, 16 April 2009

What Next?

I think I have reached a suitable point at which to preserve the current state of the code. So I'll upload version 1.1 in due course.

Next stage will be new artwork, followed by a new puzzle, then the music problem must be solved.

Scale and Flip facilities

I have now added scale and flip facilities, to allow the same image to be used for a sprite at different sizes and reversed.

Different scale in x and y direction is possible, invert, mirror and all three.

In the diagram:
1. Normal sprite
2. 75% scale on both x and y axes
3. 75% scale on both x and y axes plus mirror
4. 75% scale on both x and y axes plus mirror plus invert

Saturday, 11 April 2009

Priority

Having a little trouble with the priority of sprites, but nothing desperate yet. I have a feeling that monkeying with vector elements is the cause of the problem. I may have to try a different approach to sorting the sprite list.

(later) Schoolboy error. I was using insertElementAt() instead of setElementAt().

Thus - the Vector of Sprites appears in slist:
//      This is a sinking sort. On first pass, the highest
// priority sprite arrives at the bottom. On second,
// the next highest arrives at second bottom, etc.
// Sprites of the same priority remain in their
// original sequence with respect to each other.
for (ii = 0; ii< slist.size()-1; ii++)
{
for (jj = 0; jj < (slist.size()-ii-1); jj++)
{
spare1 = (Sprite)slist.elementAt(jj);
spare2 = (Sprite)slist.elementAt(jj+1);
if (spare1.getPriority() > spare2.getPriority())
{
slist.setElementAt(spare1, jj+1);
slist.setElementAt(spare2, jj);
}
}
}

Thursday, 9 April 2009

Gull motion bug fixed

I was dissatisfied with the original gull motion (see 30 December 2008 entry). Found out what it was today.

The previous table had the gull stopping for an extra beat at zero deflection. Now deflection goes from +3 to -3.

Monday, 6 April 2009

Important bug solved

Sorted. The solution was to drop anything being carried into the limbo room before doing the Restore. The bug was caused by the clash of an object being simultaneously carried and restored to an uncarried situation.

Also, and in connection with this bug, I added the "limbo" room to the system. All adventures need a limbo room in which to store objects that aren't anywhere else. For example, a sprite that has been destroyed, or has not yet been revealed can be left in there where it will do no harm until such a condition arises whereby the game writer decides to put the object back in play. "limbo", like "inventory" becomes a compulsory scene in the system, because it is referred to in the RestoreGame function by name.

After another sweep through the code to pick up any other anomalies or improvements, I'll publish version 1.1 in both source and runtime.

Saturday, 28 March 2009

Important bug

I've found a bug that sometimes, on a restore, leaves a sprite lying on every scene, a sprite that cannot be picked up. I can't reliably reproduce it. I thought at first that if you started a new game and restored a situation in which you were carrying a sprite, then it happened, but it doesn't seem to be that. Ho-hum... The position it occupies on the restored scene and all other scenes is the same as its original (i.e. game start) position. Later (much later, days later) I stumbled upon the bug again and can now reproduce it. It happens if I put the key in the inventory, then exit the inventory and save. Then I enter the inventory and pick up the key and restore. Now I can reproduce it, it should be simple to fix!

Friday, 27 March 2009

Development problem solved

I was finding that new versions of the code were not being acknowledged in Firefox, so that even if I made a change, it kept the old code.

Discovered that you have to bring up the Java console and type x to clear the classloader cache. At first, IE didn't seem to have the same problem, but that was probably because I restarted IE every time I tested it.

Anyway, to be on the safe side, I clear the classloader cache every time now.

And using mousePressed() instead of mouseClicked() works a treat. The mouse response is very much better now.

Development system

Over the last few days, I've set up a simple development system using command line calls to javac etc. I've installed EZ Document Safe to keep the sources and versions in order.

The good news is that the original code still compiles and runs.

I have found out why the mouse click doesn't work so well. If you drag the mouse a little when you press, you don't get a Clicked event; you may or may not get a Dragged event; you may get both; and it all depends on the JRE platform, the timing and how far it was dragged. There's a certain amount of discussion on SunWeb about the matter, and I used a test application to see what was going on.

I've devised a new system which ought to work on all platforms. I'll try it soon.

I have also downloaded JLayer, an mp3 player. It works in free-standing mode, but I don't know how it'll fare when I try to incorporate it into my code. I may just run it in a separate applet like the current midi ones.

Thursday, 26 March 2009

Some Story and Setting Outlines


Chinese Myst - Ideas


Major features :
o 3 mountains, each with a different character
o Bridges which need to be deployed
o Stairways and paths
o Pagodas, elevators, secret compartments and passages
o Monastery
o Nothing that's inappropriate technology, so use water power, clockwork, rope and pulley, steam etc.
o Locks, Puzzle locks, trapdoors
o Parts to fit in a matrix or jig-saw
o Logical puzzles

Despite appropriateness of technology, allow a little magic - tiny dragons, animated statues, self-igniting candles, ghost, fireworks, distant events in a crystal ball or animated picture or model. Also the fan is the equivalent of the Myst book (teleport mechanism).

Temple dogs, vases, chest of many drawers, lamps, screens, nested objects, musical instruments, cabinets, boxes, gong, water clock, teapot.

? Boat travel ? Aerial Runway

No language or writing, but perhaps some simple symbols.

Tiny model of the game world.

The Objective


(i) Must be revealed without verbal description so it could be demonstrated in a picture or a fan.

(ii) NOT the following hackneyed objectives:
a) Lord of Evil - destroy him... NO!
b) Imprisoned Princess - free her... NO! NO!
c) Save the Planet... NO! NO! NO!
d) Find the Ultimate Treasure... NOT AGAIN!

(iii) Well, perhaps a treasure hunt with trophy case. Collect seven treasures. The empty trophy case at the beginning, the filled one ends the game. A picture shows how the trophy case should look.

Saturday, 14 March 2009

Parallel Development

I've now described the original game, and delivered the sources for public consumption. Next, I shall embark on a new generation of the game.

Writing this game all by myself is going to be a bit of a challenge and a trifle lonely. Three threads have to be handled:
  • Engine code development
  • POVRay images development
  • Story development
Frankly, I could do with some help on any of the threads.

First, I'll set up a new code development and test environment. I don't even know if my 2003 code will still compile and work if I recompile it with an up-to-date Java. Most of my early development took place on J++, which, despite its shortcomings, was a pretty friendly development environment. Latterly, I was using the Sun bare bones development system. I flirted with Borland JBuilder for a while, but it was more trouble than benefit.

Tuesday, 10 March 2009

Returning to POVRay

scene=10
I no longer have the POVRay source I used for the example game, but the current (2008) version is not so very dissimilar, so I have stored that at http://amazonsystems.phpzilla.net too.

The whole of the game world is contained within the single source file China3.pov. Quite near the beginning of the file, you can choose a scene number. The approximate aspect covered by the scene number is described in a comment.

The islands are described by the height file Output.tga.

What you get is a terrain marked out in triangles. I have given it a jade texture, which seems to suit the angular effect. Some of the textures I have specified are rather simple and will be altered for final rendering, as they take too long for testing if complex.

The world is not very rich in variety as yet. I intend to add details such as trees and other plants, stones, and various "natural" features. Other scenery will include tunnels, stairways and buildings. I have included a bamboo object to use as building materials, with the bamboo.gif file for texture.

The game itself will require buttons, levers, doors, bridges, mechanisms and no end of cunning stuff, but often, though they may be designed in POVRay so that they match the surrounding illumination and background, they will be delivered in the game as sprites rather than as scenery, so that they can move.

Saturday, 7 March 2009

Public access to Bridge files.

I eventually settled on phpzilla.net, which provides 5 Gigs free storage (at the expense of a little banner advertising on web pages and a few splash pages which inconvenience me, but not the user). You can see the address in my links listing in the sidebar.

Wednesday, 4 March 2009

Public File Access

Although, by the time you read this, the problem will be solved, I felt it worthwhile to air the alternatives I am considering.

Since we may finish up with quite a lot of data, especially images and mp3s, I am reluctant to host them at my base website - amazonsystems.co.uk.

At first, I thought humyo.com the ideal situation for the public airing and sharing of files. I set up a Bridge account and uploaded some data files to it. However, it developed that files stored there were not freely available to web users who did not have their own humyo account. A possible solution is to set up a "guest" account at humyo, an account with read permission for the Bridge account, and publish the username and password on the blog, so anyone could have access. The downside of this is that the huge filestore (10 Gigs) on the guest account would be tempting to spammers, pornographers and other time-wasters. You can be sure they would not fail to exploit the space in some horrid fashion, and I would get the blame.

A "public" Gmail account could be used. Ideally, the data could be held as attachments to bogus emails (this usage of Gmail is quite common). Again, unfortunately, such an account would be open to abuse.

In either of the above instances, I could deliver the keys of the accounts only to those who requested them, but this would discourage casual surfers and people of a suspicious disposition, without protecting me from those who pretended an interest only to gain access to the online storage for their own ends.

The ideal medium for public data is webspace, and I am confident of finding some free webspace somewhere. I am already using a few such sites for various fringe projects, but all have rather small webspace quotas for free users. I may finish up paying for extra webspace on my own site. Sigh.

Tuesday, 3 March 2009

Panic over

The stricken site - Carfilhiot - has now been repaired. I had a MySQL backup of the site which was in Nucleus, and foolishly decided to convert it to WordPress manually, rather than use a conversion utility. This had the advantage of enabling me to check links and make small corrections, but it was time-consuming in the extreme, and I have only just finished. Work got in the way, too.

Tomorrow, I'll get started on a few more ideas I'm contemplating for the game system.

Thursday, 29 January 2009

A Little Pause

Some cretin hacked into one of my other sites, and installed a php bulk mailer, presumably in the laudable aim of extending the world's reproductive capabilities. Since I believe that the world is already over-populated, I made haste to trash the whole thing, and I'm rebuilding it. Back to game development soon.

Tuesday, 13 January 2009

The Graphic Environment of the Game


Using PovRay, a free ray-tracing package, I've built the island environment in which the game plays. You only see a fraction of it in the sample game, and even that is badly textured.

The basic terrain was mapped out using GFORGE - producing a height model which PovRay accepts and builds into a surface.

The scale is not vast. At the left of the plan above, you can see the L-shaped landing stage in brown, which is 2.8 metres wide.

A bonus of this construction method is that the interior of the surface is hollow, and so if a tunnel is driven into the rock, it reveals a cavern, the full height of the mountain. It is necessary to conceal the fact that the mountain is paper-thin by never showing the actual edge of the hole!

The development plans I have so far are :
  • a "trophy room" type of ending to the game, in which, once all the collected items are brought to the room, the game ends
  • a door with a maze lock
  • an elevator worked by water power which the player has to set working by moving valves
  • boats
  • bamboo stairways and structures
  • trees and vegetation
  • lots of odd items
  • a control centre on the left hand peak which lifts and lowers bridges and generally opens and closes pathways.
I intend to concentrate on a rich environment that is a pleasure to be in, as opposed to a simple puzzle.

The Display Manager

Finally, we come to the DisplayManager - the last item in the list of
Java classes.

The DisplayManager handles the graphics, using an off-screen buffer and
a clean version of the background. At each frame change, the previous
dirty rectangles are cleaned by writing the background into them, and
then the sprites are copied to the off-screen buffer, and the new dirty
rectangles redisplayed.

In a paint() call, only the dirty rectangles are displayed. In an
update(), the whole screen is written.

I think an unnecessary DirtyRectSet is defined in Bridge. Priority is
not being taken into account in sprite write sequence. There may still
be some confusion as to when an update and when a full redisplay takes
place.


/**
*
* DisplayManager.java
* @author Mark G. Tacchi (mtacchi@next.com)
* @version 0.8
* Mar 28/1996
* Heavily modified, with permission, by Gil Williamson 2003
*
* DisplayManager provides optimized screen display. Images are drawn to
* an offscreen buffer and blitted out to the display. If images are close
* to one another, they are coalesced and blitted as a single image.
*
* A read only cache is kept which represents an untainted background image.
* This is used in the optimization algorithm as a source for a clean
* background.
*
*/


import java.awt.Rectangle;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.util.Vector;
import java.awt.Cursor;

public class DisplayManager extends java.lang.Object
{
private Image background;
private Image offScreenBuffer;
private DirtyRectSet dirtyRects = new DirtyRectSet();

/**
* A reference back to the Bridge this manager is servicing.
*/
protected Bridge owner;

public DisplayManager(Bridge theOwner)
{
owner= theOwner;
}

/**
* Set the background image to the specified image.
*/
public void setBackground (Image theImage)
{
background= theImage;
int width = background.getWidth(owner);
int height = background.getHeight(owner);
offScreenBuffer= owner.createImage(width, height);
offScreenBuffer.getGraphics().drawImage (theImage, 0, 0, owner);

dirtyRects.addRect (new Rectangle (0, 0, width,height));

}/*setBackground*/

public void refresh(Graphics g)
{
//gil temp
Rectangle r = new Rectangle(0,0,640,480);
dirtyRects.addRect(r);
paint(g);

}

/**
* Display changed portions of screen.
*/
public void paint(Graphics g)
{
DirtyRectSet flushRects;
Graphics osb;

if( offScreenBuffer == null )
osb = null;
else
osb = offScreenBuffer.getGraphics ();

//
// clear background behind actors...
//
dirtyRects.drawImage (osb, background, owner);

flushRects= dirtyRects;
dirtyRects= new DirtyRectSet();

//
// draw Sprites
//
Vector slist = owner.bridgedata.getCurrentSprites();
for (int ii = 0; ii< slist.size(); ii++)
{
Sprite sprite = (Sprite)slist.elementAt(ii);
// Zilch sprites do not get drawn
if (sprite.getClass() == Zilch.class) continue;
Rectangle r = new Rectangle(sprite.getExtent());
dirtyRects.addRect (r);
flushRects.addRect (r);
Graphics g2= osb.create (r.x, r.y, r.width, r.height);
Image imageii = sprite.getCurrentImage();
g2.drawImage(imageii, 0, 0, owner);
g2.dispose();
}
flushRects.drawImage (g, offScreenBuffer, owner);

} /*paint*/

} /*DisplayManager*/

Monday, 12 January 2009

DirtyRectSet - Dirty Rectangle Set class

DirtyRectSet is the class that collects all the bits of the image that
have been changed and therefore need replacement. It saves processing
time on image update.

Rectangles are added in ascending sequence of x coordinate, and there is
a collapse() method that enables rectangles which are rather close to
each other to be amalgamated. "Close enough" is defined by GLUE - i.e
within GLUE pixels, the rectangles overlap.

The drawImage method is immensely subtle - so subtle that it always
takes me some time to figure out exactly what it's doing. Importantly,
though, it seems to work.

 
/** * * DirtyRectSet.java * Mark Tacchi Mar 15/1996
* * * Slightly modified by Gil Williamson 2003 */

import java.util.Vector;
import java.awt.Rectangle;


public class DirtyRectSet extends java.lang.Object
{
private Vector rects;
public DirtyRectSet()
{
rects = new Vector();
}
public void addRect (Rectangle r)
{
int size = rects.size ();
for (int index = 0; index < size; index++)
{
Rectangle curr = (Rectangle)rects.elementAt (index);

if (r.x > curr.x)
{
rects.insertElementAt (r, index);
return;
}
}
rects.addElement (r);
}

final int GLUE = 64;

final private boolean closeEnough (Rectangle r1, Rectangle r2)
{
boolean result;
r1.width += GLUE;
r1.height += GLUE;
r2.width += GLUE;
r2.height += GLUE;
result = r1.intersects (r2);
r1.width -= GLUE;
r1.height -= GLUE;
r2.width -= GLUE;
r2.height -= GLUE;
return result;
}

public int getSize()
{
return(rects.size());
}

public Rectangle getRect(int index)
{
return ((Rectangle)rects.elementAt(index));
}

public void empty()
{
if (rects.size()>0)
{
rects.removeAllElements();
}
}

public void collapse ()
{
int index = 0;
if (rects.size () < 2)
return;
Rectangle r1 = (Rectangle)rects.elementAt (index);
Rectangle r2 = (Rectangle)rects.elementAt (index+1);
while (true)
{
// collapse R1 and R2
if (closeEnough (r1, r2))
{
r1 = r1.union (r2);
rects.setElementAt (r1, index);
rects.removeElementAt (index+1);
if (index+1 < rects.size ())
r2 = (Rectangle)rects.elementAt(index+1);
else
return;
}
// go to next pair
else if (index+2 < rects.size ())
{
r1 = r2;
r2 = (Rectangle)rects.elementAt (index+2);
index += 1;
}

// done
else
{
return;
}
}
}

public void drawImage (java.awt.Graphics g, java.awt.Image img,
Bridge owner)
{
collapse ();

for (int i= 0; i< rects.size (); i++) {
Rectangle r = (Rectangle)rects.elementAt(i);
java.awt.Graphics g2 = g.create (r.x, r.y, r.width,
r.height);
g2.drawImage(img, -r.x, -r.y, owner);
g2.dispose ();

}
}

}

Saturday, 10 January 2009

The BridgeData class

The BridgeData class varies from game to game. The first part defines all the scenes, zones and sprites. The second part has a number of service routines that deliver the information to calling methods.

There are a couple of method names that I would change for the sake of clarity, specifically:
setCurrentScene() and getCurrentScene(), which really should be called: setCurrentSceneName() and getCurrentSceneName().


// This is the class that defines all the scenes, zones and sprites
import java.util.Vector;
import java.awt.*;
import java.applet.AudioClip;
import java.net.URL;

public class BridgeData extends Object
{
private Vector scenes;
private Vector sprites;
private Scene scene;
private String currscene;
public String startup = "waitintro";
protected Bridge owner;
public BridgeData(Bridge theOwner)
{
owner = theOwner;
scenes = new Vector();
sprites = new Vector();
// Put scenes in here
//inventory
scene = new Scene ("inventory", "inventory.gif");
scene.addZone(20, 20, 80, 80, "", Cursor.CROSSHAIR_CURSOR);
scenes.addElement(scene);
//waitintro
scene = new Scene ("waitintro", "instr.gif");
scene.addZone(238, 176, 164, 124, "intro", Cursor.CROSSHAIR_CURSOR);
scenes.addElement(scene);
//wait
scene = new Scene ("wait", "hourglass.jpg");
scenes.addElement(scene);
//intro
scene = new Scene ("intro", "china.jpg", "c12");
scene.addZone(100, 310, 70, 60, "dock", Cursor.CROSSHAIR_CURSOR);
scenes.addElement(scene);
//dock
scene = new Scene ("dock", "dock.jpg", "ara");
scene.addZone(200, 210, 100, 70, "doornbox", Cursor.CROSSHAIR_CURSOR);
scene.addZone(0, 0, 640, 60, "dockup", Cursor.S_RESIZE_CURSOR);
scene.addZone(0, 0, 60, 480, "dockback", Cursor.E_RESIZE_CURSOR);
scene.addZone(580, 0, 60, 480, "dockback", Cursor.E_RESIZE_CURSOR);
scenes.addElement(scene);
//dockback
scene = new Scene ("dockback", "dockback.jpg", "ara");
scene.addZone(0, 0, 60, 480, "dock", Cursor.E_RESIZE_CURSOR);
scene.addZone(580, 0, 60, 480, "dock", Cursor.E_RESIZE_CURSOR);
scene.addZone(200, 210, 100, 70, "intro", Cursor.CROSSHAIR_CURSOR);
scenes.addElement(scene);
//dockup
scene = new Scene ("dockup", "dockup.jpg", "ara");
scene.addZone(0, 430, 640, 50, "dock", Cursor.S_RESIZE_CURSOR);
scenes.addElement(scene);
//doornbox
scene = new Scene ("doornbox", "doornbox.jpg");
scene.addZone(0, 430, 640, 50, "dock", Cursor.S_RESIZE_CURSOR);
scenes.addElement(scene);
//Put sprites in here
RippleA ripplea = new RippleA("ripplea", "intro");
sprites.addElement(ripplea);
GullA gulla = new GullA("gulla", "intro", 480, 40, 0);
sprites.addElement(gulla);
GullA gullb = new GullA("gullb", "intro", 370, 200, 78);
sprites.addElement(gullb);
GullA gullc = new GullA("gullc", "dockback", 80, 50, 12);
sprites.addElement(gullc);
GullA gulld = new GullA("gulld", "dockback", 150, 200, 78);
sprites.addElement(gulld);
// Put carryables here
GoldKey goldkey = new GoldKey("goldkey", "dock");
sprites.addElement(goldkey);
Zilch dockkeyhole = new Zilch("dockkeyhole", "doornbox");
dockkeyhole.setPosition(200, 240);
URL addr = owner.getCurrentUrl("sounds/rooster.au");
dockkeyhole.addAudio(0, owner.getAudioClip(addr));
sprites.addElement(dockkeyhole);
}
public boolean collide(String spritename, String hitter)
{
if (hitter == null)
{
return true;
}
else
{
if (spritename.equals("dockkeyhole") && (hitter.equals("goldkey")))
{
Sprite found = getSpriteByName(spritename);
if (found != null)
{
AudioClip auclip = found.getAudio(0);
auclip.play();
return true;
}
}
}
return false;
}

// Above here are game-specific functions
// Below here are general purpose functions
public Scene fetchScene(String a)
{
int ii;
if (scenes == null)
{
return null;
}
for(ii = 0; ii < scenes.size(); ii++)
{
scene = (Scene)scenes.elementAt(ii);
if (a.equals(scene.name))
{
return scene;
}
}
return null;
}
public Scene fetchCurrentScene()
{
return (fetchScene(currscene));
}
public void setCurrentScene(String name)
{
currscene = new String(name);
}
public String getCurrentScene()
{
return(currscene);
}
public Vector getSceneSprites(String sceneName)
{
Vector local = new Vector();
Sprite temp = null;
for (int ii = 0; ii < sprites.size(); ii++)
{
temp = (Sprite)sprites.elementAt(ii);
if (temp.scenename.equals(sceneName))
{
local.addElement(temp);
}
}
return local;
}
public Vector getCurrentSprites()
{
return getSceneSprites(currscene);
}
public Vector getAllSprites()
{
return sprites;
}
public Sprite getSpriteByName(String name)
{
Sprite temp;
for (int ii = 0; ii < sprites.size(); ii++)
{
temp = (Sprite)sprites.elementAt(ii);
if (temp.getName().equals(name))
{
return(temp);
}
}
return null;
}
}

Thursday, 8 January 2009

The Scene and Zone classes

The Scene and Zone classes. The comments say it all. The Scene is the equivalent of the "Room" in adventure-speak.
I can see a future need for a method that changes the destination of a zone. It would be of the form - change the destination of the nth zone in the scene which points to scene A to scene B (the normal value of n would be zero - i.e. the only zone).

// Scene class - this is the background to a scene and includes:
// the Zone class - a Zone is a rectangular area within a scene,
// usually for the purpose of enabling the player to click at
// a portion of the scene in order to move to another scene.

import java.util.Vector;
import java.awt.*;
public class Scene extends Object
{
public String name; // Text name of scene
public String imagename; // image file name for scene
public String songname; // text song name
private Vector zones; // list of zones within the scene

// Zone Class
public class Zone extends Object
{
public Rectangle rect; // extent of zone
public String destination; // text name of destination scene
public int cursor; // cursor to display while in zone
public boolean cursoron; // whether cursor displays
public Zone(Rectangle r, String d)
{
rect = new Rectangle(r);
destination = new String(d);
cursoron = false;
}
public Zone(int x, int y, int w, int h, String d, int Cursor)
{
rect = new Rectangle(x, y, w, h);
destination = new String(d);
cursor = Cursor;
cursoron = true;
}
public boolean inZone(int x, int y)
{
if (rect.contains(x, y))
return true;
return false;
}
}
public Scene(String n, String in)
{
name = new String(n);
imagename = new String(in);
zones = new Vector();
songname = new String("");
}
public Scene(String n, String in, String song)
{
name = new String(n);
imagename = new String(in);
zones = new Vector();
songname = new String(song);
}
public void addZone(int x, int y, int w, int h, String d, int e)
{
Zone z = new Zone(x, y, w, h, d, e);
zones.addElement(z);
}
public String getDest(int x, int y)
{
int ii;
Zone tz;
if (zones == null)
return null;
for (ii = 0; ii < zones.size(); ii++)
{
tz = (Zone)zones.elementAt(ii);
if (tz.inZone(x, y))
return tz.destination;
}
return null;
}
public int getZoneCursor(int x, int y)
{
int ii;
Zone tz;
if (zones == null)
return -1;
for (ii = 0; ii < zones.size(); ii++)
{
tz = (Zone)zones.elementAt(ii);
if (tz.inZone(x, y) && tz.cursoron)
return tz.cursor;
}
return -1;
}
}