diff --git a/src/roadtrip/GameApplication.java b/src/roadtrip/GameApplication.java index cd3aff1..e9f85a4 100644 --- a/src/roadtrip/GameApplication.java +++ b/src/roadtrip/GameApplication.java @@ -26,6 +26,12 @@ public abstract class GameApplication extends NotSoSimpleApplication stateManager.attach(bulletAppState); } + @Override + public void update() { + super.update(); + updateListenerPosition(); + } + protected PhysicsSpace getPhysicsSpace(){ return bulletAppState.getPhysicsSpace(); } @@ -43,4 +49,10 @@ public abstract class GameApplication extends NotSoSimpleApplication { bulletAppState.setEnabled(!paused); } + + protected void updateListenerPosition() + { + listener.setLocation(cam.getLocation()); + listener.setRotation(cam.getRotation()); + } } diff --git a/src/roadtrip/RoadTrip.java b/src/roadtrip/RoadTrip.java index c6805b1..cbf6848 100644 --- a/src/roadtrip/RoadTrip.java +++ b/src/roadtrip/RoadTrip.java @@ -153,6 +153,8 @@ public class RoadTrip extends GameApplication implements ActionListener { VehicleNode vehicle = new VehicleNode("Car " + vehicleInstance.toString(), vehicleInstance); vehicle.initialize(assetManager); + vehicle.vehicleControl.setPhysicsLocation(new Vector3f(10f + (float)Math.random() * 40f, 228f, 12f + (float)Math.random() * 40f)); + gameWorldState.vehicles.add(vehicle); getPhysicsSpace().addAll(vehicle); rootNode.attachChild(vehicle); @@ -169,7 +171,7 @@ public class RoadTrip extends GameApplication implements ActionListener { person.addControl(personControl); /**/personControl.setJumpForce(new Vector3f(0,5f,0)); personControl.setGravity(new Vector3f(0,1f,0)); - personControl.warp(new Vector3f(10f + (float)Math.random() * 20f, 30f, 12f + (float)Math.random() * 20f));/**/ + personControl.warp(new Vector3f(10f + (float)Math.random() * 20f, 230f, 12f + (float)Math.random() * 20f));/**/ //personControl.setPhysicsLocation(new Vector3f(10f, 30f, 12f)); getPhysicsSpace().add(personControl); //getPhysicsSpace().addAll(person); diff --git a/src/roadtrip/RoadTripPlanner.java b/src/roadtrip/RoadTripPlanner.java new file mode 100644 index 0000000..a987d80 --- /dev/null +++ b/src/roadtrip/RoadTripPlanner.java @@ -0,0 +1,77 @@ +package roadtrip; + +import com.jme3.app.SimpleApplication; +import com.jme3.audio.AudioNode; +import com.jme3.audio.AudioSource.Status; +import com.jme3.bullet.BulletAppState; +import com.jme3.bullet.PhysicsSpace; +import com.jme3.bullet.collision.shapes.*; +import com.jme3.bullet.control.BetterCharacterControl; +import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.bullet.control.VehicleControl; +import com.jme3.font.BitmapFont; +import com.jme3.font.BitmapText; +import com.jme3.font.Rectangle; +import com.jme3.input.ChaseCamera; +import com.jme3.input.KeyInput; +import com.jme3.input.controls.ActionListener; +import com.jme3.input.controls.KeyTrigger; +import com.jme3.light.AmbientLight; +import com.jme3.light.DirectionalLight; +import com.jme3.material.Material; +import com.jme3.math.*; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.scene.Geometry; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.debug.Arrow; +import com.jme3.scene.shape.Box; +import com.jme3.scene.shape.Cylinder; +import com.jme3.terrain.geomipmap.TerrainGrid; +import com.jme3.terrain.geomipmap.TerrainGridListener; +import com.jme3.terrain.geomipmap.TerrainQuad; +import java.util.Random; +import roadtrip.model.VehicleInstance; +import roadtrip.view.CompassNode; +import roadtrip.view.GameMenuNode; +import roadtrip.view.GameWorldView; +import roadtrip.view.VehicleNode; +import roadtrip.view.model.GameWorldState; +import roadtrip.view.model.Player; + +/** + * + * @author dejvino + */ +public class RoadTripPlanner extends SimpleApplication { + + public static void main(String[] args) { + RoadTripPlanner app = new RoadTripPlanner(); + app.start(); + } + + public static boolean DEBUG = /*false;/*/true;/**/ + + protected BulletAppState bulletAppState; + private GameWorldState gameWorldState; + private GameWorldView gameWorldView; + + protected PhysicsSpace getPhysicsSpace(){ + return bulletAppState.getPhysicsSpace(); + } + + @Override + public void simpleInitApp() + { + bulletAppState = new BulletAppState(); + stateManager.attach(bulletAppState); + + bulletAppState.setDebugEnabled(DEBUG); + + gameWorldState = new GameWorldState(1L); + gameWorldView = GameWorldView.create(gameWorldState, assetManager, cam, rootNode, getPhysicsSpace()); + + flyCam.setMoveSpeed(300f); + cam.setLocation(new Vector3f(0, 200f, 0)); + } +} diff --git a/src/roadtrip/model/MapObjectInstance.java b/src/roadtrip/model/MapObjectInstance.java new file mode 100644 index 0000000..6ea927b --- /dev/null +++ b/src/roadtrip/model/MapObjectInstance.java @@ -0,0 +1,26 @@ +package roadtrip.model; + +import com.jme3.math.Vector3f; + +/** + * Created by dejvino on 21.01.2017. + */ +public class MapObjectInstance +{ + private Vector3f position; + + public MapObjectInstance(Vector3f position) + { + this.position = new Vector3f(position); + } + + public Vector3f getPosition() + { + return new Vector3f(position); + } + + public void setPosition(Vector3f position) + { + this.position = new Vector3f(position); + } +} diff --git a/src/roadtrip/model/ProceduralMapBlock.java b/src/roadtrip/model/ProceduralMapBlock.java index aaeafb3..f855008 100644 --- a/src/roadtrip/model/ProceduralMapBlock.java +++ b/src/roadtrip/model/ProceduralMapBlock.java @@ -1,5 +1,6 @@ package roadtrip.model; +import com.jme3.terrain.geomipmap.TerrainQuad; import roadtrip.model.AbstractProceduralBlock; import roadtrip.model.ProceduralMapQuadBlock; @@ -13,8 +14,10 @@ public class ProceduralMapBlock extends AbstractProceduralBlock super(seed); } - public ProceduralMapQuadBlock getMapQuadBlock(String quadName) + public ProceduralMapQuadBlock getMapQuadBlock(TerrainQuad terrainQuad) { - return getSubBlock(quadName, ProceduralMapQuadBlock.class); + ProceduralMapQuadBlock quadBlock = getSubBlock(terrainQuad.getName(), ProceduralMapQuadBlock.class); + quadBlock.initialize(terrainQuad); + return quadBlock; } } diff --git a/src/roadtrip/model/ProceduralMapQuadBlock.java b/src/roadtrip/model/ProceduralMapQuadBlock.java index b9e772a..8fd1caa 100644 --- a/src/roadtrip/model/ProceduralMapQuadBlock.java +++ b/src/roadtrip/model/ProceduralMapQuadBlock.java @@ -1,12 +1,56 @@ package roadtrip.model; +import com.jme3.bullet.collision.shapes.ConeCollisionShape; +import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import com.jme3.terrain.geomipmap.TerrainQuad; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + /** * Created by dejvino on 21.01.2017. */ public class ProceduralMapQuadBlock extends AbstractProceduralBlock { + protected float cellSize = 64 * 2f * 2f; /* terrainGrid.getPatchSize() * terrainGrid.getLocalScale().x * 2f */ + + private List mapObjects; + public ProceduralMapQuadBlock(long seed) { super(seed); } + + public void initialize(TerrainQuad terrainQuad) + { + mapObjects = new LinkedList<>(); + Random quadRand = getBlockRandom(); + Vector2f prevPos = null; + Vector2f quadPos = new Vector2f(terrainQuad.getLocalTranslation().x, terrainQuad.getLocalTranslation().z); + for (int i = 0; i < quadRand.nextInt(10000); i++) { + Vector2f pos; + if (prevPos == null || quadRand.nextFloat() < 0.2f) { + pos = new Vector2f((quadRand.nextFloat() - 0.5f) * cellSize, (quadRand.nextFloat() - 0.5f) * cellSize) + .addLocal(quadPos); + } else { + pos = new Vector2f((quadRand.nextFloat() - 0.5f) * 20f, (quadRand.nextFloat() - 0.5f) * 20f) + .addLocal(prevPos); + } + prevPos = pos; + float height = terrainQuad.getHeight(pos); + Vector3f location = new Vector3f(pos.x, height, pos.y); + mapObjects.add(new MapObjectInstance(location)); + } + } + + public Iterable getMapObjects() + { + if (mapObjects == null) throw new RuntimeException("Call to getMapObjects on an uninitialized block."); + return mapObjects; + } } diff --git a/src/roadtrip/view/GameWorldView.java b/src/roadtrip/view/GameWorldView.java index 2389cc4..efec816 100644 --- a/src/roadtrip/view/GameWorldView.java +++ b/src/roadtrip/view/GameWorldView.java @@ -5,8 +5,10 @@ import com.jme3.bullet.PhysicsSpace; import com.jme3.bullet.collision.shapes.ConeCollisionShape; import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape; import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.light.AmbientLight; +import com.jme3.light.DirectionalLight; import com.jme3.material.Material; -import com.jme3.math.Vector2f; +import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import com.jme3.renderer.Camera; import com.jme3.scene.Node; @@ -23,12 +25,11 @@ import com.jme3.terrain.noise.filter.SmoothFilter; import com.jme3.terrain.noise.fractal.FractalSum; import com.jme3.terrain.noise.modulator.NoiseModulator; import com.jme3.texture.Texture; +import roadtrip.model.MapObjectInstance; import roadtrip.model.ProceduralMapQuadBlock; import roadtrip.model.TerrainDataProvider; import roadtrip.view.model.GameWorldState; -import java.util.Random; - /** * Created by dejvino on 14.01.2017. */ @@ -59,6 +60,15 @@ public class GameWorldView { private void initialize() { + // Environment + DirectionalLight dl = new DirectionalLight(); + dl.setColor(ColorRGBA.LightGray); + dl.setDirection(new Vector3f(1, -1, 1)); + rootNode.addLight(dl); + AmbientLight al = new AmbientLight(); + al.setColor(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f)); + rootNode.addLight(al); + // TERRAIN TEXTURE material terrain.mat_terrain = new Material(assetManager, "Common/MatDefs/Terrain/HeightBasedTerrain.j3md"); @@ -133,15 +143,15 @@ public class GameWorldView { ground.addPreFilter(terrain.terrainDataProvider.iterate); - terrain.terrainGrid = new TerrainGrid("terrain", 64 + 1, 256 + 1, new FractalTileLoader(ground, 300f)); + terrain.terrainGrid = new TerrainGrid("terrain", 16 + 1, 512 + 1, new FractalTileLoader(ground, 300f)); terrain.terrainGrid.setMaterial(terrain.mat_terrain); - terrain.terrainGrid.setLocalTranslation(0, -200, 0); - terrain.terrainGrid.setLocalScale(2f, 1f, 2f); + //terrain.terrainGrid.setLocalTranslation(0, -200, 0); + //terrain.terrainGrid.setLocalScale(2f, 1f, 2f); this.rootNode.attachChild(terrain.terrainGrid); TerrainLodControl control = new TerrainGridLodControl(terrain.terrainGrid, camera); - control.setLodCalculator(new DistanceLodCalculator(64 + 1, 2.7f)); // patch size, and a multiplier + control.setLodCalculator(new DistanceLodCalculator(32 + 1, 2.7f)); // patch size, and a multiplier terrain.terrainGrid.addControl(control); final TerrainGrid terrainGrid = terrain.terrainGrid; @@ -163,48 +173,33 @@ public class GameWorldView { String quadObjectsNodeKey = getQuadObjectsNodeKey(quad); Node objects = new Node(quadObjectsNodeKey); - populateQuadObjectsNode(quad, quadObjectsNodeKey, objects); + populateQuadObjectsNode(quad, objects); rootNode.attachChild(objects); } - protected void populateQuadObjectsNode(TerrainQuad quad, String quadObjectsNodeKey, Node objects) + protected void populateQuadObjectsNode(TerrainQuad quad, Node objects) { - ProceduralMapQuadBlock mapQuadBlock = state.proceduralMap.getMapQuadBlock(quad.getName()); + ProceduralMapQuadBlock mapQuadBlock = state.proceduralMap.getMapQuadBlock(quad); - // TODO: move any access to the Random into the ProceduralMapQuadBlock - Random quadRand = mapQuadBlock.getBlockRandom(); - - // Generate trees + // Add map objects (for now - trees) Spatial treeModel = assetManager.loadModel("Models/tree.j3o"); //System.out.println("Grid @ " + terrainGrid.getLocalTranslation() + " s " + terrainGrid.getLocalScale()); //System.out.println("Quad " + quad.getName() + " @ " + quad.getLocalTranslation()); - float cellSize = terrainGrid.getPatchSize() * terrainGrid.getLocalScale().x * 2f; - Vector2f prevPos = null; - for (int i = 0; i < quadRand.nextInt(10000); i++) { - Vector2f pos; - if (prevPos == null || quadRand.nextFloat() < 0.2f) { - pos = new Vector2f((quadRand.nextFloat() - 0.5f) * cellSize, (quadRand.nextFloat() - 0.5f) * cellSize) - .addLocal(quad.getWorldTranslation().x, quad.getWorldTranslation().z); - } else { - pos = new Vector2f((quadRand.nextFloat() - 0.5f) * 20f, (quadRand.nextFloat() - 0.5f) * 20f).addLocal(prevPos); - } - prevPos = pos; - float height = quad.getHeight(pos); - Vector3f location = new Vector3f(pos.x, height, pos.y) - .addLocal(terrainGrid.getWorldTranslation()); - System.out.println("Tree " + i + ": " + location); - Spatial treeInstance = treeModel.clone(); - treeInstance.setLocalTranslation(location); + for (MapObjectInstance mapObject : mapQuadBlock.getMapObjects()) { + Vector3f pos = mapObject.getPosition(); + Spatial modelInstance = treeModel.clone(); + modelInstance.setLocalTranslation(pos); // TODO: physics from the model and not hard-coded //RigidBodyControl control = treeInstance.getControl(RigidBodyControl.class); RigidBodyControl control = new RigidBodyControl(new ConeCollisionShape(1f, 5f), 0f); if (control != null) { - treeInstance.addControl(control); - control.setPhysicsLocation(location); + modelInstance.addControl(control); + control.setPhysicsLocation(pos); physicsSpace.add(control); } - objects.attachChild(treeInstance); + objects.attachChild(modelInstance); } + //objects.setLocalTranslation(terrainGrid.getWorldTranslation()); } @Override diff --git a/src/roadtrip/view/VehicleNode.java b/src/roadtrip/view/VehicleNode.java index 7dcaeed..d97ccc4 100644 --- a/src/roadtrip/view/VehicleNode.java +++ b/src/roadtrip/view/VehicleNode.java @@ -213,7 +213,6 @@ public class VehicleNode extends Node vehicle.attachChild(vehicle.wheelSlipAudio); vehicle.addControl(vehicleControl); - vehicleControl.setPhysicsLocation(new Vector3f(10f + (float)Math.random() * 40f, 28f, 12f + (float)Math.random() * 40f)); } public void update(float tpf)