我应该如何在这个2D游戏中实现跳跃/重力/下降

时间:2016-02-18 10:08:34

标签: java 2d

所以这是我的Player课程(我想跳到空格键上的对象),我只是不知道从哪里开始,有什么好的资源我可以在互联网上阅读与我有关吗?任何帮助都很棒,谢谢。

package com.zetcode;
import java.awt.Color;
import java.awt.Graphics;

public class Player extends Creature {

    private boolean jumping = false;
    private Creature creature;

    public Player(Handler handler, float x, float y) {
        super(handler, x, y, Creature.PLAYER_WIDTH, Creature.PLAYER_HEIGHT);

        bounds.x = 16;
        bounds.y = 31;
        bounds.width = 40;
        bounds.height = 58;
    }

    @Override
    public void tick() {
        getInput();
        move();
        handler.getGameCamera().centerOnEntity(this);
    }

    private void getInput(){
        xMove = 0;
        yMove = 3;
        gravity = 2;

        if(handler.getKeyManager().jump)
            yMove = -speed;
        if(handler.getKeyManager().down)
            yMove = speed;
        if(handler.getKeyManager().left)
            xMove = -speed;
        if(handler.getKeyManager().right)
            xMove = speed;
    }

    @Override
    public void render(Graphics g) {
        g.drawImage(Assets.player, (int) (x -     handler.getGameCamera().getxOffset()), (int) (y -   handler.getGameCamera().getyOffset()), width, height, null);
    }
}

这是我的KeyManager课程:

package com.zetcode;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class KeyManager implements KeyListener{

    private boolean[] keys;
    public boolean up, down, left, right, jump;

    public KeyManager(){
        keys = new boolean[256];
    }

    public void tick(){
        down = keys[KeyEvent.VK_S];
        left = keys[KeyEvent.VK_A];
        right = keys[KeyEvent.VK_D];
        jump = keys[KeyEvent.VK_SPACE];
    }

    @Override
    public void keyPressed(KeyEvent e) {
        keys[e.getKeyCode()] = true;
        System.out.println("A Key was pressed");
    }

    @Override
    public void keyReleased(KeyEvent e) {
        keys[e.getKeyCode()] = false;
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }
}

我一直在努力为我的角色实现一种跳跃方式,目前玩家在空格键上按Y轴向上移动,但是我可以按住键并无休止地跳跃。

我将添加我的碰撞检测Creature类:

package com.zetcode;

public abstract class Creature extends Entity {

    public static final int DEFAULT_HEALTH = 10;
    public static final float DEFAULT_SPEED = 3.0f;
    public static final int DEFAULT_CREATURE_WIDTH = 64,
            DEFAULT_CREATURE_HEIGHT = 64;
    public static final int PLAYER_HEIGHT = 90, PLAYER_WIDTH = 64;

    protected int health;
    protected float speed;
    protected float xMove, yMove;
    protected float gravity;

    public boolean falling = true;
    private boolean jumping = false;

    public Creature(Handler handler, float x, float y, int width, int height) {
        super(handler, x, y, width, height);
        health = DEFAULT_HEALTH;
        speed = DEFAULT_SPEED;
        xMove = 0;
        yMove = 0;
        gravity = 0;
    }

    //collision detection

    public void move(){
        moveX();
        moveY();
    }

    public void moveX(){
        if(xMove > 0){//move right
            int tx = (int) (x + xMove + bounds.x + bounds.width) / Tile.TILE_WIDTH;

            if(!collisionWithTile(tx, (int) (y + bounds.y) / Tile.TILE_HEIGHT) && //check top right corner of hitbox
                    !collisionWithTile(tx, (int) (y + bounds.y + bounds.height) / Tile.TILE_HEIGHT)){ //check bottom right corner of hitbox
                x += xMove;
            }else{
                x = tx * Tile.TILE_WIDTH - bounds.x - bounds.width - 1;
            }

        }else if(xMove < 0){//move left
            int tx = (int) (x + xMove + bounds.x) / Tile.TILE_WIDTH;

            if(!collisionWithTile(tx, (int) (y + bounds.y) / Tile.TILE_HEIGHT) && //check top left corner of hitbox
                    !collisionWithTile(tx, (int) (y + bounds.y + bounds.height) / Tile.TILE_HEIGHT)){ //check bottom left corner of hitbox
                x += xMove;
            }else{
                x = tx * Tile.TILE_WIDTH + Tile.TILE_WIDTH - bounds.x;
            }
        }
    }

    public void moveY(){
        if(yMove < 0){//up
            int ty = (int) (y+ yMove + bounds.y) / Tile.TILE_HEIGHT;

            if(!collisionWithTile((int) (x + bounds.x) / Tile.TILE_WIDTH, ty) &&
                    !collisionWithTile((int) (x + bounds.x + bounds.width) / Tile.TILE_WIDTH,ty)){
                y += yMove;
            }else{
                y = ty * Tile.TILE_HEIGHT + Tile.TILE_HEIGHT - bounds.y;
            }

        }else if(yMove > 0){//down
            int ty = (int) (y+ yMove + bounds.y + bounds.getHeight()) /      Tile.TILE_HEIGHT;

            if(!collisionWithTile((int) (x + bounds.x) / Tile.TILE_WIDTH,ty) &&
                    !collisionWithTile((int) (x + bounds.x + bounds.width) /   Tile.TILE_WIDTH,ty)){
                y += yMove;
            }else{
                y = ty * Tile.TILE_HEIGHT - bounds.y - bounds.height -1;
            }
        }
    }

    protected boolean collisionWithTile(int x, int y){
        return handler.getWorld().getTile(x, y).isSolid();
    }

    //getters and setters

    public float getxMove() {
        return xMove;
    }

    public void setxMove(float xMove) {
        this.xMove = xMove;
    }

    public float getyMove() {
        return yMove;
    }

    public void setyMove(float yMove) {
        this.yMove = yMove;
    }

    public int getHealth() {
        return health;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    public float getSpeed() {
        return speed;
    }

    public void setSpeed(float speed) {
        this.speed = speed;
    }
}

1 个答案:

答案 0 :(得分:2)

您要执行的操作是为场景中的对象实施速度加速重力。速度是一个2D向量,告诉你某些东西移动的速度,而加速度告诉你速度增加多少

所有对象都应该有一个update()方法,该方法会定期调用。它会将物体的速度应用到它的位置(这就是速度和位置之间的相关关系),当你想要加速一个物体时,你基本上只会提高它的速度。在update()方法中,我们还应用重力(以负Y加速度的形式)

你也可以利用摩擦力。摩擦确保你的物体在向某个方向移动时会减速。

在这个简单的模拟中,当值接近1时,摩擦变弱。这意味着在FRICTION==1你没有摩擦,FRICTION==0你的物体会立即停止。

public class PhysicsObject {
    public static final double FRICTION = 0.99;
    public static final double GRAVITY = 0.01;
    private double posX;
    private double posY;
    private double speedX = 0;
    private double speedY = 0;

    public PhysicsObject(double posX, double posY) {
        this.posX = posX;
        this.posY = posY;
    }

    public void accelerate(double accelerationX, double accelerationY) {
        speedX += accelerationX;
        speedY += accelerationY;
    }

    public void move(double xDelta, double yDelta) {
        posX += xDelta;
        posY += yDelta;
        // do collision detection here. upon collision, set speedX/speedY to zero..!
    }

    public void update() {
        move(speedX, speedY);
        speedX *= FRICTION;
        speedY *= FRICTION;
        accelerate(0, -GRAVITY); // gravity accelerates the object downwards each tick
    }

    public double getPosX() {
        return posX;
    }

    public double getPosY() {
        return posY;
    }
}

您还可以使用update()来处理碰撞检测(将速度设置为零),敌人可以执行AI逻辑。

您的班级Player可以对PhysicsObject进行扩展,并使用方法jump()runLeft()runRight(),如下所示:

public class Player extends PhysicsObject{
    public static final double JUMP_STRENGTH = 5;
    public static final double SPEED = 1;
    public void jump() {
        accelerate(0, JUMP_STRENGTH); // change 5 for some constant or variable indicating the "strength" of the jump
    }

    public void runRight() {
        move(SPEED, 0);
    }

    public void runLeft() {
        move(-SPEED, 0);
    }
}

碰撞检测本身就是一件很重要的事情,这里涉及的内容太多了,但是this video很好地描述了它。去看看吧!