Lesson 7: Animation

Return to the home page

The goal:

Click for full size. Hover over for more details.

Click here to download the code. (If the page opens in the broswer, you can right click on link and click "Save Link As", or right click on the page and click "Save As")

            
        	// most applications will want to extend the SimpleGame class
            import com.jme.app.SimpleGame;
            
            // a vector containing three float numbers;
            //   used to store positions and translations
            import com.jme.math.Vector3f;
            import com.jme.math.Quaternion;
            import com.jme.math.FastMath;
            
            // geometric shapes used in program
            import com.jme.scene.shape.Box;
            
            // use predefined colors and create custom colors
            import com.jme.renderer.ColorRGBA;
            
            // work with basic materials
            import com.jme.scene.state.MaterialState;
            
            // process user input
            import com.jme.input.InputHandler;
            import com.jme.input.KeyInput;
            import com.jme.input.KeyBindingManager;
            import com.jme.input.FirstPersonHandler;
            
            // an internal vertex of the scenegraph tree;
            //  use to group together objects,
            //  apply render settings, which affects all child vertices
            import com.jme.scene.Node;
            import com.jme.scene.Spatial;
            import com.jme.scene.Geometry;
            
            // animate spatials
            import com.jme.animation.SpatialTransformer;
            
            /**
             *   Demonstrate two types of movement:
             *   translation (uses Vectors)
             *   and rotation (using Quaternions).
             */
            public class AnimDemo extends SimpleGame
            {
               // a geometric shape that will be rendered
               Box myBox;
               SpatialTransformer myMover;
            
               public static void main(String[] args)
               {
                   // create an instance of this program
                   AnimDemo app = new AnimDemo();
            
                   // before the main program starts, display the graphics configuration window
                   //   where the user can choose among screen resolution, color depth, and full screen options
                   app.setConfigShowMode(ConfigShowMode.AlwaysShow);
            
                   // The start() method runs simpleInitGame(),
                   //   then starts the game loop: simpleUpdate(), then simpleRender()
                   // To terminate game loop, call finish()
                   app.start();
               }
            
               protected void simpleInitGame()
               {
                   // make the standard cursor visible.
                   org.lwjgl.input.Mouse.setGrabbed(false);
                   // SimpleGame class defaults mouse behavior to rotate view; here we disable this.
                   ((FirstPersonHandler)input).getMouseLookHandler().setEnabled(false);
            
                   // create a material to apply to geometric objects, use objects' default color,
                   //  apply to front and back, and assign rendering to root node
                   MaterialState customMaterial = display.getRenderer().createMaterialState();
                   customMaterial.setColorMaterial(MaterialState.ColorMaterial.AmbientAndDiffuse);
                   customMaterial.setMaterialFace(MaterialState.MaterialFace.FrontAndBack);
                   rootNode.setRenderState(customMaterial);
            
                   myBox = new Box("s", new Vector3f(0,0,0), 1, 1, 1 );
                   myBox.setRandomColors();
                   rootNode.attachChild( myBox );
            
                   buildInput();
            
                   myMover = new SpatialTransformer();
            
                   // parameter: number of spatial objects this transformer will move.
                   myMover = new SpatialTransformer(1);
            
                   // load spatial(s) to be affected into the transformer.
                   // parameters: spatial variable, index in SpatialTransformer (like an array), -1 (always).
                   myMover.setObject( myBox, 0, -1 );
            
                   // describe transformations of each object at each point in time.
                   // parameters: index in SpatialTransformer, time at which this state should be reached,
                   //   and Vector3f||Quaternion||Vector3f (for Position||Rotation||Scale)
                   myMover.setPosition( 0, 0, new Vector3f(0,0,0) );
                   myMover.setRotation( 0, 0, new Quaternion() );
                   myMover.setScale( 0, 0, new Vector3f(1,1,1) );
            
                   // from start until given time, the given transformation will be continuously applied
                   myMover.setPosition( 0, 1, new Vector3f(5,5,5) );
                   myMover.setPosition( 0, 2, new Vector3f(0,0,0) );
                   myMover.setRotation( 0, 2, new Quaternion() );
                   myMover.setRotation( 0, 3, new Quaternion().fromAngleAxis(FastMath.PI / 3, new Vector3f(1,1,1)) );
                   myMover.setScale( 0, 3, new Vector3f(1,1,1) );
                   myMover.setScale( 0, 4, new Vector3f(1,3,1) );
                   myMover.setScale( 0, 5, new Vector3f(3,3,1) );
                   myMover.setScale( 0, 6, new Vector3f(1,1,1) );
                   myMover.setPosition( 0, 6.0f, new Vector3f(0,0,0) );
                   myMover.setPosition( 0, 6.5f, new Vector3f(2,0,0) );
                   myMover.setPosition( 0, 7.0f, new Vector3f(2,2,0) );
                   myMover.setPosition( 0, 7.5f, new Vector3f(0,2,0) );
                   myMover.setPosition( 0, 8.0f, new Vector3f(0,0,0) );
            
                   // automatically generate all of the small, incrimental values not specified above. Makes the animation nice and smooth
                   myMover.interpolateMissing();
                   // choose the object(s) to be controlled by this SpatialTransformer
                   // NOTE: user will not be able to move myBox unless myBox.clearControllers() is called
                   myBox.addController(myMover);
                   // don't start animator until we say so.
                   myMover.setActive(false);
               }
            
               protected void simpleUpdate()
               {
                   try {   Thread.sleep(1000/120);   } // force decrease in frames per second
                   catch (Exception e) {             }
            
                   processInput();
               }
            
               protected void simpleRender()
               {
                   // nothing to add
               }
            
               // create input bindings
               public void buildInput()
               {
                   // remove all pre-existing key assignments
                   // KeyBindingManager.getKeyBindingManager().removeAll();
            
                   KeyBindingManager.getKeyBindingManager().set( "exit", KeyInput.KEY_ESCAPE );
                   KeyBindingManager.getKeyBindingManager().set( "animateBox", KeyInput.KEY_1 );
                   KeyBindingManager.getKeyBindingManager().set( "animatePause", KeyInput.KEY_2 );
                   KeyBindingManager.getKeyBindingManager().set( "animateRestart",  KeyInput.KEY_3 );
                   KeyBindingManager.getKeyBindingManager().set( "animateStats", KeyInput.KEY_4 );
               }
            
               // process input entered since last update.
               public void processInput()
               {
                   // to determine if SpatialTransformer is currently animating
                   //  (because it remains active even when animation sequence has completed)
                   boolean currentlyTransforming =
                   ( myMover.getCurTime() > 0 && myMover.getCurTime() < myMover.getMaxTime() );
            
                   if (KeyBindingManager.getKeyBindingManager().isValidCommand("animateBox", false))
                       myMover.setActive(true);
            
                   if (KeyBindingManager.getKeyBindingManager().isValidCommand("animatePause", false))
                       myMover.setActive( !myMover.isActive() );
            
                   if (KeyBindingManager.getKeyBindingManager().isValidCommand("animateRestart", false))
                       myMover.setCurTime( 0 );
            
                   if (KeyBindingManager.getKeyBindingManager().isValidCommand("animateStats", false))
                   {
                       System.out.println("Animator time:   " + myMover.getCurTime() );
                       System.out.println("Animator active? " + myMover.isActive() );
                   }
               }
            }
     

Return to the home page