【问题标题】:What is wrong with my jump logic?我的跳跃逻辑有什么问题?
【发布时间】:2017-08-12 14:57:22
【问题描述】:

出于某种原因,每次我在我正在制作的游戏中跳跃时,跳跃都会比上一次跳跃更短。跳跃开始时长而雄伟(我的游戏设置在太空中),大约 10 次跳跃后,我的角色实际上是在地面上抽搐,因为跳跃的高度实际上不到一个像素。老实说,我无法找出它有什么问题,但我觉得这与我找到 deltaTime 的方式有关。请帮忙。我通常能够通过一些故障排除和/或谷歌搜索来解决我自己的问题,但老实说,我不知道出了什么问题,这一切对我来说都是合乎逻辑的。

很抱歉缺少 cmets。正如你可能从我讨厌的实现风格中看出的那样,这只是一个快速编写的项目,所以我不太关心以后看代码。我做这个主要是为了学习和练习Java。

我知道有很多课外参考,所以如果你需要看一个(我相信我包括了重要的),请告诉我。

播放器类(扩展实体):

import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.ArrayList;

import main.Main;
import scenes.Scene;
import threads.Time;

public class Player extends Entity {

    private Scene scene;

    private int HorizontalAxis = 0;

    public float speed = 0.5f;
    public float gravity = 0.001f;
    public float jumpSpeed = 1f;

    private float moveVelX = 0, moveVelY = 0;

    public Player(String name, String tag, int x, int y, int w, int h, String spritePath, Scene scene) {
        super(name, tag, x, y, w, h, spritePath);
        this.scene = scene;
    }

    public void Update() {

        //System.out.println(isGrounded());

        if (Main.keyInput.getKeyState("MoveLeft")) {
            HorizontalAxis = -1;
        }
        if (Main.keyInput.getKeyState("MoveRight")) {
            HorizontalAxis = 1;
        }
        if (Main.keyInput.getKeyState("MoveLeft") == Main.keyInput.getKeyState("MoveRight")) {
            HorizontalAxis = 0;
        }

        moveVelX = (HorizontalAxis * speed);

        if (isGrounded()) {
            moveVelY = 0;

            if (Main.keyInput.getKeyState("Jump") || Main.keyInput.getKeyState("JumpAlt")) {
                moveVelY = -jumpSpeed;
            }
        } else {
            moveVelY += gravity * Time.deltaTime.getSeconds();
        }

        setTrueX(getTrueX() + moveVelX);
        setTrueY(getTrueY() + moveVelY);
        System.out.println(moveVelY);
    }

    public void render(Graphics2D g) {
        g.drawImage(getSprite(), getX(), getY(), getWidth(), getHeight(), Main.display);
    }

    public boolean isGrounded() {
        ArrayList<Entity> groundEntities = scene.FindEntitiesWithTag("Ground");

        if (groundEntities.size() > 0) {
            for (int i = 0; i < groundEntities.size(); i++) {
                if (this.hitbox.intersects(groundEntities.get(i).hitbox)) {
                    return true;
                }
            }

            return false;
        } else {
            System.err.println("There is no ground in the scene!");
            return false;
        }
    }

}

实体类:

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

import main.Main;

public class Entity {

    public static enum AutoDrawTypes { NONE, RECTANGLE, RECTANGLE_ROUND, OVAL };
    public static AutoDrawTypes autoDrawType = Entity.AutoDrawTypes.NONE;

    public String name;
    public String tag;

    protected float x, y;

    protected int arcWidth, arcHeight;

    protected Rectangle hitbox = new Rectangle();
    protected Image sprite;

    protected Color color;

    public Entity(String tag, String name, int x, int y, int w, int h, String spritePath) {
        this.name = name;
        this.tag = tag;
        this.x = x;
        this.y = y;
        hitbox.setBounds((int)(getTrueX() - Camera.getX()), (int)(getTrueY() - Camera.getY()), w, h);
        setSprite(spritePath);
        this.autoDrawType = Entity.AutoDrawTypes.NONE;
    }

    public Entity(String tag, String name, int x, int y, int w, int h) {
        this.name = name;
        this.tag = tag;
        this.x = x;
        this.y = y;
        hitbox.setBounds((int)(getTrueX() - Camera.getX()), (int)(getTrueY() - Camera.getY()), w, h);
        this.autoDrawType = Entity.AutoDrawTypes.NONE;
    }

    public Entity(String tag, String name, int x, int y, int w, int h, Entity.AutoDrawTypes autoDrawType, Color color) {
        this.name = name;
        this.tag = tag;
        this.x = x;
        this.y = y;
        hitbox.setBounds((int)(getTrueX() - Camera.getX()), (int)(getTrueY() - Camera.getY()), w, h);
        this.autoDrawType = autoDrawType;
        this.color = color;
    }

    public Entity(String tag, String name, int x, int y, int w, int h, Entity.AutoDrawTypes autoDrawType, Color color, int arcWidth, int arcHeight) {
        this.name = name;
        this.tag = tag;
        this.x = x;
        this.y = y;
        hitbox.setBounds((int)(getTrueX() - Camera.getX()), (int)(getTrueY() - Camera.getY()), w, h);
        this.autoDrawType = autoDrawType;
        this.color = color;
        this.arcWidth = arcWidth;
        this.arcHeight = arcHeight;
    }

    public void UpdatePositionRelativeToCamera() {
        hitbox.setBounds((int)(getTrueX() - Camera.getX()), (int)(getTrueY() - Camera.getY()), getWidth(), getHeight());
    }

    public Entity() {

    }

    public void Update() {
    }

    public void render(Graphics2D g) {
        g.setColor(color);
        if (autoDrawType == Entity.AutoDrawTypes.RECTANGLE) {
            g.fillRect(getX(), getY(), getWidth(), getHeight());
        }
        if (autoDrawType == Entity.AutoDrawTypes.RECTANGLE_ROUND) {
            g.fillRoundRect(getX(), getY(), getWidth(), getHeight(), arcWidth, arcHeight);
        }
        if (autoDrawType == Entity.AutoDrawTypes.OVAL) {
            g.fillOval(getX(), getY(), getWidth(), getHeight());
        }
    }

    public void setTrueX(float x) {this.x = x;}
    public void setTrueY(float y) {this.y = y;}
    public void setX(int x) {hitbox.x = x;}
    public void setY(int y) {hitbox.y = y;}
    public void setWidth(int width) {hitbox.width = width;}
    public void setHeight(int height) {hitbox.height = height;}
    public void setSprite(String path) {
        Toolkit tk = Toolkit.getDefaultToolkit();
        if (tk == null) {
            System.err.println("Default Toolkit could not be fetched.");
            return;
        }
        sprite = tk.getImage(Main.class.getResource(path));
        if (sprite == null) {
            System.err.println("Image not found at + '" + path + "'. Check path in resources folder.");
            return;
        }
    }

    public float getTrueX() {return this.x;}
    public float getTrueY() {return this.y;}
    public int getX() {return hitbox.x;}
    public int getY() {return hitbox.y;}
    public int getWidth() {return hitbox.width;}
    public int getHeight() {return hitbox.height;}
    public Image getSprite() {return sprite;}

}

计时类(在应用程序启动时作为线程运行):

import java.time.Duration;
import java.time.Instant;

public class Time implements Runnable {

    public static boolean running = false;

    public static Duration deltaTime = Duration.ZERO;
    public static Instant beginTime = Instant.now();

    public void run() {
        while (running) {
            deltaTime = Duration.between(beginTime, Instant.now());
        }
    }
}

【问题讨论】:

  • "I don't really care much to look at the code later" -- 在这种情况下,你是对的,你不必担心代码看起来有多好或评论有多好,除非你问别人(我们!)为您审查它
  • 好的问题,在上面的代码中,你实际上在哪里有跳跃的逻辑?请解释这段代码,不幸的是我们无法编译或运行的代码,因为它具有我们不知道的依赖项。
  • 您的增量时间不是增量时间,因为 beginTime 永远不会更新
  • 欢迎来到 Stackoverflow。请通读"how do I ask a good question",并确保如果您需要其他真实人类的帮助,请努力显示minimal reproducible example。这将告诉我们您足够关心以实际找出问题所在,并让我们直奔主题,因为您显示的代码正是所涉及的代码。

标签: java game-physics


【解决方案1】:

没关系,我修好了。这是我计算 deltaTime 的方式。我决定只删除 deltaTime 并减少重力(即使它已经非常小了,哈哈)。这修复了奇怪的“随着时间的推移较小的跳跃”错误。

【讨论】:

  • 您不妨考虑删除问题
  • 你必须使用deltatime,否则重力会根据帧率而变化。但是 deltatime 应该是自上次更新以来的时间量,而不是自您启动程序以来的时间量。
  • @spectras 在物理上精确的模拟中,加速度和离开地面以来的时间量之间没有相关性,因此时间增量甚至可能不是必需的。
  • @templatetypedef> 加速没有,但是当你更新速度时,你会在从上次更新到当前更新的时间里整合它。你必须知道这个间隔有多长。考虑一下:如果你 update() 每秒 100 次,如果你 update() 每秒 20 次,你仍然希望在 1 秒后速度改变相同的量。
  • 是的,如果您不考虑增量时间,游戏将取决于您正在开发和测试的确切环境。一旦将其移植到具有更高/更低帧的环境率,游戏行为将不一致。删除依赖项可能会解决当前问题,但可能需要随着游戏的发展进行重构。
【解决方案2】:

看看这段导致玩家摔倒的代码:

    moveVelY += gravity * Time.deltaTime.getSeconds();

请注意,这会导致玩家的 y 速度随着时间的增加而增加。也就是说,就好像重力随着时间的推移而不断增加。因此,如果你早跳,就像在月球上跳,如果你晚跳,就像在木星或中子星表面跳。

要解决此问题,请删除对当前时间的依赖。只需通过重力项来增加 y 速度,这可能只是一个固定常数,除非您正在对世界物理学做一些很酷的事情。

【讨论】:

    猜你喜欢
    • 2016-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    • 1970-01-01
    相关资源
    最近更新 更多