CIS 487/587 Bruce R. Maxim UM-Dearborn Torque Programming CIS 487/587 Bruce R. Maxim UM-Dearborn 2/18/2019
Slides based on the Code Sampler Tutorials by Kevin Harris 2/18/2019
Static Shapes Static shapes added using the Torque mission editor Static shapes are pieces of game geometry used to add obstacles to a game level Static shapes should be stored in .dts files 2/18/2019
Adding Static Shapes - 1 Add the trees directory to your tutorial.base\data\shapes directory. From the torqueDemo.exe main menu, click the "Load Mission!" button and load tutorial.base Open the Mission Editor using F11 and then select "Toggle Camera" from the "Camera" menu. This will allow you to navigate around without having to walk. 2/18/2019
Adding Static Shapes - 2 You can still move around with the "W", "A", "S", "D" keys, but to look about you'll need to hold down the right mouse button since mouse motion has been taken over by the Mission Editor. Find a location that would be suitable for a tree. Change the Mission Editor mode to "World Editor Creator" mode (e.g use F4) 2/18/2019
Adding Static Shapes - 3 Expand the tree in the lower right half of the screen by clicking the "Static Shapes" entry. Expand it out like so: "Static Shapes->tutorial.base->data->Shapes->tree" Click "tree" just once to place it somewhere in your editor's view. 2/18/2019
Adding Static Shapes - 4 Select the tree with your mouse. When the tree is selected a yellow box will surround it and three blue lines, which represent the X,Y, and Z axes will appear centered on the tree. If you hover your mouse pointer over a blue axis line, the line will become highlighted. 2/18/2019
Adding Static Shapes - 5 With the axis highlighted, you can move the tree along that axis by clicking and holding the left mouse button down and moving the mouse. In a similar fashion to translation, we can rotate our tree around its three axes by holding the "Alt" key while we select the axis and move the mouse about. To do scale the tree, select the tree and then hold down both the "Ctrl" and "Alt" key. 2/18/2019
Adding Static Shapes - 6 As you hover your mouse over the yellow cube that surrounds the tree, notice that the cube's sides highlight as the mouse hovers over. Pick and scale a side by clicking and holding left mouse button down and moving mouse. If you want to save your work, select the "File->Save Mission" menu item. If not, simply hit F11 to exit the Mission Editor and exit out of the game. 2/18/2019
Trigger Objects Triggers can be used to notify Torque when the Player has entered a special area 2/18/2019
Adding Trigger Objects - 1 Copy the triggers.cs script to the directory tutorial.base/server. datablock TriggerData( TempleOfEvilTrigger ) { // tickPeriodMS is a value is used to // control how often the console // onTriggerTick callback is called while there // are any objects in the trigger. // The default value is 100 MS. tickPeriodMS = 100; }; 2/18/2019
Adding Trigger Objects - 2 function TempleOfEvilTrigger::onEnterTrigger (%this, %trigger, %obj) { echo( "The player has just entered the Temple of Evil! - Not the smartest move!"); // This method is called whenever an object // enters the %trigger area, the object is // passed as %obj. The default onEnterTrigger // method (in the C++ code) invokes the // ::onTrigger(%trigger,1) method on every object // (whatever it's type) in the same group as the // trigger. Parent::onEnterTrigger( %this, %trigger, %obj ); } 2/18/2019
Adding Trigger Objects - 3 function TempleOfEvilTrigger::onLeaveTrigger (%this, %trigger, %obj) { echo( "The player has just left the Temple of Evil! - The player lives to fight another day!"); // This method is called whenever an object leaves // the %trigger area, the object is passed as %obj. // The default onLeaveTrigger method (in the C++ // code) invokes the ::onTrigger(%trigger,0) method // on every object (whatever it's type) in the same // group as the trigger. Parent::onLeaveTrigger( %this, %trigger, %obj ); } 2/18/2019
Adding Trigger Objects - 4 function TempleOfEvilTrigger::onTickTrigger (%this, %trigger) { echo( "The player is still in the Temple of Evil! - Calling all monsters!"); // This method is called every tickPerioMS, as long // as any objects intersect the trigger. The default // onTriggerTick method (in the C++ code) invokes // the ::onTriggerTick(%trigger) method on every // object (whatever it's type) in the same group as // the trigger. Parent::onTickTrigger( %this, %trigger ); } 2/18/2019
Adding Trigger Objects - 5 Add the following line of to the end of the list of execs script to the function onServerCreated() in the tutorial_base/server/game.cs file exec("./triggers.cs"); Run the test application by double-clicking "torqueDemo.exe", which is located in the "example" directory. When the main menu comes up, click the "Load Mission!" button. A mission named, "F World", should load. 2/18/2019
Adding Trigger Objects - 6 Use F11 to open the Mission Editor and switch the editing mode to the "World Editor Creator" mode. On the right side of the editor, you should see two tree entries Expand the tree in the lower right half of the screen by clicking the "Mission Objects" entry. Expand it out like so: "Mission Objects->Mission” 2/18/2019
Adding Trigger Objects - 7 Click the "Trigger" entry in the Mission directory just once to place it into the world. Enter a new Trigger name in the dialog box. Name the new Trigger something like "myTrigger". Next, click the drop-down box labeled "Data Block" and select "TempleOfEvilTrigger". Click the dialog's "Ok" button to finalize the settings. 2/18/2019
Adding Trigger Objects - 8 At this point you should see a small, yellow cube somewhere in your editor's view. It's advisable to place trigger some where near the ground so it will be easier to walk our player through it for testing. Scale up our Trigger's area a bit so it will be easier for us to register a hit with it. Select the Trigger object and then hold down both the "Ctrl" and "Alt" key. 2/18/2019
Adding Trigger Objects - 9 Once you've positioned and scaled the Trigger like you want, place your player somewhere outside the Trigger's area and hit the F11 key to exit the Mission Editor. Now, move your player in-and-out of the Trigger's area. Hit the "~" key to bring down the game's console and note how our player's movement through the trigger was logged in the console. 2/18/2019
Adding Trigger Objects - 10 You should see something like the following: The player has just entered the Temple of Evil! Not the smartest move! The player is still in the Temple of Evil! Calling all monsters! The player has just left the Temple of Evil! – The player lives to fight another day! 2/18/2019
Adding Trigger Objects - 11 These messages are coming from our Trigger's call-back functions, which get called when ever a player interacts with a Trigger object in the game. You need to add code to the call-back functions so your game can react to the player's presence. If you want to save your work, hit F11 to re-enter the Mission Editor and select the "File->Save Mission" menu item. 2/18/2019
Shape Objects Shape objects can interact with the Player through collision events Can be used to create game power-ups or weapons that can be picked up or used 2/18/2019
Adding Shape Objects - 1 Add the superbomb directory, which contains the .dts file and its texture, to your tutorial.base/data/shapes directory. Copy the superbomb.cs script file to your tutorial.base/server directory. Open the game.cs script file located in the tutorial.base/server directory and add the following line of script to the function onServerCreated( ). exec("./superbomb.cs"); 2/18/2019
Adding Shape Objects - 2 datablock ItemData( SuperBomb ) { // The mission editor uses the "category" variable to organize this new // item under the "shapes" root category. category = "Bombs"; // Next, we'll tell the mission editor where to find the .dts shape file // that defines our Super Bomb's geometry. shapeFile = "~/data/shapes/superbomb/superbomb.dts"; }; 2/18/2019
Adding Shape Objects - 3 // The mission editor will invoke this create() method when it // wants to create an object of our new datablock type. Good // time to setup any default behavior for our object. For // example, our new object's default behavior is to be // unmovable or static and rotate in place. function ItemData::create( %data ) { echo( "ItemData::create for SuperBomb called ---------" ); %obj = new Item() dataBlock = %data; rotate = true; // All Super Bomb power-ups will rotate. static = true; // Super Bombs should stay put. }; return %obj; } 2/18/2019
Adding Shape Objects - 4 // And, of course, what good is a Super Bomb power-up // if we can't tell when the player is touching it? // Every time our player touches a Super Bomb the // onCollision() function below will get called. function SuperBomb::onCollision( %this, %obj, %col ) { echo( "SuperBomb::onCollision called ----------" ); // TO DO: Add code here to have the player react to touching the power-up! } 2/18/2019
Adding Shape Objects - 5 Run the test application by double-clicking "torqueDemo.exe", which is located in the example directory. When the main menu comes up, click the "Load Mission!" button. A mission named, "F World“ Use F11 to open the Mission Editor and switch to the "World Editor Creator" mode. 2/18/2019
Adding Shape Objects - 6 Expand the tree in the lower right half of the screen by clicking the "Shapes" entry. Expand it out like so: "Shapes->Bombs“ Click "superbomb" just once to place it into the world. Be careful here. The SuperBomb object is actually located in two places within this expandable tree. "Shapes->Bombs“ "Static Shapes->tutorial.base->data->Shapes->SuperBomb" 2/18/2019
Adding Shape Objects - 7 If you drop the regular "Static Shapes" version of the SuperBomb, you will not be able to interact with it through scripting. The "static" version will simply become part of the mission's terrain like a building or a rock would and the only interaction the player will see is the inability to walk through it. Once you've positioned the Super Bomb where you want it, hit the "~" key to bring down the game's console 2/18/2019
Adding Shape Objects - 8 note how our SuperBomb's ItemData::create method got called. It should've echoed back the following line: ItemData::create for SuperBomb called ---------- Hit the "~" key again to close the console and hit the F11 key to return to regular game play. Move the player over to the Super Bomb and run through it a few times to register some collisions with it. 2/18/2019
Adding Shape Objects - 9 If you want to save your work, select the "File->Save Mission" menu item. If not, simply hit F11 to exit the Mission Editor and exit out of the game. 2/18/2019
Scripting Particle Systems Particle systems can be used to add special effects to game environments Particle systems can be used to model smoke, fire, and explosions 2/18/2019
Adding Particle Systems - 1 Add the campfire and campfire_particles directories to your tutorial.base/data/shapes directory. Copy the campFireFx.cs script file to your tutorial.base/server directory. Open the game.cs script file located in the tutorial.base/server directory and add the following line of script to the function onServerCreated( ). exec("./campFireFx.cs"); 2/18/2019
Adding Particle Systems - 2 // FireParticle - Defines how individual particles behave. datablock ParticleData( FireParticle ) { textureName = "~/data/shapes/campfire_particles/fire"; dragCoefficient = 0.0; gravityCoefficient = -0.3; // Gravity pulls down, but a negative value makes the particles rise instead of sink inheritedVelFactor = 0.00; useInvAlpha = false; spinRandomMin = -30.0; spinRandomMax = 30.0; lifetimeMS = 500; lifetimeVarianceMS = 250; times[0] = 0.0; times[1] = 0.5; times[2] = 1.0; colors[0] = "0.8 0.6 0.0 0.1"; colors[1] = "0.8 0.6 0.0 0.1"; colors[2] = "0.0 0.0 0.0 0.0"; sizes[0] = 1.0; sizes[1] = 1.0; sizes[2] = 5.0; }; 2/18/2019
Adding Particle Systems - 3 // FireParticleEmitter - Defines how the particles enter the world. datablock ParticleEmitterData( FireParticleEmitter ) { particles = "FireParticle"; ejectionPeriodMS = 15; periodVarianceMS = 5; ejectionVelocity = 0.25; velocityVariance = 0.10; thetaMin = 0.0; thetaMax = 90.0; }; 2/18/2019
Adding Particle Systems - 4 // FireParticleEmitterNode - The particle system's node for world placement. datablock ParticleEmitterNodeData( FireParticleEmitterNode ) { timeMultiple = 1; }; 2/18/2019
Adding Particle Systems - 5 // SmokeParticle - Defines how individual particles behave. datablock ParticleData( SmokeParticle ) { textureName = "~/data/shapes/campfire_particles/smoke"; dragCoefficient = 0.0; gravityCoefficient = -0.2; // Gravity pulls down, but a negative value makes the particles rise instead of sink inheritedVelFactor = 0.00; useInvAlpha = false; spinRandomMin = -30.0; spinRandomMax = 30.0; lifetimeMS = 3000; lifetimeVarianceMS = 250; times[0] = 0.0; times[1] = 0.5; times[2] = 1.0; colors[0] = "0.6 0.6 0.6 0.1"; colors[1] = "0.6 0.6 0.6 0.1"; colors[2] = "0.6 0.6 0.6 0.0"; sizes[0] = 0.5; sizes[1] = 0.75; sizes[2] = 1.5; }; 2/18/2019
Adding Particle Systems - 6 // SmokeParticleEmitter - Defines how particles enter the world. datablock ParticleEmitterData( SmokeParticleEmitter ) { particles = SmokeParticle; ejectionPeriodMS = 20; periodVarianceMS = 5; ejectionVelocity = 0.25; velocityVariance = 0.10; thetaMin = 0.0; thetaMax = 90.0; }; 2/18/2019
Adding Particle Systems - 7 // SmokeParticleEmitterNode - Particle system's node for world // placement. datablock ParticleEmitterNodeData( SmokeParticleEmitterNode ) { timeMultiple = 1; }; 2/18/2019
Adding Particle Systems - 8 When the main menu comes up, click the "Load Mission!" button. After the mission starts, hit F11 to open the Mission Editor and switch to the "World Editor Creator" mode. Expand the tree in the lower right half of the screen by clicking the "Static Shapes" entry. Expand it out like so: "Static Shapes->tutorial.base->data->Shapes->campfire" 2/18/2019
Adding Particle Systems - 9 In the "environment" directory, click the "particleEmitter" entry just once to place it into the world. Name the new emitter something like "myFireFX". Next, click the drop-down box labeled "datablock" and select "FireParticleEmitterNode". Click the drop-down box labeled "Particle data" and select "FireParticleEmitter". 2/18/2019
Adding Particle Systems - 10 Click the dialog's "Ok" button to finalize the settings and position the resulting particle system in the middle of your camp fire model. It's important to understand that the two drop-down box entries "FireParticleEmitterNode", and "FireParticleEmitter" are not part of the Mission Editor's default setup. 2/18/2019
Adding Particle Systems - 11 These two entries were defined by our script file, campFireFx.cs This is why they are there as selectable entries – they were added through script! Once the fire particle system is positioned where you want it, return to the expandable tree menu and click the "particleEmitter" entry again to place a second particle system for the smoke effect. 2/18/2019
Adding Particle Systems - 12 Name the new emitter something like "mySmokeFX". Click the drop-down box labeled "datablock" and select "SmokeParticleEmitterNode". Click the drop-down box labeled "Particle data" and select "SmokeParticleEmitter". Click the dialog's "Ok" button to finalize the settings and place the resulting particle system in the middle of your camp fire model. 2/18/2019
Adding Particle Systems - 13 If you tweak something and your particle system suddenly breaks or you are unable to create new emitters because your script's datablocks are missing from the drop-down menus, hit the "~" key to bring down the console and look through the output for any scripting errors coming from your script's load-up. This should always be the first place to look when a problem occurs. 2/18/2019
Adding Weapons - 1 Add the rocket_launcher directory, which contains the .dts files and textures for the rocket launcher and rocket projectile, to your tutorial.base/data/shapes directory. To keep things simple, all files required by the rocket launcher, except the script itself, have been bundled together in the rocket_launcher directory. Usually files like rocket_explosion.ogg would be located in a dedicated sound directory. 2/18/2019
Adding Weapons - 2 Copy the rocket_launcher.cs script to your tutorial.base/server directory. Open the game.cs script file located in the tutorial.base/server directory and add the following line of script to the function onServerCreated( ). exec("./rocket_launcher.cs"); Make sure the new line comes before the loading of the "player.cs" script. If not, RocketLauncherImage will be undefined. 2/18/2019
Adding Weapons - 3 // When a rocket hits something, this is what it // sounds like datablock AudioProfile( RocketExplosionSound ) { filename = "~/data/shapes/rocket_launcher/rocket_explosion.ogg"; description = AudioDefault3d; preload = true; }; 2/18/2019
Adding Weapons - 4 // When rocket explodes on impact, it will emit // smoke like datablock ParticleData( RocketExplosionSmokeParticle ) { textureName = "~/data/shapes/rocket_launcher/smoke"; … }; datablock ParticleEmitterData( RocketExplosionSmokeParticleEmitter ) particles = "RocketExplosionSmokeParticle"; 2/18/2019
Adding Weapons - 5 // When a rocket explodes upon impact, it will emit // fire like this... datablock ParticleData( RocketExplosionFireParticle ) { textureName = "~/data/shapes/rocket_launcher/fire"; … }; datablock ParticleEmitterData(RocketExplosionFireParticleEmitter ) particles = "RocketExplosionFireParticle"; 2/18/2019
Adding Weapons - 6 // When a rocket explodes upon impact, it will emit // sparks like this... datablock ParticleData( RocketExplosionSparksParticles ) { textureName = "~/data/shapes/rocket_launcher/spark"; … }; datablock ParticleEmitterData (RocketExplosionSparksParticleEmitter ) particles = "RocketExplosionSparksParticles"; 2/18/2019
Adding Weapons - 7 // When a rocket hits something, it will explode like this... datablock ExplosionData( RocketExplosion ) { soundProfile = RocketExplosionSound; lifeTimeMS = 1200; lifetimeVarianceMS = 0; // Volume particles particleEmitter = RocketExplosionFireParticleEmitter; particleDensity = 100; particleRadius = 2; // Point emission particles emitter[0] = RocketExplosionSmokeParticleEmitter; emitter[1] = RocketExplosionSparksParticleEmitter; 2/18/2019
Adding Weapons - 8 // This will make the camera shake when a player gets hit // by a rocket. shakeCamera = true; camShakeFreq = "10.0 11.0 10.0"; camShakeAmp = "1.0 1.0 1.0"; camShakeDuration = 0.5; camShakeRadius = 10.0; // This will create a dynamic lighting effect in the // vicinity of the rocket's explosion. lightStartRadius = 6; lightEndRadius = 3; lightStartColor = "0.5 0.5 0.0"; lightEndColor = "0.0 0.0 0.0"; }; 2/18/2019
Adding Weapons - 9 // When a rocket is flying through the air, it will emit // exhaust like this... datablock ParticleData( RocketExhaustParticle ) { textureName = "~/data/shapes/rocket_launcher/smoke"; … }; datablock ParticleEmitterData( RocketExhaustParticleEmitter ) particles = RocketExhaustParticle; ejectionPeriodMS = 5; periodVarianceMS = 2; ejectionVelocity = 0.1; velocityVariance = 0.1; 2/18/2019
Adding Weapons - 10 // When the rocket launcher fires, it will emit a single // rocket which behaves like this... datablock ProjectileData( RocketProjectile ) { projectileShapeName = "~/data/shapes/rocket_launcher/rocket.dts"; … } 2/18/2019
Adding Weapons - 11 function RocketProjectile::onCollision ( %this, %obj, %col, %fade, %pos, %normal ) { echo("RocketProjectile::onCollision called! ---------"); // TO DO: Add code here to calculate rocket damage for any //object hit. } 2/18/2019
Adding Weapons - 12 // When the player uses the rocket launcher, it will // behave like this. There are lots of details in this // datablock datablock ShapeBaseImageData( RocketLauncherImage ) { shapeFile = "~/data/shapes/rocket_launcher/rocket_launcher.dts"; … }; 2/18/2019
Adding Weapons - 13 function RocketLauncherImage::onFire( %this, %obj, %slot ) { %projectile = %this.projectile; // Determine initial projectile velocity based on the gun's // muzzle point and the object's current velocity... %muzzleVector = %obj.getMuzzleVector( %slot ); %objectVelocity = %obj.getVelocity(); %muzzleVelocity = VectorAdd ( VectorScale(%muzzleVector,%projectile.muzzleVelocity), VectorScale(%objectVelocity, %projectile.velInheritFactor) ); 2/18/2019
Adding Weapons - 14 %p = new (%this.projectileType)() { // Create a new rocket projectile object... %p = new (%this.projectileType)() { dataBlock = %projectile; initialVelocity = %muzzleVelocity; initialPosition = %obj.getMuzzlePoint(%slot); sourceObject = %obj; sourceSlot = %slot; client = %obj.client; }; MissionCleanup.add( %p ); return %p; } 2/18/2019
Adding Weapons - 15 Open the "player.cs" script file located in the "tutorial.base/server" directory and add the following code to the function PlayerShape::onAdd. function PlayerShape::onAdd(%this,%obj) // allows player access to launcher as // soon as player is added to game { parent::onAdd( %this, %obj ); %obj.mountImage( RocketLauncherImage,0 ); %obj.setImageAmmo( 0, 1 ); } 2/18/2019
Adding Weapons - 16 Run the test application by double-clicking "torqueDemo.exe", which is located in the example directory. When the main menu comes up, click the "Load Mission!" button. When the mission loads up, you should be able to go around blasting stuff. 2/18/2019
Adding Weapons - 17 Hit the "~" key to bring down the game's console Note how each rocket that hits something calls our RocketProjectile::onCollision call-back function. You should see something like the following: RocketProjectile::onCollision called!---- 2/18/2019