簡體   English   中英

第三人稱視角控制演示中的錯誤

[英]Errors in 3rd person view control demo

因此,我正在嘗試制作第三人稱視角控制演示。 該演示將展示執行以下操作的能力:

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

這是您的問題(updateLogic()第147/157和168行):

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

您正在嘗試計算玩家觀看的方向,但是您要執行兩次相同的補償。

(此外,我認為您可能希望從播放器的偏航中減去相機的偏航,以獲取相機觀看播放器的角度)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM