Implementing the player and alien models

The player model is implemented with the PlayerModel class, and the alien model with the AlienModel class.

PlayerModel

The most important part of the PlayerModel class is the camera that represents the player's view. This camera is used when the MIDlet is to be drawn on the screen.

To implement the player model:

  1. In the PlayerModel class constructor, initialize the camera and group, and set them up so that they are ready to use.

        public PlayerModel(int width, int height) {
            cam = new Camera();
            float aspectRatio = ((float) width) / ((float) height);
            cam.setPerspective(70.0f, aspectRatio, 0.1f, 50.0f);
            cam.postRotate(-2.0f, 1.0f, 0, 0); // apply x-axis rotations to camera
            // transGroup handles both camera translation and y-axis rotations
            transGroup = new Group(); // no initial rotation
            trans.postTranslate(X_POS, Y_POS, Z_POS);
            transGroup.setTransform(trans);
            transGroup.addChild(cam);
            // store initial rotation
            yAngle = 0.0f;
        }
  2. Use the updatePosition and updateRotation methods to keep the camera in the right place and looking in the right direction.

        public void updatePosition() {
            if (upPressed || downPressed) {
                updateMove();
            }
            else if (leftPressed || rightPressed) {
                updateRotation();
            }
        }
    
        // ...
    
        private void updateRotation() {
            if (leftPressed) { // rotate left around the y-axis
                rotTrans.postRotate(ANGLE_INCR, 0, 1.0f, 0);
                yAngle += ANGLE_INCR;
            }
            else { // rotate right around the y-axis
                rotTrans.postRotate(-ANGLE_INCR, 0, 1.0f, 0);
                yAngle -= ANGLE_INCR;
            }
    
            // angle values are modulo 360 degrees
            if (yAngle >= 360.0f) {
                yAngle -= 360.0f;
            }
            else if (yAngle <= -360.0f) {
                yAngle += 360.0f;
            }
    
            // apply the y-axis rotation to transGroup
            storePosition();
            trans.setIdentity();
            trans.postTranslate(xCoord, yCoord, zCoord);
            trans.postRotate(yAngle, 0, 1.0f, 0);
            transGroup.setTransform(trans);
        }

AlienModel

The AlienModel class creates VertexBuffer , IndexBuffer , and Appearance objects, and combines them into a Mesh object that represents an alien.

To implement the alien model:

  1. Use the makeGeometry method to return the VertexBuffer.

        private static VertexBuffer makeGeometry() {
            //         create vertices
            short[] verts = getVerts();
            VertexArray va = new VertexArray(verts.length / 3, 3, 2);
            va.set(0, verts.length / 3, verts);
    
            // create normals
            byte[] norms = getNormals();
            VertexArray normArray = new VertexArray(norms.length / 3, 3, 1);
            normArray.set(0, norms.length / 3, norms);
    
            // create texture coordinates
            short[] tcs = getTexCoordsRev();
            VertexArray texArray = new VertexArray(tcs.length / 2, 2, 2);
            texArray.set(0, tcs.length / 2, tcs);
    
            float[] pbias = {(1.0f / 255.0f), (1.0f / 255.0f), (1.0f / 255.0f)};
    
            VertexBuffer vertexB = new VertexBuffer();
            vertexB.setPositions(va, (2.0f / 255.0f), pbias); // scale, bias
            vertexB.setNormals(normArray);
            vertexB.setTexCoords(0, texArray, (1.0f / 255.0f), null);
    
            return vertexB;
    
        } // end of makeGeometry()
  2. In the AlienModel class constructor, combine the objects into a Mesh object.

        public AlienModel(float xCoord, float zCoord) {
            model = new Mesh(vb, ib, app);
            model.setTranslation(xCoord + 0.25f, 0.25f, zCoord + 0.25f);
            model.scale(0.5f, 0.5f, 0.5f);
            model.setPickingEnable(true); // so can fire a pick ray at it
            // translation group for the model
            transGroup = new Group();
            transGroup.addChild(model);
            transGroup.addAnimationTrack(setUpAnimation());
        }
  3. To make the aliens move around, use a KeyframeSequence object. This is used to establish the key frames for the animation and make it move around in a circle. The translateFrames method sets up a KeyframeSequence with 8 frames, each frame taking 10 time units. Then the coordinates are set up to describe a circle of the 0.5f radius, centered in the origin on the XZ plane. A spline is used to interpolate between the points to create the circular movement.

        private KeyframeSequence translateFrames() {
            KeyframeSequence ks = new KeyframeSequence(8, 3,
                                                       KeyframeSequence.SPLINE);
    
            // move clockwise in a circle;
            // each frame is separated by 10 sequence time units
            ks.setKeyframe(0, 0, new float[]{-0.5f, 0.0f, 0.0f});
            ks.setKeyframe(1, 10, new float[]{-0.3536f, 0.0f, 0.3536f});
            ks.setKeyframe(2, 20, new float[]{0.0f, 0.0f, 0.5f});
            ks.setKeyframe(3, 30, new float[]{0.3536f, 0.0f, 0.3536f});
            ks.setKeyframe(4, 40, new float[]{0.5f, 0.0f, 0.0f});
            ks.setKeyframe(5, 50, new float[]{0.3536f, 0.0f, -0.3536f});
            ks.setKeyframe(6, 60, new float[]{0.0f, 0.0f, -0.5f});
            ks.setKeyframe(7, 70, new float[]{-0.3536f, 0.0f, -0.3536f});
    
            ks.setDuration(80); // one cycle takes 80 sequence time units
            ks.setValidRange(0, 7);
            ks.setRepeatMode(KeyframeSequence.LOOP);
            return ks;
        }
  4. Use the setUpAnimation method to create the AnimationController and AnimationTrack objects to which the alien model can be attached.

        private AnimationTrack setUpAnimation() {
            // creation animation controller
            AnimationController animController = new AnimationController();
            animController.setActiveInterval(0, 0);
    
            // creation translation animation track
            KeyframeSequence transKS = translateFrames();
            AnimationTrack transTrack = new AnimationTrack(transKS,
                                                           AnimationTrack.TRANSLATION);
            transTrack.setController(animController);
    
            return transTrack;
        }