Here is a modified version of the brick tower code I just posted that generates a spiral staircase. Also I included Oto in there
pre type="java"
package towertest;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.bullet.BulletAppState;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
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.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.BloomFilter;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.scene.shape.Sphere.TextureMode;
import com.jme3.shadow.BasicShadowRenderer;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;
/**
@author double1984 (spiral staircase by atom)
/
public class TestSpiralTowerStairs extends SimpleApplication implements ActionListener, AnimEventListener {
//character
CharacterControl character;
Node model;
//temp vectors
Vector3f walkDirection = new Vector3f();
//animation
AnimChannel animationChannel;
AnimChannel shootingChannel;
AnimControl animationControl;
float airTime = 0;
int stepsPerLayer = 1;
int stepLayers = 300;
static float stepWidth = 0.75f, stepHeight = .1f, stepDepth = 2.5f;
static float railWidth = 0.75f, railHeight = 0.75f, railDepth = .2f;
float stepRadius = 3f;
float stepAngle = 0;
float railAngle = 0;
float innerRailAngle = 0;
Material mat;
Material mat2;
Material mat3;
BasicShadowRenderer bsr;
private static final Sphere bullet;
private static final Box brick;
private static final Box rail;
private static final SphereCollisionShape bulletCollisionShape;
boolean left = false, right = false, up = false, down = false;
ChaseCamera chaseCam;
static {
bullet = new Sphere(32, 32, 0.4f, true, false);
bullet.setTextureMode(TextureMode.Projected);
bulletCollisionShape = new SphereCollisionShape(0.4f);
brick = new Box(Vector3f.ZERO, stepWidth, stepHeight, stepDepth);
brick.scaleTextureCoordinates(new Vector2f(1f, .5f));
rail = new Box(Vector3f.ZERO, railWidth, railHeight, railDepth);
rail.scaleTextureCoordinates(new Vector2f(1f, .5f));
}
private BulletAppState bulletAppState;
public static void main(String args[]) {
TestSpiralTowerStairs f = new TestSpiralTowerStairs();
f.start();
}
private void setupChaseCamera() {
flyCam.setEnabled(false);
chaseCam = new ChaseCamera(cam, model, inputManager);
}
private void setupFilter() {
FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
BloomFilter bloom = new BloomFilter(BloomFilter.GlowMode.Objects);
fpp.addFilter(bloom);
viewPort.addProcessor(fpp);
}
private void createLight() {
Vector3f direction = new Vector3f(-0.1f, -0.7f, -1).normalizeLocal();
DirectionalLight dl = new DirectionalLight();
dl.setDirection(direction);
dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));
rootNode.addLight(dl);
}
@Override
public void simpleInitApp() {
bulletAppState = new BulletAppState();
bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL);
stateManager.attach(bulletAppState);
//bulletAppState.getPhysicsSpace().enableDebug(assetManager);
createLight();
initMaterial();
initTower();
initFloor();
setupKeys();
createCharacter();
setupChaseCamera();
setupAnimationController();
setupFilter();
}
@Override
public void simpleUpdate(float tpf) {
Vector3f camDir = cam.getDirection().clone().multLocal(0.2f);
Vector3f camLeft = cam.getLeft().clone().multLocal(0.2f);
camDir.y = 0;
camLeft.y = 0;
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());
}
if (!character.onGround()) {
airTime = airTime + tpf;
} else {
airTime = 0;
}
if (walkDirection.length() == 0) {
if (!“stand”.equals(animationChannel.getAnimationName())) {
animationChannel.setAnim(“stand”, 1f);
}
} else {
character.setViewDirection(walkDirection);
if (airTime > .3f) {
if (!“stand”.equals(animationChannel.getAnimationName())) {
animationChannel.setAnim(“stand”);
}
} else if (!“Walk”.equals(animationChannel.getAnimationName())) {
animationChannel.setAnim(“Walk”, 0.7f);
}
}
character.setWalkDirection(walkDirection);
}
private PhysicsSpace getPhysicsSpace() {
return bulletAppState.getPhysicsSpace();
}
public void onAction(String binding, boolean value, float tpf) {
if (binding.equals(“CharLeft”)) {
System.out.println(“LEFT…”);
if (value) {
left = true;
} else {
left = false;
}
} else if (binding.equals(“CharRight”)) {
System.out.println(“RIGHT…”);
if (value) {
right = true;
} else {
right = false;
}
} else if (binding.equals(“CharUp”)) {
System.out.println(“FORWARD…”);
if (value) {
up = true;
} else {
up = false;
}
} else if (binding.equals(“CharDown”)) {
System.out.println(“BACKWARDS…”);
if (value) {
down = true;
} else {
down = false;
}
} else if (binding.equals(“CharSpace”)) {
System.out.println(“JUMP…”);
character.jump();
}
}
private void setupKeys() {
inputManager.addMapping(“wireframe”, new KeyTrigger(KeyInput.KEY_T));
inputManager.addListener(this, “wireframe”);
inputManager.addMapping(“CharLeft”, new KeyTrigger(KeyInput.KEY_LEFT));
inputManager.addMapping(“CharRight”, new KeyTrigger(KeyInput.KEY_RIGHT));
inputManager.addMapping(“CharUp”, new KeyTrigger(KeyInput.KEY_UP));
inputManager.addMapping(“CharDown”, new KeyTrigger(KeyInput.KEY_DOWN));
inputManager.addMapping(“CharSpace”, new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping(“CharShoot”, new KeyTrigger(KeyInput.KEY_LSHIFT));
inputManager.addListener(this, “CharLeft”);
inputManager.addListener(this, “CharRight”);
inputManager.addListener(this, “CharUp”);
inputManager.addListener(this, “CharDown”);
inputManager.addListener(this, “CharSpace”);
inputManager.addListener(this, “CharShoot”);
}
private void createCharacter() {
CapsuleCollisionShape capsule = new CapsuleCollisionShape(.4f, 2f);
character = new CharacterControl(capsule, .6f);
model = (Node) assetManager.loadModel(“Models/Oto/Oto.mesh.xml”);
model.setLocalScale(0.25f);
model.addControl(character);
character.setPhysicsLocation(new Vector3f(15, 80, 0));
rootNode.attachChild(model);
getPhysicsSpace().add(character);
System.out.println(“model local=”+model.getWorldTranslation());
}
private void setupAnimationController() {
animationControl = model.getControl(AnimControl.class);
animationControl.addListener(this);
animationChannel = animationControl.createChannel();
shootingChannel = animationControl.createChannel();
shootingChannel.addBone(animationControl.getSkeleton().getBone(“uparm.right”));
shootingChannel.addBone(animationControl.getSkeleton().getBone(“arm.right”));
shootingChannel.addBone(animationControl.getSkeleton().getBone(“hand.right”));
}
public void initTower() {
double stepX = 0;
double stepY = 0;
double stepZ = 0;
double railX = 0;
double railZ = 0;
double innerRailX = 0;
double innerRailZ = 0;
stepAngle = 0f;
railAngle = 0f;
innerRailAngle = 0f;
for (int i = 0; i < stepLayers; i++){
// Increment rows
if(i!=0)
stepY+=stepHeight2;
else
stepY=stepHeight;
// Alternate brick seams
stepAngle = 360.0f / stepsPerLayer i/24f;
railAngle = 360.0f / stepsPerLayer i/24f;
innerRailAngle = 360.0f / stepsPerLayer i/24f;
for (int j = 0; j < stepsPerLayer; j++){
stepZ = Math.cos(Math.toRadians(stepAngle))stepRadius;
stepX = Math.sin(Math.toRadians(stepAngle))stepRadius;
railZ = Math.cos(Math.toRadians(railAngle))(stepRadius+stepDepth-railDepth);
railX = Math.sin(Math.toRadians(railAngle))(stepRadius+stepDepth-railDepth);
innerRailZ = Math.cos(Math.toRadians(innerRailAngle))(stepRadius-stepDepth+railDepth);
innerRailX = Math.sin(Math.toRadians(innerRailAngle))*(stepRadius-stepDepth+railDepth);
// System.out.println(“x=”+((float)(stepX))+" y="+((float)(stepY))+" z="+(float)(stepZ));
Vector3f vtS = new Vector3f((float)(stepX), (float)(stepY), (float)(stepZ));
Vector3f vtR = new Vector3f((float)(railX), (float)(stepY+railHeight+stepHeight), (float)(railZ));
Vector3f vtInnerRail = new Vector3f((float)(innerRailX), (float)(stepY+railHeight+stepHeight), (float)(innerRailZ));
addBrick(vtS, vtR, vtInnerRail);
stepAngle += 360.0/stepsPerLayer;
railAngle += 360.0/stepsPerLayer;
innerRailAngle += 360.0/stepsPerLayer;
}
}
}
public void initFloor() {
Box floorBox = new Box(Vector3f.ZERO, 25f, 0.1f, 25f);
floorBox.scaleTextureCoordinates(new Vector2f(3, 6));
Geometry floor = new Geometry(“floor”, floorBox);
floor.setMaterial(mat3);
floor.setShadowMode(ShadowMode.Receive);
floor.setLocalTranslation(0, -0.1f, 0);
floor.addControl(new RigidBodyControl(0));
this.rootNode.attachChild(floor);
this.getPhysicsSpace().add(floor);
}
public void initMaterial() {
mat = new Material(assetManager, “Common/MatDefs/Misc/SimpleTextured.j3md”);
TextureKey key = new TextureKey(“Textures/Terrain/BrickWall/BrickWall.jpg”);
key.setGenerateMips(true);
Texture tex = assetManager.loadTexture(key);
mat.setTexture(“ColorMap”, tex);
mat2 = new Material(assetManager, “Common/MatDefs/Misc/SimpleTextured.j3md”);
TextureKey key2 = new TextureKey(“Textures/Terrain/Rock/Rock.PNG”);
key2.setGenerateMips(true);
Texture tex2 = assetManager.loadTexture(key2);
mat2.setTexture(“ColorMap”, tex2);
mat3 = new Material(assetManager, “Common/MatDefs/Misc/SimpleTextured.j3md”);
TextureKey key3 = new TextureKey(“Textures/Terrain/Pond/Pond.png”);
key3.setGenerateMips(true);
Texture tex3 = assetManager.loadTexture(key3);
tex3.setWrap(WrapMode.Repeat);
mat3.setTexture(“ColorMap”, tex3);
}
public void addBrick(Vector3f stepV, Vector3f railV, Vector3f innerRailV) {
Geometry reBoxg = new Geometry(“brick”, brick);
reBoxg.setMaterial(mat);
reBoxg.setLocalTranslation(stepV);
reBoxg.rotate(0f, (float)Math.toRadians(stepAngle) , 0f );
reBoxg.addControl(new RigidBodyControl(0f));
reBoxg.setShadowMode(ShadowMode.CastAndReceive);
reBoxg.getControl(RigidBodyControl.class).setFriction(1.6f);
this.rootNode.attachChild(reBoxg);
this.getPhysicsSpace().add(reBoxg);
Geometry reBoxgRail = new Geometry(“rail”, rail);
reBoxgRail.setMaterial(mat);
reBoxgRail.setLocalTranslation(railV);
reBoxgRail.rotate(0f, (float)Math.toRadians(railAngle) , 0f );
reBoxgRail.addControl(new RigidBodyControl(0f));
reBoxgRail.setShadowMode(ShadowMode.CastAndReceive);
reBoxgRail.getControl(RigidBodyControl.class).setFriction(1.6f);
this.rootNode.attachChild(reBoxgRail);
this.getPhysicsSpace().add(reBoxgRail);
Geometry reBoxgInnerRail = new Geometry(“rail”, rail);
reBoxgInnerRail.setMaterial(mat);
reBoxgInnerRail.setLocalTranslation(innerRailV);
reBoxgInnerRail.rotate(0f, (float)Math.toRadians(innerRailAngle) , 0f );
reBoxgInnerRail.addControl(new RigidBodyControl(0f));
reBoxgInnerRail.setShadowMode(ShadowMode.CastAndReceive);
reBoxgInnerRail.getControl(RigidBodyControl.class).setFriction(1.6f);
this.rootNode.attachChild(reBoxgInnerRail);
this.getPhysicsSpace().add(reBoxgInnerRail);
}
public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
if (channel == shootingChannel) {
channel.setAnim(“stand”);
}
}
public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
}
}
/pre
a note, if you are trying to control Oto please note the mappings, I made Oto controlled by the UP, DOWN, LEFT, RIGHT buttons instead of WASD because I am having trouble with using WASD. When I hit S in any example or any code I write the camera or character just keeps backing up even when I let off, it stops if I hit W, but does not go forward. Does anyone know if this a bug in the current release?
Hehehe you like Lego don’t you?