【问题标题】:Java 2D Platformer Gravity ImprovementsJava 2D 平台游戏重力改进
【发布时间】:2016-05-25 11:16:24
【问题描述】:

我已经开始用 Java 制作一个小游戏,并且加入了碰撞和重力的形式,玩家的速度不会像现实生活中那样随着下落而增加。我想改进这种形式的重力以使其更逼真,我还为地板设置了一个碰撞块,当玩家离开地板时,它会保持在那个高度并且不会掉落。

下面是我的 Player 类:

    import java.awt.Color;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;

    public class Player {
        private int x, y, width, height, lx, ly, dx, dy;
        private final int FallSpeed = 2;
        private final long JumpingTime = 8;
        public boolean jumping = false, falling = true;

        public Player(int x, int y, int width, int height) {
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
            lx = x;
            ly = y;
            dx = x;
            dy = y;
            new Thread(new gravityThread()).start(); // Make user fall in case they are in the air
        }

        public void setX(int x) {
            this.x = x;
            lx = x;
            dx = x;
        }

        public void setY(int y) {
            this.y = y;
            ly = y;
            dy = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        public int getWidth() {
            return width;
        }

        public int getHeight() {
            return height;
        }

        public Rectangle getBounds() {
            return new Rectangle(x, y, width, height);
        }

        public void update() {

        }

        public void move(int ax, int ay) {
            dx += ax;
            dy += ay;
            checkCollisions();
        }

        public void checkCollisions() {
            if (collided()) {
                falling = false;
                dx = lx;
                dy = ly;
            }
            x = dx;
            y = dy;
            lx = x;
            ly = y;
        }

        public boolean collided() {
            Rectangle desired = new Rectangle(dx, dy, width, height);
            for (Rectangle r : CollisionManager.collisions) if (r.intersects(desired)) return true;
            return false;
        }

        public void jump() {
            falling = false;
            jumping = true;
            new Thread(new gravityThread()).start();
        }

        public void render(Graphics2D g2d) {
            g2d.setColor(Color.black);
            g2d.fill(getBounds());
        }

        private class gravityThread implements Runnable {

            int i = 0;

            @Override
            public void run() {
                while(jumping) {
                    try {
                        i++;
                        Thread.sleep(JumpingTime);
                        move(0, -FallSpeed);
                        if (i == 40) {
                            jumping = false;
                            falling = true;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        System.exit(0);
                    }
                }
                while(falling) {
                    try {
                        Thread.sleep(JumpingTime);
                        move(0, FallSpeed);
                    } catch (Exception e) {
                        e.printStackTrace();
                        System.exit(0);
                    }
                }
            }
        }
    }

在另一个处理将所有内容绘制到窗口的类中,我用这个 sn-p 控制玩家移动:

    public void onUpdate() {
            if (this.screenFactory.getGame().getKeyboardListener().isKeyPressed(KeyEvent.VK_A))
                player.move(-WalkSpeed, 0);
            if (this.screenFactory.getGame().getKeyboardListener().isKeyPressed(KeyEvent.VK_D))
                player.move(WalkSpeed, 0);

            if (this.screenFactory.getGame().getKeyboardListener().isKeyPressed(KeyEvent.VK_SPACE)) {
                if (!player.jumping && !player.falling)
                    player.jump();
            }

            if (player.getY() >= screenHeight - player.getHeight()) {
                player.setY(screenHeight - player.getHeight());
                player.falling = false;
            }
            if (player.getY() <= 0)
                player.setY(0);
            if (player.getX() >= screenWidth - player.getWidth())
                player.setX(screenWidth - player.getWidth());
            if (player.getX() <= 0)
                player.setX(0);
    }

【问题讨论】:

  • 为什么要在特殊线程中处理重力?没有理由,我想。您可以在onUpdate 方法中计算重力。
  • 我在它自己的线程中进行了处理,以便用户可以在空中移动,他们仍然可以在onUpdate 方法中移动吗?
  • 要添加物理,您需要了解物理。如果您不了解它们,您如何期望能够应用现实物理学?了解物理学中的速度、加速度等,您将能够添加逼真的坠落。
  • @Tobias 我明白它在现实生活中是如何运作的,玩家会根据失败所花费的时间而更快地下降,但这并不意味着我知道如何很好地实现它。
  • 我会投票关闭它作为 stackoverflow.com/questions/35478428/… 的副本,但我犹豫在这里使用 dupehammer。

标签: java game-physics


【解决方案1】:
  • 重力为 9.81 m/s²
  • 获取您的“draw-update-speed”,这是 s(实际上,您应该每秒至少更新 30 次。计算时请记住这一点)
  • 得到你对长度的定义,这是 m

两个对象的位置取决于当前速度 v 和每帧的加速度(g-force)a。 东西落得越久,落得越快……

编辑:要使跌倒/跳跃时的侧向运动更加逼真,您需要使用 sin()、cos()。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 2015-05-20
    相关资源
    最近更新 更多