1 /* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 package jme3test.games; 34 35 import com.jme3.app.SimpleApplication; 36 import com.jme3.bounding.BoundingVolume; 37 import com.jme3.font.BitmapFont; 38 import com.jme3.font.BitmapText; 39 import com.jme3.input.KeyInput; 40 import com.jme3.input.controls.AnalogListener; 41 import com.jme3.input.controls.KeyTrigger; 42 import com.jme3.material.Material; 43 import com.jme3.math.ColorRGBA; 44 import com.jme3.math.FastMath; 45 import com.jme3.math.Quaternion; 46 import com.jme3.math.Vector3f; 47 import com.jme3.scene.Geometry; 48 import com.jme3.scene.Node; 49 import com.jme3.scene.Spatial.CullHint; 50 import com.jme3.scene.shape.Box; 51 import com.jme3.scene.shape.Dome; 52 import java.util.ArrayList; 53 import java.util.logging.Level; 54 import java.util.logging.Logger; 55 56 /** 57 * @author Kyle "bonechilla" Williams 58 */ 59 public class CubeField extends SimpleApplication implements AnalogListener { 60 61 public static void main(String[] args) { 62 CubeField app = new CubeField(); 63 app.start(); 64 } 65 66 private BitmapFont defaultFont; 67 68 private boolean START; 69 private int difficulty, Score, colorInt, highCap, lowCap,diffHelp; 70 private Node player; 71 private Geometry fcube; 72 private ArrayList<Geometry> cubeField; 73 private ArrayList<ColorRGBA> obstacleColors; 74 private float speed, coreTime,coreTime2; 75 private float camAngle = 0; 76 private BitmapText fpsScoreText, pressStart; 77 78 private boolean solidBox = true; 79 private Material playerMaterial; 80 private Material floorMaterial; 81 82 private float fpsRate = 1000f / 1f; 83 84 /** 85 * Initializes game 86 */ 87 @Override 88 public void simpleInitApp() { 89 Logger.getLogger("com.jme3").setLevel(Level.WARNING); 90 91 flyCam.setEnabled(false); 92 setDisplayStatView(false); 93 94 Keys(); 95 96 defaultFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); 97 pressStart = new BitmapText(defaultFont, false); 98 fpsScoreText = new BitmapText(defaultFont, false); 99 100 loadText(fpsScoreText, "Current Score: 0", defaultFont, 0, 2, 0); 101 loadText(pressStart, "PRESS ENTER", defaultFont, 0, 5, 0); 102 103 player = createPlayer(); 104 rootNode.attachChild(player); 105 cubeField = new ArrayList<Geometry>(); 106 obstacleColors = new ArrayList<ColorRGBA>(); 107 108 gameReset(); 109 } 110 /** 111 * Used to reset cubeField 112 */ 113 private void gameReset(){ 114 Score = 0; 115 lowCap = 10; 116 colorInt = 0; 117 highCap = 40; 118 difficulty = highCap; 119 120 for (Geometry cube : cubeField){ 121 cube.removeFromParent(); 122 } 123 cubeField.clear(); 124 125 if (fcube != null){ 126 fcube.removeFromParent(); 127 } 128 fcube = createFirstCube(); 129 130 obstacleColors.clear(); 131 obstacleColors.add(ColorRGBA.Orange); 132 obstacleColors.add(ColorRGBA.Red); 133 obstacleColors.add(ColorRGBA.Yellow); 134 renderer.setBackgroundColor(ColorRGBA.White); 135 speed = lowCap / 400f; 136 coreTime = 20.0f; 137 coreTime2 = 10.0f; 138 diffHelp=lowCap; 139 player.setLocalTranslation(0,0,0); 140 } 141 142 @Override 143 public void simpleUpdate(float tpf) { 144 camTakeOver(tpf); 145 if (START){ 146 gameLogic(tpf); 147 } 148 colorLogic(); 149 } 150 /** 151 * Forcefully takes over Camera adding functionality and placing it behind the character 152 * @param tpf Tickes Per Frame 153 */ 154 private void camTakeOver(float tpf) { 155 cam.setLocation(player.getLocalTranslation().add(-8, 2, 0)); 156 cam.lookAt(player.getLocalTranslation(), Vector3f.UNIT_Y); 157 158 Quaternion rot = new Quaternion(); 159 rot.fromAngleNormalAxis(camAngle, Vector3f.UNIT_Z); 160 cam.setRotation(cam.getRotation().mult(rot)); 161 camAngle *= FastMath.pow(.99f, fpsRate * tpf); 162 } 163 164 @Override 165 public void requestClose(boolean esc) { 166 if (!esc){ 167 System.out.println("The game was quit."); 168 }else{ 169 System.out.println("Player has Collided. Final Score is " + Score); 170 } 171 context.destroy(false); 172 } 173 /** 174 * Randomly Places a cube on the map between 30 and 90 paces away from player 175 */ 176 private void randomizeCube() { 177 Geometry cube = fcube.clone(); 178 int playerX = (int) player.getLocalTranslation().getX(); 179 int playerZ = (int) player.getLocalTranslation().getZ(); 180 // float x = FastMath.nextRandomInt(playerX + difficulty + 10, playerX + difficulty + 150); 181 float x = FastMath.nextRandomInt(playerX + difficulty + 30, playerX + difficulty + 90); 182 float z = FastMath.nextRandomInt(playerZ - difficulty - 50, playerZ + difficulty + 50); 183 cube.getLocalTranslation().set(x, 0, z); 184 185 // playerX+difficulty+30,playerX+difficulty+90 186 187 Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); 188 if (!solidBox){ 189 mat.getAdditionalRenderState().setWireframe(true); 190 } 191 mat.setColor("Color", obstacleColors.get(FastMath.nextRandomInt(0, obstacleColors.size() - 1))); 192 cube.setMaterial(mat); 193 194 rootNode.attachChild(cube); 195 cubeField.add(cube); 196 } 197 198 private Geometry createFirstCube() { 199 Vector3f loc = player.getLocalTranslation(); 200 loc.addLocal(4, 0, 0); 201 Box b = new Box(loc, 1, 1, 1); 202 203 Geometry geom = new Geometry("Box", b); 204 Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); 205 mat.setColor("Color", ColorRGBA.Blue); 206 geom.setMaterial(mat); 207 208 return geom; 209 } 210 211 private Node createPlayer() { 212 Dome b = new Dome(Vector3f.ZERO, 10, 100, 1); 213 Geometry playerMesh = new Geometry("Box", b); 214 215 playerMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); 216 playerMaterial.setColor("Color", ColorRGBA.Red); 217 playerMesh.setMaterial(playerMaterial); 218 playerMesh.setName("player"); 219 220 Box floor = new Box(Vector3f.ZERO.add(playerMesh.getLocalTranslation().getX(), 221 playerMesh.getLocalTranslation().getY() - 1, 0), 100, 0, 100); 222 Geometry floorMesh = new Geometry("Box", floor); 223 224 floorMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); 225 floorMaterial.setColor("Color", ColorRGBA.LightGray); 226 floorMesh.setMaterial(floorMaterial); 227 floorMesh.setName("floor"); 228 229 Node playerNode = new Node(); 230 playerNode.attachChild(playerMesh); 231 playerNode.attachChild(floorMesh); 232 233 return playerNode; 234 } 235 236 /** 237 * If Game is Lost display Score and Reset the Game 238 */ 239 private void gameLost(){ 240 START = false; 241 loadText(pressStart, "You lost! Press enter to try again.", defaultFont, 0, 5, 0); 242 gameReset(); 243 } 244 245 /** 246 * Core Game Logic 247 */ 248 private void gameLogic(float tpf){ 249 //Subtract difficulty level in accordance to speed every 10 seconds 250 if(timer.getTimeInSeconds()>=coreTime2){ 251 coreTime2=timer.getTimeInSeconds()+10; 252 if(difficulty<=lowCap){ 253 difficulty=lowCap; 254 } 255 else if(difficulty>lowCap){ 256 difficulty-=5; 257 diffHelp+=1; 258 } 259 } 260 261 if(speed<.1f){ 262 speed+=.000001f*tpf*fpsRate; 263 } 264 265 player.move(speed * tpf * fpsRate, 0, 0); 266 if (cubeField.size() > difficulty){ 267 cubeField.remove(0); 268 }else if (cubeField.size() != difficulty){ 269 randomizeCube(); 270 } 271 272 if (cubeField.isEmpty()){ 273 requestClose(false); 274 }else{ 275 for (int i = 0; i < cubeField.size(); i++){ 276 277 //better way to check collision 278 Geometry playerModel = (Geometry) player.getChild(0); 279 Geometry cubeModel = cubeField.get(i); 280 cubeModel.updateGeometricState(); 281 282 BoundingVolume pVol = playerModel.getWorldBound(); 283 BoundingVolume vVol = cubeModel.getWorldBound(); 284 285 if (pVol.intersects(vVol)){ 286 gameLost(); 287 return; 288 } 289 //Remove cube if 10 world units behind player 290 if (cubeField.get(i).getLocalTranslation().getX() + 10 < player.getLocalTranslation().getX()){ 291 cubeField.get(i).removeFromParent(); 292 cubeField.remove(cubeField.get(i)); 293 } 294 295 } 296 } 297 298 Score += fpsRate * tpf; 299 fpsScoreText.setText("Current Score: "+Score); 300 } 301 /** 302 * Sets up the keyboard bindings 303 */ 304 private void Keys() { 305 inputManager.addMapping("START", new KeyTrigger(KeyInput.KEY_RETURN)); 306 inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_LEFT)); 307 inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_RIGHT)); 308 inputManager.addListener(this, "START", "Left", "Right"); 309 } 310 311 public void onAnalog(String binding, float value, float tpf) { 312 if (binding.equals("START") && !START){ 313 START = true; 314 guiNode.detachChild(pressStart); 315 System.out.println("START"); 316 }else if (START == true && binding.equals("Left")){ 317 player.move(0, 0, -(speed / 2f) * value * fpsRate); 318 camAngle -= value*tpf; 319 }else if (START == true && binding.equals("Right")){ 320 player.move(0, 0, (speed / 2f) * value * fpsRate); 321 camAngle += value*tpf; 322 } 323 } 324 325 /** 326 * Determines the colors of the player, floor, obstacle and background 327 */ 328 private void colorLogic() { 329 if (timer.getTimeInSeconds() >= coreTime){ 330 331 colorInt++; 332 coreTime = timer.getTimeInSeconds() + 20; 333 334 335 switch (colorInt){ 336 case 1: 337 obstacleColors.clear(); 338 solidBox = false; 339 obstacleColors.add(ColorRGBA.Green); 340 renderer.setBackgroundColor(ColorRGBA.Black); 341 playerMaterial.setColor("Color", ColorRGBA.White); 342 floorMaterial.setColor("Color", ColorRGBA.Black); 343 break; 344 case 2: 345 obstacleColors.set(0, ColorRGBA.Black); 346 solidBox = true; 347 renderer.setBackgroundColor(ColorRGBA.White); 348 playerMaterial.setColor("Color", ColorRGBA.Gray); 349 floorMaterial.setColor("Color", ColorRGBA.LightGray); 350 break; 351 case 3: 352 obstacleColors.set(0, ColorRGBA.Pink); 353 break; 354 case 4: 355 obstacleColors.set(0, ColorRGBA.Cyan); 356 obstacleColors.add(ColorRGBA.Magenta); 357 renderer.setBackgroundColor(ColorRGBA.Gray); 358 floorMaterial.setColor("Color", ColorRGBA.Gray); 359 playerMaterial.setColor("Color", ColorRGBA.White); 360 break; 361 case 5: 362 obstacleColors.remove(0); 363 renderer.setBackgroundColor(ColorRGBA.Pink); 364 solidBox = false; 365 playerMaterial.setColor("Color", ColorRGBA.White); 366 break; 367 case 6: 368 obstacleColors.set(0, ColorRGBA.White); 369 solidBox = true; 370 renderer.setBackgroundColor(ColorRGBA.Black); 371 playerMaterial.setColor("Color", ColorRGBA.Gray); 372 floorMaterial.setColor("Color", ColorRGBA.LightGray); 373 break; 374 case 7: 375 obstacleColors.set(0, ColorRGBA.Green); 376 renderer.setBackgroundColor(ColorRGBA.Gray); 377 playerMaterial.setColor("Color", ColorRGBA.Black); 378 floorMaterial.setColor("Color", ColorRGBA.Orange); 379 break; 380 case 8: 381 obstacleColors.set(0, ColorRGBA.Red); 382 floorMaterial.setColor("Color", ColorRGBA.Pink); 383 break; 384 case 9: 385 obstacleColors.set(0, ColorRGBA.Orange); 386 obstacleColors.add(ColorRGBA.Red); 387 obstacleColors.add(ColorRGBA.Yellow); 388 renderer.setBackgroundColor(ColorRGBA.White); 389 playerMaterial.setColor("Color", ColorRGBA.Red); 390 floorMaterial.setColor("Color", ColorRGBA.Gray); 391 colorInt=0; 392 break; 393 default: 394 break; 395 } 396 } 397 } 398 /** 399 * Sets up a BitmapText to be displayed 400 * @param txt the Bitmap Text 401 * @param text the 402 * @param font the font of the text 403 * @param x 404 * @param y 405 * @param z 406 */ 407 private void loadText(BitmapText txt, String text, BitmapFont font, float x, float y, float z) { 408 txt.setSize(font.getCharSet().getRenderedSize()); 409 txt.setLocalTranslation(txt.getLineWidth() * x, txt.getLineHeight() * y, z); 410 txt.setText(text); 411 guiNode.attachChild(txt); 412 } 413 }