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

查看:46
本文介绍了我应该如何在这个 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;
    }
}

推荐答案

你想做的,是实现速度加速度重力> 用于场景中的对象.速度是一个二维向量,它告诉您物体移动的速度,而加速度则告诉您速度增加了多少.

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.

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

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..

你类 Player 可以扩展这个 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天全站免登陆