Fog is, of course, another nifty weather feature. We've already
This layered fog is a limited form of volumetric fog. It is limited in the sense that although you can specify the upper and lower bounds of the fog, it will appear at those levels throughout the entire map.
You can use this layered fog to complement the moving cloud textures to create clouds (except that the fog will never be at the same altitude as the cloud textures). You can also deposit fog in low-lying
A good use for this fog is underwater, helping to reduce visibility there. This reduced visibility results because of silt and other materials that often exist underwater, cutting down your ability to see far.
This layered volume fog is specified in the Sky mission object that we
fogVolume1 = "500 0 100";
The three parameter
|
Parameter |
Description |
|---|---|
|
distance |
View distance when in the layer. This works like the distance fog, except that a value of 0 here means there is no fog at all. If you want a really, really close view distance, use 1, not 0. |
|
bottom |
Bottom of fog layer. |
|
top |
Top of fog layer. |
You already know how to edit the mission file and change the properties of the various mission objects, so go ahead and putz around with the fog values and see how they work.
Torque has built-in capabilities to generate storms, using lightning, rain, and thunder. It's pretty cool how this is done. You can manually instigate a
| Note |
The lightning storm features require the use of sound effects files, but we don't cover those until the
|
There's some preparation we need to do at this point before proceeding with the rest of the weather features. We need to get some sound files, images, and supporting code files and put them in the right places for our game, as
In the directory C:\3DGPAi1\RESOURCES\CH18 locate the file
SettingsScreen.cs
and copy it to the directory C:\aEmaga6\control\client\misc\. Then copy
SettingsScreen.gui
from the same place to C:\aEmaga6\control\client\interfaces\.
Copy the following files to the directory C:\aEmaga6\control\data\sound\:
C:\aEmaga6\control\data\sound\thunder1.wav C:\aEmaga6\control\data\sound\thunder2.wav C:\aEmaga6\control\data\sound\thunder3.wav C:\aEmaga6\control\data\sound\thunder4.wav C:\aEmaga6\control\data\sound\buttonOver.wav C:\aEmaga6\control\data\sound\rain.wav
Copy the following files from the same place:
C:\aEmaga6\control\data\sound\lightning.dml C:\aEmaga6\control\data\sound\lightning1frame1.png C:\aEmaga6\control\data\sound\lightning1frame2.png C:\aEmaga6\control\data\sound\lightning1frame3.png C:\aEmaga6\control\data\sound\rain.dml C:\aEmaga6\control\data\sound\rain.png
However, this time they go to the directory C:\aEmaga6\control\data\maps\.
Edit the file C:\aEmaga6\control\client\initialize.cs and locate the following line:
Exec("./interfaces/MasterScreen.gui");
and after it, add this line:
Exec("./interfaces/SetupScreen.gui");
Next, locate the line:
Exec("./misc/MasterScreen.cs");
and after it, add this line:
Exec("./misc/SetupScreen.cs");
Edit the file C:\aEmaga6\control\client\default_profile.cs and add the following line near the top:
GuiButtonProfile.soundButtonOver = "AudioButtonOver";
Copy the file C:\3DGPAi1\RESOURCES\CH18\OpenAL32.dll to the directory C:\aEmaga6\.
Locate the file C:\aEmaga6\control\client\initialize.cs and add these lines to the top:
$pref::Audio::driver = "OpenAL"; $pref::Audio::forceMaxDistanceUpdate = 0; $pref::Audio::environmentEnabled = 0; $pref::Audio::masterVolume = 1.0; $pref::Audio::channelVolume1 = 1.0; $pref::Audio::channelVolume2 = 1.0; $pref::Audio::channelVolume3 = 1.0; $pref::Audio::channelVolume4 = 1.0; $pref::Audio::channelVolume5 = 1.0; $pref::Audio::channelVolume6 = 1.0; $pref::Audio::channelVolume7 = 1.0; $pref::Audio::channelVolume8 = 1.0; $GuiAudioType = 1; $SimAudioType = 2; $MessageAudioType = 3; new AudioDescription(AudioGui) { volume = 1.0; isLooping= false; is3D = false; type = $GuiAudioType; }; new AudioDescription(AudioMessage) { volume = 1.0; isLooping= false; is3D = false; type = $MessageAudioType; }; new AudioProfile(AudioButtonOver) { filename = "~/data/sound/buttonOver.wav"; description = "AudioGui"; preload = true; };
Now that we've done that, we can move on to the storm-specific stuff.
Type the following into a new file and save it as C:\aEmaga6\control\server\misc\ weather.cs.
datablock AudioProfile(HeavyRainSound) { filename = "~/data/sound/rain.wav"; description = AudioLooping2d; }; datablock AudioProfile(ThunderCrash1Sound) { filename = "~/data/sound/thunder1.wav"; description = Audio2d; }; datablock AudioProfile(ThunderCrash2Sound) { filename = "~/data/sound/thunder2.wav"; description = Audio2d; }; datablock AudioProfile(ThunderCrash3Sound) { filename = "~/data/sound/thunder3.wav"; description = Audio2d; }; datablock AudioProfile(ThunderCrash4Sound) { filename = "~/data/sound/thunder4.wav"; description = Audio2d; }; datablock LightningData(LightningStorm) { strikeTextures[0] = "~/data/maps/lightning.dml"; thunderSounds[0] = ThunderCrash1Sound; thunderSounds[1] = ThunderCrash2Sound; thunderSounds[2] = ThunderCrash3Sound; thunderSounds[3] = ThunderCrash4Sound; }; datablock PrecipitationData(HeavyRain) { type = 1; materialList = "~/data/maps/rain.dml"; soundProfile = "HeavyRainSound"; sizeX = 0.1; sizeY = 0.1; movingBoxPer = 0.35; divHeightVal = 1.5; sizeBigBox = 1; topBoxSpeed = 20; frontBoxSpeed = 30; topBoxDrawPer = 0.5; bottomDrawHeight = 40; skipIfPer = -0.3; bottomSpeedPer = 1.0; frontSpeedPer = 1.5; frontRadiusPer = 0.5; };
Finally, add some datablocks to the mission file to cause our new storm features to load when the game launches. Locate the mission file again, C:\aEmaga6\control\data\maps\book_ch6.mis, and find the last two lines of code, which should look like this:
}; //--- OBJECT WRITE END ---
And add the following two datablocks before those last two lines:
new Precipitation(RainStorm) { position = "-45.0071 -29.016 244.517"; rotation = "1 0 0 0"; scale = "1 1 1"; nameTag = "rs"; dataBlock = "HeavyRain"; offsetSpeed = "0.25"; minVelocity = "1.5"; maxVelocity = "3"; color1 = "1.000000 1.000000 1.000000 1.000000"; color2 = "-1.000000 0.000000 0.000000 1.000000"; color3 = "-1.000000 0.000000 0.000000 1.000000"; percentage = "1"; maxNumDrops = "5000"; MaxRadius = "60"; }; new Lightning(ElectricalStorm) { position = "200 100 300"; rotation = "1 0 0 0"; scale = "250 400 500"; datablock = "LightningStorm"; strikesPerMinute = "30"; strikeWidth = "2.5"; chanceToHitTarget = "100"; strikeRadius = "250"; boltStartRadius = "20";
color
= "1.000000 1.000000 1.000000 1.000000"; fadeColor = "0.100000 0.100000 1.000000 1.000000"; useFog = "1"; locked = "true"; };
That should do it. Launch your game, and enjoy the storm!
You will have noticed that when you
rain.dml
file, you will see this one line:
rain.png
Figure 18.14 shows what this texture looks like. It has 16 images of raindrops in a 4 by 4 grid arrangement.
Figure 18.14:
Raindrop images.
Now, the actual texture file has a difference—the areas shown in black in Figure 18.14 are really transparent when
rain.png
file. Then edit the
rain.dml
file to point to your new version instead of the original.
The same process applies to the lightning images, except that the lightning images are not grids. Instead, the
lightning.dml
material file looks like this:
lightning1frame1 lightning1frame2 lightning1frame3
The
lightning.dml
material file is a list of lightning image files that are displayed in sequence as the lightning stroke occurs. Figure 18.15 shows each of these images in order, from left to right.
Figure 18.15:
Lightning stroke images.
When making the lightning frame files, you need to make them 128 pixels wide by 256 pixels high. Draw your lightning bolts on a black background—all the areas you leave black will be treated as transparent. That is, they really are black and are not just rendered that way for purposes of the picture, as was the case back with Figure 18.14.
Now, let's take a look at what makes lightning tick, as it were. There are two significant declarations: one is the LightningData datablock in the server code, and the other is the Lightning object definition that resides in the mission file. The datablock is transmitted to the client when the mission is loaded with the Lightning object definition getting transmitted to the client. The datablock describes what resources are used to create the lightning visuals and sound effects, as follows:
datablock LightningData(LightningStorm) { strikeTextures[0] = "~/data/maps/lightning.dml"; thunderSounds[0] = ThunderCrash1Sound; thunderSounds[1] = ThunderCrash2Sound; thunderSounds[2] = ThunderCrash3Sound; thunderSounds[3] = ThunderCrash4Sound; };
Every time Torque triggers the thunder, one of the listed
thunderSound
n
properties is
The Lightning object defines how the lightning actually works in the game, as follows:
new Lightning(ElectricalStorm) { position = "200 100 300"; rotation = "1 0 0 0"; scale = "250 400 500"; datablock = "LightningStorm"; strikesPerMinute = "30"; strikeWidth = "2.5"; chanceToHitTarget = "100"; strikeRadius = "250"; boltStartRadius = "20"; color = "1.000000 1.000000 1.000000 1.000000"; fadeColor = "0.100000 0.100000 1.000000 1.000000"; useFog = "1"; };
Obviously, it's important to
When a bolt is generated, a random spot within a circular area is chosen to be the place where the bolt begins, and then another random spot within a different circular area is chosen to be the spot where the bolt hits. The
The centers of the start and strike areas are defined by the position property. The whole shebang can be made larger or smaller based on the scale property. The rotation property has no effect.
The color property defines a coloring that is applied when the bolt first appears, and the color values are changed over the life of the bolt until they reach the settings in fadeColor .
The useFog property indicates whether the fog defined by the stormFog n property in the Sky mission object will be used.
In Figure 18.16 you can see a lighting bolt coming out of the sky in the game setting.
Figure 18.16:
A lightning bolt.
You can make it rain in much the same way as you make thunder and lightning, though there are differences in the details.
For one thing, the Precipitation datablock is much bigger.
datablock PrecipitationData(HeavyRain) { type = 1; materialList = "~/data/maps/rain.dml"; soundProfile = "HeavyRainSound"; sizeX = 0.1; sizeY = 0.1; movingBoxPer = 0.35; divHeightVal = 1.5; sizeBigBox = 1; topBoxSpeed = 20; frontBoxSpeed = 30; topBoxDrawPer = 0.5; bottomDrawHeight = 40; skipIfPer = -0.3; bottomSpeedPer = 1.0; frontSpeedPer = 1.5; frontRadiusPer = 0.5; };
Significant properties here are
sizeX
and
sizeY
, which
The rest of the properties are not well documented and are hard to decipher. Of course, you are free to fiddle with them to your heart's content. The settings included in the
If you do experiment with the datablock, realize that the rain is generated at the client. Other players don't see the exact same raindrops at the same instant that you do—it would be lunacy to try to make the server track each drop! Therefore, the rain is generated in a box that envelops the player and moves around as the player moves. The drops are initiated at the top of the box and tracked and rendered as they move down, pulled by gravity. That little bit of detail might help you with your experimentation.
The Precipitation object declaration looks like this:
new Precipitation(RainStorm) { position = "-45.0071 -29.016 244.517"; rotation = "1 0 0 0"; scale = "1 1 1"; dataBlock = "HeavyRain"; offsetSpeed = "0.25"; minVelocity = "1.5"; maxVelocity = "3"; percentage = "1"; maxNumDrops = "5000"; MaxRadius = "60"; };
The significant properties here are offsetSpeed , which describes how quickly the rain moves across in front of you, and minVelocity and maxVelocity , which describe the lower and upper bounds (respectively) of randomly chosen drop velocities. The latter two keep the rain from falling as a uniform sheet, thus giving it a more realistic appearance.
The
percentage
property dictates the density of the drops, while
maxNumDrops
indicates the upper bounds of the number of drops to create.
MaxRadius
is the outer bounds of the area
Okay, so it may not be perfect, but it is neat. There are two useful object
The first is the stormCloud method that belongs to the Sky object. It looks like this:
Sky.stormCloud (flag, fade)
Set the flag to 1 if you want to create storm clouds and 0 if you want them to go away. To use the method, you would first call
Sky.stormCloud (0, 0)
as soon as your game starts to ensure that the clouds are not visible—all you would see is the
Then, at the moment you decide to call up a storm with your wand, you would call
Sky.stormCloud (1, 60)
somewhere in your script. This will cause the engine to gradually fade in your clouds over a 60-second time frame. When the storm clears, you make them go away gradually by calling
Sky.stormCloud (0, 60)
. Of course, you could use a different fade value, making it as long or short as you
The second method is a nice complement to the stormCloud method. It is called stormPrecipitation and belongs to the Precipitation object. It looks like this:
Precipitation.stormPrecipitation( flag, fade )
It works the same way as stormCloud but obviously applies to the precipitation.
Use the two methods together, with appropriate fade values, to get a nice storm effect. Try them out in your sample game by entering the commands manually in the console.