General Questions - Dungeon Crawler

Hi All,

I’ve just joined the forum and just started out with jMonkeyEngine (Also my first time playing with 3D) anyways my plan is to make a game I’ve been doing in HTML (www.bloodwych.co.uk) but in 3D for a couple of reasons.

I want to learn Java
3D looks nice and gives me nice effects (jMonkeyEngine looks really good)
Its all new stuff to learn (Which is always fun, even if its stressful)

So I started a few days ago playing around with making shapes/lighting/shadows/cameras and came up with this

I’m really after a bit of help or pointing to the right posts for a few issues I’m facing

I want the game will be like Grimrock (grimrock.net) but for two players, I’ll list the issues I’m currently having and any advise/help would be welcome

My player is a box which will be step bases movement. I’ve got the player strafing left/right and moving backward/forwards but I cant get the camera to rotate even then though my player box does. Im using a CameraNode connected to my player Node but two things I find.

  1. The camera does not move with the player unless I update the cam.setLocation manually I thought it would follow the player as its attached?
  2. I cant get the camera to rotate left/right

My next question is about Assets I have created a new folder ‘DataFiles’ which holds my map files, I use a Java FileInputStream to load the files but whats the best way of saying the location?

Next question is about speed, does jMonkeyEngine know what is visible to the camera and only draw whats needed or do I need to do the logic to only draw/load whats visible to the player?

Last question (for the moment) is I want to make a Torch like effect with the camera lighting flickers that’s following the player, I thought maybe doing a Random update on the .setRadius of the PointLight that I use but is that correct? Something like cameraLight.setRadius(15+r.nextFloat())

I really appreciate any help, I’m not a good programming and T suck at math so the project is pretty doomed but I enjoy playing :slight_smile:

Maybe someones already done a 3D Maze type game they have posted the source, I’ve tried searching for the answers but do far not managed to find the answers.

Hi and welcome!
I am also pretty new to JME but I think I can help you with at least two of your questions:

My next question is about Assets I have created a new folder ‘DataFiles’ which holds my map files, I use a Java FileInputStream to load the files but whats the best way of saying the location?

I handle this with having a folder called ‘data’. This has always to be at the same location as the jar after exporting but I can access it with using the path “data/”. I used a constant String to save this so I can easily change it if I change the folder’s name. This way I can also use a specific folder while I am at the SDK and just have to move it to teh jar after exporting. My lines for this are:
(Just switch the comments)

//public static String PATH = "data/";
public static String PATH = "D:/TST_JME/";
jMonkeyEngine know what is visible to the camera and only draw whats needed or do I need to do the logic to only draw/load whats visible to the player?

If I am not totally wrong only stuff is drawn that is actually visible but many spatials attached to the rootNode do also slow down the performance. For this I detach every Spatial after every 10 updates and check if they are still visible to the cam:

rootNode.detachAllChildren();

for(int i = 0; i < spatialListCheck.size(); i++)
{
                
   if(GraphicTools.isVisibleToCam(getCamera(), spatialListCheck.get(i).SPATIAL))
   {
                  
       rootNode.attachChild(spatialListCheck.get(i).SPATIAL);
   }
}

I hope this helps you a little :slight_smile:

1 Like
@madmunky said: My player is a box which will be step bases movement. I've got the player strafing left/right and moving backward/forwards but I cant get the camera to rotate even then though my player box does. Im using a CameraNode connected to my player Node but two things I find.
  1. The camera does not move with the player unless I update the cam.setLocation manually I thought it would follow the player as its attached?
  2. I cant get the camera to rotate left/right

We’d have to see the code.

@madmunky said: My next question is about Assets I have created a new folder 'DataFiles' which holds my map files, I use a Java FileInputStream to load the files but whats the best way of saying the location?

You could put them in the asset folder and they will get jarred with the other assets. Then you can use the asset manager to find them or just load it as a class resource.

@madmunky said: Next question is about speed, does jMonkeyEngine know what is visible to the camera and only draw whats needed or do I need to do the logic to only draw/load whats visible to the player?

Objects are not rendered if they are not on the screen. They are “updated”, though. If you have several thousand objects then it’s worth considering some way of reducing it… common way is paging of some kind.

Thanks both for replying, as for the code currently for the camera this is what i do…

excuse the code, its all just code to learn the basics


public class Main extends SimpleApplication {

   // public SpotLight lamp = new SpotLight(); 
    Node player = new Node();//new Geometry("Player",b)
    Boolean isRunning=true;
    CameraNode playerView = null;
    PointLight cameraLight = new PointLight();
    Random r = new Random();
    FilterPostProcessor fpp = null;
    PointLightShadowFilter dlsf = null;
            
    public static void main(String[] args) {
        Main app = new Main();
        AppSettings settings = new AppSettings(true);
        settings.setResolution(1024, 768);
        app.setSettings(settings);
        app.setShowSettings(false);        
        app.start();     
                
    }

    @Override
    public void simpleInitApp() {
        flyCam.setEnabled(false);
        //flyCam.setMoveSpeed(20);
        //flyCam.setRotationSpeed(3);
        
        createLevelGrid(30,30);             
        Box b = new Box(1.5f,1,1.5f);
        Geometry p = new Geometry("Player",b);
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setTexture("ColorMap", assetManager.loadTexture("Textures/No Texture.png"));
        mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);    
        p.setMaterial(mat);
        p.setLocalTranslation(new Vector3f(30,0,30));
        
        LightControl lightControl = new LightControl(cameraLight);
        p.addControl(lightControl);
        
        player.addLight(cameraLight);
        player.attachChild(p);      
        
        cameraLight.setRadius(15);
        cameraLight.setColor(ColorRGBA.White);
        
        rootNode.attachChild(player);      
        rootNode.addLight(cameraLight);
        
        PointLightShadowRenderer dlsr = new PointLightShadowRenderer(assetManager, 1);
        dlsr.setLight(cameraLight);
        viewPort.addProcessor(dlsr);

        dlsf = new PointLightShadowFilter(assetManager, 1);
        dlsf.setLight(cameraLight);
        dlsf.setEnabled(true);
        fpp = new FilterPostProcessor(assetManager);
        fpp.addFilter(dlsf);
        viewPort.addProcessor(fpp);
        cam.setLocation(p.getLocalTranslation());
        
        playerView = new CameraNode("playerCam",cam);
        playerView.setControlDir(CameraControl.ControlDirection.SpatialToCamera);
        player.attachChild(playerView);
        playerView.setLocalTranslation(p.getLocalTranslation());

    }

    @Override
    public void simpleUpdate(float tpf) {

            System.out.println("Location: " + cam.getLocation());
            System.out.println("Direction: " +cam.getDirection());
            System.out.println("Rotation: " +cam.getRotation());   
            
    }

    @Override
    public void simpleRender(RenderManager rm) {
        
    }

private ActionListener actionListener = new ActionListener() {
    public void onAction(String name, boolean keyPressed, float tpf) {

      Vector3f v = player.getLocalTranslation();
      Vector3f p = player.getChild("Player").getLocalTranslation();
      
        if (name.equals("Left")&& !keyPressed) {                    
          player.setLocalTranslation(v.x + 3f, v.y, v.z);
          playerView.setLocalTranslation(p.x,p.y,p.z-3f);
        cam.setLocation(playerView.getLocalTranslation());
        }
        if (name.equals("Right")&& !keyPressed) {          
          player.setLocalTranslation(v.x - 3f, v.y, v.z);
          playerView.setLocalTranslation(p.x,p.y,p.z-3f);
          cam.setLocation(playerView.getLocalTranslation());
        }
        if (name.equals("Forward")&& !keyPressed) {          
          player.setLocalTranslation(v.x, v.y, v.z+ 3f);
          playerView.setLocalTranslation(p.x,p.y,p.z-3f);
        cam.setLocation(playerView.getLocalTranslation());
        }
        if (name.equals("Backward")&& !keyPressed) {          
          player.setLocalTranslation(v.x, v.y, v.z- 3f);
          playerView.setLocalTranslation(p.x,p.y,p.z-3f);
          cam.setLocation(playerView.getLocalTranslation());
        }
        if (name.equals("Rotate_Right")&& !keyPressed) {
          player.getChild("Player").rotate(0,0.01f,0);
          cam.setRotation(new Quaternion().fromAngleAxis(FastMath.PI/4,   new Vector3f(1,0,0)));
        }        
    }
  };
  };

In addition to printing the camera values, print the playerView values… and then take out your cam.setLocation() overrides so that you can track down what’s happening.

Thanks pspeed: Its strange but now the Camera is moving with the Player object even without me updating the cam location :slight_smile:

Any ideas about rotation?

Print the values and see what they are doing. And then post the latest code.

@madmunky said: Its strange but now the Camera is moving with the Player object even without me updating the cam location :)

Well of course… you’ve put this in your code:

[java]
playerView = new CameraNode("playerCam",cam);
playerView.setControlDir(CameraControl.ControlDirection.SpatialToCamera); // <---- MAGICAL! :wink:
player.attachChild(playerView);
playerView.setLocalTranslation(p.getLocalTranslation());
[/java]

You don’t have to set the camera position every frame, the CameraControl.ControlDirection.SpatialToCamera already sticks it to the spatial so… it will always follow exactly the spatial position :smiley: It’s magical :wink:

@.Ben. said: Well of course... you've put this in your code:

[java]
playerView = new CameraNode("playerCam",cam);
playerView.setControlDir(CameraControl.ControlDirection.SpatialToCamera); // <---- MAGICAL! :wink:
player.attachChild(playerView);
playerView.setLocalTranslation(p.getLocalTranslation());
[/java]

You don’t have to set the camera position every frame, the CameraControl.ControlDirection.SpatialToCamera already sticks it to the spatial so… it will always follow exactly the spatial position :smiley: It’s magical :wink:

Yes, his point was that for some reason it wasn’t working before (thus this thread) but now it is and he feels like he didn’t change anything to fix it. Though without a sort of methodical (and boring) approach to fixing problems it happens quite often that one fixes something without knowing why.

I assumed he did change this before posting that it was working:

@pspeed said: take out your cam.setLocation() overrides so that you can track down what's happening.
@.Ben. said: I assumed he did change this before posting that it was working:

Yes, but the reason he had that was because the CameraNode wasn’t working for him… so he was setting stuff manually.

I told him to remove that for two reasons. 1) because then we could get better debugging values. 2) because I half thought it would work fine based on his problem and the code presented. Something else must have been causing camera node to fail before and now that’s fixed. There is more going on than we can see and that’s why rotation needs to be debugged next.

Hi All,

I think Benjamin D was right I must have added that to fix something else not realizing it also fixed my camera movement issue

So I have rotation working using the commands


        if (name.equals("Rotate_Right")&& !keyPressed) {
          playerView.rotate(new Quaternion().fromAngleAxis(FastMath.PI/2,   new Vector3f(0,-1,0)));
        } 
        if (name.equals("Rotate_Left")&& !keyPressed) {
          playerView.rotate(new Quaternion().fromAngleAxis(FastMath.PI/2,   new Vector3f(0,1,0)));
        } 

Now my last question that I asked was

Last question (for the moment) is I want to make a Torch like effect with the camera lighting flickers that’s following the player, I thought maybe doing a Random update on the .setRadius of the PointLight that I use but is that correct? Something like cameraLight.setRadius(15+r.nextFloat())

Anyone have any ideas about that one, as I now have another question as all my others have almost been answered

Given the type of game I trying to do normally the camera is set just behind the square the party would actually be on as being on the front edge of the square and seeing the wall in front would look pretty poo and because I am making a multiplayer game it means I have to actually draw the players party in game (4 characters on each edge of the square) which will mean im drawing the players party right in front of the camera and will block the view of the screen, is it possible to draw models that can only be seen by a certain camera.

So to understand better pictures always help

Example 1: What the camera should really see when in the square in front of the wall

Example 2: What I will be drawing as the last moveable square in front of the wall, so my party will actually be in the square.

1 Like

Why not cull that wall when the camera is positioned behind it? In other words, you could call that_wall.setCullHint(Spatial.CullHint.Always); to make it invisible and then that_wall.setCullHint(Spatial.CullHint.Dynamic); to revert it back to normal/visible. I guess the way to implement what you want depends largely on how you coded the walls themselves. Are you keeping them in an array, are they all square wall units independant or are you using only 1 geometry to draw a long wall that covers many units? I don’t know… you know better how to implement this I guess?

Or are you saying that you want the camera to “chase” the players instead of it being an FPS style camera?

No its a FPS style camera but that camera is always on the back edge of the square but if I do that and draw the party characters on the screen all the camera will be looking at its the back of the front two players.

OK This is driving me mad, so I’ve managed to fix most my issues and now I want to know if my Player is facing North/East/South/West


public static final Quaternion PITCH090 = new Quaternion().fromAngleAxis(-FastMath.PI/2,   new Vector3f(0,1,0));
public static final Quaternion RPITCH090 = new Quaternion().fromAngleAxis(FastMath.PI/2,   new Vector3f(0,1,0));

public void movePlayer(String name, boolean keyPressed, float tpf){
        
        Vector3f v = this.party.getLocalTranslation();

        if (name.equals("Left")&& !keyPressed) {                    
          this.party.setLocalTranslation(v.x + 3, v.y, v.z);   
          this.updateDirection();
        }
        if (name.equals("Right")&& !keyPressed) {          
          this.party.setLocalTranslation(v.x - 3, v.y, v.z);
          this.updateDirection();
        }
        if (name.equals("Forward")&& !keyPressed) {          
          this.party.setLocalTranslation(v.x, v.y, v.z+ 3);
          this.updateDirection();
        }
        if (name.equals("Backward")&& !keyPressed) {          
          this.party.setLocalTranslation(v.x, v.y, v.z- 3);
          this.updateDirection();
        }
        if (name.equals("Rotate_Right")&& !keyPressed) {
            this.party.rotate(PITCH090);
            this.updateDirection();
        } 
        if (name.equals("Rotate_Left")&& !keyPressed) {
         this.party.rotate(RPITCH090);
         this.updateDirection();
        } 
        if (!keyPressed){
            //printDebug();    
            
        }
        
        
        
    }
    
    private void updateDirection(){

        Float dir = this.cam.getRotation().getY();
        System.out.println("Dir: " + this.party.getLocalRotation());
        
        if (new Float(0.0).equals(dir)){
            this.direction = playerDirection.SOUTH;
        }
        else if (new Float(-0.9999999).equals(dir)){
            this.direction = playerDirection.NORTH;
        }
        else if (new Float(0.7071067).equals(dir)){
            this.direction = playerDirection.SOUTH;
        }
        else if (new Float(-0.7071067).equals(dir)){
            this.direction = playerDirection.WEST;
        }        
    }

This prints out this (This is me rotating 360x2)

Dir: (0.0, -0.70710677, 0.0, 0.70710677)
Dir: (0.0, -0.99999994, 0.0, 0.0)
Dir: (0.0, -0.7071067, 0.0, -0.7071067)
Dir: (0.0, 0.0, 0.0, -0.9999999)
Dir: (0.0, 0.7071067, 0.0, -0.7071067)
Dir: (0.0, 0.9999999, 0.0, 0.0)
Dir: (0.0, 0.7071067, 0.0, 0.7071067)
Dir: (0.0, 0.0, 0.0, 0.9999999)

From stackoverflow.com:
“Also note that generally speaking, you want to compare two floats/doubles by seeing if they’re very close, not if they’re exactly equal. This is due to rounding errors that floats can accumulate, especially when a decimal number can’t be exactly represented as a float (e.g. 0.1)”.

One way, probably sub-optimal, would be to multiply a north vector by the rotation of your player and use that data to infer the direction.

Thanks by why do I get a completely different output when at the same rotation after spinning once

Dir: (0.0, -0.70710677, 0.0, 0.70710677) - North
vs
Dir: (0.0, 0.7071067, 0.0, -0.7071067) - North

Well, The W component (4th one) is what makes it similar to the previous rotation.

There are more than 1 way to represent a similar orientation in a quaternion.

@.Ben. said: Well, The W component (4th one) is what makes it similar to the previous rotation.

There are more than 1 way to represent a similar orientation in a quaternion.

Exactly two, in fact.