Torque 2D/T2D 3DShapes
From TDN
Contents |
Introduction
This document is intended to provide an example on how to get started using the "t2dShape3D" object. Complete knowledge of how to generate ".dts" shapes (hereto referred to as "shapes") is assumed and will not be covered here. Additionally, aspects of shapes such as animation files (".dsq") and triggers are assumed knowledge. Further information on shapes can be found on TDN.
It should be understood that this object provides a 3D context within a 2D environment and is therefore limited to the constraints of such an environment. No 3D lighting or 3D collision-detection is provided but can easily be implemented for your specific game development needs.
For this tutorial, we're assuming that you've got a set of ".dts" shapes, separate ".dsq" animation(s) and triggers embedded into your animations that you can use. Failing that, feel free to use this Soldier Example.
Okay then, let's get started!
Shape Object Creation
The "t2dShape3D" object (hereto referred to as the "shape-object") is based upon the core-object "t2dSceneObject" so it inherits everything you come to expect from TGB objects such as mounting, physics, collision-detection etc. Obviously the shape-object has functionality over and above this and it's this functionality that we'll focus on here. It is assumed that you're familiar with all other calls. For clarity, all shape-object specific functionality will be highlighted in bold.
So without any delay, here's how you'd create a shape-object:
%shape = new t2dShape3D() { scenegraph = t2dScene; };
%shape.setShape("./models/soldier.dts");
As you can see, you create the shape-object as normal. The only required step to get the object rendering is to select the appropriate shape. When you select a shape, it is important that all dependant files are located in the same directory such as skins etc.
Now that you've got your shape on the screen, you can manipulate it as a normal TGB scene-object. For instance, you'd probably want to initially reposition and/or resize the object like so:
%shape = new t2dShape3D() { scenegraph = t2dScene; };
%shape.setShape("soldier.dts");
%shape.setPosition( "20 10" );
%shape.setSize( 15 );
That's it! As it stands, you're set to use the object as if it was a standard sprite but you'll eventually want to do something more sophisticated with the object so let's talk about that.
One of the first things you notice from above is that the shape's size is adjusted to best fit within the 2D area of the core-object. This is okay but due to the fact that we're dealing with a 3D object within a 2D space, TGB needs to provide a little more flexibility on how the shape is positioned within this object-window. One of the things that you'll soon notice when you start to animate shapes is that animations, by their very nature, move/distort the shape therefore allow the shape to temporarily move outside the object-window. TGB will clip (stop) the shape from rendering outside this object-window.
Shape Scale / Offset
At this point, TGB doesn’t know every aspect of all the animations you could potentially play so it's up to you to determine the scaling of the object so that it doesn't go outside these bounds. Most of the time, this won't be a problem but if your object does a somersault or other "drastic" animation, you may need to take this into account. Luckily, TGB provides a simple mechanism for you to control the sizing of the object over and above the object-window scale. Here's how you do it:
// Set the shape to be half-scale. %shape.setShapeScale( 0.5 );
It's as simple as that. If you change the size of your object, the shape will still be halved in size in the object-window. This allows you to tweak your object until, no matter what animation is played, it doesn't exit the window.
Actually, we used a shortcut above; because we're talking about a 3D shape, TGB allows you to specify scaling in independent axis to allow you to scale the shape in a non-uniform way like so:
// Set the shape to non-uniformly scaled (half width/three-quarter height/normal depth). %shape.setShapeScale( "0.5 0.75 1.0" );
Non-Uniform Scaling
Another attribute of shapes that you may want to control is the center-point of the shape. You may want to do this to offset the shape within the object-window. This is easy to achieve using the following:
// Adjust the shape offset in the Y axis. %shape.setShapeOffset( "0 0.5 0" );
The shape-offset can be adjusted in any/all of the three independent axes. The units used are related to the size of the object-window (being as this is adjusting the shape in relation to the object-window), therefore a value of "0.5" in the Y axis adjusts by half the height of the object window. This is understandable for the X and Y axis for what about the Z axis? The Z axis is offset as a unit of the shapes "depth". In other words a value of "0.5" would offset the shape in Z by half of the objects dimension. This axis offset is rarely used but can be useful for specific effects.
*** NOTE ***
TGB orientates the X/Y axis so that they correspond to the axis that all other TGB objects use e.g. the horizontal and vertical axis respectively. The Z axis goes into/out of the screen e.g. the direction of the layers. This is the same for all calls that allow you to provide separate X, Y and Z parameters.
Headline text
link titleLink titleItalic textBold textShape Rotation
One of the more common features you'll use with shapes is rotation. Unlike standard rotation in 2D, you've obviously got an extra dimension with shapes. This means that the core rotation capabilities are not adequate to orientate your shapes. Rather than using the existing rotations capabilities and adding an extra function to specify the additional dimension, the shape-object has its own rotation functions. In-fact, rotation of the underlying object should not be used as it will confuse what you see on the screen!
Without further delay, here's how you specify a 3D rotation for shapes:
// Orientate the shape in 3D. %shape.setShapeRotation( "45 0 0" );
As you'd expect, the above command will orientate the shape in the X axis by 45-degrees. That's pretty simple to understand but what if we want to start the object rotating rather than set a specific orientation? To do this, you need to set the shapes angular velocity like so:
// Automatically rotate the shape in 3D. %shape.setShapeAngularVelocity( "0 90 0" );
As you'd expect, the above command will rotate the shape by 90-degrees/second along the Y axis.
You should always be aware, particularly when the center of rotation is offset from the center of the shape as the shape can move outside the object-window. With careful use of scale/offset, you can stop this happening.
*** NOTE ***
When rotating a shape, the rotation takes place around the specified axis e.g. rotation around the X axis causes an object to rotate in the "vertical" direction. Talking about "vertical" is dangerous as combining different orientations causes the "vertical" to change.
Shape Skin
The following assumes you fully understand how to create and define DTS skins and skin-sets. To specify a skin/set simply use the following:
// Set Shape Skin. %shape.setSkin( "mySet", "mySkin" );
A skin-set allows you to specify a group of skins into a logical group. This is rather advanced and quite often, you'd have a single default skin (meaning you'd use this function) or multiple skins all in the same set.
Shape Detail-Level
T2D provides the ability to manually select a level-of-detail (LOD) for your object. You can select the detail level like so:
// Set Detail Level. %shape.setDetailLevel( 0 );
As you can see, the detail-level is a simple numeric value. Detail-levels start at "0" and increase to the number of defined levels within the shape itself. For instance, if the shape has "4" detail levels, these can be selected using the range "0" to "3". The default detail-level, if not specified, is "0" e.g. the highest. Detail-levels are not automatically generated; they are defined within the shape by the artist.
One of the problems when switching between detail-levels is "popping" e.g. an instant transition between one level and the other causes an ugly jump. To get around this problem, you can specify an "intra" detail-level in the range "0.0" to "1.0". This allows you to change the detail-level gradually, blending between the old level and the new.
You do this by specifying the "intra" detail level like so:
// Set Detail Level half-way between level 0 and 1. %shape.setDetailLevel( 0, 0.5 );
As you can see the second parameter specifies the "intra" detail-level.
You can retrieve the number of available detail-levels, the current detail-level as well as the intra-detail-level at any time like so:
// Fetch the number of detail-levels. %detailLevels = %shape.getDetailLevelCount(); // Fetch the current detail-level. %currentDetail = %shape.getCurrentDetailLevel(); // Fetch the current intra-detail-level. %currentIntraDetail = %shape.getCurrentIntraDetailLevel();
Here's an example of using different detail levels:-
- NOTE ***
In the future, there'll be a mechanism to automatically adjust the LOD. Also, the "intra" detail-level will be adjusted automatically so that no "popping" occurs.
Shape Animation
We'll assume here that you've got a handful of animation files located with the "soldier.dts" shape example above. Let's start by configuring these animations so that you can "play" them using the shape-object. Before you can play animations however, you must associate the animations with the shape itself.
You may be forgiven for assuming that you associate the animations with the shape using the shape-object itself or that you simply specify the animation file ".dsq" when playing an animation. Although it is possible for the system to work like this, the end result would be much more complicated to work with, especially when you consider that anytime you wanted to play an animation, you'd need to specify a filename! Also, you can have multiple shape-objects using the same shape and so being forced to specify/associate animations like this would get tedious.
TGB therefore doesn't do this and allows for a much more streamlined method to handle animations using an "alias" name for each and every animation. To tell TGB which animations are associated with a specific shape, you need to use a new object called a "TSShapeConstructor" datablock (hereto referred to as shape-constructor. This datablock completely defines all animations, animation-name (alias) and animation sequences in a single configuration so that when a shape is used, all the animations are available without further configuration.
- NOTE ***
The prefix "TS" stands for "Three-Space" which is the 3D nomenclature used in the Torque Game Engine (TGE). The reason this wasn't renamed to use the prefix "t2d" was to allow existing users of the TGE to associate with the datablock but to also allow people who may use the TGE in the future to easily understand the datablock and its relevant documentation.
Here's an example of using a shape-constructor:
datablock TSShapeConstructor(soldierDTS)
{
baseShape = "./soldier.dts";
sequence0 = "./soldier-idle.dsq idle";
sequence1 = "./soldier-move.dsq move";
sequence2 = "./soldier-attack.dsq attack";
sequence3 = "./soldier-react.dsq react";
sequence4 = "./soldier-death.dsq death";
};
As you can see, the datablock is fairly simple; it first defines the base-shape (".dts") that all animations will be associated with. It then defines animation sequences (".dsq"). At the end of every sequence is a word; this is the alias for the animation and it is this alias that is used to play animations.
- NOTE ***
Shape-constructor datablocks must be defined before you use any animations for the respective shape. This is similar to the way that imageMap datablocks are used; the difference here is that you don't refer to the shape-constructor by its name but rather the alias names against animations. It is also important to note that the examples provided use the file location of "./" and therefore assume the code is executed in the same directory as the ".dts" and ".dsq" files. Real files should be adjusted as appropriate.
Now that we've got our shape-constructor defined, we should be happy that TGB can play any of the animations we've setup. Here's how we'd play the "move" animation above:
%shape.playAnimation( move );
It's a simple as that! The "playAnimation()" function has more parameters that allow you to control the animation itself but before we go into that, let's show you an alternative method for playing animations. Above, we used the animations alias but you can also use the sequence number. The sequence number is that defined in the shape-constructor. In the above example, the "move" sequence number is "1". Here's how we'd play that sequence:
%shape.playAnimationSequence( 1 );
Pretty simple stuff! Now that you've seen how to get animations started, let's go into the additional parameters provided in both the "playAnimation()" and "playAnimationSequence()" functions.
There is in-fact, two additional parameters that you can use when starting animations, these are:-
Start Time; this is the timeline "into" the animation that you're starting. The time is normalized time meaning the range is "0.0" to "1.0". This means that specifying a start-time as "0.5" would start the animation half-way into the animation. The default, if not specified, is "0" e.g. the start of the new animation.
Transition Time; this is the time it takes for the new animation to take effect. When you start an animation, TGB will blend any existing animation with the new one. This blending means that you can gradually start an animation rather than abruptly changing it. The default, if not specified, is "0" e.g. instant change of animation.
Here are a few examples of using start/transition times:
// Start Animation at beginning but blend-in the animation over 5 seconds. %shape.playAnimation( move, 0, 5 ); // Start Animation three-quarters through and blend-in over half a second. %shape.playAnimation( move, 0.75, 0.5 ); // Identical to previous example but the animation is selected by sequence. %shape.playAnimationSequence( 1, 0.75, 0.5 );
- NOTE ***
"sequence0" in the Shape-constructor datablock defines the default animation. All shape-objects of the type defined in the shape-constructor will automatically play the "sequence0" animation without the need to specify it. This is why this animation is typically used as an "idle" animation.
Now that you've got animations running, you may be interested in fine-tuning the timing of the animation itself. You can quickly adjust the time-scale of the animations using:
// Make the shape animated at twice the rate. %shape.setTimeScale( 2.0 );
This function allows you to adjust the animation time-scale only. It does not affect the timings of the underlying core-object, only the shape animation.
Shape Animation Triggers
Now that you've got your animations configured, you may want to start using triggers. Triggers allow you to embed events in the animations themselves. The events can be placed into 32 independent channels allowing you to designate an event on a specific channel to be a specific action. Using triggers in TGB is extremely easy indeed; all you need to do to get your object to respond to triggers is activate them like so:
// Activate Trigger Monitoring. %shape.setTriggerActive( true );
If an animation is played (or is currently playing), any triggers within the animation will now cause the following callback:
// Animation Trigger Callback.
function t2dShape3D::onAnimationTrigger( %this, %triggerChannel )
{
echo( "Trigger on Object" SPC %this.getId() SPC "in channel" SPC %triggerChannel );
}
Valid trigger channels are in the range of "1" to "32" (not zero-based). This is left for compatibility with the TGE.
Typically, you'd respond to triggers on a specific channel e.g. triggers on channel #1 could be fire-events; triggers on channel #2 could be footstep-events etc.
Conclusion
We've now come to the end of our discussion on the shape-object; you should now have enough information to start using 3D shapes within TGB. We hope that you can come up with some great ways of using them to enhance your games!
Don't forget that you can always find information on the TGB shape-object in the TGB reference documentation.
All the best everyone and happy TGB'ing! ïŠ
Categories: T2D | TGB | TorqueScript | Tutorial






