Package com.rim.samples.device.openglspritegamedemo

Source Code of com.rim.samples.device.openglspritegamedemo.SpriteGameGLField

/*
* SpriteGameGLField.java
*
* Copyright � 1998-2011 Research In Motion Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Note: For the sake of simplicity, this sample application may not leverage
* resource bundles and resource strings.  However, it is STRONGLY recommended
* that application developers make use of the localization features available
* within the BlackBerry development platform to ensure a seamless application
* experience across a variety of languages and geographies.  For more information
* on localizing your application, please refer to the BlackBerry Java Development
* Environment Development Guide associated with this release.
*/

package com.rim.samples.device.openglspritegamedemo;

import javax.microedition.khronos.opengles.GL;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

import net.rim.device.api.animation.AbstractAnimation;
import net.rim.device.api.animation.Animation;
import net.rim.device.api.animation.AnimationListener;
import net.rim.device.api.animation.Animator;
import net.rim.device.api.math.Matrix4f;
import net.rim.device.api.math.Transform3D;
import net.rim.device.api.math.Vector3f;
import net.rim.device.api.opengles.GL20;
import net.rim.device.api.opengles.GLField;
import net.rim.device.api.system.Characters;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Keypad;
import net.rim.device.api.ui.TouchEvent;
import net.rim.device.api.ui.TouchGesture;
import net.rim.device.api.util.TimeSource;

/**
* The GLField which renders the current level and handles the animations and
* any keyboard or touch events.
*/
public class SpriteGameGLField extends GLField implements AnimationListener {
    /** Holds the game's current level */
    private SpriteGameLevel _level;

    /** Holds the win sprite */
    private final Sprite _win;

    /** Holds the win animation */
    private final Animation _winAnimation;

    /** Holds whether or not the win sprite should be rendered */
    private boolean _renderWin = false;

    /** Holds the lose sprite */
    private final Sprite _lose;

    /** Holds the lose animation */
    private final Animation _loseAnimation;

    /** Holds whether or not the lose sprite should be rendered */
    private boolean _renderLose = false;

    /** Holds the modelview matrix. Specific to GL20 version */
    private Matrix4f _modelview;

    /** Holds the projection matrix. Specific to GL20 version */
    private Matrix4f _projection;

    /** Holds the current level */
    private int _currentLevel = 0;

    /** Holds the version of GL being used */
    private final int _glVersion;

    /** A translation vector */
    Vector3f _t = new Vector3f();

    /** Holds the animator used to update the obstacle animations */
    private final Animator _animator;

    /** Holds whether the sprite should be moving left */
    private boolean _moveLeft;

    /** Holds whether the sprite should be moving right */
    private boolean _moveRight;

    /** Holds the list of levels */
    private final String[] _levelNames = { "/levelone.xml", "/leveltwo.xml" };

    /** Time source used for animator and to calculate elapsed time */
    private final TimeSource _timeSource;

    /** Time value used in calculating elapsed time between updates */
    private long _prevTime;

    /**
     * Constructor for the SpriteGameGLField
     *
     * @param glVersion
     *            The version of OpenGL to use
     */
    SpriteGameGLField(final int glVersion) {
        super(glVersion);

        _glVersion = glVersion;

        final Vector3f translation = new Vector3f(-40.0f, -4.0f, 0.0f);

        // Set up the win sprite
        _win = new Sprite("win.png");
        _win._transform.setScale(new Vector3f(5.0f, 5.0f, 5.0f));
        _win._transform.setTranslation(translation);

        // Set up the lose sprite
        _lose = new Sprite("lose.png");
        _lose._transform.setScale(new Vector3f(5.0f, 5.0f, 5.0f));
        _lose._transform.setTranslation(translation);

        _timeSource = new TimeSource();
        _timeSource.start();
        _animator = new Animator(0, _timeSource);

        // Set up the win animation
        _winAnimation =
                _animator.addAnimation(_win._transform,
                        Transform3D.ANIMATION_PROPERTY_TRANSLATE, 4,
                        new float[] { 0.0f, 0.2f, 0.8f, 1.0f }, 0, new float[] {
                                -40.0f, -4.0f, 0.0f, 0.0f, -4.0f, 0.0f, 0.0f,
                                -4.0f, 0.0f, 20.0f, -4.0f, 0.0f }, 0,
                        Animation.EASINGCURVE_LINEAR, 1750L);
        _winAnimation.setRepeatCount(1);
        _winAnimation.setListener(this);

        // set up the lose animation
        _loseAnimation =
                _animator.addAnimation(_lose._transform,
                        Transform3D.ANIMATION_PROPERTY_TRANSLATE, 4,
                        new float[] { 0.0f, 0.2f, 0.8f, 1.0f }, 0, new float[] {
                                -40.0f, -4.0f, 0.0f, 0.0f, -4.0f, 0.0f, 0.0f,
                                -4.0f, 0.0f, 20.0f, -4.0f, 0.0f }, 0,
                        Animation.EASINGCURVE_LINEAR, 1750L);
        _loseAnimation.setRepeatCount(1);
        _loseAnimation.setListener(this);

        loadLevel();
    }

    /**
     * @see net.rim.device.api.ui.Field#layout(int, int)
     */
    protected void layout(final int width, final int height) {
        setExtent(width, height);
    }

    /**
     * @see GLField#initialize(GL)
     */
    protected void initialize(final GL gl) {
        // Determine what version of OpenGL we are using
        // and call the corresponding initialize() method.
        if (_glVersion == GLField.VERSION_1_1) {
            initialize((GL11) gl);
        } else {
            initialize((GL20) gl);
        }

        setTargetFrameRate(70);
    }

    /**
     * Initialize method for OpenGL v1.1
     *
     * @param gl
     *            The OpenGL 1.1 object that will be initialized
     */
    private void initialize(final GL11 gl) {
        // Set up the GL11 object
        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glClearColor(0.35f, 0.67f, 1.0f, 1.0f);
        gl.glEnable(GL10.GL_NORMALIZE);
        gl.glEnable(GL10.GL_CULL_FACE);
        gl.glEnable(GL10.GL_COLOR_MATERIAL);
        gl.glShadeModel(GL10.GL_SMOOTH);
        gl.glDisable(GL10.GL_DITHER);
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

        // Set up the orthographic (2D) projection matrix
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glOrthof(-12.0f, 12.0f, -10.0f, 20.0f * Display.getHeight()
                / Display.getWidth() - 10.0f, -1.0f, 1.0f);

        _win.initialize(gl);
        _lose.initialize(gl);
    }

    /**
     * Initialize method for OpenGL v2.0
     *
     * @param gl
     *            The OpenGL 2.0 object that will be initialized
     */
    private void initialize(final GL20 gl) {
        _modelview = new Matrix4f();
        _projection = new Matrix4f();

        // Set up the GL20 object
        gl.glClearColor(0.35f, 0.67f, 1.0f, 1.0f);
        gl.glEnable(GL20.GL_CULL_FACE);
        gl.glDisable(GL20.GL_DITHER);
        gl.glEnable(GL20.GL_BLEND);
        gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);

        // Load the shader used for rendering
        Sprite.loadShader(gl);

        // Set up the orthographic (2D) projection matrix
        Matrix4f.createOrthographic(-12.0f, 12.0f, -10.0f, 20.0f
                * Display.getHeight() / Display.getWidth() - 10.0f, -1.0f,
                10.0f, _projection);

        _win.initialize(gl);
        _lose.initialize(gl);
    }

    /**
     * @see GLField#update()
     */
    protected void update() {
        _animator.update();

        // Get amount of time last frame took, in seconds
        final float elapsedTime = (_timeSource.getTime() - _prevTime) / 1000.0f;
        _prevTime = _timeSource.getTime();

        // Process input (Note: touch events are also set up to add
        // these keys to the array).
        if (_moveLeft) {
            _level.getCharacter().move(-elapsedTime * 60);
        }

        if (_moveRight) {
            _level.getCharacter().move(elapsedTime * 60);
        }

        int result = 0;

        // Update the level
        if (!_renderWin || !_renderLose) {
            result = _level.update();
        }

        // The level has been won, so begin the win animation
        if (result == SpriteGameLevel.LEVEL_WIN && !_renderWin) {
            _winAnimation.begin(0L);
        }

        // The level has been lost, so begin the lose animation
        else if (result == SpriteGameLevel.LEVEL_LOSE) {
            _level.getCharacter().reset();
            _loseAnimation.begin(0L);
        }
    }

    /**
     * @see GLField#render(GL)
     */
    protected void render(final GL gl) {
        // Determine what OpenGL version to use
        // and call the corresponding render() method.
        if (gl instanceof GL20) {
            render((GL20) gl);
        } else {
            render((GL11) gl);
        }
    }

    /**
     * Render method for OpenGL v1.1
     *
     * @param gl
     *            The OpenGL v1.1 object that will be used to render
     */
    private void render(final GL11 gl) {
        if (!_level.isLevelLoaded()) {
            return;
        }

        if (!_level.isLevelInitialized()) {
            _level.initialize(gl);
        }

        // Clear the color and depth buffers
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        // Clear the modelview matrix
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();

        // Translate to the correct location
        gl.glTranslatef(0.0f, 0.0f, -1.0f);

        // Render the level.
        _level.render(gl);

        // If the win or lose animations are running, render the corresponding
        // sprite
        if (_renderWin) {
            _win.render(gl);
        }

        if (_renderLose) {
            _lose.render(gl);
        }
    }

    /**
     * Render method for OpenGL v2.0
     *
     * @param gl
     *            The OpenGL 2.0 object that will be used to render
     */
    private void render(final GL20 gl) {
        if (!_level.isLevelLoaded()) {
            return;
        }

        if (!_level.isLevelInitialized()) {
            _level.initialize(gl);
        }

        // Clear the color and depth buffers
        gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);

        // Load the shader program
        gl.glUseProgram(Sprite.getProgram());

        // Load the projection matrix
        gl.glUniformMatrix4fv(Sprite.getProjectionMatrixLocation(), 1, false,
                _projection.getArray(), 0);

        // Render the level
        _level.render(gl, _modelview);

        // If the win or lose animations are running, render the corresponding
        // sprite
        if (_renderWin) {
            _win.render(gl, _modelview);
        }

        if (_renderLose) {
            _lose.render(gl, _modelview);
        }
    }

    /**
     * Loads the current level
     */
    private void loadLevel() {
        _level = new SpriteGameLevel(_levelNames[_currentLevel], _animator);

        _currentLevel++;

        if (_currentLevel >= _levelNames.length) {
            _currentLevel = 0;
        }
    }

    /**
     * @see net.rim.device.api.animation.AnimationListener#animationBegin(AbstractAnimation)
     */
    public void animationBegin(final AbstractAnimation animation) {
        if (animation == _winAnimation) {
            _renderWin = true;
        } else if (animation == _loseAnimation) {
            _renderLose = true;
        }
    }

    /**
     * @see net.rim.device.api.animation.AnimationListener#animationEnd(AbstractAnimation)
     */
    public void animationEnd(final AbstractAnimation animation) {
        if (animation == _winAnimation) {
            _renderWin = false;
            loadLevel();
        } else if (animation == _loseAnimation) {
            _renderLose = false;
        }
    }

    /**
     * @see net.rim.device.api.ui.Field#keyDown(int, int)
     */
    protected boolean keyDown(final int keycode, final int time) {
        final StringBuffer sb = new StringBuffer();

        // Retrieve the characters mapped to the keycode for the current
        // keyboard layout
        Keypad.getKeyChars(keycode, sb);

        if (sb.toString().indexOf('q') != -1) {
            _moveLeft = true;
        }

        if (sb.toString().indexOf('w') != -1) {
            _moveRight = true;
        }

        return false;
    }

    /**
     * @see net.rim.device.api.ui.Field#keyUp(int, int)
     */
    protected boolean keyUp(final int keycode, final int time) {
        final StringBuffer sb = new StringBuffer();

        // Retrieve the characters mapped to the keycode for the current
        // keyboard layout
        Keypad.getKeyChars(keycode, sb);

        if (sb.toString().indexOf('q') != -1) {
            _moveLeft = false;
        }
        if (sb.toString().indexOf('w') != -1) {
            _moveRight = false;
        }

        return false;
    }

    /**
     * @see net.rim.device.api.ui.Field#keyChar(char, int, int)
     */
    protected boolean keyChar(final char c, final int status, final int time) {
        switch (c) {
        case Characters.SPACE:
            _level.getCharacter().jump();
            return true;
        case Characters.LATIN_SMALL_LETTER_S:
            _level.getCharacter().shrink();
            return true;
        case Characters.ESCAPE:
        default:
            return false;
        }
    }

    /**
     * @see net.rim.device.api.ui.Field#navigationClick(int, int)
     */
    protected boolean navigationClick(final int status, final int time) {
        _level.getCharacter().jump();
        return true;
    }

    /**
     * @see net.rim.device.api.ui.Field#navigationMovement(int, int, int, int)
     */
    protected boolean navigationMovement(final int dx, final int dy,
            final int status, final int time) {
        _level.getCharacter().move(dx * 4);
        return true;
    }

    /**
     * @see net.rim.device.api.ui.Field#touchEvent(TouchEvent)
     */
    protected boolean touchEvent(final TouchEvent message) {
        if (message == null) {
            return false;
        }

        boolean tappedCenter = false;

        switch (message.getEvent()) {
        case TouchEvent.GESTURE: {
            final TouchGesture gesture = message.getGesture();

            if (gesture.getEvent() == TouchGesture.SWIPE) {
                final int direction = gesture.getSwipeDirection();
                if (direction == TouchGesture.SWIPE_NORTH
                        || direction == TouchGesture.SWIPE_SOUTH) {
                    // Swipe up or down to shrink or grow
                    _level.getCharacter().shrink();
                }
            }

            break;
        }
        case TouchEvent.DOWN: {
            final int x = message.getX(1);
            final int x2 = message.getX(2);

            // Touch with two fingers to jump. Note: can tap the screen
            // while moving in a direction to jump while moving.
            if (x2 != -1) {
                _level.getCharacter().jump();
            } else {
                final int displayWidth = Display.getWidth();

                // Touch the left or right quarter of the
                // screen to move in that direction.
                if (x < displayWidth / 4) {
                    _moveLeft = true;
                } else if (x > displayWidth - displayWidth / 4) {
                    _moveRight = true;
                } else {
                    tappedCenter = true;
                }
            }

            break;
        }

        case TouchEvent.UP: {
            final int x = message.getX(1);

            // Release the first finger that went down to stop moving
            if (x != -1) {
                _moveLeft = false;
                _moveRight = false;
            }

            // Jump if the middle of the screen was tapped
            if (tappedCenter) {
                _level.getCharacter().jump();
            }

            break;
        }
        }

        return true;
    }
}
TOP

Related Classes of com.rim.samples.device.openglspritegamedemo.SpriteGameGLField

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.