停止后稍微滑动一下

时间:2013-07-20 20:15:03

标签: java opengl lwjgl game-physics

还记得玩超级马里奥兄弟吗?当马里奥移动时,他跑,然后当玩家停止移动时,他停下来,但他没有完全停下来。他滑了一下。我需要做到这一点。在过去的两天里,我一直在完全改写我的Mario克隆/平台游戏的运动,因为我之前的模型效率低下而且总体上很糟糕。现在,我不知道如何继续这么小的速度,以便停止不是那么突然。我怎么做到这一点?以下所有移动代码都在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;
    }

}

1 个答案:

答案 0 :(得分:3)

每次更新都会降低马里奥的速度,并以速度移动马里奥的位置。

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

请改为尝试:

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递增/递减,则减速会使Mario停止。

此外,你应该按时间缩放你的速度,以便游戏在不同的硬件上运行类似。在发展的这一点上,这一点不太重要;请记住未来。