java - 停下来后稍微滑行

标签 java opengl lwjgl game-physics

还记得玩《 super 马里奥兄弟》吗?当马里奥移动时,他会跑,然后当玩家停止移动时,他也会停下来,但他并没有完全停止。他滑动了一点。我需要完成这个任务。在过去的两天里,我完全重写了我的马里奥克隆/平台游戏的 Action ,因为我之前的模型效率低下,而且总体来说很糟糕。现在,我不知道如何继续保持那么小的速度,这样停止就不会那么突然。我将如何实现这个目标?下面所有用于移动的代码都在 Player 类中,而控件代码则在 Main 类中。那么我该怎么做才能检测玩家何时停止,并使用它来增加一点速度呢?

主要:

import com.hasherr.platformer.entity.Player;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;

public class Main {

    private void display() {
        try {
            Display.setDisplayMode(new DisplayMode(1000, 550));
            Display.setTitle("Unnamed Platformer Game");
            Display.create();
        } catch (LWJGLException e) {
            e.printStackTrace();
            System.exit(0);
        }

        // OpenGL

        while (!Display.isCloseRequested()) {
            Display.update();
            Display.sync(60); // sync to 60 fps
            initGL();

            player.update();
            handleKeyboardInput();
        }

        Display.destroy();
    }

    private boolean keyboardInUse() {
        boolean keyboardInUse;
        if (!(Keyboard.isKeyDown(Keyboard.KEY_A)
                || Keyboard.isKeyDown(Keyboard.KEY_D) || Keyboard
                    .isKeyDown(Keyboard.KEY_SPACE))) {
            keyboardInUse = false;
        } else {
            keyboardInUse = true;
        }

        return keyboardInUse;
    }

    private void handleKeyboardInput() {
        if (!keyboardInUse()) {
            player.goingLeft = false;
            player.goingRight = false;
            player.resetVelocity();
        }

        if (Keyboard.isKeyDown(Keyboard.KEY_D)) {   
            player.goingLeft = false;
            player.goingRight = true;
            player.moveRight();
        } else if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
            player.goingLeft = true;
            player.goingRight = false;
            player.moveLeft();
        } else if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
            player.jump();
        }

    }

    private void initGL() {
        // initial OpenGL items for 2D rendering
        glClear(GL_COLOR_BUFFER_BIT);
        glEnable(GL_TEXTURE_2D);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glOrtho(0, 1000, 0, 550, 1, -1);

        // start rendering player image
        player.grabTexture().bind();
        glBegin(GL_QUADS);

        glTexCoord2f(0, 0);
        glVertex2f(player.xPos, player.yPos);

        glTexCoord2f(1, 0);
        glVertex2f(player.xPos + 150, player.yPos);

        glTexCoord2f(1, 1);
        glVertex2f(player.xPos + 150, player.yPos + 150);

        glTexCoord2f(0, 1);
        glVertex2f(player.xPos, player.yPos + 150);
        glEnd(); // stop rendering this image
    }

    Player player = new Player();

    public static void main(String[] args) {
        Main main = new Main();
        main.display();
    }
}

玩家:

import java.io.IOException;

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

public class Player {

    public Texture playerTexture;

    // Positions & speed
    public float xPos = 20.0f; // This is initial
    public float yPos = 0.0f; // Same as above.

    public float xVel, yVel;

    public static int gravityForce = 6;
    public static int jumpVelocity = 100;
    private float moveSpeed = 8.0f;
    private static int MAX_MOVE_SPEED = 25;

    public boolean isSupported = true; // Once again, initial value.
    public boolean goingRight, goingLeft, canJump;

    // movement methods & constants

    public void update() {
        applyGravity();
        checkForSupport();
    }

    public Texture grabTexture() {
        try {
            playerTexture = TextureLoader.getTexture("PNG",
                    ResourceLoader.getResourceAsStream("res/test_char.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return playerTexture;
    }

    private void checkForSupport() {
        if (yPos == 0) {
            isSupported = true;
        } else if (yPos > 0 /* and is not on a platform */) {
            isSupported = false;
        }
    }

    private void applyGravity() {
        if (!isSupported) {
            yPos -= gravityForce;
        } 
    }

    public void printPos(String moveMethod) {
        System.out.println(" X: " + xPos + " Y: " + yPos + " Going Right: "
                + goingRight + " Going Left: " + goingLeft);
    }

    // movement methods

    public void resetVelocity() {
        moveSpeed = 15;
    }

    private void accelerateX() {
        moveSpeed += (float) (moveSpeed * 0.0096);
        if (moveSpeed >= MAX_MOVE_SPEED) {
            moveSpeed = MAX_MOVE_SPEED;
        }
        System.out.println(moveSpeed);
    }

    private void accelerateY() {

    }

    public void moveRight() {
        printPos("Moving Right!");
        accelerateX();
        xPos += moveSpeed;
    }

    public void moveLeft() {
        printPos("Moving Left!");
        accelerateX();
        xPos -= moveSpeed;
    }

    public void jump() {
        printPos("Jumping!");
        accelerateY();
        yPos += jumpVelocity;
    }

}

最佳答案

每次更新都会减少马里奥的速度,并根据他的速度移动马里奥的位置。

您应该允许他的速度在多次更新中持续存在。目前,只有按下向左或向右箭头键时,您才能移动马里奥。这是一个很好的方法,并且适用于某些游戏,但是现在您想要更多的物理行为,因此需要一种新的方法。是时候保存一些能量了!

试试这个:

float acceleration = 15;
private void accelerateX(float speed) {
    moveSpeed += (float) (speed * 0.0096);
    if (moveSpeed >= MAX_MOVE_SPEED) {
        moveSpeed = MAX_MOVE_SPEED;
    }else if(moveSpeed<=-MAX_MOVE_SPEED){ moveSpeed= - MAX_MOVE_SPEED;}
}
public void moveRight() {
    printPos("Moving Right!");
    accelerateX(acceleration);
}

public void moveLeft() {
    printPos("Moving Left!");
    accelerateX(-acceleration);
}
//call this every update.
public void update(){
    float minMoveSpeed = 1;
    //snap to zero movement if movespeed is too slow.
    //this is so the player actually stops moving eventually. otherwise
    //the dampening affect would constantly shift the player to and fro.
    if(this.moveSpeed<minMoveSpeed && this.moveSpeed>-minMoveSpeed){
        this.moveSpeed = 0;
    }
    else{
        float dampening = 1f;
        //Counter velocity. this will bring mario to a halt over a number of updates
        //play with the value of dampening to get right effect.
        double sign = -(int)Math.signum(moveSpeed);
        float dampeningValue = dampening*sign;
        this.moveSpeed += dampeningValue;
    }
    xPos+= this.moveSpeed;
}

这段代码允许他的速度在更新过程中持续存在,如果速度没有通过 moveRight/moveLeft 增加/减少,减速会使马里奥停下来。

此外,您应该按时间缩放速度,以便游戏在不同的硬件上运行相似。在开发的这个阶段,这一点不太重要;只是为了将来记住它。

关于java - 停下来后稍微滑行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17766304/

相关文章:

c++ - 我们需要序列化 ​​VAO 和 VBO

java - Opengl - 后处理多个 FBO - 我做错了什么?

java - 为什么 Java 崩溃(退出代码 134)?

java - 无法读取项目 'SpringRest' 中的 hibernate-validator-5.3.6.Final.jar'

Java检测url

c++ - OpenGl 纹理太暗

java - 在JOGL2中绘制图像

java - 正交投影 - 使物体适合屏幕?

java - 为什么这个作业不起作用?

java - 如何在 Felix 请求过滤器中获取当前 Jackrabbit 用户?