第三人称视图控件演示中的错误

时间:2012-01-10 01:10:03

标签: java math opengl lwjgl

所以,我正在尝试制作第三人称视图控件演示。此演示将显示执行以下操作的能力:

1)围绕“播放器”旋转相机。

2)根据您按下操纵杆的方向和相机的方向移动播放器。

3)根据玩家角度和摄像机角度显示广告牌玩家精灵的正确角度。

现在1和2正在工作,但我无法弄清楚显示正确的敌人角度有什么不对。

这是我到目前为止所获得的相关代码:

private void updateLogic(int delta) {

        if (joystick != null) {
            joystick.poll();


            rjoyAngle += ((joystick.getRXAxisValue()/5) );
            rjoyAngle = ((rjoyAngle + 360) % 360);

            System.out.println("rangle = " + rjoyAngle);


            camPos.x = (float) (player.pos.x - (Math.sin(rjoyAngle) * camRadius));
            camPos.z = (float) (player.pos.z + (Math.cos(-rjoyAngle) * camRadius));

            camYaw = (float) ((Math.toDegrees(((Math.atan2(-(camPos.x - player.pos.x), -(camPos.z - player.pos.z)))))+ 360) % 360);
            System.out.println("Cam X: " + camPos.x + " Z: " + camPos.z + " yaw: " + camYaw);


            float pyaw = ((player.yaw + 360) % 360);
            float eyaw = ((camYaw + 360) % 360);
            dirYaw = (pyaw + eyaw) % 360;

            if(joystick.getXAxisValue() >= -0.5f && joystick.getXAxisValue() <= 0.5f &&  joystick.getYAxisValue() >= -0.5f &&  joystick.getYAxisValue() <= 0.5f){
                //deadzone?
            }

            else{
                player.yaw = (float) Math.toDegrees(Math.atan2(joystick.getXAxisValue(), joystick.getYAxisValue()));
                pyaw = ((player.yaw + 360) % 360);
                eyaw = ((camYaw + 360) % 360);
                dirYaw = (pyaw + eyaw) % 360;
                Vector3f move = new Vector3f();
                move.x -= 3 * (float)Math.sin(Math.toRadians(dirYaw));
                move.z -= 3 * (float)Math.cos(Math.toRadians(dirYaw));

                Vector3f.add(player.pos, move, player.pos);

            }

            pyaw = ((player.yaw + 360) % 360);
            eyaw = ((camYaw + 360) % 360);
            playerViewYaw = (dirYaw + eyaw) % 360;
        }

        player.update();
    }

draw和getSpriteNumber方法:

private void renderGL() {

        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
        loadIdentity(); // Reset The View


        floorTex.bind();
        GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
        GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);

        GL11.glBegin(GL11.GL_QUADS); // Start Drawing The Cube
            GL11.glColor3f(1.0f, 1.0f, 1.0f); // Set The Color To White
                GL11.glTexCoord2f(0,0);                                                                             GL11.glVertex3f(-fieldSize, -groundDepth, -fieldSize);  // Top left Of The Quad (bottom)
                GL11.glTexCoord2f(fieldSize/floorTex.getTextureWidth(),0);                                          GL11.glVertex3f(fieldSize, -groundDepth, -fieldSize);   // Top right Of The Quad (bottom)
                GL11.glTexCoord2f(fieldSize/floorTex.getTextureWidth(),fieldSize/floorTex.getTextureHeight());      GL11.glVertex3f(fieldSize, -groundDepth, fieldSize);  // Bottom right Of The Quad (bottom)
                GL11.glTexCoord2f(0,fieldSize/floorTex.getTextureHeight());                                         GL11.glVertex3f(-fieldSize, -groundDepth, fieldSize);   // Bottom left Of The Quad (bottom)
        GL11.glEnd(); // Done Drawing The Quad

        int direction = getSpriteNum(playerViewYaw);

        drawBillBoardSprite(playerTex[0][direction],player.pos, 0, 1,1,1, 5, 10);   
    }


    public int getSpriteNum(float direction){
        direction = (float) Math.abs(Math.floor((direction + 22.5) / 45.0));

    //  direction = direction * 2;

        if (direction == 8) direction = 0;

        return (int)direction;
    }

这应该是你需要看到的唯一代码,但我会发布所有这些只是为了安全,我甚至会给你们一个拉链项目。

Dream.java:

import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Controller;
import org.lwjgl.input.Controllers;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;

import org.lwjgl.util.vector.Vector3f;

import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;

public class Dream {

    String windowTitle = "Dream - By William Starkovich";
    public boolean closeRequested = false;

    Player player;
    Vector3f camPos;
    float camYaw;
    float camRadius;
    float rjoyAngle = 0;
    Controllers controllers ;
    Controller joystick;
    Texture playerTex[][];
    Texture floorTex;
    float dirYaw;
    float playerViewYaw;
    long lastFrameTime; // used to calculate delta
    float fieldSize = 500;
    float groundDepth = 5;

    public void run() {

        createWindow();
        getDelta(); // Initialise delta timer
        init();
        initGL();


        while (!closeRequested) {
            pollInput(getDelta());
            updateLogic(getDelta());
            renderGL();

            Display.update();
            Display.sync(60);

        }

        cleanup();
    }


    public void init(){
        player = new Player(0,0,0);
        camRadius = 25;
        camYaw = 0;
        camPos = new Vector3f(0,0,-camRadius);
        playerTex = new Texture[1][8];

        try{

             floorTex = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("data/graphics/floor.png"));                 

             for(int i = 0; i < 1; i++){
                 for(int j = 0; j < 8; j++){
                     playerTex[i][j] = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("data/graphics/player/enemy"+i+"-"+j+".png"));
                 }
             }

             controllers = new Controllers();
             Controllers.create();
               if (Controllers.getControllerCount() > 0) {
                   joystick = Controllers.getController(0);
                   joystick.setXAxisDeadZone(0.7f);
                   joystick.setYAxisDeadZone(0.7f);
                   joystick.setRXAxisDeadZone(0.7f);
                   joystick.setRYAxisDeadZone(0.7f);
                   System.out.println("Joystick has "+joystick.getButtonCount() +" buttons. Its name is "+joystick.getName());
               }
               else joystick = null;
        }

        catch(Exception e){
            e.printStackTrace();
        }
    }

    private void initGL() {

        /* OpenGL */
        int width = Display.getDisplayMode().getWidth();
        int height = Display.getDisplayMode().getHeight();

        GL11.glViewport(0, 0, width, height); // Reset The Current Viewport
        GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
        GL11.glLoadIdentity(); // Reset The Projection Matrix
        GLU.gluPerspective(45.0f, ((float) width / (float) height), 0.1f, 600.0f); // Calculate The Aspect Ratio Of The Window
        GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
        GL11.glLoadIdentity(); // Reset The Modelview Matrix

        GL11.glShadeModel(GL11.GL_SMOOTH); // Enables Smooth Shading
        GL11.glClearColor(0, 0.3f, 0.5f, 1f); // Black Background
        GL11.glClearDepth(1.0f); // Depth Buffer Setup
        GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing
        GL11.glDepthFunc(GL11.GL_LEQUAL); // The Type Of Depth Test To Do
        GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST); // Really Nice Perspective Calculations
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glEnable(GL11.GL_BLEND);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
        GL11.glEnable(GL11.GL_ALPHA_TEST);
        GL11.glAlphaFunc(GL11.GL_GREATER, 0.9f);
    }

    private void updateLogic(int delta) {

        if (joystick != null) {
            joystick.poll();


            rjoyAngle += ((joystick.getRXAxisValue()/5) );
            rjoyAngle = ((rjoyAngle + 360) % 360);

            System.out.println("rangle = " + rjoyAngle);


            camPos.x = (float) (player.pos.x - (Math.sin(rjoyAngle) * camRadius));
            camPos.z = (float) (player.pos.z + (Math.cos(-rjoyAngle) * camRadius));

            camYaw = (float) ((Math.toDegrees(((Math.atan2(-(camPos.x - player.pos.x), -(camPos.z - player.pos.z)))))+ 360) % 360);
            System.out.println("Cam X: " + camPos.x + " Z: " + camPos.z + " yaw: " + camYaw);


            float pyaw = ((player.yaw + 360) % 360);
            float eyaw = ((camYaw + 360) % 360);
            dirYaw = (pyaw + eyaw) % 360;

            if(joystick.getXAxisValue() >= -0.5f && joystick.getXAxisValue() <= 0.5f &&  joystick.getYAxisValue() >= -0.5f &&  joystick.getYAxisValue() <= 0.5f){
                //deadzone?
            }

            else{
                player.yaw = (float) Math.toDegrees(Math.atan2(joystick.getXAxisValue(), joystick.getYAxisValue()));
                pyaw = ((player.yaw + 360) % 360);
                eyaw = ((camYaw + 360) % 360);
                dirYaw = (pyaw + eyaw) % 360;
                Vector3f move = new Vector3f();
                move.x -= 3 * (float)Math.sin(Math.toRadians(dirYaw));
                move.z -= 3 * (float)Math.cos(Math.toRadians(dirYaw));

                Vector3f.add(player.pos, move, player.pos);

            }

            pyaw = ((player.yaw + 360) % 360);
            eyaw = ((camYaw + 360) % 360);
            playerViewYaw = (dirYaw + eyaw) % 360;
        }

        player.update();
    }


    private void loadIdentity(){
        /* OpenGL */
        int width = Display.getDisplayMode().getWidth();
        int height = Display.getDisplayMode().getHeight();

        GL11.glLoadIdentity(); // Reset The Modelview Matrix
        //roatate the yaw around the Y axis
        GL11.glRotatef(camYaw, 0.0f, -1.0f, 0.0f);
        GL11.glTranslatef(camPos.x, -3, camPos.z);
    }

    private void renderGL() {

        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
        loadIdentity(); // Reset The View


        floorTex.bind();
        GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
        GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);

        GL11.glBegin(GL11.GL_QUADS); // Start Drawing The Cube
            GL11.glColor3f(1.0f, 1.0f, 1.0f); // Set The Color To White
                GL11.glTexCoord2f(0,0);                                                                             GL11.glVertex3f(-fieldSize, -groundDepth, -fieldSize);  // Top left Of The Quad (bottom)
                GL11.glTexCoord2f(fieldSize/floorTex.getTextureWidth(),0);                                          GL11.glVertex3f(fieldSize, -groundDepth, -fieldSize);   // Top right Of The Quad (bottom)
                GL11.glTexCoord2f(fieldSize/floorTex.getTextureWidth(),fieldSize/floorTex.getTextureHeight());      GL11.glVertex3f(fieldSize, -groundDepth, fieldSize);  // Bottom right Of The Quad (bottom)
                GL11.glTexCoord2f(0,fieldSize/floorTex.getTextureHeight());                                         GL11.glVertex3f(-fieldSize, -groundDepth, fieldSize);   // Bottom left Of The Quad (bottom)
        GL11.glEnd(); // Done Drawing The Quad

        int direction = getSpriteNum(playerViewYaw);

        drawBillBoardSprite(playerTex[0][direction],player.pos, 0, 1,1,1, 5, 10);   
    }


    public int getSpriteNum(float direction){
        direction = (float) Math.abs(Math.floor((direction + 22.5) / 45.0));

    //  direction = direction * 2;

        if (direction == 8) direction = 0;

        return (int)direction;
    }

    public void drawBillBoardSprite(Texture texture, Vector3f sprPos, float y, float r, float g, float b, float sprWidth, float sprHeight){
         // store the current model matrix
        GL11.glPushMatrix();
            GL11.glColor3f(r,g,b);
            GL11.glTranslatef(-sprPos.x, y, -sprPos.z);
            // bind to the appropriate texture for this sprite
            texture.bind();

            FloatBuffer modelview = BufferUtils.createFloatBuffer(16);

            // get the current modelview matrix
            GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelview);

            // Note that a row in the C convention is a column 
            // in OpenGL convention (see the red book, pg.106 in version 1.2)
            // right vector is [1,0,0]  (1st column)
            // lookAt vector is [0,0,1] (3d column)
            // leave the up vector unchanged (2nd column)
            // notice the increment in i in the first cycle (i+=2)
            for(int i=0; i<3; i+=2 ) 
                for(int j=0; j<3; j++ ) {
                    if ( i==j )
                        modelview.put(i*4+j, 1.0f);
                    else
                        modelview.put(i*4+j, 0.0f);
                }

            // set the modelview matrix
            GL11.glLoadMatrix(modelview);

            // draw a quad textured to match the sprite
            GL11.glBegin(GL11.GL_QUADS);
                GL11.glTexCoord2f(0,0);                                     GL11.glVertex3f((float) - (sprWidth/2),(float) (sprHeight/2), 0);    // Top left Of The Quad (Left)
                GL11.glTexCoord2f(texture.getWidth(), 0);                   GL11.glVertex3f((float) + (sprWidth/2),(float) (sprHeight/2), 0);  // Top right Of The Quad (Left)
                GL11.glTexCoord2f(texture.getWidth(), texture.getHeight()); GL11.glVertex3f((float) + (sprWidth/2),(float) -(sprHeight/2), 0);   // Bottom right Of The Quad (Left)
                GL11.glTexCoord2f(0, texture.getHeight());                  GL11.glVertex3f((float) - (sprWidth/2),(float) -(sprHeight/2), 0);   // Bottom left Of The Quad (Left)
            GL11.glEnd();

        // restore the model view matrix to prevent contamination
        GL11.glPopMatrix();
    }

    /**
     * Poll Input
     */
    public void pollInput(float delta) {    

        if (Keyboard.isKeyDown(Keyboard.KEY_F12)){
            closeRequested = true;
        }

        if (Display.isCloseRequested()) {
            closeRequested = true;
        }
    }

    /** 
     * Calculate how many milliseconds have passed 
     * since last frame.
     * 
     * @return milliseconds passed since last frame 
     */
    public int getDelta() {
        long time = (Sys.getTime() * 1000) / Sys.getTimerResolution();
        int delta = (int) (time - lastFrameTime);
        lastFrameTime = time;

        return delta;
    }


    private void createWindow() {
        try {
            Display.setDisplayMode(new DisplayMode(640, 480));
            Display.setFullscreen(true);
            Display.setVSyncEnabled(true);
            Display.setTitle(windowTitle);
            Display.create();

            //hide the mouse
            Mouse.setGrabbed(true);
        } catch (LWJGLException e) {
            Sys.alert("Error", "Initialization failed!\n\n" + e.getMessage());
            System.exit(0);
        }
    }

    /**
     * Destroy and clean up resources
     */
    private void cleanup() {
        Display.destroy();
    }

    public static void main(String[] args) {
        Dream dream = new Dream();
        dream.run();
    }
}

Player.java:

import java.util.Vector;

import org.lwjgl.util.vector.Vector3f;


public class Player {
    float mouseSensitivity = 0.05f;
    float movementSpeed = 0.04f; //move 10 units per second

    Vector3f pos;
    float yaw = 0;
    float pitch = 0;
    float maxPitch = 90;

    float width = 1;
    float height = 1;

    int inFieldType = 0;


    public Player(float sx, float sz, float sa){
        pos = new Vector3f(sx,0,sz);
        yaw = sa;
    }

    public void update(){

    }
}

这是演示项目(在Eclipse中): http://dl.dropbox.com/u/28109593/Dream.zip

1 个答案:

答案 0 :(得分:0)

这是您的问题(updateLogic()第147/157和168行):

dirYaw = (pyaw + eyaw) % 360;
...
playerViewYaw = (dirYaw + eyaw) % 360;

您正在尝试计算播放器的观看方向,但您要执行两次相同的补偿。

(另外,我认为你会想要从玩家偏航中减去相机偏航以获得相机从中观察玩家的角度)。