Android Open Source - Roll-Ball-Roll Game Running State






From Project

Back to project page Roll-Ball-Roll.

License

The source code is released under:

GNU General Public License

If you think the Android project Roll-Ball-Roll listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * Copyright (c) 2014 Lewis Chun/*w w  w. j a  v  a 2s.  c o  m*/
 * Android game in which the user controls a ball to get a high score.
 *
 * This file is part of Roll Ball Roll.
 *
 * Roll Ball Roll is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.zwac035.finalprogram;

import com.zwac035.finalprogram.box.BoxControl;
import com.zwac035.finalprogram.managers.ManagerFacade;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.collision.CollisionResults;
import com.jme3.font.BitmapText;
import com.jme3.input.controls.TouchListener;
import com.jme3.input.event.TouchEvent;
import static com.jme3.input.event.TouchEvent.Type.DOWN;
import static com.jme3.input.event.TouchEvent.Type.FLING;
import static com.jme3.input.event.TouchEvent.Type.MOVE;
import static com.jme3.input.event.TouchEvent.Type.UP;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.ui.Picture;
import java.util.concurrent.Callable;

/**
 * The main game class that is responsible for updating everything in the game.
 * @author Lewis Chun
 */
public class GameRunningState extends AbstractAppState implements TouchListener, ForceChangeListener {
    
    /**
     * Accelerometer readings
     */
    private float[] sensorValues = new float[]{0, 0, 0};
    /**
     * Node for all the boxes
     */
    private Node boxesNode;
    /**
     * The managers for the boxes, floor and triangles
     */
    private ManagerFacade manager;
    /**
     * Text in the top right corner, for displaying the score
     */
    private BitmapText scoreText;
    private BitmapText countDownText;
    /**
     * The physics engine
     */
    private BulletAppState bulletAppState;
    /**
     * The state that is active when the game is paused
     */
    private GamePauseState gamePauseState;
    
    private float screenHeight, screenWidth, pictureDim;
    /**
     * The box the user has just touched
     */
    private Geometry heldBox;
    private Camera cam;
    /**
     * This is the distance from the centre of the screen, to the point the floor
     * goes offscreen. 4 floor pieces * the height of a piece.
     */
    private float centerOffset = 4 * 4;
    private Node guiNode;
    private Node mainRootNode;
    private Node rootNode;
    private Node mainGuiNode;
    private boolean justEnabled = false;
    private boolean shouldEnable;
    private SimpleApplication main;
    
    public boolean shouldStop = false, countingDown = false;
    public long timer;
    public float score = 0;
    
    public GameRunningState(boolean enabled){
        shouldEnable = enabled;
    }
    
    @Override
    public void initialize(AppStateManager stateManager, Application app){
        super.initialize(stateManager, app);
        
        main = (SimpleApplication) app;
        rootNode = new Node("RunningRoot");
        cam = main.getCamera();
        mainRootNode = main.getRootNode();
        
        bulletAppState = stateManager.getState(BulletAppState.class);
        gamePauseState = stateManager.getState(GamePauseState.class);
        
        // Set up the floor node and the boxes node
        Node floorNode = new Node();
        Node triangleNode = new Node();
        boxesNode = new Node("Boxes");
        
        manager = new ManagerFacade(boxesNode, floorNode, triangleNode, getPhysics(), false);
        
        // Attach all the objects to the world
        rootNode.attachChild(boxesNode);
        rootNode.attachChild(floorNode);
        rootNode.attachChild(triangleNode);
        
        screenWidth = main.getContext().getSettings().getWidth();
        screenHeight = main.getContext().getSettings().getHeight();
          
        // Set up the GUI   
        guiNode = new Node("RunningGUI");

        // Create the score text
        scoreText = new BitmapText(Res.guiFont, false);
        scoreText.setSize(screenWidth * 0.1f);
        scoreText.setColor(ColorRGBA.White);
        scoreText.setText("0.0");
        scoreText.setLocalTranslation(screenWidth - scoreText.getLineWidth(), screenHeight, 0);
        guiNode.attachChild(scoreText);
        // And the pause button
        Picture pauseButton = Res.pauseButton;
        pictureDim = screenWidth * 0.1f;
        pauseButton.setHeight(pictureDim);
        pauseButton.setWidth(pictureDim);
        pauseButton.setPosition(5, screenHeight - pictureDim - 5);
        guiNode.attachChild(pauseButton);
        
        // Create the count down text
        countDownText = new BitmapText(Res.guiFont, false);
        countDownText.setSize(screenWidth * 0.2f);
        countDownText.setColor(ColorRGBA.Yellow);
        
        mainGuiNode = main.getGuiNode();
        
        if(shouldEnable){
            begin();
        }
        super.setEnabled(shouldEnable);
        
    }
    
    /**
     * Call to start the game
     */
    public void begin(){
        GameCamera.getInstance().reset();
        Player.getInstance().moveTo(0, 0, 1);
        mainGuiNode.attachChild(guiNode);
        mainRootNode.attachChild(rootNode);
        manager.initialise();
        unpause();
    }
    
    public void unpause(){
        super.setEnabled(true);
        bulletAppState.setEnabled(true);
        
        guiNode.attachChild(Res.pauseButton);
        justEnabled = true;
        Res.backgroundMusic.play();
    }
    
    public void pause()  {
        super.setEnabled(false);
        if(this.initialized){
            bulletAppState.setEnabled(false);

            gamePauseState.setEnabled(true);
            // Safely run this on the main thread
            main.enqueue(new Callable<Void>() {
                @Override
                public Void call(){
                    guiNode.detachChild(Res.pauseButton);
                    Res.backgroundMusic.pause();
                    return null;
                }
            });
        }
    }
    
    @Override
    public void update(float tpf) {
        if(isEnabled()){
            // Set the speed of the camera based on how far along it is
            Node centralPoint = GameCamera.getInstance().getCamNode();
            Vector3f screenCenterLocation = centralPoint.getLocalTranslation();
            int hundreds = (int) screenCenterLocation.y / 100;
            if(hundreds < 5){
                int tens = (((int) screenCenterLocation.y) - (hundreds * 100)) / (10 * (hundreds + 1));
                GameCamera.getInstance().setSpeed((1 + ((float) hundreds * 1) + (((float) tens) * 0.1f)));
            }
            RigidBodyControl player = Player.getInstance().getPhysicsControl();
            // Move the player based on the accelerometer readings
            player.applyCentralForce((new Vector3f(sensorValues[0], 
                    sensorValues[1] - (GameCamera.getInstance().getSpeed() / 2), 
                    0)).negateLocal());
            // Test to see if the ball has fallen off the floor
            Vector3f playerLocation = player.getPhysicsLocation();
            if(playerLocation.z < -5){
                // GAME OVER!
                shouldStop = true;
            }
            if(playerLocation.y < screenCenterLocation.y - 9.5){
                if(countingDown){
                    long timeNow = System.currentTimeMillis();
                    int timeLeft = 5 - (((int)(timeNow - timer))/1000);
                    countDownText.setText(Integer.toString(timeLeft));
                    if(timeLeft <= 0){
                        countDownText.setText("");
                        mainGuiNode.detachChild(countDownText);
                        shouldStop = true;
                    }
                } else {
                    countingDown = true;
                    timer = System.currentTimeMillis();
                    countDownText.setText("5");
                    mainGuiNode.attachChild(countDownText);
                }
                float textX = (playerLocation.x + 6) * screenWidth / 12;
                countDownText.setLocalTranslation(textX - (countDownText.getLineWidth()), countDownText.getHeight() + 5, 0);
            } else {
                countingDown = false;
                if(mainGuiNode.hasChild(countDownText)){
                    mainGuiNode.detachChild(countDownText);
                }
            }
            float screenCenterY = screenCenterLocation.y + centerOffset;
            manager.updateManagers(tpf, screenCenterY);
            // Round the location to 2 decimal places, and see if it's a new score
            float newScore = (Math.round(playerLocation.y * 10f))/10f;
            if(newScore > score){
                score = newScore;
                scoreText.setText(score + "");
                scoreText.setLocalTranslation(screenWidth - scoreText.getLineWidth(), screenHeight, 0);
            }
        }
    }
    
    /**
     * Get the physics world used by the physics engine.
     */
    public PhysicsSpace getPhysics(){
        return bulletAppState.getPhysicsSpace();
    }
    
    public void onTouch(String name, TouchEvent event, float tpf) {
        if(isEnabled() && isInitialized()){
            switch(event.getType()){
                case DOWN:
                    // Cast a line into the world and see if it collides with any 
                    // of the nodes in boxesNode
                    CollisionResults results = new CollisionResults();
                    // The line is based of the cameras position and direction
                    Vector3f click3d = cam.getWorldCoordinates(
                        new Vector2f(event.getX(), event.getY()), 0f).clone();
                    Vector3f dir = cam.getWorldCoordinates(
                        new Vector2f(event.getX(), event.getY()), 1f).subtractLocal(click3d).normalizeLocal();
                    Ray ray = new Ray(click3d, dir);
                    boxesNode.collideWith(ray, results);
                    if(results.size() > 0){
                        heldBox = results.getClosestCollision().getGeometry();
                        heldBox.getControl(BoxControl.class).onTouch();
                    }
                    break;
                case MOVE:
                    if(heldBox != null){
                        RigidBodyControl boxControl = heldBox.getControl(RigidBodyControl.class);
                        // Move the box. I need to find a better way of moving it though.
                        if(event.getDeltaY() < 0 && heldBox.getLocalTranslation().z < 2){
                            boxControl.setLinearVelocity(new Vector3f(event.getDeltaX(), event.getDeltaY(), 0));
                        } else {
                            boxControl.setLinearVelocity(new Vector3f(event.getDeltaX(), 0, event.getDeltaY()));
                        }
                    }
                    break;
                case UP:
                    heldBox = null;
                    break;
                case FLING:
                    // Fling means there has been a quick movement before lifting your finger
                    // So I use it to apply a bit of force.
                    if(heldBox != null){
                        heldBox.getControl(RigidBodyControl.class).applyCentralForce(new Vector3f(event.getDeltaX(), 0, event.getDeltaY()));
                    }
                    break;
                case TAP:
                    if(!justEnabled){
                        if(event.getX() < pictureDim + 5 && event.getY() > screenHeight - pictureDim - 5){
                            pause();   
                        }
                    } else {
                        justEnabled = false;
                    }
            }
        }
    }

    public void onNewForce(float[] newForces) {
        sensorValues = newForces;
    }
    
}




Java Source Code List

com.zwac035.finalprogram.Database.java
com.zwac035.finalprogram.EnterNameActivity.java
com.zwac035.finalprogram.FloorType.java
com.zwac035.finalprogram.ForceChangeListener.java
com.zwac035.finalprogram.GameCamera.java
com.zwac035.finalprogram.GamePauseState.java
com.zwac035.finalprogram.GameRunningState.java
com.zwac035.finalprogram.HighScoreScreenActivity.java
com.zwac035.finalprogram.InfoScreenActivity.java
com.zwac035.finalprogram.Level.java
com.zwac035.finalprogram.MainActivity.java
com.zwac035.finalprogram.Main.java
com.zwac035.finalprogram.Player.java
com.zwac035.finalprogram.Res.java
com.zwac035.finalprogram.ShopActivity.java
com.zwac035.finalprogram.StartScreenActivity.java
com.zwac035.finalprogram.TutorialState.java
com.zwac035.finalprogram.box.BoxControl.java
com.zwac035.finalprogram.box.BoxType.java
com.zwac035.finalprogram.box.ExplodingBox.java
com.zwac035.finalprogram.box.HeavyBox.java
com.zwac035.finalprogram.box.MagnetBox.java
com.zwac035.finalprogram.box.NormalBoxControl.java
com.zwac035.finalprogram.box.Triangle.java
com.zwac035.finalprogram.managers.BoxManager.java
com.zwac035.finalprogram.managers.BoxPool.java
com.zwac035.finalprogram.managers.FloorManager.java
com.zwac035.finalprogram.managers.FloorPool.java
com.zwac035.finalprogram.managers.LevelChangeManager.java
com.zwac035.finalprogram.managers.LevelChangeObservable.java
com.zwac035.finalprogram.managers.LevelChangeObserver.java
com.zwac035.finalprogram.managers.LevelManager.java
com.zwac035.finalprogram.managers.ManagerFacade.java
com.zwac035.finalprogram.managers.Manager.java
com.zwac035.finalprogram.managers.TriangleManager.java
com.zwac035.finalprogram.managers.TrianglePool.java