mirror of
https://github.com/Dejvino/roadtrip
synced 2024-11-14 13:03:28 +00:00
Map: refactored populating of map objects to use the new procedural blocks.
This commit is contained in:
parent
7893ff412b
commit
4a87dbc674
@ -90,70 +90,8 @@ public class RoadTrip extends GameApplication implements ActionListener {
|
|||||||
al.setColor(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
|
al.setColor(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
|
||||||
rootNode.addLight(al);
|
rootNode.addLight(al);
|
||||||
|
|
||||||
gameWorldState = new GameWorldState();
|
gameWorldState = new GameWorldState(1L);
|
||||||
gameWorldView = GameWorldView.create(gameWorldState, assetManager, cam, rootNode);
|
gameWorldView = GameWorldView.create(gameWorldState, assetManager, cam, rootNode, getPhysicsSpace());
|
||||||
final TerrainGrid terrainGrid = gameWorldView.terrain.terrainGrid;
|
|
||||||
terrainGrid.addListener(new TerrainGridListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void gridMoved(Vector3f newCenter) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tileAttached(Vector3f cell, TerrainQuad quad) {
|
|
||||||
while(quad.getControl(RigidBodyControl.class)!=null){
|
|
||||||
quad.removeControl(RigidBodyControl.class);
|
|
||||||
}
|
|
||||||
quad.addControl(new RigidBodyControl(new HeightfieldCollisionShape(quad.getHeightMap(), terrainGrid.getLocalScale()), 0));
|
|
||||||
getPhysicsSpace().add(quad);
|
|
||||||
|
|
||||||
String treesKey = "trees-" + quad.getName();
|
|
||||||
Spatial treesOld = rootNode.getChild(treesKey);
|
|
||||||
if (treesOld != null) {
|
|
||||||
getPhysicsSpace().removeAll(treesOld);
|
|
||||||
treesOld.removeFromParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
Node trees = new Node(treesKey);
|
|
||||||
Random quadRand = new Random(treesKey.hashCode());
|
|
||||||
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;
|
|
||||||
for (int i = 0; i < quadRand.nextInt(1000); i++) {
|
|
||||||
Vector2f pos = new Vector2f((quadRand.nextFloat() - 0.5f) * cellSize, (quadRand.nextFloat() - 0.5f) * cellSize)
|
|
||||||
.addLocal(quad.getWorldTranslation().x, quad.getWorldTranslation().z);
|
|
||||||
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);
|
|
||||||
//RigidBodyControl control = treeInstance.getControl(RigidBodyControl.class);
|
|
||||||
RigidBodyControl control = new RigidBodyControl(new ConeCollisionShape(1f, 5f), 0f);
|
|
||||||
if (control != null) {
|
|
||||||
treeInstance.addControl(control);
|
|
||||||
control.setPhysicsLocation(location);
|
|
||||||
getPhysicsSpace().add(control);
|
|
||||||
}
|
|
||||||
trees.attachChild(treeInstance);
|
|
||||||
}
|
|
||||||
rootNode.attachChild(trees);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tileDetached(Vector3f cell, TerrainQuad quad) {
|
|
||||||
if (quad.getControl(RigidBodyControl.class) != null) {
|
|
||||||
getPhysicsSpace().remove(quad);
|
|
||||||
quad.removeControl(RigidBodyControl.class);
|
|
||||||
String treesKey = "trees-" + quad.getName();
|
|
||||||
Spatial trees = rootNode.getChild(treesKey);
|
|
||||||
getPhysicsSpace().removeAll(trees);
|
|
||||||
trees.removeFromParent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
addCar();
|
addCar();
|
||||||
addCar();
|
addCar();
|
||||||
|
@ -39,7 +39,7 @@ public abstract class AbstractProceduralBlock implements ProceduralBlock
|
|||||||
{
|
{
|
||||||
if (subBlockClass == null) throw new NullPointerException("subBlockClass");
|
if (subBlockClass == null) throw new NullPointerException("subBlockClass");
|
||||||
try {
|
try {
|
||||||
Constructor<T> constructor = subBlockClass.getConstructor(Long.class);
|
Constructor<T> constructor = subBlockClass.getConstructor(Long.TYPE);
|
||||||
return constructor.newInstance(getSubBlockSeed(subBlockKey));
|
return constructor.newInstance(getSubBlockSeed(subBlockKey));
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
throw new IllegalArgumentException("Class " + subBlockClass + " does not have the default constructor with a single 'long' parameter.", e);
|
throw new IllegalArgumentException("Class " + subBlockClass + " does not have the default constructor with a single 'long' parameter.", e);
|
||||||
|
12
src/roadtrip/model/ProceduralMapQuadBlock.java
Normal file
12
src/roadtrip/model/ProceduralMapQuadBlock.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package roadtrip.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by dejvino on 21.01.2017.
|
||||||
|
*/
|
||||||
|
public class ProceduralMapQuadBlock extends AbstractProceduralBlock
|
||||||
|
{
|
||||||
|
public ProceduralMapQuadBlock(long seed)
|
||||||
|
{
|
||||||
|
super(seed);
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,16 @@
|
|||||||
package roadtrip.view;
|
package roadtrip.view;
|
||||||
|
|
||||||
import com.jme3.asset.AssetManager;
|
import com.jme3.asset.AssetManager;
|
||||||
|
import com.jme3.bullet.PhysicsSpace;
|
||||||
|
import com.jme3.bullet.collision.shapes.ConeCollisionShape;
|
||||||
import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape;
|
import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape;
|
||||||
import com.jme3.bullet.control.RigidBodyControl;
|
import com.jme3.bullet.control.RigidBodyControl;
|
||||||
import com.jme3.material.Material;
|
import com.jme3.material.Material;
|
||||||
|
import com.jme3.math.Vector2f;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.Camera;
|
import com.jme3.renderer.Camera;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
import com.jme3.terrain.geomipmap.*;
|
import com.jme3.terrain.geomipmap.*;
|
||||||
import com.jme3.terrain.geomipmap.grid.FractalTileLoader;
|
import com.jme3.terrain.geomipmap.grid.FractalTileLoader;
|
||||||
import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
|
import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;
|
||||||
@ -19,31 +23,36 @@ import com.jme3.terrain.noise.filter.SmoothFilter;
|
|||||||
import com.jme3.terrain.noise.fractal.FractalSum;
|
import com.jme3.terrain.noise.fractal.FractalSum;
|
||||||
import com.jme3.terrain.noise.modulator.NoiseModulator;
|
import com.jme3.terrain.noise.modulator.NoiseModulator;
|
||||||
import com.jme3.texture.Texture;
|
import com.jme3.texture.Texture;
|
||||||
|
import roadtrip.model.ProceduralMapQuadBlock;
|
||||||
import roadtrip.model.TerrainDataProvider;
|
import roadtrip.model.TerrainDataProvider;
|
||||||
import roadtrip.view.model.GameWorldState;
|
import roadtrip.view.model.GameWorldState;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by dejvino on 14.01.2017.
|
* Created by dejvino on 14.01.2017.
|
||||||
*/
|
*/
|
||||||
public class GameWorldView {
|
public class GameWorldView {
|
||||||
|
|
||||||
private GameWorldState state;
|
private final GameWorldState state;
|
||||||
|
|
||||||
private AssetManager assetManager;
|
private final AssetManager assetManager;
|
||||||
private Camera camera;
|
private final Camera camera;
|
||||||
private Node rootNode;
|
private final Node rootNode;
|
||||||
|
private final PhysicsSpace physicsSpace;
|
||||||
|
|
||||||
public TerrainView terrain = new TerrainView(new TerrainDataProvider());
|
public TerrainView terrain = new TerrainView(new TerrainDataProvider());
|
||||||
|
|
||||||
public GameWorldView(GameWorldState gameWorldState, AssetManager assetManager, Camera camera, Node rootNode) {
|
public GameWorldView(GameWorldState gameWorldState, AssetManager assetManager, Camera camera, Node rootNode, PhysicsSpace physicsSpace) {
|
||||||
this.state = gameWorldState;
|
this.state = gameWorldState;
|
||||||
this.assetManager = assetManager;
|
this.assetManager = assetManager;
|
||||||
this.camera = camera;
|
this.camera = camera;
|
||||||
this.rootNode = rootNode;
|
this.rootNode = rootNode;
|
||||||
|
this.physicsSpace = physicsSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GameWorldView create(GameWorldState gameWorldState, AssetManager assetManager, Camera camera, Node rootNode) {
|
public static GameWorldView create(GameWorldState gameWorldState, AssetManager assetManager, Camera camera, Node rootNode, PhysicsSpace physicsSpace) {
|
||||||
GameWorldView gameWorldView = new GameWorldView(gameWorldState, assetManager, camera, rootNode);
|
GameWorldView gameWorldView = new GameWorldView(gameWorldState, assetManager, camera, rootNode, physicsSpace);
|
||||||
gameWorldView.initialize();
|
gameWorldView.initialize();
|
||||||
return gameWorldView;
|
return gameWorldView;
|
||||||
}
|
}
|
||||||
@ -134,5 +143,88 @@ public class GameWorldView {
|
|||||||
TerrainLodControl control = new TerrainGridLodControl(terrain.terrainGrid, camera);
|
TerrainLodControl control = new TerrainGridLodControl(terrain.terrainGrid, camera);
|
||||||
control.setLodCalculator(new DistanceLodCalculator(64 + 1, 2.7f)); // patch size, and a multiplier
|
control.setLodCalculator(new DistanceLodCalculator(64 + 1, 2.7f)); // patch size, and a multiplier
|
||||||
terrain.terrainGrid.addControl(control);
|
terrain.terrainGrid.addControl(control);
|
||||||
|
|
||||||
|
final TerrainGrid terrainGrid = terrain.terrainGrid;
|
||||||
|
terrainGrid.addListener(new TerrainGridListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void gridMoved(Vector3f newCenter) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tileAttached(Vector3f cell, TerrainQuad quad) {
|
||||||
|
while(quad.getControl(RigidBodyControl.class)!=null){
|
||||||
|
quad.removeControl(RigidBodyControl.class);
|
||||||
|
}
|
||||||
|
quad.addControl(new RigidBodyControl(new HeightfieldCollisionShape(quad.getHeightMap(), terrainGrid.getLocalScale()), 0));
|
||||||
|
physicsSpace.add(quad);
|
||||||
|
|
||||||
|
removeQuadObjectsNode(quad);
|
||||||
|
|
||||||
|
String quadObjectsNodeKey = getQuadObjectsNodeKey(quad);
|
||||||
|
Node objects = new Node(quadObjectsNodeKey);
|
||||||
|
populateQuadObjectsNode(quad, quadObjectsNodeKey, objects);
|
||||||
|
rootNode.attachChild(objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void populateQuadObjectsNode(TerrainQuad quad, String quadObjectsNodeKey, Node objects)
|
||||||
|
{
|
||||||
|
ProceduralMapQuadBlock mapQuadBlock = state.proceduralMap.getMapQuadBlock(quad.getName());
|
||||||
|
|
||||||
|
// TODO: move any access to the Random into the ProceduralMapQuadBlock
|
||||||
|
Random quadRand = mapQuadBlock.getBlockRandom();
|
||||||
|
|
||||||
|
// Generate 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;
|
||||||
|
for (int i = 0; i < quadRand.nextInt(1000); i++) {
|
||||||
|
Vector2f pos = new Vector2f((quadRand.nextFloat() - 0.5f) * cellSize, (quadRand.nextFloat() - 0.5f) * cellSize)
|
||||||
|
.addLocal(quad.getWorldTranslation().x, quad.getWorldTranslation().z);
|
||||||
|
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);
|
||||||
|
// 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);
|
||||||
|
physicsSpace.add(control);
|
||||||
|
}
|
||||||
|
objects.attachChild(treeInstance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tileDetached(Vector3f cell, TerrainQuad quad) {
|
||||||
|
if (quad.getControl(RigidBodyControl.class) != null) {
|
||||||
|
physicsSpace.remove(quad);
|
||||||
|
quad.removeControl(RigidBodyControl.class);
|
||||||
|
}
|
||||||
|
removeQuadObjectsNode(quad);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void removeQuadObjectsNode(TerrainQuad quad)
|
||||||
|
{
|
||||||
|
Spatial quadObjectsNodeOld = rootNode.getChild(getQuadObjectsNodeKey(quad));
|
||||||
|
if (quadObjectsNodeOld != null) {
|
||||||
|
physicsSpace.removeAll(quadObjectsNodeOld);
|
||||||
|
quadObjectsNodeOld.removeFromParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getQuadObjectsNodeKey(TerrainQuad quad)
|
||||||
|
{
|
||||||
|
return "Objects-" + quad.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -8,6 +8,13 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Created by dejvino on 14.01.2017.
|
* Created by dejvino on 14.01.2017.
|
||||||
*/
|
*/
|
||||||
public class GameWorldState {
|
public class GameWorldState
|
||||||
public List<VehicleNode> vehicles = new LinkedList<>();
|
{
|
||||||
|
public final ProceduralMapBlock proceduralMap;
|
||||||
|
public final List<VehicleNode> vehicles = new LinkedList<>();
|
||||||
|
|
||||||
|
public GameWorldState(long worldSeed)
|
||||||
|
{
|
||||||
|
this.proceduralMap = new ProceduralMapBlock(worldSeed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
20
src/roadtrip/view/model/ProceduralMapBlock.java
Normal file
20
src/roadtrip/view/model/ProceduralMapBlock.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package roadtrip.view.model;
|
||||||
|
|
||||||
|
import roadtrip.model.AbstractProceduralBlock;
|
||||||
|
import roadtrip.model.ProceduralMapQuadBlock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by dejvino on 21.01.2017.
|
||||||
|
*/
|
||||||
|
public class ProceduralMapBlock extends AbstractProceduralBlock
|
||||||
|
{
|
||||||
|
public ProceduralMapBlock(long seed)
|
||||||
|
{
|
||||||
|
super(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProceduralMapQuadBlock getMapQuadBlock(String quadName)
|
||||||
|
{
|
||||||
|
return getSubBlock(quadName, ProceduralMapQuadBlock.class);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user