Spiral Staircase Code

Here is a modified version of the brick tower code I just posted that generates a spiral staircase. Also I included Oto in there :slight_smile:







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+=stepHeight
2;


            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?

:wink: