You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
414 lines
14 KiB
414 lines
14 KiB
/*
|
|
* Copyright (c) 2009-2010 jMonkeyEngine
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
package jme3game.cubefield;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import com.jme3.app.SimpleApplication;
|
|
import com.jme3.bounding.BoundingVolume;
|
|
import com.jme3.font.BitmapFont;
|
|
import com.jme3.font.BitmapText;
|
|
import com.jme3.input.KeyInput;
|
|
import com.jme3.input.controls.AnalogListener;
|
|
import com.jme3.input.controls.KeyTrigger;
|
|
import com.jme3.material.Material;
|
|
import com.jme3.math.ColorRGBA;
|
|
import com.jme3.math.FastMath;
|
|
import com.jme3.math.Quaternion;
|
|
import com.jme3.math.Vector3f;
|
|
import com.jme3.scene.Geometry;
|
|
import com.jme3.scene.Node;
|
|
import com.jme3.scene.Spatial.CullHint;
|
|
import com.jme3.scene.shape.Box;
|
|
import com.jme3.scene.shape.Dome;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
|
|
/**
|
|
* @author Kyle "bonechilla" Williams
|
|
*/
|
|
public class CubeField extends SimpleApplication implements AnalogListener {
|
|
|
|
public static void main(String[] args) {
|
|
CubeField app = new CubeField();
|
|
app.start();
|
|
}
|
|
|
|
private BitmapFont defaultFont;
|
|
|
|
private boolean START;
|
|
private int difficulty, Score, colorInt, highCap, lowCap,diffHelp;
|
|
private Node player;
|
|
private Geometry fcube;
|
|
private ArrayList<Geometry> cubeField;
|
|
private ArrayList<ColorRGBA> obstacleColors;
|
|
private float speed, coreTime,coreTime2;
|
|
private float camAngle = 0;
|
|
private BitmapText fpsScoreText, pressStart;
|
|
|
|
private boolean solidBox = true;
|
|
private Material playerMaterial;
|
|
private Material floorMaterial;
|
|
|
|
private float fpsRate = 1000f / 1f;
|
|
|
|
/**
|
|
* Initializes game
|
|
*/
|
|
@Override
|
|
public void simpleInitApp() {
|
|
Logger.getLogger("com.jme3").setLevel(Level.WARNING);
|
|
|
|
flyCam.setEnabled(false);
|
|
statsView.setCullHint(CullHint.Always);
|
|
|
|
Keys();
|
|
|
|
defaultFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
|
|
pressStart = new BitmapText(defaultFont, false);
|
|
fpsScoreText = new BitmapText(defaultFont, false);
|
|
|
|
loadText(fpsScoreText, "Current Score: 0", defaultFont, 0, 2, 0);
|
|
loadText(pressStart, "PRESS ENTER", defaultFont, 0, 5, 0);
|
|
|
|
player = createPlayer();
|
|
rootNode.attachChild(player);
|
|
cubeField = new ArrayList<Geometry>();
|
|
obstacleColors = new ArrayList<ColorRGBA>();
|
|
|
|
gameReset();
|
|
}
|
|
/**
|
|
* Used to reset cubeField
|
|
*/
|
|
private void gameReset(){
|
|
Score = 0;
|
|
lowCap = 10;
|
|
colorInt = 0;
|
|
highCap = 40;
|
|
difficulty = highCap;
|
|
|
|
for (Geometry cube : cubeField){
|
|
cube.removeFromParent();
|
|
}
|
|
cubeField.clear();
|
|
|
|
if (fcube != null){
|
|
fcube.removeFromParent();
|
|
}
|
|
fcube = createFirstCube();
|
|
|
|
obstacleColors.clear();
|
|
obstacleColors.add(ColorRGBA.Orange);
|
|
obstacleColors.add(ColorRGBA.Red);
|
|
obstacleColors.add(ColorRGBA.Yellow);
|
|
renderer.setBackgroundColor(ColorRGBA.White);
|
|
speed = lowCap / 400f;
|
|
coreTime = 20.0f;
|
|
coreTime2 = 10.0f;
|
|
diffHelp=lowCap;
|
|
player.setLocalTranslation(0,0,0);
|
|
}
|
|
|
|
@Override
|
|
public void simpleUpdate(float tpf) {
|
|
camTakeOver(tpf);
|
|
if (START){
|
|
gameLogic(tpf);
|
|
}
|
|
colorLogic();
|
|
}
|
|
/**
|
|
* Forcefully takes over Camera adding functionality and placing it behind the character
|
|
* @param tpf Tickes Per Frame
|
|
*/
|
|
private void camTakeOver(float tpf) {
|
|
cam.setLocation(player.getLocalTranslation().add(-8, 2, 0));
|
|
cam.lookAt(player.getLocalTranslation(), Vector3f.UNIT_Y);
|
|
|
|
Quaternion rot = new Quaternion();
|
|
rot.fromAngleNormalAxis(camAngle, Vector3f.UNIT_Z);
|
|
cam.setRotation(cam.getRotation().mult(rot));
|
|
camAngle *= FastMath.pow(.99f, fpsRate * tpf);
|
|
}
|
|
|
|
@Override
|
|
public void requestClose(boolean esc) {
|
|
if (!esc){
|
|
System.out.println("The game was quit.");
|
|
}else{
|
|
System.out.println("Player has Collided. Final Score is " + Score);
|
|
}
|
|
context.destroy(false);
|
|
}
|
|
/**
|
|
* Randomly Places a cube on the map between 30 and 90 paces away from player
|
|
*/
|
|
private void randomizeCube() {
|
|
Geometry cube = fcube.clone();
|
|
int playerX = (int) player.getLocalTranslation().getX();
|
|
int playerZ = (int) player.getLocalTranslation().getZ();
|
|
// float x = FastMath.nextRandomInt(playerX + difficulty + 10, playerX + difficulty + 150);
|
|
float x = FastMath.nextRandomInt(playerX + difficulty + 30, playerX + difficulty + 90);
|
|
float z = FastMath.nextRandomInt(playerZ - difficulty - 50, playerZ + difficulty + 50);
|
|
cube.getLocalTranslation().set(x, 0, z);
|
|
|
|
// playerX+difficulty+30,playerX+difficulty+90
|
|
|
|
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
|
if (!solidBox){
|
|
mat.getAdditionalRenderState().setWireframe(true);
|
|
}
|
|
mat.setColor("Color", obstacleColors.get(FastMath.nextRandomInt(0, obstacleColors.size() - 1)));
|
|
cube.setMaterial(mat);
|
|
|
|
rootNode.attachChild(cube);
|
|
cubeField.add(cube);
|
|
}
|
|
|
|
private Geometry createFirstCube() {
|
|
Vector3f loc = player.getLocalTranslation();
|
|
loc.addLocal(4, 0, 0);
|
|
Box b = new Box(loc, 1, 1, 1);
|
|
|
|
Geometry geom = new Geometry("Box", b);
|
|
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
|
mat.setColor("Color", ColorRGBA.Blue);
|
|
geom.setMaterial(mat);
|
|
|
|
return geom;
|
|
}
|
|
|
|
private Node createPlayer() {
|
|
Dome b = new Dome(Vector3f.ZERO, 10, 100, 1);
|
|
Geometry playerMesh = new Geometry("Box", b);
|
|
|
|
playerMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
|
playerMaterial.setColor("Color", ColorRGBA.Red);
|
|
playerMesh.setMaterial(playerMaterial);
|
|
playerMesh.setName("player");
|
|
|
|
Box floor = new Box(Vector3f.ZERO.add(playerMesh.getLocalTranslation().getX(),
|
|
playerMesh.getLocalTranslation().getY() - 1, 0), 100, 0, 100);
|
|
Geometry floorMesh = new Geometry("Box", floor);
|
|
|
|
floorMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
|
floorMaterial.setColor("Color", ColorRGBA.LightGray);
|
|
floorMesh.setMaterial(floorMaterial);
|
|
floorMesh.setName("floor");
|
|
|
|
Node playerNode = new Node();
|
|
playerNode.attachChild(playerMesh);
|
|
playerNode.attachChild(floorMesh);
|
|
|
|
return playerNode;
|
|
}
|
|
|
|
/**
|
|
* If Game is Lost display Score and Reset the Game
|
|
*/
|
|
private void gameLost(){
|
|
START = false;
|
|
loadText(pressStart, "You lost! Press enter to try again.", defaultFont, 0, 5, 0);
|
|
gameReset();
|
|
}
|
|
|
|
/**
|
|
* Core Game Logic
|
|
*/
|
|
private void gameLogic(float tpf){
|
|
//Subtract difficulty level in accordance to speed every 10 seconds
|
|
if(timer.getTimeInSeconds()>=coreTime2){
|
|
coreTime2=timer.getTimeInSeconds()+10;
|
|
if(difficulty<=lowCap){
|
|
difficulty=lowCap;
|
|
}
|
|
else if(difficulty>lowCap){
|
|
difficulty-=5;
|
|
diffHelp+=1;
|
|
}
|
|
}
|
|
|
|
if(speed<.1f){
|
|
speed+=.000001f*tpf*fpsRate;
|
|
}
|
|
|
|
player.move(speed * tpf * fpsRate, 0, 0);
|
|
if (cubeField.size() > difficulty){
|
|
cubeField.remove(0);
|
|
}else if (cubeField.size() != difficulty){
|
|
randomizeCube();
|
|
}
|
|
|
|
if (cubeField.isEmpty()){
|
|
requestClose(false);
|
|
}else{
|
|
for (int i = 0; i < cubeField.size(); i++){
|
|
|
|
//better way to check collision
|
|
Geometry playerModel = (Geometry) player.getChild(0);
|
|
Geometry cubeModel = cubeField.get(i);
|
|
cubeModel.updateGeometricState();
|
|
|
|
BoundingVolume pVol = playerModel.getWorldBound();
|
|
BoundingVolume vVol = cubeModel.getWorldBound();
|
|
|
|
if (pVol.intersects(vVol)){
|
|
gameLost();
|
|
return;
|
|
}
|
|
//Remove cube if 10 world units behind player
|
|
if (cubeField.get(i).getLocalTranslation().getX() + 10 < player.getLocalTranslation().getX()){
|
|
cubeField.get(i).removeFromParent();
|
|
cubeField.remove(cubeField.get(i));
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
Score += fpsRate * tpf;
|
|
fpsScoreText.setText("Current Score: "+Score);
|
|
}
|
|
/**
|
|
* Sets up the keyboard bindings
|
|
*/
|
|
private void Keys() {
|
|
inputManager.addMapping("START", new KeyTrigger(KeyInput.KEY_RETURN));
|
|
inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_LEFT));
|
|
inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_RIGHT));
|
|
inputManager.addListener(this, "START", "Left", "Right");
|
|
}
|
|
|
|
public void onAnalog(String binding, float value, float tpf) {
|
|
if (binding.equals("START") && !START){
|
|
START = true;
|
|
guiNode.detachChild(pressStart);
|
|
System.out.println("START");
|
|
}else if (START == true && binding.equals("Left")){
|
|
player.move(0, 0, -(speed / 2f) * value * fpsRate);
|
|
camAngle -= value*tpf;
|
|
}else if (START == true && binding.equals("Right")){
|
|
player.move(0, 0, (speed / 2f) * value * fpsRate);
|
|
camAngle += value*tpf;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Determines the colors of the player, floor, obstacle and background
|
|
*/
|
|
private void colorLogic() {
|
|
if (timer.getTimeInSeconds() >= coreTime){
|
|
|
|
colorInt++;
|
|
coreTime = timer.getTimeInSeconds() + 20;
|
|
|
|
|
|
switch (colorInt){
|
|
case 1:
|
|
obstacleColors.clear();
|
|
solidBox = false;
|
|
obstacleColors.add(ColorRGBA.Green);
|
|
renderer.setBackgroundColor(ColorRGBA.Black);
|
|
playerMaterial.setColor("Color", ColorRGBA.White);
|
|
floorMaterial.setColor("Color", ColorRGBA.Black);
|
|
break;
|
|
case 2:
|
|
obstacleColors.set(0, ColorRGBA.Black);
|
|
solidBox = true;
|
|
renderer.setBackgroundColor(ColorRGBA.White);
|
|
playerMaterial.setColor("Color", ColorRGBA.Gray);
|
|
floorMaterial.setColor("Color", ColorRGBA.LightGray);
|
|
break;
|
|
case 3:
|
|
obstacleColors.set(0, ColorRGBA.Pink);
|
|
break;
|
|
case 4:
|
|
obstacleColors.set(0, ColorRGBA.Cyan);
|
|
obstacleColors.add(ColorRGBA.Magenta);
|
|
renderer.setBackgroundColor(ColorRGBA.Gray);
|
|
floorMaterial.setColor("Color", ColorRGBA.Gray);
|
|
playerMaterial.setColor("Color", ColorRGBA.White);
|
|
break;
|
|
case 5:
|
|
obstacleColors.remove(0);
|
|
renderer.setBackgroundColor(ColorRGBA.Pink);
|
|
solidBox = false;
|
|
playerMaterial.setColor("Color", ColorRGBA.White);
|
|
break;
|
|
case 6:
|
|
obstacleColors.set(0, ColorRGBA.White);
|
|
solidBox = true;
|
|
renderer.setBackgroundColor(ColorRGBA.Black);
|
|
playerMaterial.setColor("Color", ColorRGBA.Gray);
|
|
floorMaterial.setColor("Color", ColorRGBA.LightGray);
|
|
break;
|
|
case 7:
|
|
obstacleColors.set(0, ColorRGBA.Green);
|
|
renderer.setBackgroundColor(ColorRGBA.Gray);
|
|
playerMaterial.setColor("Color", ColorRGBA.Black);
|
|
floorMaterial.setColor("Color", ColorRGBA.Orange);
|
|
break;
|
|
case 8:
|
|
obstacleColors.set(0, ColorRGBA.Red);
|
|
floorMaterial.setColor("Color", ColorRGBA.Pink);
|
|
break;
|
|
case 9:
|
|
obstacleColors.set(0, ColorRGBA.Orange);
|
|
obstacleColors.add(ColorRGBA.Red);
|
|
obstacleColors.add(ColorRGBA.Yellow);
|
|
renderer.setBackgroundColor(ColorRGBA.White);
|
|
playerMaterial.setColor("Color", ColorRGBA.Red);
|
|
floorMaterial.setColor("Color", ColorRGBA.Gray);
|
|
colorInt=0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Sets up a BitmapText to be displayed
|
|
* @param txt the Bitmap Text
|
|
* @param text the
|
|
* @param font the font of the text
|
|
* @param x
|
|
* @param y
|
|
* @param z
|
|
*/
|
|
private void loadText(BitmapText txt, String text, BitmapFont font, float x, float y, float z) {
|
|
txt.setSize(font.getCharSet().getRenderedSize());
|
|
txt.setLocalTranslation(txt.getLineWidth() * x, txt.getLineHeight() * y, z);
|
|
txt.setText(text);
|
|
guiNode.attachChild(txt);
|
|
}
|
|
} |