我应该如何在此2d Java游戏中实现跳跃/重力/下落 [英] How should I implement Jumping/gravity/falling in this 2d Java Game

查看:185
本文介绍了我应该如何在此2d Java游戏中实现跳跃/重力/下落的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以这是我的 Player 类(我想在空格键上跳转的对象),我只是不知道从哪里开始,有什么好的资源可以在与我有关的互联网上阅读?

So Here's my Player class (The object I would like to jump on spacebar), I just don't know where to begin, are there any good resources I can read on the internet that relates to me? Any help is great, thank-you.

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轴向上移动,但我可以按住

I have been struggling to implement a way for my character to jump, currently the player moves up the Y axis on spacebar press but I can hold the key down and jump endlessly.

我将添加我的 Creature 类,该类具有碰撞检测功能:

I'll add my Creature class which has my collision detection:

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;
    }
}


推荐答案

您要做的就是为场景中的对象实现速度加速度重力。速度是2D向量,它告诉您某事物移动的速度,而加速度则告诉您速度增加了多少

What you want to do, is implement speed, acceleration and gravity for the objects on your scene. Speed is a 2D vector, which tells you how fast something moves, while acceleration tells you how much the speed increases.

所有对象都应具有 update()方法,该方法会定期调用。它将对象的速度应用于其位置(无论如何,速度和位置如何相关),并且当您要加速对象时,基本上只是增加它的速度。在 update()方法中,我们还应用重力(以负Y加速度的形式)

All objects should have an update() method, which is called periodically. It will apply the speed of the object to it's position (that's how speed and position are related anyways) and when you want to accelerate an object, you will basically just increase its speed. In the update() method we also apply gravity (in form of negative Y acceleration)

利用摩擦。摩擦力可以确保您的物体沿特定方向移动时会变慢。

You can also make use of friction. Friction makes sure that your objects will slow down, as they move into a certain direction.

在此简单的模拟中,当值接近<$ c $时,摩擦力变弱了。 c> 1 。这意味着在 FRICTION == 1 时您没有摩擦,而在 FRICTION == 0 时,您的对象将立即停止。 / p>

In this simple simulation, friction gets weaker, as the value approaches 1. That means at FRICTION==1 you have no friction and at FRICTION==0 your objects will stop immediately.

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逻辑。

You can also use update() to process collision detection (which should set speed to zero) and enemies could do their AI logic..

您将<$ c类$ c>播放器可以扩展此 PhysicsObject 并具有方法 jump() runLeft() runRight(),看起来像这样:

You class Player could extend this PhysicsObject and have the methods jump(), runLeft() and runRight(), which could look like this:

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);
    }
}

碰撞检测本身就是一件大事此处内容过多,但此视频很好地描述了该视频。去看看吧!

Collision detection is a huge thing on it's own and it would be too much to cover here, but this video describes it very well. Go check it out!

这篇关于我应该如何在此2d Java游戏中实现跳跃/重力/下落的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆