HelloTerrainCollision.java 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * Copyright (c) 2009-2012 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. package jme3test.helloworld;
  33. import com.jme3.app.SimpleApplication;
  34. import com.jme3.bullet.BulletAppState;
  35. import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
  36. import com.jme3.bullet.collision.shapes.CollisionShape;
  37. import com.jme3.bullet.control.CharacterControl;
  38. import com.jme3.bullet.control.RigidBodyControl;
  39. import com.jme3.bullet.util.CollisionShapeFactory;
  40. import com.jme3.input.KeyInput;
  41. import com.jme3.input.controls.ActionListener;
  42. import com.jme3.input.controls.KeyTrigger;
  43. import com.jme3.material.Material;
  44. import com.jme3.math.Vector3f;
  45. import com.jme3.renderer.Camera;
  46. import com.jme3.scene.Node;
  47. import com.jme3.terrain.geomipmap.TerrainLodControl;
  48. import com.jme3.terrain.geomipmap.TerrainQuad;
  49. import com.jme3.terrain.heightmap.AbstractHeightMap;
  50. import com.jme3.terrain.heightmap.ImageBasedHeightMap;
  51. import com.jme3.texture.Texture;
  52. import com.jme3.texture.Texture.WrapMode;
  53. import java.util.ArrayList;
  54. import java.util.List;
  55. /**
  56. * This demo shows a terrain with collision detection,
  57. * that you can walk around in with a first-person perspective.
  58. * This code combines HelloCollision and HelloTerrain.
  59. */
  60. public class HelloTerrainCollision extends SimpleApplication
  61. implements ActionListener {
  62. private BulletAppState bulletAppState;
  63. private RigidBodyControl landscape;
  64. private CharacterControl player;
  65. private Vector3f walkDirection = new Vector3f();
  66. private boolean left = false, right = false, up = false, down = false;
  67. private TerrainQuad terrain;
  68. private Material mat_terrain;
  69. public static void main(String[] args) {
  70. HelloTerrainCollision app = new HelloTerrainCollision();
  71. app.start();
  72. }
  73. @Override
  74. public void simpleInitApp() {
  75. /** Set up Physics */
  76. bulletAppState = new BulletAppState();
  77. stateManager.attach(bulletAppState);
  78. //bulletAppState.getPhysicsSpace().enableDebug(assetManager);
  79. flyCam.setMoveSpeed(100);
  80. setUpKeys();
  81. /** 1. Create terrain material and load four textures into it. */
  82. mat_terrain = new Material(assetManager,
  83. "Common/MatDefs/Terrain/Terrain.j3md");
  84. /** 1.1) Add ALPHA map (for red-blue-green coded splat textures) */
  85. mat_terrain.setTexture("Alpha", assetManager.loadTexture(
  86. "Textures/Terrain/splat/alphamap.png"));
  87. /** 1.2) Add GRASS texture into the red layer (Tex1). */
  88. Texture grass = assetManager.loadTexture(
  89. "Textures/Terrain/splat/grass.jpg");
  90. grass.setWrap(WrapMode.Repeat);
  91. mat_terrain.setTexture("Tex1", grass);
  92. mat_terrain.setFloat("Tex1Scale", 64f);
  93. /** 1.3) Add DIRT texture into the green layer (Tex2) */
  94. Texture dirt = assetManager.loadTexture(
  95. "Textures/Terrain/splat/dirt.jpg");
  96. dirt.setWrap(WrapMode.Repeat);
  97. mat_terrain.setTexture("Tex2", dirt);
  98. mat_terrain.setFloat("Tex2Scale", 32f);
  99. /** 1.4) Add ROAD texture into the blue layer (Tex3) */
  100. Texture rock = assetManager.loadTexture(
  101. "Textures/Terrain/splat/road.jpg");
  102. rock.setWrap(WrapMode.Repeat);
  103. mat_terrain.setTexture("Tex3", rock);
  104. mat_terrain.setFloat("Tex3Scale", 128f);
  105. /** 2. Create the height map */
  106. AbstractHeightMap heightmap = null;
  107. Texture heightMapImage = assetManager.loadTexture(
  108. "Textures/Terrain/splat/mountains512.png");
  109. heightmap = new ImageBasedHeightMap(heightMapImage.getImage());
  110. heightmap.load();
  111. /** 3. We have prepared material and heightmap.
  112. * Now we create the actual terrain:
  113. * 3.1) Create a TerrainQuad and name it "my terrain".
  114. * 3.2) A good value for terrain tiles is 64x64 -- so we supply 64+1=65.
  115. * 3.3) We prepared a heightmap of size 512x512 -- so we supply 512+1=513.
  116. * 3.4) As LOD step scale we supply Vector3f(1,1,1).
  117. * 3.5) We supply the prepared heightmap itself.
  118. */
  119. terrain = new TerrainQuad("my terrain", 65, 513, heightmap.getHeightMap());
  120. /** 4. We give the terrain its material, position & scale it, and attach it. */
  121. terrain.setMaterial(mat_terrain);
  122. terrain.setLocalTranslation(0, -100, 0);
  123. terrain.setLocalScale(2f, 1f, 2f);
  124. rootNode.attachChild(terrain);
  125. /** 5. The LOD (level of detail) depends on were the camera is: */
  126. List<Camera> cameras = new ArrayList<Camera>();
  127. cameras.add(getCamera());
  128. TerrainLodControl control = new TerrainLodControl(terrain, cameras);
  129. terrain.addControl(control);
  130. /** 6. Add physics: */
  131. // We set up collision detection for the scene by creating a
  132. // compound collision shape and a static RigidBodyControl with mass zero.*/
  133. CollisionShape terrainShape =
  134. CollisionShapeFactory.createMeshShape((Node) terrain);
  135. landscape = new RigidBodyControl(terrainShape, 0);
  136. terrain.addControl(landscape);
  137. // We set up collision detection for the player by creating
  138. // a capsule collision shape and a CharacterControl.
  139. // The CharacterControl offers extra settings for
  140. // size, stepheight, jumping, falling, and gravity.
  141. // We also put the player in its starting position.
  142. CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1);
  143. player = new CharacterControl(capsuleShape, 0.05f);
  144. player.setJumpSpeed(20);
  145. player.setFallSpeed(30);
  146. player.setGravity(30);
  147. player.setPhysicsLocation(new Vector3f(-10, 10, 10));
  148. // We attach the scene and the player to the rootnode and the physics space,
  149. // to make them appear in the game world.
  150. bulletAppState.getPhysicsSpace().add(terrain);
  151. bulletAppState.getPhysicsSpace().add(player);
  152. }
  153. /** We over-write some navigational key mappings here, so we can
  154. * add physics-controlled walking and jumping: */
  155. private void setUpKeys() {
  156. inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
  157. inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
  158. inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W));
  159. inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S));
  160. inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
  161. inputManager.addListener(this, "Left");
  162. inputManager.addListener(this, "Right");
  163. inputManager.addListener(this, "Up");
  164. inputManager.addListener(this, "Down");
  165. inputManager.addListener(this, "Jump");
  166. }
  167. /** These are our custom actions triggered by key presses.
  168. * We do not walk yet, we just keep track of the direction the user pressed. */
  169. public void onAction(String binding, boolean value, float tpf) {
  170. if (binding.equals("Left")) {
  171. if (value) { left = true; } else { left = false; }
  172. } else if (binding.equals("Right")) {
  173. if (value) { right = true; } else { right = false; }
  174. } else if (binding.equals("Up")) {
  175. if (value) { up = true; } else { up = false; }
  176. } else if (binding.equals("Down")) {
  177. if (value) { down = true; } else { down = false; }
  178. } else if (binding.equals("Jump")) {
  179. player.jump();
  180. }
  181. }
  182. /**
  183. * This is the main event loop--walking happens here.
  184. * We check in which direction the player is walking by interpreting
  185. * the camera direction forward (camDir) and to the side (camLeft).
  186. * The setWalkDirection() command is what lets a physics-controlled player walk.
  187. * We also make sure here that the camera moves with player.
  188. */
  189. @Override
  190. public void simpleUpdate(float tpf) {
  191. Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);
  192. Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);
  193. walkDirection.set(0, 0, 0);
  194. if (left) { walkDirection.addLocal(camLeft); }
  195. if (right) { walkDirection.addLocal(camLeft.negate()); }
  196. if (up) { walkDirection.addLocal(camDir); }
  197. if (down) { walkDirection.addLocal(camDir.negate()); }
  198. player.setWalkDirection(walkDirection);
  199. cam.setLocation(player.getPhysicsLocation());
  200. }
  201. }