Part 4 – Scripting and time

So far our simple examples has only been static. But through scripting you can make put some life into the screen.

Script can be implemented using JavaScript objects that implement one or more of the following methods (update, render, activated, deactivated) (These methods are defined in the Component - See the http://www.kickjs.org/api/classes/kick.scene.Component.html ). The most important of these methods are the update method, which is called once per frame for each active component (an active component means that it is added to a GameObject in the active scene).

Let’s look at a simple example:

 var RotatorComponent = function(config){
     var rotationEuler = [0,0,0],
         thisObj = this;

     this.rotationSpeed = config.rotationSpeed;

     this.update = function(){
         var gameObject = thisObj.gameObject,
             transform = gameObject.transform,
             time = gameObject.engine.time,
             deltaTime = time.deltaTime;
         rotationEuler[2] += deltaTime*thisObj.rotationSpeed;
         transform.localRotationEuler = rotationEuler;
     };
 };

 // init engine (create 3d context)
 var engine = new kick.core.Engine('3dCanvas');

 // create a game object in [0,0,0] facing down the -z axis
 var cameraObject = engine.activeScene.createGameObject();
 cameraObject.transform.position = [0,0,5];
 // create a orthographic camera
 var camera = new kick.scene.Camera({
     perspective: false,
     left:-5,
     right:5,
     top:5,
     bottom:-5
 });
 cameraObject.addComponent(camera);

 // create material
 var shader = engine.project.load(engine.project.ENGINE_SHADER_UNLIT);
 var material = new kick.material.Material({
     shader: shader,
     uniformData:{
         mainColor: [1,1,1,1]
     }
 });

 // create meshes
 var meshes = [engine.project.ENGINE_MESH_TRIANGLE, engine.project.ENGINE_MESH_CUBE];
 for (var i=0;i<meshes.length;i++){
     var gameObject = engine.activeScene.createGameObject();
     gameObject.transform.position = [-2.0+4*i,0,0];
     var meshRenderer = new kick.scene.MeshRenderer();
     meshRenderer.mesh = engine.project.load(meshes[i]);
     meshRenderer.material = material;
     gameObject.addComponent(meshRenderer);
     var rotationSpeed = i-0.4;
     gameObject.addComponent(new RotatorComponent({rotationSpeed:rotationSpeed}));
 }

Here two RotatorComponent objects are created (one for each of the visible GameObjects). The RotatorComponent constructor function takes an input parameter containing the rotation speed. Also note how each component has a reference to the GameObject owning this component.

Note that the code uses the Time object (received from the Engine object). The Time object let you create animation that runs independent of the framerate. The time object also contains time (since start of program), frame (count) and a scale property that can be used to implement slow-motion effects easily (is basically multiplied with the delta time).

Sometimes your Component need to do some initialization. Note that when the component constructor is called the component may not be setup properly (for instance it does not have any reference to any GameObject yet). A way to do this is to implement the activated method. This method will be called when the component is added to the scene.

 var RotatorComponent = function(config){
     var transform,
         time,
         rotationEuler = [0,0,0],
         thisObj = this;

     this.rotationSpeed = config.rotationSpeed || 0.1;

     // Get references to objects used in the update method performs better
     this.activated = function(){
         transform = thisObj.gameObject.transform;
         time = thisObj.gameObject.engine.time;
     };

     this.update = function(){
         rotationEuler[2]+=time.deltaTime*thisObj.rotationSpeed;
         transform.localRotationEuler = rotationEuler;
     };
 };

 // init engine (create 3d context)
 var engine = new kick.core.Engine('3dCanvas');

 // create a game object in [0,0,0] facing down the -z axis
 var cameraObject = engine.activeScene.createGameObject();
 cameraObject.transform.position = [0,0,5];
 // create a orthographic camera
 var camera = new kick.scene.Camera({
     perspective: false,
     left:-5,
     right:5,
     top:5,
     bottom:-5
 });
 cameraObject.addComponent(camera);

 // create material
 var shader = engine.project.load(engine.project.ENGINE_SHADER_UNLIT);
 var material = new kick.material.Material({
     shader: shader,
     uniformData:{
         mainColor: [1,1,1,1]
     }
 });

 // create meshes
 var meshes = [engine.project.ENGINE_MESH_TRIANGLE, engine.project.ENGINE_MESH_CUBE];
 for (var i=0;i<meshes.length;i++){
     var gameObject = engine.activeScene.createGameObject();
     gameObject.transform.position = [-2.0+4*i,0,0];
     var meshRenderer = new kick.scene.MeshRenderer();
     meshRenderer.mesh = engine.project.load(meshes[i]);
     meshRenderer.material = material;
     gameObject.addComponent(meshRenderer);
     var rotationSpeed = i-0.4;
     gameObject.addComponent(new RotatorComponent({rotationSpeed:rotationSpeed}));
 }