Torque 2D - Tips!
by Melv May · in Torque 2D Beginner · 02/18/2013 (2:20 am) · 18 replies
Here you can find a list of tips that you should find useful.
About the author
#2
In legacy Torque 2D you could always add a behavior to a SceneObject. In Torque 2D MIT you can not only do this but you can also add behaviors to the Scene to give you scene-wide functionality.
This could prove useful in situations where you're finding yourself adding dummy SceneObject to the Scene just so you can add a behavior that logically doesn't apply to any one object.
02/19/2013 (2:11 am)
Tip #2In legacy Torque 2D you could always add a behavior to a SceneObject. In Torque 2D MIT you can not only do this but you can also add behaviors to the Scene to give you scene-wide functionality.
This could prove useful in situations where you're finding yourself adding dummy SceneObject to the Scene just so you can add a behavior that logically doesn't apply to any one object.
#3
As your code gets larger and more complex, it's extremely useful to know what script an object was created in. You can use the progenitor file feature here to aid you.
Any object you have create in TorqueScript will have its "progenitor file" set or in other words, the file which created it will be referenced.
For instance, if you have a script file "T2D/main.cs" that contains the function:
If you run the "HelloWorld" function you'll see the output:
You can also override this by calling "setProgenitorFile()" should you so wish.
TAML, by default, will also set the progenitor file for any objects it creates during a read operation. In this case, TAML sets the file to be the TAML file being read. If you don't want TAML to do this then you can turn it off with the TAML method "setProgenitorUpdate(false)" or the field "ProgenitorUpdate". With it off, the file is the script file that started the TAML read operation.
02/19/2013 (11:01 pm)
Tip #3As your code gets larger and more complex, it's extremely useful to know what script an object was created in. You can use the progenitor file feature here to aid you.
Any object you have create in TorqueScript will have its "progenitor file" set or in other words, the file which created it will be referenced.
For instance, if you have a script file "T2D/main.cs" that contains the function:
function HelloWorld()
{
%obj = new ScriptObject();
echo( "I was created in" SPC %obj.getProgenitorFile() );
}If you run the "HelloWorld" function you'll see the output:
"I was created in T2D/main.cs"
You can also override this by calling "setProgenitorFile()" should you so wish.
TAML, by default, will also set the progenitor file for any objects it creates during a read operation. In this case, TAML sets the file to be the TAML file being read. If you don't want TAML to do this then you can turn it off with the TAML method "setProgenitorUpdate(false)" or the field "ProgenitorUpdate". With it off, the file is the script file that started the TAML read operation.
#4
If you want a piece of code called periodically then you can use the periodic timer that's available on every object you create. It doesn't matter what the object is i.e. a Scene, SceneObject, SimSet, ScriptObject etc.
To start a periodic timer, you simply do the following:
Using only these two arguments, the timer will continue to run until either the object which the timer is running on is deleted or you stop the timer explicit like this:
Therefore, if you specify "1" then it'll run once. If you specify either "0" or don't specify it then it'll run forever or at least until you tell it to stop or delete the object which the timer is running on.
Internally, every object you create from TorqueScript is derived from an engine type of "SimObject". It's this object which hosts the timer functionality.
You can only have one periodic timer per object. If you start a timer on an object which already has its timer running, it will automatically stop the previous timer first so you don't need to deal with that by calling "stopTimer()". Feel free to delete the object without having to stop the timer first, any running timer will automatically be stopped for you.
Several of the example "toy" modules use this functionality. Here are a few references to them:
Sphere-Stack Toy
Tumbler Toy
Alpha-Blend Toy
As an interesting side-note: Whilst writing this tip I noticed that some of the toys generate a specific number of objects i.e. balls to stack or tumble etc. They do this by counting how many have been created and then stopping the timer. It's actually possible to use the timer itself and its "repeat" argument to control that so that it just stops when it has called the appropriate function enough times!
02/21/2013 (1:35 am)
Tip #4If you want a piece of code called periodically then you can use the periodic timer that's available on every object you create. It doesn't matter what the object is i.e. a Scene, SceneObject, SimSet, ScriptObject etc.
To start a periodic timer, you simply do the following:
// Let's just create an object, this can be anything. %obj = new ScriptObject(); // Start the timer. %obj.startTimer( "MyTimerFunction", 500, 10 );When you start a timer you must provide two things:
- Callback Function - The name of the callback function to call for each timer repetition.
- Time Period - The period of time (in milliseconds) between each callback.
Using only these two arguments, the timer will continue to run until either the object which the timer is running on is deleted or you stop the timer explicit like this:
// Stop the timer on this object. %obj.stopTimer();There is a third (optional) argument that you can provide as well:
- Repeat - The number of times the timer should repeat. If not specified or zero then it will run infinitely
Therefore, if you specify "1" then it'll run once. If you specify either "0" or don't specify it then it'll run forever or at least until you tell it to stop or delete the object which the timer is running on.
Internally, every object you create from TorqueScript is derived from an engine type of "SimObject". It's this object which hosts the timer functionality.
You can only have one periodic timer per object. If you start a timer on an object which already has its timer running, it will automatically stop the previous timer first so you don't need to deal with that by calling "stopTimer()". Feel free to delete the object without having to stop the timer first, any running timer will automatically be stopped for you.
Several of the example "toy" modules use this functionality. Here are a few references to them:
Sphere-Stack Toy
Tumbler Toy
Alpha-Blend Toy
As an interesting side-note: Whilst writing this tip I noticed that some of the toys generate a specific number of objects i.e. balls to stack or tumble etc. They do this by counting how many have been created and then stopping the timer. It's actually possible to use the timer itself and its "repeat" argument to control that so that it just stops when it has called the appropriate function enough times!
#5
The Scene uses world-units when positioning and sizing objects within the world. To the physics system, these world-units are physical units of one meter i.e. one world-unit is one meter.
The SceneWindow which acts as the Torque 2D camera provides a view onto the world and views an area of your choosing. The SceneWindow renders the view into the GUI which itself is sized in pixels therefore the region the camera is viewing equates directly to how a world-unit (meter) translates to on-screen pixels.
If you want to know what the current scaling is then you can use the the following method:
Each value is the number of pixels per world-unit in each axis.
You can also see this value if you turn-on the debug metrics in the "rendering" section like so:
When you choose the sizes of your scene objects in your scenes and your typical camera view area, this call can help you choose your art sizes.
All it's really doing is taking the resolution in any axis and dividing it by the camera size in the same axis so you can easily calculate this yourself.
02/22/2013 (7:05 am)
Tip #5The Scene uses world-units when positioning and sizing objects within the world. To the physics system, these world-units are physical units of one meter i.e. one world-unit is one meter.
The SceneWindow which acts as the Torque 2D camera provides a view onto the world and views an area of your choosing. The SceneWindow renders the view into the GUI which itself is sized in pixels therefore the region the camera is viewing equates directly to how a world-unit (meter) translates to on-screen pixels.
If you want to know what the current scaling is then you can use the the following method:
echo( SandboxWindow.getCameraRenderScale() );This returns a space-separated two-value vector with the first value being the scaling in the horizontal (X) axis and the second value being the scaling in the vertical (Y) axis.
Each value is the number of pixels per world-unit in each axis.
You can also see this value if you turn-on the debug metrics in the "rendering" section like so:
SandboxScene.setDebugOn( metrics );Doing this, shows you how many pixels per world-unit are rendered:
%renderScale = SandboxWindow.getCameraRenderScale(); echo( "Pixels per World-Unit X:" SPC %getWord( %renderScale, 0 ) ); echo( "Pixels per World-Unit Y:" SPC %getWord( %renderScale, 1 ) );When designing your game, you may want to consider having a target design surface resolution and base your art-work against that.
When you choose the sizes of your scene objects in your scenes and your typical camera view area, this call can help you choose your art sizes.
All it's really doing is taking the resolution in any axis and dividing it by the camera size in the same axis so you can easily calculate this yourself.
#6
This is a very simple tip, but it can save you a lot of time debugging. Whenever you are experiencing a problem related to a custom module or an asset, one of the first things you should do is check the console. If you are not seeing any error specific to the problem you are encountering, you can turn on full echo output for the ModuleDatabase and AssetDatabase independently.
If you open the root main.cs, you should see the following two lines:
If you set these to true, you will get a step-by-step print of each asset or module operation that is performed. Be prepared, as this will dramatically increase your console log if you have a lot of modules or assets.
02/25/2013 (10:53 am)
Tip #6This is a very simple tip, but it can save you a lot of time debugging. Whenever you are experiencing a problem related to a custom module or an asset, one of the first things you should do is check the console. If you are not seeing any error specific to the problem you are encountering, you can turn on full echo output for the ModuleDatabase and AssetDatabase independently.
If you open the root main.cs, you should see the following two lines:
// Set module database information echo. ModuleDatabase.EchoInfo = false; // Set asset database information echo. AssetDatabase.EchoInfo = false;
If you set these to true, you will get a step-by-step print of each asset or module operation that is performed. Be prepared, as this will dramatically increase your console log if you have a lot of modules or assets.
#7
While not technical, this is an extremely valuable tip. If you are ever in dire need of immediate help, there is a dedicated IRC channel you can join for live support. There are several veteran Torque users who lurk, including myself. Whether it's about Torque 2D, Torque 3D, or general information (such as TorqueScript syntax), you can join the IRC channel and ask questions. Here is the information:
Server: irc.maxgaming.net
Channel: #garagegames
Take your pick of IRC clients. I personally use Mibbit on Windows, Colloquy on OS X.
02/26/2013 (11:32 am)
Tip #7While not technical, this is an extremely valuable tip. If you are ever in dire need of immediate help, there is a dedicated IRC channel you can join for live support. There are several veteran Torque users who lurk, including myself. Whether it's about Torque 2D, Torque 3D, or general information (such as TorqueScript syntax), you can join the IRC channel and ask questions. Here is the information:
Server: irc.maxgaming.net
Channel: #garagegames
Take your pick of IRC clients. I personally use Mibbit on Windows, Colloquy on OS X.
#8
Sometimes you need to create a Gui Control which extends over the entire screen while still featuring transparent areas where the user can interact with the scene being displayed underneath it.
Imagine a scenario where you would have Gui Objects at the screen's top, bottom and sides.
By default, the GuiControl will not let you click or touch anything that is not part of it.
To remedy this behavior, you need to set the GuiControl's Modal property to false.
You might think that simply adding the line Modal = true to the gui.taml file would work but this actually generates an error when running the project.
You need to create a GuiProfile which specifically sets the Profile property Modal to false and then assign the profile to the GuiControl which requires it.
First, create the Profile in script :
All guiprofiles for the Sandbox demo are located in Sandbox/1/gui/guiprofiles.cs
Note that you can create your own guiprofiles.cs file in a separate module which will simply add your profiles to the existing ones.
03/01/2013 (8:11 am)
Tip #8Sometimes you need to create a Gui Control which extends over the entire screen while still featuring transparent areas where the user can interact with the scene being displayed underneath it.
Imagine a scenario where you would have Gui Objects at the screen's top, bottom and sides.
By default, the GuiControl will not let you click or touch anything that is not part of it.
To remedy this behavior, you need to set the GuiControl's Modal property to false.
You might think that simply adding the line Modal = true to the gui.taml file would work but this actually generates an error when running the project.
You need to create a GuiProfile which specifically sets the Profile property Modal to false and then assign the profile to the GuiControl which requires it.
First, create the Profile in script :
if (!isObject(GuiModelessProfile)) new GuiControlProfile (GuiModelessProfile)
{
Modal="false";
};Then, in your GuiControl's gui.taml file, simply add the line<GuiControl ... Profile = 'GuiModelessProfile' ... >
All guiprofiles for the Sandbox demo are located in Sandbox/1/gui/guiprofiles.cs
Note that you can create your own guiprofiles.cs file in a separate module which will simply add your profiles to the existing ones.
#9
Torque 2D defaults to rendering images using Bilinear Filtering which reduces pixellation however it causes adjacent texels in your texture to be sampled for each texel which can cause bleeding. This can become an issue on the "edges" of your image contents i.e. the region surrounding your player, projectile or other image.
It may be preferable to not use bilinear filtering but instead using Nearest Neighbor Interpolation. In this mode you won't get texel bleeding but you will be prone to pixellation. Also if you're downscaling i.e. rendering images smaller than they are, you'll get less than satisfactory results.
You have two choices here.
First, you can select the filter mode on a per-ImageAsset basis. You do this by using the field "FilterMode" in the ImageAsset type like so:
Second, you can actually set the default global filter mode using a script-variable preference like so:
If no global filter mode is specified and neither is a filter mode on an ImageAsset then "Nearest" is used.
03/04/2013 (3:47 am)
Tip #9Torque 2D defaults to rendering images using Bilinear Filtering which reduces pixellation however it causes adjacent texels in your texture to be sampled for each texel which can cause bleeding. This can become an issue on the "edges" of your image contents i.e. the region surrounding your player, projectile or other image.
It may be preferable to not use bilinear filtering but instead using Nearest Neighbor Interpolation. In this mode you won't get texel bleeding but you will be prone to pixellation. Also if you're downscaling i.e. rendering images smaller than they are, you'll get less than satisfactory results.
You have two choices here.
First, you can select the filter mode on a per-ImageAsset basis. You do this by using the field "FilterMode" in the ImageAsset type like so:
<ImageAsset
AssetName="MyAsset"
FilterMode="Nearest"
.../>You can set filter mode to "Nearest" or "Bilinear" and it will override the default global filter mode.Second, you can actually set the default global filter mode using a script-variable preference like so:
$pref::T2D::imageAssetGlobalFilterMode = "Nearest";Be sure so set this early-on in the start-up as it is only used when an asset is loaded. If an asset is unloaded and loaded again then it will be used again. The Sandbox does this in its preferences.
If no global filter mode is specified and neither is a filter mode on an ImageAsset then "Nearest" is used.
#10
Throughout the engine's scripts, whenever a color is needed, you will usually find a human-readable name for the color such as CornflowerBlue instead of the expected RGBA nomenclature.
You can find the list of stock color names (and add to it!) in the following file: color.cc
03/07/2013 (12:04 pm)
Tip #10Throughout the engine's scripts, whenever a color is needed, you will usually find a human-readable name for the color such as CornflowerBlue instead of the expected RGBA nomenclature.
You can find the list of stock color names (and add to it!) in the following file: color.cc
#11
When initializing the scenewindow for your game, you might be tempted to set the camera size, position, zoom and angle as in this example :
While this might make your code structure easier to follow, these values are optional!
When you create a new scenewindow object, the engine automatically sets those defaults for you.
Extra Hint : The scenewindow camera default size of 100 75 simply reflects most resolutions's 4:3 format.
03/11/2013 (7:22 pm)
Tip #11When initializing the scenewindow for your game, you might be tempted to set the camera size, position, zoom and angle as in this example :
mySceneWindow.setCameraPosition( 0, 0 );
mySceneWindow.setCameraSize( 100, 75 );
mySceneWindow.setCameraZoom( 1 );
mySceneWindow.setCameraAngle( 0 );While this might make your code structure easier to follow, these values are optional!
When you create a new scenewindow object, the engine automatically sets those defaults for you.
Extra Hint : The scenewindow camera default size of 100 75 simply reflects most resolutions's 4:3 format.
#12
T2D features several debug visualization options :
- "fps"
- "controllers"
- "joints"
- "wireframe"
- "aabb"
- "oobb"
- "sleep"
- "collision"
- "position"
- "sort"
You can set individual debug visualizations on and off by using the Scene.SetDebugOn() and Scene.SetDebugOff() functions.
For example, to enable the frames per seconds display (fps), you would type in
To disable the fps display, you would type in
Note that you can set several options at once, using a space-separated string, like so :
Also:
------
To view what Debug visualization options are currently enabled, you would use the getDebugOn() function with no arguments, which will return a string of space-separated items
If we were to run this after the previous example, the result would be : "fps collision metrics".
03/17/2013 (9:31 am)
Tip #12T2D features several debug visualization options :
- "fps"
- "controllers"
- "joints"
- "wireframe"
- "aabb"
- "oobb"
- "sleep"
- "collision"
- "position"
- "sort"
You can set individual debug visualizations on and off by using the Scene.SetDebugOn() and Scene.SetDebugOff() functions.
For example, to enable the frames per seconds display (fps), you would type in
Scene.setDebugOn("fps");To disable the fps display, you would type in
Scene.setDebugOff("fps");Note that you can set several options at once, using a space-separated string, like so :
Scene.setDebugOn("fps collision metrics");Also:
Scene.setDebugOn( "fps", "collision", "metrics" );
------
To view what Debug visualization options are currently enabled, you would use the getDebugOn() function with no arguments, which will return a string of space-separated items
Scene.getDebugOn();
If we were to run this after the previous example, the result would be : "fps collision metrics".
#13
When you look at the root 'main.cs' file in the Sandbox, you will notice several functions that are designed to help you follow the program's flow very precisely.
Here is a brief explanation of what each function actually does.
setScriptExecEcho( true ); -> Everytime a script file is executed, it will be written out to the console.
AssetDatabase.EchoInfo = true; -> Everytime an Asset is loaded or unloaded, the console will detail the asset activity, mainly the id of the loaded asset, and how many references to this asset exist in the current program.
trace(true); -> Every single time the code enters or exits a function will be listed in the console.
ModuleDatabase.EchoInfo = true; - > The console will tell you when modules are loaded and unloaded as well as the version of the concerned module.
03/18/2013 (1:50 am)
Tip #13When you look at the root 'main.cs' file in the Sandbox, you will notice several functions that are designed to help you follow the program's flow very precisely.
Here is a brief explanation of what each function actually does.
setScriptExecEcho( true ); -> Everytime a script file is executed, it will be written out to the console.
AssetDatabase.EchoInfo = true; -> Everytime an Asset is loaded or unloaded, the console will detail the asset activity, mainly the id of the loaded asset, and how many references to this asset exist in the current program.
trace(true); -> Every single time the code enters or exits a function will be listed in the console.
ModuleDatabase.EchoInfo = true; - > The console will tell you when modules are loaded and unloaded as well as the version of the concerned module.
#14
When creating joints, you will, in most cases, use two sceneobjects as in this example :
You can however, omit one of the sceneobjects and replace it with an empty string :
In this case, the engine will replace the empty string ("") with the Scene's groundbody, which is centered at position "0 0".
Note that the Scene's groundbody is not exposed to the script engine. This means that you cannot change or access its properties via script.
03/20/2013 (4:41 am)
Tip #14When creating joints, you will, in most cases, use two sceneobjects as in this example :
Scene.createRevoluteJoint(%object1,%object2);
You can however, omit one of the sceneobjects and replace it with an empty string :
Scene.createRevoluteJoint(%object1,"");
In this case, the engine will replace the empty string ("") with the Scene's groundbody, which is centered at position "0 0".
Note that the Scene's groundbody is not exposed to the script engine. This means that you cannot change or access its properties via script.
#15
Throughout the code, you will often see the two acronyms AABB and OOBB.
AABB stands for Axis-Aligned Bounding Box. If you turn on the AABB debug visualization, as shown in
Tip #12, you will see a box encompassing the object. Notice that the box will not rotate with the object, i.e. it stays aligned with the world's axes.
OOBB stands for Object-Oriented Bounding Box, which will be a square area, encompassing the object and rotating with it.
03/23/2013 (8:13 am)
Tip #15Throughout the code, you will often see the two acronyms AABB and OOBB.
AABB stands for Axis-Aligned Bounding Box. If you turn on the AABB debug visualization, as shown in
Tip #12, you will see a box encompassing the object. Notice that the box will not rotate with the object, i.e. it stays aligned with the world's axes.
OOBB stands for Object-Oriented Bounding Box, which will be a square area, encompassing the object and rotating with it.
#16
When you load a Scene from a .taml file, all of the Assets in the .taml file will obviously be loaded when the game starts.
IF you create objects (such as bullets) on the fly during the game however, the first time you will instance an object, the asset will have to be loaded for the first time, which might create a slight delay or slowdown as the imagefile is loaded, etc.
To circumvent that, you can specify what assets to preload in the level's taml file.
So even if you don't have a bullet initially present in your level, you can add its asset to Scene.AssetPreload so that when you create the projectile, its asset will already be loaded and the instancing will be many many times faster.
04/08/2013 (4:45 pm)
Tip #16When you load a Scene from a .taml file, all of the Assets in the .taml file will obviously be loaded when the game starts.
IF you create objects (such as bullets) on the fly during the game however, the first time you will instance an object, the asset will have to be loaded for the first time, which might create a slight delay or slowdown as the imagefile is loaded, etc.
To circumvent that, you can specify what assets to preload in the level's taml file.
<Scene>
<Scene.AssetPreloads>
<Asset Id="@asset=ToyAssets:Particles1" />
</Scene>So even if you don't have a bullet initially present in your level, you can add its asset to Scene.AssetPreload so that when you create the projectile, its asset will already be loaded and the instancing will be many many times faster.
#17
http://www.garagegames.com/community/forums/viewthread/138463
07/21/2014 (6:58 am)
If you use Torsion this script documentation trick will be usefulhttp://www.garagegames.com/community/forums/viewthread/138463
#18
I picked up this tip from Luminary Apps.
My testing of this in T2D yielded positive results in joint accuracy and control, including preventing the "breaking" of joints. Keep in mind that increasing these values can affect performance if you go too high and have too many objects on screen, but I did not have any problems on my machines.
08/14/2014 (8:01 am)
If your joints are a little too "floppy", you can try increasing the velocity and position iterations of the box2d simulation. From your Scene object:%scene.setPositionIterations(50); %scene.setVelocityIterations(50);
I picked up this tip from Luminary Apps.
My testing of this in T2D yielded positive results in joint accuracy and control, including preventing the "breaking" of joints. Keep in mind that increasing these values can affect performance if you go too high and have too many objects on screen, but I did not have any problems on my machines.
Associate Melv May
The "Canvas" type now provides the ability to control whether the background is cleared and if so, what color is it cleared to like so:
or
Clearing the background each frame is wasteful if the whole screen is being drawn over by your scenes contents.
A nice way of seeing if you are always drawing over the background is to set the canvas background color to something you're not using in your scene like the color "HotPink".
The Canvas type defaults to using a background color of "black".
In addition, the "SceneWindow" type also provides exactly the same functionality but in this case it defaults to off. Any SceneWindow rendering a Scene will clear its background region to the specified color prior to rendering.
The background color you typically see is the color set by the Canvas during a frame render and not the SceneWindow background. This means that you can render multiple SceneWindows over the top of each other without them clearing the one rendered previously.
or
Finally, as you can see, any field or method that accepts a color can use one of the stock colors supported which can be found here.