Столкновения с Ландшафтом
Этот урок расширяет урок HelloTerrain и в нём вы делаете ландшафт твердым. Вы комбинируете то, что вы узнали в Hello Terrain и Hello Collision, и добавляете CollisionShape в ландшафт. CollisionShape местности позволяет игроку от первого лица (который тоже является CollisionShape) сталкиваться с рельефом, т.е. ходить по нему и стоять на нем.
Пример кода
package jme3test.helloworld; import com.jme3.app.SimpleApplication; import com.jme3.bullet.BulletAppState; import com.jme3.bullet.collision.shapes.CapsuleCollisionShape; import com.jme3.bullet.collision.shapes.CollisionShape; import com.jme3.bullet.control.CharacterControl; import com.jme3.bullet.control.RigidBodyControl; import com.jme3.bullet.util.CollisionShapeFactory; import com.jme3.input.KeyInput; import com.jme3.input.controls.ActionListener; import com.jme3.input.controls.KeyTrigger; import com.jme3.material.Material; import com.jme3.math.Vector3f; import com.jme3.renderer.Camera; import com.jme3.scene.Node; import com.jme3.terrain.geomipmap.TerrainLodControl; import com.jme3.terrain.heightmap.AbstractHeightMap; import com.jme3.terrain.geomipmap.TerrainQuad; import com.jme3.terrain.heightmap.ImageBasedHeightMap; import com.jme3.texture.Texture; import com.jme3.texture.Texture.WrapMode; import java.util.ArrayList; import java.util.List; import jme3tools.converters.ImageToAwt; /** * Эта демонстрация показывает обнаружением столкновения с местностью, * по которой вы можете ходить, с перспективой от первого лица. * Этот код объединяет HelloCollision и HelloTerrain. */ public class HelloTerrainCollision extends SimpleApplication implements ActionListener { private BulletAppState bulletAppState; private RigidBodyControl landscape; private CharacterControl player; private Vector3f walkDirection = new Vector3f(); private boolean left = false, right = false, up = false, down = false; private TerrainQuad terrain; private Material mat_terrain; public static void main(String[] args) { HelloTerrainCollision app = new HelloTerrainCollision(); app.start(); } @Override public void simpleInitApp() { /** Настроить физику */ bulletAppState = new BulletAppState(); stateManager.attach(bulletAppState); //Раскомментирование для отладки. //bulletAppState.setDebugEnabled(true); flyCam.setMoveSpeed(100); setUpKeys(); /** 1. Создайте материал ландшафта и загрузите в него четыре текстуры. */ mat_terrain = new Material(assetManager, "Common/MatDefs/Terrain/Terrain.j3md"); /** 1.1) Добавьте ALPHA map (для splat текстур с красно-сине-зелеными кодами) */ mat_terrain.setTexture("Alpha", assetManager.loadTexture( "Textures/Terrain/splat/alphamap.png")); /** 1.2) Добавьте GRASS(ТРАВЫ) текстуру в красный слой (Tex1). */ Texture grass = assetManager.loadTexture( "Textures/Terrain/splat/grass.jpg"); grass.setWrap(WrapMode.Repeat); mat_terrain.setTexture("Tex1", grass); mat_terrain.setFloat("Tex1Scale", 64f); /** 1.3) Добавьте DIRT(ПОЧВА) текстуру в зелёный слой (Tex2) */ Texture dirt = assetManager.loadTexture( "Textures/Terrain/splat/dirt.jpg"); dirt.setWrap(WrapMode.Repeat); mat_terrain.setTexture("Tex2", dirt); mat_terrain.setFloat("Tex2Scale", 32f); /** 1.4) Добавьте ROAD(ДОРОГА) текстуру в голубой слой (Tex3) */ Texture rock = assetManager.loadTexture( "Textures/Terrain/splat/road.jpg"); rock.setWrap(WrapMode.Repeat); mat_terrain.setTexture("Tex3", rock); mat_terrain.setFloat("Tex3Scale", 128f); /** 2. Создайте height map */ AbstractHeightMap heightmap = null; Texture heightMapImage = assetManager.loadTexture( "Textures/Terrain/splat/mountains512.png"); heightmap = new ImageBasedHeightMap(heightMapImage.getImage()); heightmap.load(); /** 3. Мы подготовили material и heightmap. * Теперь мы создаем сам ландшафт: * 3.1) Создайте TerrainQuad и назовите его "my terrain". * 3.2) Хорошее значение для плиток ландшафта 64x64 -- поэтому мы предоставляем 64+1=65. * 3.3) Мы подготовили heightmap размером 512x512 -- поэтому мы предоставляем 512+1=513. * 3.4) В качестве шага масштаба LOD мы предоставляем Vector3f(1,1,1). * 3.5) Мы предоставляем подготовленную себе heightmap. */ terrain = new TerrainQuad("my terrain", 65, 513, heightmap.getHeightMap()); /** 4. Мы даем ландшафту его материал, расположение и его масштаб и прикрепляем. */ terrain.setMaterial(mat_terrain); terrain.setLocalTranslation(0, -100, 0); terrain.setLocalScale(2f, 1f, 2f); rootNode.attachChild(terrain); /** 5. LOD (Уровень деталей) зависит от того, того есть ли камера: */ List<Camera> cameras = new ArrayList<Camera>(); cameras.add(getCamera()); TerrainLodControl control = new TerrainLodControl(terrain, cameras); terrain.addControl(control); /** 6. Добавим физику: Мы установили обнаружение столкновения для сцены, создав статический RigidBodyControl с нулевой массой.*/ terrain.addControl(new RigidBodyControl(0)); // Мы установили обнаружение столкновения для player, создав // фигуру столкновения капсул и CharacterControl.. // CharacterControl предлагает дополнительные настройки для // размера, высоты шага, прыжка, падения и силы тяжести. // Мы также ставим игрока в исходное положение. CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1); player = new CharacterControl(capsuleShape, 0.05f); player.setJumpSpeed(20); player.setFallSpeed(30); // пред jME3.2 // player.setGravity(30f); // >= jME3.2 player.setGravity(new Vector3f(0,-30f,0)); player.setPhysicsLocation(new Vector3f(-10, 10, 10)); // Мы присоединяем сцену и игрока к rootnode и physics space, // чтобы они появились в игровом мире. bulletAppState.getPhysicsSpace().add(terrain); bulletAppState.getPhysicsSpace().add(player); } /** Мы переписываем некоторые сопоставления навигационных клавиш здесь, так мы можем * добавить контролируемую физикой ходьбу и прыжки: */ private void setUpKeys() { inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A)); inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D)); inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W)); inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S)); inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE)); inputManager.addListener(this, "Left"); inputManager.addListener(this, "Right"); inputManager.addListener(this, "Up"); inputManager.addListener(this, "Down"); inputManager.addListener(this, "Jump"); } /** Это наши пользовательские действия, вызванные нажатиями клавиш. * Мы еще не ходим, мы просто отслеживаем направление, которое пользователь нажал. */ public void onAction(String binding, boolean value, float tpf) { if (binding.equals("Left")) { if (value) { left = true; } else { left = false; } } else if (binding.equals("Right")) { if (value) { right = true; } else { right = false; } } else if (binding.equals("Up")) { if (value) { up = true; } else { up = false; } } else if (binding.equals("Down")) { if (value) { down = true; } else { down = false; } } else if (binding.equals("Jump")) { player.jump(new Vector3f(0,10,0)); } } /** * Это главный цикл события--ходьбы, ходьба происходит здесь. * Мы проверяем, в каком направлении идет игрок, интерпретируя * направление камеры вперед (camDir) и в стороны (camLeft). * Команда setWalkDirection() это то что позволяет физике контролировать ходьбу player. * Мы также следим за тем, чтобы камера двигалась вместе с игроком. */ @Override public void simpleUpdate(float tpf) { Vector3f camDir = cam.getDirection().clone().multLocal(0.6f); Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f); walkDirection.set(0, 0, 0); if (left) { walkDirection.addLocal(camLeft); } if (right) { walkDirection.addLocal(camLeft.negate()); } if (up) { walkDirection.addLocal(camDir); } if (down) { walkDirection.addLocal(camDir.negate()); } player.setWalkDirection(walkDirection); cam.setLocation(player.getPhysicsLocation()); } }
Чтобы попробовать этот код, создайте новый проект Создать проект ▸ JME3 ▸ BasicGame, используя настройки по умолчанию. Вставьте код примера поверх предварительно сгенерированного класса Main.java. При необходимости измените пакет на «mygame». Откройте Свойства ▸ Свойства проект ▸ Библиотеки и добавьте библиотеку jme3-test-data, чтобы убедиться, что у вас есть все файлы.
Скомпилируйте и запустите код. Вы должны увидеть ландшафт. Вы можете использовать клавиши
и мышь, чтобы бегать вверх и вниз по холмам.Понимание кода
Код Ландшафта
Прочтите урок Hello Terrain для получения информации о следующих частях, которые мы повторно используем:
- AbstractHeightMap — эффективный способ описания формы поверхности местности.
- Материал Terrain.j3md и его текстурные слои позволяют вам раскрашивать скалистые горы, травянистые долины и проложенную дорожку, пересекающую ландшафт.
- TerrainQuad — это законченный Spatial terrain, который вы прикрепляете к rootNode.
Код обнаружения столкновений
Прочтите Hello Collision для получения информации о следующих частях, которые мы повторно используем:
- Строки BulletAppState активируют физику.
- ActionListener (onAction()) позволяет перенастроить обработку ввода для игрока от первого лица, поэтому он учитывает обнаружение конфликтов.
- Пользовательский метод setUpKeys() загружает перенастроенные обработчики ввода. Теперь они не просто идут куда-то, но и вычисляют вектор направления walkDirection, который нам нужен для обнаружения столкновения.
- simpleUpdate() использует вектор walkDirection и осуществляет ходьбу персонажа, принимая во внимание препятствия и сплошные стены/пол.
player.setWalkDirection(walkDirection);
- Пейзаж RigidBodyControl — это CollisionShape местности.
- Игрок с физикой и от первого лица является CapsuleCollisionShape с CharacterControl.
Объединение двух
Вот измененные части, чтобы объединить эти два аспекта:
- Вы создаете статический (нулевой-массы) RigidBodyControl.
- Добавьте control в terrain, чтобы сделать его с физикой.
/** 6. Добавим физику: */ terrain.addControl(new RigidBodyControl(0));
Вы прикрепляете terrain и player от первого лица к rootNode и к physics space, чтобы они отображались в игровом мире.
bulletAppState.getPhysicsSpace().add(terrain); bulletAppState.getPhysicsSpace().add(player);
Заключение
Вы видите, что вы можете комбинировать фрагменты образцов кода (например из, HelloTerrain и HelloCollision) и создавать из него новое приложение, которое объединяет две функции в новое.
Вы должны подняться высоко в области и упасть на карту, давая вам несколько секунд, чтобы осмотреть площадь. Затем прогуляйтесь и посмотрите, как вам эта земля.
Смотрите также:
Переведено для jmonkeyengine.ru, оригинал.
Автор перевода: Andry
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.