Section2: Using scripting to change wind speed
We begin by adding a scroll bar and some simple VBScript to our HTML. The script will call the applet setWindSpeed and pass the value.

| <OBJECT ID="ScrollBar1" WIDTH=203 HEIGHT=16 CLASSID="CLSID:DFD181E0-5E2F-11CE-A449-00AA004A803D"> <PARAM NAME="Size" VALUE="5362;423"> <PARAM NAME="Max" VALUE="10"> <PARAM NAME="LargeChange" VALUE="2">
<PARAM NAME="Orientation" VALUE="1">
</OBJECT>
<script language="VBScript">
<!--
sub ScrollBar1_change()
document.lhouse.setWindSpeed scrollbar1.value
end sub
-->
</script>

Here, back in the lhouseModel class, declare a number of variables that will be used throughout the sample. These variables are declared as switchers so that the behavior (Bvr) they contain (a number) can be updated from an external method or a notifier.

public ModifiableBehavior _windSpeed;
Normalized value between 0 and 1
public ModifiableBehavior _windMode;
public ModifiableBehavior _breezeInterval;
public DXMEvent _grabEvent;
public Vector3Bvr _originalPath;
public Vector3Bvr _actualPath;

This is the method that the applet will call to update the wind speed. Notice the switchTo call that swaps the current Bvr for a new one. Note: to convert a primitive Java data types (such as integers) to behaviors use the toBvr() helper method.

public void setWindSpeed(int val) {
_windSpeed.switchTo( div(toBvr(val),toBvr(10)) );
_windMode.switchTo(mul(add(toBvr(val),toBvr(1)),toBvr(0.9)));
}

The createModel method, tells DirectAnimation how to construct a run time model for the animation.

public void createModel(BvrsToRun blist) {

Begin the demo code by initializing switchers and giving them their default number behaviors. For convenience get the actual Bvr out of the switcher and store it as the variable windSpeed. Also, create a windDistance value based on the windSpeed (this will be used to move the clouds later on). The most interesting variable here is the WindAngle which is a value that changes randomly over time. The example on this page allows you to see the changing values of these numbers as you move the slider.

_windSpeed = new ModifiableBehavior(toBvr(0));
_windMode = new ModifiableBehavior(toBvr(0));
_breezeInterval = new ModifiableBehavior(toBvr(2));
NumberBvr windSpeed = (NumberBvr)_windSpeed.getBvr();
NumberBvr windMode = (NumberBvr)_windMode.getBvr();
NumberBvr windDistance = integral(windSpeed);
NumberBvr windAngle = generateWindAngle(blist);
NumberBvr random = seededRandom(.11);
blist.add(random);

Above, you saw the use of the generateWindAngle to actually get the random value, here is what the method does:

private NumberBvr generateWindAngle(BvrsToRun blist) {
ModifiableBehavior breezeAngle = new ModifiableBehavior(toBvr(0));

Explicitly start a seededRandom behavior.

NumberBvr random = seededRandom(.27);
blist.add(random);

Create an event which triggers after each breeze interval passes.

DXMEvent timerEv = timer((NumberBvr)_breezeInterval.getBvr());

Attach the random value as eventData.

timerEv = timerEv.snapshotEvent(random);

You want a number behavior that refers to itself, so use newUninitBvr().

NumberBvr loop = NumberBvr.newUninitBvr();

To get a randomly changing breeze, create a method that will get called every time the timerEv event occurs, then smoothly transitions our current breezeAngle to a new random breezeAngle. This is the purpose of the newBreeze class, which extends UntilNotifier. Pass it the values it will need to construct and return a new behavior.

UntilNotifier newBreeze = new Breeze((NumberBvr)_windSpeed.getBvr(),
_breezeInterval, breezeAngle, loop);
NumberBvr angle = (NumberBvr)breezeAngle.getBvr();
timerEv = andEvent(timerEv, timerEv.snapshotEvent(angle));

Now, initialize the loop to the value that is the current breezeAngle, until timerEv, when the newBreeze notify method is called.

loop.init((NumberBvr)untilNotify(angle, timerEv, newBreeze));

return this value as the actual breeze angle.

return loop;
}

The callback serves an important function in DirectAnimation. It allows the reconstruction of a running behavior based on its current value and the time that it was triggered. In the breeze class, the sample uses the constructor to pass it all the values it needs to update the current behavior.

class Breeze extends Statics implements UntilNotifier {
private ModifiableBehavior _breezeInterval;
private ModifiableBehavior _breezeAngle;
private NumberBvr _windSpeed;
private NumberBvr _loop;
public Breeze(NumberBvr windSpeed, ModifiableBehavior breezeInterval,
ModifiableBehavior breezeAngle, NumberBvr loop) {
_windSpeed = windSpeed;
_breezeInterval = breezeInterval;
_breezeAngle = breezeAngle;
_loop = loop;
}

Now in the notify method, you can do some actual work.

public Behavior notify(Object eventData, Behavior curBvr, BvrsToRun lst) {

First snapshot (freeze) the random value attached as eventData.

NumberBvr random = (NumberBvr)((PairObject)eventData).getFirst();

Also snapshot the current breezeAngle based on the event time.

NumberBvr oldAngle = (NumberBvr)((PairObject)eventData).getSecond();

Calculate the difference delta between the two and transition the breezeAngle from one to the other over a period of two seconds.

NumberBvr deltaAngle = mul(toBvr(2), sub(random,toBvr(.5)));
_breezeInterval.switchTo(mul(toBvr(5), random));
_breezeAngle.switchTo(add(oldAngle,deltaAngle));
NumberBvr changingAngle =
add(oldAngle, mul(deltaAngle, DxmNumber.smooth0to1(toBvr(2))));
return (NumberBvr)until(changingAngle, timer(toBvr(2)), _loop);
}
}

© 1997 Microsoft Corporation. All rights reserved. Terms of Use.