Section3: Including Cell Based Images

Here, begin importing the raw images. If the image has multiple cells make use of the cellImage1 utility.

ImageBvr clouds,scene;
cellImage1 kite,ocean1,ocean2,palm1,palm2,palm3,beachboy;
URL mediaBase = getImportBase();
URL imgBase = buildURL(mediaBase, "image/");
URL geoBase = buildURL(mediaBase, "geometry/");
URL sndBase = buildURL(mediaBase, "sound/");
kite = new cellImage1(buildURL(imgBase, "kite.gif"),4);
scene = importImage(buildURL(imgBase, "scene.jpg"));
ocean1 = new cellImage1(buildURL(imgBase, "ocean.gif"),4);
ocean2 = new cellImage1(buildURL(imgBase, "ocean2.gif"),4);
palm1 = new cellImage1(buildURL(imgBase, "palm1.gif"),5);
palm2 = new cellImage1(buildURL(imgBase, "palm2.gif"),5);
palm3 = new cellImage1(buildURL(imgBase, "palm3.gif"),5);
clouds = importImage(buildURL(imgBase, "clouds.gif"));
beachboy = new cellImage1(buildURL(imgBase, "beachboy.gif"),2);

Here, use the synthetic ocean sounds that are explained in Section 5. The event caused by a crashing wave is used to create an ocean index. An animateTrees method is called to generate psuedo-random tree indexes. These indexes will be used with the showIndex method to determine which tree cell to display.

oceanSynth ocean = new oceanSynth(add(toBvr(.2),windSpeed));
NumberBvr oceanIndex = animateOcean(ocean.soundEvent());
NumberBvr treeIndex1 = animateTrees(windSpeed, 1);
NumberBvr treeIndex2 = animateTrees(windSpeed, .88);
NumberBvr treeIndex3 = animateTrees(windSpeed, .71);

So how does cellImage1 work? The contructor takes an image and frame count and imports that image.

public class cellImage1 extends Statics {
public cellImage1(java.net.URL url, int frameCount) {
super();
_BaseImg = importImage(url);
_FrameCount = toBvr(frameCount);
}

To get a particular frame of the cellImage, the author can make a call to the showIndex method. This will return a properly cropped image. The following code calculates the minimum and maximum points of the indexed image, crops the entire image, then centers the new image.

public ImageBvr showIndex(NumberBvr index) {
NumberBvr actualIndex = sub(sub(_FrameCount, toBvr(1)), index);
Bbox2Bvr frame = _BaseImg.boundingBox();
NumberBvr cellHeight =
div(sub(frame.getMax().getY(),frame.getMin().getY()),
_FrameCount);
NumberBvr cellMin = add(frame.getMin().getY(), mul(cellHeight, actualIndex));
NumberBvr cellMax = add(cellMin, cellHeight);
ImageBvr cellImg =
_BaseImg.crop(
point2(frame.getMin().getX(), cellMin),
point2(frame.getMax().getX(), cellMax));
ImageBvr cntrImg =
cellImg.transform(
translate(toBvr(0), sub(neg(cellMin),div(cellHeight,toBvr(2)))));
return cntrImg;
}

The loopStrip is a handy method that cycles through all the cells at the indicated speed (in frames per second).

public ImageBvr loopStrip(NumberBvr speed) {
return showIndex(
mod(floor(mul(localTime,speed)),_FrameCount));
}
public ImageBvr _BaseImg;
public NumberBvr _FrameCount;
}

Here is how these two methods operate.

private NumberBvr animateOcean(DXMEvent ev) {

Sequence for clam ocean.

Behavior[] calm = { toBvr(0), toBvr(1) };

Sequence for crashing wave.

Behavior[] wave = { toBvr(2), toBvr(3), toBvr(2) };

Cycles through the calm values every 0.5 seconds.

Cycler calmCycle = new Cycler(calm, timer(toBvr(.5)));

Cycles through the calm values every 0.25 seconds.

Cycler crashCycle = new Cycler(wave, timer(toBvr(.25)));

Use an uninitialized behavior so it can refer to itself.

NumberBvr animateOcean = NumberBvr.newUninitBvr();

The behavior is calmCycle until ev, then crashCycle for 0.75 seconds, and then back to the initial state.

animateOcean.init((NumberBvr)
until(calmCycle.getBvr(), ev,
until(crashCycle.getBvr(), timer(toBvr(.75)), animateOcean)));
return animateOcean;
}
private NumberBvr animateTrees(NumberBvr windSpeed, double seed) {

A jitter method gives a semi-random value that oscillates between zero and one.

NumberBvr jitter =
floor(mod(
add(DxmNumber.smooth0to1(mul(sub(toBvr(1.2),windSpeed), toBvr(10*seed))),
(NumberBvr)_breezeInterval.getBvr()),
toBvr(2)));

As the wind speed increases, the trees tend to bend back. To get this effect increase the cell image used.

NumberBvr normalIndex = floor(mul(toBvr(3), windSpeed));

The final index jiggles the bent tree.

return add(normalIndex, jitter);
}

Here, construct moving clouds by translating an infinitely tiled image of clouds by the windDistance.

Bbox2Bvr BB = clouds.boundingBox();
Vector2Bvr cloudPos =
vector2(neg(mod(div(windDistance, toBvr(200)),
sub(BB.getMax().getX(), BB.getMin().getX()) )), toBvr(0));
ImageBvr xfClouds = clouds.transform(translate(cloudPos));
ImageBvr movingClouds = xfClouds.tile().crop(BB.getMin(), BB.getMax());

Here, create an array of all the time-varying sprite images, using loopStrip and showIndex where appropiate.

ImageBvr[] sprites = {
kite.loopStrip(add(windSpeed,toBvr(.2))),
scene,
ocean1.showIndex(oceanIndex),
ocean2.showIndex(oceanIndex),
palm1.showIndex(treeIndex1),
palm2.showIndex(treeIndex2),
palm3.showIndex(treeIndex3),
movingClouds,
beachboy.loopStrip(toBvr(1))
};

Also create an array of points which will be used as the initial positions of the above mentioned time-varying sprites.

Point2Bvr[] spritePos = {
kitePos,
point2(toBvr( 0),toBvr( 0)),
point2(mul(toBvr( 78),pixelBvr),mul(toBvr(-100),pixelBvr)),
point2(mul(toBvr(-252),pixelBvr),mul(toBvr( -21),pixelBvr)),
point2(mul(toBvr(-250),pixelBvr),mul(toBvr( 20),pixelBvr)),
point2(mul(toBvr(-158),pixelBvr),mul(toBvr( 2),pixelBvr)),
point2(mul(toBvr( -98),pixelBvr),mul(toBvr( -1),pixelBvr)),
point2(toBvr( 0),mul(toBvr( 106),pixelBvr)),
bboyPos
};

Then apply the sprite translation to all the sprites, to move them to their initial location.

ImageBvr[] iSprites = new ImageBvr[9];
for(int i=0; i<9; i++)
iSprites[i] = sprites[i]
.transform(translate(sub(spritePos[i],origin2)));

Overlay all the 2-D sprites (the first overlay is at the top and the last will be at the bottom). This new composite is made pickable for later use.

PickableImage allSprites = new PickableImage(
overlay(iSprites[0], overlay(iSprites[8], overlay(kiteString,
overlay(iSprites[4], overlay(iSprites[5], overlay(iSprites[6],
overlay(iSprites[7], overlay(iSprites[2],
overlay(iSprites[3], iSprites[1] ))))))))));

Finally, obtain the upper right corner of the composite, which will be used to scale the geometries.

Point2Bvr imageUR = allSprites.getImageBvr().boundingBox().getMax();
© 1997 Microsoft Corporation. All rights reserved. Terms of Use.