
We have learned how to create a loop FOR at this lesson.
The "timestep block" is a very useful "event block" of the Blink3D API.
An "event block" normally captures something that the user did (a mouseclick, by example). The "timestep block" captures the "final redesign of a 3D scene". What is this?
A BBG world is really a 2D figure that needs to be redesigned many times to show the eventual new "point-of-view" of the camera. The interval between redesigns (re-renderings) depends of the velocity of the CPU of the user.It will be fast on fast new computers and slow on old computers.
We call this "time for redesign": framerate.
So: the velocity of re-execution of the lines of code that are inside a "timestep block" is that of the framerate. And we can use it to do loops depending of the framerate
We can recreate the sample of that lesson, created using the "loop FOR" :
myLoop1 = new Object();
i=0;
myLoop1.timestep = function(appLag, dt){
chat.print('The double of the counter is: ', i*2);
i++;
if(i>=5)Application.removeTimestep(myLoop1);
}
Application.addTimestep(myLoop1 );
First of all we need to create a prefix, an object .
myLoop1 = new Object();
To start the loop we use the line of code:
Application.addTimestep(myLoop1 );
The main part of the block is:
myLoop1.timestep = function(appLag, dt){
//code here
// to stop use: Application.removeTimestep(myLoop1);
}
The parameter/variable appLag contains the number of seconds since the start of the world, the dt contains the number of seconds since the last timestep. If you like to create a timer framerate independent you need to use these variables.
To stop the loop we use: removeAnimator(myLoop1).But it's important to note that the loop will stop only after this roundtrip.
We will use a "timestep block" to open smoothly our door. But we need to learn another trick.
The Class Vector has a method whose name is blend. If we like to increase a vector Vector1 some percentage of another vector Vector2, we can use (for 50%):
Vector1 = Vector1.blend( Vector2, 50/100 );
How can we use this resource for our door? Look the figure.
If we like to increase the vector having the values (0,0,0) until it has the values (6,0,0) smoothly, in 6 framerates, we can use a "timestep block":
actualframe=0;
totalframes=6;
myVector=Vector(0,0,0);
myFinalvector = Vector(-6,0,0);
myLoop1 = new Object();
myLoop1.timestep = function(appLag, dt){
if(actualframe<=totalframes){
myVector = myVector.blend(myFinalVector,1/totalframes);
}
actualframe++;
if(actualframe>=totalframes){
Application.removeTimestep(myLoop1);
Chat.print("The Vector is now -6,0,0.");
}
}
Application.addTimestep(myLoop1 );
We can do the same trick to open our door, puting the start of the "timestep block" triggered by the click of the button:
Look all the new code to open the door. What is new is bolded:
// Attach the Land
oLandEntity = Scene.createEntity( "Land", "land.mesh" );
Scene.rootNode.attachObject(oLandEntity );
oLandEntity.fixed = true;
oLandEntity.collisionGeometryType = oLandEntity.COLLISION_GEOM_TRI_SOUP;
oLandEntity.createPhysicalModel();
oLandEntity.active = false;
oLandEntity.position = Vector(0, 0, 0);
// Create a point light
oPointLight = Scene.createPointLight( "SceneLight" );
oPointLight.position = Vector( 20, 300, 50 );
// Adding the left part of the wall having the door
oObjEntity = Scene.createEntity( "Obj", "wall1.mesh" );
oObjNode = Scene.createSceneNode( "ObjNode" );
oObjNode.attachObject( oObjEntity );
oObjNode.translate(Vector(0,0,0 ), oObjNode.TRANSFORM_WORLD );
oObjEntity.fixed = true;
oObjEntity.collisionGeometryType = oObjEntity.COLLISION_GEOM_TRI_SOUP;
oObjEntity.createPhysicalModel();
oObjEntity.active = true;
// Adding the right part of the wall having the door
oObj2Entity = Scene.createEntity( "Obj2", "wall2.mesh" );
oObj2Node = Scene.createSceneNode( "Obj2Node" );
oObj2Node.attachObject( oObj2Entity );
oObj2Node.translate(Vector(0,0,0 ), oObj2Node.TRANSFORM_WORLD );
oObj2Entity.fixed = true;
oObj2Entity.collisionGeometryType = oObj2Entity.COLLISION_GEOM_TRI_SOUP;
oObj2Entity.createPhysicalModel();
oObj2Entity.active = true;
//The door
oObj3Entity = Scene.createEntity( "Obj3", "door.mesh" );
oObj3Node = Scene.createSceneNode( "Obj3Node" );
oObj3Node.attachObject( oObj3Entity );
oObj3Node.translate(Vector(0,0,0 ), oObj3Node.TRANSFORM_WORLD );
oObj3Entity.fixed = true;
oObj3Entity.collisionGeometryType = oObj3Entity.COLLISION_GEOM_TRI_SOUP;
oObj3Entity.createPhysicalModel();
oObj3Entity.active = true;
//The button
oButton = GUISystem.createButton( "BtUse" );
oButton.active = true;
oButton.alwaysOnTop = true;
oButton.text = "USE ITEM";
oButton.absolutePositionX=100;
oButton.absolutePositionY=70;
oButton.absoluteWidth = 40;//HEIGHT
oButton.absoluteHeight = 180;//width
oButton.normalTextColor = Color( 0, 0, 1, 1 );//blue
oButton.onClicked = function( sWindowName){
oObj3Entity.collide= false;
Application.addTimestep(doorTimestep );
}
oButton.addListener(oButton.ON_EVENT_CLICKED );
GUISystem.addChildWindow( oButton);
//The "timestep block"
actualframe=0;
totalframes=2000;
doorOpen=Vector(-500,0,0);
doorNowPos=Vector(0,0,0);
doorTimestep = new Object();
doorTimestep.timestep = function(appLag, dt ){
if(actualframe<=totalframes){
doorNowPos = doorNowPos.blend(doorOpen,1/totalframes);
oObj3Node.translate(doorNowPos , oObj3Node.TRANSFORM_WORLD );
}
actualframe++;
if(actualframe>=totalframes){
Application.removeTimestep(doorTimestep);
Chat.print("The door is open.");
}
}
You can use:
oObj3Entity.collide= false;
in the begining of the timestep loop (our option here) or in the end, before the Chat.print. May be at the end is more "realistic" - the avatar only can enter when the door is completely open..
TIP:Increasing the value of "totalframes" we reduce the velocity of the door to open
Now YOU have the knowledge to create a complete exercice: the player picks the two keys, they go to the Inventory, the player, using the blue key, opens the blue door.
Try. And good luck!
PREVIOUS LESSON NEXT LESSON T.CONTENTS HOMEPAGE
