General Questions - Dungeon Crawler

Identical, yes, similar, well thousands :stuck_out_tongue:

@.Ben. said: Identical, yes, similar, well thousands :P

Well, sure, but then the statement becomes about as meaningful as “There are thousands of ways to represent numbers similar to 5.”

Where as “for a given specific orientation, there are only two quaternions” is significant… especially as compared to “for a given specific orientation, there are near-inifinite euler angle triples…” (Infinite without floating point resolution messing it up.)

So to wrap up, the bottom line is:
when: q is a quaternion representing orientation
then effectively: q = -q

Yeah yeah, it’s just that the way he has it set up, it’s already so analogic that in the end, I fear his players will never go in straight lines anyway, unless the corridors are short enough for the floating point to not cause any problems.

Personnally, I would have used the PI constants instead of hardcoding floats. Just my 2 cents.

If anyone can show me any example code on how I should be doing this it would be really helpful

So, you let the player face any direction they want and you want to know whether they are generally facing north/south/east/west? (A probably we can easily solve… dot product to the rescue.)

Or…? Otherwise, if they can only face one of these directions anyway then why not set the camera to a cardinal direction instead of going the other way around.

So the player will move in a fixed grid movement and be able to rotate 90’ Left or Right at a time (like a old school dungeon crawler) take a look at this as this is the same as I’m trying to get smooth movement but with fixed rotation

Then don’t turn the camera, turn the player… let the camera follow the player. Then you will always know n/s/e/w because the direction will only ever be those.

I’m not turning the camera, I turn the ‘Party’ which is the Node holding the Geometry

@madmunky said: I'm not turning the camera, I turn the 'Party' which is the Node holding the Geometry

Then you shouldn’t need to do this:
[java]
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;
    }        
}

[/java]

Set the camera direction based on this.direction and not the other way around.

I though I updated that but I still get the same result with getting the Location


private void updateDirection(){
        
        Float dir = this.party.getLocalRotation().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.EAST;
        }
        else if (new Float(-0.7071067).equals(dir)){
            this.direction = playerDirection.WEST;
        }
    }

I think I have this working but no idea if this is the correct way


private void updateDirection(){
        
        //Direction Y: 0.99 - NORTH
        //Direction W: 0
        //Direction Y: 0.7 - EAST
        //Direction W: 0.7
        //Direction Y: 0 - SOUTH
        //Direction W: 0.99
        //Direction Y: -0.7 - WEST
        //Direction W: 0.7
        //Direction Y: -0.99 - NORTH
        //Direction W: 0
        //Direction Y: -0.7 - EAST
        //Direction W: -0.7
        //Direction Y: 0 - SOUTH
        //Direction W: -0.99
        //Direction Y: 0.7 - WEST
        //Direction W: -0.7
        
        DecimalFormat df = new DecimalFormat("##.##");
        df.setRoundingMode(RoundingMode.DOWN);
        String dirY = df.format(this.party.getWorldRotation().getY());
        String dirW = df.format(this.party.getWorldRotation().getW());        
        
        if (dirY.equals("0.99") && dirW.equals("0") || dirY.equals("-0.99") && dirW.equals("0") ){
            this.direction = playerDirection.NORTH;
        }
        else if (dirY.equals("0.7") && dirW.equals("0.7") || dirY.equals("-0.7") && dirW.equals("-0.7") ){
            this.direction = playerDirection.EAST;
        }
        else if (dirY.equals("0") && dirW.equals("0.99") || dirY.equals("0") && dirW.equals("-0.99") ){
            this.direction = playerDirection.SOUTH;
        }
        else if (dirY.equals("-0.7") && dirW.equals("0.7") || dirY.equals("0.7") && dirW.equals("-0.7") ){
            this.direction = playerDirection.WEST;
        }
        
        System.out.println("Player Direction: " + this.direction);
    }

OK but my question is, why not use the PI constants instead of floats? Also Paul’s suggestion combined:

In your “party” class, make a facing_direction member variable. This will store what direction the party is facing in the form of like: playerDirection.SOUTH

Also, in the your “party” class, make a member function to turn SIMILAR to (may be wrong, feel free to correct me):

[java]
function turn(boolean is_turning_right){
switch(this.facing_direction){
case playerDirection.SOUTH:
this.facing_direction = (is_turning_right ? playerDirection.WEST : playerDirection.EAST);
float y_angle = (is_turning_right ? -FastMath.HALF_PI : FastMath.HALF_PI);
break;
case playerDirection.WEST:
this.facing_direction = (is_turning_right ? playerDirection.NORTH : playerDirection.SOUTH);
float y_angle = (is_turning_right ? 0 : FastMath.PI);
break;
case playerDirection.NORTH:
this.facing_direction = (is_turning_right ? playerDirection.EAST : playerDirection.WEST);
float y_angle = (is_turning_right ? FastMath.HALF_PI : -FastMath.HALF_PI);
break;
case playerDirection.EAST:
this.facing_direction = (is_turning_right ? playerDirection.SOUTH : playerDirection.NORTH);
float y_angle = (is_turning_right ? FastMath.PI : 0);
break;
}

        this.dat_party_node.setLocalRotation(new Quaternion(new float[]{0, y_angle, 0}));
    }

[/java]

(I assume you already set up your key mappings in your app, if not you can use something like this)
[java]
inputManager.addMapping(“Left”, new KeyTrigger(KeyInput.KEY_A));
inputManager.addListener(this, “Left”);
[/java]

Then when a player presses the LEFT key, you can rotate 1 step to the left, use something like this:

[java]
@Override
public void onAction(String binding, boolean isPressed, float tpf) {
switch (binding) {
case “Left”:
if(isPressed){
dat_party.turn(false); // “is_turning_right” -> FALSE
}
break;
case “Right”:
if(isPressed){
dat_party.turn(true); // “is_turning_right” -> TRUE
}
break;
}
}
[/java]

I mean, that’s it, no float numbers or anything unprecise. Correct me if I’m wrong, I just tossed this here like that on top of my head.

[java]
public enum Direction {
North(0), South(FastMath.PI), East(FastMath.HALF_PI), West(-FastMath.HALF_PI);

private float angleRads;
private Direction( float rads ) {
    this.angleRads = rads;
}

public Direction turn( boolean left ) {
    switch(this) {
        case North: return left ? West : East;
        case South: return left ? East : West;
        case East: return left ? North : South;
        case West: return left ? South : East;
        default: return null; // never happens
    }
}

public float angleRads() {
    return angleRads;
}

}
[/java]

Then just use Direction is your direction.

private Direction dir;

To turn left, dir = dir.turn(true);

To turn right, dir = dir.turn(false);

To set the camera:
cam.setRotation(new Quaternion().fromAngles(0, dir.angleRads(), 0);
…or whatever. (Note: I think angleRads needs to be adjusted for the x/z plane for -z to be north if that’s desired.)

Thank pspeed

You had one typeo

case West: return left ? South : North;

But apart from that it works, thanks everyone for the help finally able to walk around my level :slight_smile:

Woop 2 Players :slight_smile:

Thanks again all for the help, am taking baby steps at a time but still enjoying it.

New question…

So at the moment because I use a CameraNode to follow my Spatial (CameraNode.setControlDir(CameraControl.ControlDirection.SpatialToCamera)) I’m trying to play around with the Camera setFrustumPerspective but no matter what I do it looks horrible

It seems to make the width (X) of everything OK but stretches it in the Y really badly so everythink looks really long is there a batter way of getting the result I want, the problem I have is the standard Frustum is OK but it seem the camera is on the front edge of my Spatial rather than in the middle

Hopefully that makes a little sense :s

Your code looks fine from here, wink wink.

Code related to the Frustum :slight_smile:

        float aspect = (float)this.cam.getWidth() / (float)this.cam.getHeight();
        aspect += 0.3;
        this.cam.setFrustumPerspective(90, aspect, 0.1f, 13);
        
        if (Main.player[0] == null){
            this.cam.setViewPort(0.25f , 0.75f  ,  0.0f , 0.5f);            
        }else{
            this.cam.setViewPort(0.25f , 0.75f  ,  0.5f , 1.0f);            
        }

        for (int x = 0;x < player.length;x++){
            ViewPort viewPortx = renderManager.createMainView(String.format("player<%s>ViewPort",x), player[x].cam); 
            viewPortx.attachScene(rootNode);
            player[x].vp = viewPortx;
            rootNode.attachChild(player[x].party);      
            rootNode.addLight(player[x].light);
            //System.out.println(player[x].cam.getName());
        }

[java]
float aspect = (float)this.cam.getWidth() / (float)this.cam.getHeight();
aspect += 0.3;
this.cam.setFrustumPerspective(90, aspect, 0.1f, 13);
[/java]

a) what’s the magic 0.3 for?

b) why such an incredibly short far plane?

a) Just playing around
b) Trying to emulate the distance you could see in the original game