Storms


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 storm using script code, and there are some functions provided that will automate portions for you.

Note

The lightning storm features require the use of sound effects files, but we don't cover those until the next chapter. So you will have to add the appropriate code to make the sound effects work.This will be done with minimal commentary here—just enough to get the thunder sounds working. See Chapters 19 and 20 for a detailed look at sounds.

Setting Up Sound

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 follows:

  1. 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\.

  2. 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 
  3. 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\.

  4. 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"); 
  5. Next, locate the line:

     Exec("./misc/MasterScreen.cs"); 

    and after it, add this line:

     Exec("./misc/SetupScreen.cs"); 
  6. Edit the file C:\aEmaga6\control\client\default_profile.cs and add the following line near the top:

     GuiButtonProfile.soundButtonOver = "AudioButtonOver"; 
  7. Copy the file C:\3DGPAi1\RESOURCES\CH18\OpenAL32.dll to the directory C:\aEmaga6\.

  8. 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.

  9. 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; }; 
  10. 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!

Storm Materials

You will have noticed that when you copied those files from the book's resources directory, there were DML (material definition) and PNG files for both the lightning and rain. If you look inside the 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.

click to expand
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 viewed in the file. To create your own such file, make a new file in Paint Shop Pro, and set it to 128 pixels square, 16 million colors (24 bits), and transparent using the New Image dialog box. Then choose View, Change Grid Guide and Snap Properties, and set the vertical and horizontal values in the Current Image Settings to 32 for both. A 4 by 4 grid will appear in your view of the new blank image. Draw your version of each of the 16 drops in a grid box on the image. The grid is not part of the image. Save the file and deposit it in the same place where you had put the 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.

click to expand
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.

Lightning

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 thunderSoundn properties is chosen randomly.

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 indicate which datablock to use. This is done with the datablock property. There are then a couple of self-evident properties: strikesPerMinute and chanceToHitTarget. Then strikeWidth indicates the scale factor applied to the image overlay of the lightning bolt that comes from the image files.

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 size of the starting area is defined by boltStartRadius, and the size of the strike area is defined by strikeRadius.

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 stormFogn 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.

click to expand
Figure 18.16: A lightning bolt.

Rain

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 dictate the scaled size of the drops.

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 preceding code work well.

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 surrounding the player where the engine can create drops.

A Perfect Storm

Okay, so it may not be perfect, but it is neat. There are two useful object methods that you can use to move a storm in and out gradually without the need to manipulate the storm-related objects in detail.

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 skybox.

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 desire.

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.




3D Game Programming All in One
3D Game Programming All in One (Course Technology PTR Game Development Series)
ISBN: 159200136X
EAN: 2147483647
Year: 2006
Pages: 197

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net